@@ -48,7 +48,8 @@ use rustc_session::cstore::CrateStoreDyn;
4848use rustc_span:: hygiene:: MacroKind ;
4949use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
5050use 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 } ;
5253pub use subst:: * ;
5354pub 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
21542070impl < ' tcx > FieldDef {
0 commit comments