Skip to content

Commit 27fb904

Browse files
committed
move some layout logic to rustc_target::abi::layout
1 parent 09a3846 commit 27fb904

File tree

15 files changed

+1231
-1157
lines changed

15 files changed

+1231
-1157
lines changed

Cargo.lock

+3
Original file line numberDiff line numberDiff line change
@@ -4281,6 +4281,8 @@ name = "rustc_target"
42814281
version = "0.0.0"
42824282
dependencies = [
42834283
"bitflags",
4284+
"rand 0.8.5",
4285+
"rand_xoshiro",
42844286
"rustc_data_structures",
42854287
"rustc_feature",
42864288
"rustc_index",
@@ -4336,6 +4338,7 @@ dependencies = [
43364338
"rustc_infer",
43374339
"rustc_middle",
43384340
"rustc_span",
4341+
"rustc_target",
43394342
"rustc_trait_selection",
43404343
"smallvec",
43414344
"tracing",

compiler/rustc_hir_analysis/src/collect.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ use rustc_middle::hir::nested_filter;
3232
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
3333
use rustc_middle::mir::mono::Linkage;
3434
use rustc_middle::ty::query::Providers;
35+
use rustc_middle::ty::repr_options_of_def;
3536
use rustc_middle::ty::util::{Discr, IntTypeExt};
36-
use rustc_middle::ty::ReprOptions;
3737
use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, IsSuggestable, Ty, TyCtxt};
3838
use rustc_session::lint;
3939
use rustc_session::parse::feature_err;
@@ -860,7 +860,7 @@ fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {
860860
bug!();
861861
};
862862

863-
let repr = ReprOptions::new(tcx, def_id.to_def_id());
863+
let repr = repr_options_of_def(tcx, def_id.to_def_id());
864864
let (kind, variants) = match item.kind {
865865
ItemKind::Enum(ref def, _) => {
866866
let mut distance_from_explicit = 0;

compiler/rustc_lint/src/types.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable,
1212
use rustc_span::source_map;
1313
use rustc_span::symbol::sym;
1414
use rustc_span::{Span, Symbol};
15-
use rustc_target::abi::{Abi, WrappingRange};
15+
use rustc_target::abi::{Abi, Size, WrappingRange};
1616
use rustc_target::abi::{Integer, TagEncoding, Variants};
1717
use rustc_target::spec::abi::Abi as SpecAbi;
1818

@@ -225,11 +225,11 @@ fn report_bin_hex_error(
225225
cx: &LateContext<'_>,
226226
expr: &hir::Expr<'_>,
227227
ty: attr::IntType,
228+
size: Size,
228229
repr_str: String,
229230
val: u128,
230231
negative: bool,
231232
) {
232-
let size = Integer::from_attr(&cx.tcx, ty).size();
233233
cx.struct_span_lint(
234234
OVERFLOWING_LITERALS,
235235
expr.span,
@@ -352,6 +352,7 @@ fn lint_int_literal<'tcx>(
352352
cx,
353353
e,
354354
attr::IntType::SignedInt(ty::ast_int_ty(t)),
355+
Integer::from_int_ty(cx, t).size(),
355356
repr_str,
356357
v,
357358
negative,
@@ -437,6 +438,7 @@ fn lint_uint_literal<'tcx>(
437438
cx,
438439
e,
439440
attr::IntType::UnsignedInt(ty::ast_uint_ty(t)),
441+
Integer::from_uint_ty(cx, t).size(),
440442
repr_str,
441443
lit_val,
442444
false,

compiler/rustc_middle/src/ty/adt.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,15 @@ use rustc_index::vec::{Idx, IndexVec};
1414
use rustc_query_system::ich::StableHashingContext;
1515
use rustc_session::DataTypeKind;
1616
use rustc_span::symbol::sym;
17-
use rustc_target::abi::VariantIdx;
17+
use rustc_target::abi::{ReprOptions, VariantIdx};
1818

1919
use std::cell::RefCell;
2020
use std::cmp::Ordering;
2121
use std::hash::{Hash, Hasher};
2222
use std::ops::Range;
2323
use std::str;
2424

25-
use super::{
26-
Destructor, FieldDef, GenericPredicates, ReprOptions, Ty, TyCtxt, VariantDef, VariantDiscr,
27-
};
25+
use super::{Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, VariantDiscr};
2826

2927
bitflags! {
3028
#[derive(HashStable, TyEncodable, TyDecodable)]

compiler/rustc_middle/src/ty/layout.rs

+12-19
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
22
use crate::ty::normalize_erasing_regions::NormalizationError;
33
use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitable};
4-
use rustc_ast as ast;
5-
use rustc_attr as attr;
64
use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
75
use rustc_hir as hir;
86
use rustc_hir::def_id::DefId;
@@ -20,7 +18,6 @@ use std::ops::Bound;
2018

2119
pub trait IntegerExt {
2220
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>;
23-
fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer;
2421
fn from_int_ty<C: HasDataLayout>(cx: &C, ity: ty::IntTy) -> Integer;
2522
fn from_uint_ty<C: HasDataLayout>(cx: &C, uty: ty::UintTy) -> Integer;
2623
fn repr_discr<'tcx>(
@@ -49,22 +46,6 @@ impl IntegerExt for Integer {
4946
}
5047
}
5148

52-
/// Gets the Integer type from an attr::IntType.
53-
fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer {
54-
let dl = cx.data_layout();
55-
56-
match ity {
57-
attr::SignedInt(ast::IntTy::I8) | attr::UnsignedInt(ast::UintTy::U8) => I8,
58-
attr::SignedInt(ast::IntTy::I16) | attr::UnsignedInt(ast::UintTy::U16) => I16,
59-
attr::SignedInt(ast::IntTy::I32) | attr::UnsignedInt(ast::UintTy::U32) => I32,
60-
attr::SignedInt(ast::IntTy::I64) | attr::UnsignedInt(ast::UintTy::U64) => I64,
61-
attr::SignedInt(ast::IntTy::I128) | attr::UnsignedInt(ast::UintTy::U128) => I128,
62-
attr::SignedInt(ast::IntTy::Isize) | attr::UnsignedInt(ast::UintTy::Usize) => {
63-
dl.ptr_sized_integer()
64-
}
65-
}
66-
}
67-
6849
fn from_int_ty<C: HasDataLayout>(cx: &C, ity: ty::IntTy) -> Integer {
6950
match ity {
7051
ty::IntTy::I8 => I8,
@@ -237,6 +218,18 @@ pub struct LayoutCx<'tcx, C> {
237218
pub param_env: ty::ParamEnv<'tcx>,
238219
}
239220

221+
impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> {
222+
type TargetDataLayoutRef = &'tcx TargetDataLayout;
223+
224+
fn delay_bug(&self, txt: &str) {
225+
self.tcx.sess.delay_span_bug(DUMMY_SP, txt);
226+
}
227+
228+
fn current_data_layout(&self) -> Self::TargetDataLayoutRef {
229+
&self.tcx.data_layout
230+
}
231+
}
232+
240233
/// Type size "skeleton", i.e., the only information determining a type's size.
241234
/// While this is conservative, (aside from constant sizes, only pointers,
242235
/// newtypes thereof and null pointer optimized enums are allowed), it is

compiler/rustc_middle/src/ty/mod.rs

+62-146
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ use rustc_session::cstore::CrateStoreDyn;
4848
use rustc_span::hygiene::MacroKind;
4949
use rustc_span::symbol::{kw, sym, Ident, Symbol};
5050
use rustc_span::{ExpnId, Span};
51-
use rustc_target::abi::{Align, VariantIdx};
51+
use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx};
52+
pub use rustc_target::abi::{ReprFlags, ReprOptions};
5253
pub use subst::*;
5354
pub use vtable::*;
5455

@@ -1994,161 +1995,76 @@ impl Hash for FieldDef {
19941995
}
19951996
}
19961997

1997-
bitflags! {
1998-
#[derive(TyEncodable, TyDecodable, Default, HashStable)]
1999-
pub struct ReprFlags: u8 {
2000-
const IS_C = 1 << 0;
2001-
const IS_SIMD = 1 << 1;
2002-
const IS_TRANSPARENT = 1 << 2;
2003-
// Internal only for now. If true, don't reorder fields.
2004-
const IS_LINEAR = 1 << 3;
2005-
// If true, the type's layout can be randomized using
2006-
// the seed stored in `ReprOptions.layout_seed`
2007-
const RANDOMIZE_LAYOUT = 1 << 4;
2008-
// Any of these flags being set prevent field reordering optimisation.
2009-
const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits
2010-
| ReprFlags::IS_SIMD.bits
2011-
| ReprFlags::IS_LINEAR.bits;
2012-
}
2013-
}
2014-
2015-
/// Represents the repr options provided by the user,
2016-
#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Default, HashStable)]
2017-
pub struct ReprOptions {
2018-
pub int: Option<attr::IntType>,
2019-
pub align: Option<Align>,
2020-
pub pack: Option<Align>,
2021-
pub flags: ReprFlags,
2022-
/// The seed to be used for randomizing a type's layout
2023-
///
2024-
/// Note: This could technically be a `[u8; 16]` (a `u128`) which would
2025-
/// be the "most accurate" hash as it'd encompass the item and crate
2026-
/// hash without loss, but it does pay the price of being larger.
2027-
/// Everything's a tradeoff, a `u64` seed should be sufficient for our
2028-
/// purposes (primarily `-Z randomize-layout`)
2029-
pub field_shuffle_seed: u64,
2030-
}
2031-
2032-
impl ReprOptions {
2033-
pub fn new(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions {
2034-
let mut flags = ReprFlags::empty();
2035-
let mut size = None;
2036-
let mut max_align: Option<Align> = None;
2037-
let mut min_pack: Option<Align> = None;
2038-
2039-
// Generate a deterministically-derived seed from the item's path hash
2040-
// to allow for cross-crate compilation to actually work
2041-
let mut field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash();
2042-
2043-
// If the user defined a custom seed for layout randomization, xor the item's
2044-
// path hash with the user defined seed, this will allowing determinism while
2045-
// still allowing users to further randomize layout generation for e.g. fuzzing
2046-
if let Some(user_seed) = tcx.sess.opts.unstable_opts.layout_seed {
2047-
field_shuffle_seed ^= user_seed;
2048-
}
2049-
2050-
for attr in tcx.get_attrs(did, sym::repr) {
2051-
for r in attr::parse_repr_attr(&tcx.sess, attr) {
2052-
flags.insert(match r {
2053-
attr::ReprC => ReprFlags::IS_C,
2054-
attr::ReprPacked(pack) => {
2055-
let pack = Align::from_bytes(pack as u64).unwrap();
2056-
min_pack = Some(if let Some(min_pack) = min_pack {
2057-
min_pack.min(pack)
2058-
} else {
2059-
pack
2060-
});
2061-
ReprFlags::empty()
2062-
}
2063-
attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
2064-
attr::ReprSimd => ReprFlags::IS_SIMD,
2065-
attr::ReprInt(i) => {
2066-
size = Some(i);
2067-
ReprFlags::empty()
2068-
}
2069-
attr::ReprAlign(align) => {
2070-
max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap()));
2071-
ReprFlags::empty()
2072-
}
2073-
});
2074-
}
2075-
}
1998+
pub fn repr_options_of_def(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions {
1999+
let mut flags = ReprFlags::empty();
2000+
let mut size = None;
2001+
let mut max_align: Option<Align> = None;
2002+
let mut min_pack: Option<Align> = None;
20762003

2077-
// If `-Z randomize-layout` was enabled for the type definition then we can
2078-
// consider performing layout randomization
2079-
if tcx.sess.opts.unstable_opts.randomize_layout {
2080-
flags.insert(ReprFlags::RANDOMIZE_LAYOUT);
2081-
}
2004+
// Generate a deterministically-derived seed from the item's path hash
2005+
// to allow for cross-crate compilation to actually work
2006+
let mut field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash();
20822007

2083-
// This is here instead of layout because the choice must make it into metadata.
2084-
if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) {
2085-
flags.insert(ReprFlags::IS_LINEAR);
2086-
}
2087-
2088-
Self { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
2089-
}
2090-
2091-
#[inline]
2092-
pub fn simd(&self) -> bool {
2093-
self.flags.contains(ReprFlags::IS_SIMD)
2008+
// If the user defined a custom seed for layout randomization, xor the item's
2009+
// path hash with the user defined seed, this will allowing determinism while
2010+
// still allowing users to further randomize layout generation for e.g. fuzzing
2011+
if let Some(user_seed) = tcx.sess.opts.unstable_opts.layout_seed {
2012+
field_shuffle_seed ^= user_seed;
20942013
}
20952014

2096-
#[inline]
2097-
pub fn c(&self) -> bool {
2098-
self.flags.contains(ReprFlags::IS_C)
2099-
}
2100-
2101-
#[inline]
2102-
pub fn packed(&self) -> bool {
2103-
self.pack.is_some()
2104-
}
2105-
2106-
#[inline]
2107-
pub fn transparent(&self) -> bool {
2108-
self.flags.contains(ReprFlags::IS_TRANSPARENT)
2109-
}
2110-
2111-
#[inline]
2112-
pub fn linear(&self) -> bool {
2113-
self.flags.contains(ReprFlags::IS_LINEAR)
2114-
}
2115-
2116-
/// Returns the discriminant type, given these `repr` options.
2117-
/// This must only be called on enums!
2118-
pub fn discr_type(&self) -> attr::IntType {
2119-
self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize))
2120-
}
2121-
2122-
/// Returns `true` if this `#[repr()]` should inhabit "smart enum
2123-
/// layout" optimizations, such as representing `Foo<&T>` as a
2124-
/// single pointer.
2125-
pub fn inhibit_enum_layout_opt(&self) -> bool {
2126-
self.c() || self.int.is_some()
2127-
}
2128-
2129-
/// Returns `true` if this `#[repr()]` should inhibit struct field reordering
2130-
/// optimizations, such as with `repr(C)`, `repr(packed(1))`, or `repr(<int>)`.
2131-
pub fn inhibit_struct_field_reordering_opt(&self) -> bool {
2132-
if let Some(pack) = self.pack {
2133-
if pack.bytes() == 1 {
2134-
return true;
2135-
}
2015+
for attr in tcx.get_attrs(did, sym::repr) {
2016+
for r in attr::parse_repr_attr(&tcx.sess, attr) {
2017+
flags.insert(match r {
2018+
attr::ReprC => ReprFlags::IS_C,
2019+
attr::ReprPacked(pack) => {
2020+
let pack = Align::from_bytes(pack as u64).unwrap();
2021+
min_pack =
2022+
Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack });
2023+
ReprFlags::empty()
2024+
}
2025+
attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
2026+
attr::ReprSimd => ReprFlags::IS_SIMD,
2027+
attr::ReprInt(i) => {
2028+
size = Some(match i {
2029+
attr::IntType::SignedInt(x) => match x {
2030+
ast::IntTy::Isize => IntegerType::Pointer(true),
2031+
ast::IntTy::I8 => IntegerType::Fixed(Integer::I8, true),
2032+
ast::IntTy::I16 => IntegerType::Fixed(Integer::I16, true),
2033+
ast::IntTy::I32 => IntegerType::Fixed(Integer::I32, true),
2034+
ast::IntTy::I64 => IntegerType::Fixed(Integer::I64, true),
2035+
ast::IntTy::I128 => IntegerType::Fixed(Integer::I128, true),
2036+
},
2037+
attr::IntType::UnsignedInt(x) => match x {
2038+
ast::UintTy::Usize => IntegerType::Pointer(false),
2039+
ast::UintTy::U8 => IntegerType::Fixed(Integer::I8, false),
2040+
ast::UintTy::U16 => IntegerType::Fixed(Integer::I16, false),
2041+
ast::UintTy::U32 => IntegerType::Fixed(Integer::I32, false),
2042+
ast::UintTy::U64 => IntegerType::Fixed(Integer::I64, false),
2043+
ast::UintTy::U128 => IntegerType::Fixed(Integer::I128, false),
2044+
},
2045+
});
2046+
ReprFlags::empty()
2047+
}
2048+
attr::ReprAlign(align) => {
2049+
max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap()));
2050+
ReprFlags::empty()
2051+
}
2052+
});
21362053
}
2137-
2138-
self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some()
21392054
}
21402055

2141-
/// Returns `true` if this type is valid for reordering and `-Z randomize-layout`
2142-
/// was enabled for its declaration crate
2143-
pub fn can_randomize_type_layout(&self) -> bool {
2144-
!self.inhibit_struct_field_reordering_opt()
2145-
&& self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT)
2056+
// If `-Z randomize-layout` was enabled for the type definition then we can
2057+
// consider performing layout randomization
2058+
if tcx.sess.opts.unstable_opts.randomize_layout {
2059+
flags.insert(ReprFlags::RANDOMIZE_LAYOUT);
21462060
}
21472061

2148-
/// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations.
2149-
pub fn inhibit_union_abi_opt(&self) -> bool {
2150-
self.c()
2062+
// This is here instead of layout because the choice must make it into metadata.
2063+
if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) {
2064+
flags.insert(ReprFlags::IS_LINEAR);
21512065
}
2066+
2067+
ReprOptions { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
21522068
}
21532069

21542070
impl<'tcx> FieldDef {

0 commit comments

Comments
 (0)