@@ -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 ;
@@ -975,27 +976,36 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
975
976
} ;
976
977
977
978
if tcx. is_foreign_item ( def_id) {
978
- // Foreign items are always linked against, there's no way of instantiating them.
979
- return false ;
979
+ if tcx. sess . opts . unstable_opts . mir_only_libs {
980
+ return tcx. is_mir_available ( instance. def_id ( ) ) ;
981
+ } else {
982
+ // Foreign items are always linked against, there's no way of instantiating them.
983
+ return false ;
984
+ }
985
+ }
986
+
987
+ if tcx. sess . opts . unstable_opts . mir_only_libs {
988
+ let has_mir = tcx. is_mir_available ( instance. def_id ( ) ) ;
989
+ return has_mir || matches ! ( tcx. def_kind( instance. def_id( ) ) , DefKind :: Static ( _) ) ;
980
990
}
981
991
982
992
if def_id. is_local ( ) {
983
993
// Local items cannot be referred to locally without monomorphizing them locally.
984
994
return true ;
985
995
}
986
996
997
+ if let DefKind :: Static ( _) = tcx. def_kind ( def_id) {
998
+ // We cannot monomorphize statics from upstream crates.
999
+ return false ;
1000
+ }
1001
+
987
1002
if tcx. is_reachable_non_generic ( def_id)
988
1003
|| instance. polymorphize ( tcx) . upstream_monomorphization ( tcx) . is_some ( )
989
1004
{
990
1005
// We can link to the item in question, no instance needed in this crate.
991
1006
return false ;
992
1007
}
993
1008
994
- if let DefKind :: Static ( _) = tcx. def_kind ( def_id) {
995
- // We cannot monomorphize statics from upstream crates.
996
- return false ;
997
- }
998
-
999
1009
if !tcx. is_mir_available ( def_id) {
1000
1010
tcx. dcx ( ) . emit_fatal ( NoOptimizedMir {
1001
1011
span : tcx. def_span ( def_id) ,
@@ -1295,6 +1305,38 @@ impl<'v> RootCollector<'_, 'v> {
1295
1305
. unwrap ( ) ;
1296
1306
1297
1307
self . output . push ( create_fn_mono_item ( self . tcx , start_instance, DUMMY_SP ) ) ;
1308
+
1309
+ // An upstream extern function may be used anywhere in the dependency tree, so we
1310
+ // cannot do any reachability analysis on them. We blindly monomorphize every
1311
+ // extern function declared anywhere in our dependency tree. We must give them
1312
+ // GloballyShared codegen because we don't know if the only call to an upstream
1313
+ // extern function is also upstream: We don't have reachability information. All we
1314
+ // can do is codegen all extern functions and pray for the linker to delete the
1315
+ // ones that are reachable.
1316
+ if self . tcx . building_mir_only_bin ( ) {
1317
+ for ( symbol, _info) in
1318
+ self . tcx . crates ( ( ) ) . into_iter ( ) . flat_map ( |krate| self . tcx . exported_symbols ( * krate) )
1319
+ {
1320
+ let def_id = match symbol {
1321
+ ExportedSymbol :: NonGeneric ( def_id) => def_id,
1322
+ _ => {
1323
+ eprintln ! ( "Not handling exported symbol {:?}" , symbol) ;
1324
+ continue ;
1325
+ }
1326
+ } ;
1327
+ if self . tcx . def_kind ( def_id) != DefKind :: Fn {
1328
+ eprintln ! ( "Not handling exported def {:?}" , def_id) ;
1329
+ continue ;
1330
+ }
1331
+ let instance = Instance :: mono ( self . tcx , * def_id) ;
1332
+ // FIXME: This is probably not the right span. What is?
1333
+ let item = create_fn_mono_item ( self . tcx , instance, DUMMY_SP ) ;
1334
+ // FIXME: Do we need this check?
1335
+ if !self . output . iter ( ) . any ( |out| out. node . def_id ( ) == * def_id) {
1336
+ self . output . push ( item) ;
1337
+ }
1338
+ }
1339
+ }
1298
1340
}
1299
1341
}
1300
1342
0 commit comments