authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-03 15:10:16+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-03 17:55:22+01:00
loge0b1170b676c04d1293970c717e13bdc01584671
tree30e369b2173470b0c399cfb4d7cbbdd518086265
parentcfceec15e10a30a595dbbb5300acdb2d17e16d75

x64: swap out register exceptions for freeze/unfreeze api


1 files changed, 99 insertions(+), 55 deletions(-)

src/arch/x86_64/CodeGen.zig+99-55
...@@ -21,7 +21,7 @@ const Emit = @import("Emit.zig");...@@ -21,7 +21,7 @@ const Emit = @import("Emit.zig");
21const Liveness = @import("../../Liveness.zig");21const Liveness = @import("../../Liveness.zig");
22const Mir = @import("Mir.zig");22const Mir = @import("Mir.zig");
23const Module = @import("../../Module.zig");23const Module = @import("../../Module.zig");
24const RegisterManager = @import("../../register_manager.zig").RegisterManager;24const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
25const Target = std.Target;25const Target = std.Target;
26const Type = @import("../../type.zig").Type;26const Type = @import("../../type.zig").Type;
27const TypedValue = @import("../../TypedValue.zig");27const TypedValue = @import("../../TypedValue.zig");
...@@ -33,6 +33,8 @@ const InnerError = error{...@@ -33,6 +33,8 @@ const InnerError = error{
33 CodegenFail,33 CodegenFail,
34};34};
3535
36const RegisterManager = RegisterManagerFn(Self, Register, &callee_preserved_regs);
37
36gpa: Allocator,38gpa: Allocator,
37air: Air,39air: Air,
38liveness: Liveness,40liveness: Liveness,
...@@ -73,7 +75,7 @@ branch_stack: *std.ArrayList(Branch),...@@ -73,7 +75,7 @@ branch_stack: *std.ArrayList(Branch),
73// Key is the block instruction75// Key is the block instruction
74blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, BlockData) = .{},76blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, BlockData) = .{},
7577
76register_manager: RegisterManager(Self, Register, &callee_preserved_regs) = .{},78register_manager: RegisterManager = .{},
77/// Maps offset to what is stored there.79/// Maps offset to what is stored there.
78stack: std.AutoHashMapUnmanaged(u32, StackAllocation) = .{},80stack: std.AutoHashMapUnmanaged(u32, StackAllocation) = .{},
7981
...@@ -169,6 +171,24 @@ pub const MCValue = union(enum) {...@@ -169,6 +171,24 @@ pub const MCValue = union(enum) {
169 else => false,171 else => false,
170 };172 };
171 }173 }
174
175 fn freezeIfRegister(mcv: MCValue, mgr: *RegisterManager) void {
176 switch (mcv) {
177 .register => |reg| {
178 mgr.freezeRegs(&.{reg});
179 },
180 else => {},
181 }
182 }
183
184 fn unfreezeIfRegister(mcv: MCValue, mgr: *RegisterManager) void {
185 switch (mcv) {
186 .register => |reg| {
187 mgr.unfreezeRegs(&.{reg});
188 },
189 else => {},
190 }
191 }
172};192};
173193
174const Branch = struct {194const Branch = struct {
...@@ -836,20 +856,6 @@ fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, ty: Type, mcv: MCVa...@@ -836,20 +856,6 @@ fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, ty: Type, mcv: MCVa
836 return MCValue{ .register = reg };856 return MCValue{ .register = reg };
837}857}
838858
839/// Like `copyToNewRegister` but allows to specify a list of excluded registers which
840/// will not be selected for allocation. This can be done via `exceptions` slice.
841fn copyToNewRegisterWithExceptions(
842 self: *Self,
843 reg_owner: Air.Inst.Index,
844 ty: Type,
845 mcv: MCValue,
846 exceptions: []const Register,
847) !MCValue {
848 const reg = try self.register_manager.allocReg(reg_owner, exceptions);
849 try self.genSetReg(ty, reg, mcv);
850 return MCValue{ .register = reg };
851}
852
853fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {859fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {
854 const stack_offset = try self.allocMemPtr(inst);860 const stack_offset = try self.allocMemPtr(inst);
855 return self.finishAir(inst, .{ .ptr_stack_offset = @intCast(i32, stack_offset) }, .{ .none, .none, .none });861 return self.finishAir(inst, .{ .ptr_stack_offset = @intCast(i32, stack_offset) }, .{ .none, .none, .none });
...@@ -897,8 +903,9 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -897,8 +903,9 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
897 return self.fail("TODO implement intCast for abi sizes larger than 8", .{});903 return self.fail("TODO implement intCast for abi sizes larger than 8", .{});
898 }904 }
899905
900 if (operand.isRegister()) self.register_manager.freezeRegs(&.{operand.register});906 operand.freezeIfRegister(&self.register_manager);
901 defer if (operand.isRegister()) self.register_manager.unfreezeRegs(&.{operand.register});907 defer operand.unfreezeIfRegister(&self.register_manager);
908
902 break :blk try self.copyToNewRegister(inst, dest_ty, operand);909 break :blk try self.copyToNewRegister(inst, dest_ty, operand);
903 };910 };
904911
...@@ -1366,8 +1373,7 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1366,8 +1373,7 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
1366}1373}
13671374
1368fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Register {1375fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Register {
1369 const reg = try self.register_manager.allocReg(null, &.{});1376 const reg = try self.copyToTmpRegister(index_ty, index);
1370 try self.genSetReg(index_ty, reg, index);
1371 try self.genIMulOpMir(index_ty, .{ .register = reg }, .{ .immediate = elem_size });1377 try self.genIMulOpMir(index_ty, .{ .register = reg }, .{ .immediate = elem_size });
1372 return reg;1378 return reg;
1373}1379}
...@@ -1376,16 +1382,26 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1376,16 +1382,26 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1376 const is_volatile = false; // TODO1382 const is_volatile = false; // TODO
1377 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1383 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1378 const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else result: {1384 const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else result: {
1379 const slice_mcv = try self.resolveInst(bin_op.lhs);
1380 const slice_ty = self.air.typeOf(bin_op.lhs);1385 const slice_ty = self.air.typeOf(bin_op.lhs);
1386 const slice_mcv = try self.resolveInst(bin_op.lhs);
1387 slice_mcv.freezeIfRegister(&self.register_manager);
1388 defer slice_mcv.unfreezeIfRegister(&self.register_manager);
1389
1381 const elem_ty = slice_ty.childType();1390 const elem_ty = slice_ty.childType();
1382 const elem_size = elem_ty.abiSize(self.target.*);1391 const elem_size = elem_ty.abiSize(self.target.*);
1383 var buf: Type.SlicePtrFieldTypeBuffer = undefined;1392 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1384 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);1393 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
1394
1385 const index_ty = self.air.typeOf(bin_op.rhs);1395 const index_ty = self.air.typeOf(bin_op.rhs);
1386 const index_mcv = try self.resolveInst(bin_op.rhs);1396 const index_mcv = try self.resolveInst(bin_op.rhs);
1397 index_mcv.freezeIfRegister(&self.register_manager);
1398 defer index_mcv.unfreezeIfRegister(&self.register_manager);
1399
1387 const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_size);1400 const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_size);
1388 const addr_reg = try self.register_manager.allocReg(null, &.{offset_reg});1401 self.register_manager.freezeRegs(&.{offset_reg});
1402 defer self.register_manager.unfreezeRegs(&.{offset_reg});
1403
1404 const addr_reg = try self.register_manager.allocReg(null, &.{});
1389 switch (slice_mcv) {1405 switch (slice_mcv) {
1390 .stack_offset => |off| {1406 .stack_offset => |off| {
1391 // mov reg, [rbp - 8]1407 // mov reg, [rbp - 8]
...@@ -1401,7 +1417,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1401,7 +1417,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1401 },1417 },
1402 else => return self.fail("TODO implement slice_elem_val when slice is {}", .{slice_mcv}),1418 else => return self.fail("TODO implement slice_elem_val when slice is {}", .{slice_mcv}),
1403 }1419 }
1404 // TODO we could allocate register here, but need to except addr register and potentially1420 // TODO we could allocate register here, but need to expect addr register and potentially
1405 // offset register.1421 // offset register.
1406 const dst_mcv = try self.allocRegOrMem(inst, false);1422 const dst_mcv = try self.allocRegOrMem(inst, false);
1407 try self.genBinMathOpMir(.add, slice_ptr_field_type, .{ .register = addr_reg.to64() }, .{1423 try self.genBinMathOpMir(.add, slice_ptr_field_type, .{ .register = addr_reg.to64() }, .{
...@@ -1427,14 +1443,23 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1427,14 +1443,23 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
1427 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1443 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1428 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1444 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1429 const array_ty = self.air.typeOf(bin_op.lhs);1445 const array_ty = self.air.typeOf(bin_op.lhs);
1430 const array = try self.resolveInst(bin_op.lhs);
1431 const array_abi_size = array_ty.abiSize(self.target.*);1446 const array_abi_size = array_ty.abiSize(self.target.*);
1447 const array = try self.resolveInst(bin_op.lhs);
1448 array.freezeIfRegister(&self.register_manager);
1449 defer array.unfreezeIfRegister(&self.register_manager);
1450
1432 const elem_ty = array_ty.childType();1451 const elem_ty = array_ty.childType();
1433 const elem_abi_size = elem_ty.abiSize(self.target.*);1452 const elem_abi_size = elem_ty.abiSize(self.target.*);
1434 const index_ty = self.air.typeOf(bin_op.rhs);1453 const index_ty = self.air.typeOf(bin_op.rhs);
1435 const index = try self.resolveInst(bin_op.rhs);1454 const index = try self.resolveInst(bin_op.rhs);
1455 index.freezeIfRegister(&self.register_manager);
1456 defer index.unfreezeIfRegister(&self.register_manager);
1457
1436 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);1458 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
1437 const addr_reg = try self.register_manager.allocReg(null, &.{offset_reg});1459 self.register_manager.freezeRegs(&.{offset_reg});
1460 defer self.register_manager.unfreezeRegs(&.{offset_reg});
1461
1462 const addr_reg = try self.register_manager.allocReg(null, &.{});
1438 switch (array) {1463 switch (array) {
1439 .stack_offset => |off| {1464 .stack_offset => |off| {
1440 // lea reg, [rbp]1465 // lea reg, [rbp]
...@@ -1449,7 +1474,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1449,7 +1474,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
1449 },1474 },
1450 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),1475 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
1451 }1476 }
1452 // TODO we could allocate register here, but need to except addr register and potentially1477 // TODO we could allocate register here, but need to expect addr register and potentially
1453 // offset register.1478 // offset register.
1454 const dst_mcv = try self.allocRegOrMem(inst, false);1479 const dst_mcv = try self.allocRegOrMem(inst, false);
1455 try self.genBinMathOpMir(.add, array_ty, .{ .register = addr_reg.to64() }, .{ .register = offset_reg.to64() });1480 try self.genBinMathOpMir(.add, array_ty, .{ .register = addr_reg.to64() }, .{ .register = offset_reg.to64() });
...@@ -1475,12 +1500,17 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1475,12 +1500,17 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
1475 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1500 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1476 const ptr_ty = self.air.typeOf(extra.lhs);1501 const ptr_ty = self.air.typeOf(extra.lhs);
1477 const ptr = try self.resolveInst(extra.lhs);1502 const ptr = try self.resolveInst(extra.lhs);
1503 ptr.freezeIfRegister(&self.register_manager);
1504 defer ptr.unfreezeIfRegister(&self.register_manager);
1505
1478 const elem_ty = ptr_ty.elemType2();1506 const elem_ty = ptr_ty.elemType2();
1479 const elem_abi_size = elem_ty.abiSize(self.target.*);1507 const elem_abi_size = elem_ty.abiSize(self.target.*);
1480 const index_ty = self.air.typeOf(extra.rhs);1508 const index_ty = self.air.typeOf(extra.rhs);
1481 const index = try self.resolveInst(extra.rhs);1509 const index = try self.resolveInst(extra.rhs);
1482 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);1510 index.freezeIfRegister(&self.register_manager);
1511 defer index.unfreezeIfRegister(&self.register_manager);
14831512
1513 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
1484 self.register_manager.freezeRegs(&.{offset_reg});1514 self.register_manager.freezeRegs(&.{offset_reg});
1485 defer self.register_manager.unfreezeRegs(&.{offset_reg});1515 defer self.register_manager.unfreezeRegs(&.{offset_reg});
14861516
...@@ -1587,6 +1617,9 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1587,6 +1617,9 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1587 return self.fail("TODO implement loading from MCValue.embedded_in_code", .{});1617 return self.fail("TODO implement loading from MCValue.embedded_in_code", .{});
1588 },1618 },
1589 .register => |reg| {1619 .register => |reg| {
1620 self.register_manager.freezeRegs(&.{reg});
1621 defer self.register_manager.unfreezeRegs(&.{reg});
1622
1590 switch (dst_mcv) {1623 switch (dst_mcv) {
1591 .dead => unreachable,1624 .dead => unreachable,
1592 .undef => unreachable,1625 .undef => unreachable,
...@@ -1607,16 +1640,15 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1607,16 +1640,15 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1607 },1640 },
1608 .stack_offset => |off| {1641 .stack_offset => |off| {
1609 if (abi_size <= 8) {1642 if (abi_size <= 8) {
1610 const tmp_reg = try self.register_manager.allocReg(null, &.{reg});1643 const tmp_reg = try self.register_manager.allocReg(null, &.{});
1611 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);1644 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
1612 return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });1645 return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
1613 }1646 }
16141647
1615 const regs = try self.register_manager.allocRegs(1648 self.register_manager.freezeRegs(&.{ .rax, .rcx });
1616 3,1649 defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx });
1617 .{ null, null, null },1650
1618 &.{ reg, .rax, .rcx },1651 const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{});
1619 );
1620 const addr_reg = regs[0];1652 const addr_reg = regs[0];
1621 const count_reg = regs[1];1653 const count_reg = regs[1];
1622 const tmp_reg = regs[2];1654 const tmp_reg = regs[2];
...@@ -1634,7 +1666,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1634,7 +1666,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1634 try self.register_manager.getReg(.rcx, null);1666 try self.register_manager.getReg(.rcx, null);
16351667
1636 // TODO allow for abi size to be u641668 // TODO allow for abi size to be u64
1637 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });1669 try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) });
16381670
1639 return self.genInlineMemcpy(1671 return self.genInlineMemcpy(
1640 -(off + @intCast(i32, abi_size)),1672 -(off + @intCast(i32, abi_size)),
...@@ -1786,8 +1818,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -1786,8 +1818,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
1786 // TODO: in case the address fits in an imm32 we can use [ds:imm32]1818 // TODO: in case the address fits in an imm32 we can use [ds:imm32]
1787 // instead of wasting an instruction copying the address to a register1819 // instead of wasting an instruction copying the address to a register
17881820
1789 if (value.isRegister()) self.register_manager.freezeRegs(&.{value.register});1821 value.freezeIfRegister(&self.register_manager);
1790 defer if (value.isRegister()) self.register_manager.unfreezeRegs(&.{value.register});1822 defer value.unfreezeIfRegister(&self.register_manager);
17911823
1792 const addr_reg = try self.copyToTmpRegister(ptr_ty, .{ .immediate = addr });1824 const addr_reg = try self.copyToTmpRegister(ptr_ty, .{ .immediate = addr });
1793 // to get the actual address of the value we want to modify we have to go through the GOT1825 // to get the actual address of the value we want to modify we have to go through the GOT
...@@ -2012,22 +2044,16 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:...@@ -2012,22 +2044,16 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
2012 }2044 }
2013 } else {2045 } else {
2014 if (lhs.isMemory()) {2046 if (lhs.isMemory()) {
2015 dst_mcv = if (rhs.isRegister())2047 rhs.freezeIfRegister(&self.register_manager);
2016 // If the allocated register is the same as the rhs register, don't allocate that one2048 defer rhs.unfreezeIfRegister(&self.register_manager);
2017 // and instead spill a subsequent one. Otherwise, this can result in a miscompilation2049
2018 // in the presence of several binary operations performed in a single block.2050 dst_mcv = try self.copyToNewRegister(inst, dst_ty, lhs);
2019 try self.copyToNewRegisterWithExceptions(inst, dst_ty, lhs, &.{rhs.register})
2020 else
2021 try self.copyToNewRegister(inst, dst_ty, lhs);
2022 src_mcv = rhs;2051 src_mcv = rhs;
2023 } else {2052 } else {
2024 dst_mcv = if (lhs.isRegister())2053 lhs.freezeIfRegister(&self.register_manager);
2025 // If the allocated register is the same as the rhs register, don't allocate that one2054 defer lhs.unfreezeIfRegister(&self.register_manager);
2026 // and instead spill a subsequent one. Otherwise, this can result in a miscompilation2055
2027 // in the presence of several binary operations performed in a single block.2056 dst_mcv = try self.copyToNewRegister(inst, dst_ty, rhs);
2028 try self.copyToNewRegisterWithExceptions(inst, dst_ty, rhs, &.{lhs.register})
2029 else
2030 try self.copyToNewRegister(inst, dst_ty, rhs);
2031 src_mcv = lhs;2057 src_mcv = lhs;
2032 }2058 }
2033 }2059 }
...@@ -2039,7 +2065,11 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:...@@ -2039,7 +2065,11 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
2039 switch (src_mcv) {2065 switch (src_mcv) {
2040 .immediate => |imm| {2066 .immediate => |imm| {
2041 if (imm > math.maxInt(u31)) {2067 if (imm > math.maxInt(u31)) {
2042 src_mcv = MCValue{ .register = try self.copyToTmpRegister(Type.initTag(.u64), src_mcv) };2068 dst_mcv.freezeIfRegister(&self.register_manager);
2069 defer dst_mcv.unfreezeIfRegister(&self.register_manager);
2070
2071 const tmp_reg = try self.copyToTmpRegister(Type.u64, src_mcv);
2072 src_mcv = MCValue{ .register = tmp_reg };
2043 }2073 }
2044 },2074 },
2045 else => {},2075 else => {},
...@@ -2901,6 +2931,8 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2901,6 +2931,8 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
2901 const un_op = self.air.instructions.items(.data)[inst].un_op;2931 const un_op = self.air.instructions.items(.data)[inst].un_op;
2902 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2932 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2903 const operand_ptr = try self.resolveInst(un_op);2933 const operand_ptr = try self.resolveInst(un_op);
2934 operand_ptr.freezeIfRegister(&self.register_manager);
2935 defer operand_ptr.unfreezeIfRegister(&self.register_manager);
2904 const operand: MCValue = blk: {2936 const operand: MCValue = blk: {
2905 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {2937 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
2906 // The MCValue that holds the pointer can be re-used as the value.2938 // The MCValue that holds the pointer can be re-used as the value.
...@@ -2930,6 +2962,8 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2930,6 +2962,8 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
2930 const un_op = self.air.instructions.items(.data)[inst].un_op;2962 const un_op = self.air.instructions.items(.data)[inst].un_op;
2931 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2963 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2932 const operand_ptr = try self.resolveInst(un_op);2964 const operand_ptr = try self.resolveInst(un_op);
2965 operand_ptr.freezeIfRegister(&self.register_manager);
2966 defer operand_ptr.unfreezeIfRegister(&self.register_manager);
2933 const operand: MCValue = blk: {2967 const operand: MCValue = blk: {
2934 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {2968 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
2935 // The MCValue that holds the pointer can be re-used as the value.2969 // The MCValue that holds the pointer can be re-used as the value.
...@@ -2959,6 +2993,8 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2959,6 +2993,8 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
2959 const un_op = self.air.instructions.items(.data)[inst].un_op;2993 const un_op = self.air.instructions.items(.data)[inst].un_op;
2960 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2994 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2961 const operand_ptr = try self.resolveInst(un_op);2995 const operand_ptr = try self.resolveInst(un_op);
2996 operand_ptr.freezeIfRegister(&self.register_manager);
2997 defer operand_ptr.unfreezeIfRegister(&self.register_manager);
2962 const operand: MCValue = blk: {2998 const operand: MCValue = blk: {
2963 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {2999 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
2964 // The MCValue that holds the pointer can be re-used as the value.3000 // The MCValue that holds the pointer can be re-used as the value.
...@@ -2988,6 +3024,8 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2988,6 +3024,8 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
2988 const un_op = self.air.instructions.items(.data)[inst].un_op;3024 const un_op = self.air.instructions.items(.data)[inst].un_op;
2989 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {3025 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2990 const operand_ptr = try self.resolveInst(un_op);3026 const operand_ptr = try self.resolveInst(un_op);
3027 operand_ptr.freezeIfRegister(&self.register_manager);
3028 defer operand_ptr.unfreezeIfRegister(&self.register_manager);
2991 const operand: MCValue = blk: {3029 const operand: MCValue = blk: {
2992 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {3030 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
2993 // The MCValue that holds the pointer can be re-used as the value.3031 // The MCValue that holds the pointer can be re-used as the value.
...@@ -3345,7 +3383,10 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE...@@ -3345,7 +3383,10 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
3345 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });3383 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
3346 }3384 }
33473385
3348 const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{ .rax, .rcx });3386 self.register_manager.freezeRegs(&.{ .rax, .rcx });
3387 defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx });
3388
3389 const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{});
3349 const addr_reg = regs[0];3390 const addr_reg = regs[0];
3350 const count_reg = regs[1];3391 const count_reg = regs[1];
3351 const tmp_reg = regs[2];3392 const tmp_reg = regs[2];
...@@ -3363,7 +3404,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE...@@ -3363,7 +3404,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
3363 });3404 });
33643405
3365 // TODO allow for abi_size to be u643406 // TODO allow for abi_size to be u64
3366 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });3407 try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) });
3367 try self.genInlineMemcpy(3408 try self.genInlineMemcpy(
3368 -(stack_offset + @intCast(i32, abi_size)),3409 -(stack_offset + @intCast(i32, abi_size)),
3369 .rsp,3410 .rsp,
...@@ -3510,7 +3551,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro...@@ -3510,7 +3551,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
3510 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });3551 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
3511 }3552 }
35123553
3513 const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{ .rax, .rcx, .rbp });3554 self.register_manager.freezeRegs(&.{ .rax, .rcx, .rbp });
3555 defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx, .rbp });
3556
3557 const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{});
3514 const addr_reg = regs[0];3558 const addr_reg = regs[0];
3515 const count_reg = regs[1];3559 const count_reg = regs[1];
3516 const tmp_reg = regs[2];3560 const tmp_reg = regs[2];
...@@ -3528,7 +3572,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro...@@ -3528,7 +3572,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
3528 });3572 });
35293573
3530 // TODO allow for abi_size to be u643574 // TODO allow for abi_size to be u64
3531 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });3575 try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) });
35323576
3533 return self.genInlineMemcpy(3577 return self.genInlineMemcpy(
3534 -(stack_offset + @intCast(i32, abi_size)),3578 -(stack_offset + @intCast(i32, abi_size)),