@@ -170,6 +170,7 @@ use rustc_hir as hir;
170
170
use rustc_hir:: def:: DefKind ;
171
171
use rustc_hir:: def_id:: { DefId , DefIdMap , LocalDefId } ;
172
172
use rustc_hir:: lang_items:: LangItem ;
173
+ use rustc_middle:: middle:: exported_symbols:: ExportedSymbol ;
173
174
use rustc_middle:: mir:: interpret:: { AllocId , ErrorHandled , GlobalAlloc , Scalar } ;
174
175
use rustc_middle:: mir:: mono:: { InstantiationMode , MonoItem } ;
175
176
use rustc_middle:: mir:: visit:: Visitor as MirVisitor ;
@@ -184,6 +185,7 @@ use rustc_middle::ty::{
184
185
} ;
185
186
use rustc_middle:: ty:: { GenericArgKind , GenericArgs } ;
186
187
use rustc_middle:: { middle:: codegen_fn_attrs:: CodegenFnAttrFlags , mir:: visit:: TyContext } ;
188
+ use rustc_session:: config:: CrateType ;
187
189
use rustc_session:: config:: EntryFnType ;
188
190
use rustc_session:: lint:: builtin:: LARGE_ASSIGNMENTS ;
189
191
use rustc_session:: Limit ;
@@ -316,6 +318,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
316
318
}
317
319
318
320
collector. push_extra_entry_roots ( ) ;
321
+ collector. push_extra_roots_from_mir_only_rlibs ( ) ;
319
322
}
320
323
321
324
// We can only codegen items that are instantiable - items all of
@@ -1025,9 +1028,24 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
1025
1028
return true ;
1026
1029
} ;
1027
1030
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
+
1028
1037
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 { .. } ) ;
1031
1049
}
1032
1050
1033
1051
if tcx. intrinsic ( def_id) . is_some_and ( |i| i. must_be_overridden ) {
@@ -1040,18 +1058,20 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
1040
1058
return true ;
1041
1059
}
1042
1060
1061
+ if !def_is_for_mir_only_rlib {
1062
+ if let DefKind :: Static { .. } = tcx. def_kind ( def_id) {
1063
+ // We cannot monomorphize statics from upstream crates.
1064
+ return false ;
1065
+ }
1066
+ }
1067
+
1043
1068
if tcx. is_reachable_non_generic ( def_id)
1044
1069
|| instance. polymorphize ( tcx) . upstream_monomorphization ( tcx) . is_some ( )
1045
1070
{
1046
1071
// We can link to the item in question, no instance needed in this crate.
1047
1072
return false ;
1048
1073
}
1049
1074
1050
- if let DefKind :: Static { .. } = tcx. def_kind ( def_id) {
1051
- // We cannot monomorphize statics from upstream crates.
1052
- return false ;
1053
- }
1054
-
1055
1075
if !tcx. is_mir_available ( def_id) {
1056
1076
tcx. dcx ( ) . emit_fatal ( NoOptimizedMir {
1057
1077
span : tcx. def_span ( def_id) ,
@@ -1358,6 +1378,76 @@ impl<'v> RootCollector<'_, 'v> {
1358
1378
1359
1379
self . output . push ( create_fn_mono_item ( self . tcx , start_instance, DUMMY_SP ) ) ;
1360
1380
}
1381
+
1382
+ fn push_extra_roots_from_mir_only_rlibs ( & mut self ) {
1383
+ // An upstream extern function may be used anywhere in the dependency tree, so we
1384
+ // cannot do any reachability analysis on them. We blindly monomorphize every
1385
+ // extern function declared anywhere in our dependency tree. We must give them
1386
+ // GloballyShared codegen because we don't know if the only call to an upstream
1387
+ // extern function is also upstream: We don't have reachability information. All we
1388
+ // can do is codegen all extern functions and pray for the linker to delete the
1389
+ // ones that are reachable.
1390
+ if !self . tcx . crate_types ( ) . iter ( ) . any ( |c| !matches ! ( c, CrateType :: Rlib ) ) {
1391
+ return ;
1392
+ }
1393
+
1394
+ /*
1395
+ eprintln!(
1396
+ "Monomorphizing upstream crates for {:?}, {:?}",
1397
+ self.tcx.crate_name(rustc_span::def_id::LOCAL_CRATE),
1398
+ self.tcx.crate_types()
1399
+ );
1400
+ for krate in self.tcx.mir_only_crates(()) {
1401
+ eprintln!("{:?}", self.tcx.crate_name(*krate));
1402
+ }
1403
+ */
1404
+
1405
+ for ( symbol, _info) in self
1406
+ . tcx
1407
+ . mir_only_crates ( ( ) )
1408
+ . into_iter ( )
1409
+ . filter ( |krate| {
1410
+ if [ "alloc" , "core" , "std" ] . contains ( & self . tcx . crate_name ( * * krate) . as_str ( ) )
1411
+ && self . tcx . crate_types ( ) == & [ CrateType :: ProcMacro ]
1412
+ {
1413
+ false
1414
+ } else {
1415
+ if self . tcx . crate_types ( ) == & [ CrateType :: ProcMacro ] {
1416
+ eprintln ! ( "{:?}" , self . tcx. crate_name( * * krate) . as_str( ) ) ;
1417
+ }
1418
+ true
1419
+ }
1420
+ } )
1421
+ . flat_map ( |krate| self . tcx . exported_symbols ( * krate) )
1422
+ {
1423
+ let def_id = match symbol {
1424
+ ExportedSymbol :: NonGeneric ( def_id) => def_id,
1425
+ ExportedSymbol :: ThreadLocalShim ( def_id) => {
1426
+ //eprintln!("{:?}", def_id);
1427
+ let item = MonoItem :: Fn ( Instance {
1428
+ def : InstanceDef :: ThreadLocalShim ( * def_id) ,
1429
+ args : GenericArgs :: empty ( ) ,
1430
+ } ) ;
1431
+ self . output . push ( dummy_spanned ( item) ) ;
1432
+ continue ;
1433
+ }
1434
+ _ => continue ,
1435
+ } ;
1436
+ match self . tcx . def_kind ( def_id) {
1437
+ DefKind :: Fn | DefKind :: AssocFn => {
1438
+ //eprintln!("{:?}", def_id);
1439
+ let instance = Instance :: mono ( self . tcx , * def_id) ;
1440
+ let item = create_fn_mono_item ( self . tcx , instance, DUMMY_SP ) ;
1441
+ self . output . push ( item) ;
1442
+ }
1443
+ DefKind :: Static { .. } => {
1444
+ //eprintln!("{:?}", def_id);
1445
+ self . output . push ( dummy_spanned ( MonoItem :: Static ( * def_id) ) ) ;
1446
+ }
1447
+ _ => { }
1448
+ }
1449
+ }
1450
+ }
1361
1451
}
1362
1452
1363
1453
#[ instrument( level = "debug" , skip( tcx, output) ) ]
0 commit comments