Querify fn_abi_of_{fn_ptr,instance}.

This commit is contained in:
Eduard-Mihai Burtescu 2021-09-02 00:29:15 +03:00
parent e9b68304ef
commit c1837ef1c5
19 changed files with 152 additions and 93 deletions

View file

@ -53,7 +53,11 @@ pub(crate) fn get_function_sig<'tcx>(
inst: Instance<'tcx>, inst: Instance<'tcx>,
) -> Signature { ) -> Signature {
assert!(!inst.substs.needs_infer()); assert!(!inst.substs.needs_infer());
clif_sig_from_fn_abi(tcx, triple, &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, &[])) clif_sig_from_fn_abi(
tcx,
triple,
&RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()),
)
} }
/// Instance must be monomorphized /// Instance must be monomorphized
@ -350,14 +354,13 @@ pub(crate) fn codegen_terminator_call<'tcx>(
}; };
let extra_args = &args[fn_sig.inputs().len()..]; let extra_args = &args[fn_sig.inputs().len()..];
let extra_args = extra_args let extra_args = fx
.iter() .tcx
.map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))) .mk_type_list(extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))));
.collect::<Vec<_>>();
let fn_abi = if let Some(instance) = instance { let fn_abi = if let Some(instance) = instance {
RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, &extra_args) RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args)
} else { } else {
RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_ty.fn_sig(fx.tcx), &extra_args) RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_ty.fn_sig(fx.tcx), extra_args)
}; };
let is_cold = instance let is_cold = instance
@ -525,7 +528,8 @@ pub(crate) fn codegen_drop<'tcx>(
def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0), def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
substs: drop_instance.substs, substs: drop_instance.substs,
}; };
let fn_abi = RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, &[]); let fn_abi =
RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty());
let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi);
let sig = fx.bcx.import_signature(sig); let sig = fx.bcx.import_signature(sig);
@ -534,7 +538,8 @@ pub(crate) fn codegen_drop<'tcx>(
_ => { _ => {
assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _))); assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _)));
let fn_abi = RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(drop_instance, &[]); let fn_abi =
RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(drop_instance, ty::List::empty());
let arg_value = drop_place.place_ref( let arg_value = drop_place.place_ref(
fx, fx,

View file

@ -61,7 +61,7 @@ pub(crate) fn codegen_fn<'tcx>(
instance, instance,
symbol_name, symbol_name,
mir, mir,
fn_abi: Some(RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, &[])), fn_abi: Some(RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty())),
bcx, bcx,
block_map, block_map,

View file

@ -276,7 +276,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> {
&self, &self,
err: FnAbiError<'tcx>, err: FnAbiError<'tcx>,
span: Span, span: Span,
fn_abi_request: FnAbiRequest<'_, 'tcx>, fn_abi_request: FnAbiRequest<'tcx>,
) -> ! { ) -> ! {
RevealAllLayoutCx(self.tcx).handle_fn_abi_err(err, span, fn_abi_request) RevealAllLayoutCx(self.tcx).handle_fn_abi_err(err, span, fn_abi_request)
} }
@ -402,7 +402,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> {
&self, &self,
err: FnAbiError<'tcx>, err: FnAbiError<'tcx>,
span: Span, span: Span,
fn_abi_request: FnAbiRequest<'_, 'tcx>, fn_abi_request: FnAbiRequest<'tcx>,
) -> ! { ) -> ! {
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
self.0.sess.span_fatal(span, &err.to_string()) self.0.sess.span_fatal(span, &err.to_string())

View file

@ -80,7 +80,10 @@ impl CommentWriter {
vec![ vec![
format!("symbol {}", tcx.symbol_name(instance).name), format!("symbol {}", tcx.symbol_name(instance).name),
format!("instance {:?}", instance), format!("instance {:?}", instance),
format!("abi {:?}", RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, &[])), format!(
"abi {:?}",
RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty())
),
String::new(), String::new(),
] ]
} else { } else {

View file

@ -107,7 +107,7 @@ impl FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
&self, &self,
err: FnAbiError<'tcx>, err: FnAbiError<'tcx>,
span: Span, span: Span,
fn_abi_request: FnAbiRequest<'_, 'tcx>, fn_abi_request: FnAbiRequest<'tcx>,
) -> ! { ) -> ! {
self.cx.handle_fn_abi_err(err, span, fn_abi_request) self.cx.handle_fn_abi_err(err, span, fn_abi_request)
} }

