@@ -548,8 +548,12 @@ pub type FieldPath = Vec<u32>;
548
548
/// A structure, a product type in ADT terms.
549
549
#[ derive( PartialEq , Eq , Hash , Debug ) ]
550
550
pub struct Struct {
551
+ /// Maximum alignment of fields and repr alignment.
551
552
pub align : Align ,
552
553
554
+ /// Primitive alignment of fields without repr alignment.
555
+ pub primitive_align : Align ,
556
+
553
557
/// If true, no alignment padding is used.
554
558
pub packed : bool ,
555
559
@@ -583,10 +587,20 @@ impl<'a, 'gcx, 'tcx> Struct {
583
587
fn new ( dl : & TargetDataLayout , fields : & Vec < & ' a Layout > ,
584
588
repr : & ReprOptions , kind : StructKind ,
585
589
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
+
587
600
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 ( ) ,
590
604
sized : true ,
591
605
offsets : vec ! [ ] ,
592
606
memory_index : vec ! [ ] ,
@@ -660,7 +674,9 @@ impl<'a, 'gcx, 'tcx> Struct {
660
674
// Invariant: offset < dl.obj_size_bound() <= 1<<61
661
675
if !ret. packed {
662
676
let align = field. align ( dl) ;
677
+ let primitive_align = field. primitive_align ( dl) ;
663
678
ret. align = ret. align . max ( align) ;
679
+ ret. primitive_align = ret. primitive_align . max ( primitive_align) ;
664
680
offset = offset. abi_align ( align) ;
665
681
}
666
682
@@ -671,6 +687,11 @@ impl<'a, 'gcx, 'tcx> Struct {
671
687
. map_or ( Err ( LayoutError :: SizeOverflow ( scapegoat) ) , Ok ) ?;
672
688
}
673
689
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
+ }
674
695
675
696
debug ! ( "Struct::new min_size: {:?}" , offset) ;
676
697
ret. min_size = offset;
@@ -836,12 +857,23 @@ impl<'a, 'gcx, 'tcx> Struct {
836
857
}
837
858
Ok ( None )
838
859
}
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
+ }
839
870
}
840
871
841
872
/// An untagged union.
842
873
#[ derive( PartialEq , Eq , Hash , Debug ) ]
843
874
pub struct Union {
844
875
pub align : Align ,
876
+ pub primitive_align : Align ,
845
877
846
878
pub min_size : Size ,
847
879
@@ -851,8 +883,10 @@ pub struct Union {
851
883
852
884
impl < ' a , ' gcx , ' tcx > Union {
853
885
fn new ( dl : & TargetDataLayout , packed : bool ) -> Union {
886
+ let align = if packed { dl. i8_align } else { dl. aggregate_align } ;
854
887
Union {
855
- align : if packed { dl. i8_align } else { dl. aggregate_align } ,
888
+ align : align,
889
+ primitive_align : align,
856
890
min_size : Size :: from_bytes ( 0 ) ,
857
891
packed : packed,
858
892
}
@@ -875,6 +909,7 @@ impl<'a, 'gcx, 'tcx> Union {
875
909
876
910
if !self . packed {
877
911
self . align = self . align . max ( field. align ( dl) ) ;
912
+ self . primitive_align = self . primitive_align . max ( field. primitive_align ( dl) ) ;
878
913
}
879
914
self . min_size = cmp:: max ( self . min_size , field. size ( dl) ) ;
880
915
}
@@ -888,6 +923,16 @@ impl<'a, 'gcx, 'tcx> Union {
888
923
pub fn stride ( & self ) -> Size {
889
924
self . min_size . abi_align ( self . align )
890
925
}
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
+ }
891
936
}
892
937
893
938
/// The first half of a fat pointer.
@@ -924,6 +969,7 @@ pub enum Layout {
924
969
/// If true, the size is exact, otherwise it's only a lower bound.
925
970
sized : bool ,
926
971
align : Align ,
972
+ primitive_align : Align ,
927
973
element_size : Size ,
928
974
count : u64
929
975
} ,
@@ -970,7 +1016,8 @@ pub enum Layout {
970
1016
discr : Integer ,
971
1017
variants : Vec < Struct > ,
972
1018
size : Size ,
973
- align : Align
1019
+ align : Align ,
1020
+ primitive_align : Align ,
974
1021
} ,
975
1022
976
1023
/// Two cases distinguished by a nullable pointer: the case with discriminant
@@ -1118,6 +1165,7 @@ impl<'a, 'gcx, 'tcx> Layout {
1118
1165
Array {
1119
1166
sized : true ,
1120
1167
align : element. align ( dl) ,
1168
+ primitive_align : element. primitive_align ( dl) ,
1121
1169
element_size : element_size,
1122
1170
count : count
1123
1171
}
@@ -1127,6 +1175,7 @@ impl<'a, 'gcx, 'tcx> Layout {
1127
1175
Array {
1128
1176
sized : false ,
1129
1177
align : element. align ( dl) ,
1178
+ primitive_align : element. primitive_align ( dl) ,
1130
1179
element_size : element. size ( dl) ,
1131
1180
count : 0
1132
1181
}
@@ -1135,6 +1184,7 @@ impl<'a, 'gcx, 'tcx> Layout {
1135
1184
Array {
1136
1185
sized : false ,
1137
1186
align : dl. i8_align ,
1187
+ primitive_align : dl. i8_align ,
1138
1188
element_size : Size :: from_bytes ( 1 ) ,
1139
1189
count : 0
1140
1190
}
@@ -1340,6 +1390,7 @@ impl<'a, 'gcx, 'tcx> Layout {
1340
1390
assert ! ( discr_max >= 0 ) ;
1341
1391
let ( min_ity, _) = Integer :: repr_discr ( tcx, ty, & def. repr , 0 , discr_max) ;
1342
1392
let mut align = dl. aggregate_align ;
1393
+ let mut primitive_align = dl. aggregate_align ;
1343
1394
let mut size = Size :: from_bytes ( 0 ) ;
1344
1395
1345
1396
// We're interested in the smallest alignment, so start large.
@@ -1369,6 +1420,7 @@ impl<'a, 'gcx, 'tcx> Layout {
1369
1420
}
1370
1421
size = cmp:: max ( size, st. min_size ) ;
1371
1422
align = align. max ( st. align ) ;
1423
+ primitive_align = primitive_align. max ( st. primitive_align ) ;
1372
1424
Ok ( st)
1373
1425
} ) . collect :: < Result < Vec < _ > , _ > > ( ) ?;
1374
1426
@@ -1435,7 +1487,8 @@ impl<'a, 'gcx, 'tcx> Layout {
1435
1487
discr : ity,
1436
1488
variants : variants,
1437
1489
size : size,
1438
- align : align
1490
+ align : align,
1491
+ primitive_align : primitive_align
1439
1492
}
1440
1493
}
1441
1494
@@ -1557,6 +1610,30 @@ impl<'a, 'gcx, 'tcx> Layout {
1557
1610
}
1558
1611
}
1559
1612
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
+
1560
1637
pub fn field_offset < C : HasDataLayout > ( & self ,
1561
1638
cx : C ,
1562
1639
i : usize ,
0 commit comments