@@ -548,8 +548,12 @@ pub type FieldPath = Vec<u32>;
548548/// A structure, a product type in ADT terms.
549549#[ derive( PartialEq , Eq , Hash , Debug ) ]
550550pub struct Struct {
551+ /// Maximum alignment of fields and repr alignment.
551552 pub align : Align ,
552553
554+ /// Primitive alignment of fields without repr alignment.
555+ pub primitive_align : Align ,
556+
553557 /// If true, no alignment padding is used.
554558 pub packed : bool ,
555559
@@ -583,10 +587,20 @@ impl<'a, 'gcx, 'tcx> Struct {
583587 fn new ( dl : & TargetDataLayout , fields : & Vec < & ' a Layout > ,
584588 repr : & ReprOptions , kind : StructKind ,
585589 scapegoat : Ty < ' gcx > ) -> Result < Struct , LayoutError < ' gcx > > {
586- let packed = repr. packed ( ) ;
590+ if repr. packed ( ) && repr. align > 0 {
591+ bug ! ( "Struct cannot be packed and aligned" ) ;
592+ }
593+
594+ let align = if repr. packed ( ) {
595+ dl. i8_align
596+ } else {
597+ dl. aggregate_align
598+ } ;
599+
587600 let mut ret = Struct {
588- align : if packed { dl. i8_align } else { dl. aggregate_align } ,
589- packed : packed,
601+ align : align,
602+ primitive_align : align,
603+ packed : repr. packed ( ) ,
590604 sized : true ,
591605 offsets : vec ! [ ] ,
592606 memory_index : vec ! [ ] ,
@@ -660,7 +674,9 @@ impl<'a, 'gcx, 'tcx> Struct {
660674 // Invariant: offset < dl.obj_size_bound() <= 1<<61
661675 if !ret. packed {
662676 let align = field. align ( dl) ;
677+ let primitive_align = field. primitive_align ( dl) ;
663678 ret. align = ret. align . max ( align) ;
679+ ret. primitive_align = ret. primitive_align . max ( primitive_align) ;
664680 offset = offset. abi_align ( align) ;
665681 }
666682
@@ -671,6 +687,11 @@ impl<'a, 'gcx, 'tcx> Struct {
671687 . map_or ( Err ( LayoutError :: SizeOverflow ( scapegoat) ) , Ok ) ?;
672688 }
673689
690+ if repr. align > 0 {
691+ let repr_align = repr. align as u64 ;
692+ ret. align = ret. align . max ( Align :: from_bytes ( repr_align, repr_align) . unwrap ( ) ) ;
693+ debug ! ( "Struct::new repr_align: {:?}" , repr_align) ;
694+ }
674695
675696 debug ! ( "Struct::new min_size: {:?}" , offset) ;
676697 ret. min_size = offset;
@@ -836,12 +857,23 @@ impl<'a, 'gcx, 'tcx> Struct {
836857 }
837858 Ok ( None )
838859 }
860+
861+ pub fn over_align ( & self ) -> Option < u32 > {
862+ let align = self . align . abi ( ) ;
863+ let primitive_align = self . primitive_align . abi ( ) ;
864+ if align > primitive_align {
865+ Some ( align as u32 )
866+ } else {
867+ None
868+ }
869+ }
839870}
840871
841872/// An untagged union.
842873#[ derive( PartialEq , Eq , Hash , Debug ) ]
843874pub struct Union {
844875 pub align : Align ,
876+ pub primitive_align : Align ,
845877
846878 pub min_size : Size ,
847879
@@ -851,8 +883,10 @@ pub struct Union {
851883
852884impl < ' a , ' gcx , ' tcx > Union {
853885 fn new ( dl : & TargetDataLayout , packed : bool ) -> Union {
886+ let align = if packed { dl. i8_align } else { dl. aggregate_align } ;
854887 Union {
855- align : if packed { dl. i8_align } else { dl. aggregate_align } ,
888+ align : align,
889+ primitive_align : align,
856890 min_size : Size :: from_bytes ( 0 ) ,
857891 packed : packed,
858892 }
@@ -875,6 +909,7 @@ impl<'a, 'gcx, 'tcx> Union {
875909
876910 if !self . packed {
877911 self . align = self . align . max ( field. align ( dl) ) ;
912+ self . primitive_align = self . primitive_align . max ( field. primitive_align ( dl) ) ;
878913 }
879914 self . min_size = cmp:: max ( self . min_size , field. size ( dl) ) ;
880915 }
@@ -888,6 +923,16 @@ impl<'a, 'gcx, 'tcx> Union {
888923 pub fn stride ( & self ) -> Size {
889924 self . min_size . abi_align ( self . align )
890925 }
926+
927+ pub fn over_align ( & self ) -> Option < u32 > {
928+ let align = self . align . abi ( ) ;
929+ let primitive_align = self . primitive_align . abi ( ) ;
930+ if align > primitive_align {
931+ Some ( align as u32 )
932+ } else {
933+ None
934+ }
935+ }
891936}
892937
893938/// The first half of a fat pointer.
@@ -924,6 +969,7 @@ pub enum Layout {
924969 /// If true, the size is exact, otherwise it's only a lower bound.
925970 sized : bool ,
926971 align : Align ,
972+ primitive_align : Align ,
927973 element_size : Size ,
928974 count : u64
929975 } ,
@@ -970,7 +1016,8 @@ pub enum Layout {
9701016 discr : Integer ,
9711017 variants : Vec < Struct > ,
9721018 size : Size ,
973- align : Align
1019+ align : Align ,
1020+ primitive_align : Align ,
9741021 } ,
9751022
9761023 /// Two cases distinguished by a nullable pointer: the case with discriminant
@@ -1118,6 +1165,7 @@ impl<'a, 'gcx, 'tcx> Layout {
11181165 Array {
11191166 sized : true ,
11201167 align : element. align ( dl) ,
1168+ primitive_align : element. primitive_align ( dl) ,
11211169 element_size : element_size,
11221170 count : count
11231171 }
@@ -1127,6 +1175,7 @@ impl<'a, 'gcx, 'tcx> Layout {
11271175 Array {
11281176 sized : false ,
11291177 align : element. align ( dl) ,
1178+ primitive_align : element. primitive_align ( dl) ,
11301179 element_size : element. size ( dl) ,
11311180 count : 0
11321181 }
@@ -1135,6 +1184,7 @@ impl<'a, 'gcx, 'tcx> Layout {
11351184 Array {
11361185 sized : false ,
11371186 align : dl. i8_align ,
1187+ primitive_align : dl. i8_align ,
11381188 element_size : Size :: from_bytes ( 1 ) ,
11391189 count : 0
11401190 }
@@ -1340,6 +1390,7 @@ impl<'a, 'gcx, 'tcx> Layout {
13401390 assert ! ( discr_max >= 0 ) ;
13411391 let ( min_ity, _) = Integer :: repr_discr ( tcx, ty, & def. repr , 0 , discr_max) ;
13421392 let mut align = dl. aggregate_align ;
1393+ let mut primitive_align = dl. aggregate_align ;
13431394 let mut size = Size :: from_bytes ( 0 ) ;
13441395
13451396 // We're interested in the smallest alignment, so start large.
@@ -1369,6 +1420,7 @@ impl<'a, 'gcx, 'tcx> Layout {
13691420 }
13701421 size = cmp:: max ( size, st. min_size ) ;
13711422 align = align. max ( st. align ) ;
1423+ primitive_align = primitive_align. max ( st. primitive_align ) ;
13721424 Ok ( st)
13731425 } ) . collect :: < Result < Vec < _ > , _ > > ( ) ?;
13741426
@@ -1435,7 +1487,8 @@ impl<'a, 'gcx, 'tcx> Layout {
14351487 discr : ity,
14361488 variants : variants,
14371489 size : size,
1438- align : align
1490+ align : align,
1491+ primitive_align : primitive_align
14391492 }
14401493 }
14411494
@@ -1557,6 +1610,30 @@ impl<'a, 'gcx, 'tcx> Layout {
15571610 }
15581611 }
15591612
1613+ /// Returns alignment before repr alignment is applied
1614+ pub fn primitive_align ( & self , dl : & TargetDataLayout ) -> Align {
1615+ match * self {
1616+ Array { primitive_align, .. } | General { primitive_align, .. } => primitive_align,
1617+ Univariant { ref variant, .. } |
1618+ StructWrappedNullablePointer { nonnull : ref variant, .. } => {
1619+ variant. primitive_align
1620+ } ,
1621+
1622+ _ => self . align ( dl)
1623+ }
1624+ }
1625+
1626+ /// Returns repr alignment if it is greater than the primitive alignment.
1627+ pub fn over_align ( & self , dl : & TargetDataLayout ) -> Option < u32 > {
1628+ let align = self . align ( dl) ;
1629+ let primitive_align = self . primitive_align ( dl) ;
1630+ if align. abi ( ) > primitive_align. abi ( ) {
1631+ Some ( align. abi ( ) as u32 )
1632+ } else {
1633+ None
1634+ }
1635+ }
1636+
15601637 pub fn field_offset < C : HasDataLayout > ( & self ,
15611638 cx : C ,
15621639 i : usize ,
0 commit comments