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