authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-08-02 16:02:49+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-09-26 18:21:21+01:00
log4bd05848f28f413b415b29491ba0e2b3fa3c2dda
treef2270a6ea9a0eef4320f5ae1969fd8a4a02d9d65
parent0579c6a0254a00f5bb0d3cbef51ada1a1feaf500
signature Commit is signed but in an unrecognized format.

link: simplify public API

There was a bunch of legacy cruft in the linker's public API which was duplicating functionality, particularly regarding symbols and relocations. Move towards standardising on an interface based on `link.File.SymbolId`. The `navSymbol` and `uavSymbol` functions return `link.File.SymbolId`s representing a given NAV or UAV; then, with that `SymbolId`, codegen can call `relocSymAddr` to relocate that symbol's absolute address. The caller is responsible for writing placeholder bytes (probably zeroes) to be overwritten by that relocation. Previously the API told you an address to write in, but this was entirely redundant with the added relocation.

12 files changed, 122 insertions(+), 306 deletions(-)

src/codegen.zig+12-90
...@@ -754,23 +754,15 @@ fn lowerUavRef(...@@ -754,23 +754,15 @@ fn lowerUavRef(
754 }754 }
755755
756 const uav_align = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu);756 const uav_align = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu);
757 _ = try lf.lowerUav(pt, uav_val, uav_align);
758757
759 const vaddr = lf.getUavVAddr(uav_val, .{758 try lf.relocSymAddr(.{
760 .parent = reloc_parent,759 .parent = reloc_parent,
761 .offset = w.end,760 .offset = w.end,
761 .target = try lf.uavSymbol(pt, uav_val, uav_align),
762 .addend = @intCast(offset),762 .addend = @intCast(offset),
763 }) catch |err| switch (err) {763 });
764 error.OutOfMemory => |e| return e,764
765 else => |e| std.debug.panic("TODO rework lowerUav. internal error: {t}", .{e}),765 try w.splatByteAll(0, ptr_width_bytes); // overwritten by relocation
766 };
767 const endian = target.cpu.arch.endian();
768 switch (ptr_width_bytes) {
769 2 => try w.writeInt(u16, @intCast(vaddr), endian),
770 4 => try w.writeInt(u32, @intCast(vaddr), endian),
771 8 => try w.writeInt(u64, vaddr, endian),
772 else => unreachable,
773 }
774}766}
775767
776fn lowerNavRef(768fn lowerNavRef(
...@@ -805,84 +797,14 @@ fn lowerNavRef(...@@ -805,84 +797,14 @@ fn lowerNavRef(
805 else => {},797 else => {},
806 }798 }
807799
808 const vaddr = lf.getNavVAddr(pt, nav_index, .{800 try lf.relocSymAddr(.{
809 .parent = reloc_parent,801 .parent = reloc_parent,
810 .offset = w.end,802 .offset = w.end,
803 .target = try lf.navSymbol(nav_index),
811 .addend = @intCast(offset),804 .addend = @intCast(offset),
812 }) catch @panic("TODO rework getNavVAddr");805 });
813 const endian = target.cpu.arch.endian();
814 switch (ptr_width_bytes) {
815 2 => try w.writeInt(u16, @intCast(vaddr), endian),
816 4 => try w.writeInt(u32, @intCast(vaddr), endian),
817 8 => try w.writeInt(u64, vaddr, endian),
818 else => unreachable,
819 }
820}
821
822pub fn genNavRef(
823 lf: *link.File,
824 pt: Zcu.PerThread,
825 nav_index: InternPool.Nav.Index,
826) Error!link.File.SymbolId {
827 const zcu = pt.zcu;
828 const ip = &zcu.intern_pool;
829 const nav = ip.getNav(nav_index);
830 log.debug("genNavRef({f})", .{nav.fqn.fmt(ip)});
831806
832 const is_threadlocal = nav.resolved.?.@"threadlocal" and zcu.comp.config.any_non_single_threaded;807 try w.splatByteAll(0, ptr_width_bytes); // overwritten by relocation
833 const lib_name, const linkage = if (nav.getExtern(ip)) |e|
834 .{ e.lib_name, e.linkage }
835 else
836 .{ .none, .internal };
837 if (lf.cast(.elf)) |elf_file| {
838 const zo = elf_file.zigObjectPtr().?;
839 switch (linkage) {
840 .internal => {
841 const sym_index = try zo.getOrCreateMetadataForNav(zcu, nav_index);
842 if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true;
843 return @fromBackingInt(@intCast(sym_index));
844 },
845 .strong, .weak => {
846 const sym_index = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
847 switch (linkage) {
848 .internal => unreachable,
849 .strong => {},
850 .weak => zo.symbol(sym_index).flags.weak = true,
851 .link_once => unreachable,
852 }
853 if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true;
854 return @fromBackingInt(@intCast(sym_index));
855 },
856 .link_once => unreachable,
857 }
858 } else if (lf.cast(.elf2)) |elf| {
859 return elf.navSymbol(nav_index);
860 } else if (lf.cast(.macho)) |macho_file| {
861 const zo = macho_file.getZigObject().?;
862 switch (linkage) {
863 .internal => {
864 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index);
865 if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true;
866 return @fromBackingInt(@intCast(sym_index));
867 },
868 .strong, .weak => {
869 const sym_index = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
870 switch (linkage) {
871 .internal => unreachable,
872 .strong => {},
873 .weak => zo.symbols.items[sym_index].flags.weak = true,
874 .link_once => unreachable,
875 }
876 if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true;
877 return @fromBackingInt(@intCast(sym_index));
878 },
879 .link_once => unreachable,
880 }
881 } else if (lf.cast(.coff)) |coff| {
882 return @fromBackingInt(@intCast(@backingInt(try coff.navSymbol(zcu, nav_index))));
883 } else {
884 std.debug.panic("TODO genNavRef for '{t}'", .{lf.tag});
885 }
886}808}
887809
888/// deprecated legacy type810/// deprecated legacy type
...@@ -924,13 +846,13 @@ pub fn genTypedValue(...@@ -924,13 +846,13 @@ pub fn genTypedValue(
924 .none => .none,846 .none => .none,
925 .undef => .undef,847 .undef => .undef,
926 .immediate => |imm| .{ .immediate = imm },848 .immediate => |imm| .{ .immediate = imm },
927 .lea_nav => |nav| .{ .lea_symbol = try genNavRef(lf, pt, nav) },849 .lea_nav => |nav| .{ .lea_symbol = try lf.navSymbol(nav) },
928 .load_uav => |uav| .{ .load_symbol = try lf.lowerUav(850 .load_uav => |uav| .{ .load_symbol = try lf.uavSymbol(
929 pt,851 pt,
930 uav.val,852 uav.val,
931 Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),853 Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),
932 ) },854 ) },
933 .lea_uav => |uav| .{ .lea_symbol = try lf.lowerUav(855 .lea_uav => |uav| .{ .lea_symbol = try lf.uavSymbol(
934 pt,856 pt,
935 uav.val,857 uav.val,
936 Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),858 Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),
src/codegen/aarch64/Mir.zig+2-6
...@@ -93,11 +93,7 @@ pub fn emit(...@@ -93,11 +93,7 @@ pub fn emit(
93 lf,93 lf,
94 zcu,94 zcu,
95 atom_index,95 atom_index,
96 try @import("../../codegen.zig").genNavRef(96 try lf.navSymbol(nav_reloc.nav),
97 lf,
98 pt,
99 nav_reloc.nav,
100 ),
101 mir.body[nav_reloc.reloc.label],97 mir.body[nav_reloc.reloc.label],
102 body_end - Instruction.size * (1 + nav_reloc.reloc.label),98 body_end - Instruction.size * (1 + nav_reloc.reloc.label),
103 nav_reloc.reloc.addend,99 nav_reloc.reloc.addend,
...@@ -107,7 +103,7 @@ pub fn emit(...@@ -107,7 +103,7 @@ pub fn emit(
107 lf,103 lf,
108 zcu,104 zcu,
109 atom_index,105 atom_index,
110 try lf.lowerUav(106 try lf.uavSymbol(
111 pt,107 pt,
112 uav_reloc.uav.val,108 uav_reloc.uav.val,
113 ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu),109 ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu),
src/codegen/loongarch/Mir.zig+3-12
...@@ -83,11 +83,7 @@ pub fn emit(...@@ -83,11 +83,7 @@ pub fn emit(
83 lf,83 lf,
84 zcu,84 zcu,
85 atom_index,85 atom_index,
86 try @import("../../codegen.zig").genNavRef(86 try lf.navSymbol(nav_reloc.nav),
87 lf,
88 pt,
89 nav_reloc.nav,
90 ),
91 nav_reloc.reloc.type,87 nav_reloc.reloc.type,
92 body_end - @sizeOf(Instruction) * (1 + nav_reloc.reloc.label),88 body_end - @sizeOf(Instruction) * (1 + nav_reloc.reloc.label),
93 nav_reloc.reloc.addend,89 nav_reloc.reloc.addend,
...@@ -97,7 +93,7 @@ pub fn emit(...@@ -97,7 +93,7 @@ pub fn emit(
97 lf,93 lf,
98 zcu,94 zcu,
99 atom_index,95 atom_index,
100 try lf.lowerUav(96 try lf.uavSymbol(
101 pt,97 pt,
102 uav_reloc.uav.val,98 uav_reloc.uav.val,
103 ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu),99 ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu),
...@@ -142,16 +138,11 @@ pub fn emit(...@@ -142,16 +138,11 @@ pub fn emit(
142 ) catch |err|138 ) catch |err|
143 return zcu.codegenFail(func.owner_nav, "emit reloc failed: {t}", .{err});139 return zcu.codegenFail(func.owner_nav, "emit reloc failed: {t}", .{err});
144140
145 const func_nav = try @import("../../codegen.zig").genNavRef(
146 lf,
147 pt,
148 func.owner_nav,
149 );
150 for (mir.internal_relocs) |internal_reloc| emitReloc(141 for (mir.internal_relocs) |internal_reloc| emitReloc(
151 lf,142 lf,
152 zcu,143 zcu,
153 atom_index,144 atom_index,
154 func_nav,145 try lf.navSymbol(func.owner_nav),
155 internal_reloc.reloc.type,146 internal_reloc.reloc.type,
156 body_end - @sizeOf(Instruction) * (1 + internal_reloc.reloc.label),147 body_end - @sizeOf(Instruction) * (1 + internal_reloc.reloc.label),
157 @sizeOf(Instruction) * (@as(i64, @intCast(mir.prologue.len + mir.body.len - internal_reloc.target))),148 @sizeOf(Instruction) * (@as(i64, @intCast(mir.prologue.len + mir.body.len - internal_reloc.target))),
src/codegen/riscv64/CodeGen.zig+1-1
...@@ -8160,7 +8160,7 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {...@@ -8160,7 +8160,7 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {
8160 const lf = func.bin_file;8160 const lf = func.bin_file;
81618161
8162 const result: codegen.MCValue = if (val.isUndef(pt.zcu))8162 const result: codegen.MCValue = if (val.isUndef(pt.zcu))
8163 .{ .load_symbol = try lf.lowerUav(pt, val.toIntern(), .none) }8163 .{ .load_symbol = try lf.uavSymbol(pt, val.toIntern(), .none) }
8164 else8164 else
8165 try codegen.genTypedValue(lf, pt, val, func.target);8165 try codegen.genTypedValue(lf, pt, val, func.target);
8166 const mcv: MCValue = switch (result) {8166 const mcv: MCValue = switch (result) {
src/codegen/x86_64/Emit.zig+4-8
...@@ -100,11 +100,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -100,11 +100,7 @@ pub fn emitMir(emit: *Emit) Error!void {
100 .inst => |inst| .{ .inst = inst },100 .inst => |inst| .{ .inst = inst },
101 .table => .table,101 .table => .table,
102 .nav => |nav| {102 .nav => |nav| {
103 const symbol_id = try codegen.genNavRef(103 const symbol_id = try emit.bin_file.navSymbol(nav);
104 emit.bin_file,
105 emit.pt,
106 nav,
107 );
108 const target_symbol: RelocInfo.Target.Symbol = if (ip.getNav(nav).getExtern(ip)) |@"extern"| .{104 const target_symbol: RelocInfo.Target.Symbol = if (ip.getNav(nav).getExtern(ip)) |@"extern"| .{
109 .symbol = symbol_id,105 .symbol = symbol_id,
110 .is_extern = switch (@"extern".visibility) {106 .is_extern = switch (@"extern".visibility) {
...@@ -124,7 +120,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -124,7 +120,7 @@ pub fn emitMir(emit: *Emit) Error!void {
124 }120 }
125 },121 },
126 .uav => |uav| .{ .symbol = .{122 .uav => |uav| .{ .symbol = .{
127 .symbol = try emit.bin_file.lowerUav(123 .symbol = try emit.bin_file.uavSymbol(
128 emit.pt,124 emit.pt,
129 uav.val,125 uav.val,
130 Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),126 Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),
...@@ -597,12 +593,12 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -597,12 +593,12 @@ pub fn emitMir(emit: *Emit) Error!void {
597 .nav => |nav| @unionInit(593 .nav => |nav| @unionInit(
598 DwarfLoc,594 DwarfLoc,
599 addr_loc,595 addr_loc,
600 try codegen.genNavRef(emit.bin_file, emit.pt, nav),596 try emit.bin_file.navSymbol(nav),
601 ),597 ),
602 .uav => |uav| @unionInit(598 .uav => |uav| @unionInit(
603 DwarfLoc,599 DwarfLoc,
604 addr_loc,600 addr_loc,
605 try emit.bin_file.lowerUav(601 try emit.bin_file.uavSymbol(
606 emit.pt,602 emit.pt,
607 uav.val,603 uav.val,
608 Type.fromInterned(uav.orig_ty)604 Type.fromInterned(uav.orig_ty)
src/link.zig+10-18
...@@ -1039,6 +1039,7 @@ pub const File = struct {...@@ -1039,6 +1039,7 @@ pub const File = struct {
1039 pub const RelocInfo = struct {1039 pub const RelocInfo = struct {
1040 parent: Parent,1040 parent: Parent,
1041 offset: u64,1041 offset: u64,
1042 target: SymbolId,
1042 addend: u32,1043 addend: u32,
10431044
1044 pub const Parent = union(enum) {1045 pub const Parent = union(enum) {
...@@ -1048,16 +1049,9 @@ pub const File = struct {...@@ -1048,16 +1049,9 @@ pub const File = struct {
1048 };1049 };
1049 };1050 };
10501051
1051 /// Get allocated `Nav`'s address in virtual memory.
1052 /// The linker is passed information about the containing atom, `parent_atom_index`, and offset within it's
1053 /// memory buffer, `offset`, so that it can make a note of potential relocation sites, should the
1054 /// `Nav`'s address was not yet resolved, or the containing atom gets moved in virtual memory.
1055 /// May be called before or after updateFunc/updateNav therefore it is up to the linker to allocate
1056 /// the block/atom.
1057 /// Never called when LLVM is codegenning the ZCU.1052 /// Never called when LLVM is codegenning the ZCU.
1058 pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) Error!u64 {1053 pub fn relocSymAddr(base: *File, reloc_info: RelocInfo) Error!void {
1059 assert(pt.zcu.llvm_object == null);1054 assert(base.comp.zcu.?.llvm_object == null);
1060
1061 switch (base.tag) {1055 switch (base.tag) {
1062 .lld => unreachable,1056 .lld => unreachable,
1063 .c => unreachable,1057 .c => unreachable,
...@@ -1067,20 +1061,19 @@ pub const File = struct {...@@ -1067,20 +1061,19 @@ pub const File = struct {
1067 .spork8 => unreachable,1061 .spork8 => unreachable,
1068 inline else => |tag| {1062 inline else => |tag| {
1069 dev.check(tag.devFeature());1063 dev.check(tag.devFeature());
1070 return @as(*tag.Type(), @fieldParentPtr("base", base)).getNavVAddr(pt, nav_index, reloc_info);1064 return @as(*tag.Type(), @fieldParentPtr("base", base)).relocSymAddr(reloc_info);
1071 },1065 },
1072 }1066 }
1073 }1067 }
10741068
1075 /// Never called when LLVM is codegenning the ZCU.1069 /// Never called when LLVM is codegenning the ZCU.
1076 pub fn lowerUav(1070 pub fn uavSymbol(
1077 base: *File,1071 base: *File,
1078 pt: Zcu.PerThread,1072 pt: Zcu.PerThread,
1079 decl_val: InternPool.Index,1073 uav_val: InternPool.Index,
1080 decl_align: InternPool.Alignment,1074 uav_align: InternPool.Alignment,
1081 ) Error!SymbolId {1075 ) Error!SymbolId {
1082 assert(pt.zcu.llvm_object == null);1076 assert(pt.zcu.llvm_object == null);
1083
1084 switch (base.tag) {1077 switch (base.tag) {
1085 .lld => unreachable,1078 .lld => unreachable,
1086 .c => unreachable,1079 .c => unreachable,
...@@ -1090,15 +1083,14 @@ pub const File = struct {...@@ -1090,15 +1083,14 @@ pub const File = struct {
1090 .spork8 => unreachable,1083 .spork8 => unreachable,
1091 inline else => |tag| {1084 inline else => |tag| {
1092 dev.check(tag.devFeature());1085 dev.check(tag.devFeature());
1093 return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerUav(pt, decl_val, decl_align);1086 return @as(*tag.Type(), @fieldParentPtr("base", base)).uavSymbol(pt, uav_val, uav_align);
1094 },1087 },
1095 }1088 }
1096 }1089 }
10971090
1098 /// Never called when LLVM is codegenning the ZCU.1091 /// Never called when LLVM is codegenning the ZCU.
1099 pub fn getUavVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) Error!u64 {1092 pub fn navSymbol(base: *File, nav: InternPool.Nav.Index) Error!SymbolId {
1100 assert(base.comp.zcu.?.llvm_object == null);1093 assert(base.comp.zcu.?.llvm_object == null);
1101
1102 switch (base.tag) {1094 switch (base.tag) {
1103 .lld => unreachable,1095 .lld => unreachable,
1104 .c => unreachable,1096 .c => unreachable,
...@@ -1108,7 +1100,7 @@ pub const File = struct {...@@ -1108,7 +1100,7 @@ pub const File = struct {
1108 .spork8 => unreachable,1100 .spork8 => unreachable,
1109 inline else => |tag| {1101 inline else => |tag| {
1110 dev.check(tag.devFeature());1102 dev.check(tag.devFeature());
1111 return @as(*tag.Type(), @fieldParentPtr("base", base)).getUavVAddr(decl_val, reloc_info);1103 return @as(*tag.Type(), @fieldParentPtr("base", base)).navSymbol(nav);
1112 },1104 },
1113 }1105 }
1114 }1106 }
src/link/Coff.zig+13-34
...@@ -2935,18 +2935,19 @@ fn navMapIndex(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.Na...@@ -2935,18 +2935,19 @@ fn navMapIndex(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.Na
2935 if (!sym_gop.found_existing) sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();2935 if (!sym_gop.found_existing) sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();
2936 return @fromBackingInt(@intCast(sym_gop.index));2936 return @fromBackingInt(@intCast(sym_gop.index));
2937}2937}
2938pub fn navSymbol(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index {2938pub fn navSymbol(coff: *Coff, nav_index: InternPool.Nav.Index) link.Error!link.File.SymbolId {
2939 const zcu = coff.base.comp.zcu.?;
2939 const ip = &zcu.intern_pool;2940 const ip = &zcu.intern_pool;
2940 const nav = ip.getNav(nav_index);2941 const nav = ip.getNav(nav_index);
2941 if (nav.getExtern(ip)) |@"extern"| return coff.globalSymbol(.{2942 if (nav.getExtern(ip)) |@"extern"| return @bitCast(try coff.globalSymbol(.{
2942 .name = @"extern".name.toSlice(ip),2943 .name = @"extern".name.toSlice(ip),
2943 .lib_name = @"extern".lib_name.toSlice(ip),2944 .lib_name = @"extern".lib_name.toSlice(ip),
2944 // TODO: Threadlocal as well?2945 // TODO: Threadlocal as well?
2945 .type = if (ip.isFunctionType(nav.resolved.?.type)) .code else .data,2946 .type = if (ip.isFunctionType(nav.resolved.?.type)) .code else .data,
2946 .dll_storage_class = if (@"extern".is_dll_import) .dllimport else .default,2947 .dll_storage_class = if (@"extern".is_dll_import) .dllimport else .default,
2947 });2948 }));
2948 const nmi = try coff.navMapIndex(zcu, nav_index);2949 const nmi = try coff.navMapIndex(zcu, nav_index);
2949 return nmi.symbol(coff);2950 return @bitCast(nmi.symbol(coff));
2950}2951}
29512952
2952fn uavMapIndex(coff: *Coff, uav_val: InternPool.Index) !Node.UavMapIndex {2953fn uavMapIndex(coff: *Coff, uav_val: InternPool.Index) !Node.UavMapIndex {
...@@ -2956,10 +2957,6 @@ fn uavMapIndex(coff: *Coff, uav_val: InternPool.Index) !Node.UavMapIndex {...@@ -2956,10 +2957,6 @@ fn uavMapIndex(coff: *Coff, uav_val: InternPool.Index) !Node.UavMapIndex {
2956 if (!sym_gop.found_existing) sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();2957 if (!sym_gop.found_existing) sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();
2957 return @fromBackingInt(@intCast(sym_gop.index));2958 return @fromBackingInt(@intCast(sym_gop.index));
2958}2959}
2959pub fn uavSymbol(coff: *Coff, uav_val: InternPool.Index) !Symbol.Index {
2960 const umi = try coff.uavMapIndex(uav_val);
2961 return umi.symbol(coff);
2962}
29632960
2964pub fn lazySymbol(coff: *Coff, lazy: link.File.LazySymbol) !Symbol.Index {2961pub fn lazySymbol(coff: *Coff, lazy: link.File.LazySymbol) !Symbol.Index {
2965 const gpa = coff.base.comp.gpa;2962 const gpa = coff.base.comp.gpa;
...@@ -2972,24 +2969,8 @@ pub fn lazySymbol(coff: *Coff, lazy: link.File.LazySymbol) !Symbol.Index {...@@ -2972,24 +2969,8 @@ pub fn lazySymbol(coff: *Coff, lazy: link.File.LazySymbol) !Symbol.Index {
2972 return sym_gop.value_ptr.*;2969 return sym_gop.value_ptr.*;
2973}2970}
29742971
2975pub fn getNavVAddr(2972pub fn relocSymAddr(coff: *Coff, reloc_info: link.File.RelocInfo) link.Error!void {
2976 coff: *Coff,2973 const target_si: Symbol.Index = @bitCast(reloc_info.target);
2977 pt: Zcu.PerThread,
2978 nav: InternPool.Nav.Index,
2979 reloc_info: link.File.RelocInfo,
2980) link.Error!u64 {
2981 return coff.getVAddr(reloc_info, try coff.navSymbol(pt.zcu, nav));
2982}
2983
2984pub fn getUavVAddr(
2985 coff: *Coff,
2986 uav: InternPool.Index,
2987 reloc_info: link.File.RelocInfo,
2988) link.Error!u64 {
2989 return coff.getVAddr(reloc_info, try coff.uavSymbol(uav));
2990}
2991
2992pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol.Index) link.Error!u64 {
2993 try coff.addReloc(2974 try coff.addReloc(
2994 @fromBackingInt(@intCast(@backingInt(reloc_info.parent.atom_index))),2975 @fromBackingInt(@intCast(@backingInt(reloc_info.parent.atom_index))),
2995 reloc_info.offset,2976 reloc_info.offset,
...@@ -3001,10 +2982,6 @@ pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol....@@ -3001,10 +2982,6 @@ pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol.
3001 .I386 => .{ .I386 = .DIR32 },2982 .I386 => .{ .I386 = .DIR32 },
3002 },2983 },
3003 );2984 );
3004
3005 var vaddr: u64 = target_si.get(coff).rva;
3006 if (coff.isImage()) vaddr += coff.optionalHeaderField(.image_base);
3007 return vaddr;
3008}2985}
30092986
3010/// Caller guarantees there is capacity for one member and two nodes2987/// Caller guarantees there is capacity for one member and two nodes
...@@ -5580,13 +5557,15 @@ pub fn updateContainerType(...@@ -5580,13 +5557,15 @@ pub fn updateContainerType(
5580 };5557 };
5581}5558}
55825559
5583pub fn lowerUav(5560pub fn uavSymbol(
5584 coff: *Coff,5561 coff: *Coff,
5585 pt: Zcu.PerThread,5562 pt: Zcu.PerThread,
5586 uav_val: InternPool.Index,5563 uav_val: InternPool.Index,
5587 uav_align: InternPool.Alignment,5564 uav_align: InternPool.Alignment,
5588) link.Error!link.File.SymbolId {5565) link.Error!link.File.SymbolId {
5589 const zcu = pt.zcu;5566 _ = pt;
5567
5568 const zcu = coff.base.comp.zcu.?;
5590 const gpa = zcu.gpa;5569 const gpa = zcu.gpa;
55915570
5592 try coff.pending_uavs.ensureUnusedCapacity(gpa, 1);5571 try coff.pending_uavs.ensureUnusedCapacity(gpa, 1);
...@@ -7471,8 +7450,8 @@ fn updateExportInner(...@@ -7471,8 +7450,8 @@ fn updateExportInner(
74717450
7472 try coff.symbols.ensureUnusedCapacity(gpa, 1);7451 try coff.symbols.ensureUnusedCapacity(gpa, 1);
7473 const exported_si: Symbol.Index = switch (exp.exported) {7452 const exported_si: Symbol.Index = switch (exp.exported) {
7474 .nav => |nav| try coff.navSymbol(zcu, nav),7453 .nav => |nav| @bitCast(try coff.navSymbol(nav)),
7475 .uav => |uav| @fromBackingInt(@intCast(@backingInt(try coff.lowerUav(7454 .uav => |uav| @fromBackingInt(@intCast(@backingInt(try coff.uavSymbol(
7476 pt,7455 pt,
7477 uav,7456 uav,
7478 Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu),7457 Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu),
src/link/Elf.zig+8-8
...@@ -463,21 +463,21 @@ pub fn deinit(self: *Elf) void {...@@ -463,21 +463,21 @@ pub fn deinit(self: *Elf) void {
463 self.dump_argv_list.deinit(gpa);463 self.dump_argv_list.deinit(gpa);
464}464}
465465
466pub fn getNavVAddr(self: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {466pub fn navSymbol(self: *Elf, nav: InternPool.Nav.Index) link.Error!link.File.SymbolId {
467 return self.zigObjectPtr().?.getNavVAddr(self, pt, nav_index, reloc_info);467 return self.zigObjectPtr().?.navSymbol(self, nav);
468}468}
469469
470pub fn lowerUav(470pub fn relocSymAddr(self: *Elf, reloc_info: link.File.RelocInfo) !void {
471 return self.zigObjectPtr().?.relocSymAddr(self, reloc_info);
472}
473
474pub fn uavSymbol(
471 self: *Elf,475 self: *Elf,
472 pt: Zcu.PerThread,476 pt: Zcu.PerThread,
473 uav: InternPool.Index,477 uav: InternPool.Index,
474 explicit_alignment: InternPool.Alignment,478 explicit_alignment: InternPool.Alignment,
475) !link.File.SymbolId {479) !link.File.SymbolId {
476 return self.zigObjectPtr().?.lowerUav(self, pt, uav, explicit_alignment);480 return self.zigObjectPtr().?.uavSymbol(self, pt, uav, explicit_alignment);
477}
478
479pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
480 return self.zigObjectPtr().?.getUavVAddr(self, uav, reloc_info);
481}481}
482482
483/// Returns end pos of collision, if any.483/// Returns end pos of collision, if any.
src/link/Elf/ZigObject.zig+30-42
...@@ -917,53 +917,42 @@ pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8...@@ -917,53 +917,42 @@ pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8
917 return code;917 return code;
918}918}
919919
920pub fn getNavVAddr(920pub fn navSymbol(
921 self: *ZigObject,921 zo: *ZigObject,
922 elf_file: *Elf,922 elf_file: *Elf,
923 pt: Zcu.PerThread,
924 nav_index: InternPool.Nav.Index,923 nav_index: InternPool.Nav.Index,
925 reloc_info: link.File.RelocInfo,924) link.Error!link.File.SymbolId {
926) !u64 {925 const zcu = elf_file.base.comp.zcu.?;
927 const zcu = pt.zcu;
928 const ip = &zcu.intern_pool;926 const ip = &zcu.intern_pool;
929 const nav = ip.getNav(nav_index);927 const nav = ip.getNav(nav_index);
930 log.debug("getNavVAddr {f}({d})", .{ nav.fqn.fmt(ip), nav_index });928 if (nav.getExtern(ip)) |@"extern"| {
931 const this_sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol(929 const sym_index = try zo.getGlobalSymbol(
932 elf_file,930 elf_file,
933 nav.name.toSlice(ip),931 nav.name.toSlice(ip),
934 @"extern".lib_name.toSlice(ip),932 @"extern".lib_name.toSlice(ip),
935 ) else try self.getOrCreateMetadataForNav(zcu, nav_index);933 );
936 const this_sym = self.symbol(this_sym_index);934 if (@"extern".linkage == .weak) {
937 const vaddr = this_sym.address(.{}, elf_file);935 zo.symbol(sym_index).flags.weak = true;
938 switch (reloc_info.parent) {936 }
939 .none => unreachable,937 if (nav.resolved.?.@"threadlocal") {
940 .atom_index => |atom_index| {938 zo.symbol(sym_index).flags.is_tls = true;
941 const parent_atom = self.symbol(@backingInt(atom_index)).atom(elf_file).?;939 }
942 const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch);940 return @fromBackingInt(sym_index);
943 try parent_atom.addReloc(elf_file.base.comp.gpa, .{941 } else {
944 .r_offset = reloc_info.offset,942 const sym_index = try zo.getOrCreateMetadataForNav(zcu, nav_index);
945 .r_info = (@as(u64, @intCast(this_sym_index)) << 32) | r_type,943 if (nav.resolved.?.@"threadlocal") {
946 .r_addend = reloc_info.addend,944 zo.symbol(sym_index).flags.is_tls = true;
947 }, self);945 }
948 },946 return @fromBackingInt(sym_index);
949 .debug_output => |debug_output| try debug_output.dwarf.infoExternalReloc(.{
950 .source_off = @intCast(reloc_info.offset),
951 .target_sym = @fromBackingInt(@intCast(this_sym_index)),
952 .target_off = reloc_info.addend,
953 }),
954 }947 }
955 return @intCast(vaddr);
956}948}
957949
958pub fn getUavVAddr(950pub fn relocSymAddr(
959 self: *ZigObject,951 self: *ZigObject,
960 elf_file: *Elf,952 elf_file: *Elf,
961 uav: InternPool.Index,
962 reloc_info: link.File.RelocInfo,953 reloc_info: link.File.RelocInfo,
963) !u64 {954) !void {
964 const sym_index = self.uavs.get(uav).?.symbol_index;955 const this_sym_index = @backingInt(reloc_info.target);
965 const sym = self.symbol(sym_index);
966 const vaddr = sym.address(.{}, elf_file);
967 switch (reloc_info.parent) {956 switch (reloc_info.parent) {
968 .none => unreachable,957 .none => unreachable,
969 .atom_index => |atom_index| {958 .atom_index => |atom_index| {
...@@ -971,20 +960,19 @@ pub fn getUavVAddr(...@@ -971,20 +960,19 @@ pub fn getUavVAddr(
971 const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch);960 const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch);
972 try parent_atom.addReloc(elf_file.base.comp.gpa, .{961 try parent_atom.addReloc(elf_file.base.comp.gpa, .{
973 .r_offset = reloc_info.offset,962 .r_offset = reloc_info.offset,
974 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,963 .r_info = (@as(u64, @intCast(this_sym_index)) << 32) | r_type,
975 .r_addend = reloc_info.addend,964 .r_addend = reloc_info.addend,
976 }, self);965 }, self);
977 },966 },
978 .debug_output => |debug_output| try debug_output.dwarf.infoExternalReloc(.{967 .debug_output => |debug_output| try debug_output.dwarf.infoExternalReloc(.{
979 .source_off = @intCast(reloc_info.offset),968 .source_off = @intCast(reloc_info.offset),
980 .target_sym = @fromBackingInt(@intCast(sym_index)),969 .target_sym = @fromBackingInt(@intCast(this_sym_index)),
981 .target_off = reloc_info.addend,970 .target_off = reloc_info.addend,
982 }),971 }),
983 }972 }
984 return @intCast(vaddr);
985}973}
986974
987pub fn lowerUav(975pub fn uavSymbol(
988 self: *ZigObject,976 self: *ZigObject,
989 elf_file: *Elf,977 elf_file: *Elf,
990 pt: Zcu.PerThread,978 pt: Zcu.PerThread,
...@@ -1889,7 +1877,7 @@ pub fn updateExports(...@@ -1889,7 +1877,7 @@ pub fn updateExports(
1889 break :blk self.navs.getPtr(nav).?;1877 break :blk self.navs.getPtr(nav).?;
1890 },1878 },
1891 .uav => |uav| self.uavs.getPtr(uav) orelse blk: {1879 .uav => |uav| self.uavs.getPtr(uav) orelse blk: {
1892 _ = try self.lowerUav(elf_file, pt, uav, .none);1880 _ = try self.uavSymbol(elf_file, pt, uav, .none);
1893 break :blk self.uavs.getPtr(uav).?;1881 break :blk self.uavs.getPtr(uav).?;
1894 },1882 },
1895 };1883 };
src/link/Elf2.zig+3-33
...@@ -4326,36 +4326,7 @@ pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.Fil...@@ -4326,36 +4326,7 @@ pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.Fil
4326 const s: Symbol.Id = .local(nmi.symbol(elf));4326 const s: Symbol.Id = .local(nmi.symbol(elf));
4327 return s.toTypeErased();4327 return s.toTypeErased();
4328}4328}
4329pub fn uavSymbol(4329pub fn relocSymAddr(elf: *Elf, reloc_info: link.File.RelocInfo) link.Error!void {
4330 elf: *Elf,
4331 uav_val: InternPool.Index,
4332 uav_align: InternPool.Alignment,
4333) link.Error!link.File.SymbolId {
4334 const diags = &elf.base.comp.link_diags;
4335 const umi = elf.uavMapIndex(uav_val, uav_align) catch |err| switch (err) {
4336 else => |e| return e,
4337 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
4338 };
4339 const s: Symbol.Id = .local(umi.symbol(elf));
4340 return s.toTypeErased();
4341}
4342pub fn getNavVAddr(
4343 elf: *Elf,
4344 pt: Zcu.PerThread,
4345 nav: InternPool.Nav.Index,
4346 reloc_info: link.File.RelocInfo,
4347) link.Error!u64 {
4348 _ = pt;
4349 return elf.getVAddr(reloc_info, try elf.navSymbol(nav));
4350}
4351pub fn getUavVAddr(
4352 elf: *Elf,
4353 uav_val: InternPool.Index,
4354 reloc_info: link.File.RelocInfo,
4355) link.Error!u64 {
4356 return elf.getVAddr(reloc_info, try elf.uavSymbol(uav_val, .none));
4357}
4358pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target: link.File.SymbolId) link.Error!u64 {
4359 try elf.addReloc(4330 try elf.addReloc(
4360 switch (reloc_info.parent) {4331 switch (reloc_info.parent) {
4361 .none => unreachable,4332 .none => unreachable,
...@@ -4363,13 +4334,12 @@ pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target: link.File.Sy...@@ -4363,13 +4334,12 @@ pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target: link.File.Sy
4363 .debug_output => |debug_output| Node.toAtom(debug_output.dwarf2.info_writer.ni),4334 .debug_output => |debug_output| Node.toAtom(debug_output.dwarf2.info_writer.ni),
4364 },4335 },
4365 reloc_info.offset,4336 reloc_info.offset,
4366 target,4337 reloc_info.target,
4367 reloc_info.addend,4338 reloc_info.addend,
4368 .absAddr(elf),4339 .absAddr(elf),
4369 );4340 );
4370 return Symbol.Id.fromTypeErased(target).value(elf);
4371}4341}
4372pub fn lowerUav(4342pub fn uavSymbol(
4373 elf: *Elf,4343 elf: *Elf,
4374 pt: Zcu.PerThread,4344 pt: Zcu.PerThread,
4375 uav_val: InternPool.Index,4345 uav_val: InternPool.Index,
src/link/MachO.zig+8-8
...@@ -3124,21 +3124,21 @@ pub fn freeNav(self: *MachO, nav: InternPool.Nav.Index) void {...@@ -3124,21 +3124,21 @@ pub fn freeNav(self: *MachO, nav: InternPool.Nav.Index) void {
3124 return self.getZigObject().?.freeNav(nav);3124 return self.getZigObject().?.freeNav(nav);
3125}3125}
31263126
3127pub fn getNavVAddr(self: *MachO, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {3127pub fn navSymbol(self: *MachO, nav: InternPool.Nav.Index) link.Error!link.File.SymbolId {
3128 return self.getZigObject().?.getNavVAddr(self, pt, nav_index, reloc_info);3128 return self.getZigObject().?.navSymbol(self, nav);
3129}3129}
31303130
3131pub fn lowerUav(3131pub fn relocSymAddr(self: *MachO, reloc_info: link.File.RelocInfo) link.Error!void {
3132 return self.getZigObject().?.relocSymAddr(self, reloc_info);
3133}
3134
3135pub fn uavSymbol(
3132 self: *MachO,3136 self: *MachO,
3133 pt: Zcu.PerThread,3137 pt: Zcu.PerThread,
3134 uav: InternPool.Index,3138 uav: InternPool.Index,
3135 explicit_alignment: InternPool.Alignment,3139 explicit_alignment: InternPool.Alignment,
3136) !link.File.SymbolId {3140) !link.File.SymbolId {
3137 return self.getZigObject().?.lowerUav(self, pt, uav, explicit_alignment);3141 return self.getZigObject().?.uavSymbol(self, pt, uav, explicit_alignment);
3138}
3139
3140pub fn getUavVAddr(self: *MachO, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
3141 return self.getZigObject().?.getUavVAddr(self, uav, reloc_info);
3142}3142}
31433143
3144pub fn getGlobalSymbol(self: *MachO, name: []const u8, lib_name: ?[]const u8) !u32 {3144pub fn getGlobalSymbol(self: *MachO, name: []const u8, lib_name: ?[]const u8) !u32 {
src/link/MachO/ZigObject.zig+28-46
...@@ -611,60 +611,43 @@ pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.E...@@ -611,60 +611,43 @@ pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.E
611 assert(!self.debug_strtab_dirty);611 assert(!self.debug_strtab_dirty);
612}612}
613613
614pub fn getNavVAddr(614pub fn navSymbol(
615 self: *ZigObject,615 zo: *ZigObject,
616 macho_file: *MachO,616 macho_file: *MachO,
617 pt: Zcu.PerThread,
618 nav_index: InternPool.Nav.Index,617 nav_index: InternPool.Nav.Index,
619 reloc_info: link.File.RelocInfo,618) link.Error!link.File.SymbolId {
620) !u64 {619 const zcu = macho_file.base.comp.zcu.?;
621 const zcu = pt.zcu;
622 const ip = &zcu.intern_pool;620 const ip = &zcu.intern_pool;
623 const nav = ip.getNav(nav_index);621 const nav = ip.getNav(nav_index);
624 log.debug("getNavVAddr {f}({d})", .{ nav.fqn.fmt(ip), nav_index });622 if (nav.getExtern(ip)) |@"extern"| {
625 const sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol(623 const sym_index = try zo.getGlobalSymbol(
626 macho_file,624 macho_file,
627 nav.name.toSlice(ip),625 nav.name.toSlice(ip),
628 @"extern".lib_name.toSlice(ip),626 @"extern".lib_name.toSlice(ip),
629 ) else try self.getOrCreateMetadataForNav(macho_file, nav_index);627 );
630 const sym = self.symbols.items[sym_index];628 if (@"extern".linkage == .weak) {
631 const vaddr = sym.getAddress(.{}, macho_file);629 zo.symbols.items[sym_index].flags.weak = true;
632 switch (reloc_info.parent) {630 }
633 .none => unreachable,631 if (nav.resolved.?.@"threadlocal") {
634 .atom_index => |atom_index| {632 zo.symbols.items[sym_index].flags.tlv = true;
635 const parent_atom = self.symbols.items[@backingInt(atom_index)].getAtom(macho_file).?;633 }
636 try parent_atom.addReloc(macho_file, .{634 return @fromBackingInt(sym_index);
637 .tag = .@"extern",635 } else {
638 .offset = @intCast(reloc_info.offset),636 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index);
639 .target = sym_index,637 if (nav.resolved.?.@"threadlocal") {
640 .addend = reloc_info.addend,638 zo.symbols.items[sym_index].flags.tlv = true;
641 .type = .unsigned,639 }
642 .meta = .{640 return @fromBackingInt(sym_index);
643 .pcrel = false,
644 .has_subtractor = false,
645 .length = 3,
646 .symbolnum = @intCast(sym.nlist_idx),
647 },
648 });
649 },
650 .debug_output => |debug_output| try debug_output.dwarf.infoExternalReloc(.{
651 .source_off = @intCast(reloc_info.offset),
652 .target_sym = @fromBackingInt(@intCast(sym_index)),
653 .target_off = reloc_info.addend,
654 }),
655 }641 }
656 return vaddr;
657}642}
658643
659pub fn getUavVAddr(644pub fn relocSymAddr(
660 self: *ZigObject,645 self: *ZigObject,
661 macho_file: *MachO,646 macho_file: *MachO,
662 uav: InternPool.Index,
663 reloc_info: link.File.RelocInfo,647 reloc_info: link.File.RelocInfo,
664) !u64 {648) !void {
665 const sym_index = self.uavs.get(uav).?.symbol_index;649 const sym_index = @backingInt(reloc_info.target);
666 const sym = self.symbols.items[sym_index];650 const sym = self.symbols.items[sym_index];
667 const vaddr = sym.getAddress(.{}, macho_file);
668 switch (reloc_info.parent) {651 switch (reloc_info.parent) {
669 .none => unreachable,652 .none => unreachable,
670 .atom_index => |atom_index| {653 .atom_index => |atom_index| {
...@@ -689,10 +672,9 @@ pub fn getUavVAddr(...@@ -689,10 +672,9 @@ pub fn getUavVAddr(
689 .target_off = reloc_info.addend,672 .target_off = reloc_info.addend,
690 }),673 }),
691 }674 }
692 return vaddr;
693}675}
694676
695pub fn lowerUav(677pub fn uavSymbol(
696 self: *ZigObject,678 self: *ZigObject,
697 macho_file: *MachO,679 macho_file: *MachO,
698 pt: Zcu.PerThread,680 pt: Zcu.PerThread,
...@@ -1281,7 +1263,7 @@ pub fn updateExports(...@@ -1281,7 +1263,7 @@ pub fn updateExports(
1281 break :blk self.navs.getPtr(nav).?;1263 break :blk self.navs.getPtr(nav).?;
1282 },1264 },
1283 .uav => |uav| self.uavs.getPtr(uav) orelse blk: {1265 .uav => |uav| self.uavs.getPtr(uav) orelse blk: {
1284 _ = try self.lowerUav(macho_file, pt, uav, .none);1266 _ = try self.uavSymbol(macho_file, pt, uav, .none);
1285 break :blk self.uavs.getPtr(uav).?;1267 break :blk self.uavs.getPtr(uav).?;
1286 },1268 },
1287 };1269 };