@@ -211,7 +211,7 @@ use rustc_hir as hir;
211211use rustc_hir:: def:: DefKind ;
212212use rustc_hir:: def_id:: { DefId , DefIdMap , LocalDefId } ;
213213use rustc_hir:: lang_items:: LangItem ;
214- use rustc_middle:: middle:: codegen_fn_attrs :: CodegenFnAttrFlags ;
214+ use rustc_middle:: middle:: exported_symbols :: ExportedSymbol ;
215215use rustc_middle:: mir:: interpret:: { AllocId , ErrorHandled , GlobalAlloc , Scalar } ;
216216use rustc_middle:: mir:: mono:: { InstantiationMode , MonoItem } ;
217217use rustc_middle:: mir:: visit:: Visitor as MirVisitor ;
@@ -225,6 +225,8 @@ use rustc_middle::ty::{
225225 TypeVisitableExt , VtblEntry ,
226226} ;
227227use rustc_middle:: ty:: { GenericArgKind , GenericArgs } ;
228+ use rustc_middle:: { middle:: codegen_fn_attrs:: CodegenFnAttrFlags } ;
229+ use rustc_session:: config:: CrateType ;
228230use rustc_session:: config:: EntryFnType ;
229231use rustc_session:: lint:: builtin:: LARGE_ASSIGNMENTS ;
230232use rustc_session:: Limit ;
@@ -1112,28 +1114,45 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
11121114 return true ;
11131115 } ;
11141116
1117+ let def_is_for_mir_only_rlib = if def_id. krate == rustc_hir:: def_id:: LOCAL_CRATE {
1118+ tcx. building_mir_only_rlib ( )
1119+ } else {
1120+ tcx. mir_only_crates ( ( ) ) . iter ( ) . any ( |c| * c == def_id. krate )
1121+ } ;
1122+
11151123 if tcx. is_foreign_item ( def_id) {
1116- // Foreign items are always linked against, there's no way of instantiating them.
1117- return false ;
1124+ if def_is_for_mir_only_rlib {
1125+ return tcx. is_mir_available ( instance. def_id ( ) ) ;
1126+ } else {
1127+ // Foreign items are always linked against, there's no way of instantiating them.
1128+ return false ;
1129+ }
1130+ }
1131+
1132+ if def_is_for_mir_only_rlib {
1133+ let has_mir = tcx. is_mir_available ( instance. def_id ( ) ) ;
1134+ return has_mir || matches ! ( tcx. def_kind( instance. def_id( ) ) , DefKind :: Static { .. } ) ;
11181135 }
11191136
11201137 if def_id. is_local ( ) {
11211138 // Local items cannot be referred to locally without monomorphizing them locally.
11221139 return true ;
11231140 }
11241141
1142+ if !def_is_for_mir_only_rlib {
1143+ if let DefKind :: Static { .. } = tcx. def_kind ( def_id) {
1144+ // We cannot monomorphize statics from upstream crates.
1145+ return false ;
1146+ }
1147+ }
1148+
11251149 if tcx. is_reachable_non_generic ( def_id)
11261150 || instance. polymorphize ( tcx) . upstream_monomorphization ( tcx) . is_some ( )
11271151 {
11281152 // We can link to the item in question, no instance needed in this crate.
11291153 return false ;
11301154 }
11311155
1132- if let DefKind :: Static { .. } = tcx. def_kind ( def_id) {
1133- // We cannot monomorphize statics from upstream crates.
1134- return false ;
1135- }
1136-
11371156 if !tcx. is_mir_available ( def_id) {
11381157 tcx. dcx ( ) . emit_fatal ( NoOptimizedMir {
11391158 span : tcx. def_span ( def_id) ,
@@ -1535,6 +1554,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionStrategy) -> Vec<MonoI
15351554 }
15361555
15371556 collector. push_extra_entry_roots ( ) ;
1557+ collector. push_extra_roots_from_mir_only_rlibs ( ) ;
15381558 }
15391559
15401560 // We can only codegen items that are instantiable - items all of
@@ -1669,6 +1689,50 @@ impl<'v> RootCollector<'_, 'v> {
16691689
16701690 self . output . push ( create_fn_mono_item ( self . tcx , start_instance, DUMMY_SP ) ) ;
16711691 }
1692+
1693+ fn push_extra_roots_from_mir_only_rlibs ( & mut self ) {
1694+ // An upstream extern function may be used anywhere in the dependency tree, so we
1695+ // cannot do any reachability analysis on them. We blindly monomorphize every
1696+ // extern function declared anywhere in our dependency tree. We must give them
1697+ // GloballyShared codegen because we don't know if the only call to an upstream
1698+ // extern function is also upstream: We don't have reachability information. All we
1699+ // can do is codegen all extern functions and pray for the linker to delete the
1700+ // ones that are reachable.
1701+ if !self . tcx . crate_types ( ) . iter ( ) . any ( |c| !matches ! ( c, CrateType :: Rlib ) ) {
1702+ return ;
1703+ }
1704+
1705+ for ( symbol, _info) in self
1706+ . tcx
1707+ . mir_only_crates ( ( ) )
1708+ . into_iter ( )
1709+ . flat_map ( |krate| self . tcx . exported_symbols ( * krate) )
1710+ {
1711+ let def_id = match symbol {
1712+ ExportedSymbol :: NonGeneric ( def_id) => def_id,
1713+ ExportedSymbol :: ThreadLocalShim ( def_id) => {
1714+ let item = MonoItem :: Fn ( Instance {
1715+ def : InstanceDef :: ThreadLocalShim ( * def_id) ,
1716+ args : GenericArgs :: empty ( ) ,
1717+ } ) ;
1718+ self . output . push ( dummy_spanned ( item) ) ;
1719+ continue ;
1720+ }
1721+ _ => continue ,
1722+ } ;
1723+ match self . tcx . def_kind ( def_id) {
1724+ DefKind :: Fn | DefKind :: AssocFn => {
1725+ let instance = Instance :: mono ( self . tcx , * def_id) ;
1726+ let item = create_fn_mono_item ( self . tcx , instance, DUMMY_SP ) ;
1727+ self . output . push ( item) ;
1728+ }
1729+ DefKind :: Static { .. } => {
1730+ self . output . push ( dummy_spanned ( MonoItem :: Static ( * def_id) ) ) ;
1731+ }
1732+ _ => { }
1733+ }
1734+ }
1735+ }
16721736}
16731737
16741738#[ instrument( level = "debug" , skip( tcx, output) ) ]
0 commit comments