From 784704ac3a0f5bd48dd3e1f21fc20590ec5f60bd Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 5 Oct 2022 14:14:04 +0300 Subject: [PATCH] Sema: create sub block for inline loops Closes #13038 --- src/Sema.zig | 21 ++++++++++++++++----- test/behavior/eval.zig | 14 ++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 7dea22099520..80f7debc7bed 100644 --- a/src/Sema.zig +++ b/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: { diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index 849e0ca6ccf4..5faabe142fd5 100644 --- a/test/behavior/eval.zig +++ b/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); +}