authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-07 10:31:08+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-07 10:31:08+02:00
log43a627927f989034ae64846abea73bc8bdb545be
tree013d5461f93704047072e6b6849a4028577394f1
parentac954eb539ec242af568fe3565094cea12c4beea

x64: fix misused register locks


2 files changed, 26 insertions(+), 27 deletions(-)

src/arch/x86_64/CodeGen.zig+19-26
......@@ -211,6 +211,16 @@ pub const MCValue = union(enum) {
211211 else => false,
212212 };
213213 }
214
215 fn asRegister(mcv: MCValue) ?Register {
216 return switch (mcv) {
217 .register,
218 .register_overflow_unsigned,
219 .register_overflow_signed,
220 => |reg| reg,
221 else => null,
222 };
223 }
214224};
215225
216226const Branch = struct {
......@@ -842,20 +852,15 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
842852 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
843853 branch.inst_table.putAssumeCapacityNoClobber(inst, result);
844854
845 switch (result) {
846 .register,
847 .register_overflow_signed,
848 .register_overflow_unsigned,
849 => |reg| {
850 // In some cases (such as bitcast), an operand
851 // may be the same MCValue as the result. If
852 // that operand died and was a register, it
853 // was freed by processDeath. We have to
854 // "re-allocate" the register.
855 if (self.register_manager.isRegFree(reg)) {
856 self.register_manager.getRegAssumeFree(reg, inst);
857 }
858 },
855 if (result.asRegister()) |reg| {
856 // In some cases (such as bitcast), an operand
857 // may be the same MCValue as the result. If
858 // that operand died and was a register, it
859 // was freed by processDeath. We have to
860 // "re-allocate" the register.
861 if (self.register_manager.isRegFree(reg)) {
862 self.register_manager.getRegAssumeFree(reg, inst);
863 }
859864 }
860865 }
861866 self.finishAirBookkeeping();
......@@ -4011,12 +4016,6 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
40114016 const ret_ty = self.fn_type.fnReturnType();
40124017 switch (self.ret_mcv) {
40134018 .stack_offset => {
4014 var reg_locks: [2]RegisterLock = undefined;
4015 self.register_manager.freezeRegsAssumeUnused(2, .{ .rax, .rcx }, &reg_locks);
4016 defer for (reg_locks) |reg| {
4017 self.register_manager.unfreezeReg(reg);
4018 };
4019
40204019 const reg = try self.copyToTmpRegister(Type.usize, self.ret_mcv);
40214020 const reg_lock = self.register_manager.freezeRegAssumeUnused(reg);
40224021 defer self.register_manager.unfreezeReg(reg_lock);
......@@ -4051,12 +4050,6 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
40514050 const elem_ty = ptr_ty.elemType();
40524051 switch (self.ret_mcv) {
40534052 .stack_offset => {
4054 var reg_locks: [2]RegisterLock = undefined;
4055 self.register_manager.freezeRegsAssumeUnused(2, .{ .rax, .rcx }, &reg_locks);
4056 defer for (reg_locks) |reg| {
4057 self.register_manager.unfreezeReg(reg);
4058 };
4059
40604053 const reg = try self.copyToTmpRegister(Type.usize, self.ret_mcv);
40614054 const reg_lock = self.register_manager.freezeRegAssumeUnused(reg);
40624055 defer self.register_manager.unfreezeReg(reg_lock);
src/register_manager.zig+7-1
......@@ -127,7 +127,11 @@ pub fn RegisterManager(
127127 /// Only the owner of the `RegisterLock` can unfreeze the
128128 /// register later.
129129 pub fn freezeReg(self: *Self, reg: Register) ?RegisterLock {
130 if (self.isRegFrozen(reg)) return null;
130 log.debug("freezing {}", .{reg});
131 if (self.isRegFrozen(reg)) {
132 log.debug(" register already locked", .{});
133 return null;
134 }
131135 const mask = getRegisterMask(reg) orelse return null;
132136 self.frozen_registers |= mask;
133137 return RegisterLock{ .register = reg };
......@@ -136,6 +140,7 @@ pub fn RegisterManager(
136140 /// Like `freezeReg` but asserts the register was unused always
137141 /// returning a valid lock.
138142 pub fn freezeRegAssumeUnused(self: *Self, reg: Register) RegisterLock {
143 log.debug("freezing asserting free {}", .{reg});
139144 assert(!self.isRegFrozen(reg));
140145 const mask = getRegisterMask(reg) orelse unreachable;
141146 self.frozen_registers |= mask;
......@@ -158,6 +163,7 @@ pub fn RegisterManager(
158163 /// Requires `RegisterLock` to unfreeze a register.
159164 /// Call `freezeReg` to obtain the lock first.
160165 pub fn unfreezeReg(self: *Self, lock: RegisterLock) void {
166 log.debug("unfreezing {}", .{lock.register});
161167 const mask = getRegisterMask(lock.register) orelse return;
162168 self.frozen_registers &= ~mask;
163169 }