diff options
Diffstat (limited to 'compiler/rustc_middle')
| -rw-r--r-- | compiler/rustc_middle/src/query/mod.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/layout.rs | 123 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/query.rs | 1 |
3 files changed, 87 insertions, 58 deletions
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 4296acce1ff..6a1ebbba817 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1128,6 +1128,27 @@ rustc_queries! { 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) -> &'tcx [(CrateNum, LinkagePreference)] { desc { "dylib dependency formats of crate" } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 04d8eaf7c9f..f72f045e907 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -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)) } diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 15a8888ee65..154b26464a8 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -48,6 +48,7 @@ use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::utils::NativeLibKind; use rustc_session::Limits; +use rustc_target::abi; use rustc_target::spec::PanicStrategy; use rustc_ast as ast; |
