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-27 10:19:54+01:00
log02b67d7e19455cfc069daf9e665fe28d4d01a9f2
treed1aef670795636e89a52a22eb0d2fa0bc2dfb808
parente4d1bd610534c9a6ed01a17481bc4b6dc5b7d8dc
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(+), 290 deletions(-)

src/codegen.zig+12-74
...@@ -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,68 +797,14 @@ fn lowerNavRef(...@@ -805,68 +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}
821806
822pub fn genNavRef(807 try w.splatByteAll(0, ptr_width_bytes); // overwritten by relocation
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)});
831
832 const is_threadlocal = nav.resolved.?.@"threadlocal" and zcu.comp.config.any_non_single_threaded;
833 if (lf.cast(.elf)) |elf_file| {
834 const zo = elf_file.zigObjectPtr().?;
835 if (nav.getExtern(ip)) |e| {
836 const sym_index = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip));
837 switch (e.linkage) {
838 .strong => {},
839 .weak => zo.symbol(sym_index).flags.weak = true,
840 }
841 if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true;
842 return @fromBackingInt(@intCast(sym_index));
843 } else {
844 const sym_index = try zo.getOrCreateMetadataForNav(zcu, nav_index);
845 if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true;
846 return @fromBackingInt(@intCast(sym_index));
847 }
848 } else if (lf.cast(.elf2)) |elf| {
849 return elf.navSymbol(nav_index);
850 } else if (lf.cast(.macho)) |macho_file| {
851 const zo = macho_file.getZigObject().?;
852 if (nav.getExtern(ip)) |e| {
853 const sym_index = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip));
854 switch (e.linkage) {
855 .strong => {},
856 .weak => zo.symbols.items[sym_index].flags.weak = true,
857 }
858 if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true;
859 return @fromBackingInt(@intCast(sym_index));
860 } else {
861 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index);
862 if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true;
863 return @fromBackingInt(@intCast(sym_index));
864 }
865 } else if (lf.cast(.coff)) |coff| {
866 return @fromBackingInt(@intCast(@backingInt(try coff.navSymbol(zcu, nav_index))));
867 } else {
868 std.debug.panic("TODO genNavRef for '{t}'", .{lf.tag});
869 }
870}808}
871809
872/// deprecated legacy type810/// deprecated legacy type
...@@ -908,13 +846,13 @@ pub fn genTypedValue(...@@ -908,13 +846,13 @@ pub fn genTypedValue(
908 .none => .none,846 .none => .none,
909 .undef => .undef,847 .undef => .undef,
910 .immediate => |imm| .{ .immediate = imm },848 .immediate => |imm| .{ .immediate = imm },
911 .lea_nav => |nav| .{ .lea_symbol = try genNavRef(lf, pt, nav) },849 .lea_nav => |nav| .{ .lea_symbol = try lf.navSymbol(nav) },
912 .load_uav => |uav| .{ .load_symbol = try lf.lowerUav(850 .load_uav => |uav| .{ .load_symbol = try lf.uavSymbol(
913 pt,851 pt,
914 uav.val,852 uav.val,
915 Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),853 Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),
916 ) },854 ) },
917 .lea_uav => |uav| .{ .lea_symbol = try lf.lowerUav(855 .lea_uav => |uav| .{ .lea_symbol = try lf.uavSymbol(
918 pt,856 pt,
919 uav.val,857 uav.val,
920 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
...@@ -4324,36 +4324,7 @@ pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.Fil...@@ -4324,36 +4324,7 @@ pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.Fil
4324 const s: Symbol.Id = .local(nmi.symbol(elf));4324 const s: Symbol.Id = .local(nmi.symbol(elf));
4325 return s.toTypeErased();4325 return s.toTypeErased();
4326}4326}
4327pub fn uavSymbol(4327pub fn relocSymAddr(elf: *Elf, reloc_info: link.File.RelocInfo) link.Error!void {
4328 elf: *Elf,
4329 uav_val: InternPool.Index,
4330 uav_align: InternPool.Alignment,
4331) link.Error!link.File.SymbolId {
4332 const diags = &elf.base.comp.link_diags;
4333 const umi = elf.uavMapIndex(uav_val, uav_align) catch |err| switch (err) {
4334 else => |e| return e,
4335 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
4336 };
4337 const s: Symbol.Id = .local(umi.symbol(elf));
4338 return s.toTypeErased();
4339}
4340pub fn getNavVAddr(
4341 elf: *Elf,
4342 pt: Zcu.PerThread,
4343 nav: InternPool.Nav.Index,
4344 reloc_info: link.File.RelocInfo,
4345) link.Error!u64 {
4346 _ = pt;
4347 return elf.getVAddr(reloc_info, try elf.navSymbol(nav));
4348}
4349pub fn getUavVAddr(
4350 elf: *Elf,
4351 uav_val: InternPool.Index,
4352 reloc_info: link.File.RelocInfo,
4353) link.Error!u64 {
4354 return elf.getVAddr(reloc_info, try elf.uavSymbol(uav_val, .none));
4355}
4356pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target: link.File.SymbolId) link.Error!u64 {
4357 try elf.addReloc(4328 try elf.addReloc(
4358 switch (reloc_info.parent) {4329 switch (reloc_info.parent) {
4359 .none => unreachable,4330 .none => unreachable,
...@@ -4361,13 +4332,12 @@ pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target: link.File.Sy...@@ -4361,13 +4332,12 @@ pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target: link.File.Sy
4361 .debug_output => |debug_output| Node.toAtom(debug_output.dwarf2.info_writer.ni),4332 .debug_output => |debug_output| Node.toAtom(debug_output.dwarf2.info_writer.ni),
4362 },4333 },
4363 reloc_info.offset,4334 reloc_info.offset,
4364 target,4335 reloc_info.target,
4365 reloc_info.addend,4336 reloc_info.addend,
4366 .absAddr(elf),4337 .absAddr(elf),
4367 );4338 );
4368 return Symbol.Id.fromTypeErased(target).value(elf);
4369}4339}
4370pub fn lowerUav(4340pub fn uavSymbol(
4371 elf: *Elf,4341 elf: *Elf,
4372 pt: Zcu.PerThread,4342 pt: Zcu.PerThread,
4373 uav_val: InternPool.Index,4343 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 };