From a1d7c51d27734f5af98e96d26a50357d6e145009 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 24 Aug 2021 20:42:32 +0300 Subject: [PATCH 01/10] ty::layout: move `trait FnAbiExt` to just before its `impl`. --- compiler/rustc_middle/src/ty/layout.rs | 56 +++++++++++++------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 1bea1cbc3b94b..83bb6b15262fd 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2633,34 +2633,6 @@ impl<'tcx> ty::Instance<'tcx> { } } -pub trait FnAbiExt<'tcx, C> -where - C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec, -{ - /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. - /// - /// NB: this doesn't handle virtual calls - those should use `FnAbi::of_instance` - /// instead, where the instance is an `InstanceDef::Virtual`. - fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; - - /// 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 `::fn`). - fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; - - fn new_internal( - cx: &C, - sig: ty::PolyFnSig<'tcx>, - extra_args: &[Ty<'tcx>], - caller_location: Option>, - codegen_fn_attr_flags: CodegenFnAttrFlags, - make_self_ptr_thin: bool, - ) -> Self; - fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi); -} - /// Calculates whether a function's ABI can unwind or not. /// /// This takes two primary parameters: @@ -2816,6 +2788,34 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv { } } +pub trait FnAbiExt<'tcx, C> +where + C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec, +{ + /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. + /// + /// NB: this doesn't handle virtual calls - those should use `FnAbi::of_instance` + /// instead, where the instance is an `InstanceDef::Virtual`. + fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; + + /// 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 `::fn`). + fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; + + fn new_internal( + cx: &C, + sig: ty::PolyFnSig<'tcx>, + extra_args: &[Ty<'tcx>], + caller_location: Option>, + codegen_fn_attr_flags: CodegenFnAttrFlags, + make_self_ptr_thin: bool, + ) -> Self; + fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi); +} + impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>> where C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec, From feca7d0a03ffe1c786f6fe00330b6d2df59bcfef Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 24 Aug 2021 20:45:37 +0300 Subject: [PATCH 02/10] ty::layout: split out a private trait from `FnAbiExt`. --- compiler/rustc_middle/src/ty/layout.rs | 31 +++++++++++++++++--------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 83bb6b15262fd..793dda5c928bc 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2804,16 +2804,6 @@ where /// NB: that includes virtual calls, which are represented by "direct calls" /// to an `InstanceDef::Virtual` instance (of `::fn`). fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; - - fn new_internal( - cx: &C, - sig: ty::PolyFnSig<'tcx>, - extra_args: &[Ty<'tcx>], - caller_location: Option>, - codegen_fn_attr_flags: CodegenFnAttrFlags, - make_self_ptr_thin: bool, - ) -> Self; - fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi); } impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>> @@ -2844,7 +2834,28 @@ where matches!(instance.def, ty::InstanceDef::Virtual(..)), ) } +} + +/// Implementation detail of computing `FnAbi`s, shouldn't be exported. +trait FnAbiInternalExt<'tcx, C> +where + C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec, +{ + fn new_internal( + cx: &C, + sig: ty::PolyFnSig<'tcx>, + extra_args: &[Ty<'tcx>], + caller_location: Option>, + codegen_fn_attr_flags: CodegenFnAttrFlags, + make_self_ptr_thin: bool, + ) -> Self; + fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi); +} +impl<'tcx, C> FnAbiInternalExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>> +where + C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec, +{ fn new_internal( cx: &C, sig: ty::PolyFnSig<'tcx>, From 4d36faf9ef10bda32c606517d0f2007fd53b16ac Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 25 Aug 2021 11:50:26 +0300 Subject: [PATCH 03/10] rustc_target: `adjust_for_cabi` -> `adjust_for_foreign_abi`. --- compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_target/src/abi/call/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 793dda5c928bc..95dda620cd445 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -3098,7 +3098,7 @@ where return; } - if let Err(msg) = self.adjust_for_cabi(cx, abi) { + if let Err(msg) = self.adjust_for_foreign_abi(cx, abi) { cx.tcx().sess.fatal(&msg); } } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 927bebd8157a6..bce86ca809d2a 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -600,7 +600,7 @@ pub struct FnAbi<'a, Ty> { } impl<'a, Ty> FnAbi<'a, Ty> { - pub fn adjust_for_cabi(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String> + pub fn adjust_for_foreign_abi(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String> where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, From 7f2f927eb81c75fd0f8e5900588eb962be0a4be9 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 26 Aug 2021 19:01:55 +0300 Subject: [PATCH 04/10] ty::layout: propagate errors up to (but not out of) `FnAbi::of_*`. --- compiler/rustc_middle/src/ty/layout.rs | 129 +++++++++++++++++----- compiler/rustc_target/src/abi/call/mod.rs | 27 ++++- 2 files changed, 129 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 95dda620cd445..e11993c758099 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -18,7 +18,7 @@ use rustc_target::abi::call::{ ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind, }; use rustc_target::abi::*; -use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy}; +use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target}; use std::cmp; use std::fmt; @@ -2015,6 +2015,12 @@ impl<'tcx> HasDataLayout for TyCtxt<'tcx> { } } +impl<'tcx> HasTargetSpec for TyCtxt<'tcx> { + fn target_spec(&self) -> &Target { + &self.sess.target + } +} + impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { @@ -2048,6 +2054,12 @@ impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> { } } +impl<'tcx, T: HasTargetSpec> HasTargetSpec for LayoutCx<'tcx, T> { + fn target_spec(&self) -> &Target { + self.tcx.target_spec() + } +} + impl<'tcx, T: HasTyCtxt<'tcx>> HasTyCtxt<'tcx> for LayoutCx<'tcx, T> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx.tcx() @@ -2788,9 +2800,39 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv { } } +/// Error produced by attempting to compute or adjust a `FnAbi`. +enum FnAbiError<'tcx> { + /// Error produced by a `layout_of` call, while computing `FnAbi` initially. + Layout(LayoutError<'tcx>), + + /// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI. + AdjustForForeignAbi(call::AdjustForForeignAbiError), +} + +impl From> for FnAbiError<'tcx> { + fn from(err: LayoutError<'tcx>) -> Self { + Self::Layout(err) + } +} + +impl From for FnAbiError<'_> { + fn from(err: call::AdjustForForeignAbiError) -> Self { + Self::AdjustForForeignAbi(err) + } +} + +impl<'tcx> fmt::Display for FnAbiError<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Layout(err) => err.fmt(f), + Self::AdjustForForeignAbi(err) => err.fmt(f), + } + } +} + pub trait FnAbiExt<'tcx, C> where - C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec, + C: HasTyCtxt<'tcx> + HasParamEnv<'tcx>, { /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. /// @@ -2808,10 +2850,26 @@ where impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>> where - C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec, + C: HasTyCtxt<'tcx> + HasParamEnv<'tcx>, { fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { - call::FnAbi::new_internal(cx, sig, extra_args, None, CodegenFnAttrFlags::empty(), false) + call::FnAbi::new_internal( + &LayoutCx { tcx: cx.tcx(), param_env: cx.param_env() }, + sig, + extra_args, + None, + CodegenFnAttrFlags::empty(), + false, + ) + .unwrap_or_else(|err| { + // FIXME(eddyb) get a better `span` here. + let span = DUMMY_SP; + if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { + cx.tcx().sess.span_fatal(span, &err.to_string()) + } else { + span_bug!(span, "`FnAbi::of_fn_ptr({}, {:?})` failed: {}", sig, extra_args, err); + } + }) } fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { @@ -2826,35 +2884,57 @@ where let attrs = cx.tcx().codegen_fn_attrs(instance.def_id()).flags; call::FnAbi::new_internal( - cx, + &LayoutCx { tcx: cx.tcx(), param_env: cx.param_env() }, sig, extra_args, caller_location, attrs, matches!(instance.def, ty::InstanceDef::Virtual(..)), ) + .unwrap_or_else(|err| { + // FIXME(eddyb) get a better `span` here. + let span = cx.tcx().def_span(instance.def_id()); + if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { + cx.tcx().sess.span_fatal(span, &err.to_string()) + } else { + span_bug!( + span, + "`FnAbi::of_instance({}, {:?})` failed: {}", + instance, + extra_args, + err + ); + } + }) } } /// Implementation detail of computing `FnAbi`s, shouldn't be exported. -trait FnAbiInternalExt<'tcx, C> +// FIXME(eddyb) move this off of being generic on `C: LayoutOf`, and +// explicitly take `LayoutCx` *or* `TyCtxt` and `ParamEnvAnd<...>`. +trait FnAbiInternalExt<'tcx, C>: Sized where - C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec, + C: LayoutOf<'tcx, LayoutOfResult = Result, LayoutError<'tcx>>> + + HasTargetSpec, { + // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?) + // arguments of this method, into a separate `struct`. fn new_internal( cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>], caller_location: Option>, codegen_fn_attr_flags: CodegenFnAttrFlags, + // FIXME(eddyb) replace this with something typed, like an `enum`. make_self_ptr_thin: bool, - ) -> Self; - fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi); + ) -> Result>; + fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) -> Result<(), FnAbiError<'tcx>>; } impl<'tcx, C> FnAbiInternalExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>> where - C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec, + C: LayoutOf<'tcx, LayoutOfResult = Result, LayoutError<'tcx>>> + + HasTargetSpec, { fn new_internal( cx: &C, @@ -2863,10 +2943,10 @@ where caller_location: Option>, codegen_fn_attr_flags: CodegenFnAttrFlags, force_thin_self_ptr: bool, - ) -> Self { + ) -> Result> { debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args); - let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); + let sig = cx.tcx().normalize_erasing_late_bound_regions(cx.param_env(), sig); let conv = conv_from_spec_abi(cx.tcx(), sig.abi); @@ -2972,10 +3052,10 @@ where } }; - let arg_of = |ty: Ty<'tcx>, arg_idx: Option| { + let arg_of = |ty: Ty<'tcx>, arg_idx: Option| -> Result<_, FnAbiError<'tcx>> { let is_return = arg_idx.is_none(); - let layout = cx.layout_of(ty); + let layout = cx.layout_of(ty)?; let layout = if force_thin_self_ptr && arg_idx == Some(0) { // Don't pass the vtable, it's not an argument of the virtual fn. // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait` @@ -3006,11 +3086,11 @@ where } } - arg + Ok(arg) }; let mut fn_abi = FnAbi { - ret: arg_of(sig.output(), None), + ret: arg_of(sig.output(), None)?, args: inputs .iter() .cloned() @@ -3018,20 +3098,20 @@ where .chain(caller_location) .enumerate() .map(|(i, ty)| arg_of(ty, Some(i))) - .collect(), + .collect::>()?, c_variadic: sig.c_variadic, fixed_count: inputs.len(), conv, can_unwind: fn_can_unwind(cx.tcx(), codegen_fn_attr_flags, sig.abi), }; - fn_abi.adjust_for_abi(cx, sig.abi); + fn_abi.adjust_for_abi(cx, sig.abi)?; debug!("FnAbi::new_internal = {:?}", fn_abi); - fn_abi + Ok(fn_abi) } - fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) { + fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) -> Result<(), FnAbiError<'tcx>> { if abi == SpecAbi::Unadjusted { - return; + return Ok(()); } if abi == SpecAbi::Rust @@ -3095,12 +3175,11 @@ where for arg in &mut self.args { fixup(arg); } - return; + } else { + self.adjust_for_foreign_abi(cx, abi)?; } - if let Err(msg) = self.adjust_for_foreign_abi(cx, abi) { - cx.tcx().sess.fatal(&msg); - } + Ok(()) } } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index bce86ca809d2a..75c526c97414f 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -1,6 +1,7 @@ use crate::abi::{self, Abi, Align, FieldsShape, Size}; use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout}; use crate::spec::{self, HasTargetSpec}; +use std::fmt; mod aarch64; mod amdgpu; @@ -599,8 +600,28 @@ pub struct FnAbi<'a, Ty> { pub can_unwind: bool, } +/// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI. +pub enum AdjustForForeignAbiError { + /// Target architecture doesn't support "foreign" (i.e. non-Rust) ABIs. + Unsupported { arch: String, abi: spec::abi::Abi }, +} + +impl fmt::Display for AdjustForForeignAbiError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Unsupported { arch, abi } => { + write!(f, "target architecture {:?} does not support `extern {}` ABI", arch, abi) + } + } + } +} + impl<'a, Ty> FnAbi<'a, Ty> { - pub fn adjust_for_foreign_abi(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String> + pub fn adjust_for_foreign_abi( + &mut self, + cx: &C, + abi: spec::abi::Abi, + ) -> Result<(), AdjustForForeignAbiError> where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, @@ -655,7 +676,9 @@ impl<'a, Ty> FnAbi<'a, Ty> { } "asmjs" => wasm::compute_c_abi_info(cx, self), "bpf" => bpf::compute_abi_info(self), - a => return Err(format!("unrecognized arch \"{}\" in target specification", a)), + arch => { + return Err(AdjustForForeignAbiError::Unsupported { arch: arch.to_string(), abi }); + } } Ok(()) From 0c02e3f550dbebe297f897b03be4e9dd3454695e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 26 Aug 2021 19:47:07 +0300 Subject: [PATCH 05/10] ty::context: move interning `Allocation`s and `Layout`s to `direct_interners!`. --- compiler/rustc_middle/src/ty/context.rs | 81 ++++++++----------------- 1 file changed, 26 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1f5057d1da22f..7cd5584c3589b 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -118,8 +118,8 @@ pub struct CtxtInterners<'tcx> { /// The arena that types, regions, etc. are allocated from. arena: &'tcx WorkerLocal>, - /// Specifically use a speedy hash algorithm for these hash sets, since - /// they're accessed quite often. + // Specifically use a speedy hash algorithm for these hash sets, since + // they're accessed quite often. type_: InternedSet<'tcx, TyS<'tcx>>, type_list: InternedSet<'tcx, List>>, substs: InternedSet<'tcx, InternalSubsts<'tcx>>, @@ -132,9 +132,9 @@ pub struct CtxtInterners<'tcx> { projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, const_: InternedSet<'tcx, Const<'tcx>>, - /// Const allocations. - allocation: InternedSet<'tcx, Allocation>, + const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List>, + layout: InternedSet<'tcx, Layout>, } impl<'tcx> CtxtInterners<'tcx> { @@ -152,8 +152,9 @@ impl<'tcx> CtxtInterners<'tcx> { projs: Default::default(), place_elems: Default::default(), const_: Default::default(), - allocation: Default::default(), + const_allocation: Default::default(), bound_variable_kinds: Default::default(), + layout: Default::default(), } } @@ -1062,10 +1063,9 @@ pub struct GlobalCtxt<'tcx> { /// Stores memory for globals (statics/consts). pub(crate) alloc_map: Lock>, - layout_interner: ShardedHashMap<&'tcx Layout, ()>, - output_filenames: Arc, + // FIXME(eddyb) this doesn't belong here and should be using a query. pub(super) vtables_cache: Lock, Option>), AllocId>>, } @@ -1107,13 +1107,6 @@ impl<'tcx> TyCtxt<'tcx> { self.arena.alloc(ty::AdtDef::new(self, did, kind, variants, repr)) } - pub fn intern_const_alloc(self, alloc: Allocation) -> &'tcx Allocation { - self.interners - .allocation - .intern(alloc, |alloc| Interned(self.interners.arena.alloc(alloc))) - .0 - } - /// Allocates a read-only byte or string literal for `mir::interpret`. pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId { // Create an allocation that just contains these bytes. @@ -1122,20 +1115,19 @@ impl<'tcx> TyCtxt<'tcx> { self.create_memory_alloc(alloc) } + // FIXME(eddyb) move to `direct_interners!`. pub fn intern_stability(self, stab: attr::Stability) -> &'tcx attr::Stability { self.stability_interner.intern(stab, |stab| self.arena.alloc(stab)) } + // FIXME(eddyb) move to `direct_interners!`. pub fn intern_const_stability(self, stab: attr::ConstStability) -> &'tcx attr::ConstStability { self.const_stability_interner.intern(stab, |stab| self.arena.alloc(stab)) } - pub fn intern_layout(self, layout: Layout) -> &'tcx Layout { - self.layout_interner.intern(layout, |layout| self.arena.alloc(layout)) - } - /// Returns a range of the start/end indices specified with the /// `rustc_layout_scalar_valid_range` attribute. + // FIXME(eddyb) this is an awkward spot for this method, maybe move it? pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound, Bound) { let attrs = self.get_attrs(def_id); let get = |name| { @@ -1210,7 +1202,6 @@ impl<'tcx> TyCtxt<'tcx> { evaluation_cache: Default::default(), crate_name: Symbol::intern(crate_name), data_layout, - layout_interner: Default::default(), stability_interner: Default::default(), const_stability_interner: Default::default(), alloc_map: Lock::new(interpret::AllocMap::new()), @@ -1670,7 +1661,7 @@ macro_rules! nop_list_lift { nop_lift! {type_; Ty<'a> => Ty<'tcx>} nop_lift! {region; Region<'a> => Region<'tcx>} nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>} -nop_lift! {allocation; &'a Allocation => &'tcx Allocation} +nop_lift! {const_allocation; &'a Allocation => &'tcx Allocation} nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>} nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>} @@ -1962,8 +1953,12 @@ impl<'tcx> TyCtxt<'tcx> { "Const Stability interner: #{}", self.0.const_stability_interner.len() )?; - writeln!(fmt, "Allocation interner: #{}", self.0.interners.allocation.len())?; - writeln!(fmt, "Layout interner: #{}", self.0.layout_interner.len())?; + writeln!( + fmt, + "Const Allocation interner: #{}", + self.0.interners.const_allocation.len() + )?; + writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?; Ok(()) } @@ -2051,38 +2046,6 @@ impl<'tcx, T> Borrow<[T]> for Interned<'tcx, List> { } } -impl<'tcx> Borrow for Interned<'tcx, RegionKind> { - fn borrow(&self) -> &RegionKind { - &self.0 - } -} - -impl<'tcx> Borrow> for Interned<'tcx, Const<'tcx>> { - fn borrow<'a>(&'a self) -> &'a Const<'tcx> { - &self.0 - } -} - -impl<'tcx> Borrow for Interned<'tcx, Allocation> { - fn borrow<'a>(&'a self) -> &'a Allocation { - &self.0 - } -} - -impl<'tcx> PartialEq for Interned<'tcx, Allocation> { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} - -impl<'tcx> Eq for Interned<'tcx, Allocation> {} - -impl<'tcx> Hash for Interned<'tcx, Allocation> { - fn hash(&self, s: &mut H) { - self.0.hash(s) - } -} - macro_rules! direct_interners { ($($name:ident: $method:ident($ty:ty),)+) => { $(impl<'tcx> PartialEq for Interned<'tcx, $ty> { @@ -2099,9 +2062,15 @@ macro_rules! direct_interners { } } + impl<'tcx> Borrow<$ty> for Interned<'tcx, $ty> { + fn borrow<'a>(&'a self) -> &'a $ty { + &self.0 + } + } + impl<'tcx> TyCtxt<'tcx> { pub fn $method(self, v: $ty) -> &'tcx $ty { - self.interners.$name.intern_ref(&v, || { + self.interners.$name.intern(v, |v| { Interned(self.interners.arena.alloc(v)) }).0 } @@ -2112,6 +2081,8 @@ macro_rules! direct_interners { direct_interners! { region: mk_region(RegionKind), const_: mk_const(Const<'tcx>), + const_allocation: intern_const_alloc(Allocation), + layout: intern_layout(Layout), } macro_rules! slice_interners { From 344df76fed727b565b905f3f32ee467f8e3aec2d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 26 Aug 2021 21:58:34 +0300 Subject: [PATCH 06/10] ty::layout: intern `FnAbi`s as `&'tcx`. --- .../rustc_codegen_cranelift/src/common.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/mod.rs | 2 +- compiler/rustc_middle/src/arena.rs | 3 ++- compiler/rustc_middle/src/ty/context.rs | 5 +++++ compiler/rustc_middle/src/ty/layout.rs | 16 +++++++------- compiler/rustc_target/src/abi/call/mod.rs | 22 +++++++++---------- 7 files changed, 29 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 6f7ca51d038c0..06d1fc717cc92 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -239,7 +239,7 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { pub(crate) instance: Instance<'tcx>, pub(crate) symbol_name: SymbolName<'tcx>, pub(crate) mir: &'tcx Body<'tcx>, - pub(crate) fn_abi: Option>>, + pub(crate) fn_abi: Option<&'tcx FnAbi<'tcx, Ty<'tcx>>>, pub(crate) bcx: FunctionBuilder<'clif>, pub(crate) block_map: IndexVec, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index cd0e9354c2441..c557946afbc4b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -124,7 +124,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { &self, fx: &mut FunctionCx<'a, 'tcx, Bx>, bx: &mut Bx, - fn_abi: FnAbi<'tcx, Ty<'tcx>>, + fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>, fn_ptr: Bx::Value, llargs: &[Bx::Value], destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>, diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index e2edd44826717..2c7636f1913dd 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -29,7 +29,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { cx: &'a Bx::CodegenCx, - fn_abi: FnAbi<'tcx, Ty<'tcx>>, + fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>, /// When unwinding is initiated, we have to store this personality /// value somewhere so that we can load it and re-use it in the diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 59db2c6636ff9..2dd43a4e8522d 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -11,7 +11,8 @@ macro_rules! arena_types { ($macro:path, $tcx:lifetime) => ( $macro!([ - [] layouts: rustc_target::abi::Layout, + [] layout: rustc_target::abi::Layout, + [] fn_abi: rustc_target::abi::call::FnAbi<$tcx, rustc_middle::ty::Ty<$tcx>>, // AdtDef are interned and compared by address [] adt_def: rustc_middle::ty::AdtDef, [] steal_thir: rustc_data_structures::steal::Steal>, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 7cd5584c3589b..e803a667879a1 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -55,6 +55,7 @@ use rustc_span::def_id::{DefPathHash, StableCrateId}; use rustc_span::source_map::{MultiSpan, SourceMap}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; +use rustc_target::abi::call::FnAbi; use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; @@ -135,6 +136,7 @@ pub struct CtxtInterners<'tcx> { const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List>, layout: InternedSet<'tcx, Layout>, + fn_abi: InternedSet<'tcx, FnAbi<'tcx, Ty<'tcx>>>, } impl<'tcx> CtxtInterners<'tcx> { @@ -155,6 +157,7 @@ impl<'tcx> CtxtInterners<'tcx> { const_allocation: Default::default(), bound_variable_kinds: Default::default(), layout: Default::default(), + fn_abi: Default::default(), } } @@ -1959,6 +1962,7 @@ impl<'tcx> TyCtxt<'tcx> { self.0.interners.const_allocation.len() )?; writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?; + writeln!(fmt, "FnAbi interner: #{}", self.0.interners.fn_abi.len())?; Ok(()) } @@ -2083,6 +2087,7 @@ direct_interners! { const_: mk_const(Const<'tcx>), const_allocation: intern_const_alloc(Allocation), layout: intern_layout(Layout), + fn_abi: intern_fn_abi(FnAbi<'tcx, Ty<'tcx>>), } macro_rules! slice_interners { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index e11993c758099..42ac77054190a 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2838,21 +2838,21 @@ where /// /// NB: this doesn't handle virtual calls - those should use `FnAbi::of_instance` /// instead, where the instance is an `InstanceDef::Virtual`. - fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; + fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> &'tcx Self; /// 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 `::fn`). - fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; + fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> &'tcx Self; } impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>> where C: HasTyCtxt<'tcx> + HasParamEnv<'tcx>, { - fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { + fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> &'tcx Self { call::FnAbi::new_internal( &LayoutCx { tcx: cx.tcx(), param_env: cx.param_env() }, sig, @@ -2872,7 +2872,7 @@ where }) } - fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { + fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> &'tcx Self { let sig = instance.fn_sig_for_fn_abi(cx.tcx()); let caller_location = if instance.def.requires_caller_location(cx.tcx()) { @@ -2912,7 +2912,7 @@ where /// Implementation detail of computing `FnAbi`s, shouldn't be exported. // FIXME(eddyb) move this off of being generic on `C: LayoutOf`, and // explicitly take `LayoutCx` *or* `TyCtxt` and `ParamEnvAnd<...>`. -trait FnAbiInternalExt<'tcx, C>: Sized +trait FnAbiInternalExt<'tcx, C> where C: LayoutOf<'tcx, LayoutOfResult = Result, LayoutError<'tcx>>> + HasTargetSpec, @@ -2927,7 +2927,7 @@ where codegen_fn_attr_flags: CodegenFnAttrFlags, // FIXME(eddyb) replace this with something typed, like an `enum`. make_self_ptr_thin: bool, - ) -> Result>; + ) -> Result<&'tcx Self, FnAbiError<'tcx>>; fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) -> Result<(), FnAbiError<'tcx>>; } @@ -2943,7 +2943,7 @@ where caller_location: Option>, codegen_fn_attr_flags: CodegenFnAttrFlags, force_thin_self_ptr: bool, - ) -> Result> { + ) -> Result<&'tcx Self, FnAbiError<'tcx>> { debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args); let sig = cx.tcx().normalize_erasing_late_bound_regions(cx.param_env(), sig); @@ -3106,7 +3106,7 @@ where }; fn_abi.adjust_for_abi(cx, sig.abi)?; debug!("FnAbi::new_internal = {:?}", fn_abi); - Ok(fn_abi) + Ok(cx.tcx().intern_fn_abi(fn_abi)) } fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) -> Result<(), FnAbiError<'tcx>> { diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 75c526c97414f..6f06f2b56ada6 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -25,7 +25,7 @@ mod x86; mod x86_64; mod x86_win64; -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum PassMode { /// Ignore the argument. /// @@ -60,7 +60,7 @@ pub use attr_impl::ArgAttribute; mod attr_impl { // The subset of llvm::Attribute needed for arguments, packed into a bitfield. bitflags::bitflags! { - #[derive(Default)] + #[derive(Default, HashStable_Generic)] pub struct ArgAttribute: u16 { const NoAlias = 1 << 1; const NoCapture = 1 << 2; @@ -77,7 +77,7 @@ mod attr_impl { /// Sometimes an ABI requires small integers to be extended to a full or partial register. This enum /// defines if this extension should be zero-extension or sign-extension when necessary. When it is /// not necessary to extend the argument, this enum is ignored. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum ArgExtension { None, Zext, @@ -86,7 +86,7 @@ pub enum ArgExtension { /// A compact representation of LLVM attributes (at least those relevant for this module) /// that can be manipulated without interacting with LLVM's Attribute machinery. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct ArgAttributes { pub regular: ArgAttribute, pub arg_ext: ArgExtension, @@ -127,14 +127,14 @@ impl ArgAttributes { } } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum RegKind { Integer, Float, Vector, } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct Reg { pub kind: RegKind, pub size: Size, @@ -184,7 +184,7 @@ impl Reg { /// An argument passed entirely registers with the /// same kind (e.g., HFA / HVA on PPC64 and AArch64). -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct Uniform { pub unit: Reg, @@ -209,7 +209,7 @@ impl Uniform { } } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct CastTarget { pub prefix: [Option; 8], pub prefix_chunk_size: Size, @@ -437,7 +437,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { /// Information about how to pass an argument to, /// or return a value from, a function, under some ABI. -#[derive(Debug)] +#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct ArgAbi<'a, Ty> { pub layout: TyAndLayout<'a, Ty>, @@ -545,7 +545,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } } -#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum Conv { // General language calling conventions, for which every target // should have its own backend (e.g. LLVM) support. @@ -579,7 +579,7 @@ pub enum Conv { /// /// I will do my best to describe this structure, but these /// comments are reverse-engineered and may be inaccurate. -NDM -#[derive(Debug)] +#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct FnAbi<'a, Ty> { /// The LLVM types of each argument. pub args: Vec>, From 319dec89e7cee269a4a9b029a2da846bb76ea813 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 1 Sep 2021 14:19:49 +0300 Subject: [PATCH 07/10] rustc_codegen_llvm: move misplaced `HasParamEnv` impl. --- compiler/rustc_codegen_llvm/src/context.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 2d397dc583534..1d6efdf5f2510 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -835,6 +835,12 @@ impl ty::layout::HasTyCtxt<'tcx> for CodegenCx<'ll, 'tcx> { } } +impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> { + fn param_env(&self) -> ty::ParamEnv<'tcx> { + ty::ParamEnv::reveal_all() + } +} + impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { type LayoutOfResult = TyAndLayout<'tcx>; @@ -847,9 +853,3 @@ impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { } } } - -impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - ty::ParamEnv::reveal_all() - } -} From e9b68304efc447a7bcd35b06511f6dfdfe9da16d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 2 Sep 2021 00:09:34 +0300 Subject: [PATCH 08/10] ty::layout: replicate `layout_of` setup for `fn_abi_of_{fn_ptr,instance}`. --- .../rustc_codegen_cranelift/src/abi/mod.rs | 12 +- compiler/rustc_codegen_cranelift/src/base.rs | 5 +- .../rustc_codegen_cranelift/src/common.rs | 55 ++++- .../rustc_codegen_cranelift/src/constant.rs | 4 +- .../src/pretty_clif.rs | 5 +- compiler/rustc_codegen_llvm/src/builder.rs | 20 +- compiler/rustc_codegen_llvm/src/callee.rs | 6 +- compiler/rustc_codegen_llvm/src/context.rs | 46 +++- .../src/coverageinfo/mod.rs | 7 +- .../src/debuginfo/create_scope_map.rs | 5 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 4 +- compiler/rustc_codegen_llvm/src/mono_item.rs | 5 +- compiler/rustc_codegen_llvm/src/type_of.rs | 5 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 14 +- compiler/rustc_codegen_ssa/src/mir/mod.rs | 4 +- .../rustc_codegen_ssa/src/traits/backend.rs | 16 +- compiler/rustc_middle/src/ty/layout.rs | 221 +++++++++--------- 17 files changed, 277 insertions(+), 157 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 13790409e59f6..6317e1d5d1aba 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -5,7 +5,7 @@ mod pass_mode; mod returning; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::layout::FnAbiOf; use rustc_target::abi::call::{Conv, FnAbi}; use rustc_target::spec::abi::Abi; @@ -53,7 +53,7 @@ pub(crate) fn get_function_sig<'tcx>( inst: Instance<'tcx>, ) -> Signature { assert!(!inst.substs.needs_infer()); - clif_sig_from_fn_abi(tcx, triple, &FnAbi::of_instance(&RevealAllLayoutCx(tcx), inst, &[])) + clif_sig_from_fn_abi(tcx, triple, &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, &[])) } /// Instance must be monomorphized @@ -355,9 +355,9 @@ pub(crate) fn codegen_terminator_call<'tcx>( .map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))) .collect::>(); let fn_abi = if let Some(instance) = instance { - FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), instance, &extra_args) + RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, &extra_args) } else { - FnAbi::of_fn_ptr(&RevealAllLayoutCx(fx.tcx), 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 @@ -525,7 +525,7 @@ pub(crate) fn codegen_drop<'tcx>( def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0), substs: drop_instance.substs, }; - let fn_abi = FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), virtual_drop, &[]); + let fn_abi = RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, &[]); let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); let sig = fx.bcx.import_signature(sig); @@ -534,7 +534,7 @@ pub(crate) fn codegen_drop<'tcx>( _ => { assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _))); - let fn_abi = FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), drop_instance, &[]); + let fn_abi = RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(drop_instance, &[]); let arg_value = drop_place.place_ref( fx, diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index d29558a4e1f65..872c7edc791ff 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -3,8 +3,7 @@ use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_index::vec::IndexVec; use rustc_middle::ty::adjustment::PointerCast; -use rustc_middle::ty::layout::FnAbiExt; -use rustc_target::abi::call::FnAbi; +use rustc_middle::ty::layout::FnAbiOf; use crate::constant::ConstantCx; use crate::prelude::*; @@ -62,7 +61,7 @@ pub(crate) fn codegen_fn<'tcx>( instance, symbol_name, mir, - fn_abi: Some(FnAbi::of_instance(&RevealAllLayoutCx(tcx), instance, &[])), + fn_abi: Some(RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, &[])), bcx, block_map, diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 06d1fc717cc92..4a8be89460fcf 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -1,5 +1,7 @@ use rustc_index::vec::IndexVec; -use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers}; +use rustc_middle::ty::layout::{ + FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, +}; use rustc_middle::ty::SymbolName; use rustc_target::abi::call::FnAbi; use rustc_target::abi::{Integer, Primitive}; @@ -266,6 +268,20 @@ impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> { } } +impl<'tcx> FnAbiOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'_, 'tcx>, + ) -> ! { + RevealAllLayoutCx(self.tcx).handle_fn_abi_err(err, span, fn_abi_request) + } +} + impl<'tcx> layout::HasTyCtxt<'tcx> for FunctionCx<'_, '_, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.tcx @@ -378,6 +394,43 @@ impl<'tcx> LayoutOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> { } } +impl<'tcx> FnAbiOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'_, 'tcx>, + ) -> ! { + if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { + self.0.sess.span_fatal(span, &err.to_string()) + } else { + match fn_abi_request { + FnAbiRequest::OfFnPtr { sig, extra_args } => { + span_bug!( + span, + "`fn_abi_of_fn_ptr({}, {:?})` failed: {}", + sig, + extra_args, + err + ); + } + FnAbiRequest::OfInstance { instance, extra_args } => { + span_bug!( + span, + "`fn_abi_of_instance({}, {:?})` failed: {}", + instance, + extra_args, + err + ); + } + } + } + } +} + impl<'tcx> layout::HasTyCtxt<'tcx> for RevealAllLayoutCx<'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.0 diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 424a0d742d12b..5c4991f1fb667 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -129,9 +129,7 @@ pub(crate) fn codegen_constant<'tcx>( }; let const_val = match const_.val { ConstKind::Value(const_val) => const_val, - ConstKind::Unevaluated(uv) - if fx.tcx.is_static(uv.def.did) => - { + ConstKind::Unevaluated(uv) if fx.tcx.is_static(uv.def.did) => { assert!(uv.substs(fx.tcx).is_empty()); assert!(uv.promoted.is_none()); diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index 05db74745a1c0..0b80ef1c04e76 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -61,9 +61,8 @@ use cranelift_codegen::{ write::{FuncWriter, PlainWriter}, }; -use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::layout::FnAbiOf; use rustc_session::config::OutputType; -use rustc_target::abi::call::FnAbi; use crate::prelude::*; @@ -81,7 +80,7 @@ impl CommentWriter { vec![ format!("symbol {}", tcx.symbol_name(instance).name), format!("instance {:?}", instance), - format!("abi {:?}", FnAbi::of_instance(&RevealAllLayoutCx(tcx), instance, &[])), + format!("abi {:?}", RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, &[])), String::new(), ] } else { diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 799f9a57e93a2..8e3aaf56382b1 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -15,10 +15,12 @@ use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::MemFlags; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; -use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; +use rustc_middle::ty::layout::{ + FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, +}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; -use rustc_target::abi::{self, Align, Size, WrappingRange}; +use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange}; use rustc_target::spec::{HasTargetSpec, Target}; use std::borrow::Cow; use std::ffi::CStr; @@ -97,6 +99,20 @@ impl LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { } } +impl FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'_, 'tcx>, + ) -> ! { + self.cx.handle_fn_abi_err(err, span, fn_abi_request) + } +} + impl Deref for Builder<'_, 'll, 'tcx> { type Target = CodegenCx<'ll, 'tcx>; diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index bb16c90cd12f1..1a2aea015b1af 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -4,7 +4,7 @@ //! and methods are represented as just a fn ptr and not a full //! closure. -use crate::abi::{FnAbi, FnAbiLlvmExt}; +use crate::abi::FnAbiLlvmExt; use crate::attributes; use crate::context::CodegenCx; use crate::llvm; @@ -12,7 +12,7 @@ use crate::value::Value; use rustc_codegen_ssa::traits::*; use tracing::debug; -use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; use rustc_middle::ty::{self, Instance, TypeFoldable}; /// Codegens a reference to a fn/method item, monomorphizing and @@ -42,7 +42,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value sym ); - let fn_abi = FnAbi::of_instance(cx, instance, &[]); + let fn_abi = cx.fn_abi_of_instance(instance, &[]); let llfn = if let Some(llfn) = cx.get_declared_value(&sym) { // Create a fn pointer with the new signature. diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 1d6efdf5f2510..f1a2968ce59b1 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -15,14 +15,19 @@ use rustc_data_structures::base_n; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; use rustc_middle::mir::mono::CodegenUnit; -use rustc_middle::ty::layout::{HasParamEnv, LayoutError, LayoutOfHelpers, TyAndLayout}; +use rustc_middle::ty::layout::{ + FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers, + TyAndLayout, +}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CFGuard, CrateType, DebugInfo}; use rustc_session::Session; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; -use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; +use rustc_target::abi::{ + call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx, +}; use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel}; use smallvec::SmallVec; @@ -853,3 +858,40 @@ impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { } } } + +impl FnAbiOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'_, 'tcx>, + ) -> ! { + if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { + self.sess().span_fatal(span, &err.to_string()) + } else { + match fn_abi_request { + FnAbiRequest::OfFnPtr { sig, extra_args } => { + span_bug!( + span, + "`fn_abi_of_fn_ptr({}, {:?})` failed: {}", + sig, + extra_args, + err + ); + } + FnAbiRequest::OfInstance { instance, extra_args } => { + span_bug!( + span, + "`fn_abi_of_instance({}, {:?})` failed: {}", + instance, + extra_args, + err + ); + } + } + } + } +} diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 019bf4a09a787..cc1376278aaa4 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -1,6 +1,6 @@ use crate::llvm; -use crate::abi::{Abi, FnAbi}; +use crate::abi::Abi; use crate::builder::Builder; use crate::common::CodegenCx; @@ -20,7 +20,7 @@ use rustc_middle::mir::coverage::{ CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op, }; use rustc_middle::ty; -use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::Instance; @@ -200,8 +200,7 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx let llfn = cx.declare_fn( &tcx.symbol_name(instance).name, - &FnAbi::of_fn_ptr( - cx, + &cx.fn_abi_of_fn_ptr( ty::Binder::dummy(tcx.mk_fn_sig( iter::once(tcx.mk_unit()), tcx.mk_unit(), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index c2725b83f50d6..e5fd5bae01b74 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -3,12 +3,11 @@ use super::utils::DIB; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext}; use rustc_codegen_ssa::traits::*; -use crate::abi::FnAbi; use crate::common::CodegenCx; use crate::llvm; use crate::llvm::debuginfo::{DILocation, DIScope}; use rustc_middle::mir::{Body, SourceScope}; -use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::{self, Instance}; use rustc_session::config::DebugInfo; @@ -94,7 +93,7 @@ fn make_mir_scope( ty::ParamEnv::reveal_all(), callee, ); - let callee_fn_abi = FnAbi::of_instance(cx, callee, &[]); + let callee_fn_abi = cx.fn_abi_of_instance(callee, &[]); cx.dbg_scope_fn(callee, &callee_fn_abi, None) } None => unsafe { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 1060f911a9ed4..a046c518e1aa7 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -15,7 +15,7 @@ use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; use rustc_hir as hir; -use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, LayoutOf}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf}; use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{sym, symbol::kw, Span, Symbol}; @@ -737,7 +737,7 @@ fn gen_fn<'ll, 'tcx>( rust_fn_sig: ty::PolyFnSig<'tcx>, codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>), ) -> (&'ll Type, &'ll Value) { - let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]); + let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, &[]); let llty = fn_abi.llvm_type(cx); let llfn = cx.declare_fn(name, &fn_abi); cx.set_frame_pointer_type(llfn); diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 8ba3e870fbb71..b0301fa75aadf 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -1,4 +1,3 @@ -use crate::abi::FnAbi; use crate::attributes; use crate::base; use crate::context::CodegenCx; @@ -8,7 +7,7 @@ use rustc_codegen_ssa::traits::*; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; pub use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{Linkage, Visibility}; -use rustc_middle::ty::layout::{FnAbiExt, LayoutOf}; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeFoldable}; use rustc_session::config::CrateType; use rustc_target::spec::RelocModel; @@ -53,7 +52,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { ) { assert!(!instance.substs.needs_infer()); - let fn_abi = FnAbi::of_instance(self, instance, &[]); + let fn_abi = self.fn_abi_of_instance(instance, &[]); let lldecl = self.declare_fn(symbol_name, &fn_abi); unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 3e39bf3e995a2..94ad84aadd84c 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -1,10 +1,9 @@ -use crate::abi::FnAbi; use crate::common::*; use crate::context::TypeLowering; use crate::type_::Type; use rustc_codegen_ssa::traits::*; use rustc_middle::bug; -use rustc_middle::ty::layout::{FnAbiExt, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TypeFoldable}; use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape}; @@ -231,7 +230,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { ty::Adt(def, _) if def.is_box() => { cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx)) } - ty::FnPtr(sig) => cx.fn_ptr_backend_type(&FnAbi::of_fn_ptr(cx, sig, &[])), + ty::FnPtr(sig) => cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, &[])), _ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO), }; cx.scalar_lltypes.borrow_mut().insert(self.ty, llty); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index c557946afbc4b..fac72c39b5e68 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -14,7 +14,7 @@ use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; use rustc_middle::mir::AssertKind; use rustc_middle::mir::{self, SwitchTargets}; -use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, LayoutOf}; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Instance, Ty, TypeFoldable}; use rustc_span::source_map::Span; @@ -337,7 +337,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), substs: drop_fn.substs, }; - let fn_abi = FnAbi::of_instance(&bx, virtual_drop, &[]); + let fn_abi = bx.fn_abi_of_instance(virtual_drop, &[]); let vtable = args[1]; args = &args[..1]; ( @@ -346,7 +346,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn_abi, ) } - _ => (bx.get_fn_addr(drop_fn), FnAbi::of_instance(&bx, drop_fn, &[])), + _ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, &[])), }; helper.do_call( self, @@ -433,7 +433,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Obtain the panic entry point. let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item); let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = FnAbi::of_instance(&bx, instance, &[]); + let fn_abi = bx.fn_abi_of_instance(instance, &[]); let llfn = bx.get_fn_addr(instance); // Codegen the actual panic invoke/call. @@ -494,7 +494,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let def_id = common::langcall(bx.tcx(), Some(source_info.span), "", LangItem::Panic); let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = FnAbi::of_instance(bx, instance, &[]); + let fn_abi = bx.fn_abi_of_instance(instance, &[]); let llfn = bx.get_fn_addr(instance); // Codegen the actual panic invoke/call. @@ -579,8 +579,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .collect::>(); let fn_abi = match instance { - Some(instance) => FnAbi::of_instance(&bx, instance, &extra_args), - None => FnAbi::of_fn_ptr(&bx, sig, &extra_args), + Some(instance) => bx.fn_abi_of_instance(instance, &extra_args), + None => bx.fn_abi_of_fn_ptr(sig, &extra_args), }; if intrinsic == Some(sym::transmute) { diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 2c7636f1913dd..3fd9dc08c2be2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -2,7 +2,7 @@ use crate::traits::*; use rustc_errors::ErrorReported; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TypeFoldable}; use rustc_target::abi::call::{FnAbi, PassMode}; @@ -139,7 +139,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let mir = cx.tcx().instance_mir(instance.def); - let fn_abi = FnAbi::of_instance(cx, instance, &[]); + let fn_abi = cx.fn_abi_of_instance(instance, &[]); debug!("fn_abi: {:?}", fn_abi); let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir); diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index dbb7e1ee8b17f..82b79fd0b2ac3 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -8,14 +8,15 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorReported; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; -use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{Ty, TyCtxt}; use rustc_session::{ config::{self, OutputFilenames, PrintRequest}, Session, }; use rustc_span::symbol::Symbol; +use rustc_target::abi::call::FnAbi; use rustc_target::spec::Target; pub use rustc_data_structures::sync::MetadataRef; @@ -38,12 +39,19 @@ pub trait BackendTypes { } pub trait Backend<'tcx>: - Sized + BackendTypes + HasTyCtxt<'tcx> + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + Sized + + BackendTypes + + HasTyCtxt<'tcx> + + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>> { } impl<'tcx, T> Backend<'tcx> for T where - Self: BackendTypes + HasTyCtxt<'tcx> + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + Self: BackendTypes + + HasTyCtxt<'tcx> + + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>> { } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 42ac77054190a..04d8eaf7c9f80 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2035,6 +2035,12 @@ impl<'tcx> HasDataLayout for ty::query::TyCtxtAt<'tcx> { } } +impl<'tcx> HasTargetSpec for ty::query::TyCtxtAt<'tcx> { + fn target_spec(&self) -> &Target { + &self.sess.target + } +} + impl<'tcx> HasTyCtxt<'tcx> for ty::query::TyCtxtAt<'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { @@ -2142,10 +2148,10 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> { #[inline] fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult { let span = if !span.is_dummy() { span } else { self.layout_tcx_at_span() }; + let tcx = self.tcx().at(span); + MaybeResult::from( - self.tcx() - .at(span) - .layout_of(self.param_env().and(ty)) + tcx.layout_of(self.param_env().and(ty)) .map_err(|err| self.handle_layout_err(err, span, ty)), ) } @@ -2545,10 +2551,10 @@ impl<'a, 'tcx> HashStable> for LayoutError<'tcx> { impl<'tcx> ty::Instance<'tcx> { // NOTE(eddyb) this is private to avoid using it from outside of - // `FnAbi::of_instance` - any other uses are either too high-level + // `fn_abi_of_instance` - any other uses are either too high-level // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead), // or should go through `FnAbi` instead, to avoid losing any - // adjustments `FnAbi::of_instance` might be performing. + // adjustments `fn_abi_of_instance` might be performing. fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { // FIXME(davidtwco,eddyb): A `ParamEnv` should be passed through to this function. let ty = self.ty(tcx, ty::ParamEnv::reveal_all()); @@ -2801,7 +2807,7 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv { } /// Error produced by attempting to compute or adjust a `FnAbi`. -enum FnAbiError<'tcx> { +pub enum FnAbiError<'tcx> { /// Error produced by a `layout_of` call, while computing `FnAbi` initially. Layout(LayoutError<'tcx>), @@ -2830,125 +2836,124 @@ impl<'tcx> fmt::Display for FnAbiError<'tcx> { } } -pub trait FnAbiExt<'tcx, C> -where - C: HasTyCtxt<'tcx> + HasParamEnv<'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>] }, +} + +/// Trait for contexts that want to be able to compute `FnAbi`s. +/// This automatically gives access to `FnAbiOf`, through a blanket `impl`. +pub trait FnAbiOfHelpers<'tcx>: LayoutOfHelpers<'tcx> { + /// The `&FnAbi`-wrapping type (or `&FnAbi` itself), which will be + /// returned from `fn_abi_of_*` (see also `handle_fn_abi_err`). + type FnAbiOfResult: MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>>; + + /// Helper used for `fn_abi_of_*`, to adapt `tcx.fn_abi_of_*(...)` into a + /// `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 + /// `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>, + ) -> >>>::Error; +} + +/// Blanket extension trait for contexts that can compute `FnAbi`s. +pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. /// - /// NB: this doesn't handle virtual calls - those should use `FnAbi::of_instance` + /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` /// instead, where the instance is an `InstanceDef::Virtual`. - fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> &'tcx Self; + #[inline] + fn fn_abi_of_fn_ptr( + &self, + sig: ty::PolyFnSig<'tcx>, + extra_args: &[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() }; + + 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 }) + }), + ) + } /// 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 `::fn`). - fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> &'tcx Self; -} - -impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>> -where - C: HasTyCtxt<'tcx> + HasParamEnv<'tcx>, -{ - fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> &'tcx Self { - call::FnAbi::new_internal( - &LayoutCx { tcx: cx.tcx(), param_env: cx.param_env() }, - sig, - extra_args, - None, - CodegenFnAttrFlags::empty(), - false, - ) - .unwrap_or_else(|err| { - // FIXME(eddyb) get a better `span` here. - let span = DUMMY_SP; - if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { - cx.tcx().sess.span_fatal(span, &err.to_string()) - } else { - span_bug!(span, "`FnAbi::of_fn_ptr({}, {:?})` failed: {}", sig, extra_args, err); - } - }) - } + #[inline] + fn fn_abi_of_instance( + &self, + instance: ty::Instance<'tcx>, + extra_args: &[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() }; - fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> &'tcx Self { 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()) + Some(cx.tcx.caller_location_ty()) } else { None }; - let attrs = cx.tcx().codegen_fn_attrs(instance.def_id()).flags; + let attrs = cx.tcx.codegen_fn_attrs(instance.def_id()).flags; - call::FnAbi::new_internal( - &LayoutCx { tcx: cx.tcx(), param_env: cx.param_env() }, - sig, - extra_args, - caller_location, - attrs, - matches!(instance.def, ty::InstanceDef::Virtual(..)), + MaybeResult::from( + cx.fn_abi_new_internal( + 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, + // 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()) }; + self.handle_fn_abi_err(err, span, FnAbiRequest::OfInstance { instance, extra_args }) + }), ) - .unwrap_or_else(|err| { - // FIXME(eddyb) get a better `span` here. - let span = cx.tcx().def_span(instance.def_id()); - if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { - cx.tcx().sess.span_fatal(span, &err.to_string()) - } else { - span_bug!( - span, - "`FnAbi::of_instance({}, {:?})` failed: {}", - instance, - extra_args, - err - ); - } - }) } } -/// Implementation detail of computing `FnAbi`s, shouldn't be exported. -// FIXME(eddyb) move this off of being generic on `C: LayoutOf`, and -// explicitly take `LayoutCx` *or* `TyCtxt` and `ParamEnvAnd<...>`. -trait FnAbiInternalExt<'tcx, C> -where - C: LayoutOf<'tcx, LayoutOfResult = Result, LayoutError<'tcx>>> - + HasTargetSpec, -{ +impl> FnAbiOf<'tcx> for C {} + +impl<'tcx> LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> { // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?) // arguments of this method, into a separate `struct`. - fn new_internal( - cx: &C, + fn fn_abi_new_internal( + &self, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>], caller_location: Option>, codegen_fn_attr_flags: CodegenFnAttrFlags, // FIXME(eddyb) replace this with something typed, like an `enum`. - make_self_ptr_thin: bool, - ) -> Result<&'tcx Self, FnAbiError<'tcx>>; - fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) -> Result<(), FnAbiError<'tcx>>; -} - -impl<'tcx, C> FnAbiInternalExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>> -where - C: LayoutOf<'tcx, LayoutOfResult = Result, LayoutError<'tcx>>> - + HasTargetSpec, -{ - fn new_internal( - cx: &C, - sig: ty::PolyFnSig<'tcx>, - extra_args: &[Ty<'tcx>], - caller_location: Option>, - codegen_fn_attr_flags: CodegenFnAttrFlags, force_thin_self_ptr: bool, - ) -> Result<&'tcx Self, FnAbiError<'tcx>> { + ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args); - let sig = cx.tcx().normalize_erasing_late_bound_regions(cx.param_env(), sig); + let sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, sig); - let conv = conv_from_spec_abi(cx.tcx(), sig.abi); + let conv = conv_from_spec_abi(self.tcx(), sig.abi); let mut inputs = sig.inputs(); let extra_args = if sig.abi == RustCall { @@ -2975,7 +2980,7 @@ where extra_args.to_vec() }; - let target = &cx.tcx().sess.target; + let target = &self.tcx.sess.target; let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl"); let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu"; let linux_s390x_gnu_like = @@ -3008,7 +3013,7 @@ where attrs.set(ArgAttribute::NonNull); } - if let Some(pointee) = layout.pointee_info_at(cx, offset) { + if let Some(pointee) = layout.pointee_info_at(self, offset) { if let Some(kind) = pointee.safe { attrs.pointee_align = Some(pointee.align); @@ -3055,17 +3060,17 @@ where let arg_of = |ty: Ty<'tcx>, arg_idx: Option| -> Result<_, FnAbiError<'tcx>> { let is_return = arg_idx.is_none(); - let layout = cx.layout_of(ty)?; + let layout = self.layout_of(ty)?; let layout = if force_thin_self_ptr && arg_idx == Some(0) { // Don't pass the vtable, it's not an argument of the virtual fn. // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait` // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen - make_thin_self_ptr(cx, layout) + make_thin_self_ptr(self, layout) } else { layout }; - let mut arg = ArgAbi::new(cx, layout, |layout, scalar, offset| { + let mut arg = ArgAbi::new(self, layout, |layout, scalar, offset| { let mut attrs = ArgAttributes::new(); adjust_for_rust_scalar(&mut attrs, scalar, *layout, offset, is_return); attrs @@ -3102,14 +3107,18 @@ where c_variadic: sig.c_variadic, fixed_count: inputs.len(), conv, - can_unwind: fn_can_unwind(cx.tcx(), codegen_fn_attr_flags, sig.abi), + can_unwind: fn_can_unwind(self.tcx(), codegen_fn_attr_flags, sig.abi), }; - fn_abi.adjust_for_abi(cx, sig.abi)?; + self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?; debug!("FnAbi::new_internal = {:?}", fn_abi); - Ok(cx.tcx().intern_fn_abi(fn_abi)) + Ok(self.tcx.intern_fn_abi(fn_abi)) } - fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) -> Result<(), FnAbiError<'tcx>> { + fn fn_abi_adjust_for_abi( + &self, + fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>, + abi: SpecAbi, + ) -> Result<(), FnAbiError<'tcx>> { if abi == SpecAbi::Unadjusted { return Ok(()); } @@ -3148,7 +3157,7 @@ where // anyway, we control all calls to it in libstd. Abi::Vector { .. } if abi != SpecAbi::PlatformIntrinsic - && cx.tcx().sess.target.simd_types_indirect => + && self.tcx.sess.target.simd_types_indirect => { arg.make_indirect(); return; @@ -3159,7 +3168,7 @@ where // Pass and return structures up to 2 pointers in size by value, matching `ScalarPair`. // LLVM will usually pass these in 2 registers, which is more efficient than by-ref. - let max_by_val_size = Pointer.size(cx) * 2; + let max_by_val_size = Pointer.size(self) * 2; let size = arg.layout.size; if arg.layout.is_unsized() || size > max_by_val_size { @@ -3171,12 +3180,12 @@ where arg.cast_to(Reg { kind: RegKind::Integer, size }); } }; - fixup(&mut self.ret); - for arg in &mut self.args { + fixup(&mut fn_abi.ret); + for arg in &mut fn_abi.args { fixup(arg); } } else { - self.adjust_for_foreign_abi(cx, abi)?; + fn_abi.adjust_for_foreign_abi(self, abi)?; } Ok(()) From c1837ef1c58edd48c81341126ecc94e7adc5bd3d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 2 Sep 2021 00:29:15 +0300 Subject: [PATCH 09/10] Querify `fn_abi_of_{fn_ptr,instance}`. --- .../rustc_codegen_cranelift/src/abi/mod.rs | 23 ++-- compiler/rustc_codegen_cranelift/src/base.rs | 2 +- .../rustc_codegen_cranelift/src/common.rs | 4 +- .../src/pretty_clif.rs | 5 +- compiler/rustc_codegen_llvm/src/builder.rs | 2 +- compiler/rustc_codegen_llvm/src/callee.rs | 2 +- compiler/rustc_codegen_llvm/src/context.rs | 2 +- .../src/coverageinfo/mod.rs | 2 +- .../src/debuginfo/create_scope_map.rs | 2 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 2 +- compiler/rustc_codegen_llvm/src/mono_item.rs | 2 +- compiler/rustc_codegen_llvm/src/type_of.rs | 4 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 23 ++-- compiler/rustc_codegen_ssa/src/mir/mod.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 21 +++ compiler/rustc_middle/src/ty/layout.rs | 123 +++++++++--------- compiler/rustc_middle/src/ty/query.rs | 1 + compiler/rustc_query_impl/src/keys.rs | 22 ++++ compiler/rustc_target/src/abi/call/mod.rs | 1 + 19 files changed, 152 insertions(+), 93 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 6317e1d5d1aba..15bb90678059d 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -53,7 +53,11 @@ pub(crate) fn get_function_sig<'tcx>( inst: Instance<'tcx>, ) -> Signature { 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 @@ -350,14 +354,13 @@ pub(crate) fn codegen_terminator_call<'tcx>( }; let extra_args = &args[fn_sig.inputs().len()..]; - let extra_args = extra_args - .iter() - .map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))) - .collect::>(); + let extra_args = fx + .tcx + .mk_type_list(extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx)))); 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 { - 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 @@ -525,7 +528,8 @@ pub(crate) fn codegen_drop<'tcx>( def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0), 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 = fx.bcx.import_signature(sig); @@ -534,7 +538,8 @@ pub(crate) fn codegen_drop<'tcx>( _ => { 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( fx, diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 872c7edc791ff..d8fa2c7690468 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -61,7 +61,7 @@ pub(crate) fn codegen_fn<'tcx>( instance, symbol_name, 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, block_map, diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 4a8be89460fcf..0e84681d9ad94 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -276,7 +276,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> { &self, err: FnAbiError<'tcx>, span: Span, - fn_abi_request: FnAbiRequest<'_, 'tcx>, + fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { RevealAllLayoutCx(self.tcx).handle_fn_abi_err(err, span, fn_abi_request) } @@ -402,7 +402,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> { &self, err: FnAbiError<'tcx>, span: Span, - fn_abi_request: FnAbiRequest<'_, 'tcx>, + fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { self.0.sess.span_fatal(span, &err.to_string()) diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index 0b80ef1c04e76..ec846d71960b8 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -80,7 +80,10 @@ impl CommentWriter { vec![ format!("symbol {}", tcx.symbol_name(instance).name), 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(), ] } else { diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 8e3aaf56382b1..dab7d3eaa8cfd 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -107,7 +107,7 @@ impl FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { &self, err: FnAbiError<'tcx>, span: Span, - fn_abi_request: FnAbiRequest<'_, 'tcx>, + fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { self.cx.handle_fn_abi_err(err, span, fn_abi_request) } diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index 1a2aea015b1af..a96ba148a6ce3 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -42,7 +42,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value 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) { // Create a fn pointer with the new signature. diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index f1a2968ce59b1..52a12b2fd81d8 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -867,7 +867,7 @@ impl FnAbiOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { &self, err: FnAbiError<'tcx>, span: Span, - fn_abi_request: FnAbiRequest<'_, 'tcx>, + fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { self.sess().span_fatal(span, &err.to_string()) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index cc1376278aaa4..093aceda2b741 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -208,7 +208,7 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx hir::Unsafety::Unsafe, Abi::Rust, )), - &[], + ty::List::empty(), ), ); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index e5fd5bae01b74..1612922d43953 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -93,7 +93,7 @@ fn make_mir_scope( ty::ParamEnv::reveal_all(), 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) } None => unsafe { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index a046c518e1aa7..9d0e0e6394434 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -737,7 +737,7 @@ fn gen_fn<'ll, 'tcx>( rust_fn_sig: ty::PolyFnSig<'tcx>, codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>), ) -> (&'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 llfn = cx.declare_fn(name, &fn_abi); cx.set_frame_pointer_type(llfn); diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index b0301fa75aadf..34982f769d03a 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -52,7 +52,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { ) { 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); unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 94ad84aadd84c..757ccbddbeedf 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -230,7 +230,9 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { ty::Adt(def, _) if def.is_box() => { 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), }; cx.scalar_lltypes.borrow_mut().insert(self.ty, llty); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index fac72c39b5e68..cc9dd378ee497 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -337,7 +337,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), 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]; args = &args[..1]; ( @@ -346,7 +346,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { 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( self, @@ -433,7 +433,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Obtain the panic entry point. let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item); 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); // Codegen the actual panic invoke/call. @@ -494,7 +494,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let def_id = common::langcall(bx.tcx(), Some(source_info.span), "", LangItem::Panic); 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); // 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 = extra_args - .iter() - .map(|op_arg| { - let op_ty = op_arg.ty(self.mir, bx.tcx()); - self.monomorphize(op_ty) - }) - .collect::>(); + let extra_args = bx.tcx().mk_type_list(extra_args.iter().map(|op_arg| { + let op_ty = op_arg.ty(self.mir, bx.tcx()); + self.monomorphize(op_ty) + })); let fn_abi = match instance { - Some(instance) => bx.fn_abi_of_instance(instance, &extra_args), - None => bx.fn_abi_of_fn_ptr(sig, &extra_args), + Some(instance) => bx.fn_abi_of_instance(instance, extra_args), + None => bx.fn_abi_of_fn_ptr(sig, extra_args), }; if intrinsic == Some(sym::transmute) { diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 3fd9dc08c2be2..9ad2a66bc6aec 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -139,7 +139,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( 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); let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 4296acce1ffbe..6a1ebbba817db 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>)> + ) -> 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 `::fn`). + query fn_abi_of_instance( + key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> + ) -> 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 04d8eaf7c9f80..f72f045e9079c 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(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> 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> }, + OfInstance { instance: ty::Instance<'tcx>, extra_args: &'tcx ty::List> }, } /// 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>, ) -> >>>::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>, ) -> 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>, ) -> 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> 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>)>, +) -> 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>)>, +) -> 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 15a8888ee65ed..154b26464a804 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; diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 42e8b4023cfad..563a3cf14382c 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -449,3 +449,25 @@ impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) { DUMMY_SP } } + +impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List>) { + #[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>) { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.0.default_span(tcx) + } +} diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 6f06f2b56ada6..324278c57bf14 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -601,6 +601,7 @@ pub struct FnAbi<'a, Ty> { } /// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI. +#[derive(Clone, Debug, HashStable_Generic)] pub enum AdjustForForeignAbiError { /// Target architecture doesn't support "foreign" (i.e. non-Rust) ABIs. Unsupported { arch: String, abi: spec::abi::Abi }, From 8c918d7e2d973ac3d148097224e0951daba16835 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 9 Sep 2021 09:43:47 +0300 Subject: [PATCH 10/10] [HACK(eddyb)] arena-allocate but don't intern `FnAbi`s. --- compiler/rustc_middle/src/ty/context.rs | 5 ----- compiler/rustc_middle/src/ty/layout.rs | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e803a667879a1..7cd5584c3589b 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -55,7 +55,6 @@ use rustc_span::def_id::{DefPathHash, StableCrateId}; use rustc_span::source_map::{MultiSpan, SourceMap}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; -use rustc_target::abi::call::FnAbi; use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; @@ -136,7 +135,6 @@ pub struct CtxtInterners<'tcx> { const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List>, layout: InternedSet<'tcx, Layout>, - fn_abi: InternedSet<'tcx, FnAbi<'tcx, Ty<'tcx>>>, } impl<'tcx> CtxtInterners<'tcx> { @@ -157,7 +155,6 @@ impl<'tcx> CtxtInterners<'tcx> { const_allocation: Default::default(), bound_variable_kinds: Default::default(), layout: Default::default(), - fn_abi: Default::default(), } } @@ -1962,7 +1959,6 @@ impl<'tcx> TyCtxt<'tcx> { self.0.interners.const_allocation.len() )?; writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?; - writeln!(fmt, "FnAbi interner: #{}", self.0.interners.fn_abi.len())?; Ok(()) } @@ -2087,7 +2083,6 @@ direct_interners! { const_: mk_const(Const<'tcx>), const_allocation: intern_const_alloc(Allocation), layout: intern_layout(Layout), - fn_abi: intern_fn_abi(FnAbi<'tcx, Ty<'tcx>>), } macro_rules! slice_interners { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index f72f045e9079c..cfbbec374a172 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -3118,7 +3118,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }; self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?; debug!("fn_abi_new_uncached = {:?}", fn_abi); - Ok(self.tcx.intern_fn_abi(fn_abi)) + Ok(self.tcx.arena.alloc(fn_abi)) } fn fn_abi_adjust_for_abi(