@@ -170,6 +170,7 @@ use rustc_hir as hir;
170170use  rustc_hir:: def:: DefKind ; 
171171use  rustc_hir:: def_id:: { DefId ,  DefIdMap ,  LocalDefId } ; 
172172use  rustc_hir:: lang_items:: LangItem ; 
173+ use  rustc_middle:: middle:: exported_symbols:: ExportedSymbol ; 
173174use  rustc_middle:: mir:: interpret:: { AllocId ,  ErrorHandled ,  GlobalAlloc ,  Scalar } ; 
174175use  rustc_middle:: mir:: mono:: { InstantiationMode ,  MonoItem } ; 
175176use  rustc_middle:: mir:: visit:: Visitor  as  MirVisitor ; 
@@ -184,6 +185,7 @@ use rustc_middle::ty::{
184185} ; 
185186use  rustc_middle:: ty:: { GenericArgKind ,  GenericArgs } ; 
186187use  rustc_middle:: { middle:: codegen_fn_attrs:: CodegenFnAttrFlags ,  mir:: visit:: TyContext } ; 
188+ use  rustc_session:: config:: CrateType ; 
187189use  rustc_session:: config:: EntryFnType ; 
188190use  rustc_session:: lint:: builtin:: LARGE_ASSIGNMENTS ; 
189191use  rustc_session:: Limit ; 
@@ -316,6 +318,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
316318        } 
317319
318320        collector. push_extra_entry_roots ( ) ; 
321+         collector. push_extra_roots_from_mir_only_rlibs ( ) ; 
319322    } 
320323
321324    // We can only codegen items that are instantiable - items all of 
@@ -1025,28 +1028,45 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
10251028        return  true ; 
10261029    } ; 
10271030
1031+     let  def_is_for_mir_only_rlib = if  def_id. krate  == rustc_hir:: def_id:: LOCAL_CRATE  { 
1032+         tcx. building_mir_only_rlib ( ) 
1033+     }  else  { 
1034+         tcx. mir_only_crates ( ( ) ) . iter ( ) . any ( |c| * c == def_id. krate ) 
1035+     } ; 
1036+ 
10281037    if  tcx. is_foreign_item ( def_id)  { 
1029-         // Foreign items are always linked against, there's no way of instantiating them. 
1030-         return  false ; 
1038+         if  def_is_for_mir_only_rlib { 
1039+             return  tcx. is_mir_available ( instance. def_id ( ) ) ; 
1040+         }  else  { 
1041+             // Foreign items are always linked against, there's no way of instantiating them. 
1042+             return  false ; 
1043+         } 
1044+     } 
1045+ 
1046+     if  def_is_for_mir_only_rlib { 
1047+         let  has_mir = tcx. is_mir_available ( instance. def_id ( ) ) ; 
1048+         return  has_mir || matches ! ( tcx. def_kind( instance. def_id( ) ) ,  DefKind :: Static  {  .. } ) ; 
10311049    } 
10321050
10331051    if  def_id. is_local ( )  { 
10341052        // Local items cannot be referred to locally without monomorphizing them locally. 
10351053        return  true ; 
10361054    } 
10371055
1056+     if  !def_is_for_mir_only_rlib { 
1057+         if  let  DefKind :: Static  {  .. }  = tcx. def_kind ( def_id)  { 
1058+             // We cannot monomorphize statics from upstream crates. 
1059+             return  false ; 
1060+         } 
1061+     } 
1062+ 
10381063    if  tcx. is_reachable_non_generic ( def_id) 
10391064        || instance. polymorphize ( tcx) . upstream_monomorphization ( tcx) . is_some ( ) 
10401065    { 
10411066        // We can link to the item in question, no instance needed in this crate. 
10421067        return  false ; 
10431068    } 
10441069
1045-     if  let  DefKind :: Static  {  .. }  = tcx. def_kind ( def_id)  { 
1046-         // We cannot monomorphize statics from upstream crates. 
1047-         return  false ; 
1048-     } 
1049- 
10501070    if  !tcx. is_mir_available ( def_id)  { 
10511071        tcx. dcx ( ) . emit_fatal ( NoOptimizedMir  { 
10521072            span :  tcx. def_span ( def_id) , 
@@ -1353,6 +1373,50 @@ impl<'v> RootCollector<'_, 'v> {
13531373
13541374        self . output . push ( create_fn_mono_item ( self . tcx ,  start_instance,  DUMMY_SP ) ) ; 
13551375    } 
1376+ 
1377+     fn  push_extra_roots_from_mir_only_rlibs ( & mut  self )  { 
1378+         // An upstream extern function may be used anywhere in the dependency tree, so we 
1379+         // cannot do any reachability analysis on them. We blindly monomorphize every 
1380+         // extern function declared anywhere in our dependency tree. We must give them 
1381+         // GloballyShared codegen because we don't know if the only call to an upstream 
1382+         // extern function is also upstream: We don't have reachability information. All we 
1383+         // can do is codegen all extern functions and pray for the linker to delete the 
1384+         // ones that are reachable. 
1385+         if  !self . tcx . crate_types ( ) . iter ( ) . any ( |c| !matches ! ( c,  CrateType :: Rlib ) )  { 
1386+             return ; 
1387+         } 
1388+ 
1389+         for  ( symbol,  _info)  in  self 
1390+             . tcx 
1391+             . mir_only_crates ( ( ) ) 
1392+             . into_iter ( ) 
1393+             . flat_map ( |krate| self . tcx . exported_symbols ( * krate) ) 
1394+         { 
1395+             let  def_id = match  symbol { 
1396+                 ExportedSymbol :: NonGeneric ( def_id)  => def_id, 
1397+                 ExportedSymbol :: ThreadLocalShim ( def_id)  => { 
1398+                     let  item = MonoItem :: Fn ( Instance  { 
1399+                         def :  InstanceDef :: ThreadLocalShim ( * def_id) , 
1400+                         args :  GenericArgs :: empty ( ) , 
1401+                     } ) ; 
1402+                     self . output . push ( dummy_spanned ( item) ) ; 
1403+                     continue ; 
1404+                 } 
1405+                 _ => continue , 
1406+             } ; 
1407+             match  self . tcx . def_kind ( def_id)  { 
1408+                 DefKind :: Fn  | DefKind :: AssocFn  => { 
1409+                     let  instance = Instance :: mono ( self . tcx ,  * def_id) ; 
1410+                     let  item = create_fn_mono_item ( self . tcx ,  instance,  DUMMY_SP ) ; 
1411+                     self . output . push ( item) ; 
1412+                 } 
1413+                 DefKind :: Static  {  .. }  => { 
1414+                     self . output . push ( dummy_spanned ( MonoItem :: Static ( * def_id) ) ) ; 
1415+                 } 
1416+                 _ => { } 
1417+             } 
1418+         } 
1419+     } 
13561420} 
13571421
13581422#[ instrument( level = "debug" ,  skip( tcx,  output) ) ]  
0 commit comments