From 68cfa736dfd38cc151af1f9e1b0edb3041bc237c Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 26 Jul 2025 06:23:31 -0400 Subject: [PATCH 1/2] x86_64: fix switch on mod result Closes #24541 --- src/arch/x86_64/CodeGen.zig | 17 ++++++++--------- test/behavior/switch.zig | 10 ++++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 89a23d3514..a7d771853c 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -1103,11 +1103,7 @@ const FormatAirData = struct { inst: Air.Inst.Index, }; fn formatAir(data: FormatAirData, w: *std.io.Writer) Writer.Error!void { - // not acceptable implementation because it ignores `w`: - //data.self.air.dumpInst(data.inst, data.self.pt, data.self.liveness); - _ = data; - _ = w; - @panic("TODO: unimplemented"); + data.self.air.writeInst(w, data.inst, data.self.pt, data.self.liveness); } fn fmtAir(self: *CodeGen, inst: Air.Inst.Index) std.fmt.Formatter(FormatAirData, formatAir) { return .{ .data = .{ .self = self, .inst = inst } }; @@ -179300,10 +179296,13 @@ fn lowerSwitchBr( } else undefined; const table_start: u31 = @intCast(cg.mir_table.items.len); { - const condition_index_reg = if (condition_index.isRegister()) - condition_index.getReg().? - else - try cg.copyToTmpRegister(.usize, condition_index); + const condition_index_reg = condition_index_reg: { + if (condition_index.isRegister()) { + const condition_index_reg = condition_index.getReg().?; + if (condition_index_reg.isClass(.general_purpose)) break :condition_index_reg condition_index_reg; + } + break :condition_index_reg try cg.copyToTmpRegister(.usize, condition_index); + }; const condition_index_lock = cg.register_manager.lockReg(condition_index_reg); defer if (condition_index_lock) |lock| cg.register_manager.unlockReg(lock); try cg.truncateRegister(condition_ty, condition_index_reg); diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index 813530b361..764080b937 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -1072,3 +1072,13 @@ test "switch on a signed value smaller than the smallest prong value" { else => {}, } } + +test "switch on 8-bit mod result" { + var x: u8 = undefined; + x = 16; + switch (x % 4) { + 0 => {}, + 1, 2, 3 => return error.TestFailed, + else => unreachable, + } +} From 3194a4d22b755393296a4db4c85d7b54ea83e96d Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 26 Jul 2025 07:30:56 -0400 Subject: [PATCH 2/2] x86_64: fix dst create alloc reg clobbering src Closes #24390 --- src/arch/x86_64/CodeGen.zig | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index a7d771853c..d100070294 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -191920,18 +191920,15 @@ const Select = struct { error.InvalidInstruction => { const fixes = @tagName(mir_tag[0]); const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?; - return s.cg.fail( - "invalid instruction: '{s}{s}{s} {s} {s} {s} {s}'", - .{ - fixes[0..fixes_blank], - @tagName(mir_tag[1]), - fixes[fixes_blank + 1 ..], - @tagName(mir_ops[0]), - @tagName(mir_ops[1]), - @tagName(mir_ops[2]), - @tagName(mir_ops[3]), - }, - ); + return s.cg.fail("invalid instruction: '{s}{s}{s} {s} {s} {s} {s}'", .{ + fixes[0..fixes_blank], + @tagName(mir_tag[1]), + fixes[fixes_blank + 1 ..], + @tagName(mir_ops[0]), + @tagName(mir_ops[1]), + @tagName(mir_ops[2]), + @tagName(mir_ops[3]), + }); }, else => |e| return e, }; @@ -194423,6 +194420,18 @@ fn select( while (true) for (pattern.src[0..src_temps.len], src_temps) |src_pattern, *src_temp| { if (try src_pattern.convert(src_temp, cg)) break; } else break; + var src_locks: [s_src_temps.len][2]?RegisterLock = @splat(@splat(null)); + for (src_locks[0..src_temps.len], src_temps) |*locks, src_temp| { + const regs: [2]Register = switch (src_temp.tracking(cg).short) { + else => continue, + .register => |reg| .{ reg, .none }, + .register_pair => |regs| regs, + }; + for (regs, locks) |reg, *lock| { + if (reg == .none) continue; + lock.* = cg.register_manager.lockRegIndex(RegisterManager.indexOfRegIntoTracked(reg) orelse continue); + } + } @memcpy(s_src_temps[0..src_temps.len], src_temps); std.mem.swap(Temp, &s_src_temps[pattern.commute[0]], &s_src_temps[pattern.commute[1]]); @@ -194441,6 +194450,7 @@ fn select( } assert(s.top == 0); + for (src_locks) |locks| for (locks) |lock| if (lock) |reg| cg.register_manager.unlockReg(reg); for (tmp_locks) |locks| for (locks) |lock| if (lock) |reg| cg.register_manager.unlockReg(reg); for (dst_locks) |locks| for (locks) |lock| if (lock) |reg| cg.register_manager.unlockReg(reg); caller_preserved: {