authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-16 22:41:19+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-17 00:26:00+01:00
logc1fb14c51ef9b329c0e4dfedfe6ae591bd972a88
treef092d4e300477e99e59b18a2ea19b2e2292ea33b
parent94474ec7c783b94face643f448426bcb91adfc93

x64: handle storing non-pow2 values to stack from register

This actually requires storing and shifting mechanics so that we don't accidentally clobber anything else on the stack.

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

src/arch/x86_64/CodeGen.zig+48-9
...@@ -3715,15 +3715,54 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro...@@ -3715,15 +3715,54 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
3715 if (stack_offset > math.maxInt(i32)) {3715 if (stack_offset > math.maxInt(i32)) {
3716 return self.fail("stack offset too large", .{});3716 return self.fail("stack offset too large", .{});
3717 }3717 }
3718 _ = try self.addInst(.{3718
3719 .tag = .mov,3719 const is_power_of_two = (abi_size % 2) == 0;
3720 .ops = (Mir.Ops{3720 if (!is_power_of_two) {
3721 .reg1 = .rbp,3721 self.register_manager.freezeRegs(&.{reg});
3722 .reg2 = registerAlias(reg, @intCast(u32, abi_size)),3722 defer self.register_manager.unfreezeRegs(&.{reg});
3723 .flags = 0b10,3723
3724 }).encode(),3724 const tmp_reg = try self.copyToTmpRegister(ty, mcv);
3725 .data = .{ .imm = @bitCast(u32, -stack_offset) },3725
3726 });3726 var next_offset = stack_offset;
3727 var remainder = abi_size;
3728 while (remainder > 0) {
3729 const closest_power_of_two = @as(u6, 1) << @intCast(u3, math.log2(remainder));
3730
3731 _ = try self.addInst(.{
3732 .tag = .mov,
3733 .ops = (Mir.Ops{
3734 .reg1 = .rbp,
3735 .reg2 = registerAlias(tmp_reg, closest_power_of_two),
3736 .flags = 0b10,
3737 }).encode(),
3738 .data = .{ .imm = @bitCast(u32, -next_offset) },
3739 });
3740
3741 if (closest_power_of_two > 1) {
3742 _ = try self.addInst(.{
3743 .tag = .shr,
3744 .ops = (Mir.Ops{
3745 .reg1 = tmp_reg,
3746 .flags = 0b10,
3747 }).encode(),
3748 .data = .{ .imm = closest_power_of_two * 8 },
3749 });
3750 }
3751
3752 remainder -= closest_power_of_two;
3753 next_offset -= closest_power_of_two;
3754 }
3755 } else {
3756 _ = try self.addInst(.{
3757 .tag = .mov,
3758 .ops = (Mir.Ops{
3759 .reg1 = .rbp,
3760 .reg2 = registerAlias(reg, @intCast(u32, abi_size)),
3761 .flags = 0b10,
3762 }).encode(),
3763 .data = .{ .imm = @bitCast(u32, -stack_offset) },
3764 });
3765 }
3727 },3766 },
3728 .memory,3767 .memory,
3729 .embedded_in_code,3768 .embedded_in_code,