Commit fc5a6e0e32

Jakub Konka <kubkon@jakubkonka.com>
2022-09-10 00:18:39
x86_64: combine got_load, direct_load and imports_load into linker_load MCV
1 parent d8f2103
Changed files (3)
src
src/arch/x86_64/CodeGen.zig
@@ -128,15 +128,11 @@ pub const MCValue = union(enum) {
     /// The value is in memory at a hard-coded address.
     /// If the type is a pointer, it means the pointer address is at this memory location.
     memory: u64,
-    /// The value is in memory referenced indirectly via a GOT entry index.
-    /// If the type is a pointer, it means the pointer is referenced indirectly via GOT.
-    /// When lowered, linker will emit a relocation of type X86_64_RELOC_GOT.
-    got_load: u32,
-    imports_load: u32,
-    /// The value is in memory referenced directly via symbol index.
-    /// If the type is a pointer, it means the pointer is referenced directly via symbol index.
-    /// When lowered, linker will emit a relocation of type X86_64_RELOC_SIGNED.
-    direct_load: u32,
+    /// The value is in memory but requires a linker relocation fixup:
+    /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
+    /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
+    /// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
+    linker_load: struct { @"type": enum { got, direct, import }, sym_index: u32 },
     /// The value is one of the stack variables.
     /// If the type is a pointer, it means the pointer address is in the stack at this offset.
     stack_offset: i32,
@@ -150,9 +146,7 @@ pub const MCValue = union(enum) {
             .memory,
             .stack_offset,
             .ptr_stack_offset,
-            .direct_load,
-            .got_load,
-            .imports_load,
+            .linker_load,
             => true,
             else => false,
         };
@@ -165,26 +159,6 @@ pub const MCValue = union(enum) {
         };
     }
 
-    fn isMutable(mcv: MCValue) bool {
-        return switch (mcv) {
-            .none => unreachable,
-            .unreach => unreachable,
-            .dead => unreachable,
-
-            .immediate,
-            .memory,
-            .eflags,
-            .ptr_stack_offset,
-            .undef,
-            .register_overflow,
-            => false,
-
-            .register,
-            .stack_offset,
-            => true,
-        };
-    }
-
     fn isRegister(mcv: MCValue) bool {
         return switch (mcv) {
             .register => true,
@@ -2307,11 +2281,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
                 .data = .{ .imm = @bitCast(u32, -off) },
             });
         },
-        .memory,
-        .got_load,
-        .direct_load,
-        .imports_load,
-        => {
+        .memory, .linker_load => {
             try self.loadMemPtrIntoRegister(addr_reg, Type.usize, array);
         },
         else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
@@ -2652,11 +2622,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
                 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
             }
         },
