mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
x64: fix misused register locks
This commit is contained in:
parent
ac954eb539
commit
43a627927f
@ -211,6 +211,16 @@ pub const MCValue = union(enum) {
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
fn asRegister(mcv: MCValue) ?Register {
|
||||
return switch (mcv) {
|
||||
.register,
|
||||
.register_overflow_unsigned,
|
||||
.register_overflow_signed,
|
||||
=> |reg| reg,
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const Branch = struct {
|
||||
@ -842,20 +852,15 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
|
||||
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
|
||||
branch.inst_table.putAssumeCapacityNoClobber(inst, result);
|
||||
|
||||
switch (result) {
|
||||
.register,
|
||||
.register_overflow_signed,
|
||||
.register_overflow_unsigned,
|
||||
=> |reg| {
|
||||
// In some cases (such as bitcast), an operand
|
||||
// may be the same MCValue as the result. If
|
||||
// that operand died and was a register, it
|
||||
// was freed by processDeath. We have to
|
||||
// "re-allocate" the register.
|
||||
if (self.register_manager.isRegFree(reg)) {
|
||||
self.register_manager.getRegAssumeFree(reg, inst);
|
||||
}
|
||||
},
|
||||
if (result.asRegister()) |reg| {
|
||||
// In some cases (such as bitcast), an operand
|
||||
// may be the same MCValue as the result. If
|
||||
// that operand died and was a register, it
|
||||
// was freed by processDeath. We have to
|
||||
// "re-allocate" the register.
|
||||
if (self.register_manager.isRegFree(reg)) {
|
||||
self.register_manager.getRegAssumeFree(reg, inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.finishAirBookkeeping();
|
||||
@ -4011,12 +4016,6 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ret_ty = self.fn_type.fnReturnType();
|
||||
switch (self.ret_mcv) {
|
||||
.stack_offset => {
|
||||
var reg_locks: [2]RegisterLock = undefined;
|
||||
self.register_manager.freezeRegsAssumeUnused(2, .{ .rax, .rcx }, ®_locks);
|
||||
defer for (reg_locks) |reg| {
|
||||
self.register_manager.unfreezeReg(reg);
|
||||
};
|
||||
|
||||
const reg = try self.copyToTmpRegister(Type.usize, self.ret_mcv);
|
||||
const reg_lock = self.register_manager.freezeRegAssumeUnused(reg);
|
||||
defer self.register_manager.unfreezeReg(reg_lock);
|
||||
@ -4051,12 +4050,6 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const elem_ty = ptr_ty.elemType();
|
||||
switch (self.ret_mcv) {
|
||||
.stack_offset => {
|
||||
var reg_locks: [2]RegisterLock = undefined;
|
||||
self.register_manager.freezeRegsAssumeUnused(2, .{ .rax, .rcx }, ®_locks);
|
||||
defer for (reg_locks) |reg| {
|
||||
self.register_manager.unfreezeReg(reg);
|
||||
};
|
||||
|
||||
const reg = try self.copyToTmpRegister(Type.usize, self.ret_mcv);
|
||||
const reg_lock = self.register_manager.freezeRegAssumeUnused(reg);
|
||||
defer self.register_manager.unfreezeReg(reg_lock);
|
||||
|
||||
@ -127,7 +127,11 @@ pub fn RegisterManager(
|
||||
/// Only the owner of the `RegisterLock` can unfreeze the
|
||||
/// register later.
|
||||
pub fn freezeReg(self: *Self, reg: Register) ?RegisterLock {
|
||||
if (self.isRegFrozen(reg)) return null;
|
||||
log.debug("freezing {}", .{reg});
|
||||
if (self.isRegFrozen(reg)) {
|
||||
log.debug(" register already locked", .{});
|
||||
return null;
|
||||
}
|
||||
const mask = getRegisterMask(reg) orelse return null;
|
||||
self.frozen_registers |= mask;
|
||||
return RegisterLock{ .register = reg };
|
||||
@ -136,6 +140,7 @@ pub fn RegisterManager(
|
||||
/// Like `freezeReg` but asserts the register was unused always
|
||||
/// returning a valid lock.
|
||||
pub fn freezeRegAssumeUnused(self: *Self, reg: Register) RegisterLock {
|
||||
log.debug("freezing asserting free {}", .{reg});
|
||||
assert(!self.isRegFrozen(reg));
|
||||
const mask = getRegisterMask(reg) orelse unreachable;
|
||||
self.frozen_registers |= mask;
|
||||
@ -158,6 +163,7 @@ pub fn RegisterManager(
|
||||
/// Requires `RegisterLock` to unfreeze a register.
|
||||
/// Call `freezeReg` to obtain the lock first.
|
||||
pub fn unfreezeReg(self: *Self, lock: RegisterLock) void {
|
||||
log.debug("unfreezing {}", .{lock.register});
|
||||
const mask = getRegisterMask(lock.register) orelse return;
|
||||
self.frozen_registers &= ~mask;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user