@@ -143,7 +143,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
143143 // Simple cases, which don't need DST adjustment:
144144 // * no metadata available - just log the case
145145 // * known alignment - sized types, `[T]`, `str` or a foreign type
146- // * packed struct - there is no alignment padding
146+ // Note that looking at `field.align` is incorrect since that is not necessarily equal
147+ // to the dynamic alignment of the type.
147148 match field. ty . kind ( ) {
148149 _ if self . llextra . is_none ( ) => {
149150 debug ! (
@@ -154,14 +155,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
154155 }
155156 _ if field. is_sized ( ) => return simple ( ) ,
156157 ty:: Slice ( ..) | ty:: Str | ty:: Foreign ( ..) => return simple ( ) ,
157- ty:: Adt ( def, _) => {
158- if def. repr ( ) . packed ( ) {
159- // FIXME(eddyb) generalize the adjustment when we
160- // start supporting packing to larger alignments.
161- assert_eq ! ( self . layout. align. abi. bytes( ) , 1 ) ;
162- return simple ( ) ;
163- }
164- }
165158 _ => { }
166159 }
167160
@@ -186,7 +179,16 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
186179 let unaligned_offset = bx. cx ( ) . const_usize ( offset. bytes ( ) ) ;
187180
188181 // Get the alignment of the field
189- let ( _, unsized_align) = glue:: size_and_align_of_dst ( bx, field. ty , meta) ;
182+ let ( _, mut unsized_align) = glue:: size_and_align_of_dst ( bx, field. ty , meta) ;
183+
184+ // For packed types, we need to cap alignment.
185+ if let ty:: Adt ( def, _) = self . layout . ty . kind ( )
186+ && let Some ( packed) = def. repr ( ) . pack
187+ {
188+ let packed = bx. const_usize ( packed. bytes ( ) ) ;
189+ let cmp = bx. icmp ( IntPredicate :: IntULT , unsized_align, packed) ;
190+ unsized_align = bx. select ( cmp, unsized_align, packed)
191+ }
190192
191193 // Bump the unaligned offset up to the appropriate alignment
192194 let offset = round_up_const_value_to_alignment ( bx, unaligned_offset, unsized_align) ;
0 commit comments