aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-02-16 21:40:08 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-02-16 21:40:08 +0100
commit94474ec7c783b94face643f448426bcb91adfc93 (patch)
treefb70f73bc21f6130e55edd742b4e7df57bd96cea /src
parent09d468b237e58dd70cfa0a4311efab5ddabc9f95 (diff)
downloadzig-94474ec7c783b94face643f448426bcb91adfc93.tar.gz
zig-94474ec7c783b94face643f448426bcb91adfc93.zip
x64: refactor use of inline memcpy
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86_64/CodeGen.zig297
1 files changed, 84 insertions, 213 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index b593b3ea64..e63edf0eac 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -1782,36 +1782,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
}
- self.register_manager.freezeRegs(&.{ .rax, .rcx });
- defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx });
-
- const regs = try self.register_manager.allocRegs(3, .{ null, null, null });
- const addr_reg = regs[0];
- const count_reg = regs[1];
- const tmp_reg = regs[2];
-
- _ = try self.addInst(.{
- .tag = .mov,
- .ops = (Mir.Ops{
- .reg1 = registerAlias(addr_reg, @divExact(reg.size(), 8)),
- .reg2 = reg,
- }).encode(),
- .data = undefined,
- });
-
- try self.register_manager.getReg(.rax, null);
- try self.register_manager.getReg(.rcx, null);
-
- // TODO allow for abi size to be u64
- try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) });
-
- return self.genInlineMemcpy(
- -off,
- .rbp,
- registerAlias(addr_reg, @divExact(reg.size(), 8)),
- count_reg.to64(),
- tmp_reg.to8(),
- );
+ try self.genInlineMemcpy(off, .rbp, elem_ty, ptr);
},
else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
}
@@ -3626,62 +3597,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
}
- self.register_manager.freezeRegs(&.{ .rax, .rcx });
- defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx });
-
- const addr_reg: Register = blk: {
- switch (mcv) {
- .got_load,
- .direct_load,
- => |sym_index| {
- const flags: u2 = switch (mcv) {
- .got_load => 0b00,
- .direct_load => 0b01,
- else => unreachable,
- };
- const addr_reg = try self.register_manager.allocReg(null);
- _ = try self.addInst(.{
- .tag = .lea_pie,
- .ops = (Mir.Ops{
- .reg1 = addr_reg.to64(),
- .flags = flags,
- }).encode(),
- .data = .{
- .load_reloc = .{
- .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
- .sym_index = sym_index,
- },
- },
- });
- break :blk addr_reg;
- },
- .memory => |addr| {
- const addr_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = addr });
- break :blk addr_reg;
- },
- else => unreachable,
- }
- };
-
- 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];
-
- try self.register_manager.getReg(.rax, null);
- try self.register_manager.getReg(.rcx, null);
-
- // TODO allow for abi_size to be u64
- try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) });
- try self.genInlineMemcpy(
- -stack_offset,
- .rsp,
- addr_reg.to64(),
- count_reg.to64(),
- tmp_reg.to8(),
- );
+ try self.genInlineMemcpy(stack_offset, .rsp, ty, mcv);
},
.register => |reg| {
_ = try self.addInst(.{
@@ -3698,41 +3614,13 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
const reg = try self.copyToTmpRegister(ty, mcv);
return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
},
- .stack_offset => |off| {
+ .stack_offset => {
if (abi_size <= 8) {
const reg = try self.copyToTmpRegister(ty, mcv);
return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
}
- self.register_manager.freezeRegs(&.{ .rax, .rcx });
- defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx });
-
- const regs = try self.register_manager.allocRegs(3, .{ null, null, null });
- const addr_reg = regs[0];
- const count_reg = regs[1];
- const tmp_reg = regs[2];
-
- try self.register_manager.getReg(.rax, null);
- try self.register_manager.getReg(.rcx, null);
-
- _ = try self.addInst(.{
- .tag = .lea,
- .ops = (Mir.Ops{
- .reg1 = addr_reg.to64(),
- .reg2 = .rbp,
- }).encode(),
- .data = .{ .imm = @bitCast(u32, -off) },
- });
-
- // TODO allow for abi_size to be u64
- try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) });
- try self.genInlineMemcpy(
- -stack_offset,
- .rsp,
- addr_reg.to64(),
- count_reg.to64(),
- tmp_reg.to8(),
- );
+ try self.genInlineMemcpy(stack_offset, .rsp, ty, mcv);
},
else => return self.fail("TODO implement args on stack for {}", .{mcv}),
}
@@ -3847,65 +3735,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
}
- 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;
- },
- .direct_load,
- .got_load,
- => |sym_index| {
- const flags: u2 = switch (mcv) {
- .got_load => 0b00,
- .direct_load => 0b01,
- else => unreachable,
- };
- const addr_reg = try self.register_manager.allocReg(null);
- _ = try self.addInst(.{
- .tag = .lea_pie,
- .ops = (Mir.Ops{
- .reg1 = addr_reg.to64(),
- .flags = flags,
- }).encode(),
- .data = .{
- .load_reloc = .{
- .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
- .sym_index = sym_index,
- },
- },
- });
- break :blk addr_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,
- .rbp,
- addr_reg.to64(),
- count_reg.to64(),
- tmp_reg.to8(),
- );
+ try self.genInlineMemcpy(stack_offset, .rbp, ty, mcv);
},
.ptr_stack_offset => {
const reg = try self.copyToTmpRegister(ty, mcv);
@@ -3922,48 +3752,89 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
}
- self.register_manager.freezeRegs(&.{ .rax, .rcx, .rbp });
- defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx, .rbp });
+ try self.genInlineMemcpy(stack_offset, .rbp, ty, mcv);
+ },
+ }
+}
- const regs = try self.register_manager.allocRegs(3, .{ null, null, null });
- const addr_reg = regs[0];
- const count_reg = regs[1];
- const tmp_reg = regs[2];
+fn genInlineMemcpy(self: *Self, stack_offset: i32, stack_reg: Register, ty: Type, val: MCValue) InnerError!void {
+ const abi_size = ty.abiSize(self.target.*);
- try self.register_manager.getReg(.rax, null);
- try self.register_manager.getReg(.rcx, null);
+ try self.register_manager.getReg(.rax, null);
+ try self.register_manager.getReg(.rcx, null);
- _ = try self.addInst(.{
- .tag = .lea,
- .ops = (Mir.Ops{
- .reg1 = addr_reg.to64(),
- .reg2 = .rbp,
- }).encode(),
- .data = .{ .imm = @bitCast(u32, -off) },
- });
+ self.register_manager.freezeRegs(&.{ .rax, .rcx, .rbp });
+ defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx, .rbp });
+
+ const addr_reg: Register = blk: {
+ switch (val) {
+ .memory => |addr| {
+ const reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = addr });
+ break :blk reg;
+ },
+ .direct_load,
+ .got_load,
+ => |sym_index| {
+ const flags: u2 = switch (val) {
+ .got_load => 0b00,
+ .direct_load => 0b01,
+ else => unreachable,
+ };
+ const addr_reg = (try self.register_manager.allocReg(null)).to64();
+ _ = try self.addInst(.{
+ .tag = .lea_pie,
+ .ops = (Mir.Ops{
+ .reg1 = addr_reg,
+ .flags = flags,
+ }).encode(),
+ .data = .{
+ .load_reloc = .{
+ .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
+ .sym_index = sym_index,
+ },
+ },
+ });
+ break :blk addr_reg;
+ },
+ .stack_offset => |off| {
+ const addr_reg = (try self.register_manager.allocReg(null)).to64();
+ _ = try self.addInst(.{
+ .tag = .lea,
+ .ops = (Mir.Ops{
+ .reg1 = addr_reg,
+ .reg2 = .rbp,
+ }).encode(),
+ .data = .{ .imm = @bitCast(u32, -off) },
+ });
+ break :blk addr_reg;
+ },
+ .register => |reg| {
+ const addr_reg = try self.register_manager.allocReg(null);
+ _ = try self.addInst(.{
+ .tag = .mov,
+ .ops = (Mir.Ops{
+ .reg1 = registerAlias(addr_reg, @divExact(reg.size(), 8)),
+ .reg2 = reg,
+ }).encode(),
+ .data = undefined,
+ });
+ break :blk addr_reg.to64();
+ },
+ else => {
+ return self.fail("TODO implement memcpy for setting stack from {}", .{val});
+ },
+ }
+ };
- // TODO allow for abi_size to be u64
- try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) });
+ self.register_manager.freezeRegs(&.{addr_reg});
+ defer self.register_manager.unfreezeRegs(&.{addr_reg});
- return self.genInlineMemcpy(
- -stack_offset,
- .rbp,
- addr_reg.to64(),
- count_reg.to64(),
- tmp_reg.to8(),
- );
- },
- }
-}
+ const regs = try self.register_manager.allocRegs(2, .{ null, null });
+ const count_reg = regs[0].to64();
+ const tmp_reg = regs[1].to8();
+
+ try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) });
-fn genInlineMemcpy(
- self: *Self,
- stack_offset: i32,
- stack_reg: Register,
- addr_reg: Register,
- count_reg: Register,
- tmp_reg: Register,
-) InnerError!void {
// mov rcx, 0
_ = try self.addInst(.{
.tag = .mov,
@@ -4016,7 +3887,7 @@ fn genInlineMemcpy(
.reg1 = stack_reg,
.reg2 = tmp_reg.to8(),
}).encode(),
- .data = .{ .imm = @bitCast(u32, stack_offset) },
+ .data = .{ .imm = @bitCast(u32, -stack_offset) },
});
// add rcx, 1
@@ -4959,8 +4830,8 @@ fn parseRegName(name: []const u8) ?Register {
return std.meta.stringToEnum(Register, name);
}
+/// Returns register wide enough to hold at least `size_bytes`.
fn registerAlias(reg: Register, size_bytes: u32) Register {
- // For x86_64 we have to pick a smaller register alias depending on abi size.
if (size_bytes == 0) {
unreachable; // should be comptime known
} else if (size_bytes <= 1) {