Skip to content

Commit 071bac7

Browse files
committed
Auto merge of #127779 - momvart:should_codegen_hook, r=<try>
Add a hook for `should_codegen_locally` This PR lifts the module-local function `should_codegen_locally` to `TyCtxt` as a hook. In addition to monomorphization, this function is used for checking the dependency of `compiler_builtins` on other libraries. Moving this function to the hooks also makes overriding it possible for the tools that use the rustc interface.
2 parents ff4b398 + 9b80250 commit 071bac7

File tree

9 files changed

+62
-58
lines changed

9 files changed

+62
-58
lines changed

compiler/rustc_codegen_cranelift/src/abi/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ use std::mem;
1010
use cranelift_codegen::ir::{ArgumentPurpose, SigRef};
1111
use cranelift_codegen::isa::CallConv;
1212
use cranelift_module::ModuleError;
13+
use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization;
1314
use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall;
1415
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1516
use rustc_middle::ty::layout::FnAbiOf;
1617
use rustc_middle::ty::print::with_no_trimmed_paths;
1718
use rustc_middle::ty::TypeVisitableExt;
18-
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
1919
use rustc_session::Session;
2020
use rustc_span::source_map::Spanned;
2121
use rustc_target::abi::call::{Conv, FnAbi, PassMode};

compiler/rustc_codegen_cranelift/src/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ use cranelift_codegen::CodegenError;
55
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
66
use cranelift_module::ModuleError;
77
use rustc_ast::InlineAsmOptions;
8+
use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization;
89
use rustc_index::IndexVec;
910
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1011
use rustc_middle::ty::adjustment::PointerCoercion;
1112
use rustc_middle::ty::layout::FnAbiOf;
1213
use rustc_middle::ty::print::with_no_trimmed_paths;
1314
use rustc_middle::ty::TypeVisitableExt;
14-
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
1515

1616
use crate::constant::ConstantCx;
1717
use crate::debuginfo::{FunctionDebugContext, TypeDebugContext};

compiler/rustc_codegen_cranelift/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ extern crate rustc_hir;
2424
extern crate rustc_incremental;
2525
extern crate rustc_index;
2626
extern crate rustc_metadata;
27-
extern crate rustc_monomorphize;
2827
extern crate rustc_session;
2928
extern crate rustc_span;
3029
extern crate rustc_target;

compiler/rustc_codegen_ssa/src/base.rs

+28
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,34 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
806806
ongoing_codegen
807807
}
808808

