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
457457 continue;
458458 }
459459
460 return addZIRInst(mod, parent_scope, src, zir.Inst.BreakVoid, .{
460 return addZirInstTag(mod, parent_scope, src, .break_void, .{
461461 .block = continue_block,
462 }, .{});
462 });
463463 },
464464 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
465465 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
......@@ -1908,22 +1908,13 @@ fn whileExpr(
19081908 if (while_node.inline_token) |tok|
19091909 return mod.failTok(scope, tok, "TODO inline while", .{});
19101910
1911 var expr_scope: Scope.GenZIR = .{
1911 var loop_scope: Scope.GenZIR = .{
19121912 .parent = scope,
19131913 .decl = scope.ownerDecl().?,
19141914 .arena = scope.arena(),
19151915 .instructions = .{},
19161916 };
1917 setBlockResultLoc(&expr_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 };
1917 setBlockResultLoc(&loop_scope, rl);
19271918 defer loop_scope.instructions.deinit(mod.gpa);
19281919
19291920 var continue_scope: Scope.GenZIR = .{
......@@ -1957,11 +1948,21 @@ fn whileExpr(
19571948 if (while_node.continue_expr) |cont_expr| {
19581949 _ = try expr(mod, &loop_scope.base, .{ .ty = void_type }, cont_expr);
19591950 }
1960 const loop = try addZIRInstLoop(mod, &expr_scope.base, while_src, .{
1961 .instructions = try expr_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items),
1962 });
1951 const loop = try scope.arena().create(zir.Inst.Loop);
1952 loop.* = .{
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 };
19631964 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}),
19651966 });
19661967 loop_scope.break_block = while_block;
19671968 loop_scope.continue_block = cond_block;
......@@ -1984,8 +1985,8 @@ fn whileExpr(
19841985 // declare payload to the then_scope
19851986 const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, then_src, while_node.payload);
19861987
1987 expr_scope.break_count += 1;
1988 const then_result = try expr(mod, then_sub_scope, expr_scope.break_result_loc, while_node.body);
1988 loop_scope.break_count += 1;
1989 const then_result = try expr(mod, then_sub_scope, loop_scope.break_result_loc, while_node.body);
19891990
19901991 var else_scope: Scope.GenZIR = .{
19911992 .parent = &continue_scope.base,
......@@ -1996,17 +1997,15 @@ fn whileExpr(
19961997 defer else_scope.instructions.deinit(mod.gpa);
19971998
19981999 var else_src: usize = undefined;
1999 var else_sub_scope: *Module.Scope = undefined;
20002000 const else_result: ?*zir.Inst = if (while_node.@"else") |else_node| blk: {
20012001 else_src = tree.token_locs[else_node.body.lastToken()].start;
20022002 // 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;
2006 break :blk try expr(mod, else_sub_scope, expr_scope.break_result_loc, else_node.body);
2005 loop_scope.break_count += 1;
2006 break :blk try expr(mod, else_sub_scope, loop_scope.break_result_loc, else_node.body);
20072007 } else blk: {
20082008 else_src = tree.token_locs[while_node.lastToken()].start;
2009 else_sub_scope = &else_scope.base;
20102009 break :blk null;
20112010 };
20122011 if (loop_scope.label) |some| {
......@@ -2018,7 +2017,7 @@ fn whileExpr(
20182017 mod,
20192018 scope,
20202019 rl,
2021 &expr_scope,
2020 &loop_scope,
20222021 &then_scope,
20232022 &else_scope,
20242023 &condbr.positionals.then_body,
......@@ -2037,9 +2036,6 @@ fn forExpr(
20372036 rl: ResultLoc,
20382037 for_node: *ast.Node.For,
20392038) InnerError!*zir.Inst {
2040 if (true) {
2041 @panic("TODO reimplement this");
2042 }
20432039 if (for_node.label) |label| {
20442040 try checkLabelRedefinition(mod, scope, label);
20452041 }
......@@ -2047,42 +2043,34 @@ fn forExpr(
20472043 if (for_node.inline_token) |tok|
20482044 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
20582046 // setup variables and constants
20592047 const tree = scope.tree();
20602048 const for_src = tree.token_locs[for_node.for_token].start;
20612049 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, .{
20632051 .ty = Type.initTag(.type),
20642052 .val = Value.initTag(.usize_type),
20652053 });
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);
20672055 // initialize to zero
2068 const zero = try addZIRInstConst(mod, &for_scope.base, for_src, .{
2056 const zero = try addZIRInstConst(mod, scope, for_src, .{
20692057 .ty = Type.initTag(.usize),
20702058 .val = Value.initTag(.zero),
20712059 });
2072 _ = try addZIRBinOp(mod, &for_scope.base, for_src, .store, index_ptr, zero);
2060 _ = try addZIRBinOp(mod, scope, for_src, .store, index_ptr, zero);
20732061 break :blk index_ptr;
20742062 };
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);
20762064 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
20792067 var loop_scope: Scope.GenZIR = .{
2080 .parent = &for_scope.base,
2081 .decl = for_scope.decl,
2082 .arena = for_scope.arena,
2068 .parent = scope,
2069 .decl = scope.ownerDecl().?,
2070 .arena = scope.arena(),
20832071 .instructions = .{},
2084 .break_result_loc = rl,
20852072 };
2073 setBlockResultLoc(&loop_scope, rl);
20862074 defer loop_scope.instructions.deinit(mod.gpa);
20872075
20882076 var cond_scope: Scope.GenZIR = .{
......@@ -2115,12 +2103,21 @@ fn forExpr(
21152103 const index_plus_one = try addZIRBinOp(mod, &loop_scope.base, for_src, .add, index_2, one);
21162104 _ = try addZIRBinOp(mod, &loop_scope.base, for_src, .store, index_ptr, index_plus_one);
21172105
2118 // looping stuff
2119 const loop = try addZIRInstLoop(mod, &for_scope.base, for_src, .{
2120 .instructions = try for_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items),
2121 });
2106 const loop = try scope.arena().create(zir.Inst.Loop);
2107 loop.* = .{
2108 .base = .{
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 };
21222119 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}),
21242121 });
21252122 loop_scope.break_block = for_block;
21262123 loop_scope.continue_block = cond_block;
......@@ -2141,15 +2138,6 @@ fn forExpr(
21412138 };
21422139 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
21532141 var index_scope: Scope.LocalPtr = undefined;
21542142 const then_sub_scope = blk: {
21552143 const payload = for_node.payload.castTag(.PointerIndexPayload).?;
......@@ -2178,16 +2166,8 @@ fn forExpr(
21782166 break :blk &index_scope.base;
21792167 };
21802168
2181 const then_result = try expr(mod, then_sub_scope, branch_rl, for_node.body);
2182 if (!then_result.tag.isNoReturn()) {
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 };
2169 loop_scope.break_count += 1;
2170 const then_result = try expr(mod, then_sub_scope, loop_scope.break_result_loc, for_node.body);
21912171
21922172 // else branch
21932173 var else_scope: Scope.GenZIR = .{
......@@ -2198,30 +2178,35 @@ fn forExpr(
21982178 };
21992179 defer else_scope.instructions.deinit(mod.gpa);
22002180
2201 if (for_node.@"else") |else_node| {
2202 const else_src = tree.token_locs[else_node.body.lastToken()].start;
2203 const else_result = try expr(mod, &else_scope.base, branch_rl, else_node.body);
2204 if (!else_result.tag.isNoReturn()) {
2205 _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.Break, .{
2206 .block = for_block,
2207 .operand = else_result,
2208 }, .{});
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),
2181 var else_src: usize = undefined;
2182 const else_result: ?*zir.Inst = if (for_node.@"else") |else_node| blk: {
2183 else_src = tree.token_locs[else_node.body.lastToken()].start;
2184 loop_scope.break_count += 1;
2185 break :blk try expr(mod, &else_scope.base, loop_scope.break_result_loc, else_node.body);
2186 } else blk: {
2187 else_src = tree.token_locs[for_node.lastToken()].start;
2188 break :blk null;
22182189 };
22192190 if (loop_scope.label) |some| {
22202191 if (!some.used) {
22212192 return mod.fail(scope, tree.token_locs[some.token].start, "unused for label", .{});
22222193 }
22232194 }
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 );
22252210}
22262211
22272212fn getRangeNode(node: *ast.Node) ?*ast.Node.SimpleInfixOp {