@@ -214,6 +214,7 @@ use rustc_hir::def::DefKind;
214
214
use rustc_hir:: def_id:: { DefId , DefIdMap , LocalDefId } ;
215
215
use rustc_hir:: lang_items:: LangItem ;
216
216
use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
217
+ use rustc_middle:: middle:: exported_symbols:: ExportedSymbol ;
217
218
use rustc_middle:: mir:: interpret:: { AllocId , ErrorHandled , GlobalAlloc , Scalar } ;
218
219
use rustc_middle:: mir:: mono:: { InstantiationMode , MonoItem } ;
219
220
use rustc_middle:: mir:: visit:: Visitor as MirVisitor ;
@@ -229,7 +230,7 @@ use rustc_middle::ty::{
229
230
use rustc_middle:: util:: Providers ;
230
231
use rustc_middle:: { bug, span_bug} ;
231
232
use rustc_session:: Limit ;
232
- use rustc_session:: config:: EntryFnType ;
233
+ use rustc_session:: config:: { CrateType , EntryFnType } ;
233
234
use rustc_span:: source_map:: { Spanned , dummy_spanned, respan} ;
234
235
use rustc_span:: symbol:: sym;
235
236
use rustc_span:: { DUMMY_SP , Span } ;
@@ -926,28 +927,45 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxtAt<'tcx>, instance: Instance<'tcx>) -
926
927
return true ;
927
928
} ;
928
929
930
+ let def_is_for_mir_only_rlib = if def_id. krate == rustc_hir:: def_id:: LOCAL_CRATE {
931
+ tcx. building_mir_only_rlib ( )
932
+ } else {
933
+ tcx. mir_only_crates ( ( ) ) . iter ( ) . any ( |c| * c == def_id. krate )
934
+ } ;
935
+
929
936
if tcx. is_foreign_item ( def_id) {
930
- // Foreign items are always linked against, there's no way of instantiating them.
931
- return false ;
937
+ if def_is_for_mir_only_rlib {
938
+ return tcx. is_mir_available ( instance. def_id ( ) ) ;
939
+ } else {
940
+ // Foreign items are always linked against, there's no way of instantiating them.
941
+ return false ;
942
+ }
943
+ }
944
+
945
+ if def_is_for_mir_only_rlib {
946
+ let has_mir = tcx. is_mir_available ( instance. def_id ( ) ) ;
947
+ return has_mir || matches ! ( tcx. def_kind( instance. def_id( ) ) , DefKind :: Static { .. } ) ;
932
948
}
933
949
934
950
if def_id. is_local ( ) {
935
951
// Local items cannot be referred to locally without monomorphizing them locally.
936
952
return true ;
937
953
}
938
954
955
+ if !def_is_for_mir_only_rlib {
956
+ if let DefKind :: Static { .. } = tcx. def_kind ( def_id) {
957
+ // We cannot monomorphize statics from upstream crates.
958
+ return false ;
959
+ }
960
+ }
961
+
939
962
if tcx. is_reachable_non_generic ( def_id)
940
963
|| instance. polymorphize ( * tcx) . upstream_monomorphization ( * tcx) . is_some ( )
941
964
{
942
965
// We can link to the item in question, no instance needed in this crate.
943
966
return false ;
944
967
}
945
968
946
- if let DefKind :: Static { .. } = tcx. def_kind ( def_id) {
947
- // We cannot monomorphize statics from upstream crates.
948
- return false ;
949
- }
950
-
951
969
if !tcx. is_mir_available ( def_id) {
952
970
tcx. dcx ( ) . emit_fatal ( NoOptimizedMir {
953
971
span : tcx. def_span ( def_id) ,
@@ -1324,6 +1342,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionStrategy) -> Vec<MonoI
1324
1342
}
1325
1343
1326
1344
collector. push_extra_entry_roots ( ) ;
1345
+ collector. push_extra_roots_from_mir_only_rlibs ( ) ;
1327
1346
}
1328
1347
1329
1348
// We can only codegen items that are instantiable - items all of
@@ -1468,6 +1487,50 @@ impl<'v> RootCollector<'_, 'v> {
1468
1487
1469
1488
self . output . push ( create_fn_mono_item ( self . tcx , start_instance, DUMMY_SP ) ) ;
1470
1489
}
1490
+
1491
+ fn push_extra_roots_from_mir_only_rlibs ( & mut self ) {
1492
+ // An upstream extern function may be used anywhere in the dependency tree, so we
1493
+ // cannot do any reachability analysis on them. We blindly monomorphize every
1494
+ // extern function declared anywhere in our dependency tree. We must give them
1495
+ // GloballyShared codegen because we don't know if the only call to an upstream
1496
+ // extern function is also upstream: We don't have reachability information. All we
1497
+ // can do is codegen all extern functions and pray for the linker to delete the
1498
+ // ones that are reachable.
1499
+ if !self . tcx . crate_types ( ) . iter ( ) . any ( |c| !matches ! ( c, CrateType :: Rlib ) ) {
1500
+ return ;
1501
+ }
1502
+
1503
+ for ( symbol, _info) in self
1504
+ . tcx
1505
+ . mir_only_crates ( ( ) )
1506
+ . into_iter ( )
1507
+ . flat_map ( |krate| self . tcx . exported_symbols ( * krate) )
1508
+ {
1509
+ let def_id = match symbol {
1510
+ ExportedSymbol :: NonGeneric ( def_id) => def_id,
1511
+ ExportedSymbol :: ThreadLocalShim ( def_id) => {
1512
+ let item = MonoItem :: Fn ( Instance {
1513
+ def : InstanceKind :: ThreadLocalShim ( * def_id) ,
1514
+ args : GenericArgs :: empty ( ) ,
1515
+ } ) ;
1516
+ self . output . push ( dummy_spanned ( item) ) ;
1517
+ continue ;
1518
+ }
1519
+ _ => continue ,
1520
+ } ;
1521
+ match self . tcx . def_kind ( def_id) {
1522
+ DefKind :: Fn | DefKind :: AssocFn => {
1523
+ let instance = Instance :: mono ( self . tcx , * def_id) ;
1524
+ let item = create_fn_mono_item ( self . tcx , instance, DUMMY_SP ) ;
1525
+ self . output . push ( item) ;
1526
+ }
1527
+ DefKind :: Static { .. } => {
1528
+ self . output . push ( dummy_spanned ( MonoItem :: Static ( * def_id) ) ) ;
1529
+ }
1530
+ _ => { }
1531
+ }
1532
+ }
1533
+ }
1471
1534
}
1472
1535
1473
1536
#[ instrument( level = "debug" , skip( tcx, output) ) ]
0 commit comments