@@ -211,7 +211,7 @@ use rustc_hir as hir;
211
211
use rustc_hir:: def:: DefKind ;
212
212
use rustc_hir:: def_id:: { DefId , DefIdMap , LocalDefId } ;
213
213
use rustc_hir:: lang_items:: LangItem ;
214
- use rustc_middle:: middle:: codegen_fn_attrs :: CodegenFnAttrFlags ;
214
+ use rustc_middle:: middle:: exported_symbols :: ExportedSymbol ;
215
215
use rustc_middle:: mir:: interpret:: { AllocId , ErrorHandled , GlobalAlloc , Scalar } ;
216
216
use rustc_middle:: mir:: mono:: { InstantiationMode , MonoItem } ;
217
217
use rustc_middle:: mir:: visit:: Visitor as MirVisitor ;
@@ -225,6 +225,8 @@ use rustc_middle::ty::{
225
225
TypeVisitableExt , VtblEntry ,
226
226
} ;
227
227
use rustc_middle:: ty:: { GenericArgKind , GenericArgs } ;
228
+ use rustc_middle:: { middle:: codegen_fn_attrs:: CodegenFnAttrFlags } ;
229
+ use rustc_session:: config:: CrateType ;
228
230
use rustc_session:: config:: EntryFnType ;
229
231
use rustc_session:: lint:: builtin:: LARGE_ASSIGNMENTS ;
230
232
use rustc_session:: Limit ;
@@ -1112,28 +1114,45 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
1112
1114
return true ;
1113
1115
} ;
1114
1116
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
+
1115
1123
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 { .. } ) ;
1118
1135
}
1119
1136
1120
1137
if def_id. is_local ( ) {
1121
1138
// Local items cannot be referred to locally without monomorphizing them locally.
1122
1139
return true ;
1123
1140
}
1124
1141
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
+
1125
1149
if tcx. is_reachable_non_generic ( def_id)
1126
1150
|| instance. polymorphize ( tcx) . upstream_monomorphization ( tcx) . is_some ( )
1127
1151
{
1128
1152
// We can link to the item in question, no instance needed in this crate.
1129
1153
return false ;
1130
1154
}
1131
1155
1132
- if let DefKind :: Static { .. } = tcx. def_kind ( def_id) {
1133
- // We cannot monomorphize statics from upstream crates.
1134
- return false ;
1135
- }
1136
-
1137
1156
if !tcx. is_mir_available ( def_id) {
1138
1157
tcx. dcx ( ) . emit_fatal ( NoOptimizedMir {
1139
1158
span : tcx. def_span ( def_id) ,
@@ -1535,6 +1554,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionStrategy) -> Vec<MonoI
1535
1554
}
1536
1555
1537
1556
collector. push_extra_entry_roots ( ) ;
1557
+ collector. push_extra_roots_from_mir_only_rlibs ( ) ;
1538
1558
}
1539
1559
1540
1560
// We can only codegen items that are instantiable - items all of
@@ -1669,6 +1689,50 @@ impl<'v> RootCollector<'_, 'v> {
1669
1689
1670
1690
self . output . push ( create_fn_mono_item ( self . tcx , start_instance, DUMMY_SP ) ) ;
1671
1691
}
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
+ }
1672
1736
}
1673
1737
1674
1738
#[ instrument( level = "debug" , skip( tcx, output) ) ]
0 commit comments