authorgravatar for xtex@astrafall.orgxtex <xtex@astrafall.org> 2026-09-02 13:23:12+08:00
committergravatar for xtex@astrafall.orgxtex <xtex@astrafall.org> 2026-10-03 15:20:14+08:00
logd81bdd8ab9092b844c974d0ab6dfe150cbf18f8d
tree127b98b1ad27c485795e80d3b8a5d4bb4b466122
parent1926e8c679dcf2264cd8af9f5bb1a62b8938c41f
signature Signed by SSH key SHA256:IEYEjkZlkUTr5U9GiDAmZU/4eZus2t2RsxusyhQqwao

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

1 files changed, 3 insertions(+), 2 deletions(-)

src/codegen/x86_64/CodeGen.zig+3-2
...@@ -177120,8 +177120,6 @@ fn lowerSwitchBr(...@@ -177120,8 +177120,6 @@ fn lowerSwitchBr(
177120 var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), cg.gpa);177120 var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), cg.gpa);
177121 const allocator = bfa.allocator();177121 const allocator = bfa.allocator();
177122177122
177123 const state = try cg.saveState();
177124
177125 const liveness = try cg.liveness.getSwitchBr(allocator, inst, switch_br.cases_len + 1);177123 const liveness = try cg.liveness.getSwitchBr(allocator, inst, switch_br.cases_len + 1);
177126 defer allocator.free(liveness.deaths);177124 defer allocator.free(liveness.deaths);
177127177125
...@@ -177232,6 +177230,7 @@ fn lowerSwitchBr(...@@ -177232,6 +177230,7 @@ fn lowerSwitchBr(
177232 }177230 }
177233 };177231 };
177234 var cases_it = switch_br.iterateCases();177232 var cases_it = switch_br.iterateCases();
177233 const state = try cg.saveState();
177235 while (cases_it.next()) |case| {177234 while (cases_it.next()) |case| {
177236 {177235 {
177237 const table = cg.mir_table.items[table_start..][0..table_len];177236 const table = cg.mir_table.items[table_start..][0..table_len];
...@@ -177388,6 +177387,7 @@ fn lowerSwitchBr(...@@ -177388,6 +177387,7 @@ fn lowerSwitchBr(
177388177387
177389 // The jump to skip this case if the conditions all failed.177388 // The jump to skip this case if the conditions all failed.
177390 const skip_case_reloc = try cg.asmJmpReloc(undefined);177389 const skip_case_reloc = try cg.asmJmpReloc(undefined);
177390 const state = try cg.saveState();
177391177391
177392 for (liveness.deaths[case.idx]) |operand| try cg.processDeath(operand, .{});177392 for (liveness.deaths[case.idx]) |operand| try cg.processDeath(operand, .{});
177393177393
...@@ -177406,6 +177406,7 @@ fn lowerSwitchBr(...@@ -177406,6 +177406,7 @@ fn lowerSwitchBr(
177406 }177406 }
177407 if (switch_br.else_body_len > 0) {177407 if (switch_br.else_body_len > 0) {
177408 const else_body = cases_it.elseBody();177408 const else_body = cases_it.elseBody();
177409 const state = try cg.saveState();
177409177410
177410 const else_deaths = liveness.deaths.len - 1;177411 const else_deaths = liveness.deaths.len - 1;
177411 for (liveness.deaths[else_deaths]) |operand| try cg.processDeath(operand, .{});177412 for (liveness.deaths[else_deaths]) |operand| try cg.processDeath(operand, .{});