zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit c1fb14c51ef9b329c0e4dfedfe6ae591bd972a88 (tree)
parent 94474ec7c783b94face643f448426bcb91adfc93
Author: Jakub Konka <kubkon@jakubkonka.com>
Date:   Wed, 16 Feb 2022 22:41:19 +0100

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.

Diffstat:
Msrc/arch/x86_64/CodeGen.zig | 57++++++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 48 insertions(+), 9 deletions(-)

diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig @@ -3715,15 +3715,54 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro if (stack_offset > math.maxInt(i32)) { return self.fail("stack offset too large", .{}); } - _ = try self.addInst(.{ - .tag = .mov, - .ops = (Mir.Ops{ - .reg1 = .rbp, - .reg2 = registerAlias(reg, @intCast(u32, abi_size)), - .flags = 0b10, - }).encode(), - .data = .{ .imm = @bitCast(u32, -stack_offset) }, - }); + + const is_power_of_two = (abi_size % 2) == 0; + if (!is_power_of_two) { + self.register_manager.freezeRegs(&.{reg}); + defer self.register_manager.unfreezeRegs(&.{reg}); + + const tmp_reg = try self.copyToTmpRegister(ty, mcv); + + var next_offset = stack_offset; + var remainder = abi_size; + while (remainder > 0) { + const closest_power_of_two = @as(u6, 1) << @intCast(u3, math.log2(remainder)); + + _ = try self.addInst(.{ + .tag = .mov, + .ops = (Mir.Ops{ + .reg1 = .rbp, + .reg2 = registerAlias(tmp_reg, closest_power_of_two), + .flags = 0b10, + }).encode(), + .data = .{ .imm = @bitCast(u32, -next_offset) }, + }); + + if (closest_power_of_two > 1) { + _ = try self.addInst(.{ + .tag = .shr, + .ops = (Mir.Ops{ + .reg1 = tmp_reg, + .flags = 0b10, + }).encode(), + .data = .{ .imm = closest_power_of_two * 8 }, + }); + } + + remainder -= closest_power_of_two; + next_offset -= closest_power_of_two; + } + } else { + _ = try self.addInst(.{ + .tag = .mov, + .ops = (Mir.Ops{ + .reg1 = .rbp, + .reg2 = registerAlias(reg, @intCast(u32, abi_size)), + .flags = 0b10, + }).encode(), + .data = .{ .imm = @bitCast(u32, -stack_offset) }, + }); + } }, .memory, .embedded_in_code,