Skip to content

Commit d371ebe

Browse files
committed
only compute codegen_fn_attrs where needed
1 parent 66ff6c3 commit d371ebe

File tree

11 files changed

+154
-51
lines changed

11 files changed

+154
-51
lines changed

compiler/rustc_metadata/src/rmeta/encoder.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
10071007
record!(self.tables.def_span[def_id] <- tcx.def_span(def_id));
10081008
self.encode_attrs(def_id);
10091009
record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id));
1010-
record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id));
1010+
if tcx.has_codegen_attrs(def_kind) {
1011+
record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id));
1012+
}
10111013
if should_encode_visibility(def_kind) {
10121014
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
10131015
}

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,9 @@ bitflags! {
9595
}
9696

9797
impl CodegenFnAttrs {
98-
pub fn new() -> CodegenFnAttrs {
98+
pub const EMPTY: &'static Self = &Self::new();
99+
100+
pub const fn new() -> CodegenFnAttrs {
99101
CodegenFnAttrs {
100102
flags: CodegenFnAttrFlags::empty(),
101103
inline: InlineAttr::None,

compiler/rustc_middle/src/ty/instance.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,8 @@ impl<'tcx> InstanceDef<'tcx> {
246246
match *self {
247247
InstanceDef::Item(ty::WithOptConstParam { did: def_id, .. })
248248
| InstanceDef::Virtual(def_id, _) => {
249-
tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
249+
tcx.has_codegen_attrs(tcx.def_kind(def_id))
250+
&& tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
250251
}
251252
InstanceDef::ClosureOnceShim { call_once: _, track_caller } => track_caller,
252253
_ => false,

compiler/rustc_middle/src/ty/util.rs

+36
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,42 @@ impl<'tcx> TyCtxt<'tcx> {
139139
hasher.finish()
140140
}
141141

142+
pub fn has_codegen_attrs(self, def_kind: DefKind) -> bool {
143+
match def_kind {
144+
DefKind::Fn
145+
| DefKind::AssocFn
146+
| DefKind::Ctor(..)
147+
| DefKind::Closure
148+
| DefKind::Generator
149+
| DefKind::Static(_) => true,
150+
DefKind::Mod
151+
| DefKind::Struct
152+
| DefKind::Union
153+
| DefKind::Enum
154+
| DefKind::Variant
155+
| DefKind::Trait
156+
| DefKind::TyAlias
157+
| DefKind::ForeignTy
158+
| DefKind::TraitAlias
159+
| DefKind::AssocTy
160+
| DefKind::Const
161+
| DefKind::AssocConst
162+
| DefKind::Macro(..)
163+
| DefKind::Use
164+
| DefKind::ForeignMod
165+
| DefKind::OpaqueTy
166+
| DefKind::Impl
167+
| DefKind::Field
168+
| DefKind::TyParam
169+
| DefKind::ConstParam
170+
| DefKind::LifetimeParam
171+
| DefKind::AnonConst
172+
| DefKind::InlineConst
173+
| DefKind::GlobalAsm
174+
| DefKind::ExternCrate => false,
175+
}
176+
}
177+
142178
pub fn res_generics_def_id(self, res: Res) -> Option<DefId> {
143179
match res {
144180
Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => {

compiler/rustc_mir_build/src/check_unsafety.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct UnsafetyVisitor<'a, 'tcx> {
2727
body_unsafety: BodyUnsafety,
2828
/// The `#[target_feature]` attributes of the body. Used for checking
2929
/// calls to functions with `#[target_feature]` (RFC 2396).
30-
body_target_features: &'tcx Vec<Symbol>,
30+
body_target_features: &'tcx [Symbol],
3131
/// When inside the LHS of an assignment to a field, this is the type
3232
/// of the LHS and the span of the assignment expression.
3333
assignment_info: Option<(Ty<'tcx>, Span)>,
@@ -661,7 +661,11 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
661661
BodyUnsafety::Safe
662662
}
663663
});
664-
let body_target_features = &tcx.codegen_fn_attrs(def.did).target_features;
664+
let body_target_features: &[_] = if tcx.has_codegen_attrs(tcx.def_kind(def.did)) {
665+
&tcx.codegen_fn_attrs(def.did).target_features
666+
} else {
667+
&[]
668+
};
665669
let safety_context =
666670
if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
667671
let mut visitor = UnsafetyVisitor {

compiler/rustc_mir_transform/src/check_unsafety.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,12 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
375375
}
376376

377377
let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features;
378-
let self_features = &self.tcx.codegen_fn_attrs(self.body_did).target_features;
378+
// Constants don't have codegen attributes, so the body might not have codegen attributes.
379+
let self_features: &[_] = if self.tcx.has_codegen_attrs(self.tcx.def_kind(self.body_did)) {
380+
&self.tcx.codegen_fn_attrs(self.body_did).target_features
381+
} else {
382+
&[]
383+
};
379384

380385
// Is `callee_features` a subset of `calling_features`?
381386
if !callee_features.iter().all(|feature| self_features.contains(feature)) {

compiler/rustc_passes/src/check_attr.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ impl CheckAttrVisitor<'_> {
104104
sym::rustc_allow_const_fn_unstable => {
105105
self.check_rustc_allow_const_fn_unstable(hir_id, &attr, span, target)
106106
}
107+
sym::rustc_std_internal_symbol => {
108+
self.check_rustc_std_internal_symbol(&attr, span, target)
109+
}
107110
sym::naked => self.check_naked(hir_id, attr, span, target),
108111
sym::rustc_legacy_const_generics => {
109112
self.check_rustc_legacy_const_generics(&attr, span, target, item)
@@ -193,6 +196,7 @@ impl CheckAttrVisitor<'_> {
193196
return;
194197
}
195198

199+
// FIXME(@lcnr): this doesn't belong here.
196200
if matches!(target, Target::Closure | Target::Fn | Target::Method(_) | Target::ForeignFn) {
197201
self.tcx.ensure().codegen_fn_attrs(self.tcx.hir().local_def_id(hir_id));
198202
}
@@ -1659,7 +1663,7 @@ impl CheckAttrVisitor<'_> {
16591663
}
16601664
}
16611665
sym::align => {
1662-
if let (Target::Fn, true) = (target, !self.tcx.features().fn_align) {
1666+
if let (Target::Fn, false) = (target, self.tcx.features().fn_align) {
16631667
feature_err(
16641668
&self.tcx.sess.parse_sess,
16651669
sym::fn_align,
@@ -1980,6 +1984,25 @@ impl CheckAttrVisitor<'_> {
19801984
}
19811985
}
19821986

1987+
fn check_rustc_std_internal_symbol(
1988+
&self,
1989+
attr: &Attribute,
1990+
span: Span,
1991+
target: Target,
1992+
) -> bool {
1993+
match target {
1994+
Target::Fn | Target::Static => true,
1995+
_ => {
1996+
self.tcx
1997+
.sess
1998+
.struct_span_err(attr.span, "attribute should be applied functions or statics")
1999+
.span_label(span, "not a function or static")
2000+
.emit();
2001+
false
2002+
}
2003+
}
2004+
}
2005+
19832006
/// default_method_body_is_const should only be applied to trait methods with default bodies.
19842007
fn check_default_method_body_is_const(
19852008
&self,

compiler/rustc_passes/src/dead.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -452,15 +452,17 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
452452
}
453453

454454
let def_id = tcx.hir().local_def_id(id);
455-
let cg_attrs = tcx.codegen_fn_attrs(def_id);
456-
457-
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
458-
// forcefully, e.g., for placing it in a specific section.
459-
if cg_attrs.contains_extern_indicator()
460-
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
461-
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
462-
{
463-
return true;
455+
if tcx.has_codegen_attrs(tcx.def_kind(def_id)) {
456+
let cg_attrs = tcx.codegen_fn_attrs(def_id);
457+
458+
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
459+
// forcefully, e.g., for placing it in a specific section.
460+
if cg_attrs.contains_extern_indicator()
461+
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
462+
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
463+
{
464+
return true;
465+
}
464466
}
465467

466468
tcx.lint_level_at_node(lint::builtin::DEAD_CODE, id).0 == lint::Allow

compiler/rustc_passes/src/reachable.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,11 @@ impl<'tcx> ReachableContext<'tcx> {
208208
} else {
209209
false
210210
};
211-
let codegen_attrs = self.tcx.codegen_fn_attrs(search_item);
211+
let codegen_attrs = if self.tcx.has_codegen_attrs(self.tcx.def_kind(search_item)) {
212+
self.tcx.codegen_fn_attrs(search_item)
213+
} else {
214+
CodegenFnAttrs::EMPTY
215+
};
212216
let is_extern = codegen_attrs.contains_extern_indicator();
213217
let std_internal =
214218
codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
@@ -329,16 +333,18 @@ impl CollectPrivateImplItemsVisitor<'_, '_> {
329333
// Anything which has custom linkage gets thrown on the worklist no
330334
// matter where it is in the crate, along with "special std symbols"
331335
// which are currently akin to allocator symbols.
332-
let codegen_attrs = self.tcx.codegen_fn_attrs(def_id);
333-
if codegen_attrs.contains_extern_indicator()
334-
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
335-
// FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by
336-
// `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their
337-
// `SymbolExportLevel::Rust` export level but may end up being exported in dylibs.
338-
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED)
339-
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
340-
{
341-
self.worklist.push(def_id);
336+
if self.tcx.has_codegen_attrs(self.tcx.def_kind(def_id)) {
337+
let codegen_attrs = self.tcx.codegen_fn_attrs(def_id);
338+
if codegen_attrs.contains_extern_indicator()
339+
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
340+
// FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by
341+
// `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their
342+
// `SymbolExportLevel::Rust` export level but may end up being exported in dylibs.
343+
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED)
344+
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
345+
{
346+
self.worklist.push(def_id);
347+
}
342348
}
343349
}
344350
}

compiler/rustc_symbol_mangling/src/lib.rs

+25-14
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,10 @@
9696
#[macro_use]
9797
extern crate rustc_middle;
9898

99+
use rustc_hir::def::DefKind;
99100
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
100101
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
102+
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
101103
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
102104
use rustc_middle::ty::query::Providers;
103105
use rustc_middle::ty::subst::SubstsRef;
@@ -175,7 +177,11 @@ fn compute_symbol_name<'tcx>(
175177
}
176178

177179
// FIXME(eddyb) Precompute a custom symbol name based on attributes.
178-
let attrs = tcx.codegen_fn_attrs(def_id);
180+
let attrs = if tcx.has_codegen_attrs(tcx.def_kind(def_id)) {
181+
tcx.codegen_fn_attrs(def_id)
182+
} else {
183+
CodegenFnAttrs::EMPTY
184+
};
179185

180186
// Foreign items by default use no mangling for their symbol name. There's a
181187
// few exceptions to this rule though:
@@ -213,20 +219,25 @@ fn compute_symbol_name<'tcx>(
213219
return tcx.item_name(def_id).to_string();
214220
}
215221

216-
let avoid_cross_crate_conflicts =
217-
// If this is an instance of a generic function, we also hash in
218-
// the ID of the instantiating crate. This avoids symbol conflicts
219-
// in case the same instances is emitted in two crates of the same
220-
// project.
221-
is_generic(substs) ||
222+
// If we're dealing with an instance of a function that's inlined from
223+
// another crate but we're marking it as globally shared to our
224+
// compilation (aka we're not making an internal copy in each of our
225+
// codegen units) then this symbol may become an exported (but hidden
226+
// visibility) symbol. This means that multiple crates may do the same
227+
// and we want to be sure to avoid any symbol conflicts here.
228+
let is_globally_shared_function = matches!(
229+
tcx.def_kind(instance.def_id()),
230+
DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator | DefKind::Ctor(..)
231+
) && matches!(
232+
MonoItem::Fn(instance).instantiation_mode(tcx),
233+
InstantiationMode::GloballyShared { may_conflict: true }
234+
);
222235

223-
// If we're dealing with an instance of a function that's inlined from
224-
// another crate but we're marking it as globally shared to our
225-
// compilation (aka we're not making an internal copy in each of our
226-
// codegen units) then this symbol may become an exported (but hidden
227-
// visibility) symbol. This means that multiple crates may do the same
228-
// and we want to be sure to avoid any symbol conflicts here.
229-
matches!(MonoItem::Fn(instance).instantiation_mode(tcx), InstantiationMode::GloballyShared { may_conflict: true });
236+
// If this is an instance of a generic function, we also hash in
237+
// the ID of the instantiating crate. This avoids symbol conflicts
238+
// in case the same instances is emitted in two crates of the same
239+
// project.
240+
let avoid_cross_crate_conflicts = is_generic(substs) || is_globally_shared_function;
230241

231242
let instantiating_crate =
232243
if avoid_cross_crate_conflicts { Some(compute_instantiating_crate()) } else { None };

compiler/rustc_typeck/src/collect.rs

+21-10
Original file line numberDiff line numberDiff line change
@@ -2720,6 +2720,14 @@ fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
27202720
}
27212721

27222722
fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
2723+
if cfg!(debug_assertions) {
2724+
let def_kind = tcx.def_kind(did);
2725+
assert!(
2726+
tcx.has_codegen_attrs(def_kind),
2727+
"unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}",
2728+
);
2729+
}
2730+
27232731
let did = did.expect_local();
27242732
let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did));
27252733
let mut codegen_fn_attrs = CodegenFnAttrs::new();
@@ -3223,19 +3231,22 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
32233231

32243232
/// Computes the set of target features used in a function for the purposes of
32253233
/// inline assembly.
3226-
fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, id: DefId) -> &'tcx FxHashSet<Symbol> {
3234+
fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<Symbol> {
32273235
let mut target_features = tcx.sess.target_features.clone();
3228-
let attrs = tcx.codegen_fn_attrs(id);
3229-
target_features.extend(&attrs.target_features);
3230-
match attrs.instruction_set {
3231-
None => {}
3232-
Some(InstructionSetAttr::ArmA32) => {
3233-
target_features.remove(&sym::thumb_mode);
3234-
}
3235-
Some(InstructionSetAttr::ArmT32) => {
3236-
target_features.insert(sym::thumb_mode);
3236+
if tcx.has_codegen_attrs(tcx.def_kind(did)) {
3237+
let attrs = tcx.codegen_fn_attrs(did);
3238+
target_features.extend(&attrs.target_features);
3239+
match attrs.instruction_set {
3240+
None => {}
3241+
Some(InstructionSetAttr::ArmA32) => {
3242+
target_features.remove(&sym::thumb_mode);
3243+
}
3244+
Some(InstructionSetAttr::ArmT32) => {
3245+
target_features.insert(sym::thumb_mode);
3246+
}
32373247
}
32383248
}
3249+
32393250
tcx.arena.alloc(target_features)
32403251
}
32413252

0 commit comments

Comments
 (0)