@@ -170,6 +170,7 @@ use rustc_hir as hir;
170170use rustc_hir:: def:: DefKind ;
171171use rustc_hir:: def_id:: { DefId , DefIdMap , LocalDefId } ;
172172use rustc_hir:: lang_items:: LangItem ;
173+ use rustc_middle:: middle:: exported_symbols:: ExportedSymbol ;
173174use rustc_middle:: mir:: interpret:: { AllocId , ErrorHandled , GlobalAlloc , Scalar } ;
174175use rustc_middle:: mir:: mono:: { InstantiationMode , MonoItem } ;
175176use rustc_middle:: mir:: visit:: Visitor as MirVisitor ;
@@ -975,27 +976,36 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
975976 } ;
976977
977978 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 ( _) ) ;
980990 }
981991
982992 if def_id. is_local ( ) {
983993 // Local items cannot be referred to locally without monomorphizing them locally.
984994 return true ;
985995 }
986996
997+ if let DefKind :: Static ( _) = tcx. def_kind ( def_id) {
998+ // We cannot monomorphize statics from upstream crates.
999+ return false ;
1000+ }
1001+
9871002 if tcx. is_reachable_non_generic ( def_id)
9881003 || instance. polymorphize ( tcx) . upstream_monomorphization ( tcx) . is_some ( )
9891004 {
9901005 // We can link to the item in question, no instance needed in this crate.
9911006 return false ;
9921007 }
9931008
994- if let DefKind :: Static ( _) = tcx. def_kind ( def_id) {
995- // We cannot monomorphize statics from upstream crates.
996- return false ;
997- }
998-
9991009 if !tcx. is_mir_available ( def_id) {
10001010 tcx. dcx ( ) . emit_fatal ( NoOptimizedMir {
10011011 span : tcx. def_span ( def_id) ,
@@ -1295,6 +1305,36 @@ impl<'v> RootCollector<'_, 'v> {
12951305 . unwrap ( ) ;
12961306
12971307 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+ continue ;
1324+ }
1325+ } ;
1326+ if self . tcx . def_kind ( def_id) != DefKind :: Fn {
1327+ continue ;
1328+ }
1329+ let instance = Instance :: mono ( self . tcx , * def_id) ;
1330+ // FIXME: This is probably not the right span. What is?
1331+ let item = create_fn_mono_item ( self . tcx , instance, DUMMY_SP ) ;
1332+ // FIXME: Do we need this check?
1333+ if !self . output . iter ( ) . any ( |out| out. node . def_id ( ) == * def_id) {
1334+ self . output . push ( item) ;
1335+ }
1336+ }
1337+ }
12981338 }
12991339}
13001340
0 commit comments