Commit b626977f45

Veikka Tuominen <git@vexu.eu>
2022-10-05 13:14:04
Sema: create sub block for inline loops
Closes #13038
1 parent ba4aa12
Changed files (2)
src
test
behavior
src/Sema.zig
@@ -1302,17 +1302,28 @@ fn analyzeBodyInner(
                 // current list of parameters and restore it later.
                 // Note: this probably needs to be resolved in a more general manner.
                 const prev_params = block.params;
-                const prev_inline_block = block.inline_block;
-                if (tags[inline_body[inline_body.len - 1]] == .repeat_inline) {
-                    block.inline_block = inline_body[0];
+                const need_sub_block = tags[inline_body[inline_body.len - 1]] == .repeat_inline;
+                var sub_block = block;
+                var block_space: Block = undefined;
+                // NOTE: this has to be done like this because branching in
+                // defers here breaks stage1.
+                block_space.instructions = .{};
+                if (need_sub_block) {
+                    block_space = block.makeSubBlock();
+                    block_space.inline_block = inline_body[0];
+                    sub_block = &block_space;
                 }
                 block.params = .{};
                 defer {
                     block.params.deinit(gpa);
                     block.params = prev_params;
-                    block.inline_block = prev_inline_block;
+                    block_space.instructions.deinit(gpa);
                 }
-                const opt_break_data = try sema.analyzeBodyBreak(block, inline_body);
+                const opt_break_data = try sema.analyzeBodyBreak(sub_block, inline_body);
+                if (need_sub_block) {
+                    try block.instructions.appendSlice(gpa, block_space.instructions.items);
+                }
+
                 // A runtime conditional branch that needs a post-hoc block to be
                 // emitted communicates this by mapping the block index into the inst map.
                 if (map.get(inst)) |new_block_ref| ph: {
test/behavior/eval.zig
@@ -1398,3 +1398,17 @@ test "continue in inline for inside a comptime switch" {
     }
     try expect(count == 4);
 }
+
+test "continue nested inline for loop" {
+    var a: u8 = 0;
+    loop: inline for ([_]u8{ 1, 2 }) |x| {
+        inline for ([_]u8{1}) |y| {
+            if (x == y) {
+                continue :loop;
+            }
+        }
+        a = x;
+        try expect(x == 2);
+    }
+    try expect(a == 2);
+}