-        .memory,
-        .got_load,
-        .direct_load,
-        .imports_load,
-        => {
+        .memory, .linker_load => {
             const reg = try self.copyToTmpRegister(ptr_ty, ptr);
             try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
         },
@@ -2691,10 +2657,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
 
 fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue) InnerError!void {
     switch (ptr) {
-        .got_load,
-        .direct_load,
-        .imports_load,
-        => |sym_index| {
+        .linker_load => |load_struct| {
             const abi_size = @intCast(u32, ptr_ty.abiSize(self.target.*));
             const mod = self.bin_file.options.module.?;
             const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl);
@@ -2702,11 +2665,10 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
                 fn_owner_decl.link.macho.sym_index
             else
                 fn_owner_decl.link.coff.sym_index;
-            const flags: u2 = switch (ptr) {
-                .got_load => 0b00,
-                .direct_load => 0b01,
-                .imports_load => 0b10,
-                else => unreachable,
+            const flags: u2 = switch (load_struct.@"type") {
+                .got => 0b00,
+                .direct => 0b01,
+                .import => 0b10,
             };
             _ = try self.addInst(.{
                 .tag = .lea_pic,
@@ -2717,7 +2679,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
                 .data = .{
                     .relocation = .{
                         .atom_index = atom_index,
-                        .sym_index = sym_index,
+                        .sym_index = load_struct.sym_index,
                     },
                 },
             });
@@ -2801,9 +2763,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
                 .register => |src_reg| {
                     try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0);
                 },
-                .got_load,
-                .direct_load,
-                .imports_load,
+                .linker_load,
                 .memory,
                 .stack_offset,
                 => {
@@ -2822,11 +2782,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
                 },
             }
         },
-        .got_load,
-        .direct_load,
-        .imports_load,
-        .memory,
-        => {
+        .linker_load, .memory => {
             const value_lock: ?RegisterLock = switch (value) {
                 .register => |reg| self.register_manager.lockReg(reg),
                 else => null,
@@ -2894,11 +2850,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
                 .register => {
                     return self.store(new_ptr, value, ptr_ty, value_ty);
                 },
-                .got_load,
-                .direct_load,
-                .imports_load,
-                .memory,
-                => {
+                .linker_load, .memory => {
                     if (abi_size <= 8) {
                         const tmp_reg = try self.register_manager.allocReg(null, gp);
                         const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
@@ -3606,9 +3558,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
                     });
                 },
                 .memory,
-                .got_load,
-                .direct_load,
-                .imports_load,
+                .linker_load,
                 .eflags,
                 => {
                     assert(abi_size <= 8);
@@ -3694,10 +3644,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
                 => {
                     return self.fail("TODO implement x86 ADD/SUB/CMP source memory", .{});
                 },
-                .got_load,
-                .direct_load,
-                .imports_load,
-                => {
+                .linker_load => {
                     return self.fail("TODO implement x86 ADD/SUB/CMP source symbol at index in linker", .{});
                 },
                 .eflags => {
@@ -3708,10 +3655,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
         .memory => {
             return self.fail("TODO implement x86 ADD/SUB/CMP destination memory", .{});
         },
-        .got_load,
-        .direct_load,
-        .imports_load,
-        => {
+        .linker_load => {
             return self.fail("TODO implement x86 ADD/SUB/CMP destination symbol at index", .{});
         },
     }
@@ -3779,10 +3723,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
                 .memory => {
                     return self.fail("TODO implement x86 multiply source memory", .{});
                 },
-                .got_load,
-                .direct_load,
-                .imports_load,
-                => {
+                .linker_load => {
                     return self.fail("TODO implement x86 multiply source symbol at index in linker", .{});
                 },
                 .eflags => {
@@ -3826,10 +3767,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
                 .memory, .stack_offset => {
                     return self.fail("TODO implement x86 multiply source memory", .{});
                 },
-                .got_load,
-                .direct_load,
-                .imports_load,
-                => {
+                .linker_load => {
                     return self.fail("TODO implement x86 multiply source symbol at index in linker", .{});
                 },
                 .eflags => {
@@ -3840,10 +3778,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
         .memory => {
             return self.fail("TODO implement x86 multiply destination memory", .{});
         },
-        .got_load,
-        .direct_load,
-        .imports_load,
-        => {
+        .linker_load => {
             return self.fail("TODO implement x86 multiply destination symbol at index in linker", .{});
         },
     }
@@ -4006,9 +3941,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
             .unreach => unreachable,
             .dead => unreachable,
             .memory => unreachable,
-            .got_load => unreachable,
-            .direct_load => unreachable,
-            .imports_load => unreachable,
+            .linker_load => unreachable,
             .eflags => unreachable,
             .register_overflow => unreachable,
         }
@@ -4066,7 +3999,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
                 const func = func_payload.data;
                 const fn_owner_decl = mod.declPtr(func.owner_decl);
                 try self.genSetReg(Type.initTag(.usize), .rax, .{
-                    .got_load = fn_owner_decl.link.coff.sym_index,
+                    .linker_load = .{
+                        .@"type" = .got,
+                        .sym_index = fn_owner_decl.link.coff.sym_index,
+                    },
                 });
                 _ = try self.addInst(.{
                     .tag = .call,
@@ -4087,7 +4023,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
                 }
                 const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
                 try self.genSetReg(Type.initTag(.usize), .rax, .{
-                    .imports_load = sym_index,
+                    .linker_load = .{
+                        .@"type" = .import,
+                        .sym_index = sym_index,
+                    },
                 });
                 _ = try self.addInst(.{
                     .tag = .call,
@@ -4119,7 +4058,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
                 const func = func_payload.data;
                 const fn_owner_decl = mod.declPtr(func.owner_decl);
                 const sym_index = fn_owner_decl.link.macho.sym_index;
-                try self.genSetReg(Type.initTag(.usize), .rax, .{ .got_load = sym_index });
+                try self.genSetReg(Type.initTag(.usize), .rax, .{
+                    .linker_load = .{
+                        .@"type" = .got,
+                        .sym_index = sym_index,
+                    },
+                });
                 // callq *%rax
                 _ = try self.addInst(.{
                     .tag = .call,
@@ -4505,11 +4449,7 @@ fn genVarDbgInfo(
                     leb128.writeILEB128(dbg_info.writer(), -off) catch unreachable;
                     dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
                 },
-                .memory,
-                .got_load,
-                .direct_load,
-                .imports_load,
-                => {
+                .memory, .linker_load => {
                     const ptr_width = @intCast(u8, @divExact(self.target.cpu.arch.ptrBitWidth(), 8));
                     const is_ptr = switch (tag) {
                         .dbg_var_ptr => true,
@@ -4540,10 +4480,11 @@ fn genVarDbgInfo(
                         try dbg_info.append(DW.OP.deref);
                     }
                     switch (mcv) {
-                        .got_load,
-                        .direct_load,
-                        .imports_load,
-                        => |index| try dw.addExprlocReloc(index, offset, is_ptr),
+                        .linker_load => |load_struct| try dw.addExprlocReloc(
+                            load_struct.sym_index,
+                            offset,
+                            is_ptr,
+                        ),
                         else => {},
                     }
                 },
@@ -5587,11 +5528,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
                 else => return self.fail("TODO implement inputs on stack for {} with abi size > 8", .{mcv}),
             }
         },
-        .memory,
-        .direct_load,
-        .got_load,
-        .imports_load,
-        => {
+        .memory, .linker_load => {
             if (abi_size <= 8) {
                 const reg = try self.copyToTmpRegister(ty, mcv);
                 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
@@ -5835,11 +5772,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
                 },
             }
         },
-        .memory,
-        .got_load,
-        .direct_load,
-        .imports_load,
-        => {
+        .memory, .linker_load => {
             if (abi_size <= 8) {
                 const reg = try self.copyToTmpRegister(ty, mcv);
                 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts);
@@ -5959,11 +5892,7 @@ fn genInlineMemcpy(
     const tmp_reg = regs[4].to8();
 
     switch (dst_ptr) {
-        .memory,
-        .got_load,
-        .direct_load,
-        .imports_load,
-        => {
+        .memory, .linker_load => {
             try self.loadMemPtrIntoRegister(dst_addr_reg, Type.usize, dst_ptr);
         },
         .ptr_stack_offset, .stack_offset => |off| {
@@ -5992,11 +5921,7 @@ fn genInlineMemcpy(
     }
 
     switch (src_ptr) {
-        .memory,
-        .got_load,
-        .direct_load,
-        .imports_load,
-        => {
+        .memory, .linker_load => {
             try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_ptr);
         },
         .ptr_stack_offset, .stack_offset => |off| {
@@ -6120,11 +6045,7 @@ fn genInlineMemset(
     const index_reg = regs[1].to64();
 
     switch (dst_ptr) {
-        .memory,
-        .got_load,
-        .direct_load,
-        .imports_load,
-        => {
+        .memory, .linker_load => {
             try self.loadMemPtrIntoRegister(addr_reg, Type.usize, dst_ptr);
         },
         .ptr_stack_offset, .stack_offset => |off| {
@@ -6356,10 +6277,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
                 .data = undefined,
             });
         },
-        .direct_load,
-        .got_load,
-        .imports_load,
-        => {
+        .linker_load => {
             switch (ty.zigTypeTag()) {
                 .Float => {
                     const base_reg = try self.register_manager.allocReg(null, gp);
@@ -6753,11 +6671,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
     // TODO Is this the only condition for pointer dereference for memcpy?
     const src: MCValue = blk: {
         switch (src_ptr) {
-            .got_load,
-            .direct_load,
-            .imports_load,
-            .memory,
-            => {
+            .linker_load, .memory => {
                 const reg = try self.register_manager.allocReg(null, gp);
                 try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr);
                 _ = try self.addInst(.{
@@ -6997,10 +6911,16 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
         return MCValue{ .memory = got_addr };
     } else if (self.bin_file.cast(link.File.MachO)) |_| {
         assert(decl.link.macho.sym_index != 0);
-        return MCValue{ .got_load = decl.link.macho.sym_index };
+        return MCValue{ .linker_load = .{
+            .@"type" = .got,
+            .sym_index = decl.link.macho.sym_index,
+        } };
     } else if (self.bin_file.cast(link.File.Coff)) |_| {
         assert(decl.link.coff.sym_index != 0);
-        return MCValue{ .got_load = decl.link.coff.sym_index };
+        return MCValue{ .linker_load = .{
+            .@"type" = .got,
+            .sym_index = decl.link.coff.sym_index,
+        } };
     } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
         try p9.seeDecl(decl_index);
         const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
@@ -7019,9 +6939,15 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
         const vaddr = elf_file.local_symbols.items[local_sym_index].st_value;
         return MCValue{ .memory = vaddr };
     } else if (self.bin_file.cast(link.File.MachO)) |_| {
-        return MCValue{ .direct_load = local_sym_index };
+        return MCValue{ .linker_load = .{
+            .@"type" = .direct,
+            .sym_index = local_sym_index,
+        } };
     } else if (self.bin_file.cast(link.File.Coff)) |_| {
-        return MCValue{ .direct_load = local_sym_index };
+        return MCValue{ .linker_load = .{
+            .@"type" = .direct,
+            .sym_index = local_sym_index,
+        } };
     } else if (self.bin_file.cast(link.File.Plan9)) |_| {
         return self.fail("TODO lower unnamed const in Plan9", .{});
     } else {
src/arch/x86_64/Emit.zig
@@ -1021,7 +1021,7 @@ fn mirLeaPic(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
             .@"type" = switch (ops.flags) {
                 0b00 => .got,
                 0b01 => .direct,
-                0b10 => .imports,
+                0b10 => .import,
                 else => unreachable,
             },
             .target = switch (ops.flags) {
src/link/Coff.zig
@@ -127,7 +127,7 @@ pub const Reloc = struct {
     @"type": enum {
         got,
         direct,
-        imports,
+        import,
     },
     target: SymbolWithLoc,
     offset: u32,
@@ -141,7 +141,7 @@ pub const Reloc = struct {
         switch (self.@"type") {
             .got => return coff_file.getGotAtomForSymbol(self.target),
             .direct => return coff_file.getAtomForSymbol(self.target),
-            .imports => return coff_file.getImportAtomForSymbol(self.target),
+            .import => return coff_file.getImportAtomForSymbol(self.target),
         }
     }
 };