astgen: fix continue expressions

This commit is contained in:
Andrew Kelley 2021-03-26 18:26:39 -07:00
parent a217ad59c7
commit a72bfd00cf
2 changed files with 97 additions and 99 deletions

View File

@ -766,11 +766,9 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerErro
} }
fn continueExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref { fn continueExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {
if (true) @panic("TODO update for zir-memory-layout"); const parent_gz = parent_scope.getGenZir();
const tree = parent_scope.tree(); const tree = parent_gz.tree();
const node_datas = tree.nodes.items(.data); const node_datas = tree.nodes.items(.data);
const main_tokens = tree.nodes.items(.main_token);
const break_label = node_datas[node].lhs; const break_label = node_datas[node].lhs;
// Look for the label in the scope. // Look for the label in the scope.
@ -779,10 +777,11 @@ fn continueExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerE
switch (scope.tag) { switch (scope.tag) {
.gen_zir => { .gen_zir => {
const gen_zir = scope.cast(Scope.GenZir).?; const gen_zir = scope.cast(Scope.GenZir).?;
const continue_block = gen_zir.continue_block orelse { const continue_block = gen_zir.continue_block;
if (continue_block == 0) {
scope = gen_zir.parent; scope = gen_zir.parent;
continue; continue;
}; }
if (break_label != 0) blk: { if (break_label != 0) blk: {
if (gen_zir.label) |*label| { if (gen_zir.label) |*label| {
if (try tokenIdentEql(mod, parent_scope, label.token, break_label)) { if (try tokenIdentEql(mod, parent_scope, label.token, break_label)) {
@ -795,9 +794,8 @@ fn continueExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerE
continue; continue;
} }
_ = try addZirInstTag(mod, parent_scope, src, .break_void, .{ // TODO emit a break_inline if the loop being continued is inline
.block = continue_block, _ = try parent_gz.addBreak(.@"break", continue_block, .void_value);
});
return zir.Inst.Ref.unreachable_value; return zir.Inst.Ref.unreachable_value;
}, },
.local_val => scope = scope.cast(Scope.LocalVal).?.parent, .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
@ -806,7 +804,7 @@ fn continueExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerE
const label_name = try mod.identifierTokenString(parent_scope, break_label); const label_name = try mod.identifierTokenString(parent_scope, break_label);
return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name}); return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name});
} else { } else {
return mod.failTok(parent_scope, src, "continue expression outside loop", .{}); return mod.failNode(parent_scope, node, "continue expression outside loop", .{});
}, },
} }
} }

View File

@ -1128,97 +1128,97 @@ pub fn addCases(ctx: *TestContext) !void {
, &[_][]const u8{":4:8: error: unable to infer variable type"}); , &[_][]const u8{":4:8: error: unable to infer variable type"});
} }
//{ {
// var case = ctx.exe("break/continue", linux_x64); var case = ctx.exe("break/continue", linux_x64);
// // Break out of loop // Break out of loop
// case.addCompareOutput( case.addCompareOutput(
// \\export fn _start() noreturn { \\export fn _start() noreturn {
// \\ while (true) { \\ while (true) {
// \\ break; \\ break;
// \\ } \\ }
// \\ \\
// \\ exit(); \\ exit();
// \\} \\}
// \\ \\
// \\fn exit() noreturn { \\fn exit() noreturn {
// \\ asm volatile ("syscall" \\ asm volatile ("syscall"
// \\ : \\ :
// \\ : [number] "{rax}" (231), \\ : [number] "{rax}" (231),
// \\ [arg1] "{rdi}" (0) \\ [arg1] "{rdi}" (0)
// \\ : "rcx", "r11", "memory" \\ : "rcx", "r11", "memory"
// \\ ); \\ );
// \\ unreachable; \\ unreachable;
// \\} \\}
// , ,
// "", "",
// ); );
// case.addCompareOutput( case.addCompareOutput(
// \\export fn _start() noreturn { \\export fn _start() noreturn {
// \\ foo: while (true) { \\ foo: while (true) {
// \\ break :foo; \\ break :foo;
// \\ } \\ }
// \\ \\
// \\ exit(); \\ exit();
// \\} \\}
// \\ \\
// \\fn exit() noreturn { \\fn exit() noreturn {
// \\ asm volatile ("syscall" \\ asm volatile ("syscall"
// \\ : \\ :
// \\ : [number] "{rax}" (231), \\ : [number] "{rax}" (231),
// \\ [arg1] "{rdi}" (0) \\ [arg1] "{rdi}" (0)
// \\ : "rcx", "r11", "memory" \\ : "rcx", "r11", "memory"
// \\ ); \\ );
// \\ unreachable; \\ unreachable;
// \\} \\}
// , ,
// "", "",
// ); );
// // Continue in loop // Continue in loop
// case.addCompareOutput( case.addCompareOutput(
// \\export fn _start() noreturn { \\export fn _start() noreturn {
// \\ var i: u64 = 0; \\ var i: u64 = 0;
// \\ while (true) : (i+=1) { \\ while (true) : (i+=1) {
// \\ if (i == 4) exit(); \\ if (i == 4) exit();
// \\ continue; \\ continue;
// \\ } \\ }
// \\} \\}
// \\ \\
// \\fn exit() noreturn { \\fn exit() noreturn {
// \\ asm volatile ("syscall" \\ asm volatile ("syscall"
// \\ : \\ :
// \\ : [number] "{rax}" (231), \\ : [number] "{rax}" (231),
// \\ [arg1] "{rdi}" (0) \\ [arg1] "{rdi}" (0)
// \\ : "rcx", "r11", "memory" \\ : "rcx", "r11", "memory"
// \\ ); \\ );
// \\ unreachable; \\ unreachable;
// \\} \\}
// , ,
// "", "",
// ); );
// case.addCompareOutput( case.addCompareOutput(
// \\export fn _start() noreturn { \\export fn _start() noreturn {
// \\ var i: u64 = 0; \\ var i: u64 = 0;
// \\ foo: while (true) : (i+=1) { \\ foo: while (true) : (i+=1) {
// \\ if (i == 4) exit(); \\ if (i == 4) exit();
// \\ continue :foo; \\ continue :foo;
// \\ } \\ }
// \\} \\}
// \\ \\
// \\fn exit() noreturn { \\fn exit() noreturn {
// \\ asm volatile ("syscall" \\ asm volatile ("syscall"
// \\ : \\ :
// \\ : [number] "{rax}" (231), \\ : [number] "{rax}" (231),
// \\ [arg1] "{rdi}" (0) \\ [arg1] "{rdi}" (0)
// \\ : "rcx", "r11", "memory" \\ : "rcx", "r11", "memory"
// \\ ); \\ );
// \\ unreachable; \\ unreachable;
// \\} \\}
// , ,
// "", "",
// ); );
//} }
{ {
var case = ctx.exe("unused labels", linux_x64); var case = ctx.exe("unused labels", linux_x64);