Commit d2c4597eb5

Jakub Konka <kubkon@jakubkonka.com>
2023-11-02 13:21:25
x86_64: rewrite .got.zig movs to standard loads when emitting objects
1 parent ccb2afa
Changed files (2)
src
arch
src/arch/x86_64/Emit.zig
@@ -85,14 +85,15 @@ pub fn emitMir(emit: *Emit) Error!void {
                     @tagName(emit.lower.bin_file.tag),
                 }),
                 .linker_reloc => |data| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {
+                    const is_obj = emit.lower.bin_file.options.effectiveOutputMode() == .Obj;
                     const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
                     const sym_index = elf_file.zigObjectPtr().?.symbol(data.sym_index);
                     const sym = elf_file.symbol(sym_index);
-                    if (sym.flags.needs_zig_got and emit.lower.bin_file.options.effectiveOutputMode() != .Obj) {
+                    if (sym.flags.needs_zig_got and !is_obj) {
                         _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
                     }
                     if (emit.lower.bin_file.options.pic) {
-                        const r_type: u32 = if (sym.flags.needs_zig_got)
+                        const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj)
                             link.File.Elf.R_X86_64_ZIG_GOTPCREL
                         else if (sym.flags.needs_got)
                             std.elf.R_X86_64_GOTPCREL
@@ -104,7 +105,7 @@ pub fn emitMir(emit: *Emit) Error!void {
                             .r_addend = -4,
                         });
                     } else {
-                        const r_type: u32 = if (sym.flags.needs_zig_got)
+                        const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj)
                             link.File.Elf.R_X86_64_ZIG_GOT32
                         else if (sym.flags.needs_got)
                             std.elf.R_X86_64_GOT32
src/arch/x86_64/Lower.zig
@@ -319,6 +319,15 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate {
 }
 
 fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {
+    const needsZigGot = struct {
+        fn needsZigGot(sym: bits.Symbol, ctx: *link.File) bool {
+            const elf_file = ctx.cast(link.File.Elf).?;
+            const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
+            return elf_file.symbol(sym_index).flags.needs_zig_got;
+        }
+    }.needsZigGot;
+
+    const is_obj = lower.bin_file.options.effectiveOutputMode() == .Obj;
     var emit_prefix = prefix;
     var emit_mnemonic = mnemonic;
     var emit_ops_storage: [4]Operand = undefined;
@@ -334,7 +343,13 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
                     assert(mem_op.sib.scale_index.scale == 0);
                     _ = lower.reloc(.{ .linker_reloc = sym });
                     break :op if (lower.bin_file.options.pic) switch (mnemonic) {
-                        .mov, .lea => .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },
+                        .lea => {
+                            break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
+                        },
+                        .mov => {
+                            if (is_obj and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea;
+                            break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
+                        },
                         else => unreachable,
                     } else switch (mnemonic) {
                         .call => .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
@@ -344,9 +359,12 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
                             emit_mnemonic = .mov;
                             break :op .{ .imm = Immediate.s(0) };
                         },
-                        .mov => .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
-                            .base = .{ .reg = .ds },
-                        }) },
+                        .mov => {
+                            if (is_obj and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea;
+                            break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
+                                .base = .{ .reg = .ds },
+                            }) };
+                        },
                         else => unreachable,
                     };
                 },