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
27322732 }
27332733 },
27342734 .register => |src_reg| {
2735 _ = try self.addInst(.{
2736 .tag = .mov,
2737 .ops = Mir.Inst.Ops.encode(.{
2738 .reg1 = reg.to64(),
2739 .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),
2740 .flags = 0b10,
2741 }),
2742 .data = .{ .imm = 0 },
2743 });
2735 const src_reg_lock = self.register_manager.lockReg(src_reg);
2736 defer if (src_reg_lock) |lock| self.register_manager.unlockReg(lock);
2737
2738 // TODO common code-path with genSetStack, refactor!
2739 if (!math.isPowerOfTwo(abi_size)) {
2740 const tmp_reg = try self.copyToTmpRegister(value_ty, value);
2741
2742 var next_offset: i32 = 0;
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 }
27442775 },
27452776 .got_load,
27462777 .direct_load,