| ... | @@ -457,9 +457,9 @@ fn continueExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowE | ... | @@ -457,9 +457,9 @@ fn continueExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowE |
| 457 | continue; | 457 | continue; |
| 458 | } | 458 | } |
| 459 | | 459 | |
| 460 | return addZIRInst(mod, parent_scope, src, zir.Inst.BreakVoid, .{ | 460 | return addZirInstTag(mod, parent_scope, src, .break_void, .{ |
| 461 | .block = continue_block, | 461 | .block = continue_block, |
| 462 | }, .{}); | 462 | }); |
| 463 | }, | 463 | }, |
| 464 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, | 464 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 465 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, | 465 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| ... | @@ -1908,22 +1908,13 @@ fn whileExpr( | ... | @@ -1908,22 +1908,13 @@ fn whileExpr( |
| 1908 | if (while_node.inline_token) |tok| | 1908 | if (while_node.inline_token) |tok| |
| 1909 | return mod.failTok(scope, tok, "TODO inline while", .{}); | 1909 | return mod.failTok(scope, tok, "TODO inline while", .{}); |
| 1910 | | 1910 | |
| 1911 | var expr_scope: Scope.GenZIR = .{ | 1911 | var loop_scope: Scope.GenZIR = .{ |
| 1912 | .parent = scope, | 1912 | .parent = scope, |
| 1913 | .decl = scope.ownerDecl().?, | 1913 | .decl = scope.ownerDecl().?, |
| 1914 | .arena = scope.arena(), | 1914 | .arena = scope.arena(), |
| 1915 | .instructions = .{}, | 1915 | .instructions = .{}, |
| 1916 | }; | 1916 | }; |
| 1917 | setBlockResultLoc(&expr_scope, rl); | 1917 | setBlockResultLoc(&loop_scope, rl); |
| 1918 | defer expr_scope.instructions.deinit(mod.gpa); | | |
| 1919 | | | |
| 1920 | var loop_scope: Scope.GenZIR = .{ | | |
| 1921 | .parent = &expr_scope.base, | | |
| 1922 | .decl = expr_scope.decl, | | |
| 1923 | .arena = expr_scope.arena, | | |
| 1924 | .instructions = .{}, | | |
| 1925 | .break_result_loc = rl, | | |
| 1926 | }; | | |
| 1927 | defer loop_scope.instructions.deinit(mod.gpa); | 1918 | defer loop_scope.instructions.deinit(mod.gpa); |
| 1928 | | 1919 | |
| 1929 | var continue_scope: Scope.GenZIR = .{ | 1920 | var continue_scope: Scope.GenZIR = .{ |
| ... | @@ -1957,11 +1948,21 @@ fn whileExpr( | ... | @@ -1957,11 +1948,21 @@ fn whileExpr( |
| 1957 | if (while_node.continue_expr) |cont_expr| { | 1948 | if (while_node.continue_expr) |cont_expr| { |
| 1958 | _ = try expr(mod, &loop_scope.base, .{ .ty = void_type }, cont_expr); | 1949 | _ = try expr(mod, &loop_scope.base, .{ .ty = void_type }, cont_expr); |
| 1959 | } | 1950 | } |
| 1960 | const loop = try addZIRInstLoop(mod, &expr_scope.base, while_src, .{ | 1951 | const loop = try scope.arena().create(zir.Inst.Loop); |
| 1961 | .instructions = try expr_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items), | 1952 | loop.* = .{ |
| 1962 | }); | 1953 | .base = .{ |
| | 1954 | .tag = .loop, |
| | 1955 | .src = while_src, |
| | 1956 | }, |
| | 1957 | .positionals = .{ |
| | 1958 | .body = .{ |
| | 1959 | .instructions = try scope.arena().dupe(*zir.Inst, loop_scope.instructions.items), |
| | 1960 | }, |
| | 1961 | }, |
| | 1962 | .kw_args = .{}, |
| | 1963 | }; |
| 1963 | const while_block = try addZIRInstBlock(mod, scope, while_src, .block, .{ | 1964 | const while_block = try addZIRInstBlock(mod, scope, while_src, .block, .{ |
| 1964 | .instructions = try expr_scope.arena.dupe(*zir.Inst, expr_scope.instructions.items), | 1965 | .instructions = try scope.arena().dupe(*zir.Inst, &[1]*zir.Inst{&loop.base}), |
| 1965 | }); | 1966 | }); |
| 1966 | loop_scope.break_block = while_block; | 1967 | loop_scope.break_block = while_block; |
| 1967 | loop_scope.continue_block = cond_block; | 1968 | loop_scope.continue_block = cond_block; |
| ... | @@ -1984,8 +1985,8 @@ fn whileExpr( | ... | @@ -1984,8 +1985,8 @@ fn whileExpr( |
| 1984 | // declare payload to the then_scope | 1985 | // declare payload to the then_scope |
| 1985 | const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, then_src, while_node.payload); | 1986 | const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, then_src, while_node.payload); |
| 1986 | | 1987 | |
| 1987 | expr_scope.break_count += 1; | 1988 | loop_scope.break_count += 1; |
| 1988 | const then_result = try expr(mod, then_sub_scope, expr_scope.break_result_loc, while_node.body); | 1989 | const then_result = try expr(mod, then_sub_scope, loop_scope.break_result_loc, while_node.body); |
| 1989 | | 1990 | |
| 1990 | var else_scope: Scope.GenZIR = .{ | 1991 | var else_scope: Scope.GenZIR = .{ |
| 1991 | .parent = &continue_scope.base, | 1992 | .parent = &continue_scope.base, |
| ... | @@ -1996,17 +1997,15 @@ fn whileExpr( | ... | @@ -1996,17 +1997,15 @@ fn whileExpr( |
| 1996 | defer else_scope.instructions.deinit(mod.gpa); | 1997 | defer else_scope.instructions.deinit(mod.gpa); |
| 1997 | | 1998 | |
| 1998 | var else_src: usize = undefined; | 1999 | var else_src: usize = undefined; |
| 1999 | var else_sub_scope: *Module.Scope = undefined; | | |
| 2000 | const else_result: ?*zir.Inst = if (while_node.@"else") |else_node| blk: { | 2000 | const else_result: ?*zir.Inst = if (while_node.@"else") |else_node| blk: { |
| 2001 | else_src = tree.token_locs[else_node.body.lastToken()].start; | 2001 | else_src = tree.token_locs[else_node.body.lastToken()].start; |
| 2002 | // declare payload to the then_scope | 2002 | // declare payload to the then_scope |
| 2003 | else_sub_scope = try cond_kind.elseSubScope(mod, &else_scope, else_src, else_node.payload); | 2003 | const else_sub_scope = try cond_kind.elseSubScope(mod, &else_scope, else_src, else_node.payload); |
| 2004 | | 2004 | |
| 2005 | expr_scope.break_count += 1; | 2005 | loop_scope.break_count += 1; |
| 2006 | break :blk try expr(mod, else_sub_scope, expr_scope.break_result_loc, else_node.body); | 2006 | break :blk try expr(mod, else_sub_scope, loop_scope.break_result_loc, else_node.body); |
| 2007 | } else blk: { | 2007 | } else blk: { |
| 2008 | else_src = tree.token_locs[while_node.lastToken()].start; | 2008 | else_src = tree.token_locs[while_node.lastToken()].start; |
| 2009 | else_sub_scope = &else_scope.base; | | |
| 2010 | break :blk null; | 2009 | break :blk null; |
| 2011 | }; | 2010 | }; |
| 2012 | if (loop_scope.label) |some| { | 2011 | if (loop_scope.label) |some| { |
| ... | @@ -2018,7 +2017,7 @@ fn whileExpr( | ... | @@ -2018,7 +2017,7 @@ fn whileExpr( |
| 2018 | mod, | 2017 | mod, |
| 2019 | scope, | 2018 | scope, |
| 2020 | rl, | 2019 | rl, |
| 2021 | &expr_scope, | 2020 | &loop_scope, |
| 2022 | &then_scope, | 2021 | &then_scope, |
| 2023 | &else_scope, | 2022 | &else_scope, |
| 2024 | &condbr.positionals.then_body, | 2023 | &condbr.positionals.then_body, |
| ... | @@ -2037,9 +2036,6 @@ fn forExpr( | ... | @@ -2037,9 +2036,6 @@ fn forExpr( |
| 2037 | rl: ResultLoc, | 2036 | rl: ResultLoc, |
| 2038 | for_node: *ast.Node.For, | 2037 | for_node: *ast.Node.For, |
| 2039 | ) InnerError!*zir.Inst { | 2038 | ) InnerError!*zir.Inst { |
| 2040 | if (true) { | | |
| 2041 | @panic("TODO reimplement this"); | | |
| 2042 | } | | |
| 2043 | if (for_node.label) |label| { | 2039 | if (for_node.label) |label| { |
| 2044 | try checkLabelRedefinition(mod, scope, label); | 2040 | try checkLabelRedefinition(mod, scope, label); |
| 2045 | } | 2041 | } |
| ... | @@ -2047,42 +2043,34 @@ fn forExpr( | ... | @@ -2047,42 +2043,34 @@ fn forExpr( |
| 2047 | if (for_node.inline_token) |tok| | 2043 | if (for_node.inline_token) |tok| |
| 2048 | return mod.failTok(scope, tok, "TODO inline for", .{}); | 2044 | return mod.failTok(scope, tok, "TODO inline for", .{}); |
| 2049 | | 2045 | |
| 2050 | var for_scope: Scope.GenZIR = .{ | | |
| 2051 | .parent = scope, | | |
| 2052 | .decl = scope.ownerDecl().?, | | |
| 2053 | .arena = scope.arena(), | | |
| 2054 | .instructions = .{}, | | |
| 2055 | }; | | |
| 2056 | defer for_scope.instructions.deinit(mod.gpa); | | |
| 2057 | | | |
| 2058 | // setup variables and constants | 2046 | // setup variables and constants |
| 2059 | const tree = scope.tree(); | 2047 | const tree = scope.tree(); |
| 2060 | const for_src = tree.token_locs[for_node.for_token].start; | 2048 | const for_src = tree.token_locs[for_node.for_token].start; |
| 2061 | const index_ptr = blk: { | 2049 | const index_ptr = blk: { |
| 2062 | const usize_type = try addZIRInstConst(mod, &for_scope.base, for_src, .{ | 2050 | const usize_type = try addZIRInstConst(mod, scope, for_src, .{ |
| 2063 | .ty = Type.initTag(.type), | 2051 | .ty = Type.initTag(.type), |
| 2064 | .val = Value.initTag(.usize_type), | 2052 | .val = Value.initTag(.usize_type), |
| 2065 | }); | 2053 | }); |
| 2066 | const index_ptr = try addZIRUnOp(mod, &for_scope.base, for_src, .alloc, usize_type); | 2054 | const index_ptr = try addZIRUnOp(mod, scope, for_src, .alloc, usize_type); |
| 2067 | // initialize to zero | 2055 | // initialize to zero |
| 2068 | const zero = try addZIRInstConst(mod, &for_scope.base, for_src, .{ | 2056 | const zero = try addZIRInstConst(mod, scope, for_src, .{ |
| 2069 | .ty = Type.initTag(.usize), | 2057 | .ty = Type.initTag(.usize), |
| 2070 | .val = Value.initTag(.zero), | 2058 | .val = Value.initTag(.zero), |
| 2071 | }); | 2059 | }); |
| 2072 | _ = try addZIRBinOp(mod, &for_scope.base, for_src, .store, index_ptr, zero); | 2060 | _ = try addZIRBinOp(mod, scope, for_src, .store, index_ptr, zero); |
| 2073 | break :blk index_ptr; | 2061 | break :blk index_ptr; |
| 2074 | }; | 2062 | }; |
| 2075 | const array_ptr = try expr(mod, &for_scope.base, .ref, for_node.array_expr); | 2063 | const array_ptr = try expr(mod, scope, .ref, for_node.array_expr); |
| 2076 | const cond_src = tree.token_locs[for_node.array_expr.firstToken()].start; | 2064 | const cond_src = tree.token_locs[for_node.array_expr.firstToken()].start; |
| 2077 | const len = try addZIRUnOp(mod, &for_scope.base, cond_src, .indexable_ptr_len, array_ptr); | 2065 | const len = try addZIRUnOp(mod, scope, cond_src, .indexable_ptr_len, array_ptr); |
| 2078 | | 2066 | |
| 2079 | var loop_scope: Scope.GenZIR = .{ | 2067 | var loop_scope: Scope.GenZIR = .{ |
| 2080 | .parent = &for_scope.base, | 2068 | .parent = scope, |
| 2081 | .decl = for_scope.decl, | 2069 | .decl = scope.ownerDecl().?, |
| 2082 | .arena = for_scope.arena, | 2070 | .arena = scope.arena(), |
| 2083 | .instructions = .{}, | 2071 | .instructions = .{}, |
| 2084 | .break_result_loc = rl, | | |
| 2085 | }; | 2072 | }; |
| | 2073 | setBlockResultLoc(&loop_scope, rl); |
| 2086 | defer loop_scope.instructions.deinit(mod.gpa); | 2074 | defer loop_scope.instructions.deinit(mod.gpa); |
| 2087 | | 2075 | |
| 2088 | var cond_scope: Scope.GenZIR = .{ | 2076 | var cond_scope: Scope.GenZIR = .{ |
| ... | @@ -2115,12 +2103,21 @@ fn forExpr( | ... | @@ -2115,12 +2103,21 @@ fn forExpr( |
| 2115 | const index_plus_one = try addZIRBinOp(mod, &loop_scope.base, for_src, .add, index_2, one); | 2103 | const index_plus_one = try addZIRBinOp(mod, &loop_scope.base, for_src, .add, index_2, one); |
| 2116 | _ = try addZIRBinOp(mod, &loop_scope.base, for_src, .store, index_ptr, index_plus_one); | 2104 | _ = try addZIRBinOp(mod, &loop_scope.base, for_src, .store, index_ptr, index_plus_one); |
| 2117 | | 2105 | |
| 2118 | // looping stuff | 2106 | const loop = try scope.arena().create(zir.Inst.Loop); |
| 2119 | const loop = try addZIRInstLoop(mod, &for_scope.base, for_src, .{ | 2107 | loop.* = .{ |
| 2120 | .instructions = try for_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items), | 2108 | .base = .{ |
| 2121 | }); | 2109 | .tag = .loop, |
| | 2110 | .src = for_src, |
| | 2111 | }, |
| | 2112 | .positionals = .{ |
| | 2113 | .body = .{ |
| | 2114 | .instructions = try scope.arena().dupe(*zir.Inst, loop_scope.instructions.items), |
| | 2115 | }, |
| | 2116 | }, |
| | 2117 | .kw_args = .{}, |
| | 2118 | }; |
| 2122 | const for_block = try addZIRInstBlock(mod, scope, for_src, .block, .{ | 2119 | const for_block = try addZIRInstBlock(mod, scope, for_src, .block, .{ |
| 2123 | .instructions = try for_scope.arena.dupe(*zir.Inst, for_scope.instructions.items), | 2120 | .instructions = try scope.arena().dupe(*zir.Inst, &[1]*zir.Inst{&loop.base}), |
| 2124 | }); | 2121 | }); |
| 2125 | loop_scope.break_block = for_block; | 2122 | loop_scope.break_block = for_block; |
| 2126 | loop_scope.continue_block = cond_block; | 2123 | loop_scope.continue_block = cond_block; |
| ... | @@ -2141,15 +2138,6 @@ fn forExpr( | ... | @@ -2141,15 +2138,6 @@ fn forExpr( |
| 2141 | }; | 2138 | }; |
| 2142 | defer then_scope.instructions.deinit(mod.gpa); | 2139 | defer then_scope.instructions.deinit(mod.gpa); |
| 2143 | | 2140 | |
| 2144 | // Most result location types can be forwarded directly; however | | |
| 2145 | // if we need to write to a pointer which has an inferred type, | | |
| 2146 | // proper type inference requires peer type resolution on the while's | | |
| 2147 | // branches. | | |
| 2148 | const branch_rl: ResultLoc = switch (rl) { | | |
| 2149 | .discard, .none, .ty, .ptr, .ref => rl, | | |
| 2150 | .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = for_block }, | | |
| 2151 | }; | | |
| 2152 | | | |
| 2153 | var index_scope: Scope.LocalPtr = undefined; | 2141 | var index_scope: Scope.LocalPtr = undefined; |
| 2154 | const then_sub_scope = blk: { | 2142 | const then_sub_scope = blk: { |
| 2155 | const payload = for_node.payload.castTag(.PointerIndexPayload).?; | 2143 | const payload = for_node.payload.castTag(.PointerIndexPayload).?; |
| ... | @@ -2178,16 +2166,8 @@ fn forExpr( | ... | @@ -2178,16 +2166,8 @@ fn forExpr( |
| 2178 | break :blk &index_scope.base; | 2166 | break :blk &index_scope.base; |
| 2179 | }; | 2167 | }; |
| 2180 | | 2168 | |
| 2181 | const then_result = try expr(mod, then_sub_scope, branch_rl, for_node.body); | 2169 | loop_scope.break_count += 1; |
| 2182 | if (!then_result.tag.isNoReturn()) { | 2170 | const then_result = try expr(mod, then_sub_scope, loop_scope.break_result_loc, for_node.body); |
| 2183 | _ = try addZIRInst(mod, then_sub_scope, then_src, zir.Inst.Break, .{ | | |
| 2184 | .block = cond_block, | | |
| 2185 | .operand = then_result, | | |
| 2186 | }, .{}); | | |
| 2187 | } | | |
| 2188 | condbr.positionals.then_body = .{ | | |
| 2189 | .instructions = try then_scope.arena.dupe(*zir.Inst, then_scope.instructions.items), | | |
| 2190 | }; | | |
| 2191 | | 2171 | |
| 2192 | // else branch | 2172 | // else branch |
| 2193 | var else_scope: Scope.GenZIR = .{ | 2173 | var else_scope: Scope.GenZIR = .{ |
| ... | @@ -2198,30 +2178,35 @@ fn forExpr( | ... | @@ -2198,30 +2178,35 @@ fn forExpr( |
| 2198 | }; | 2178 | }; |
| 2199 | defer else_scope.instructions.deinit(mod.gpa); | 2179 | defer else_scope.instructions.deinit(mod.gpa); |
| 2200 | | 2180 | |
| 2201 | if (for_node.@"else") |else_node| { | 2181 | var else_src: usize = undefined; |
| 2202 | const else_src = tree.token_locs[else_node.body.lastToken()].start; | 2182 | const else_result: ?*zir.Inst = if (for_node.@"else") |else_node| blk: { |
| 2203 | const else_result = try expr(mod, &else_scope.base, branch_rl, else_node.body); | 2183 | else_src = tree.token_locs[else_node.body.lastToken()].start; |
| 2204 | if (!else_result.tag.isNoReturn()) { | 2184 | loop_scope.break_count += 1; |
| 2205 | _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.Break, .{ | 2185 | break :blk try expr(mod, &else_scope.base, loop_scope.break_result_loc, else_node.body); |
| 2206 | .block = for_block, | 2186 | } else blk: { |
| 2207 | .operand = else_result, | 2187 | else_src = tree.token_locs[for_node.lastToken()].start; |
| 2208 | }, .{}); | 2188 | break :blk null; |
| 2209 | } | | |
| 2210 | } else { | | |
| 2211 | const else_src = tree.token_locs[for_node.lastToken()].start; | | |
| 2212 | _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.BreakVoid, .{ | | |
| 2213 | .block = for_block, | | |
| 2214 | }, .{}); | | |
| 2215 | } | | |
| 2216 | condbr.positionals.else_body = .{ | | |
| 2217 | .instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items), | | |
| 2218 | }; | 2189 | }; |
| 2219 | if (loop_scope.label) |some| { | 2190 | if (loop_scope.label) |some| { |
| 2220 | if (!some.used) { | 2191 | if (!some.used) { |
| 2221 | return mod.fail(scope, tree.token_locs[some.token].start, "unused for label", .{}); | 2192 | return mod.fail(scope, tree.token_locs[some.token].start, "unused for label", .{}); |
| 2222 | } | 2193 | } |
| 2223 | } | 2194 | } |
| 2224 | return &for_block.base; | 2195 | return finishThenElseBlock( |
| | 2196 | mod, |
| | 2197 | scope, |
| | 2198 | rl, |
| | 2199 | &loop_scope, |
| | 2200 | &then_scope, |
| | 2201 | &else_scope, |
| | 2202 | &condbr.positionals.then_body, |
| | 2203 | &condbr.positionals.else_body, |
| | 2204 | then_src, |
| | 2205 | else_src, |
| | 2206 | then_result, |
| | 2207 | else_result, |
| | 2208 | for_block, |
| | 2209 | ); |
| 2225 | } | 2210 | } |
| 2226 | | 2211 | |
| 2227 | fn getRangeNode(node: *ast.Node) ?*ast.Node.SimpleInfixOp { | 2212 | fn getRangeNode(node: *ast.Node) ?*ast.Node.SimpleInfixOp { |