aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-02-07 16:02:43 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-02-07 20:13:29 +0100
commitbbd7969c87e03c9312eeafd9940ef8287a3ad689 (patch)
tree293c89a8c76f0df820dc86a79102bc8ebbb58d7a /src
parent0a7801236cf3601ff20b3c1c16cd27c1d089157e (diff)
downloadzig-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.zig43
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 });