| ... | @@ -2663,11 +2663,28 @@ fn getOrPutGlobalSymbol( | ... | @@ -2663,11 +2663,28 @@ fn getOrPutGlobalSymbol( |
| 2663 | coff: *Coff, | 2663 | coff: *Coff, |
| 2664 | opts: GlobalOptions, | 2664 | opts: GlobalOptions, |
| 2665 | ) !std.AutoArrayHashMapUnmanaged(GlobalName, Symbol.Index).GetOrPutResult { | 2665 | ) !std.AutoArrayHashMapUnmanaged(GlobalName, Symbol.Index).GetOrPutResult { |
| 2666 | const gpa = coff.base.comp.gpa; | 2666 | const comp = coff.base.comp; |
| | 2667 | const gpa = comp.gpa; |
| 2667 | try coff.symbols.ensureUnusedCapacity(gpa, 1); | 2668 | try coff.symbols.ensureUnusedCapacity(gpa, 1); |
| | 2669 | |
| | 2670 | const lib_name = if (opts.lib_name) |lib_name| lib_name: { |
| | 2671 | const is_libc = std.zig.target.isLibCLibName(&comp.root_mod.resolved_target.result, lib_name); |
| | 2672 | if (is_libc) { |
| | 2673 | // This is guaranteed by Sema.handleExternLibName |
| | 2674 | if (!comp.config.link_libc) unreachable; |
| | 2675 | |
| | 2676 | // TODO: The user has requested this symbol come from libc, but this logic allows |
| | 2677 | // it to come from anywhere. We need to know what inputs are libc inputs, |
| | 2678 | // and set a flag to only search them for this symbol. |
| | 2679 | break :lib_name null; |
| | 2680 | } |
| | 2681 | |
| | 2682 | break :lib_name lib_name; |
| | 2683 | } else null; |
| | 2684 | |
| 2668 | const sym_gop = try coff.globals.getOrPut(gpa, .{ | 2685 | const sym_gop = try coff.globals.getOrPut(gpa, .{ |
| 2669 | .name = try coff.getOrPutString(opts.name), | 2686 | .name = try coff.getOrPutString(opts.name), |
| 2670 | .lib_name = try coff.getOrPutOptionalString(opts.lib_name), | 2687 | .lib_name = try coff.getOrPutOptionalString(lib_name), |
| 2671 | }); | 2688 | }); |
| 2672 | if (!sym_gop.found_existing) { | 2689 | if (!sym_gop.found_existing) { |
| 2673 | const si = coff.addSymbolAssumeCapacity(); | 2690 | const si = coff.addSymbolAssumeCapacity(); |
| ... | @@ -5576,6 +5593,7 @@ pub fn flush( | ... | @@ -5576,6 +5593,7 @@ pub fn flush( |
| 5576 | // this should be set after updateExports instead | 5593 | // this should be set after updateExports instead |
| 5577 | coff.exports_complete = true; | 5594 | coff.exports_complete = true; |
| 5578 | | 5595 | |
| | 5596 | while (try coff.resolve(tid)) {} |
| 5579 | while (try coff.idle(tid)) {} | 5597 | while (try coff.idle(tid)) {} |
| 5580 | | 5598 | |
| 5581 | if (coff.isImage()) | 5599 | if (coff.isImage()) |
| ... | @@ -5598,7 +5616,10 @@ pub fn flush( | ... | @@ -5598,7 +5616,10 @@ pub fn flush( |
| 5598 | return comp.link_diags.fail("dumping link snapshot failed: {t}", .{err}); | 5616 | return comp.link_diags.fail("dumping link snapshot failed: {t}", .{err}); |
| 5599 | } | 5617 | } |
| 5600 | | 5618 | |
| 5601 | pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | 5619 | /// Runs a single "resolution" task. |
| | 5620 | /// These are tasks that need to modify the node structure in some way. |
| | 5621 | /// They must run in a defined order with respect to linker tasks. |
| | 5622 | fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 5602 | const comp = coff.base.comp; | 5623 | const comp = coff.base.comp; |
| 5603 | task: { | 5624 | task: { |
| 5604 | while (coff.section_merge_pending_index < coff.section_merges.count()) { | 5625 | while (coff.section_merge_pending_index < coff.section_merges.count()) { |
| ... | @@ -5658,7 +5679,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -5658,7 +5679,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 5658 | }; | 5679 | }; |
| 5659 | break :task; | 5680 | break :task; |
| 5660 | } | 5681 | } |
| 5661 | if (coff.inputs_complete and coff.global_pending_index < coff.globals.count()) { | 5682 | if (coff.exports_complete and coff.global_pending_index < coff.globals.count()) { |
| 5662 | const gmi: Node.GlobalMapIndex = .wrap(coff.global_pending_index); | 5683 | const gmi: Node.GlobalMapIndex = .wrap(coff.global_pending_index); |
| 5663 | const sub_prog_node = coff.synth_prog_node.start( | 5684 | const sub_prog_node = coff.synth_prog_node.start( |
| 5664 | gmi.globalName(coff).name.toSlice(coff), | 5685 | gmi.globalName(coff).name.toSlice(coff), |
| ... | @@ -5751,6 +5772,53 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -5751,6 +5772,53 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 5751 | }; | 5772 | }; |
| 5752 | break :task; | 5773 | break :task; |
| 5753 | } | 5774 | } |
| | 5775 | if (coff.symbol_table.pending_shrink) { |
| | 5776 | defer coff.symbol_table.pending_shrink = false; |
| | 5777 | const sub_prog_node = coff.idleProgNode( |
| | 5778 | tid, |
| | 5779 | coff.symbol_prog_node, |
| | 5780 | coff.getNode(coff.symbol_table.ni), |
| | 5781 | ); |
| | 5782 | defer sub_prog_node.end(); |
| | 5783 | |
| | 5784 | const number_of_symbols = coff.targetLoad(&coff.headerPtr().number_of_symbols); |
| | 5785 | coff.symbol_table.ni.shrink( |
| | 5786 | &coff.mf, |
| | 5787 | comp.gpa, |
| | 5788 | number_of_symbols * std.coff.Symbol.sizeOf(), |
| | 5789 | true, |
| | 5790 | ) catch |err| switch (err) { |
| | 5791 | error.OutOfMemory => return error.OutOfMemory, |
| | 5792 | else => |e| return comp.link_diags.fail( |
| | 5793 | "linker failed to compact symbol table: {t}", |
| | 5794 | .{e}, |
| | 5795 | ), |
| | 5796 | }; |
| | 5797 | |
| | 5798 | break :task; |
| | 5799 | } |
| | 5800 | } |
| | 5801 | |
| | 5802 | if (coff.section_merge_pending_index < coff.section_merges.count()) return true; |
| | 5803 | if (coff.pending_uavs.count() > 0) return true; |
| | 5804 | if (coff.pending_input != null) return true; |
| | 5805 | if (coff.exports_complete and coff.globals.count() > coff.global_pending_index) return true; |
| | 5806 | assert(!coff.exports_complete or coff.inputs_complete); |
| | 5807 | if (coff.exports_complete and coff.late_globals.items.len > coff.late_globals_pending_index) return true; |
| | 5808 | if (coff.exports_complete and coff.pending_special_symbol != .none) return true; |
| | 5809 | for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true; |
| | 5810 | if (coff.symbol_table.pending.count() > 0) return true; |
| | 5811 | if (coff.symbol_table.pending_shrink) return true; |
| | 5812 | return false; |
| | 5813 | } |
| | 5814 | |
| | 5815 | pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| | 5816 | // Idle tasks should not modify create / modify nodes, otherwise the output is not reproducible. |
| | 5817 | coff.mf.nodes_lock.lock(); |
| | 5818 | defer coff.mf.nodes_lock.unlock(); |
| | 5819 | |
| | 5820 | const comp = coff.base.comp; |
| | 5821 | task: { |
| 5754 | // TODO: Idle task for flushing obj into lib | 5822 | // TODO: Idle task for flushing obj into lib |
| 5755 | if (coff.input_section_pending_index < coff.input_sections.items.len) { | 5823 | if (coff.input_section_pending_index < coff.input_sections.items.len) { |
| 5756 | const isi: Node.InputSection.Index = @enumFromInt(coff.input_section_pending_index); | 5824 | const isi: Node.InputSection.Index = @enumFromInt(coff.input_section_pending_index); |
| ... | @@ -5809,46 +5877,11 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -5809,46 +5877,11 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 5809 | coff.flushExportsSort(); | 5877 | coff.flushExportsSort(); |
| 5810 | break :task; | 5878 | break :task; |
| 5811 | } | 5879 | } |
| 5812 | if (coff.symbol_table.pending_shrink) { | | |
| 5813 | defer coff.symbol_table.pending_shrink = false; | | |
| 5814 | const sub_prog_node = coff.idleProgNode( | | |
| 5815 | tid, | | |
| 5816 | coff.symbol_prog_node, | | |
| 5817 | coff.getNode(coff.symbol_table.ni), | | |
| 5818 | ); | | |
| 5819 | defer sub_prog_node.end(); | | |
| 5820 | | | |
| 5821 | const number_of_symbols = coff.targetLoad(&coff.headerPtr().number_of_symbols); | | |
| 5822 | coff.symbol_table.ni.shrink( | | |
| 5823 | &coff.mf, | | |
| 5824 | comp.gpa, | | |
| 5825 | number_of_symbols * std.coff.Symbol.sizeOf(), | | |
| 5826 | true, | | |
| 5827 | ) catch |err| switch (err) { | | |
| 5828 | error.OutOfMemory => return error.OutOfMemory, | | |
| 5829 | else => |e| return comp.link_diags.fail( | | |
| 5830 | "linker failed to compact symbol table: {t}", | | |
| 5831 | .{e}, | | |
| 5832 | ), | | |
| 5833 | }; | | |
| 5834 | | | |
| 5835 | break :task; | | |
| 5836 | } | | |
| 5837 | } | 5880 | } |
| 5838 | if (coff.section_merge_pending_index < coff.section_merges.count()) return true; | | |
| 5839 | if (coff.pending_uavs.count() > 0) return true; | | |
| 5840 | if (coff.pending_input != null) return true; | | |
| 5841 | if (coff.inputs_complete and coff.globals.count() > coff.global_pending_index) return true; | | |
| 5842 | assert(!coff.exports_complete or coff.inputs_complete); | | |
| 5843 | if (coff.exports_complete and coff.late_globals.items.len > coff.late_globals_pending_index) return true; | | |
| 5844 | if (coff.exports_complete and coff.pending_special_symbol != .none) return true; | | |
| 5845 | for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true; | | |
| 5846 | if (coff.symbol_table.pending.count() > 0) return true; | | |
| 5847 | if (coff.input_sections.items.len > coff.input_section_pending_index) return true; | 5881 | if (coff.input_sections.items.len > coff.input_section_pending_index) return true; |
| 5848 | if (coff.mf.updates.items.len > 0) return true; | 5882 | if (coff.mf.updates.items.len > 0) return true; |
| 5849 | if (coff.pending_members.count() > 0) return true; | 5883 | if (coff.pending_members.count() > 0) return true; |
| 5850 | if (coff.export_table.pending_sort) return true; | 5884 | if (coff.export_table.pending_sort) return true; |
| 5851 | if (coff.symbol_table.pending_shrink) return true; | | |
| 5852 | return false; | 5885 | return false; |
| 5853 | } | 5886 | } |
| 5854 | | 5887 | |
| ... | @@ -6924,7 +6957,6 @@ fn flushMember(coff: *Coff, mi: Member.Index) !void { | ... | @@ -6924,7 +6957,6 @@ fn flushMember(coff: *Coff, mi: Member.Index) !void { |
| 6924 | }); | 6957 | }); |
| 6925 | | 6958 | |
| 6926 | var offset: u64 = 0; | 6959 | var offset: u64 = 0; |
| 6927 | | | |
| 6928 | var string_table = coff.secondLinkerMemberStringsSlice(); | 6960 | var string_table = coff.secondLinkerMemberStringsSlice(); |
| 6929 | for (coff.lib_string_table.items) |string| { | 6961 | for (coff.lib_string_table.items) |string| { |
| 6930 | const str = string.toSlice(coff); | 6962 | const str = string.toSlice(coff); |
| ... | @@ -7096,6 +7128,7 @@ fn updateExportsInner( | ... | @@ -7096,6 +7128,7 @@ fn updateExportsInner( |
| 7096 | Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu), | 7128 | Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu), |
| 7097 | ))), | 7129 | ))), |
| 7098 | }; | 7130 | }; |
| | 7131 | while (try coff.resolve(pt.tid)) {} |
| 7099 | while (try coff.idle(pt.tid)) {} | 7132 | while (try coff.idle(pt.tid)) {} |
| 7100 | | 7133 | |
| 7101 | const machine = coff.targetLoad(&coff.headerPtr().machine); | 7134 | const machine = coff.targetLoad(&coff.headerPtr().machine); |