@@ -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
@@ -1015,9 +1018,24 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
10151018 return true ;
10161019 } ;
10171020
1021+ let def_is_for_mir_only_rlib = if def_id. krate == rustc_hir:: def_id:: LOCAL_CRATE {
1022+ tcx. building_mir_only_rlib ( )
1023+ } else {
1024+ tcx. mir_only_crates ( ( ) ) . iter ( ) . any ( |c| * c == def_id. krate )
1025+ } ;
1026+
10181027 if tcx. is_foreign_item ( def_id) {
1019- // Foreign items are always linked against, there's no way of instantiating them.
1020- return false ;
1028+ if def_is_for_mir_only_rlib {
1029+ return tcx. is_mir_available ( instance. def_id ( ) ) ;
1030+ } else {
1031+ // Foreign items are always linked against, there's no way of instantiating them.
1032+ return false ;
1033+ }
1034+ }
1035+
1036+ if def_is_for_mir_only_rlib {
1037+ let has_mir = tcx. is_mir_available ( instance. def_id ( ) ) ;
1038+ return has_mir || matches ! ( tcx. def_kind( instance. def_id( ) ) , DefKind :: Static ( _) ) ;
10211039 }
10221040
10231041 if tcx. intrinsic ( def_id) . is_some_and ( |i| i. must_be_overridden ) {
@@ -1030,18 +1048,18 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
10301048 return true ;
10311049 }
10321050
1051+ if let DefKind :: Static ( _) = tcx. def_kind ( def_id) {
1052+ // We cannot monomorphize statics from upstream crates.
1053+ return false ;
1054+ }
1055+
10331056 if tcx. is_reachable_non_generic ( def_id)
10341057 || instance. polymorphize ( tcx) . upstream_monomorphization ( tcx) . is_some ( )
10351058 {
10361059 // We can link to the item in question, no instance needed in this crate.
10371060 return false ;
10381061 }
10391062
1040- if let DefKind :: Static ( _) = tcx. def_kind ( def_id) {
1041- // We cannot monomorphize statics from upstream crates.
1042- return false ;
1043- }
1044-
10451063 if !tcx. is_mir_available ( def_id) {
10461064 tcx. dcx ( ) . emit_fatal ( NoOptimizedMir {
10471065 span : tcx. def_span ( def_id) ,
@@ -1348,6 +1366,76 @@ impl<'v> RootCollector<'_, 'v> {
13481366
13491367 self . output . push ( create_fn_mono_item ( self . tcx , start_instance, DUMMY_SP ) ) ;
13501368 }
1369+
1370+ fn push_extra_roots_from_mir_only_rlibs ( & mut self ) {
1371+ // An upstream extern function may be used anywhere in the dependency tree, so we
1372+ // cannot do any reachability analysis on them. We blindly monomorphize every
1373+ // extern function declared anywhere in our dependency tree. We must give them
1374+ // GloballyShared codegen because we don't know if the only call to an upstream
1375+ // extern function is also upstream: We don't have reachability information. All we
1376+ // can do is codegen all extern functions and pray for the linker to delete the
1377+ // ones that are reachable.
1378+ if !self . tcx . crate_types ( ) . iter ( ) . any ( |c| !matches ! ( c, CrateType :: Rlib ) ) {
1379+ return ;
1380+ }
1381+
1382+ /*
1383+ eprintln!(
1384+ "Monomorphizing upstream crates for {:?}, {:?}",
1385+ self.tcx.crate_name(rustc_span::def_id::LOCAL_CRATE),
1386+ self.tcx.crate_types()
1387+ );
1388+ for krate in self.tcx.mir_only_crates(()) {
1389+ eprintln!("{:?}", self.tcx.crate_name(*krate));
1390+ }
1391+ */
1392+
1393+ for ( symbol, _info) in self
1394+ . tcx
1395+ . mir_only_crates ( ( ) )
1396+ . into_iter ( )
1397+ . filter ( |krate| {
1398+ if [ "alloc" , "core" , "std" ] . contains ( & self . tcx . crate_name ( * * krate) . as_str ( ) )
1399+ && self . tcx . crate_types ( ) == & [ CrateType :: ProcMacro ]
1400+ {
1401+ false
1402+ } else {
1403+ if self . tcx . crate_types ( ) == & [ CrateType :: ProcMacro ] {
1404+ eprintln ! ( "{:?}" , self . tcx. crate_name( * * krate) . as_str( ) ) ;
1405+ }
1406+ true
1407+ }
1408+ } )
1409+ . flat_map ( |krate| self . tcx . exported_symbols ( * krate) )
1410+ {
1411+ let def_id = match symbol {
1412+ ExportedSymbol :: NonGeneric ( def_id) => def_id,
1413+ ExportedSymbol :: ThreadLocalShim ( def_id) => {
1414+ //eprintln!("{:?}", def_id);
1415+ let item = MonoItem :: Fn ( Instance {
1416+ def : InstanceDef :: ThreadLocalShim ( * def_id) ,
1417+ args : GenericArgs :: empty ( ) ,
1418+ } ) ;
1419+ self . output . push ( dummy_spanned ( item) ) ;
1420+ continue ;
1421+ }
1422+ _ => continue ,
1423+ } ;
1424+ match self . tcx . def_kind ( def_id) {
1425+ DefKind :: Fn | DefKind :: AssocFn => {
1426+ //eprintln!("{:?}", def_id);
1427+ let instance = Instance :: mono ( self . tcx , * def_id) ;
1428+ let item = create_fn_mono_item ( self . tcx , instance, DUMMY_SP ) ;
1429+ self . output . push ( item) ;
1430+ }
1431+ DefKind :: Static ( _) => {
1432+ //eprintln!("{:?}", def_id);
1433+ self . output . push ( dummy_spanned ( MonoItem :: Static ( * def_id) ) ) ;
1434+ }
1435+ _ => { }
1436+ }
1437+ }
1438+ }
13511439}
13521440
13531441#[ instrument( level = "debug" , skip( tcx, output) ) ]
0 commit comments