Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

store codegen_fn_attrs in crate metadata #96473

Merged
merged 5 commits into from
May 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions compiler/rustc_hir/src/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,43 @@ impl DefKind {
_ => false,
}
}

/// Whether `query get_codegen_attrs` should be used with this definition.
pub fn has_codegen_attrs(self) -> bool {
match self {
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,
}
}
}

/// The resolution of a path or export.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
type_of => { table }
variances_of => { table }
fn_sig => { table }
codegen_fn_attrs => { table }
impl_trait_ref => { table }
const_param_default => { table }
thir_abstract_const => { table }
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +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));
if def_kind.has_codegen_attrs() {
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));
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use rustc_hir::definitions::DefKey;
use rustc_hir::lang_items;
use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
use rustc_middle::mir;
use rustc_middle::thir;
Expand Down Expand Up @@ -329,6 +330,7 @@ define_tables! {
type_of: Table<DefIndex, Lazy!(Ty<'tcx>)>,
variances_of: Table<DefIndex, Lazy<[ty::Variance]>>,
fn_sig: Table<DefIndex, Lazy!(ty::PolyFnSig<'tcx>)>,
codegen_fn_attrs: Table<DefIndex, Lazy!(CodegenFnAttrs)>,
impl_trait_ref: Table<DefIndex, Lazy!(ty::TraitRef<'tcx>)>,
const_param_default: Table<DefIndex, Lazy<rustc_middle::ty::Const<'tcx>>>,
optimized_mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,8 @@ rustc_queries! {
query codegen_fn_attrs(def_id: DefId) -> CodegenFnAttrs {
desc { |tcx| "computing codegen attributes of `{}`", tcx.def_path_str(def_id) }
storage(ArenaCacheSelector<'tcx>)
cache_on_disk_if { true }
cache_on_disk_if { def_id.is_local() }
separate_provide_extern
}

query asm_target_features(def_id: DefId) -> &'tcx FxHashSet<Symbol> {
Expand Down
23 changes: 23 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::dep_graph::{DepGraph, DepKind, DepKindStruct};
use crate::hir::place::Place as HirPlace;
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath};
use crate::middle::stability;
use crate::mir::interpret::{self, Allocation, ConstAllocation, ConstValue, Scalar};
Expand Down Expand Up @@ -1066,6 +1067,28 @@ pub struct GlobalCtxt<'tcx> {
}

impl<'tcx> TyCtxt<'tcx> {
/// Expects a body and returns its codegen attributes.
///
/// Unlike `codegen_fn_attrs`, this returns `CodegenFnAttrs::EMPTY` for
/// constants.
pub fn body_codegen_attrs(self, def_id: DefId) -> &'tcx CodegenFnAttrs {
let def_kind = self.def_kind(def_id);
if def_kind.has_codegen_attrs() {
self.codegen_fn_attrs(def_id)
} else if matches!(
def_kind,
DefKind::AnonConst | DefKind::AssocConst | DefKind::Const | DefKind::InlineConst
) {
CodegenFnAttrs::EMPTY
} else {
bug!(
"body_codegen_fn_attrs called on unexpected definition: {:?} {:?}",
def_id,
def_kind
)
}
}

pub fn typeck_opt_const_arg(
self,
def: ty::WithOptConstParam<LocalDefId>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ 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.body_codegen_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
}
InstanceDef::ClosureOnceShim { call_once: _, track_caller } => track_caller,
_ => false,
Expand Down
41 changes: 21 additions & 20 deletions compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
use rustc_ast as ast;
use rustc_attr as attr;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::BitSet;
use rustc_index::vec::{Idx, IndexVec};
Expand Down Expand Up @@ -2762,14 +2763,22 @@ impl<'tcx> ty::Instance<'tcx> {
/// with `-Cpanic=abort` will look like they can't unwind when in fact they
/// might (from a foreign exception or similar).
#[inline]
pub fn fn_can_unwind<'tcx>(
tcx: TyCtxt<'tcx>,
codegen_fn_attr_flags: CodegenFnAttrFlags,
abi: SpecAbi,
) -> bool {
// Special attribute for functions which can't unwind.
if codegen_fn_attr_flags.contains(CodegenFnAttrFlags::NEVER_UNWIND) {
return false;
pub fn fn_can_unwind<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool {
if let Some(did) = fn_def_id {
// Special attribute for functions which can't unwind.
if tcx.codegen_fn_attrs(did).flags.contains(CodegenFnAttrFlags::NEVER_UNWIND) {
return false;
}

// With -Z panic-in-drop=abort, drop_in_place never unwinds.
//
// This is not part of `codegen_fn_attrs` as it can differ between crates
// and therefore cannot be computed in core.
if tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Abort {
if Some(did) == tcx.lang_items().drop_in_place_fn() {
return false;
}
}
}

// Otherwise if this isn't special then unwinding is generally determined by
Expand Down Expand Up @@ -2991,13 +3000,7 @@ fn fn_abi_of_fn_ptr<'tcx>(
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
let (param_env, (sig, extra_args)) = query.into_parts();

LayoutCx { tcx, param_env }.fn_abi_new_uncached(
sig,
extra_args,
None,
CodegenFnAttrFlags::empty(),
false,
)
LayoutCx { tcx, param_env }.fn_abi_new_uncached(sig, extra_args, None, None, false)
}

fn fn_abi_of_instance<'tcx>(
Expand All @@ -3014,13 +3017,11 @@ fn fn_abi_of_instance<'tcx>(
None
};

let attrs = tcx.codegen_fn_attrs(instance.def_id()).flags;

LayoutCx { tcx, param_env }.fn_abi_new_uncached(
sig,
extra_args,
caller_location,
attrs,
Some(instance.def_id()),
matches!(instance.def, ty::InstanceDef::Virtual(..)),
)
}
Expand All @@ -3033,7 +3034,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
sig: ty::PolyFnSig<'tcx>,
extra_args: &[Ty<'tcx>],
caller_location: Option<Ty<'tcx>>,
codegen_fn_attr_flags: CodegenFnAttrFlags,
fn_def_id: Option<DefId>,
// FIXME(eddyb) replace this with something typed, like an `enum`.
force_thin_self_ptr: bool,
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
Expand Down Expand Up @@ -3205,7 +3206,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
c_variadic: sig.c_variadic,
fixed_count: inputs.len(),
conv,
can_unwind: fn_can_unwind(self.tcx(), codegen_fn_attr_flags, sig.abi),
can_unwind: fn_can_unwind(self.tcx(), fn_def_id, sig.abi),
};
self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?;
debug!("fn_abi_new_uncached = {:?}", fn_abi);
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)>,
Expand Down Expand Up @@ -643,9 +643,8 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
return;
}

let (thir, expr) = match tcx.thir_body(def) {
Ok(body) => body,
Err(_) => return,
let Ok((thir, expr)) = tcx.thir_body(def) else {
return
};
let thir = &thir.borrow();
// If `thir` is empty, a type error occurred, skip this body.
Expand All @@ -661,7 +660,7 @@ 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 = &tcx.body_codegen_attrs(def.did.to_def_id()).target_features;
let safety_context =
if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
let mut visitor = UnsafetyVisitor {
Expand Down
16 changes: 7 additions & 9 deletions compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::MirPass;
use rustc_hir::def::DefKind;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::*;
use rustc_middle::ty::layout;
use rustc_middle::ty::{self, TyCtxt};
Expand Down Expand Up @@ -46,15 +45,14 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
//
// Here we test for this function itself whether its ABI allows
// unwinding or not.
let body_flags = tcx.codegen_fn_attrs(def_id).flags;
let body_ty = tcx.type_of(def_id);
let body_abi = match body_ty.kind() {
ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
ty::Closure(..) => Abi::RustCall,
ty::Generator(..) => Abi::Rust,
_ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty),
};
let body_can_unwind = layout::fn_can_unwind(tcx, body_flags, body_abi);
let body_can_unwind = layout::fn_can_unwind(tcx, Some(def_id), body_abi);

// Look in this function body for any basic blocks which are terminated
// with a function call, and whose function we're calling may unwind.
Expand All @@ -73,19 +71,19 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
TerminatorKind::Call { func, .. } => {
let ty = func.ty(body, tcx);
let sig = ty.fn_sig(tcx);
let flags = match ty.kind() {
ty::FnPtr(_) => CodegenFnAttrFlags::empty(),
ty::FnDef(def_id, _) => tcx.codegen_fn_attrs(*def_id).flags,
let fn_def_id = match ty.kind() {
ty::FnPtr(_) => None,
&ty::FnDef(def_id, _) => Some(def_id),
_ => span_bug!(span, "invalid callee of type {:?}", ty),
};
layout::fn_can_unwind(tcx, flags, sig.abi())
layout::fn_can_unwind(tcx, fn_def_id, sig.abi())
}
TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => {
tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Unwind
&& layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust)
&& layout::fn_can_unwind(tcx, None, Abi::Rust)
}
TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } => {
layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust)
layout::fn_can_unwind(tcx, None, Abi::Rust)
}
_ => continue,
};
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_mir_transform/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,8 @@ 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;
// The body might be a constant, so it doesn't have codegen attributes.
let self_features = &self.tcx.body_codegen_attrs(self.body_did.to_def_id()).target_features;

// Is `callee_features` a subset of `calling_features`?
if !callee_features.iter().all(|feature| self_features.contains(feature)) {
Expand Down
25 changes: 24 additions & 1 deletion compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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));
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
Loading