@@ -5,14 +5,16 @@ use std::path::{Path, PathBuf};
5
5
use std:: { env, io, iter, mem, str} ;
6
6
7
7
use cc:: windows_registry;
8
+ use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
8
9
use rustc_hir:: def_id:: { CrateNum , LOCAL_CRATE } ;
9
10
use rustc_metadata:: {
10
11
find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library,
11
12
} ;
12
13
use rustc_middle:: bug;
13
14
use rustc_middle:: middle:: dependency_format:: Linkage ;
14
- use rustc_middle:: middle:: exported_symbols;
15
- use rustc_middle:: middle:: exported_symbols:: { ExportedSymbol , SymbolExportInfo , SymbolExportKind } ;
15
+ use rustc_middle:: middle:: exported_symbols:: {
16
+ self , ExportedSymbol , SymbolExportInfo , SymbolExportKind ,
17
+ } ;
16
18
use rustc_middle:: ty:: TyCtxt ;
17
19
use rustc_session:: Session ;
18
20
use rustc_session:: config:: { self , CrateType , DebugInfo , LinkerPluginLto , Lto , OptLevel , Strip } ;
@@ -21,6 +23,7 @@ use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld};
21
23
use tracing:: { debug, warn} ;
22
24
23
25
use super :: command:: Command ;
26
+ use super :: link:: are_upstream_rust_objects_already_included;
24
27
use super :: symbol_export;
25
28
use crate :: errors;
26
29
@@ -1753,17 +1756,15 @@ impl<'a> Linker for AixLinker<'a> {
1753
1756
fn for_each_exported_symbols_include_dep < ' tcx > (
1754
1757
tcx : TyCtxt < ' tcx > ,
1755
1758
crate_type : CrateType ,
1756
- mut callback : impl FnMut ( ExportedSymbol < ' tcx > , SymbolExportInfo , CrateNum ) ,
1759
+ mut callback : impl FnMut ( & ' tcx [ ( ExportedSymbol < ' tcx > , SymbolExportInfo ) ] , CrateNum ) ,
1757
1760
) {
1758
1761
let formats = tcx. dependency_formats ( ( ) ) ;
1759
1762
let deps = & formats[ & crate_type] ;
1760
1763
1761
1764
for ( cnum, dep_format) in deps. iter_enumerated ( ) {
1762
1765
// For each dependency that we are linking to statically ...
1763
1766
if * dep_format == Linkage :: Static {
1764
- for & ( symbol, info) in tcx. exported_symbols ( cnum) . iter ( ) {
1765
- callback ( symbol, info, cnum) ;
1766
- }
1767
+ callback ( tcx. exported_symbols ( cnum) , cnum) ;
1767
1768
}
1768
1769
}
1769
1770
}
@@ -1783,12 +1784,14 @@ pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<St
1783
1784
fn exported_symbols_for_non_proc_macro ( tcx : TyCtxt < ' _ > , crate_type : CrateType ) -> Vec < String > {
1784
1785
let mut symbols = Vec :: new ( ) ;
1785
1786
let export_threshold = symbol_export:: crates_export_threshold ( & [ crate_type] ) ;
1786
- for_each_exported_symbols_include_dep ( tcx, crate_type, |symbol, info, cnum| {
1787
- if info. level . is_below_threshold ( export_threshold) {
1788
- symbols. push ( symbol_export:: exporting_symbol_name_for_instance_in_crate (
1789
- tcx, symbol, cnum,
1790
- ) ) ;
1791
- symbol_export:: extend_exported_symbols ( & mut symbols, tcx, symbol, cnum) ;
1787
+ for_each_exported_symbols_include_dep ( tcx, crate_type, |exported_symbols, cnum| {
1788
+ for & ( symbol, info) in exported_symbols {
1789
+ if info. level . is_below_threshold ( export_threshold) {
1790
+ symbols. push ( symbol_export:: exporting_symbol_name_for_instance_in_crate (
1791
+ tcx, symbol, cnum,
1792
+ ) ) ;
1793
+ symbol_export:: extend_exported_symbols ( & mut symbols, tcx, symbol, cnum) ;
1794
+ }
1792
1795
}
1793
1796
} ) ;
1794
1797
@@ -1808,30 +1811,84 @@ fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> {
1808
1811
vec ! [ proc_macro_decls_name, metadata_symbol_name]
1809
1812
}
1810
1813
1811
- pub ( crate ) fn linked_symbols (
1814
+ pub ( crate ) fn linked_objects (
1812
1815
tcx : TyCtxt < ' _ > ,
1813
1816
crate_type : CrateType ,
1814
- ) -> Vec < ( String , SymbolExportKind ) > {
1817
+ linked_symbols : & mut Vec < ( String , SymbolExportKind ) > ,
1818
+ ) -> FxIndexMap < CrateNum , FxHashSet < String > > {
1815
1819
match crate_type {
1816
1820
CrateType :: Executable | CrateType :: Cdylib | CrateType :: Dylib => ( ) ,
1817
1821
CrateType :: Staticlib | CrateType :: ProcMacro | CrateType :: Rlib => {
1818
- return Vec :: new ( ) ;
1822
+ return FxIndexMap :: default ( ) ;
1819
1823
}
1820
1824
}
1821
1825
1822
- let mut symbols = Vec :: new ( ) ;
1823
-
1826
+ let mut objects = FxIndexMap :: default ( ) ;
1827
+ let upstream_rust_objects_already_included =
1828
+ are_upstream_rust_objects_already_included ( tcx. sess ) ;
1824
1829
let export_threshold = symbol_export:: crates_export_threshold ( & [ crate_type] ) ;
1825
- for_each_exported_symbols_include_dep ( tcx, crate_type, |symbol, info, cnum| {
1826
- if info. level . is_below_threshold ( export_threshold) || info. used {
1827
- symbols. push ( (
1828
- symbol_export:: linking_symbol_name_for_instance_in_crate ( tcx, symbol, cnum) ,
1829
- info. kind ,
1830
- ) ) ;
1830
+ for_each_exported_symbols_include_dep ( tcx, crate_type, |exported_symbols, cnum| {
1831
+ let exported_symbols = exported_symbols. iter ( ) . filter ( |( _, info) | {
1832
+ ( !matches ! ( crate_type, CrateType :: Executable )
1833
+ && info. level . is_below_threshold ( export_threshold) )
1834
+ || info. used
1835
+ } ) ;
1836
+ if cnum == LOCAL_CRATE {
1837
+ // Since the local crate is always linked directly to object files, `#[used]` works as expected,
1838
+ // we only need add undefined symbols.
1839
+ linked_symbols. extend (
1840
+ exported_symbols
1841
+ . filter ( |( symbol, _) | match symbol {
1842
+ ExportedSymbol :: NonGeneric { cgu, .. } => cgu. is_none ( ) ,
1843
+ ExportedSymbol :: Generic ( ..)
1844
+ | ExportedSymbol :: DropGlue ( ..)
1845
+ | ExportedSymbol :: AsyncDropGlueCtorShim ( ..) => false ,
1846
+ ExportedSymbol :: ThreadLocalShim ( _def_id) => false ,
1847
+ ExportedSymbol :: NoDefId ( ..) => true ,
1848
+ } )
1849
+ . map ( |& ( symbol, info) | {
1850
+ (
1851
+ symbol_export:: linking_symbol_name_for_instance_in_crate (
1852
+ tcx, symbol, cnum,
1853
+ ) ,
1854
+ info. kind ,
1855
+ )
1856
+ } ) ,
1857
+ ) ;
1858
+ return ;
1859
+ }
1860
+ if matches ! ( crate_type, CrateType :: Executable ) && tcx. is_compiler_builtins ( cnum) {
1861
+ return ;
1831
1862
}
1863
+ let lto = upstream_rust_objects_already_included;
1864
+ let mut cgus = FxHashSet :: default ( ) ;
1865
+ for & ( symbol, info) in exported_symbols {
1866
+ match symbol {
1867
+ ExportedSymbol :: NonGeneric { cgu : Some ( cgu) , .. } => {
1868
+ if !lto {
1869
+ cgus. insert ( cgu. as_str ( ) . to_string ( ) ) ;
1870
+ }
1871
+ }
1872
+ ExportedSymbol :: NonGeneric { cgu : None , .. } | ExportedSymbol :: NoDefId ( ..) => {
1873
+ // Unresolved symbols may come from external libraries.
1874
+ linked_symbols. push ( (
1875
+ symbol_export:: linking_symbol_name_for_instance_in_crate ( tcx, symbol, cnum) ,
1876
+ info. kind ,
1877
+ ) ) ;
1878
+ }
1879
+ ExportedSymbol :: Generic ( ..)
1880
+ | ExportedSymbol :: DropGlue ( ..)
1881
+ | ExportedSymbol :: AsyncDropGlueCtorShim ( ..)
1882
+ | ExportedSymbol :: ThreadLocalShim ( ..) => { }
1883
+ } ;
1884
+ }
1885
+ if cgus. is_empty ( ) {
1886
+ return ;
1887
+ }
1888
+ objects. insert ( cnum, cgus) ;
1832
1889
} ) ;
1833
1890
1834
- symbols
1891
+ objects
1835
1892
}
1836
1893
1837
1894
/// Much simplified and explicit CLI for the NVPTX linker. The linker operates
0 commit comments