diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 7dc6d292a94af..375031f8e80ac 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -134,7 +134,27 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { #[inline(always)] pub fn layout_of(&self, ty: Ty<'tcx>) -> Result, InterpErrorKind<'tcx>> { let _trace = enter_trace_span!(M, layouting::layout_of, ty = ?ty.kind()); - LayoutOf::layout_of(self, ty) + if ty == self.tcx.types.usize { + self.layout_of_usize() + } else if ty == self.tcx.types.u16 { + Ok(TyAndLayout { ty: self.tcx.types.u16, layout: self.tcx.layouts.u16 }) + } else if ty == self.tcx.types.i16 { + Ok(TyAndLayout { ty: self.tcx.types.i16, layout: self.tcx.layouts.i16 }) + } else if ty == self.tcx.types.u32 { + Ok(TyAndLayout { ty: self.tcx.types.u32, layout: self.tcx.layouts.u32 }) + } else if ty == self.tcx.types.i32 { + Ok(TyAndLayout { ty: self.tcx.types.i32, layout: self.tcx.layouts.i32 }) + } else if ty == self.tcx.types.u64 { + Ok(TyAndLayout { ty: self.tcx.types.u64, layout: self.tcx.layouts.u64 }) + } else if ty == self.tcx.types.i64 { + Ok(TyAndLayout { ty: self.tcx.types.i64, layout: self.tcx.layouts.i64 }) + } else { + LayoutOf::layout_of(self, ty) + } + } + + pub fn layout_of_usize(&self) -> Result, InterpErrorKind<'tcx>> { + Ok(TyAndLayout { ty: self.tcx.types.usize, layout: self.tcx.layouts.usize }) } /// This inherent method takes priority over the trait method with the same name in FnAbiOf, diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 27f91b2b89b2c..53090f457b92e 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -416,7 +416,7 @@ where Downcast(_, variant) => self.project_downcast(base, variant)?, Deref => self.deref_pointer(&base.to_op(self)?)?.into(), Index(local) => { - let layout = self.layout_of(self.tcx.types.usize)?; + let layout = self.layout_of_usize()?; let n = self.local_to_op(local, Some(layout))?; let n = self.read_target_usize(&n)?; self.project_index(base, n)? diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e756277b92d76..985c91fb39e88 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -382,6 +382,21 @@ pub struct CommonConsts<'tcx> { pub(crate) valtree_zst: ValTree<'tcx>, } +pub struct CommonLayouts<'tcx> { + pub usize: Layout<'tcx>, + pub isize: Layout<'tcx>, + pub u8: Layout<'tcx>, + pub i8: Layout<'tcx>, + pub u16: Layout<'tcx>, + pub i16: Layout<'tcx>, + pub u32: Layout<'tcx>, + pub i32: Layout<'tcx>, + pub u64: Layout<'tcx>, + pub i64: Layout<'tcx>, + pub u128: Layout<'tcx>, + pub i128: Layout<'tcx>, +} + impl<'tcx> CommonTypes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { let mk = |ty| interners.intern_ty(ty); @@ -453,6 +468,44 @@ impl<'tcx> CommonTypes<'tcx> { } } +impl<'tcx> CommonLayouts<'tcx> { + fn new(interners: &CtxtInterners<'tcx>, dl: &TargetDataLayout) -> CommonLayouts<'tcx> { + use rustc_abi::{Integer, Primitive, Scalar, WrappingRange}; + + let mk_int = |int: Integer, signed: bool| { + let primitive = Primitive::Int(int, signed); + let size = int.size(); + Scalar::Initialized { value: primitive, valid_range: WrappingRange::full(size) } + }; + + let mk_scalar = |scalar: Scalar| { + Layout(Interned::new_unchecked( + interners + .layout + .intern(LayoutData::scalar(dl, scalar), |v| { + InternedInSet(interners.arena.alloc(v)) + }) + .0, + )) + }; + + CommonLayouts { + usize: mk_scalar(mk_int(dl.ptr_sized_integer(), false)), + isize: mk_scalar(mk_int(dl.ptr_sized_integer(), true)), + u8: mk_scalar(mk_int(Integer::I8, false)), + i8: mk_scalar(mk_int(Integer::I8, true)), + u16: mk_scalar(mk_int(Integer::I16, false)), + i16: mk_scalar(mk_int(Integer::I16, true)), + u32: mk_scalar(mk_int(Integer::I32, false)), + i32: mk_scalar(mk_int(Integer::I32, true)), + u64: mk_scalar(mk_int(Integer::I64, false)), + i64: mk_scalar(mk_int(Integer::I64, true)), + u128: mk_scalar(mk_int(Integer::I128, false)), + i128: mk_scalar(mk_int(Integer::I128, true)), + } + } +} + impl<'tcx> CommonLifetimes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonLifetimes<'tcx> { let mk = |r| { @@ -697,6 +750,9 @@ pub struct GlobalCtxt<'tcx> { /// Common types, pre-interned for your convenience. pub types: CommonTypes<'tcx>, + /// Common layouts, pre-computed for MIR convenience. + pub layouts: CommonLayouts<'tcx>, + /// Common lifetimes, pre-interned for your convenience. pub lifetimes: CommonLifetimes<'tcx>, @@ -930,6 +986,7 @@ impl<'tcx> TyCtxt<'tcx> { }); let interners = CtxtInterners::new(arena); let common_types = CommonTypes::new(&interners); + let common_layouts = CommonLayouts::new(&interners, &data_layout); let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); @@ -944,6 +1001,7 @@ impl<'tcx> TyCtxt<'tcx> { hooks, prof: sess.prof.clone(), types: common_types, + layouts: common_layouts, lifetimes: common_lifetimes, consts: common_consts, untracked, diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 9cc15a374ff70..a23f89284899b 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -395,8 +395,22 @@ fn layout_of_uncached<'tcx>( valid_range: WrappingRange { start: 0, end: 0x10FFFF }, }, )), - ty::Int(ity) => scalar(Int(abi::Integer::from_int_ty(dl, ity), true)), - ty::Uint(ity) => scalar(Int(abi::Integer::from_uint_ty(dl, ity), false)), + ty::Int(ity) => match ity { + ty::IntTy::I8 => tcx.layouts.i8, + ty::IntTy::I16 => tcx.layouts.i16, + ty::IntTy::I32 => tcx.layouts.i32, + ty::IntTy::I64 => tcx.layouts.i64, + ty::IntTy::I128 => tcx.layouts.i128, + ty::IntTy::Isize => tcx.layouts.isize, + }, + ty::Uint(ity) => match ity { + ty::UintTy::U8 => tcx.layouts.u8, + ty::UintTy::U16 => tcx.layouts.u16, + ty::UintTy::U32 => tcx.layouts.u32, + ty::UintTy::U64 => tcx.layouts.u64, + ty::UintTy::U128 => tcx.layouts.u128, + ty::UintTy::Usize => tcx.layouts.usize, + }, ty::Float(fty) => scalar(Float(abi::Float::from_float_ty(fty))), ty::FnPtr(..) => { let mut ptr = scalar_unit(Pointer(dl.instruction_address_space));