diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-02-07 16:02:43 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-02-07 20:13:29 +0100 |
| commit | bbd7969c87e03c9312eeafd9940ef8287a3ad689 (patch) | |
| tree | 293c89a8c76f0df820dc86a79102bc8ebbb58d7a /src | |
| parent | 0a7801236cf3601ff20b3c1c16cd27c1d089157e (diff) | |
| download | zig-bbd7969c87e03c9312eeafd9940ef8287a3ad689.tar.gz zig-bbd7969c87e03c9312eeafd9940ef8287a3ad689.zip | |
stage2,x64: implement genSetStack for memory operand
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index a60b8c78f0..7baf74c9c2 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -3487,6 +3487,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE } fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerError!void { + const abi_size = ty.abiSize(self.target.*); switch (mcv) { .dead => unreachable, .ptr_embedded_in_code => unreachable, @@ -3510,7 +3511,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro return self.genSetStack(ty, stack_offset, .{ .register = reg }); }, .immediate => |x_big| { - const abi_size = ty.abiSize(self.target.*); const adj_off = stack_offset + @intCast(i32, abi_size); if (adj_off > 128) { return self.fail("TODO implement set stack variable with large stack offset", .{}); @@ -3583,7 +3583,6 @@ 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", .{}); } - const abi_size = ty.abiSize(self.target.*); const adj_off = stack_offset + @intCast(i32, abi_size); _ = try self.addInst(.{ .tag = .mov, @@ -3600,11 +3599,46 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro .got_load, .direct_load, => { - if (ty.abiSize(self.target.*) <= 8) { + if (abi_size <= 8) { const reg = try self.copyToTmpRegister(ty, mcv); return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); } - return self.fail("TODO implement memcpy for setting stack from {}", .{mcv}); + + try self.register_manager.getReg(.rax, null); + try self.register_manager.getReg(.rcx, null); + + self.register_manager.freezeRegs(&.{ .rax, .rcx, .rbp }); + defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx, .rbp }); + + const addr_reg: Register = blk: { + switch (mcv) { + .memory => |addr| { + const reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = addr }); + break :blk reg; + }, + else => { + return self.fail("TODO implement memcpy for setting stack from {}", .{mcv}); + }, + } + }; + + self.register_manager.freezeRegs(&.{addr_reg}); + defer self.register_manager.unfreezeRegs(&.{addr_reg}); + + const regs = try self.register_manager.allocRegs(2, .{ null, null }); + const count_reg = regs[0]; + const tmp_reg = regs[1]; + + // TODO allow for abi_size to be u64 + try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) }); + + return self.genInlineMemcpy( + -(stack_offset + @intCast(i32, abi_size)), + .rbp, + addr_reg.to64(), + count_reg.to64(), + tmp_reg.to8(), + ); }, .ptr_stack_offset => { const reg = try self.copyToTmpRegister(ty, mcv); @@ -3616,7 +3650,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro return; } - const abi_size = ty.abiSize(self.target.*); if (abi_size <= 8) { const reg = try self.copyToTmpRegister(ty, mcv); return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
