@@ -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;
@@ -184,6 +185,7 @@ use rustc_middle::ty::{
184
185
};
185
186
use rustc_middle::ty::{GenericArgKind, GenericArgs};
186
187
use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
188
+ use rustc_session::config::CrateType;
187
189
use rustc_session::config::EntryFnType;
188
190
use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
189
191
use rustc_session::Limit;
@@ -316,6 +318,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
316
318
}
317
319
318
320
collector.push_extra_entry_roots();
321
+ collector.push_extra_roots_from_mir_only_rlibs();
319
322
}
320
323
321
324
// We can only codegen items that are instantiable - items all of
@@ -1025,28 +1028,45 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
1025
1028
return true;
1026
1029
};
1027
1030
1031
+ let def_is_for_mir_only_rlib = if def_id.krate == rustc_hir::def_id::LOCAL_CRATE {
1032
+ tcx.building_mir_only_rlib()
1033
+ } else {
1034
+ tcx.mir_only_crates(()).iter().any(|c| *c == def_id.krate)
1035
+ };
1036
+
1028
1037
if tcx.is_foreign_item(def_id) {
1029
- // Foreign items are always linked against, there's no way of instantiating them.
1030
- return false;
1038
+ if def_is_for_mir_only_rlib {
1039
+ return tcx.is_mir_available(instance.def_id());
1040
+ } else {
1041
+ // Foreign items are always linked against, there's no way of instantiating them.
1042
+ return false;
1043
+ }
1044
+ }
1045
+
1046
+ if def_is_for_mir_only_rlib {
1047
+ let has_mir = tcx.is_mir_available(instance.def_id());
1048
+ return has_mir || matches!(tcx.def_kind(instance.def_id()), DefKind::Static { .. });
1031
1049
}
1032
1050
1033
1051
if def_id.is_local() {
1034
1052
// Local items cannot be referred to locally without monomorphizing them locally.
1035
1053
return true;
1036
1054
}
1037
1055
1056
+ if !def_is_for_mir_only_rlib {
1057
+ if let DefKind::Static { .. } = tcx.def_kind(def_id) {
1058
+ // We cannot monomorphize statics from upstream crates.
1059
+ return false;
1060
+ }
1061
+ }
1062
+
1038
1063
if tcx.is_reachable_non_generic(def_id)
1039
1064
|| instance.polymorphize(tcx).upstream_monomorphization(tcx).is_some()
1040
1065
{
1041
1066
// We can link to the item in question, no instance needed in this crate.
1042
1067
return false;
1043
1068
}
1044
1069
1045
- if let DefKind::Static { .. } = tcx.def_kind(def_id) {
1046
- // We cannot monomorphize statics from upstream crates.
1047
- return false;
1048
- }
1049
-
1050
1070
if !tcx.is_mir_available(def_id) {
1051
1071
tcx.dcx().emit_fatal(NoOptimizedMir {
1052
1072
span: tcx.def_span(def_id),
@@ -1353,6 +1373,50 @@ impl<'v> RootCollector<'_, 'v> {
1353
1373
1354
1374
self.output.push(create_fn_mono_item(self.tcx, start_instance, DUMMY_SP));
1355
1375
}
1376
+
1377
+ fn push_extra_roots_from_mir_only_rlibs(&mut self) {
1378
+ // An upstream extern function may be used anywhere in the dependency tree, so we
1379
+ // cannot do any reachability analysis on them. We blindly monomorphize every
1380
+ // extern function declared anywhere in our dependency tree. We must give them
1381
+ // GloballyShared codegen because we don't know if the only call to an upstream
1382
+ // extern function is also upstream: We don't have reachability information. All we
1383
+ // can do is codegen all extern functions and pray for the linker to delete the
1384
+ // ones that are reachable.
1385
+ if !self.tcx.crate_types().iter().any(|c| !matches!(c, CrateType::Rlib)) {
1386
+ return;
1387
+ }
1388
+
1389
+ for (symbol, _info) in self
1390
+ .tcx
1391
+ .mir_only_crates(())
1392
+ .into_iter()
1393
+ .flat_map(|krate| self.tcx.exported_symbols(*krate))
1394
+ {
1395
+ let def_id = match symbol {
1396
+ ExportedSymbol::NonGeneric(def_id) => def_id,
1397
+ ExportedSymbol::ThreadLocalShim(def_id) => {
1398
+ let item = MonoItem::Fn(Instance {
1399
+ def: InstanceDef::ThreadLocalShim(*def_id),
1400
+ args: GenericArgs::empty(),
1401
+ });
1402
+ self.output.push(dummy_spanned(item));
1403
+ continue;
1404
+ }
1405
+ _ => continue,
1406
+ };
1407
+ match self.tcx.def_kind(def_id) {
1408
+ DefKind::Fn | DefKind::AssocFn => {
1409
+ let instance = Instance::mono(self.tcx, *def_id);
1410
+ let item = create_fn_mono_item(self.tcx, instance, DUMMY_SP);
1411
+ self.output.push(item);
1412
+ }
1413
+ DefKind::Static { .. } => {
1414
+ self.output.push(dummy_spanned(MonoItem::Static(*def_id)));
1415
+ }
1416
+ _ => {}
1417
+ }
1418
+ }
1419
+ }
1356
1420
}
1357
1421
1358
1422
#[instrument(level = "debug", skip(tcx, output))]
0 commit comments