aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2020-11-23 13:49:43 +0100
committerJakub Konka <kubkon@jakubkonka.com>2020-11-26 11:50:09 +0100
commit80b1041c21599f5d444373dd35eafe2dc68e3887 (patch)
treea0f28058948aee386476be3da7e02183b78208dc /src/codegen.zig
parent59fe3d447d8cdd5dda34d7a77459c2c6761857ea (diff)
downloadzig-80b1041c21599f5d444373dd35eafe2dc68e3887.tar.gz
zig-80b1041c21599f5d444373dd35eafe2dc68e3887.zip
stage2 macho: use RIP-relative for memory-set regs x86_64
Diffstat (limited to 'src/codegen.zig')
-rw-r--r--src/codegen.zig27
1 files changed, 23 insertions, 4 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index 48fda6f0d5..6cef7d8d0a 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -1683,11 +1683,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index * @sizeOf(u64);
switch (arch) {
.x86_64 => {
- // Here, we store the got address in %rax, and then call %rax
- // movabsq [addr], %rax
try self.genSetReg(inst.base.src, .rax, .{ .memory = got_addr });
// callq *%rax
- try self.code.ensureCapacity(self.code.items.len + 2);
self.code.appendSliceAssumeCapacity(&[2]u8{ 0xff, 0xd0 });
},
.aarch64 => {
@@ -2766,7 +2763,29 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
self.code.appendSliceAssumeCapacity(&[_]u8{ 0x8B, R });
},
.memory => |x| {
- if (x <= math.maxInt(u32)) {
+ if (self.bin_file.cast(link.File.MachO)) |macho_file| {
+ // For MachO, the binary, with the exception of object files, has to be a PIE.
+ // Therefore, we cannot load an absolute address.
+ assert(x > math.maxInt(u32)); // 32bit direct addressing is not supported by MachO.
+ // The plan here is to use RIP-relative addressing, but leaving the actual displacement
+ // information empty (0-padded) and fixing it up later in the linker.
+ try self.mod_fn.owner_decl.link.macho.addRipPosition(self.bin_file.allocator, .{
+ .address = x,
+ .start = self.code.items.len,
+ .len = 7,
+ });
+ try self.code.ensureCapacity(self.code.items.len + 9);
+ // leaq %r, [rip + disp]
+ self.code.appendSliceAssumeCapacity(&[_]u8{
+ 0x48,
+ 0x8d,
+ 0x05 | (@as(u8, reg.id() & 0b111) << 3), // R
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ });
+ } else if (x <= math.maxInt(u32)) {
// Moving from memory to a register is a variant of `8B /r`.
// Since we're using 64-bit moves, we require a REX.
// This variant also requires a SIB, as it would otherwise be RIP-relative.