authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-05 01:55:37-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-23 00:27:17-04:00
log537d7b74274c31ea4240870724ffd41e0e5de8dd
treef0b18a14be815b44df3c69752efdf0fd4c326b16
parentbd50917c0d86cc45c46cb10868e5e4da6d87c58f

Coff: rework symbol table generation

Instead of popping from the end of a map of pending symbols, use the map as the storage and flush symbols in order. This simplifies the weak external flow, and keeps the symbol table in a more intuitive order. Also, .sti is no longer in Value, which means that it won't collide with .node_offset if an imported symbol is later exported.

2 files changed, 71 insertions(+), 85 deletions(-)

src/link/Coff.zig+66-80
...@@ -615,7 +615,8 @@ pub const SymbolTable = struct {...@@ -615,7 +615,8 @@ pub const SymbolTable = struct {
615 ni: MappedFile.Node.Index,615 ni: MappedFile.Node.Index,
616 strings_ni: MappedFile.Node.Index,616 strings_ni: MappedFile.Node.Index,
617 strings: std.AutoArrayHashMapUnmanaged(String, StringIndex),617 strings: std.AutoArrayHashMapUnmanaged(String, StringIndex),
618 pending: std.AutoArrayHashMapUnmanaged(Symbol.Index, void),618 symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, SymbolTable.Index),
619 pending_symbol_index: u32,
619620
620 // Resizing the symbol table node has the result of accumulating padding621 // Resizing the symbol table node has the result of accumulating padding
621 // between the last symbol in the symbol table node and the start of the622 // between the last symbol in the symbol table node and the start of the
...@@ -653,8 +654,8 @@ pub const SymbolTable = struct {...@@ -653,8 +654,8 @@ pub const SymbolTable = struct {
653 none,654 none,
654 _,655 _,
655656
656 pub fn wrap(i: ?u32) Index {657 pub fn wrap(i: u32) Index {
657 return @enumFromInt((i orelse return .none) + 1);658 return @enumFromInt(i + 1);
658 }659 }
659660
660 pub fn unwrap(sti: Index) ?u32 {661 pub fn unwrap(sti: Index) ?u32 {
...@@ -904,13 +905,14 @@ pub const Symbol = struct {...@@ -904,13 +905,14 @@ pub const Symbol = struct {
904 };905 };
905906
906 const ValueTag = enum(u2) {907 const ValueTag = enum(u2) {
908 none,
907 node_offset,909 node_offset,
908 weak_alias_si,910 weak_alias_si,
909 weak_alias_name,911 weak_alias_name,
910 sti,
911 };912 };
912913
913 pub const Value = union(ValueTag) {914 pub const Value = union(ValueTag) {
915 none,
914 /// The offset of the symbol within its node. Used with symbols that916 /// The offset of the symbol within its node. Used with symbols that
915 /// don't create their own nodes: .input_section, .import_address_table917 /// don't create their own nodes: .input_section, .import_address_table
916 /// Images only.918 /// Images only.
...@@ -924,9 +926,6 @@ pub const Symbol = struct {...@@ -924,9 +926,6 @@ pub const Symbol = struct {
924 /// be generated and resolved if this symbol is not resolved.926 /// be generated and resolved if this symbol is not resolved.
925 /// Globals only, images only.927 /// Globals only, images only.
926 weak_alias_name: String,928 weak_alias_name: String,
927 /// Index of this symbol in the symbol table
928 /// Only used when outputting objects
929 sti: SymbolTable.Index,
930 };929 };
931930
932 const ExtraTag = enum(u2) {931 const ExtraTag = enum(u2) {
...@@ -1041,6 +1040,11 @@ pub const Symbol = struct {...@@ -1041,6 +1040,11 @@ pub const Symbol = struct {
1041 return ni;1040 return ni;
1042 }1041 }
10431042
1043 pub fn sti(si: Symbol.Index, coff: *Coff) SymbolTable.Index {
1044 assert(!coff.isImage());
1045 return coff.symbol_table.symbols.get(si) orelse .none;
1046 }
1047
1044 pub fn next(si: Symbol.Index) Symbol.Index {1048 pub fn next(si: Symbol.Index) Symbol.Index {
1045 return @enumFromInt(@intFromEnum(si) + 1);1049 return @enumFromInt(@intFromEnum(si) + 1);
1046 }1050 }
...@@ -1070,7 +1074,7 @@ pub const Symbol = struct {...@@ -1070,7 +1074,7 @@ pub const Symbol = struct {
10701074
1071 pub fn flushSymbolTableIndex(si: Symbol.Index, coff: *Coff) void {1075 pub fn flushSymbolTableIndex(si: Symbol.Index, coff: *Coff) void {
1072 const sym = si.get(coff);1076 const sym = si.get(coff);
1073 const index = sym.value.sti.unwrap() orelse return;1077 const index = si.sti(coff).unwrap().?;
1074 var ri = sym.target_relocs;1078 var ri = sym.target_relocs;
1075 while (ri != .none) {1079 while (ri != .none) {
1076 const reloc = ri.get(coff);1080 const reloc = ri.get(coff);
...@@ -1583,7 +1587,8 @@ fn create(...@@ -1583,7 +1587,8 @@ fn create(
1583 .ni = .none,1587 .ni = .none,
1584 .strings_ni = .none,1588 .strings_ni = .none,
1585 .strings = .empty,1589 .strings = .empty,
1586 .pending = .empty,1590 .symbols = .empty,
1591 .pending_symbol_index = 0,
1587 .pending_shrink = false,1592 .pending_shrink = false,
1588 },1593 },
1589 .inputs = .empty,1594 .inputs = .empty,
...@@ -1667,7 +1672,7 @@ pub fn deinit(coff: *Coff) void {...@@ -1667,7 +1672,7 @@ pub fn deinit(coff: *Coff) void {
1667 coff.import_table.iat_symbol_indices.deinit(gpa);1672 coff.import_table.iat_symbol_indices.deinit(gpa);
1668 coff.export_table.entries.deinit(gpa);1673 coff.export_table.entries.deinit(gpa);
1669 coff.symbol_table.strings.deinit(gpa);1674 coff.symbol_table.strings.deinit(gpa);
1670 coff.symbol_table.pending.deinit(gpa);1675 coff.symbol_table.symbols.deinit(gpa);
1671 coff.inputs.deinit(gpa);1676 coff.inputs.deinit(gpa);
1672 coff.input_archives.deinit(gpa);1677 coff.input_archives.deinit(gpa);
1673 coff.input_archive_members.deinit(gpa);1678 coff.input_archive_members.deinit(gpa);
...@@ -2280,7 +2285,10 @@ pub fn startProgress(coff: *Coff, prog_node: std.Progress.Node) void {...@@ -2280,7 +2285,10 @@ pub fn startProgress(coff: *Coff, prog_node: std.Progress.Node) void {
2280 });2285 });
2281 if (!isImage(coff)) {2286 if (!isImage(coff)) {
2282 prog_node.increaseEstimatedTotalItems(2);2287 prog_node.increaseEstimatedTotalItems(2);
2283 coff.symbol_prog_node = prog_node.start("Symbols", coff.symbol_table.pending.count());2288 coff.symbol_prog_node = prog_node.start(
2289 "Symbols",
2290 coff.symbol_table.symbols.count() - coff.symbol_table.pending_symbol_index,
2291 );
2284 coff.member_prog_node = prog_node.start("Members", coff.pending_members.count());2292 coff.member_prog_node = prog_node.start("Members", coff.pending_members.count());
2285 }2293 }
2286 coff.input_prog_node = prog_node.start(2294 coff.input_prog_node = prog_node.start(
...@@ -2550,8 +2558,7 @@ pub fn symbolTableEntryPtr(coff: *Coff, sti: SymbolTable.Index) ?*align(2) std.c...@@ -2550,8 +2558,7 @@ pub fn symbolTableEntryPtr(coff: *Coff, sti: SymbolTable.Index) ?*align(2) std.c
2550 return null;2558 return null;
2551}2559}
25522560
2553pub fn symbolTableSectionAuxEntryPtr(coff: *Coff, si: Symbol.Index) ?*align(2) std.coff.SectionDefinition {2561pub fn symbolTableSectionAuxEntryPtr(coff: *Coff, sti: SymbolTable.Index) ?*align(2) std.coff.SectionDefinition {
2554 const sti = si.get(coff).value.sti;
2555 if (symbolTableEntryPtr(coff, sti)) |entry| {2562 if (symbolTableEntryPtr(coff, sti)) |entry| {
2556 assert(entry.storage_class == .STATIC and entry.number_of_aux_symbols == 1);2563 assert(entry.storage_class == .STATIC and entry.number_of_aux_symbols == 1);
2557 return @ptrCast(@alignCast(symbolTableEntryStoragePtr(coff, sti.unwrap().? + 1)));2564 return @ptrCast(@alignCast(symbolTableEntryStoragePtr(coff, sti.unwrap().? + 1)));
...@@ -2560,8 +2567,7 @@ pub fn symbolTableSectionAuxEntryPtr(coff: *Coff, si: Symbol.Index) ?*align(2) s...@@ -2560,8 +2567,7 @@ pub fn symbolTableSectionAuxEntryPtr(coff: *Coff, si: Symbol.Index) ?*align(2) s
2560 }2567 }
2561}2568}
25622569
2563pub fn symbolTableWeakExternalAuxEntryPtr(coff: *Coff, si: Symbol.Index) ?*align(2) std.coff.WeakExternalDefinition {2570pub fn symbolTableWeakExternalAuxEntryPtr(coff: *Coff, sti: SymbolTable.Index) ?*align(2) std.coff.WeakExternalDefinition {
2564 const sti = si.get(coff).value.sti;
2565 if (symbolTableEntryPtr(coff, sti)) |entry| {2571 if (symbolTableEntryPtr(coff, sti)) |entry| {
2566 assert(entry.storage_class == .WEAK_EXTERNAL and entry.number_of_aux_symbols == 1);2572 assert(entry.storage_class == .WEAK_EXTERNAL and entry.number_of_aux_symbols == 1);
2567 return @ptrCast(@alignCast(symbolTableEntryStoragePtr(coff, sti.unwrap().? + 1)));2573 return @ptrCast(@alignCast(symbolTableEntryStoragePtr(coff, sti.unwrap().? + 1)));
...@@ -2604,10 +2610,10 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {...@@ -2604,10 +2610,10 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {
2604 defer coff.symbols.addOneAssumeCapacity().* = .{2610 defer coff.symbols.addOneAssumeCapacity().* = .{
2605 .ni = .none,2611 .ni = .none,
2606 .rva = 0,2612 .rva = 0,
2607 .value = .{ .sti = .none },2613 .value = .{ .none = {} },
2608 .extra = .{ .size = 0 },2614 .extra = .{ .size = 0 },
2609 .flags = .{2615 .flags = .{
2610 .value_tag = .sti,2616 .value_tag = .none,
2611 .extra_tag = .size,2617 .extra_tag = .size,
2612 .type = .unknown,2618 .type = .unknown,
2613 .dll_storage_class = .default,2619 .dll_storage_class = .default,
...@@ -2761,14 +2767,14 @@ pub fn globalSymbol(coff: *Coff, opts: GlobalOptions) !Symbol.Index {...@@ -2761,14 +2767,14 @@ pub fn globalSymbol(coff: *Coff, opts: GlobalOptions) !Symbol.Index {
2761pub fn pendingSymbolTableEntry(coff: *Coff, si: Symbol.Index) !void {2767pub fn pendingSymbolTableEntry(coff: *Coff, si: Symbol.Index) !void {
2762 assert(!coff.isImage());2768 assert(!coff.isImage());
2763 const sym = si.get(coff);2769 const sym = si.get(coff);
2764 if (sym.flags.value_tag == .sti and sym.value.sti != .none)
2765 return;
27662770
2767 assert(sym.ni != .none or sym.gmi != .none);2771 assert(sym.ni != .none or sym.gmi != .none);
2768 const gpa = coff.base.comp.gpa;2772 const gpa = coff.base.comp.gpa;
2769 const pending_gop = try coff.symbol_table.pending.getOrPut(gpa, si);2773 const gop = try coff.symbol_table.symbols.getOrPut(gpa, si);
2770 if (!pending_gop.found_existing)2774 if (!gop.found_existing) {
2771 coff.symbol_prog_node.increaseEstimatedTotalItems(1);2775 coff.symbol_prog_node.increaseEstimatedTotalItems(1);
2776 gop.value_ptr.* = .none;
2777 }
2772}2778}
27732779
2774fn navSection(2780fn navSection(
...@@ -3047,19 +3053,17 @@ fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void {...@@ -3047,19 +3053,17 @@ fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void {
3047 coff.member_prog_node.increaseEstimatedTotalItems(1);3053 coff.member_prog_node.increaseEstimatedTotalItems(1);
3048}3054}
30493055
3050fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void {3056fn flushSymbolTableEntry(coff: *Coff, index: u32, pt: Zcu.PerThread) !void {
3051 assert(!coff.isImage());3057 assert(!coff.isImage());
3052 const gpa = coff.base.comp.gpa;3058 const gpa = coff.base.comp.gpa;
30533059
3060 const si = coff.symbol_table.symbols.keys()[index];
3061 const sti = &coff.symbol_table.symbols.values()[index];
3062
3054 const sym = si.get(coff);3063 const sym = si.get(coff);
3055 assert(sym.ni != .none or sym.gmi != .none);3064 assert(sym.ni != .none or sym.gmi != .none);
3056 const existing_sti = switch (sym.flags.value_tag) {
3057 .sti => sym.value.sti,
3058 .weak_alias_si => .none,
3059 else => unreachable,
3060 };
30613065
3062 const entry = coff.symbolTableEntryPtr(existing_sti) orelse entry: {3066 const entry = coff.symbolTableEntryPtr(sti.*) orelse entry: {
3063 var buf: [15]u8 = undefined;3067 var buf: [15]u8 = undefined;
3064 const symbol_name, const num_aux_symbols: u8, const complex_type: std.coff.ComplexType =3068 const symbol_name, const num_aux_symbols: u8, const complex_type: std.coff.ComplexType =
3065 if (sym.gmi != .none) blk: {3069 if (sym.gmi != .none) blk: {
...@@ -3124,11 +3128,10 @@ fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void...@@ -3124,11 +3128,10 @@ fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void
31243128
3125 try coff.symbol_table.ni.resize(&coff.mf, gpa, new_num_symbols * std.coff.Symbol.sizeOf());3129 try coff.symbol_table.ni.resize(&coff.mf, gpa, new_num_symbols * std.coff.Symbol.sizeOf());
31263130
3127 const old_value = sym.value;3131 sti.* = .wrap(old_num_symbols);
3128 sym.setValue(.{ .sti = .wrap(old_num_symbols) });
3129 si.flushSymbolTableIndex(coff);3132 si.flushSymbolTableIndex(coff);
31303133
3131 const entry = coff.symbolTableEntryPtr(sym.value.sti).?;3134 const entry = coff.symbolTableEntryPtr(sti.*).?;
3132 symbol_name.store(coff, &entry.name);3135 symbol_name.store(coff, &entry.name);
31333136
3134 entry.section_number = @enumFromInt(@intFromEnum(sym.section_number));3137 entry.section_number = @enumFromInt(@intFromEnum(sym.section_number));
...@@ -3137,34 +3140,19 @@ fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void...@@ -3137,34 +3140,19 @@ fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void
3137 .base_type = .NULL,3140 .base_type = .NULL,
3138 };3141 };
31393142
3140 entry.storage_class = if (sym.flags.extra_tag == .next_alias_si) storage: {3143 entry.storage_class = if (sym.gmi != .none)
3141 // TODO: Could avoid this ordering issue by flushing these in fifo order, instead of lifo3144 .EXTERNAL
3142 // TODO: Instead keep a map of si -> sti (remove it from sym.value) and walk in forwards order3145 else if (sym.flags.extra_tag == .next_alias_si) storage: {
3143 // Update any existing aux symbols for weak externals that reference this symbol
3144 var any_weak_external = false;
3145 var alias_sym = sym;3146 var alias_sym = sym;
3146 while (alias_sym.flags.extra_tag == .next_alias_si) {3147 const weak_external = while (alias_sym.flags.extra_tag == .next_alias_si) {
3147 const alias_si = alias_sym.extra.next_alias_si;3148 const alias_si = alias_sym.extra.next_alias_si;
3148 alias_sym = alias_si.get(coff);3149 alias_sym = alias_si.get(coff);
3149 assert(alias_sym.ni == sym.ni);3150 assert(alias_sym.ni == sym.ni);
31503151 if (alias_sym.flags.weak_external_strat != .none)
3151 if (alias_sym.flags.weak_external_strat != .none) {3152 break true;
3152 switch (alias_sym.flags.value_tag) {3153 } else false;
3153 .sti => if (coff.symbolTableWeakExternalAuxEntryPtr(alias_si)) |aux_ptr|3154 break :storage if (weak_external) .EXTERNAL else .STATIC;
3154 coff.targetStore(&aux_ptr.tag_index, sym.value.sti.unwrap().?),3155 } else .STATIC;
3155 .weak_alias_si => {},
3156 else => unreachable,
3157 }
3158
3159 any_weak_external = true;
3160 }
3161 }
3162
3163 break :storage if (any_weak_external or sym.gmi != .none) .EXTERNAL else .STATIC;
3164 } else if (sym.gmi == .none)
3165 .STATIC
3166 else
3167 .EXTERNAL;
31683156
3169 entry.number_of_aux_symbols = num_aux_symbols;3157 entry.number_of_aux_symbols = num_aux_symbols;
3170 if (coff.targetEndian() != native_endian)3158 if (coff.targetEndian() != native_endian)
...@@ -3175,15 +3163,8 @@ fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void...@@ -3175,15 +3163,8 @@ fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void
3175 entry.section_number = .UNDEFINED;3163 entry.section_number = .UNDEFINED;
3176 entry.storage_class = .WEAK_EXTERNAL;3164 entry.storage_class = .WEAK_EXTERNAL;
31773165
3178 const alias_si = old_value.weak_alias_si;3166 const tag_index = sym.value.weak_alias_si.sti(coff).unwrap().?;
3179 const alias_sym = alias_si.get(coff);3167 const aux_ptr = coff.symbolTableWeakExternalAuxEntryPtr(sti.*).?;
3180 const tag_index = alias_sym.value.sti.unwrap() orelse tag_index: {
3181 // The alias will update `tag_index` when it is flushed
3182 assert(coff.symbol_table.pending.contains(alias_si));
3183 break :tag_index 0;
3184 };
3185
3186 const aux_ptr = coff.symbolTableWeakExternalAuxEntryPtr(si).?;
3187 aux_ptr.* = .{3168 aux_ptr.* = .{
3188 .tag_index = tag_index,3169 .tag_index = tag_index,
3189 .flag = switch (sym.flags.weak_external_strat) {3170 .flag = switch (sym.flags.weak_external_strat) {
...@@ -3203,7 +3184,7 @@ fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void...@@ -3203,7 +3184,7 @@ fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void
3203 .image_section => |sec_si| {3184 .image_section => |sec_si| {
3204 assert(si == sec_si);3185 assert(si == sec_si);
3205 const header = sym.section_number.header(coff);3186 const header = sym.section_number.header(coff);
3206 const aux_ptr = coff.symbolTableSectionAuxEntryPtr(si).?;3187 const aux_ptr = coff.symbolTableSectionAuxEntryPtr(sti.*).?;
3207 aux_ptr.* = .{3188 aux_ptr.* = .{
3208 .length = @intCast(sym.ni.location(&coff.mf).resolve(&coff.mf)[1]),3189 .length = @intCast(sym.ni.location(&coff.mf).resolve(&coff.mf)[1]),
3209 .number_of_relocations = header.number_of_relocations,3190 .number_of_relocations = header.number_of_relocations,
...@@ -3238,7 +3219,7 @@ fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void...@@ -3238,7 +3219,7 @@ fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void
3238 },3219 },
3239 });3220 });
32403221
3241 log.debug("flushSymbolTableEntry({d}) = {d}", .{ si, sym.value.sti });3222 log.debug("flushSymbolTableEntry({d}) = {d}", .{ si, sti.* });
3242}3223}
32433224
3244fn flushInputMember(coff: *Coff, iami: InputArchive.Member.Index) !void {3225fn flushInputMember(coff: *Coff, iami: InputArchive.Member.Index) !void {
...@@ -3300,7 +3281,7 @@ fn addSection(coff: *Coff, name: String, flags: std.coff.SectionHeader.Flags) !S...@@ -3300,7 +3281,7 @@ fn addSection(coff: *Coff, name: String, flags: std.coff.SectionHeader.Flags) !S
3300 try coff.nodes.ensureUnusedCapacity(gpa, 1);3281 try coff.nodes.ensureUnusedCapacity(gpa, 1);
3301 try coff.section_table.ensureUnusedCapacity(gpa, 1);3282 try coff.section_table.ensureUnusedCapacity(gpa, 1);
3302 try coff.symbols.ensureUnusedCapacity(gpa, 1);3283 try coff.symbols.ensureUnusedCapacity(gpa, 1);
3303 if (!isImage(coff)) try coff.symbol_table.pending.ensureUnusedCapacity(gpa, 1);3284 if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1);
33043285
3305 const coff_header = coff.headerPtr();3286 const coff_header = coff.headerPtr();
3306 const section_index = coff.targetLoad(&coff_header.number_of_sections);3287 const section_index = coff.targetLoad(&coff_header.number_of_sections);
...@@ -3643,8 +3624,9 @@ pub fn addReloc(...@@ -3643,8 +3624,9 @@ pub fn addReloc(
3643 else => |loc_sn| sri: {3624 else => |loc_sn| sri: {
3644 // The target may not have a node yet, or it could be an extern that will never3625 // The target may not have a node yet, or it could be an extern that will never
3645 // have a node. In that case, flushGlobal will create the symbol table entry.3626 // have a node. In that case, flushGlobal will create the symbol table entry.
3646 const sti: SymbolTable.Index = if (target.value.sti != .none)3627 const existing_sti = target_si.sti(coff);
3647 target.value.sti3628 const sti: SymbolTable.Index = if (existing_sti != .none)
3629 existing_sti
3648 else if (target.ni != .none) sti: {3630 else if (target.ni != .none) sti: {
3649 try coff.pendingSymbolTableEntry(target_si);3631 try coff.pendingSymbolTableEntry(target_si);
3650 break :sti .none;3632 break :sti .none;
...@@ -3669,7 +3651,7 @@ pub fn addReloc(...@@ -3669,7 +3651,7 @@ pub fn addReloc(
3669 }3651 }
36703652
3671 coff.targetStore(&header.number_of_relocations, new_num_relocations);3653 coff.targetStore(&header.number_of_relocations, new_num_relocations);
3672 if (coff.symbolTableSectionAuxEntryPtr(loc_sn.symbol(coff))) |aux_ptr|3654 if (coff.symbolTableSectionAuxEntryPtr(loc_sn.symbol(coff).sti(coff))) |aux_ptr|
3673 coff.targetStore(&aux_ptr.number_of_relocations, new_num_relocations);3655 coff.targetStore(&aux_ptr.number_of_relocations, new_num_relocations);
36743656
3675 // TODO: These need to allocate from a free list (once deleting relocs is supported) (or can we just remove swap?)3657 // TODO: These need to allocate from a free list (once deleting relocs is supported) (or can we just remove swap?)
...@@ -5306,7 +5288,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -5306,7 +5288,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
5306 .none => {5288 .none => {
5307 const sec_si = try coff.navSection(zcu, nav.resolved.?);5289 const sec_si = try coff.navSection(zcu, nav.resolved.?);
5308 try coff.nodes.ensureUnusedCapacity(gpa, 1);5290 try coff.nodes.ensureUnusedCapacity(gpa, 1);
5309 if (!isImage(coff)) try coff.symbol_table.pending.ensureUnusedCapacity(gpa, 1);5291 if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1);
5310 const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{5292 const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{
5311 .alignment = zcu.navAlignment(nav_index).toStdMem(),5293 .alignment = zcu.navAlignment(nav_index).toStdMem(),
5312 .moved = true,5294 .moved = true,
...@@ -5428,7 +5410,7 @@ fn updateFuncInner(...@@ -5428,7 +5410,7 @@ fn updateFuncInner(
5428 .none => {5410 .none => {
5429 const sec_si = try coff.navSection(zcu, nav.resolved.?);5411 const sec_si = try coff.navSection(zcu, nav.resolved.?);
5430 try coff.nodes.ensureUnusedCapacity(gpa, 1);5412 try coff.nodes.ensureUnusedCapacity(gpa, 1);
5431 if (!isImage(coff)) try coff.symbol_table.pending.ensureUnusedCapacity(gpa, 1);5413 if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1);
5432 const mod = zcu.navFileScope(func.owner_nav).mod.?;5414 const mod = zcu.navFileScope(func.owner_nav).mod.?;
5433 const target = &mod.resolved_target.result;5415 const target = &mod.resolved_target.result;
5434 const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{5416 const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{
...@@ -5902,19 +5884,21 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool {...@@ -5902,19 +5884,21 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
5902 };5884 };
5903 break :task;5885 break :task;
5904 };5886 };
5905 while (coff.symbol_table.pending.pop()) |pending_si| {5887 if (coff.symbol_table.pending_symbol_index < coff.symbol_table.symbols.count()) {
5906 const sym = pending_si.key.get(coff);5888 defer coff.symbol_table.pending_symbol_index += 1;
5889 const si = coff.symbol_table.symbols.keys()[coff.symbol_table.pending_symbol_index];
5890 const sym = si.get(coff);
5907 const sub_prog_node = coff.idleProgNode(5891 const sub_prog_node = coff.idleProgNode(
5908 tid,5892 tid,
5909 coff.symbol_prog_node,5893 coff.symbol_prog_node,
5910 if (sym.ni != .none)5894 if (sym.ni != .none)
5911 coff.getNode(sym.ni)5895 coff.getNode(sym.ni)
5912 else5896 else
5913 .{ .import_thunk = pending_si.key.get(coff).gmi },5897 .{ .import_thunk = sym.gmi },
5914 );5898 );
5915 defer sub_prog_node.end();5899 defer sub_prog_node.end();
5916 coff.flushSymbolTableEntry(5900 coff.flushSymbolTableEntry(
5917 pending_si.key,5901 coff.symbol_table.pending_symbol_index,
5918 .{ .zcu = comp.zcu.?, .tid = tid },5902 .{ .zcu = comp.zcu.?, .tid = tid },
5919 ) catch |err| switch (err) {5903 ) catch |err| switch (err) {
5920 error.OutOfMemory => return error.OutOfMemory,5904 error.OutOfMemory => return error.OutOfMemory,
...@@ -5935,7 +5919,7 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool {...@@ -5935,7 +5919,7 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
5935 if (coff.exports_complete and coff.late_globals.items.len > coff.late_globals_pending_index) return true;5919 if (coff.exports_complete and coff.late_globals.items.len > coff.late_globals_pending_index) return true;
5936 if (coff.exports_complete and coff.pending_special_symbol != .none) return true;5920 if (coff.exports_complete and coff.pending_special_symbol != .none) return true;
5937 for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true;5921 for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true;
5938 if (coff.symbol_table.pending.count() > 0) return true;5922 if (coff.symbol_table.pending_symbol_index < coff.symbol_table.symbols.count()) return true;
5939 return false;5923 return false;
5940}5924}
59415925
...@@ -6066,7 +6050,7 @@ fn flushUav(...@@ -6066,7 +6050,7 @@ fn flushUav(
6066 .{ .read = true, .initialized = true },6050 .{ .read = true, .initialized = true },
6067 )).symbol(coff);6051 )).symbol(coff);
6068 try coff.nodes.ensureUnusedCapacity(gpa, 1);6052 try coff.nodes.ensureUnusedCapacity(gpa, 1);
6069 if (!isImage(coff)) try coff.symbol_table.pending.ensureUnusedCapacity(gpa, 1);6053 if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1);
6070 const sym = si.get(coff);6054 const sym = si.get(coff);
6071 const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{6055 const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{
6072 .alignment = uav_align.toStdMem(),6056 .alignment = uav_align.toStdMem(),
...@@ -7012,7 +6996,7 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {...@@ -7012,7 +6996,7 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {
7012 }6996 }
70136997
7014 if (!coff.isImage()) {6998 if (!coff.isImage()) {
7015 if (coff.symbolTableSectionAuxEntryPtr(si)) |aux_ptr|6999 if (coff.symbolTableSectionAuxEntryPtr(si.sti(coff))) |aux_ptr|
7016 coff.targetStore(&aux_ptr.length, @intCast(size));7000 coff.targetStore(&aux_ptr.length, @intCast(size));
7017 }7001 }
7018 },7002 },
...@@ -7290,6 +7274,8 @@ fn updateExportsInner(...@@ -7290,6 +7274,8 @@ fn updateExportsInner(
7290 export_sym.rva = exported_sym.rva;7274 export_sym.rva = exported_sym.rva;
7291 export_sym.section_number = exported_sym.section_number;7275 export_sym.section_number = exported_sym.section_number;
7292 if (@"export".opts.linkage == .weak and !coff.isImage()) {7276 if (@"export".opts.linkage == .weak and !coff.isImage()) {
7277 // exported_si needs to be ahead of export_si in the symbol table,
7278 // so that its sti is known when creating the aux entry
7293 try coff.pendingSymbolTableEntry(exported_si);7279 try coff.pendingSymbolTableEntry(exported_si);
7294 export_sym.flags.weak_external_strat = .alias;7280 export_sym.flags.weak_external_strat = .alias;
7295 export_sym.setValue(.{ .weak_alias_si = exported_si });7281 export_sym.setValue(.{ .weak_alias_si = exported_si });
...@@ -7466,10 +7452,10 @@ fn printSymbol(...@@ -7466,10 +7452,10 @@ fn printSymbol(
7466 else7452 else
7467 0,7453 0,
7468 switch (sym.flags.value_tag) {7454 switch (sym.flags.value_tag) {
7455 .none => "xx",
7469 .weak_alias_name => "an",7456 .weak_alias_name => "an",
7470 .weak_alias_si => "as",7457 .weak_alias_si => "as",
7471 .node_offset => "no",7458 .node_offset => "no",
7472 .sti => "st",
7473 },7459 },
7474 switch (sym.flags.extra_tag) {7460 switch (sym.flags.extra_tag) {
7475 .size => "sz",7461 .size => "sz",
test/link/snapshots/static-lib.no-llvm.dmp+5-5
...@@ -4,9 +4,9 @@ xxxx 00000000 1 NULL() EXTERNAL | fooBar...@@ -4,9 +4,9 @@ xxxx 00000000 1 NULL() EXTERNAL | fooBar
4xxxx 00000000 2 NULL EXTERNAL | foo14xxxx 00000000 2 NULL EXTERNAL | foo1
5xxxx 00000004 2 NULL EXTERNAL | foo25xxxx 00000004 2 NULL EXTERNAL | foo2
6lib.lib(this_is_a_long_name.obj): COFF object6lib.lib(this_is_a_long_name.obj): COFF object
7xxxx 00000000 UNDEF NULL() WEAK_EXTERNAL | fooWeak
8 | Weak External [falls back to 00000012 via SEARCH_ALIAS]
9xxxx 00000010 2 NULL EXTERNAL | foo_array
10xxxx 00000000 2 NULL EXTERNAL | foo_strong_alias
11xxxx 00000000 2 NULL EXTERNAL | foo_strong
12xxxx 00000000 4 NULL() EXTERNAL | this_is_a_long_name.fooWeak7xxxx 00000000 4 NULL() EXTERNAL | this_is_a_long_name.fooWeak
8xxxx 00000000 2 NULL EXTERNAL | foo_strong
9xxxx 00000000 2 NULL EXTERNAL | foo_strong_alias
10xxxx 00000010 2 NULL EXTERNAL | foo_array
11xxxx 00000000 UNDEF NULL() WEAK_EXTERNAL | fooWeak
12 | Weak External [falls back to 0000000d via SEARCH_ALIAS]