809+
/// Returns whether a call from the current crate to the [`Instance`] would produce a call
810+
/// from `compiler_builtins` to a symbol the linker must resolve.
811+
///
812+
/// Such calls from `compiler_bultins` are effectively impossible for the linker to handle. Some
813+
/// linkers will optimize such that dead calls to unresolved symbols are not an error, but this is
814+
/// not guaranteed. So we used this function in codegen backends to ensure we do not generate any
815+
/// unlinkable calls.
816+
///
817+
/// Note that calls to LLVM intrinsics are uniquely okay because they won't make it to the linker.
818+
pub fn is_call_from_compiler_builtins_to_upstream_monomorphization<'tcx>(
819+
tcx: TyCtxt<'tcx>,
820+
instance: Instance<'tcx>,
821+
) -> bool {
822+
fn is_llvm_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
823+
if let Some(name) = tcx.codegen_fn_attrs(def_id).link_name {
824+
name.as_str().starts_with("llvm.")
825+
} else {
826+
false
827+
}
828+
}
829+
830+
let def_id = instance.def_id();
831+
!def_id.is_local()
832+
&& tcx.is_compiler_builtins(LOCAL_CRATE)
833+
&& !is_llvm_intrinsic(tcx, def_id)
834+
&& !tcx.should_codegen_locally(instance)
835+
}
836+
809837
impl CrateInfo {
810838
pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo {
811839
let crate_types = tcx.crate_types().to_vec();

compiler/rustc_codegen_ssa/src/mir/block.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use super::operand::OperandValue::{Immediate, Pair, Ref, ZeroSized};
33
use super::place::{PlaceRef, PlaceValue};
44
use super::{CachedLlbb, FunctionCx, LocalRef};
55

6-
use crate::base;
6+
use crate::base::{self, is_call_from_compiler_builtins_to_upstream_monomorphization};
77
use crate::common::{self, IntPredicate};
88
use crate::errors::CompilerBuiltinsCannotCall;
99
use crate::meth;
@@ -18,7 +18,6 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
1818
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
1919
use rustc_middle::ty::{self, Instance, Ty};
2020
use rustc_middle::{bug, span_bug};
21-
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
2221
use rustc_session::config::OptLevel;
2322
use rustc_span::{source_map::Spanned, sym, Span};
2423
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};

compiler/rustc_middle/src/hooks/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ declare_hooks! {
103103

104104
/// Create a list-like THIR representation for debugging.
105105
hook thir_flat(key: LocalDefId) -> String;
106+
107+
/// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we
108+
/// can just link to the upstream crate and therefore don't need a mono item.
109+
hook should_codegen_locally(instance: crate::ty::Instance<'tcx>) -> bool;
106110
}
107111

108112
#[cold]

compiler/rustc_monomorphize/src/collector.rs

+22-17
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ use rustc_middle::ty::{
228228
self, AssocKind, GenericParamDefKind, Instance, InstanceKind, Ty, TyCtxt, TypeFoldable,
229229
TypeVisitableExt, VtblEntry,
230230
};
231+
use rustc_middle::util::Providers;
231232
use rustc_middle::{bug, span_bug};
232233
use rustc_session::config::EntryFnType;
233234
use rustc_session::Limit;
@@ -399,7 +400,7 @@ fn collect_items_rec<'tcx>(
399400
let instance = Instance::mono(tcx, def_id);
400401

401402
// Sanity check whether this ended up being collected accidentally
402-
debug_assert!(should_codegen_locally(tcx, instance));
403+
debug_assert!(tcx.should_codegen_locally(instance));
403404

404405
let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() };
405406
// Nested statics have no type.
@@ -431,7 +432,7 @@ fn collect_items_rec<'tcx>(
431432
}
432433
MonoItem::Fn(instance) => {
433434
// Sanity check whether this ended up being collected accidentally
434-
debug_assert!(should_codegen_locally(tcx, instance));
435+
debug_assert!(tcx.should_codegen_locally(instance));
435436

436437
// Keep track of the monomorphization recursion depth
437438
recursion_depth_reset = Some(check_recursion_limit(
@@ -475,7 +476,7 @@ fn collect_items_rec<'tcx>(
475476
}
476477
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
477478
let instance = Instance::mono(tcx, *def_id);
478-
if should_codegen_locally(tcx, instance) {
479+
if tcx.should_codegen_locally(instance) {
479480
trace!("collecting static {:?}", def_id);
480481
used_items.push(dummy_spanned(MonoItem::Static(*def_id)));
481482
}
@@ -712,7 +713,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
712713
if let ty::Closure(def_id, args) = *source_ty.kind() {
713714
let instance =
714715
Instance::resolve_closure(self.tcx, def_id, args, ty::ClosureKind::FnOnce);
715-
if should_codegen_locally(self.tcx, instance) {
716+
if self.tcx.should_codegen_locally(instance) {
716717
self.used_items.push(create_fn_mono_item(self.tcx, instance, span));
717718
}
718719
} else {
@@ -722,7 +723,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
722723
mir::Rvalue::ThreadLocalRef(def_id) => {
723724
assert!(self.tcx.is_thread_local_static(def_id));
724725
let instance = Instance::mono(self.tcx, def_id);
725-
if should_codegen_locally(self.tcx, instance) {
726+
if self.tcx.should_codegen_locally(instance) {
726727
trace!("collecting thread-local static {:?}", def_id);
727728
self.used_items.push(respan(span, MonoItem::Static(def_id)));
728729
}
@@ -749,7 +750,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
749750
let tcx = self.tcx;
750751
let push_mono_lang_item = |this: &mut Self, lang_item: LangItem| {
751752
let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source)));
752-
if should_codegen_locally(tcx, instance) {
753+
if tcx.should_codegen_locally(instance) {
753754
this.used_items.push(create_fn_mono_item(tcx, instance, source));
754755
}
755756
};
@@ -783,7 +784,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
783784
}
784785
mir::InlineAsmOperand::SymStatic { def_id } => {
785786
let instance = Instance::mono(self.tcx, def_id);
786-
if should_codegen_locally(self.tcx, instance) {
787+
if self.tcx.should_codegen_locally(instance) {
787788
trace!("collecting asm sym static {:?}", def_id);
788789
self.used_items.push(respan(source, MonoItem::Static(def_id)));
789790
}
@@ -873,7 +874,7 @@ fn visit_instance_use<'tcx>(
873874
output: &mut MonoItems<'tcx>,
874875
) {
875876
debug!("visit_item_use({:?}, is_direct_call={:?})", instance, is_direct_call);
876-
if !should_codegen_locally(tcx, instance) {
877+
if !tcx.should_codegen_locally(instance) {
877878
return;
878879
}
879880
if let ty::InstanceKind::Intrinsic(def_id) = instance.def {
@@ -885,13 +886,13 @@ fn visit_instance_use<'tcx>(
885886
// codegen a call to that function without generating code for the function itself.
886887
let def_id = tcx.require_lang_item(LangItem::PanicNounwind, None);
887888
let panic_instance = Instance::mono(tcx, def_id);
888-
if should_codegen_locally(tcx, panic_instance) {
889+
if tcx.should_codegen_locally(panic_instance) {
889890
output.push(create_fn_mono_item(tcx, panic_instance, source));
890891
}
891892
} else if tcx.has_attr(def_id, sym::rustc_intrinsic) {
892893
// Codegen the fallback body of intrinsics with fallback bodies
893894
let instance = ty::Instance::new(def_id, instance.args);
894-
if should_codegen_locally(tcx, instance) {
895+
if tcx.should_codegen_locally(instance) {
895896
output.push(create_fn_mono_item(tcx, instance, source));
896897
}
897898
}
@@ -930,7 +931,7 @@ fn visit_instance_use<'tcx>(
930931

931932
/// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we
932933
/// can just link to the upstream crate and therefore don't need a mono item.
933-
pub(crate) fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> bool {
934+
fn should_codegen_locally<'tcx>(tcx: TyCtxtAt<'tcx>, instance: Instance<'tcx>) -> bool {
934935
let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() else {
935936
return true;
936937
};
@@ -946,7 +947,7 @@ pub(crate) fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance
946947
}
947948

948949
if tcx.is_reachable_non_generic(def_id)
949-
|| instance.polymorphize(tcx).upstream_monomorphization(tcx).is_some()
950+
|| instance.polymorphize(*tcx).upstream_monomorphization(*tcx).is_some()
950951
{
951952
// We can link to the item in question, no instance needed in this crate.
952953
return false;
@@ -1127,7 +1128,7 @@ fn create_mono_items_for_vtable_methods<'tcx>(
11271128
None
11281129
}
11291130
VtblEntry::Method(instance) => {
1130-
Some(*instance).filter(|instance| should_codegen_locally(tcx, *instance))
1131+
Some(*instance).filter(|instance| tcx.should_codegen_locally(*instance))
11311132
}
11321133
})
11331134
.map(|item| create_fn_mono_item(tcx, item, source));
@@ -1144,7 +1145,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
11441145
GlobalAlloc::Static(def_id) => {
11451146
assert!(!tcx.is_thread_local_static(def_id));
11461147
let instance = Instance::mono(tcx, def_id);
1147-
if should_codegen_locally(tcx, instance) {
1148+
if tcx.should_codegen_locally(instance) {
11481149
trace!("collecting static {:?}", def_id);
11491150
output.push(dummy_spanned(MonoItem::Static(def_id)));
11501151
}
@@ -1162,7 +1163,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
11621163
}
11631164
}
11641165
GlobalAlloc::Function { instance, .. } => {
1165-
if should_codegen_locally(tcx, instance) {
1166+
if tcx.should_codegen_locally(instance) {
11661167
trace!("collecting {:?} with {:#?}", alloc_id, instance);
11671168
output.push(create_fn_mono_item(tcx, instance, DUMMY_SP));
11681169
}
@@ -1284,7 +1285,7 @@ fn visit_mentioned_item<'tcx>(
12841285
if let ty::Closure(def_id, args) = *source_ty.kind() {
12851286
let instance =
12861287
Instance::resolve_closure(tcx, def_id, args, ty::ClosureKind::FnOnce);
1287-
if should_codegen_locally(tcx, instance) {
1288+
if tcx.should_codegen_locally(instance) {
12881289
output.push(create_fn_mono_item(tcx, instance, span));
12891290
}
12901291
} else {
@@ -1557,7 +1558,7 @@ fn create_mono_items_for_default_impls<'tcx>(
15571558
let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, args, DUMMY_SP);
15581559

15591560
let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
1560-
if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, instance) {
1561+
if mono_item.node.is_instantiable(tcx) && tcx.should_codegen_locally(instance) {
15611562
output.push(mono_item);
15621563
}
15631564
}
@@ -1613,3 +1614,7 @@ pub(crate) fn collect_crate_mono_items<'tcx>(
16131614

16141615
(mono_items, state.usage_map.into_inner())
16151616
}
1617+
1618+
pub fn provide(providers: &mut Providers) {
1619+
providers.hooks.should_codegen_locally = should_codegen_locally;
1620+
}

compiler/rustc_monomorphize/src/lib.rs

+2-35
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,11 @@
55

66
use rustc_hir::lang_items::LangItem;
77
use rustc_middle::bug;
8-
use rustc_middle::query::{Providers, TyCtxtAt};
8+
use rustc_middle::query::TyCtxtAt;
99
use rustc_middle::traits;
1010
use rustc_middle::ty::adjustment::CustomCoerceUnsized;
11-
use rustc_middle::ty::Instance;
12-
use rustc_middle::ty::TyCtxt;
1311
use rustc_middle::ty::{self, Ty};
14-
use rustc_span::def_id::DefId;
15-
use rustc_span::def_id::LOCAL_CRATE;
12+
use rustc_middle::util::Providers;
1613
use rustc_span::ErrorGuaranteed;
1714

1815
mod collector;
@@ -21,8 +18,6 @@ mod partitioning;
2118
mod polymorphize;
2219
mod util;
2320

24-
use collector::should_codegen_locally;
25-
2621
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
2722

2823
fn custom_coerce_unsize_info<'tcx>(
@@ -47,34 +42,6 @@ fn custom_coerce_unsize_info<'tcx>(
4742
}
4843
}
4944

50-
/// Returns whether a call from the current crate to the [`Instance`] would produce a call
51-
/// from `compiler_builtins` to a symbol the linker must resolve.
52-
///
53-
/// Such calls from `compiler_bultins` are effectively impossible for the linker to handle. Some
54-
/// linkers will optimize such that dead calls to unresolved symbols are not an error, but this is
55-
/// not guaranteed. So we used this function in codegen backends to ensure we do not generate any
56-
/// unlinkable calls.
57-
///
58-
/// Note that calls to LLVM intrinsics are uniquely okay because they won't make it to the linker.
59-
pub fn is_call_from_compiler_builtins_to_upstream_monomorphization<'tcx>(
60-
tcx: TyCtxt<'tcx>,
61-
instance: Instance<'tcx>,
62-
) -> bool {
63-
fn is_llvm_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
64-
if let Some(name) = tcx.codegen_fn_attrs(def_id).link_name {
65-
name.as_str().starts_with("llvm.")
66-
} else {
67-
false
68-
}
69-
}
70-
71-
let def_id = instance.def_id();
72-
!def_id.is_local()
73-
&& tcx.is_compiler_builtins(LOCAL_CRATE)
74-
&& !is_llvm_intrinsic(tcx, def_id)
75-
&& !should_codegen_locally(tcx, instance)
76-
}
77-
7845
pub fn provide(providers: &mut Providers) {
7946
partitioning::provide(providers);
8047
polymorphize::provide(providers);

compiler/rustc_monomorphize/src/partitioning.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,9 @@ use rustc_middle::mir::mono::{
112112
CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, MonoItemData,
113113
Visibility,
114114
};
115-
use rustc_middle::query::Providers;
116115
use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths};
117116
use rustc_middle::ty::{self, visit::TypeVisitableExt, InstanceKind, TyCtxt};
117+
use rustc_middle::util::Providers;
118118
use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath};
119119
use rustc_session::CodegenUnits;
120120
use rustc_span::symbol::Symbol;
@@ -1314,4 +1314,6 @@ pub fn provide(providers: &mut Providers) {
13141314
.find(|cgu| cgu.name() == name)
13151315
.unwrap_or_else(|| panic!("failed to find cgu with name {name:?}"))
13161316
};
1317+
1318+
collector::provide(providers);
13171319
}

0 commit comments

Comments
 (0)