@@ -12,7 +12,7 @@ pub use self::Integer::*;
12
12
pub use self :: Primitive :: * ;
13
13
14
14
use session:: { self , DataTypeKind , Session } ;
15
- use ty:: { self , Ty , TyCtxt , TypeFoldable , ReprOptions , ReprFlags } ;
15
+ use ty:: { self , Ty , TyCtxt , TypeFoldable , ReprOptions } ;
16
16
17
17
use syntax:: ast:: { self , FloatTy , IntTy , UintTy } ;
18
18
use syntax:: attr;
@@ -344,8 +344,8 @@ impl AddAssign for Size {
344
344
/// a maximum capacity of 2<sup>31</sup> - 1 or 2147483647.
345
345
#[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug , RustcEncodable , RustcDecodable ) ]
346
346
pub struct Align {
347
- abi : u8 ,
348
- pref : u8 ,
347
+ abi_pow2 : u8 ,
348
+ pref_pow2 : u8 ,
349
349
}
350
350
351
351
impl Align {
@@ -377,17 +377,17 @@ impl Align {
377
377
} ;
378
378
379
379
Ok ( Align {
380
- abi : log2 ( abi) ?,
381
- pref : log2 ( pref) ?,
380
+ abi_pow2 : log2 ( abi) ?,
381
+ pref_pow2 : log2 ( pref) ?,
382
382
} )
383
383
}
384
384
385
385
pub fn abi ( self ) -> u64 {
386
- 1 << self . abi
386
+ 1 << self . abi_pow2
387
387
}
388
388
389
389
pub fn pref ( self ) -> u64 {
390
- 1 << self . pref
390
+ 1 << self . pref_pow2
391
391
}
392
392
393
393
pub fn abi_bits ( self ) -> u64 {
@@ -400,15 +400,15 @@ impl Align {
400
400
401
401
pub fn min ( self , other : Align ) -> Align {
402
402
Align {
403
- abi : cmp:: min ( self . abi , other. abi ) ,
404
- pref : cmp:: min ( self . pref , other. pref ) ,
403
+ abi_pow2 : cmp:: min ( self . abi_pow2 , other. abi_pow2 ) ,
404
+ pref_pow2 : cmp:: min ( self . pref_pow2 , other. pref_pow2 ) ,
405
405
}
406
406
}
407
407
408
408
pub fn max ( self , other : Align ) -> Align {
409
409
Align {
410
- abi : cmp:: max ( self . abi , other. abi ) ,
411
- pref : cmp:: max ( self . pref , other. pref ) ,
410
+ abi_pow2 : cmp:: max ( self . abi_pow2 , other. abi_pow2 ) ,
411
+ pref_pow2 : cmp:: max ( self . pref_pow2 , other. pref_pow2 ) ,
412
412
}
413
413
}
414
414
}
@@ -974,6 +974,11 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
974
974
bug ! ( "struct cannot be packed and aligned" ) ;
975
975
}
976
976
977
+ let pack = {
978
+ let pack = repr. pack as u64 ;
979
+ Align :: from_bytes ( pack, pack) . unwrap ( )
980
+ } ;
981
+
977
982
let mut align = if packed {
978
983
dl. i8_align
979
984
} else {
@@ -984,8 +989,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
984
989
let mut offsets = vec ! [ Size :: from_bytes( 0 ) ; fields. len( ) ] ;
985
990
let mut inverse_memory_index: Vec < u32 > = ( 0 ..fields. len ( ) as u32 ) . collect ( ) ;
986
991
987
- // Anything with repr(C) or repr(packed) doesn't optimize.
988
- let mut optimize = ( repr. flags & ReprFlags :: IS_UNOPTIMISABLE ) . is_empty ( ) ;
992
+ let mut optimize = !repr. inhibit_struct_field_reordering_opt ( ) ;
989
993
if let StructKind :: Prefixed ( _, align) = kind {
990
994
optimize &= align. abi ( ) == 1 ;
991
995
}
@@ -997,18 +1001,21 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
997
1001
fields. len ( )
998
1002
} ;
999
1003
let optimizing = & mut inverse_memory_index[ ..end] ;
1004
+ let field_align = |f : & TyLayout | {
1005
+ if packed { f. align . min ( pack) . abi ( ) } else { f. align . abi ( ) }
1006
+ } ;
1000
1007
match kind {
1001
1008
StructKind :: AlwaysSized |
1002
1009
StructKind :: MaybeUnsized => {
1003
1010
optimizing. sort_by_key ( |& x| {
1004
1011
// Place ZSTs first to avoid "interesting offsets",
1005
1012
// especially with only one or two non-ZST fields.
1006
1013
let f = & fields[ x as usize ] ;
1007
- ( !f. is_zst ( ) , cmp:: Reverse ( f . align . abi ( ) ) )
1008
- } )
1014
+ ( !f. is_zst ( ) , cmp:: Reverse ( field_align ( f ) ) )
1015
+ } ) ;
1009
1016
}
1010
1017
StructKind :: Prefixed ( ..) => {
1011
- optimizing. sort_by_key ( |& x| fields[ x as usize ] . align . abi ( ) ) ;
1018
+ optimizing. sort_by_key ( |& x| field_align ( & fields[ x as usize ] ) ) ;
1012
1019
}
1013
1020
}
1014
1021
}
@@ -1022,7 +1029,10 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
1022
1029
let mut offset = Size :: from_bytes ( 0 ) ;
1023
1030
1024
1031
if let StructKind :: Prefixed ( prefix_size, prefix_align) = kind {
1025
- if !packed {
1032
+ if packed {
1033
+ let prefix_align = prefix_align. min ( pack) ;
1034
+ align = align. max ( prefix_align) ;
1035
+ } else {
1026
1036
align = align. max ( prefix_align) ;
1027
1037
}
1028
1038
offset = prefix_size. abi_align ( prefix_align) ;
@@ -1044,7 +1054,12 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
1044
1054
}
1045
1055
1046
1056
// Invariant: offset < dl.obj_size_bound() <= 1<<61
1047
- if !packed {
1057
+ if packed {
1058
+ let field_pack = field. align . min ( pack) ;
1059
+ offset = offset. abi_align ( field_pack) ;
1060
+ align = align. max ( field_pack) ;
1061
+ }
1062
+ else {
1048
1063
offset = offset. abi_align ( field. align ) ;
1049
1064
align = align. max ( field. align ) ;
1050
1065
}
@@ -1377,7 +1392,12 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
1377
1392
bug ! ( "Union cannot be packed and aligned" ) ;
1378
1393
}
1379
1394
1380
- let mut align = if def. repr . packed ( ) {
1395
+ let pack = {
1396
+ let pack = def. repr . pack as u64 ;
1397
+ Align :: from_bytes ( pack, pack) . unwrap ( )
1398
+ } ;
1399
+
1400
+ let mut align = if packed {
1381
1401
dl. i8_align
1382
1402
} else {
1383
1403
dl. aggregate_align
@@ -1393,7 +1413,10 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
1393
1413
for field in & variants[ 0 ] {
1394
1414
assert ! ( !field. is_unsized( ) ) ;
1395
1415
1396
- if !packed {
1416
+ if packed {
1417
+ let field_pack = field. align . min ( pack) ;
1418
+ align = align. max ( field_pack) ;
1419
+ } else {
1397
1420
align = align. max ( field. align ) ;
1398
1421
}
1399
1422
size = cmp:: max ( size, field. size ) ;
@@ -1740,12 +1763,13 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
1740
1763
1741
1764
fn record_layout_for_printing_outlined ( self , layout : TyLayout < ' tcx > ) {
1742
1765
// (delay format until we actually need it)
1743
- let record = |kind, opt_discr_size, variants| {
1766
+ let record = |kind, packed , opt_discr_size, variants| {
1744
1767
let type_desc = format ! ( "{:?}" , layout. ty) ;
1745
1768
self . tcx . sess . code_stats . borrow_mut ( ) . record_type_size ( kind,
1746
1769
type_desc,
1747
1770
layout. align ,
1748
1771
layout. size ,
1772
+ packed,
1749
1773
opt_discr_size,
1750
1774
variants) ;
1751
1775
} ;
@@ -1758,7 +1782,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
1758
1782
1759
1783
ty:: TyClosure ( ..) => {
1760
1784
debug ! ( "print-type-size t: `{:?}` record closure" , layout. ty) ;
1761
- record ( DataTypeKind :: Closure , None , vec ! [ ] ) ;
1785
+ record ( DataTypeKind :: Closure , false , None , vec ! [ ] ) ;
1762
1786
return ;
1763
1787
}
1764
1788
@@ -1769,6 +1793,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
1769
1793
} ;
1770
1794
1771
1795
let adt_kind = adt_def. adt_kind ( ) ;
1796
+ let adt_packed = adt_def. repr . packed ( ) ;
1772
1797
1773
1798
let build_variant_info = |n : Option < ast:: Name > ,
1774
1799
flds : & [ ast:: Name ] ,
@@ -1821,14 +1846,15 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
1821
1846
let fields: Vec < _ > =
1822
1847
variant_def. fields . iter ( ) . map ( |f| f. name ) . collect ( ) ;
1823
1848
record ( adt_kind. into ( ) ,
1849
+ adt_packed,
1824
1850
None ,
1825
1851
vec ! [ build_variant_info( Some ( variant_def. name) ,
1826
1852
& fields,
1827
1853
layout) ] ) ;
1828
1854
} else {
1829
1855
// (This case arises for *empty* enums; so give it
1830
1856
// zero variants.)
1831
- record ( adt_kind. into ( ) , None , vec ! [ ] ) ;
1857
+ record ( adt_kind. into ( ) , adt_packed , None , vec ! [ ] ) ;
1832
1858
}
1833
1859
}
1834
1860
@@ -1845,7 +1871,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
1845
1871
layout. for_variant ( self , i) )
1846
1872
} )
1847
1873
. collect ( ) ;
1848
- record ( adt_kind. into ( ) , match layout. variants {
1874
+ record ( adt_kind. into ( ) , adt_packed , match layout. variants {
1849
1875
Variants :: Tagged { ref discr, .. } => Some ( discr. value . size ( self ) ) ,
1850
1876
_ => None
1851
1877
} , variant_infos) ;
@@ -2518,8 +2544,8 @@ impl_stable_hash_for!(enum ::ty::layout::Primitive {
2518
2544
} ) ;
2519
2545
2520
2546
impl_stable_hash_for ! ( struct :: ty:: layout:: Align {
2521
- abi ,
2522
- pref
2547
+ abi_pow2 ,
2548
+ pref_pow2
2523
2549
} ) ;
2524
2550
2525
2551
impl_stable_hash_for ! ( struct :: ty:: layout:: Size {
0 commit comments