authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-06 09:03:08+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-06 13:42:11+02:00
logac1aaec9c38eb44b93099ff18579a9401f107100
tree8769d87fe8299d790aa5d2b858f1d5a535c4a8c7
parentdf38dfa4d1c9028453f90c7e37dd6c06f829a995

x64: handle CF flags spilling in overflow calls

Handle spilling of CF flags set with an overflow call. Add saving stack offset to memory.

1 files changed, 34 insertions(+), 6 deletions(-)

src/arch/x86_64/CodeGen.zig+34-6
......@@ -966,14 +966,16 @@ pub fn spillCompareFlagsIfOccupied(self: *Self) !void {
966966 const mcv = self.getResolvedInstValue(inst_to_save);
967967 assert(mcv.usesCompareFlags());
968968
969 const new_mcv = try self.allocRegOrMem(inst_to_save, true);
969 const new_mcv = try self.allocRegOrMem(inst_to_save, !mcv.isRegister());
970970 try self.setRegOrMem(self.air.typeOfIndex(inst_to_save), new_mcv, mcv);
971971 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });
972
973972 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
974973 try branch.inst_table.put(self.gpa, inst_to_save, new_mcv);
975974
976975 self.compare_flags_inst = null;
976 // TODO consolidate with register manager and spillInstruction
977 // this call should really belong in the register manager!
978 if (mcv.isRegister()) self.register_manager.freeReg(mcv.asRegister().?);
977979 }
978980}
979981
......@@ -1404,6 +1406,9 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
14041406 return self.fail("TODO implement add_with_overflow for Ints larger than 64bits", .{});
14051407 }
14061408
1409 try self.spillCompareFlagsIfOccupied();
1410 self.compare_flags_inst = inst;
1411
14071412 const partial = try self.genBinMathOp(inst, bin_op.lhs, bin_op.rhs);
14081413 const result: MCValue = switch (int_info.signedness) {
14091414 .signed => .{ .register_overflow_signed = partial.register },
......@@ -1433,6 +1438,9 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
14331438 return self.fail("TODO implement sub_with_overflow for Ints larger than 64bits", .{});
14341439 }
14351440
1441 try self.spillCompareFlagsIfOccupied();
1442 self.compare_flags_inst = inst;
1443
14361444 const partial = try self.genSubOp(inst, bin_op.lhs, bin_op.rhs);
14371445 const result: MCValue = switch (int_info.signedness) {
14381446 .signed => .{ .register_overflow_signed = partial.register },
......@@ -1456,9 +1464,6 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
14561464 switch (ty.zigTypeTag()) {
14571465 .Vector => return self.fail("TODO implement mul_with_overflow for Vector type", .{}),
14581466 .Int => {
1459 try self.spillCompareFlagsIfOccupied();
1460 self.compare_flags_inst = null;
1461
14621467 const int_info = ty.intInfo(self.target.*);
14631468
14641469 if (int_info.bits > 64) {
......@@ -1466,6 +1471,9 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
14661471 }
14671472
14681473 if (math.isPowerOfTwo(int_info.bits)) {
1474 try self.spillCompareFlagsIfOccupied();
1475 self.compare_flags_inst = inst;
1476
14691477 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.
14701478 try self.register_manager.getReg(.rax, inst);
14711479 try self.register_manager.getReg(.rdx, null);
......@@ -1487,6 +1495,9 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
14871495 break :result result;
14881496 }
14891497
1498 try self.spillCompareFlagsIfOccupied();
1499 self.compare_flags_inst = null;
1500
14901501 const dst_reg: Register = dst_reg: {
14911502 switch (int_info.signedness) {
14921503 .signed => {
......@@ -2783,7 +2794,6 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
27832794}
27842795
27852796fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {
2786 _ = ptr_ty;
27872797 const abi_size = value_ty.abiSize(self.target.*);
27882798 switch (ptr) {
27892799 .none => unreachable,
......@@ -3000,6 +3010,24 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
30003010
30013011 try self.genInlineMemcpy(.{ .register = addr_reg.to64() }, value, .{ .immediate = abi_size }, .{});
30023012 },
3013 .stack_offset => {
3014 if (abi_size <= 8) {
3015 // TODO this should really be a recursive call
3016 const tmp_reg = try self.copyToTmpRegister(value_ty, value);
3017 _ = try self.addInst(.{
3018 .tag = .mov,
3019 .ops = (Mir.Ops{
3020 .reg1 = addr_reg.to64(),
3021 .reg2 = tmp_reg,
3022 .flags = 0b10,
3023 }).encode(),
3024 .data = .{ .imm = 0 },
3025 });
3026 return;
3027 }
3028
3029 try self.genInlineMemcpy(.{ .register = addr_reg.to64() }, value, .{ .immediate = abi_size }, .{});
3030 },
30033031 else => return self.fail("TODO implement storing {} to MCValue.memory", .{value}),
30043032 }
30053033 },