View file

@ -42,7 +42,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value
sym sym
); );
let fn_abi = cx.fn_abi_of_instance(instance, &[]); let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
let llfn = if let Some(llfn) = cx.get_declared_value(&sym) { let llfn = if let Some(llfn) = cx.get_declared_value(&sym) {
// Create a fn pointer with the new signature. // Create a fn pointer with the new signature.

View file

@ -867,7 +867,7 @@ impl FnAbiOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> {
&self, &self,
err: FnAbiError<'tcx>, err: FnAbiError<'tcx>,
span: Span, span: Span,
fn_abi_request: FnAbiRequest<'_, 'tcx>, fn_abi_request: FnAbiRequest<'tcx>,
) -> ! { ) -> ! {
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
self.sess().span_fatal(span, &err.to_string()) self.sess().span_fatal(span, &err.to_string())

View file

@ -208,7 +208,7 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx
hir::Unsafety::Unsafe, hir::Unsafety::Unsafe,
Abi::Rust, Abi::Rust,
)), )),
&[], ty::List::empty(),
), ),
); );

View file

@ -93,7 +93,7 @@ fn make_mir_scope(
ty::ParamEnv::reveal_all(), ty::ParamEnv::reveal_all(),
callee, callee,
); );
let callee_fn_abi = cx.fn_abi_of_instance(callee, &[]); let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty());
cx.dbg_scope_fn(callee, &callee_fn_abi, None) cx.dbg_scope_fn(callee, &callee_fn_abi, None)
} }
None => unsafe { None => unsafe {

View file

@ -737,7 +737,7 @@ fn gen_fn<'ll, 'tcx>(
rust_fn_sig: ty::PolyFnSig<'tcx>, rust_fn_sig: ty::PolyFnSig<'tcx>,
codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>), codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>),
) -> (&'ll Type, &'ll Value) { ) -> (&'ll Type, &'ll Value) {
let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, &[]); let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
let llty = fn_abi.llvm_type(cx); let llty = fn_abi.llvm_type(cx);
let llfn = cx.declare_fn(name, &fn_abi); let llfn = cx.declare_fn(name, &fn_abi);
cx.set_frame_pointer_type(llfn); cx.set_frame_pointer_type(llfn);

View file

@ -52,7 +52,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
) { ) {
assert!(!instance.substs.needs_infer()); assert!(!instance.substs.needs_infer());
let fn_abi = self.fn_abi_of_instance(instance, &[]); let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
let lldecl = self.declare_fn(symbol_name, &fn_abi); let lldecl = self.declare_fn(symbol_name, &fn_abi);
unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) };
let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); let attrs = self.tcx.codegen_fn_attrs(instance.def_id());

View file

@ -230,7 +230,9 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
ty::Adt(def, _) if def.is_box() => { ty::Adt(def, _) if def.is_box() => {
cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx)) cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx))
} }
ty::FnPtr(sig) => cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, &[])), ty::FnPtr(sig) => {
cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty()))
}
_ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO), _ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO),
}; };
cx.scalar_lltypes.borrow_mut().insert(self.ty, llty); cx.scalar_lltypes.borrow_mut().insert(self.ty, llty);

View file

