authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-25 13:20:02-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-31 21:09:22-07:00
logde85c4ac429d5d7f937189cb444233952f7cbbed
tree04e31eca3154410e693f24c9abac40b889348c21
parent9f4ff80108ece160bed80300d753ba6efaf3b1dd

astgen: rework for loops


1 files changed, 73 insertions(+), 88 deletions(-)

src/astgen.zig+73-88
...@@ -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 }
459459
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", .{});
19101910
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);
19281919
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_scope1985 // 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);
19861987
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);
19891990
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);
19971998
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_scope2002 // 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);
20042004
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", .{});
20492045
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 constants2046 // 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 zero2055 // 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);
20782066
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);
20872075
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);
21172105
2118 // looping stuff2106 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);
21432140
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 };
21802168
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 };
21912171
2192 // else branch2172 // 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);
22002180
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}
22262211
2227fn getRangeNode(node: *ast.Node) ?*ast.Node.SimpleInfixOp {2212fn getRangeNode(node: *ast.Node) ?*ast.Node.SimpleInfixOp {