mirror of
https://github.com/ziglang/zig.git
synced 2026-01-04 04:25:05 +00:00
x86_64: start moving to new regalloc freeze API
This commit is contained in:
parent
5cf918143c
commit
09e69c8c77
@ -680,6 +680,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
||||
// zig fmt: on
|
||||
}
|
||||
|
||||
assert(!self.register_manager.frozenRegsExist());
|
||||
|
||||
if (std.debug.runtime_safety) {
|
||||
if (self.air_bookkeeping < old_air_bookkeeping + 1) {
|
||||
std.debug.panic("in codegen.zig, handling of AIR instruction %{d} ('{}') did not do proper bookkeeping. Look for a missing call to finishAir.", .{ inst, air_tags[inst] });
|
||||
@ -827,9 +830,9 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
|
||||
/// Allocates a new register and copies `mcv` into it.
|
||||
/// `reg_owner` is the instruction that gets associated with the register in the register table.
|
||||
/// This can have a side effect of spilling instructions to the stack to free up a register.
|
||||
fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
|
||||
fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, ty: Type, mcv: MCValue) !MCValue {
|
||||
const reg = try self.register_manager.allocReg(reg_owner, &.{});
|
||||
try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
|
||||
try self.genSetReg(ty, reg, mcv);
|
||||
return MCValue{ .register = reg };
|
||||
}
|
||||
|
||||
@ -838,11 +841,12 @@ fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCVa
|
||||
fn copyToNewRegisterWithExceptions(
|
||||
self: *Self,
|
||||
reg_owner: Air.Inst.Index,
|
||||
ty: Type,
|
||||
mcv: MCValue,
|
||||
exceptions: []const Register,
|
||||
) !MCValue {
|
||||
const reg = try self.register_manager.allocReg(reg_owner, exceptions);
|
||||
try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
|
||||
try self.genSetReg(ty, reg, mcv);
|
||||
return MCValue{ .register = reg };
|
||||
}
|
||||
|
||||
@ -892,13 +896,10 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
|
||||
if (operand_abi_size > 8 or dest_abi_size > 8) {
|
||||
return self.fail("TODO implement intCast for abi sizes larger than 8", .{});
|
||||
}
|
||||
const reg = switch (operand) {
|
||||
.register => |src_reg| try self.register_manager.allocReg(inst, &.{src_reg}),
|
||||
else => try self.register_manager.allocReg(inst, &.{}),
|
||||
};
|
||||
try self.genSetReg(dest_ty, reg, .{ .immediate = 0 });
|
||||
try self.genSetReg(dest_ty, reg, operand);
|
||||
break :blk .{ .register = registerAlias(reg, @intCast(u32, dest_abi_size)) };
|
||||
|
||||
if (operand.isRegister()) self.register_manager.freezeRegs(&.{operand.register});
|
||||
defer if (operand.isRegister()) self.register_manager.unfreezeRegs(&.{operand.register});
|
||||
break :blk try self.copyToNewRegister(inst, dest_ty, operand);
|
||||
};
|
||||
|
||||
return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
|
||||
@ -1208,7 +1209,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
|
||||
if (self.reuseOperand(inst, ty_op.operand, 0, operand)) {
|
||||
break :result operand;
|
||||
}
|
||||
break :result try self.copyToNewRegister(inst, operand);
|
||||
break :result try self.copyToNewRegister(inst, self.air.typeOfIndex(inst), operand);
|
||||
};
|
||||
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||
}
|
||||
@ -1479,16 +1480,11 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const index_ty = self.air.typeOf(extra.rhs);
|
||||
const index = try self.resolveInst(extra.rhs);
|
||||
const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
|
||||
const dst_mcv = blk: {
|
||||
switch (ptr) {
|
||||
.ptr_stack_offset => {
|
||||
const reg = try self.register_manager.allocReg(inst, &.{offset_reg});
|
||||
try self.genSetReg(ptr_ty, reg, ptr);
|
||||
break :blk .{ .register = reg };
|
||||
},
|
||||
else => return self.fail("TODO implement ptr_elem_ptr when ptr is {}", .{ptr}),
|
||||
}
|
||||
};
|
||||
|
||||
self.register_manager.freezeRegs(&.{offset_reg});
|
||||
defer self.register_manager.unfreezeRegs(&.{offset_reg});
|
||||
|
||||
const dst_mcv = try self.copyToNewRegister(inst, ptr_ty, ptr);
|
||||
try self.genBinMathOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
|
||||
break :result dst_mcv;
|
||||
};
|
||||
@ -1859,13 +1855,14 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
|
||||
// Source operand can be an immediate, 8 bits or 32 bits.
|
||||
// So, if either one of the operands dies with this instruction, we can use it
|
||||
// as the result MCValue.
|
||||
const dst_ty = self.air.typeOfIndex(inst);
|
||||
var dst_mcv: MCValue = undefined;
|
||||
var src_mcv: MCValue = undefined;
|
||||
if (self.reuseOperand(inst, op_lhs, 0, lhs)) {
|
||||
// LHS dies; use it as the destination.
|
||||
// Both operands cannot be memory.
|
||||
if (lhs.isMemory() and rhs.isMemory()) {
|
||||
dst_mcv = try self.copyToNewRegister(inst, lhs);
|
||||
dst_mcv = try self.copyToNewRegister(inst, dst_ty, lhs);
|
||||
src_mcv = rhs;
|
||||
} else {
|
||||
dst_mcv = lhs;
|
||||
@ -1875,7 +1872,7 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
|
||||
// RHS dies; use it as the destination.
|
||||
// Both operands cannot be memory.
|
||||
if (lhs.isMemory() and rhs.isMemory()) {
|
||||
dst_mcv = try self.copyToNewRegister(inst, rhs);
|
||||
dst_mcv = try self.copyToNewRegister(inst, dst_ty, rhs);
|
||||
src_mcv = lhs;
|
||||
} else {
|
||||
dst_mcv = rhs;
|
||||
@ -1887,18 +1884,18 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
|
||||
// If the allocated register is the same as the rhs register, don't allocate that one
|
||||
// and instead spill a subsequent one. Otherwise, this can result in a miscompilation
|
||||
// in the presence of several binary operations performed in a single block.
|
||||
try self.copyToNewRegisterWithExceptions(inst, lhs, &.{rhs.register})
|
||||
try self.copyToNewRegisterWithExceptions(inst, dst_ty, lhs, &.{rhs.register})
|
||||
else
|
||||
try self.copyToNewRegister(inst, lhs);
|
||||
try self.copyToNewRegister(inst, dst_ty, lhs);
|
||||
src_mcv = rhs;
|
||||
} else {
|
||||
dst_mcv = if (lhs.isRegister())
|
||||
// If the allocated register is the same as the rhs register, don't allocate that one
|
||||
// and instead spill a subsequent one. Otherwise, this can result in a miscompilation
|
||||
// in the presence of several binary operations performed in a single block.
|
||||
try self.copyToNewRegisterWithExceptions(inst, rhs, &.{lhs.register})
|
||||
try self.copyToNewRegisterWithExceptions(inst, dst_ty, rhs, &.{lhs.register})
|
||||
else
|
||||
try self.copyToNewRegister(inst, rhs);
|
||||
try self.copyToNewRegister(inst, dst_ty, rhs);
|
||||
src_mcv = lhs;
|
||||
}
|
||||
}
|
||||
@ -1917,7 +1914,6 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
|
||||
}
|
||||
|
||||
// Now for step 2, we assing an MIR instruction
|
||||
const dst_ty = self.air.typeOfIndex(inst);
|
||||
const air_tags = self.air.instructions.items(.tag);
|
||||
switch (air_tags[inst]) {
|
||||
.add, .addwrap, .ptr_add => try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv),
|
||||
@ -2417,7 +2413,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
|
||||
.register => |reg| {
|
||||
if (Register.allocIndex(reg) == null) {
|
||||
// Save function return value in a callee saved register
|
||||
break :result try self.copyToNewRegister(inst, info.return_value);
|
||||
break :result try self.copyToNewRegister(inst, self.air.typeOfIndex(inst), info.return_value);
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
@ -2494,7 +2490,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
|
||||
// Either one, but not both, can be a memory operand.
|
||||
// Source operand can be an immediate, 8 bits or 32 bits.
|
||||
const dst_mcv = if (lhs.isImmediate() or (lhs.isMemory() and rhs.isMemory()))
|
||||
try self.copyToNewRegister(inst, lhs)
|
||||
try self.copyToNewRegister(inst, ty, lhs)
|
||||
else
|
||||
lhs;
|
||||
// This instruction supports only signed 32-bit immediates at most.
|
||||
|
||||
@ -5,8 +5,6 @@ const maxInt = std.math.maxInt;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
test "int to ptr cast" {
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
|
||||
const x = @as(usize, 13);
|
||||
const y = @intToPtr(*u8, x);
|
||||
const z = @ptrToInt(y);
|
||||
@ -14,8 +12,6 @@ test "int to ptr cast" {
|
||||
}
|
||||
|
||||
test "integer literal to pointer cast" {
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
|
||||
const vga_mem = @intToPtr(*u16, 0xB8000);
|
||||
try expect(@ptrToInt(vga_mem) == 0xB8000);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user