@ -337,7 +337,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
substs: drop_fn.substs, substs: drop_fn.substs,
}; };
let fn_abi = bx.fn_abi_of_instance(virtual_drop, &[]); let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
let vtable = args[1]; let vtable = args[1];
args = &args[..1]; args = &args[..1];
( (
@ -346,7 +346,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
fn_abi, fn_abi,
) )
} }
_ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, &[])), _ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, ty::List::empty())),
}; };
helper.do_call( helper.do_call(
self, self,
@ -433,7 +433,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// Obtain the panic entry point. // Obtain the panic entry point.
let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item); let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
let instance = ty::Instance::mono(bx.tcx(), def_id); let instance = ty::Instance::mono(bx.tcx(), def_id);
let fn_abi = bx.fn_abi_of_instance(instance, &[]); let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
let llfn = bx.get_fn_addr(instance); let llfn = bx.get_fn_addr(instance);
// Codegen the actual panic invoke/call. // Codegen the actual panic invoke/call.
@ -494,7 +494,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let def_id = let def_id =
common::langcall(bx.tcx(), Some(source_info.span), "", LangItem::Panic); common::langcall(bx.tcx(), Some(source_info.span), "", LangItem::Panic);
let instance = ty::Instance::mono(bx.tcx(), def_id); let instance = ty::Instance::mono(bx.tcx(), def_id);
let fn_abi = bx.fn_abi_of_instance(instance, &[]); let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
let llfn = bx.get_fn_addr(instance); let llfn = bx.get_fn_addr(instance);
// Codegen the actual panic invoke/call. // Codegen the actual panic invoke/call.
@ -570,17 +570,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}; };
let extra_args = &args[sig.inputs().skip_binder().len()..]; let extra_args = &args[sig.inputs().skip_binder().len()..];
let extra_args = extra_args let extra_args = bx.tcx().mk_type_list(extra_args.iter().map(|op_arg| {
.iter()
.map(|op_arg| {
let op_ty = op_arg.ty(self.mir, bx.tcx()); let op_ty = op_arg.ty(self.mir, bx.tcx());
self.monomorphize(op_ty) self.monomorphize(op_ty)
}) }));
.collect::<Vec<_>>();
let fn_abi = match instance { let fn_abi = match instance {
Some(instance) => bx.fn_abi_of_instance(instance, &extra_args), Some(instance) => bx.fn_abi_of_instance(instance, extra_args),
None => bx.fn_abi_of_fn_ptr(sig, &extra_args), None => bx.fn_abi_of_fn_ptr(sig, extra_args),
}; };
if intrinsic == Some(sym::transmute) { if intrinsic == Some(sym::transmute) {

View file

@ -139,7 +139,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let mir = cx.tcx().instance_mir(instance.def); let mir = cx.tcx().instance_mir(instance.def);
let fn_abi = cx.fn_abi_of_instance(instance, &[]); let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
debug!("fn_abi: {:?}", fn_abi); debug!("fn_abi: {:?}", fn_abi);
let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir); let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir);

View file

