authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-25 12:26:42-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-31 21:09:22-07:00
log9f4ff80108ece160bed80300d753ba6efaf3b1dd
treedf17a0983ed0c9310e6cbc3750a87ea2e1e629b4
parente9e6cc217124cb67c94790e38feaf45abda839ff

astgen: rework while


2 files changed, 37 insertions(+), 44 deletions(-)

src/astgen.zig+35-42
...@@ -1887,10 +1887,12 @@ fn copyBodyNoEliding(body: *zir.Body, scope: Module.Scope.GenZIR) !void {...@@ -1887,10 +1887,12 @@ fn copyBodyNoEliding(body: *zir.Body, scope: Module.Scope.GenZIR) !void {
1887 };1887 };
1888}1888}
18891889
1890fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.While) InnerError!*zir.Inst {1890fn whileExpr(
1891 if (true) {1891 mod: *Module,
1892 @panic("TODO reimplement this");1892 scope: *Scope,
1893 }1893 rl: ResultLoc,
1894 while_node: *ast.Node.While,
1895) InnerError!*zir.Inst {
1894 var cond_kind: CondKind = .bool;1896 var cond_kind: CondKind = .bool;
1895 if (while_node.payload) |_| cond_kind = .{ .optional = null };1897 if (while_node.payload) |_| cond_kind = .{ .optional = null };
1896 if (while_node.@"else") |else_node| {1898 if (while_node.@"else") |else_node| {
...@@ -1912,6 +1914,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W...@@ -1912,6 +1914,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
1912 .arena = scope.arena(),1914 .arena = scope.arena(),
1913 .instructions = .{},1915 .instructions = .{},
1914 };1916 };
1917 setBlockResultLoc(&expr_scope, rl);
1915 defer expr_scope.instructions.deinit(mod.gpa);1918 defer expr_scope.instructions.deinit(mod.gpa);
19161919
1917 var loop_scope: Scope.GenZIR = .{1920 var loop_scope: Scope.GenZIR = .{
...@@ -1981,25 +1984,8 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W...@@ -1981,25 +1984,8 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
1981 // declare payload to the then_scope1984 // declare payload to the then_scope
1982 const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, then_src, while_node.payload);1985 const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, then_src, while_node.payload);
19831986
1984 // Most result location types can be forwarded directly; however1987 expr_scope.break_count += 1;
1985 // if we need to write to a pointer which has an inferred type,1988 const then_result = try expr(mod, then_sub_scope, expr_scope.break_result_loc, while_node.body);
1986 // proper type inference requires peer type resolution on the while's
1987 // branches.
1988 const branch_rl: ResultLoc = switch (rl) {
1989 .discard, .none, .ty, .ptr, .ref => rl,
1990 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = while_block },
1991 };
1992
1993 const then_result = try expr(mod, then_sub_scope, branch_rl, while_node.body);
1994 if (!then_result.tag.isNoReturn()) {
1995 _ = try addZIRInst(mod, then_sub_scope, then_src, zir.Inst.Break, .{
1996 .block = cond_block,
1997 .operand = then_result,
1998 }, .{});
1999 }
2000 condbr.positionals.then_body = .{
2001 .instructions = try then_scope.arena.dupe(*zir.Inst, then_scope.instructions.items),
2002 };
20031989
2004 var else_scope: Scope.GenZIR = .{1990 var else_scope: Scope.GenZIR = .{
2005 .parent = &continue_scope.base,1991 .parent = &continue_scope.base,
...@@ -2009,33 +1995,40 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W...@@ -2009,33 +1995,40 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
2009 };1995 };
2010 defer else_scope.instructions.deinit(mod.gpa);1996 defer else_scope.instructions.deinit(mod.gpa);
20111997
2012 if (while_node.@"else") |else_node| {1998 var else_src: usize = undefined;
2013 const else_src = tree.token_locs[else_node.body.lastToken()].start;1999 var else_sub_scope: *Module.Scope = undefined;
2000 const else_result: ?*zir.Inst = if (while_node.@"else") |else_node| blk: {
2001 else_src = tree.token_locs[else_node.body.lastToken()].start;
2014 // declare payload to the then_scope2002 // declare payload to the then_scope
2015 const else_sub_scope = try cond_kind.elseSubScope(mod, &else_scope, else_src, else_node.payload);2003 else_sub_scope = try cond_kind.elseSubScope(mod, &else_scope, else_src, else_node.payload);
20162004
2017 const else_result = try expr(mod, else_sub_scope, branch_rl, else_node.body);2005 expr_scope.break_count += 1;
2018 if (!else_result.tag.isNoReturn()) {2006 break :blk try expr(mod, else_sub_scope, expr_scope.break_result_loc, else_node.body);
2019 _ = try addZIRInst(mod, else_sub_scope, else_src, zir.Inst.Break, .{2007 } else blk: {
2020 .block = while_block,2008 else_src = tree.token_locs[while_node.lastToken()].start;
2021 .operand = else_result,2009 else_sub_scope = &else_scope.base;
2022 }, .{});2010 break :blk null;
2023 }
2024 } else {
2025 const else_src = tree.token_locs[while_node.lastToken()].start;
2026 _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.BreakVoid, .{
2027 .block = while_block,
2028 }, .{});
2029 }
2030 condbr.positionals.else_body = .{
2031 .instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items),
2032 };2011 };
2033 if (loop_scope.label) |some| {2012 if (loop_scope.label) |some| {
2034 if (!some.used) {2013 if (!some.used) {
2035 return mod.fail(scope, tree.token_locs[some.token].start, "unused while label", .{});2014 return mod.fail(scope, tree.token_locs[some.token].start, "unused while label", .{});
2036 }2015 }
2037 }2016 }
2038 return &while_block.base;2017 return finishThenElseBlock(
2018 mod,
2019 scope,
2020 rl,
2021 &expr_scope,
2022 &then_scope,
2023 &else_scope,
2024 &condbr.positionals.then_body,
2025 &condbr.positionals.else_body,
2026 then_src,
2027 else_src,
2028 then_result,
2029 else_result,
2030 while_block,
2031 );
2039}2032}
20402033
2041fn forExpr(2034fn forExpr(
src/zir.zig+2-2
...@@ -1857,7 +1857,7 @@ const DumpTzir = struct {...@@ -1857,7 +1857,7 @@ const DumpTzir = struct {
1857 .loop => {1857 .loop => {
1858 const loop = inst.castTag(.loop).?;1858 const loop = inst.castTag(.loop).?;
18591859
1860 try writer.writeAll("\n");1860 try writer.writeAll("{\n");
18611861
1862 const old_indent = dtz.indent;1862 const old_indent = dtz.indent;
1863 dtz.indent += 2;1863 dtz.indent += 2;
...@@ -1865,7 +1865,7 @@ const DumpTzir = struct {...@@ -1865,7 +1865,7 @@ const DumpTzir = struct {
1865 dtz.indent = old_indent;1865 dtz.indent = old_indent;
18661866
1867 try writer.writeByteNTimes(' ', dtz.indent);1867 try writer.writeByteNTimes(' ', dtz.indent);
1868 try writer.writeAll(")\n");1868 try writer.writeAll("})\n");
1869 },1869 },
18701870
1871 .call => {1871 .call => {