diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-01-25 13:20:02 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-01-31 21:09:22 -0700 |
| commit | de85c4ac429d5d7f937189cb444233952f7cbbed (patch) | |
| tree | 04e31eca3154410e693f24c9abac40b889348c21 /src | |
| parent | 9f4ff80108ece160bed80300d753ba6efaf3b1dd (diff) | |
| download | zig-de85c4ac429d5d7f937189cb444233952f7cbbed.tar.gz zig-de85c4ac429d5d7f937189cb444233952f7cbbed.zip | |
astgen: rework for loops
Diffstat (limited to 'src')
| -rw-r--r-- | src/astgen.zig | 161 |
1 files changed, 73 insertions, 88 deletions
diff --git a/src/astgen.zig b/src/astgen.zig index e0bd913a52..446ee98eb4 100644 --- a/src/astgen.zig +++ b/src/astgen.zig @@ -457,9 +457,9 @@ fn continueExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowE continue; } - return addZIRInst(mod, parent_scope, src, zir.Inst.BreakVoid, .{ + return addZirInstTag(mod, parent_scope, src, .break_void, .{ .block = continue_block, - }, .{}); + }); }, .local_val => scope = scope.cast(Scope.LocalVal).?.parent, .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, @@ -1908,22 +1908,13 @@ fn whileExpr( if (while_node.inline_token) |tok| return mod.failTok(scope, tok, "TODO inline while", .{}); - var expr_scope: Scope.GenZIR = .{ + var loop_scope: Scope.GenZIR = .{ .parent = scope, .decl = scope.ownerDecl().?, .arena = scope.arena(), .instructions = .{}, }; - setBlockResultLoc(&expr_scope, rl); - defer expr_scope.instructions.deinit(mod.gpa); - - var loop_scope: Scope.GenZIR = .{ - .parent = &expr_scope.base, - .decl = expr_scope.decl, - .arena = expr_scope.arena, - .instructions = .{}, - .break_result_loc = rl, - }; + setBlockResultLoc(&loop_scope, rl); defer loop_scope.instructions.deinit(mod.gpa); var continue_scope: Scope.GenZIR = .{ @@ -1957,11 +1948,21 @@ fn whileExpr( if (while_node.continue_expr) |cont_expr| { _ = try expr(mod, &loop_scope.base, .{ .ty = void_type }, cont_expr); } - const loop = try addZIRInstLoop(mod, &expr_scope.base, while_src, .{ - .instructions = try expr_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items), - }); + const loop = try scope.arena().create(zir.Inst.Loop); + loop.* = .{ + .base = .{ + .tag = .loop, + .src = while_src, + }, + .positionals = .{ + .body = .{ + .instructions = try scope.arena().dupe(*zir.Inst, loop_scope.instructions.items), + }, + }, + .kw_args = .{}, + }; const while_block = try addZIRInstBlock(mod, scope, while_src, .block, .{ - .instructions = try expr_scope.arena.dupe(*zir.Inst, expr_scope.instructions.items), + .instructions = try scope.arena().dupe(*zir.Inst, &[1]*zir.Inst{&loop.base}), }); loop_scope.break_block = while_block; loop_scope.continue_block = cond_block; @@ -1984,8 +1985,8 @@ fn whileExpr( // declare payload to the then_scope const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, then_src, while_node.payload); - expr_scope.break_count += 1; - const then_result = try expr(mod, then_sub_scope, expr_scope.break_result_loc, while_node.body); + loop_scope.break_count += 1; + const then_result = try expr(mod, then_sub_scope, loop_scope.break_result_loc, while_node.body); var else_scope: Scope.GenZIR = .{ .parent = &continue_scope.base, @@ -1996,17 +1997,15 @@ fn whileExpr( defer else_scope.instructions.deinit(mod.gpa); var else_src: usize = undefined; - var else_sub_scope: *Module.Scope = undefined; const else_result: ?*zir.Inst = if (while_node.@"else") |else_node| blk: { else_src = tree.token_locs[else_node.body.lastToken()].start; // declare payload to the then_scope - else_sub_scope = try cond_kind.elseSubScope(mod, &else_scope, else_src, else_node.payload); + const else_sub_scope = try cond_kind.elseSubScope(mod, &else_scope, else_src, else_node.payload); - expr_scope.break_count += 1; - break :blk try expr(mod, else_sub_scope, expr_scope.break_result_loc, else_node.body); + loop_scope.break_count += 1; + break :blk try expr(mod, else_sub_scope, loop_scope.break_result_loc, else_node.body); } else blk: { else_src = tree.token_locs[while_node.lastToken()].start; - else_sub_scope = &else_scope.base; break :blk null; }; if (loop_scope.label) |some| { @@ -2018,7 +2017,7 @@ fn whileExpr( mod, scope, rl, - &expr_scope, + &loop_scope, &then_scope, &else_scope, &condbr.positionals.then_body, @@ -2037,9 +2036,6 @@ fn forExpr( rl: ResultLoc, for_node: *ast.Node.For, ) InnerError!*zir.Inst { - if (true) { - @panic("TODO reimplement this"); - } if (for_node.label) |label| { try checkLabelRedefinition(mod, scope, label); } @@ -2047,42 +2043,34 @@ fn forExpr( if (for_node.inline_token) |tok| return mod.failTok(scope, tok, "TODO inline for", .{}); - var for_scope: Scope.GenZIR = .{ - .parent = scope, - .decl = scope.ownerDecl().?, - .arena = scope.arena(), - .instructions = .{}, - }; - defer for_scope.instructions.deinit(mod.gpa); - // setup variables and constants const tree = scope.tree(); const for_src = tree.token_locs[for_node.for_token].start; const index_ptr = blk: { - const usize_type = try addZIRInstConst(mod, &for_scope.base, for_src, .{ + const usize_type = try addZIRInstConst(mod, scope, for_src, .{ .ty = Type.initTag(.type), .val = Value.initTag(.usize_type), }); - const index_ptr = try addZIRUnOp(mod, &for_scope.base, for_src, .alloc, usize_type); + const index_ptr = try addZIRUnOp(mod, scope, for_src, .alloc, usize_type); // initialize to zero - const zero = try addZIRInstConst(mod, &for_scope.base, for_src, .{ + const zero = try addZIRInstConst(mod, scope, for_src, .{ .ty = Type.initTag(.usize), .val = Value.initTag(.zero), }); - _ = try addZIRBinOp(mod, &for_scope.base, for_src, .store, index_ptr, zero); + _ = try addZIRBinOp(mod, scope, for_src, .store, index_ptr, zero); break :blk index_ptr; }; - const array_ptr = try expr(mod, &for_scope.base, .ref, for_node.array_expr); + const array_ptr = try expr(mod, scope, .ref, for_node.array_expr); const cond_src = tree.token_locs[for_node.array_expr.firstToken()].start; - const len = try addZIRUnOp(mod, &for_scope.base, cond_src, .indexable_ptr_len, array_ptr); + const len = try addZIRUnOp(mod, scope, cond_src, .indexable_ptr_len, array_ptr); var loop_scope: Scope.GenZIR = .{ - .parent = &for_scope.base, - .decl = for_scope.decl, - .arena = for_scope.arena, + .parent = scope, + .decl = scope.ownerDecl().?, + .arena = scope.arena(), .instructions = .{}, - .break_result_loc = rl, }; + setBlockResultLoc(&loop_scope, rl); defer loop_scope.instructions.deinit(mod.gpa); var cond_scope: Scope.GenZIR = .{ @@ -2115,12 +2103,21 @@ fn forExpr( const index_plus_one = try addZIRBinOp(mod, &loop_scope.base, for_src, .add, index_2, one); _ = try addZIRBinOp(mod, &loop_scope.base, for_src, .store, index_ptr, index_plus_one); - // looping stuff - const loop = try addZIRInstLoop(mod, &for_scope.base, for_src, .{ - .instructions = try for_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items), - }); + const loop = try scope.arena().create(zir.Inst.Loop); + loop.* = .{ + .base = .{ + .tag = .loop, + .src = for_src, + }, + .positionals = .{ + .body = .{ + .instructions = try scope.arena().dupe(*zir.Inst, loop_scope.instructions.items), + }, + }, + .kw_args = .{}, + }; const for_block = try addZIRInstBlock(mod, scope, for_src, .block, .{ - .instructions = try for_scope.arena.dupe(*zir.Inst, for_scope.instructions.items), + .instructions = try scope.arena().dupe(*zir.Inst, &[1]*zir.Inst{&loop.base}), }); loop_scope.break_block = for_block; loop_scope.continue_block = cond_block; @@ -2141,15 +2138,6 @@ fn forExpr( }; defer then_scope.instructions.deinit(mod.gpa); - // Most result location types can be forwarded directly; however - // if we need to write to a pointer which has an inferred type, - // proper type inference requires peer type resolution on the while's - // branches. - const branch_rl: ResultLoc = switch (rl) { - .discard, .none, .ty, .ptr, .ref => rl, - .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = for_block }, - }; - var index_scope: Scope.LocalPtr = undefined; const then_sub_scope = blk: { const payload = for_node.payload.castTag(.PointerIndexPayload).?; @@ -2178,16 +2166,8 @@ fn forExpr( break :blk &index_scope.base; }; - const then_result = try expr(mod, then_sub_scope, branch_rl, for_node.body); - if (!then_result.tag.isNoReturn()) { - _ = try addZIRInst(mod, then_sub_scope, then_src, zir.Inst.Break, .{ - .block = cond_block, - .operand = then_result, - }, .{}); - } - condbr.positionals.then_body = .{ - .instructions = try then_scope.arena.dupe(*zir.Inst, then_scope.instructions.items), - }; + loop_scope.break_count += 1; + const then_result = try expr(mod, then_sub_scope, loop_scope.break_result_loc, for_node.body); // else branch var else_scope: Scope.GenZIR = .{ @@ -2198,30 +2178,35 @@ fn forExpr( }; defer else_scope.instructions.deinit(mod.gpa); - if (for_node.@"else") |else_node| { - const else_src = tree.token_locs[else_node.body.lastToken()].start; - const else_result = try expr(mod, &else_scope.base, branch_rl, else_node.body); - if (!else_result.tag.isNoReturn()) { - _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.Break, .{ - .block = for_block, - .operand = else_result, - }, .{}); - } - } else { - const else_src = tree.token_locs[for_node.lastToken()].start; - _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.BreakVoid, .{ - .block = for_block, - }, .{}); - } - condbr.positionals.else_body = .{ - .instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items), + var else_src: usize = undefined; + const else_result: ?*zir.Inst = if (for_node.@"else") |else_node| blk: { + else_src = tree.token_locs[else_node.body.lastToken()].start; + loop_scope.break_count += 1; + break :blk try expr(mod, &else_scope.base, loop_scope.break_result_loc, else_node.body); + } else blk: { + else_src = tree.token_locs[for_node.lastToken()].start; + break :blk null; }; if (loop_scope.label) |some| { if (!some.used) { return mod.fail(scope, tree.token_locs[some.token].start, "unused for label", .{}); } } - return &for_block.base; + return finishThenElseBlock( + mod, + scope, + rl, + &loop_scope, + &then_scope, + &else_scope, + &condbr.positionals.then_body, + &condbr.positionals.else_body, + then_src, + else_src, + then_result, + else_result, + for_block, + ); } fn getRangeNode(node: *ast.Node) ?*ast.Node.SimpleInfixOp { |
