authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-07 18:04:58+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-07 19:33:43+02:00
logfc015231ad4e2e449e848fd08dd003efd049ad43
tree570b0547f7cb42d3353e47532c581d7d19da1fa4
parent117f9f69e79a628347c9fdb22e7ee8618de143c5

x64: account for non-pow-two stores via register deref

In this case, we need to proceed rather carefully to avoid writing containing register width rather than the precise amount of bytes.

1 files changed, 40 insertions(+), 9 deletions(-)

src/arch/x86_64/CodeGen.zig+40-9
...@@ -2732,15 +2732,46 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2732,15 +2732,46 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2732 }2732 }
2733 },2733 },
2734 .register => |src_reg| {2734 .register => |src_reg| {
2735 _ = try self.addInst(.{2735 const src_reg_lock = self.register_manager.lockReg(src_reg);
2736 .tag = .mov,2736 defer if (src_reg_lock) |lock| self.register_manager.unlockReg(lock);
2737 .ops = Mir.Inst.Ops.encode(.{2737
2738 .reg1 = reg.to64(),2738 // TODO common code-path with genSetStack, refactor!
2739 .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),2739 if (!math.isPowerOfTwo(abi_size)) {
2740 .flags = 0b10,2740 const tmp_reg = try self.copyToTmpRegister(value_ty, value);
2741 }),2741
2742 .data = .{ .imm = 0 },2742 var next_offset: i32 = 0;
2743 });2743 var remainder = abi_size;
2744 while (remainder > 0) {
2745 const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder));
2746
2747 _ = try self.addInst(.{
2748 .tag = .mov,
2749 .ops = Mir.Inst.Ops.encode(.{
2750 .reg1 = reg.to64(),
2751 .reg2 = registerAlias(tmp_reg, nearest_power_of_two),
2752 .flags = 0b10,
2753 }),
2754 .data = .{ .imm = @bitCast(u32, -next_offset) },
2755 });
2756
2757 if (nearest_power_of_two > 1) {
2758 try self.genShiftBinOpMir(.shr, value_ty, tmp_reg, .{ .immediate = nearest_power_of_two * 8 });
2759 }
2760
2761 remainder -= nearest_power_of_two;
2762 next_offset -= nearest_power_of_two;
2763 }
2764 } else {
2765 _ = try self.addInst(.{
2766 .tag = .mov,
2767 .ops = Mir.Inst.Ops.encode(.{
2768 .reg1 = reg.to64(),
2769 .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),
2770 .flags = 0b10,
2771 }),
2772 .data = .{ .imm = 0 },
2773 });
2774 }
2744 },2775 },
2745 .got_load,2776 .got_load,
2746 .direct_load,2777 .direct_load,