mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
only compute codegen_fn_attrs
where needed
This commit is contained in:
parent
66ff6c32e5
commit
d371ebe117
@ -1007,7 +1007,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
record!(self.tables.def_span[def_id] <- tcx.def_span(def_id));
|
||||
self.encode_attrs(def_id);
|
||||
record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id));
|
||||
record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id));
|
||||
if tcx.has_codegen_attrs(def_kind) {
|
||||
record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id));
|
||||
}
|
||||
if should_encode_visibility(def_kind) {
|
||||
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
|
||||
}
|
||||
|
@ -95,7 +95,9 @@ bitflags! {
|
||||
}
|
||||
|
||||
impl CodegenFnAttrs {
|
||||
pub fn new() -> CodegenFnAttrs {
|
||||
pub const EMPTY: &'static Self = &Self::new();
|
||||
|
||||
pub const fn new() -> CodegenFnAttrs {
|
||||
CodegenFnAttrs {
|
||||
flags: CodegenFnAttrFlags::empty(),
|
||||
inline: InlineAttr::None,
|
||||
|
@ -246,7 +246,8 @@ impl<'tcx> InstanceDef<'tcx> {
|
||||
match *self {
|
||||
InstanceDef::Item(ty::WithOptConstParam { did: def_id, .. })
|
||||
| InstanceDef::Virtual(def_id, _) => {
|
||||
tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
|
||||
tcx.has_codegen_attrs(tcx.def_kind(def_id))
|
||||
&& tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
|
||||
}
|
||||
InstanceDef::ClosureOnceShim { call_once: _, track_caller } => track_caller,
|
||||
_ => false,
|
||||
|
@ -139,6 +139,42 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
hasher.finish()
|
||||
}
|
||||
|
||||
pub fn has_codegen_attrs(self, def_kind: DefKind) -> bool {
|
||||
match def_kind {
|
||||
DefKind::Fn
|
||||
| DefKind::AssocFn
|
||||
| DefKind::Ctor(..)
|
||||
| DefKind::Closure
|
||||
| DefKind::Generator
|
||||
| DefKind::Static(_) => true,
|
||||
DefKind::Mod
|
||||
| DefKind::Struct
|
||||
| DefKind::Union
|
||||
| DefKind::Enum
|
||||
| DefKind::Variant
|
||||
| DefKind::Trait
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
| DefKind::Const
|
||||
| DefKind::AssocConst
|
||||
| DefKind::Macro(..)
|
||||
| DefKind::Use
|
||||
| DefKind::ForeignMod
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::Impl
|
||||
| DefKind::Field
|
||||
| DefKind::TyParam
|
||||
| DefKind::ConstParam
|
||||
| DefKind::LifetimeParam
|
||||
| DefKind::AnonConst
|
||||
| DefKind::InlineConst
|
||||
| DefKind::GlobalAsm
|
||||
| DefKind::ExternCrate => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn res_generics_def_id(self, res: Res) -> Option<DefId> {
|
||||
match res {
|
||||
Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => {
|
||||
|
@ -27,7 +27,7 @@ struct UnsafetyVisitor<'a, 'tcx> {
|
||||
body_unsafety: BodyUnsafety,
|
||||
/// The `#[target_feature]` attributes of the body. Used for checking
|
||||
/// calls to functions with `#[target_feature]` (RFC 2396).
|
||||
body_target_features: &'tcx Vec<Symbol>,
|
||||
body_target_features: &'tcx [Symbol],
|
||||
/// When inside the LHS of an assignment to a field, this is the type
|
||||
/// of the LHS and the span of the assignment expression.
|
||||
assignment_info: Option<(Ty<'tcx>, Span)>,
|
||||
@ -661,7 +661,11 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
|
||||
BodyUnsafety::Safe
|
||||
}
|
||||
});
|
||||
let body_target_features = &tcx.codegen_fn_attrs(def.did).target_features;
|
||||
let body_target_features: &[_] = if tcx.has_codegen_attrs(tcx.def_kind(def.did)) {
|
||||
&tcx.codegen_fn_attrs(def.did).target_features
|
||||
} else {
|
||||
&[]
|
||||
};
|
||||
let safety_context =
|
||||
if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
|
||||
let mut visitor = UnsafetyVisitor {
|
||||
|
@ -375,7 +375,12 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
|
||||
}
|
||||
|
||||
let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features;
|
||||
let self_features = &self.tcx.codegen_fn_attrs(self.body_did).target_features;
|
||||
// Constants don't have codegen attributes, so the body might not have codegen attributes.
|
||||
let self_features: &[_] = if self.tcx.has_codegen_attrs(self.tcx.def_kind(self.body_did)) {
|
||||
&self.tcx.codegen_fn_attrs(self.body_did).target_features
|
||||
} else {
|
||||
&[]
|
||||
};
|
||||
|
||||
// Is `callee_features` a subset of `calling_features`?
|
||||
if !callee_features.iter().all(|feature| self_features.contains(feature)) {
|
||||
|
@ -104,6 +104,9 @@ impl CheckAttrVisitor<'_> {
|
||||
sym::rustc_allow_const_fn_unstable => {
|
||||
self.check_rustc_allow_const_fn_unstable(hir_id, &attr, span, target)
|
||||
}
|
||||
sym::rustc_std_internal_symbol => {
|
||||
self.check_rustc_std_internal_symbol(&attr, span, target)
|
||||
}
|
||||
sym::naked => self.check_naked(hir_id, attr, span, target),
|
||||
sym::rustc_legacy_const_generics => {
|
||||
self.check_rustc_legacy_const_generics(&attr, span, target, item)
|
||||
@ -193,6 +196,7 @@ impl CheckAttrVisitor<'_> {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME(@lcnr): this doesn't belong here.
|
||||
if matches!(target, Target::Closure | Target::Fn | Target::Method(_) | Target::ForeignFn) {
|
||||
self.tcx.ensure().codegen_fn_attrs(self.tcx.hir().local_def_id(hir_id));
|
||||
}
|
||||
@ -1659,7 +1663,7 @@ impl CheckAttrVisitor<'_> {
|
||||
}
|
||||
}
|
||||
sym::align => {
|
||||
if let (Target::Fn, true) = (target, !self.tcx.features().fn_align) {
|
||||
if let (Target::Fn, false) = (target, self.tcx.features().fn_align) {
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
sym::fn_align,
|
||||
@ -1980,6 +1984,25 @@ impl CheckAttrVisitor<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_rustc_std_internal_symbol(
|
||||
&self,
|
||||
attr: &Attribute,
|
||||
span: Span,
|
||||
target: Target,
|
||||
) -> bool {
|
||||
match target {
|
||||
Target::Fn | Target::Static => true,
|
||||
_ => {
|
||||
self.tcx
|
||||
.sess
|
||||
.struct_span_err(attr.span, "attribute should be applied functions or statics")
|
||||
.span_label(span, "not a function or static")
|
||||
.emit();
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// default_method_body_is_const should only be applied to trait methods with default bodies.
|
||||
fn check_default_method_body_is_const(
|
||||
&self,
|
||||
|
@ -452,15 +452,17 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
|
||||
}
|
||||
|
||||
let def_id = tcx.hir().local_def_id(id);
|
||||
let cg_attrs = tcx.codegen_fn_attrs(def_id);
|
||||
if tcx.has_codegen_attrs(tcx.def_kind(def_id)) {
|
||||
let cg_attrs = tcx.codegen_fn_attrs(def_id);
|
||||
|
||||
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
|
||||
// forcefully, e.g., for placing it in a specific section.
|
||||
if cg_attrs.contains_extern_indicator()
|
||||
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
|
||||
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
|
||||
{
|
||||
return true;
|
||||
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
|
||||
// forcefully, e.g., for placing it in a specific section.
|
||||
if cg_attrs.contains_extern_indicator()
|
||||
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
|
||||
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
tcx.lint_level_at_node(lint::builtin::DEAD_CODE, id).0 == lint::Allow
|
||||
|
@ -208,7 +208,11 @@ impl<'tcx> ReachableContext<'tcx> {
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let codegen_attrs = self.tcx.codegen_fn_attrs(search_item);
|
||||
let codegen_attrs = if self.tcx.has_codegen_attrs(self.tcx.def_kind(search_item)) {
|
||||
self.tcx.codegen_fn_attrs(search_item)
|
||||
} else {
|
||||
CodegenFnAttrs::EMPTY
|
||||
};
|
||||
let is_extern = codegen_attrs.contains_extern_indicator();
|
||||
let std_internal =
|
||||
codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
|
||||
@ -329,16 +333,18 @@ impl CollectPrivateImplItemsVisitor<'_, '_> {
|
||||
// Anything which has custom linkage gets thrown on the worklist no
|
||||
// matter where it is in the crate, along with "special std symbols"
|
||||
// which are currently akin to allocator symbols.
|
||||
let codegen_attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||
if codegen_attrs.contains_extern_indicator()
|
||||
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
|
||||
// FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by
|
||||
// `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their
|
||||
// `SymbolExportLevel::Rust` export level but may end up being exported in dylibs.
|
||||
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED)
|
||||
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
|
||||
{
|
||||
self.worklist.push(def_id);
|
||||
if self.tcx.has_codegen_attrs(self.tcx.def_kind(def_id)) {
|
||||
let codegen_attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||
if codegen_attrs.contains_extern_indicator()
|
||||
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
|
||||
// FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by
|
||||
// `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their
|
||||
// `SymbolExportLevel::Rust` export level but may end up being exported in dylibs.
|
||||
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED)
|
||||
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
|
||||
{
|
||||
self.worklist.push(def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,8 +96,10 @@
|
||||
#[macro_use]
|
||||
extern crate rustc_middle;
|
||||
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
@ -175,7 +177,11 @@ fn compute_symbol_name<'tcx>(
|
||||
}
|
||||
|
||||
// FIXME(eddyb) Precompute a custom symbol name based on attributes.
|
||||
let attrs = tcx.codegen_fn_attrs(def_id);
|
||||
let attrs = if tcx.has_codegen_attrs(tcx.def_kind(def_id)) {
|
||||
tcx.codegen_fn_attrs(def_id)
|
||||
} else {
|
||||
CodegenFnAttrs::EMPTY
|
||||
};
|
||||
|
||||
// Foreign items by default use no mangling for their symbol name. There's a
|
||||
// few exceptions to this rule though:
|
||||
@ -213,20 +219,25 @@ fn compute_symbol_name<'tcx>(
|
||||
return tcx.item_name(def_id).to_string();
|
||||
}
|
||||
|
||||
let avoid_cross_crate_conflicts =
|
||||
// If this is an instance of a generic function, we also hash in
|
||||
// the ID of the instantiating crate. This avoids symbol conflicts
|
||||
// in case the same instances is emitted in two crates of the same
|
||||
// project.
|
||||
is_generic(substs) ||
|
||||
// If we're dealing with an instance of a function that's inlined from
|
||||
// another crate but we're marking it as globally shared to our
|
||||
// compilation (aka we're not making an internal copy in each of our
|
||||
// codegen units) then this symbol may become an exported (but hidden
|
||||
// visibility) symbol. This means that multiple crates may do the same
|
||||
// and we want to be sure to avoid any symbol conflicts here.
|
||||
let is_globally_shared_function = matches!(
|
||||
tcx.def_kind(instance.def_id()),
|
||||
DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator | DefKind::Ctor(..)
|
||||
) && matches!(
|
||||
MonoItem::Fn(instance).instantiation_mode(tcx),
|
||||
InstantiationMode::GloballyShared { may_conflict: true }
|
||||
);
|
||||
|
||||
// If we're dealing with an instance of a function that's inlined from
|
||||
// another crate but we're marking it as globally shared to our
|
||||
// compilation (aka we're not making an internal copy in each of our
|
||||
// codegen units) then this symbol may become an exported (but hidden
|
||||
// visibility) symbol. This means that multiple crates may do the same
|
||||
// and we want to be sure to avoid any symbol conflicts here.
|
||||
matches!(MonoItem::Fn(instance).instantiation_mode(tcx), InstantiationMode::GloballyShared { may_conflict: true });
|
||||
// If this is an instance of a generic function, we also hash in
|
||||
// the ID of the instantiating crate. This avoids symbol conflicts
|
||||
// in case the same instances is emitted in two crates of the same
|
||||
// project.
|
||||
let avoid_cross_crate_conflicts = is_generic(substs) || is_globally_shared_function;
|
||||
|
||||
let instantiating_crate =
|
||||
if avoid_cross_crate_conflicts { Some(compute_instantiating_crate()) } else { None };
|
||||
|
@ -2720,6 +2720,14 @@ fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
|
||||
}
|
||||
|
||||
fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
|
||||
if cfg!(debug_assertions) {
|
||||
let def_kind = tcx.def_kind(did);
|
||||
assert!(
|
||||
tcx.has_codegen_attrs(def_kind),
|
||||
"unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}",
|
||||
);
|
||||
}
|
||||
|
||||
let did = did.expect_local();
|
||||
let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did));
|
||||
let mut codegen_fn_attrs = CodegenFnAttrs::new();
|
||||
@ -3223,19 +3231,22 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
|
||||
|
||||
/// Computes the set of target features used in a function for the purposes of
|
||||
/// inline assembly.
|
||||
fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, id: DefId) -> &'tcx FxHashSet<Symbol> {
|
||||
fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<Symbol> {
|
||||
let mut target_features = tcx.sess.target_features.clone();
|
||||
let attrs = tcx.codegen_fn_attrs(id);
|
||||
target_features.extend(&attrs.target_features);
|
||||
match attrs.instruction_set {
|
||||
None => {}
|
||||
Some(InstructionSetAttr::ArmA32) => {
|
||||
target_features.remove(&sym::thumb_mode);
|
||||
}
|
||||
Some(InstructionSetAttr::ArmT32) => {
|
||||
target_features.insert(sym::thumb_mode);
|
||||
if tcx.has_codegen_attrs(tcx.def_kind(did)) {
|
||||
let attrs = tcx.codegen_fn_attrs(did);
|
||||
target_features.extend(&attrs.target_features);
|
||||
match attrs.instruction_set {
|
||||
None => {}
|
||||
Some(InstructionSetAttr::ArmA32) => {
|
||||
target_features.remove(&sym::thumb_mode);
|
||||
}
|
||||
Some(InstructionSetAttr::ArmT32) => {
|
||||
target_features.insert(sym::thumb_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tcx.arena.alloc(target_features)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user