@@ -215,6 +215,7 @@ use rustc_hir::def::DefKind;
215
215
use rustc_hir:: def_id:: { DefId , DefIdMap , LocalDefId } ;
216
216
use rustc_hir:: lang_items:: LangItem ;
217
217
use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
218
+ use rustc_middle:: middle:: exported_symbols:: ExportedSymbol ;
218
219
use rustc_middle:: mir:: interpret:: { AllocId , ErrorHandled , GlobalAlloc , Scalar } ;
219
220
use rustc_middle:: mir:: mono:: { CollectionMode , InstantiationMode , MonoItem } ;
220
221
use rustc_middle:: mir:: visit:: Visitor as MirVisitor ;
@@ -230,7 +231,7 @@ use rustc_middle::ty::{
230
231
use rustc_middle:: util:: Providers ;
231
232
use rustc_middle:: { bug, span_bug} ;
232
233
use rustc_session:: Limit ;
233
- use rustc_session:: config:: EntryFnType ;
234
+ use rustc_session:: config:: { CrateType , EntryFnType } ;
234
235
use rustc_span:: source_map:: { Spanned , dummy_spanned, respan} ;
235
236
use rustc_span:: symbol:: sym;
236
237
use rustc_span:: { DUMMY_SP , Span } ;
@@ -955,23 +956,40 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxtAt<'tcx>, instance: Instance<'tcx>) -
955
956
return true ;
956
957
} ;
957
958
959
+ let def_is_for_mir_only_rlib = if def_id. krate == rustc_hir:: def_id:: LOCAL_CRATE {
960
+ tcx. building_mir_only_rlib ( )
961
+ } else {
962
+ tcx. mir_only_crates ( ( ) ) . iter ( ) . any ( |c| * c == def_id. krate )
963
+ } ;
964
+
958
965
if tcx. is_foreign_item ( def_id) {
959
- // Foreign items are always linked against, there's no way of instantiating them.
960
- return false ;
966
+ if def_is_for_mir_only_rlib {
967
+ return tcx. is_mir_available ( instance. def_id ( ) ) ;
968
+ } else {
969
+ // Foreign items are always linked against, there's no way of instantiating them.
970
+ return false ;
971
+ }
972
+ }
973
+
974
+ if def_is_for_mir_only_rlib {
975
+ let has_mir = tcx. is_mir_available ( instance. def_id ( ) ) ;
976
+ return has_mir || matches ! ( tcx. def_kind( instance. def_id( ) ) , DefKind :: Static { .. } ) ;
961
977
}
962
978
963
979
if def_id. is_local ( ) {
964
980
// Local items cannot be referred to locally without monomorphizing them locally.
965
981
return true ;
966
982
}
967
983
968
- if tcx. is_reachable_non_generic ( def_id) || instance. upstream_monomorphization ( * tcx) . is_some ( ) {
969
- // We can link to the item in question, no instance needed in this crate.
970
- return false ;
984
+ if !def_is_for_mir_only_rlib {
985
+ if let DefKind :: Static { .. } = tcx. def_kind ( def_id) {
986
+ // We cannot monomorphize statics from upstream crates.
987
+ return false ;
988
+ }
971
989
}
972
990
973
- if let DefKind :: Static { .. } = tcx. def_kind ( def_id ) {
974
- // We cannot monomorphize statics from upstream crates .
991
+ if tcx . is_reachable_non_generic ( def_id ) || instance . upstream_monomorphization ( * tcx) . is_some ( ) {
992
+ // We can link to the item in question, no instance needed in this crate .
975
993
return false ;
976
994
}
977
995
@@ -1370,6 +1388,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionStrategy) -> Vec<MonoI
1370
1388
}
1371
1389
1372
1390
collector. push_extra_entry_roots ( ) ;
1391
+ collector. push_extra_roots_from_mir_only_rlibs ( ) ;
1373
1392
}
1374
1393
1375
1394
// We can only codegen items that are instantiable - items all of
@@ -1514,6 +1533,50 @@ impl<'v> RootCollector<'_, 'v> {
1514
1533
1515
1534
self . output . push ( create_fn_mono_item ( self . tcx , start_instance, DUMMY_SP ) ) ;
1516
1535
}
1536
+
1537
+ fn push_extra_roots_from_mir_only_rlibs ( & mut self ) {
1538
+ // An upstream extern function may be used anywhere in the dependency tree, so we
1539
+ // cannot do any reachability analysis on them. We blindly monomorphize every
1540
+ // extern function declared anywhere in our dependency tree. We must give them
1541
+ // GloballyShared codegen because we don't know if the only call to an upstream
1542
+ // extern function is also upstream: We don't have reachability information. All we
1543
+ // can do is codegen all extern functions and pray for the linker to delete the
1544
+ // ones that are reachable.
1545
+ if !self . tcx . crate_types ( ) . iter ( ) . any ( |c| !matches ! ( c, CrateType :: Rlib ) ) {
1546
+ return ;
1547
+ }
1548
+
1549
+ for ( symbol, _info) in self
1550
+ . tcx
1551
+ . mir_only_crates ( ( ) )
1552
+ . into_iter ( )
1553
+ . flat_map ( |krate| self . tcx . exported_symbols ( * krate) )
1554
+ {
1555
+ let def_id = match symbol {
1556
+ ExportedSymbol :: NonGeneric ( def_id) => def_id,
1557
+ ExportedSymbol :: ThreadLocalShim ( def_id) => {
1558
+ let item = MonoItem :: Fn ( Instance {
1559
+ def : InstanceKind :: ThreadLocalShim ( * def_id) ,
1560
+ args : GenericArgs :: empty ( ) ,
1561
+ } ) ;
1562
+ self . output . push ( dummy_spanned ( item) ) ;
1563
+ continue ;
1564
+ }
1565
+ _ => continue ,
1566
+ } ;
1567
+ match self . tcx . def_kind ( def_id) {
1568
+ DefKind :: Fn | DefKind :: AssocFn => {
1569
+ let instance = Instance :: mono ( self . tcx , * def_id) ;
1570
+ let item = create_fn_mono_item ( self . tcx , instance, DUMMY_SP ) ;
1571
+ self . output . push ( item) ;
1572
+ }
1573
+ DefKind :: Static { .. } => {
1574
+ self . output . push ( dummy_spanned ( MonoItem :: Static ( * def_id) ) ) ;
1575
+ }
1576
+ _ => { }
1577
+ }
1578
+ }
1579
+ }
1517
1580
}
1518
1581
1519
1582
#[ instrument( level = "debug" , skip( tcx, output) ) ]
0 commit comments