From d81bdd8ab9092b844c974d0ab6dfe150cbf18f8d Mon Sep 17 00:00:00 2001 From: xtex Date: Wed, 2 Sep 2026 13:23:12 +0800 Subject: [PATCH 1/2] x86_64: save state after switch_br case comparison After each case body, lowerSwitchBr restores tracking state without emitting actual instructions, as state changes made in the body block can be forgotten safely. However, previously, the state was saved before generating the case condition code, leading to changes generated during the item comparison being discarded, breaking following cases. Fixes: #36732 --- src/codegen/x86_64/CodeGen.zig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index 97865d02b6f6247d285cee01f1abe03f42d908b7..b2335f3c7dfff9213e7af715123a9151dd0b0721 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -177120,8 +177120,6 @@ fn lowerSwitchBr( var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), cg.gpa); const allocator = bfa.allocator(); - const state = try cg.saveState(); - const liveness = try cg.liveness.getSwitchBr(allocator, inst, switch_br.cases_len + 1); defer allocator.free(liveness.deaths); @@ -177232,6 +177230,7 @@ fn lowerSwitchBr( } }; var cases_it = switch_br.iterateCases(); + const state = try cg.saveState(); while (cases_it.next()) |case| { { const table = cg.mir_table.items[table_start..][0..table_len]; @@ -177388,6 +177387,7 @@ fn lowerSwitchBr( // The jump to skip this case if the conditions all failed. const skip_case_reloc = try cg.asmJmpReloc(undefined); + const state = try cg.saveState(); for (liveness.deaths[case.idx]) |operand| try cg.processDeath(operand, .{}); @@ -177406,6 +177406,7 @@ fn lowerSwitchBr( } if (switch_br.else_body_len > 0) { const else_body = cases_it.elseBody(); + const state = try cg.saveState(); const else_deaths = liveness.deaths.len - 1; for (liveness.deaths[else_deaths]) |operand| try cg.processDeath(operand, .{}); -- 2.54.0 From adba66435502f0ac7f9cafe610f82960a53997da Mon Sep 17 00:00:00 2001 From: xtex Date: Tue, 8 Sep 2026 21:01:31 +0800 Subject: [PATCH 2/2] test: add regression test for #36732 --- test/behavior/switch.zig | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index 25eb5159357c06134f6b8e2f3fa5276528b7d4c4..1533d6d5693c7b6e283eab6653d8e018ea0c2d33 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -1568,3 +1568,16 @@ test "union field pointer capture preserves alignment in inline prong" { try comptime U.doTheTest(&.{ .a = 123 }); try comptime U.doTheTest(&.{ .b = 123 }); } + +test "switch on expression" { + var a: []const []const u8 = &.{ "b", "b", "A", "A", "b" }; + _ = &a; + var c: isize = 0; + for (a[1..]) |b| { + switch (b[0] % 2) { + 0 => c += 1, + else => c -= 1, + } + } + try expect(c == 0); +} -- 2.54.0