Commit 3194a4d22b

Jacob Young <jacobly0@users.noreply.github.com>
2025-07-26 13:30:56
x86_64: fix dst create alloc reg clobbering src
Closes #24390
1 parent 68cfa73
Changed files (1)
src
arch
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: {