| author | |
| committer | |
| log | 29ac68b2537b9a9c67f92cc2a5dd4c35bf1c2b31 |
| tree | a05c443ab692add1dabd0f504d28c5ca21e9ef01 |
| parent | f43f89a70588c2add2a7c84d12eef2852d215f51 |
Add an additional check before emitting `.loop_switch_br` instead
of `.switch_br` in a tagged switch statement for whether any of the
continues referencing its tag are actually runtime reachable.
This fixes triggering an assertion in Liveness caused by the invalid
assumption that every tagged switch must be a loop if its tag is
referenced in any way even if this reference is not runtime reachable.2 files changed, 15 insertions(+), 1 deletions(-)
src/Sema.zig+3-1| ... | ... | @@ -13041,8 +13041,10 @@ fn analyzeSwitchRuntimeBlock( |
| 13041 | 13041 | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(cases_extra.items)); |
| 13042 | 13042 | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(else_body)); |
| 13043 | 13043 | |
| 13044 | const has_any_continues = spa.operand == .loop and child_block.label.?.merges.extra_insts.items.len > 0; | |
| 13045 | ||
| 13044 | 13046 | return try child_block.addInst(.{ |
| 13045 | .tag = if (spa.operand == .loop) .loop_switch_br else .switch_br, | |
| 13047 | .tag = if (has_any_continues) .loop_switch_br else .switch_br, | |
| 13046 | 13048 | .data = .{ .pl_op = .{ |
| 13047 | 13049 | .operand = operand, |
| 13048 | 13050 | .payload = payload_index, |
test/cases/discard_labeled_switch_tag.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | // https://github.com/ziglang/zig/issues/24323 | |
| 2 | ||
| 3 | export fn f() void { | |
| 4 | const x: u32 = 0; | |
| 5 | sw: switch (x) { | |
| 6 | else => if (false) continue :sw undefined, | |
| 7 | } | |
| 8 | } | |
| 9 | ||
| 10 | // compile | |
| 11 | // backend=stage2,llvm | |
| 12 | // target=native |