authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-01 00:28:22+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-02 10:48:21+01:00
log09e69c8c776d21be5441a0b15f13a3ce9608ab87
tree7a0186cfb08b184778ff0a9d5f0cbed01c696a3d
parent5cf918143c7c5857142ac12c3587928ed74b2052

x86_64: start moving to new regalloc freeze API


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

src/arch/x86_64/CodeGen.zig+26-30
......@@ -680,6 +680,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
680680 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
681681 // zig fmt: on
682682 }
683
684 assert(!self.register_manager.frozenRegsExist());
685
683686 if (std.debug.runtime_safety) {
684687 if (self.air_bookkeeping < old_air_bookkeeping + 1) {
685688 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 {
827830/// Allocates a new register and copies `mcv` into it.
828831/// `reg_owner` is the instruction that gets associated with the register in the register table.
829832/// This can have a side effect of spilling instructions to the stack to free up a register.
830fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
833fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, ty: Type, mcv: MCValue) !MCValue {
831834 const reg = try self.register_manager.allocReg(reg_owner, &.{});
832 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
835 try self.genSetReg(ty, reg, mcv);
833836 return MCValue{ .register = reg };
834837}
835838
......@@ -838,11 +841,12 @@ fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCVa
838841fn copyToNewRegisterWithExceptions(
839842 self: *Self,
840843 reg_owner: Air.Inst.Index,
844 ty: Type,
841845 mcv: MCValue,
842846 exceptions: []const Register,
843847) !MCValue {
844848 const reg = try self.register_manager.allocReg(reg_owner, exceptions);
845 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
849 try self.genSetReg(ty, reg, mcv);
846850 return MCValue{ .register = reg };
847851}
848852
......@@ -892,13 +896,10 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
892896 if (operand_abi_size > 8 or dest_abi_size > 8) {
893897 return self.fail("TODO implement intCast for abi sizes larger than 8", .{});
894898 }
895 const reg = switch (operand) {
896 .register => |src_reg| try self.register_manager.allocReg(inst, &.{src_reg}),
897 else => try self.register_manager.allocReg(inst, &.{}),
898 };
899 try self.genSetReg(dest_ty, reg, .{ .immediate = 0 });
900 try self.genSetReg(dest_ty, reg, operand);
901 break :blk .{ .register = registerAlias(reg, @intCast(u32, dest_abi_size)) };
899
900 if (operand.isRegister()) self.register_manager.freezeRegs(&.{operand.register});
901 defer if (operand.isRegister()) self.register_manager.unfreezeRegs(&.{operand.register});
902 break :blk try self.copyToNewRegister(inst, dest_ty, operand);
902903 };
903904
904905 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
......@@ -1208,7 +1209,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
12081209 if (self.reuseOperand(inst, ty_op.operand, 0, operand)) {
12091210 break :result operand;
12101211 }
1211 break :result try self.copyToNewRegister(inst, operand);
1212 break :result try self.copyToNewRegister(inst, self.air.typeOfIndex(inst), operand);
12121213 };
12131214 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
12141215}
......@@ -1479,16 +1480,11 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
14791480 const index_ty = self.air.typeOf(extra.rhs);
14801481 const index = try self.resolveInst(extra.rhs);
14811482 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
1482 const dst_mcv = blk: {
1483 switch (ptr) {
1484 .ptr_stack_offset => {
1485 const reg = try self.register_manager.allocReg(inst, &.{offset_reg});
1486 try self.genSetReg(ptr_ty, reg, ptr);
1487 break :blk .{ .register = reg };
1488 },
1489 else => return self.fail("TODO implement ptr_elem_ptr when ptr is {}", .{ptr}),
1490 }
1491 };
1483
1484 self.register_manager.freezeRegs(&.{offset_reg});
1485 defer self.register_manager.unfreezeRegs(&.{offset_reg});
1486
1487 const dst_mcv = try self.copyToNewRegister(inst, ptr_ty, ptr);
14921488 try self.genBinMathOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
14931489 break :result dst_mcv;
14941490 };
......@@ -1859,13 +1855,14 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
18591855 // Source operand can be an immediate, 8 bits or 32 bits.
18601856 // So, if either one of the operands dies with this instruction, we can use it
18611857 // as the result MCValue.
1858 const dst_ty = self.air.typeOfIndex(inst);
18621859 var dst_mcv: MCValue = undefined;
18631860 var src_mcv: MCValue = undefined;
18641861 if (self.reuseOperand(inst, op_lhs, 0, lhs)) {
18651862 // LHS dies; use it as the destination.
18661863 // Both operands cannot be memory.
18671864 if (lhs.isMemory() and rhs.isMemory()) {
1868 dst_mcv = try self.copyToNewRegister(inst, lhs);
1865 dst_mcv = try self.copyToNewRegister(inst, dst_ty, lhs);
18691866 src_mcv = rhs;
18701867 } else {
18711868 dst_mcv = lhs;
......@@ -1875,7 +1872,7 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
18751872 // RHS dies; use it as the destination.
18761873 // Both operands cannot be memory.
18771874 if (lhs.isMemory() and rhs.isMemory()) {
1878 dst_mcv = try self.copyToNewRegister(inst, rhs);
1875 dst_mcv = try self.copyToNewRegister(inst, dst_ty, rhs);
18791876 src_mcv = lhs;
18801877 } else {
18811878 dst_mcv = rhs;
......@@ -1887,18 +1884,18 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
18871884 // If the allocated register is the same as the rhs register, don't allocate that one
18881885 // and instead spill a subsequent one. Otherwise, this can result in a miscompilation
18891886 // in the presence of several binary operations performed in a single block.
1890 try self.copyToNewRegisterWithExceptions(inst, lhs, &.{rhs.register})
1887 try self.copyToNewRegisterWithExceptions(inst, dst_ty, lhs, &.{rhs.register})
18911888 else
1892 try self.copyToNewRegister(inst, lhs);
1889 try self.copyToNewRegister(inst, dst_ty, lhs);
18931890 src_mcv = rhs;
18941891 } else {
18951892 dst_mcv = if (lhs.isRegister())
18961893 // If the allocated register is the same as the rhs register, don't allocate that one
18971894 // and instead spill a subsequent one. Otherwise, this can result in a miscompilation
18981895 // in the presence of several binary operations performed in a single block.
1899 try self.copyToNewRegisterWithExceptions(inst, rhs, &.{lhs.register})
1896 try self.copyToNewRegisterWithExceptions(inst, dst_ty, rhs, &.{lhs.register})
19001897 else
1901 try self.copyToNewRegister(inst, rhs);
1898 try self.copyToNewRegister(inst, dst_ty, rhs);
19021899 src_mcv = lhs;
19031900 }
19041901 }
......@@ -1917,7 +1914,6 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
19171914 }
19181915
19191916 // Now for step 2, we assing an MIR instruction
1920 const dst_ty = self.air.typeOfIndex(inst);
19211917 const air_tags = self.air.instructions.items(.tag);
19221918 switch (air_tags[inst]) {
19231919 .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 {
24172413 .register => |reg| {
24182414 if (Register.allocIndex(reg) == null) {
24192415 // Save function return value in a callee saved register
2420 break :result try self.copyToNewRegister(inst, info.return_value);
2416 break :result try self.copyToNewRegister(inst, self.air.typeOfIndex(inst), info.return_value);
24212417 }
24222418 },
24232419 else => {},
......@@ -2494,7 +2490,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
24942490 // Either one, but not both, can be a memory operand.
24952491 // Source operand can be an immediate, 8 bits or 32 bits.
24962492 const dst_mcv = if (lhs.isImmediate() or (lhs.isMemory() and rhs.isMemory()))
2497 try self.copyToNewRegister(inst, lhs)
2493 try self.copyToNewRegister(inst, ty, lhs)
24982494 else
24992495 lhs;
25002496 // This instruction supports only signed 32-bit immediates at most.
test/behavior/cast.zig-4
......@@ -5,8 +5,6 @@ const maxInt = std.math.maxInt;
55const builtin = @import("builtin");
66
77test "int to ptr cast" {
8 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
9
108 const x = @as(usize, 13);
119 const y = @intToPtr(*u8, x);
1210 const z = @ptrToInt(y);
......@@ -14,8 +12,6 @@ test "int to ptr cast" {
1412}
1513
1614test "integer literal to pointer cast" {
17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
18
1915 const vga_mem = @intToPtr(*u16, 0xB8000);
2016 try expect(@ptrToInt(vga_mem) == 0xB8000);
2117}