@ -1128,6 +1128,27 @@ rustc_queries! {
desc { "computing layout of `{}`", key.value } desc { "computing layout of `{}`", key.value }
} }
/// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
///
/// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance`
/// instead, where the instance is an `InstanceDef::Virtual`.
query fn_abi_of_fn_ptr(
key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
desc { "computing call ABI of `{}` function pointers", key.value.0 }
}
/// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
/// direct calls to an `fn`.
///
/// NB: that includes virtual calls, which are represented by "direct calls"
/// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
query fn_abi_of_instance(
key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
desc { "computing call ABI of `{}`", key.value.0 }
}
query dylib_dependency_formats(_: CrateNum) query dylib_dependency_formats(_: CrateNum)
-> &'tcx [(CrateNum, LinkagePreference)] { -> &'tcx [(CrateNum, LinkagePreference)] {
desc { "dylib dependency formats of crate" } desc { "dylib dependency formats of crate" }

View file

@ -1,4 +1,3 @@
use crate::ich::StableHashingContext;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
use crate::ty::subst::Subst; use crate::ty::subst::Subst;
@ -6,7 +5,6 @@ use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
use rustc_ast as ast; use rustc_ast as ast;
use rustc_attr as attr; use rustc_attr as attr;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::BitSet; use rustc_index::bit_set::BitSet;
@ -23,10 +21,14 @@ use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Targ
use std::cmp; use std::cmp;
use std::fmt; use std::fmt;
use std::iter; use std::iter;
use std::mem;
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
use std::ops::Bound; use std::ops::Bound;
pub fn provide(providers: &mut ty::query::Providers) {
*providers =
ty::query::Providers { layout_of, fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
}
pub trait IntegerExt { pub trait IntegerExt {
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>; fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>;
fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer; fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer;
@ -191,7 +193,7 @@ pub const FAT_PTR_EXTRA: usize = 1;
/// * Cranelift stores the base-2 log of the lane count in a 4 bit integer. /// * Cranelift stores the base-2 log of the lane count in a 4 bit integer.
pub const MAX_SIMD_LANES: u64 = 1 << 0xF; pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable)] #[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
pub enum LayoutError<'tcx> { pub enum LayoutError<'tcx> {
Unknown(Ty<'tcx>), Unknown(Ty<'tcx>),
SizeOverflow(Ty<'tcx>), SizeOverflow(Ty<'tcx>),
@ -248,10 +250,6 @@ fn layout_of<'tcx>(
}) })
} }
pub fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers { layout_of, ..*providers };
}
pub struct LayoutCx<'tcx, C> { pub struct LayoutCx<'tcx, C> {
pub tcx: C, pub tcx: C,
pub param_env: ty::ParamEnv<'tcx>, pub param_env: ty::ParamEnv<'tcx>,
@ -2537,18 +2535,6 @@ where
} }
} }
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for LayoutError<'tcx> {
#[inline]
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
use crate::ty::layout::LayoutError::*;
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
Unknown(t) | SizeOverflow(t) => t.hash_stable(hcx, hasher),
}
}
}
impl<'tcx> ty::Instance<'tcx> { impl<'tcx> ty::Instance<'tcx> {
// NOTE(eddyb) this is private to avoid using it from outside of // NOTE(eddyb) this is private to avoid using it from outside of
// `fn_abi_of_instance` - any other uses are either too high-level // `fn_abi_of_instance` - any other uses are either too high-level
@ -2807,6 +2793,7 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
} }
/// Error produced by attempting to compute or adjust a `FnAbi`. /// Error produced by attempting to compute or adjust a `FnAbi`.
#[derive(Clone, Debug, HashStable)]
pub enum FnAbiError<'tcx> { pub enum FnAbiError<'tcx> {
/// Error produced by a `layout_of` call, while computing `FnAbi` initially. /// Error produced by a `layout_of` call, while computing `FnAbi` initially.
Layout(LayoutError<'tcx>), Layout(LayoutError<'tcx>),
@ -2839,9 +2826,9 @@ impl<'tcx> fmt::Display for FnAbiError<'tcx> {
// FIXME(eddyb) maybe use something like this for an unified `fn_abi_of`, not // FIXME(eddyb) maybe use something like this for an unified `fn_abi_of`, not
// just for error handling. // just for error handling.
#[derive(Debug)] #[derive(Debug)]
pub enum FnAbiRequest<'a, 'tcx> { pub enum FnAbiRequest<'tcx> {
OfFnPtr { sig: ty::PolyFnSig<'tcx>, extra_args: &'a [Ty<'tcx>] }, OfFnPtr { sig: ty::PolyFnSig<'tcx>, extra_args: &'tcx ty::List<Ty<'tcx>> },
OfInstance { instance: ty::Instance<'tcx>, extra_args: &'a [Ty<'tcx>] }, OfInstance { instance: ty::Instance<'tcx>, extra_args: &'tcx ty::List<Ty<'tcx>> },
} }
/// Trait for contexts that want to be able to compute `FnAbi`s. /// Trait for contexts that want to be able to compute `FnAbi`s.
@ -2855,14 +2842,14 @@ pub trait FnAbiOfHelpers<'tcx>: LayoutOfHelpers<'tcx> {
/// `Self::FnAbiOfResult` (which does not need to be a `Result<...>`). /// `Self::FnAbiOfResult` (which does not need to be a `Result<...>`).
/// ///
/// Most `impl`s, which propagate `FnAbiError`s, should simply return `err`, /// Most `impl`s, which propagate `FnAbiError`s, should simply return `err`,
/// but this hook allows e.g. codegen to return only `&FnABi` from its /// but this hook allows e.g. codegen to return only `&FnAbi` from its
/// `cx.fn_abi_of_*(...)`, without any `Result<...>` around it to deal with /// `cx.fn_abi_of_*(...)`, without any `Result<...>` around it to deal with
/// (and any `FnAbiError`s are turned into fatal errors or ICEs). /// (and any `FnAbiError`s are turned into fatal errors or ICEs).
fn handle_fn_abi_err( fn handle_fn_abi_err(
&self, &self,
err: FnAbiError<'tcx>, err: FnAbiError<'tcx>,
span: Span, span: Span,
fn_abi_request: FnAbiRequest<'_, 'tcx>, fn_abi_request: FnAbiRequest<'tcx>,
) -> <Self::FnAbiOfResult as MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>>>::Error; ) -> <Self::FnAbiOfResult as MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>>>::Error;
} }
@ -2876,18 +2863,15 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
fn fn_abi_of_fn_ptr( fn fn_abi_of_fn_ptr(
&self, &self,
sig: ty::PolyFnSig<'tcx>, sig: ty::PolyFnSig<'tcx>,
extra_args: &[Ty<'tcx>], extra_args: &'tcx ty::List<Ty<'tcx>>,
) -> Self::FnAbiOfResult { ) -> Self::FnAbiOfResult {
// FIXME(eddyb) get a better `span` here. // FIXME(eddyb) get a better `span` here.
let span = self.layout_tcx_at_span(); let span = self.layout_tcx_at_span();
let cx = LayoutCx { tcx: self.tcx().at(span), param_env: self.param_env() }; let tcx = self.tcx().at(span);
MaybeResult::from( MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err(
cx.fn_abi_new_internal(sig, extra_args, None, CodegenFnAttrFlags::empty(), false) |err| self.handle_fn_abi_err(err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
.map_err(|err| { ))
self.handle_fn_abi_err(err, span, FnAbiRequest::OfFnPtr { sig, extra_args })
}),
)
} }
/// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
@ -2899,36 +2883,19 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
fn fn_abi_of_instance( fn fn_abi_of_instance(
&self, &self,
instance: ty::Instance<'tcx>, instance: ty::Instance<'tcx>,
extra_args: &[Ty<'tcx>], extra_args: &'tcx ty::List<Ty<'tcx>>,
) -> Self::FnAbiOfResult { ) -> Self::FnAbiOfResult {
// FIXME(eddyb) get a better `span` here. // FIXME(eddyb) get a better `span` here.
let span = self.layout_tcx_at_span(); let span = self.layout_tcx_at_span();
let cx = LayoutCx { tcx: self.tcx().at(span), param_env: self.param_env() }; let tcx = self.tcx().at(span);
let sig = instance.fn_sig_for_fn_abi(cx.tcx());
let caller_location = if instance.def.requires_caller_location(cx.tcx()) {
Some(cx.tcx.caller_location_ty())
} else {
None
};
let attrs = cx.tcx.codegen_fn_attrs(instance.def_id()).flags;
MaybeResult::from( MaybeResult::from(
cx.fn_abi_new_internal( tcx.fn_abi_of_instance(self.param_env().and((instance, extra_args))).map_err(|err| {
sig,
extra_args,
caller_location,
attrs,
matches!(instance.def, ty::InstanceDef::Virtual(..)),
)
.map_err(|err| {
// HACK(eddyb) at least for definitions of/calls to `Instance`s, // HACK(eddyb) at least for definitions of/calls to `Instance`s,
// we can get some kind of span even if one wasn't provided. // we can get some kind of span even if one wasn't provided.
// However, we don't do this early in order to avoid calling // However, we don't do this early in order to avoid calling
// `def_span` unconditionally (which may have a perf penalty). // `def_span` unconditionally (which may have a perf penalty).
let span = if !span.is_dummy() { span } else { cx.tcx.def_span(instance.def_id()) }; let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) };
self.handle_fn_abi_err(err, span, FnAbiRequest::OfInstance { instance, extra_args }) self.handle_fn_abi_err(err, span, FnAbiRequest::OfInstance { instance, extra_args })
}), }),
) )
@ -2937,10 +2904,50 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
impl<C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {} impl<C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {}
impl<'tcx> LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> { fn fn_abi_of_fn_ptr<'tcx>(
tcx: TyCtxt<'tcx>,
query: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'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,
)
}
fn fn_abi_of_instance<'tcx>(
tcx: TyCtxt<'tcx>,
query: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
let (param_env, (instance, extra_args)) = query.into_parts();
let sig = instance.fn_sig_for_fn_abi(tcx);
let caller_location = if instance.def.requires_caller_location(tcx) {
Some(tcx.caller_location_ty())
} else {
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,
matches!(instance.def, ty::InstanceDef::Virtual(..)),
)
}
impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
// FIXME(eddyb) perhaps group the signature/type-containing (or all of them?) // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
// arguments of this method, into a separate `struct`. // arguments of this method, into a separate `struct`.
fn fn_abi_new_internal( fn fn_abi_new_uncached(
&self, &self,
sig: ty::PolyFnSig<'tcx>, sig: ty::PolyFnSig<'tcx>,
extra_args: &[Ty<'tcx>], extra_args: &[Ty<'tcx>],
@ -2949,7 +2956,7 @@ impl<'tcx> LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
// FIXME(eddyb) replace this with something typed, like an `enum`. // FIXME(eddyb) replace this with something typed, like an `enum`.
force_thin_self_ptr: bool, force_thin_self_ptr: bool,
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args); debug!("fn_abi_new_uncached({:?}, {:?})", sig, extra_args);
let sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, sig); let sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, sig);
@ -3110,7 +3117,7 @@ impl<'tcx> LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
can_unwind: fn_can_unwind(self.tcx(), codegen_fn_attr_flags, sig.abi), can_unwind: fn_can_unwind(self.tcx(), codegen_fn_attr_flags, sig.abi),
}; };
self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?; self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?;
debug!("FnAbi::new_internal = {:?}", fn_abi); debug!("fn_abi_new_uncached = {:?}", fn_abi);
Ok(self.tcx.intern_fn_abi(fn_abi)) Ok(self.tcx.intern_fn_abi(fn_abi))
} }

View file

@ -48,6 +48,7 @@ use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
use rustc_session::utils::NativeLibKind; use rustc_session::utils::NativeLibKind;
use rustc_session::Limits; use rustc_session::Limits;
use rustc_target::abi;
use rustc_target::spec::PanicStrategy; use rustc_target::spec::PanicStrategy;
use rustc_ast as ast; use rustc_ast as ast;

View file

@ -449,3 +449,25 @@ impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
DUMMY_SP DUMMY_SP
} }
} }
impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.0.default_span(tcx)
}
}

View file

@ -601,6 +601,7 @@ pub struct FnAbi<'a, Ty> {
} }
/// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI. /// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI.
#[derive(Clone, Debug, HashStable_Generic)]
pub enum AdjustForForeignAbiError { pub enum AdjustForForeignAbiError {
/// Target architecture doesn't support "foreign" (i.e. non-Rust) ABIs. /// Target architecture doesn't support "foreign" (i.e. non-Rust) ABIs.
Unsupported { arch: String, abi: spec::abi::Abi }, Unsupported { arch: String, abi: spec::abi::Abi },