diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 6f7ca51d038..06d1fc717cc 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 cd0e9354c24..c557946afbc 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 e2edd448267..2c7636f1913 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 59db2c6636f..2dd43a4e852 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 7cd5584c358..e803a667879 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 e11993c7580..42ac7705419 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 75c526c9741..6f06f2b56ad 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>,