@@ -217,6 +217,7 @@ use rustc_hir::def::DefKind;
217217use rustc_hir:: def_id:: { DefId , DefIdMap , LocalDefId } ;
218218use rustc_hir:: lang_items:: LangItem ;
219219use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
220+ use rustc_middle:: middle:: exported_symbols:: ExportedSymbol ;
220221use rustc_middle:: mir:: interpret:: { AllocId , ErrorHandled , GlobalAlloc , Scalar } ;
221222use rustc_middle:: mir:: mono:: { InstantiationMode , MonoItem } ;
222223use rustc_middle:: mir:: visit:: Visitor as MirVisitor ;
@@ -232,7 +233,7 @@ use rustc_middle::ty::{
232233use rustc_middle:: util:: Providers ;
233234use rustc_middle:: { bug, span_bug} ;
234235use rustc_session:: Limit ;
235- use rustc_session:: config:: EntryFnType ;
236+ use rustc_session:: config:: { CrateType , EntryFnType } ;
236237use rustc_span:: source_map:: { Spanned , dummy_spanned, respan} ;
237238use rustc_span:: symbol:: { Ident , sym} ;
238239use rustc_span:: { DUMMY_SP , Span } ;
@@ -940,28 +941,45 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxtAt<'tcx>, instance: Instance<'tcx>) -
940941 return true ;
941942 } ;
942943
944+ let def_is_for_mir_only_rlib = if def_id. krate == rustc_hir:: def_id:: LOCAL_CRATE {
945+ tcx. building_mir_only_rlib ( )
946+ } else {
947+ tcx. mir_only_crates ( ( ) ) . iter ( ) . any ( |c| * c == def_id. krate )
948+ } ;
949+
943950 if tcx. is_foreign_item ( def_id) {
944- // Foreign items are always linked against, there's no way of instantiating them.
945- return false ;
951+ if def_is_for_mir_only_rlib {
952+ return tcx. is_mir_available ( instance. def_id ( ) ) ;
953+ } else {
954+ // Foreign items are always linked against, there's no way of instantiating them.
955+ return false ;
956+ }
957+ }
958+
959+ if def_is_for_mir_only_rlib {
960+ let has_mir = tcx. is_mir_available ( instance. def_id ( ) ) ;
961+ return has_mir || matches ! ( tcx. def_kind( instance. def_id( ) ) , DefKind :: Static { .. } ) ;
946962 }
947963
948964 if def_id. is_local ( ) {
949965 // Local items cannot be referred to locally without monomorphizing them locally.
950966 return true ;
951967 }
952968
969+ if !def_is_for_mir_only_rlib {
970+ if let DefKind :: Static { .. } = tcx. def_kind ( def_id) {
971+ // We cannot monomorphize statics from upstream crates.
972+ return false ;
973+ }
974+ }
975+
953976 if tcx. is_reachable_non_generic ( def_id)
954977 || instance. polymorphize ( * tcx) . upstream_monomorphization ( * tcx) . is_some ( )
955978 {
956979 // We can link to the item in question, no instance needed in this crate.
957980 return false ;
958981 }
959982
960- if let DefKind :: Static { .. } = tcx. def_kind ( def_id) {
961- // We cannot monomorphize statics from upstream crates.
962- return false ;
963- }
964-
965983 if !tcx. is_mir_available ( def_id) {
966984 tcx. dcx ( ) . emit_fatal ( NoOptimizedMir {
967985 span : tcx. def_span ( def_id) ,
@@ -1351,6 +1369,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionStrategy) -> Vec<MonoI
13511369 }
13521370
13531371 collector. push_extra_entry_roots ( ) ;
1372+ collector. push_extra_roots_from_mir_only_rlibs ( ) ;
13541373 }
13551374
13561375 // We can only codegen items that are instantiable - items all of
@@ -1495,6 +1514,50 @@ impl<'v> RootCollector<'_, 'v> {
14951514
14961515 self . output . push ( create_fn_mono_item ( self . tcx , start_instance, DUMMY_SP ) ) ;
14971516 }
1517+
1518+ fn push_extra_roots_from_mir_only_rlibs ( & mut self ) {
1519+ // An upstream extern function may be used anywhere in the dependency tree, so we
1520+ // cannot do any reachability analysis on them. We blindly monomorphize every
1521+ // extern function declared anywhere in our dependency tree. We must give them
1522+ // GloballyShared codegen because we don't know if the only call to an upstream
1523+ // extern function is also upstream: We don't have reachability information. All we
1524+ // can do is codegen all extern functions and pray for the linker to delete the
1525+ // ones that are reachable.
1526+ if !self . tcx . crate_types ( ) . iter ( ) . any ( |c| !matches ! ( c, CrateType :: Rlib ) ) {
1527+ return ;
1528+ }
1529+
1530+ for ( symbol, _info) in self
1531+ . tcx
1532+ . mir_only_crates ( ( ) )
1533+ . into_iter ( )
1534+ . flat_map ( |krate| self . tcx . exported_symbols ( * krate) )
1535+ {
1536+ let def_id = match symbol {
1537+ ExportedSymbol :: NonGeneric ( def_id) => def_id,
1538+ ExportedSymbol :: ThreadLocalShim ( def_id) => {
1539+ let item = MonoItem :: Fn ( Instance {
1540+ def : InstanceKind :: ThreadLocalShim ( * def_id) ,
1541+ args : GenericArgs :: empty ( ) ,
1542+ } ) ;
1543+ self . output . push ( dummy_spanned ( item) ) ;
1544+ continue ;
1545+ }
1546+ _ => continue ,
1547+ } ;
1548+ match self . tcx . def_kind ( def_id) {
1549+ DefKind :: Fn | DefKind :: AssocFn => {
1550+ let instance = Instance :: mono ( self . tcx , * def_id) ;
1551+ let item = create_fn_mono_item ( self . tcx , instance, DUMMY_SP ) ;
1552+ self . output . push ( item) ;
1553+ }
1554+ DefKind :: Static { .. } => {
1555+ self . output . push ( dummy_spanned ( MonoItem :: Static ( * def_id) ) ) ;
1556+ }
1557+ _ => { }
1558+ }
1559+ }
1560+ }
14981561}
14991562
15001563#[ instrument( level = "debug" , skip( tcx, output) ) ]
0 commit comments