diff options
| author | hkalbasi <hamidrezakalbasi@protonmail.com> | 2022-11-01 19:50:30 +0330 |
|---|---|---|
| committer | hkalbasi <hamidrezakalbasi@protonmail.com> | 2022-11-24 16:26:12 +0330 |
| commit | 27fb904d680996fe48e04aef65d4d655bdab843b (patch) | |
| tree | 48ed33a5a63e23d06770dc5a86ec6532e254cdc3 /compiler/rustc_middle/src | |
| parent | 09a384643ee4188fd1e837ab25856a7e8ff62d07 (diff) | |
| download | rust-27fb904d680996fe48e04aef65d4d655bdab843b.tar.gz rust-27fb904d680996fe48e04aef65d4d655bdab843b.zip | |
move some layout logic to rustc_target::abi::layout
Diffstat (limited to 'compiler/rustc_middle/src')
| -rw-r--r-- | compiler/rustc_middle/src/ty/adt.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/layout.rs | 31 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 208 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/util.rs | 23 |
4 files changed, 82 insertions, 186 deletions
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 6b6aa40a160..d3d667f6840 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -14,7 +14,7 @@ use rustc_index::vec::{Idx, IndexVec}; use rustc_query_system::ich::StableHashingContext; use rustc_session::DataTypeKind; use rustc_span::symbol::sym; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{ReprOptions, VariantIdx}; use std::cell::RefCell; use std::cmp::Ordering; @@ -22,9 +22,7 @@ use std::hash::{Hash, Hasher}; use std::ops::Range; use std::str; -use super::{ - Destructor, FieldDef, GenericPredicates, ReprOptions, Ty, TyCtxt, VariantDef, VariantDiscr, -}; +use super::{Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, VariantDiscr}; bitflags! { #[derive(HashStable, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index fea2aa8cbf8..488fd567846 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1,8 +1,6 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitable}; -use rustc_ast as ast; -use rustc_attr as attr; use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -20,7 +18,6 @@ use std::ops::Bound; pub trait IntegerExt { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>; - fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer; fn from_int_ty<C: HasDataLayout>(cx: &C, ity: ty::IntTy) -> Integer; fn from_uint_ty<C: HasDataLayout>(cx: &C, uty: ty::UintTy) -> Integer; fn repr_discr<'tcx>( @@ -49,22 +46,6 @@ impl IntegerExt for Integer { } } - /// Gets the Integer type from an attr::IntType. - fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer { - let dl = cx.data_layout(); - - match ity { - attr::SignedInt(ast::IntTy::I8) | attr::UnsignedInt(ast::UintTy::U8) => I8, - attr::SignedInt(ast::IntTy::I16) | attr::UnsignedInt(ast::UintTy::U16) => I16, - attr::SignedInt(ast::IntTy::I32) | attr::UnsignedInt(ast::UintTy::U32) => I32, - attr::SignedInt(ast::IntTy::I64) | attr::UnsignedInt(ast::UintTy::U64) => I64, - attr::SignedInt(ast::IntTy::I128) | attr::UnsignedInt(ast::UintTy::U128) => I128, - attr::SignedInt(ast::IntTy::Isize) | attr::UnsignedInt(ast::UintTy::Usize) => { - dl.ptr_sized_integer() - } - } - } - fn from_int_ty<C: HasDataLayout>(cx: &C, ity: ty::IntTy) -> Integer { match ity { ty::IntTy::I8 => I8, @@ -237,6 +218,18 @@ pub struct LayoutCx<'tcx, C> { pub param_env: ty::ParamEnv<'tcx>, } +impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> { + type TargetDataLayoutRef = &'tcx TargetDataLayout; + + fn delay_bug(&self, txt: &str) { + self.tcx.sess.delay_span_bug(DUMMY_SP, txt); + } + + fn current_data_layout(&self) -> Self::TargetDataLayoutRef { + &self.tcx.data_layout + } +} + /// Type size "skeleton", i.e., the only information determining a type's size. /// While this is conservative, (aside from constant sizes, only pointers, /// newtypes thereof and null pointer optimized enums are allowed), it is diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 0458c4abd3d..e3421ab9ce0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -48,7 +48,8 @@ use rustc_session::cstore::CrateStoreDyn; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ExpnId, Span}; -use rustc_target::abi::{Align, VariantIdx}; +use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx}; +pub use rustc_target::abi::{ReprFlags, ReprOptions}; pub use subst::*; pub use vtable::*; @@ -1994,161 +1995,76 @@ impl Hash for FieldDef { } } -bitflags! { - #[derive(TyEncodable, TyDecodable, Default, HashStable)] - pub struct ReprFlags: u8 { - const IS_C = 1 << 0; - const IS_SIMD = 1 << 1; - const IS_TRANSPARENT = 1 << 2; - // Internal only for now. If true, don't reorder fields. - const IS_LINEAR = 1 << 3; - // If true, the type's layout can be randomized using - // the seed stored in `ReprOptions.layout_seed` - const RANDOMIZE_LAYOUT = 1 << 4; - // Any of these flags being set prevent field reordering optimisation. - const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits - | ReprFlags::IS_SIMD.bits - | ReprFlags::IS_LINEAR.bits; - } -} - -/// Represents the repr options provided by the user, -#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Default, HashStable)] -pub struct ReprOptions { - pub int: Option<attr::IntType>, - pub align: Option<Align>, - pub pack: Option<Align>, - pub flags: ReprFlags, - /// The seed to be used for randomizing a type's layout - /// - /// Note: This could technically be a `[u8; 16]` (a `u128`) which would - /// be the "most accurate" hash as it'd encompass the item and crate - /// hash without loss, but it does pay the price of being larger. - /// Everything's a tradeoff, a `u64` seed should be sufficient for our - /// purposes (primarily `-Z randomize-layout`) - pub field_shuffle_seed: u64, -} - -impl ReprOptions { - pub fn new(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions { - let mut flags = ReprFlags::empty(); - let mut size = None; - let mut max_align: Option<Align> = None; - let mut min_pack: Option<Align> = None; - - // Generate a deterministically-derived seed from the item's path hash - // to allow for cross-crate compilation to actually work - let mut field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash(); - - // If the user defined a custom seed for layout randomization, xor the item's - // path hash with the user defined seed, this will allowing determinism while - // still allowing users to further randomize layout generation for e.g. fuzzing - if let Some(user_seed) = tcx.sess.opts.unstable_opts.layout_seed { - field_shuffle_seed ^= user_seed; - } - - for attr in tcx.get_attrs(did, sym::repr) { - for r in attr::parse_repr_attr(&tcx.sess, attr) { - flags.insert(match r { - attr::ReprC => ReprFlags::IS_C, - attr::ReprPacked(pack) => { - let pack = Align::from_bytes(pack as u64).unwrap(); - min_pack = Some(if let Some(min_pack) = min_pack { - min_pack.min(pack) - } else { - pack - }); - ReprFlags::empty() - } - attr::ReprTransparent => ReprFlags::IS_TRANSPARENT, - attr::ReprSimd => ReprFlags::IS_SIMD, - attr::ReprInt(i) => { - size = Some(i); - ReprFlags::empty() - } - attr::ReprAlign(align) => { - max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap())); - ReprFlags::empty() - } - }); - } - } +pub fn repr_options_of_def(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions { + let mut flags = ReprFlags::empty(); + let mut size = None; + let mut max_align: Option<Align> = None; + let mut min_pack: Option<Align> = None; - // If `-Z randomize-layout` was enabled for the type definition then we can - // consider performing layout randomization - if tcx.sess.opts.unstable_opts.randomize_layout { - flags.insert(ReprFlags::RANDOMIZE_LAYOUT); - } + // Generate a deterministically-derived seed from the item's path hash + // to allow for cross-crate compilation to actually work + let mut field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash(); - // This is here instead of layout because the choice must make it into metadata. - if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) { - flags.insert(ReprFlags::IS_LINEAR); - } - - Self { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed } - } - - #[inline] - pub fn simd(&self) -> bool { - self.flags.contains(ReprFlags::IS_SIMD) + // If the user defined a custom seed for layout randomization, xor the item's + // path hash with the user defined seed, this will allowing determinism while + // still allowing users to further randomize layout generation for e.g. fuzzing + if let Some(user_seed) = tcx.sess.opts.unstable_opts.layout_seed { + field_shuffle_seed ^= user_seed; } - #[inline] - pub fn c(&self) -> bool { - self.flags.contains(ReprFlags::IS_C) - } - - #[inline] - pub fn packed(&self) -> bool { - self.pack.is_some() - } - - #[inline] - pub fn transparent(&self) -> bool { - self.flags.contains(ReprFlags::IS_TRANSPARENT) - } - - #[inline] - pub fn linear(&self) -> bool { - self.flags.contains(ReprFlags::IS_LINEAR) - } - - /// Returns the discriminant type, given these `repr` options. - /// This must only be called on enums! - pub fn discr_type(&self) -> attr::IntType { - self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize)) - } - - /// Returns `true` if this `#[repr()]` should inhabit "smart enum - /// layout" optimizations, such as representing `Foo<&T>` as a - /// single pointer. - pub fn inhibit_enum_layout_opt(&self) -> bool { - self.c() || self.int.is_some() - } - - /// Returns `true` if this `#[repr()]` should inhibit struct field reordering - /// optimizations, such as with `repr(C)`, `repr(packed(1))`, or `repr(<int>)`. - pub fn inhibit_struct_field_reordering_opt(&self) -> bool { - if let Some(pack) = self.pack { - if pack.bytes() == 1 { - return true; - } + for attr in tcx.get_attrs(did, sym::repr) { + for r in attr::parse_repr_attr(&tcx.sess, attr) { + flags.insert(match r { + attr::ReprC => ReprFlags::IS_C, + attr::ReprPacked(pack) => { + let pack = Align::from_bytes(pack as u64).unwrap(); + min_pack = + Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack }); + ReprFlags::empty() + } + attr::ReprTransparent => ReprFlags::IS_TRANSPARENT, + attr::ReprSimd => ReprFlags::IS_SIMD, + attr::ReprInt(i) => { + size = Some(match i { + attr::IntType::SignedInt(x) => match x { + ast::IntTy::Isize => IntegerType::Pointer(true), + ast::IntTy::I8 => IntegerType::Fixed(Integer::I8, true), + ast::IntTy::I16 => IntegerType::Fixed(Integer::I16, true), + ast::IntTy::I32 => IntegerType::Fixed(Integer::I32, true), + ast::IntTy::I64 => IntegerType::Fixed(Integer::I64, true), + ast::IntTy::I128 => IntegerType::Fixed(Integer::I128, true), + }, + attr::IntType::UnsignedInt(x) => match x { + ast::UintTy::Usize => IntegerType::Pointer(false), + ast::UintTy::U8 => IntegerType::Fixed(Integer::I8, false), + ast::UintTy::U16 => IntegerType::Fixed(Integer::I16, false), + ast::UintTy::U32 => IntegerType::Fixed(Integer::I32, false), + ast::UintTy::U64 => IntegerType::Fixed(Integer::I64, false), + ast::UintTy::U128 => IntegerType::Fixed(Integer::I128, false), + }, + }); + ReprFlags::empty() + } + attr::ReprAlign(align) => { + max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap())); + ReprFlags::empty() + } + }); } - - self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some() } - /// Returns `true` if this type is valid for reordering and `-Z randomize-layout` - /// was enabled for its declaration crate - pub fn can_randomize_type_layout(&self) -> bool { - !self.inhibit_struct_field_reordering_opt() - && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT) + // If `-Z randomize-layout` was enabled for the type definition then we can + // consider performing layout randomization + if tcx.sess.opts.unstable_opts.randomize_layout { + flags.insert(ReprFlags::RANDOMIZE_LAYOUT); } - /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations. - pub fn inhibit_union_abi_opt(&self) -> bool { - self.c() + // This is here instead of layout because the choice must make it into metadata. + if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) { + flags.insert(ReprFlags::IS_LINEAR); } + + ReprOptions { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed } } impl<'tcx> FieldDef { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index f72e236eda1..6561c4c278d 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -8,8 +8,6 @@ use crate::ty::{ }; use crate::ty::{GenericArgKind, SubstsRef}; use rustc_apfloat::Float as _; -use rustc_ast as ast; -use rustc_attr::{self as attr, SignedInt, UnsignedInt}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorGuaranteed; @@ -19,7 +17,7 @@ use rustc_hir::def_id::DefId; use rustc_index::bit_set::GrowableBitSet; use rustc_macros::HashStable; use rustc_span::{sym, DUMMY_SP}; -use rustc_target::abi::{Integer, Size, TargetDataLayout}; +use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout}; use rustc_target::spec::abi::Abi; use smallvec::SmallVec; use std::{fmt, iter}; @@ -104,21 +102,12 @@ pub trait IntTypeExt { fn initial_discriminant<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Discr<'tcx>; } -impl IntTypeExt for attr::IntType { +impl IntTypeExt for IntegerType { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - match *self { - SignedInt(ast::IntTy::I8) => tcx.types.i8, - SignedInt(ast::IntTy::I16) => tcx.types.i16, - SignedInt(ast::IntTy::I32) => tcx.types.i32, - SignedInt(ast::IntTy::I64) => tcx.types.i64, - SignedInt(ast::IntTy::I128) => tcx.types.i128, - SignedInt(ast::IntTy::Isize) => tcx.types.isize, - UnsignedInt(ast::UintTy::U8) => tcx.types.u8, - UnsignedInt(ast::UintTy::U16) => tcx.types.u16, - UnsignedInt(ast::UintTy::U32) => tcx.types.u32, - UnsignedInt(ast::UintTy::U64) => tcx.types.u64, - UnsignedInt(ast::UintTy::U128) => tcx.types.u128, - UnsignedInt(ast::UintTy::Usize) => tcx.types.usize, + match self { + IntegerType::Pointer(true) => tcx.types.isize, + IntegerType::Pointer(false) => tcx.types.usize, + IntegerType::Fixed(i, s) => i.to_ty(tcx, *s), } } |
