@@ -217,6 +217,7 @@ use rustc_hir::def::DefKind;
217
217
use rustc_hir:: def_id:: { DefId , DefIdMap , LocalDefId } ;
218
218
use rustc_hir:: lang_items:: LangItem ;
219
219
use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
220
+ use rustc_middle:: middle:: exported_symbols:: ExportedSymbol ;
220
221
use rustc_middle:: mir:: interpret:: { AllocId , ErrorHandled , GlobalAlloc , Scalar } ;
221
222
use rustc_middle:: mir:: mono:: { InstantiationMode , MonoItem } ;
222
223
use rustc_middle:: mir:: visit:: Visitor as MirVisitor ;
@@ -232,7 +233,7 @@ use rustc_middle::ty::{
232
233
use rustc_middle:: util:: Providers ;
233
234
use rustc_middle:: { bug, span_bug} ;
234
235
use rustc_session:: Limit ;
235
- use rustc_session:: config:: EntryFnType ;
236
+ use rustc_session:: config:: { CrateType , EntryFnType } ;
236
237
use rustc_span:: source_map:: { Spanned , dummy_spanned, respan} ;
237
238
use rustc_span:: symbol:: { Ident , sym} ;
238
239
use rustc_span:: { DUMMY_SP , Span } ;
@@ -940,28 +941,45 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxtAt<'tcx>, instance: Instance<'tcx>) -
940
941
return true ;
941
942
} ;
942
943
944
+ let def_is_for_mir_only_rlib = if def_id. krate == rustc_hir:: def_id:: LOCAL_CRATE {
945
+ tcx. building_mir_only_rlib ( )
946
+ } else {
947
+ tcx. mir_only_crates ( ( ) ) . iter ( ) . any ( |c| * c == def_id. krate )
948
+ } ;
949
+
943
950
if tcx. is_foreign_item ( def_id) {
944
- // Foreign items are always linked against, there's no way of instantiating them.
945
- return false ;
951
+ if def_is_for_mir_only_rlib {
952
+ return tcx. is_mir_available ( instance. def_id ( ) ) ;
953
+ } else {
954
+ // Foreign items are always linked against, there's no way of instantiating them.
955
+ return false ;
956
+ }
957
+ }
958
+
959
+ if def_is_for_mir_only_rlib {
960
+ let has_mir = tcx. is_mir_available ( instance. def_id ( ) ) ;
961
+ return has_mir || matches ! ( tcx. def_kind( instance. def_id( ) ) , DefKind :: Static { .. } ) ;
946
962
}
947
963
948
964
if def_id. is_local ( ) {
949
965
// Local items cannot be referred to locally without monomorphizing them locally.
950
966
return true ;
951
967
}
952
968
969
+ if !def_is_for_mir_only_rlib {
970
+ if let DefKind :: Static { .. } = tcx. def_kind ( def_id) {
971
+ // We cannot monomorphize statics from upstream crates.
972
+ return false ;
973
+ }
974
+ }
975
+
953
976
if tcx. is_reachable_non_generic ( def_id)
954
977
|| instance. polymorphize ( * tcx) . upstream_monomorphization ( * tcx) . is_some ( )
955
978
{
956
979
// We can link to the item in question, no instance needed in this crate.
957
980
return false ;
958
981
}
959
982
960
- if let DefKind :: Static { .. } = tcx. def_kind ( def_id) {
961
- // We cannot monomorphize statics from upstream crates.
962
- return false ;
963
- }
964
-
965
983
if !tcx. is_mir_available ( def_id) {
966
984
tcx. dcx ( ) . emit_fatal ( NoOptimizedMir {
967
985
span : tcx. def_span ( def_id) ,
@@ -1351,6 +1369,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionStrategy) -> Vec<MonoI
1351
1369
}
1352
1370
1353
1371
collector. push_extra_entry_roots ( ) ;
1372
+ collector. push_extra_roots_from_mir_only_rlibs ( ) ;
1354
1373
}
1355
1374
1356
1375
// We can only codegen items that are instantiable - items all of
@@ -1495,6 +1514,50 @@ impl<'v> RootCollector<'_, 'v> {
1495
1514
1496
1515
self . output . push ( create_fn_mono_item ( self . tcx , start_instance, DUMMY_SP ) ) ;
1497
1516
}
1517
+
1518
+ fn push_extra_roots_from_mir_only_rlibs ( & mut self ) {
1519
+ // An upstream extern function may be used anywhere in the dependency tree, so we
1520
+ // cannot do any reachability analysis on them. We blindly monomorphize every
1521
+ // extern function declared anywhere in our dependency tree. We must give them
1522
+ // GloballyShared codegen because we don't know if the only call to an upstream
1523
+ // extern function is also upstream: We don't have reachability information. All we
1524
+ // can do is codegen all extern functions and pray for the linker to delete the
1525
+ // ones that are reachable.
1526
+ if !self . tcx . crate_types ( ) . iter ( ) . any ( |c| !matches ! ( c, CrateType :: Rlib ) ) {
1527
+ return ;
1528
+ }
1529
+
1530
+ for ( symbol, _info) in self
1531
+ . tcx
1532
+ . mir_only_crates ( ( ) )
1533
+ . into_iter ( )
1534
+ . flat_map ( |krate| self . tcx . exported_symbols ( * krate) )
1535
+ {
1536
+ let def_id = match symbol {
1537
+ ExportedSymbol :: NonGeneric ( def_id) => def_id,
1538
+ ExportedSymbol :: ThreadLocalShim ( def_id) => {
1539
+ let item = MonoItem :: Fn ( Instance {
1540
+ def : InstanceKind :: ThreadLocalShim ( * def_id) ,
1541
+ args : GenericArgs :: empty ( ) ,
1542
+ } ) ;
1543
+ self . output . push ( dummy_spanned ( item) ) ;
1544
+ continue ;
1545
+ }
1546
+ _ => continue ,
1547
+ } ;
1548
+ match self . tcx . def_kind ( def_id) {
1549
+ DefKind :: Fn | DefKind :: AssocFn => {
1550
+ let instance = Instance :: mono ( self . tcx , * def_id) ;
1551
+ let item = create_fn_mono_item ( self . tcx , instance, DUMMY_SP ) ;
1552
+ self . output . push ( item) ;
1553
+ }
1554
+ DefKind :: Static { .. } => {
1555
+ self . output . push ( dummy_spanned ( MonoItem :: Static ( * def_id) ) ) ;
1556
+ }
1557
+ _ => { }
1558
+ }
1559
+ }
1560
+ }
1498
1561
}
1499
1562
1500
1563
#[ instrument( level = "debug" , skip( tcx, output) ) ]
0 commit comments