1
Fork 0

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

@ -1,4 +1,3 @@
use crate::ich::StableHashingContext;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
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_attr as attr;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
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::fmt;
use std::iter;
use std::mem;
use std::num::NonZeroUsize;
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 {
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>;
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.
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> {
Unknown(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 tcx: C,
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> {
// NOTE(eddyb) this is private to avoid using it from outside of
// `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`.
#[derive(Clone, Debug, HashStable)]
pub enum FnAbiError<'tcx> {
/// Error produced by a `layout_of` call, while computing `FnAbi` initially.
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
// just for error handling.
#[derive(Debug)]
pub enum FnAbiRequest<'a, 'tcx> {
OfFnPtr { sig: ty::PolyFnSig<'tcx>, extra_args: &'a [Ty<'tcx>] },
OfInstance { instance: ty::Instance<'tcx>, extra_args: &'a [Ty<'tcx>] },
pub enum FnAbiRequest<'tcx> {
OfFnPtr { sig: ty::PolyFnSig<'tcx>, extra_args: &'tcx ty::List<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.
@ -2855,14 +2842,14 @@ pub trait FnAbiOfHelpers<'tcx>: LayoutOfHelpers<'tcx> {
/// `Self::FnAbiOfResult` (which does not need to be a `Result<...>`).
///
/// 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
/// (and any `FnAbiError`s are turned into fatal errors or ICEs).
fn handle_fn_abi_err(
&self,
err: FnAbiError<'tcx>,
span: Span,
fn_abi_request: FnAbiRequest<'_, 'tcx>,
fn_abi_request: FnAbiRequest<'tcx>,
) -> <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(
&self,
sig: ty::PolyFnSig<'tcx>,
extra_args: &[Ty<'tcx>],
extra_args: &'tcx ty::List<Ty<'tcx>>,
) -> Self::FnAbiOfResult {
// FIXME(eddyb) get a better `span` here.
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(
cx.fn_abi_new_internal(sig, extra_args, None, CodegenFnAttrFlags::empty(), false)
.map_err(|err| {
self.handle_fn_abi_err(err, span, FnAbiRequest::OfFnPtr { sig, extra_args })
}),
)
MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((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
@ -2899,36 +2883,19 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
fn fn_abi_of_instance(
&self,
instance: ty::Instance<'tcx>,
extra_args: &[Ty<'tcx>],
extra_args: &'tcx ty::List<Ty<'tcx>>,
) -> Self::FnAbiOfResult {
// FIXME(eddyb) get a better `span` here.
let span = self.layout_tcx_at_span();
let cx = LayoutCx { tcx: self.tcx().at(span), param_env: self.param_env() };
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;
let tcx = self.tcx().at(span);
MaybeResult::from(
cx.fn_abi_new_internal(
sig,
extra_args,
caller_location,
attrs,
matches!(instance.def, ty::InstanceDef::Virtual(..)),
)
.map_err(|err| {
tcx.fn_abi_of_instance(self.param_env().and((instance, extra_args))).map_err(|err| {
// HACK(eddyb) at least for definitions of/calls to `Instance`s,
// 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
// `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 })
}),
)
@ -2937,10 +2904,50 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
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?)
// arguments of this method, into a separate `struct`.
fn fn_abi_new_internal(
fn fn_abi_new_uncached(
&self,
sig: ty::PolyFnSig<'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`.
force_thin_self_ptr: bool,
) -> 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);
@ -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),
};
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))
}