@@ -116,11 +116,12 @@ fn struct_llfields<'a, 'tcx>(
116116 ) ;
117117 assert ! ( target_offset >= offset) ;
118118 let padding = target_offset - offset;
119- let padding_align = prev_effective_align. min ( effective_field_align) ;
120- assert_eq ! ( offset. align_to( padding_align) + padding, target_offset) ;
121- result. push ( cx. type_padding_filler ( padding, padding_align) ) ;
122- debug ! ( " padding before: {:?}" , padding) ;
123-
119+ if padding != Size :: ZERO {
120+ let padding_align = prev_effective_align. min ( effective_field_align) ;
121+ assert_eq ! ( offset. align_to( padding_align) + padding, target_offset) ;
122+ result. push ( cx. type_padding_filler ( padding, padding_align) ) ;
123+ debug ! ( " padding before: {:?}" , padding) ;
124+ }
124125 result. push ( field. llvm_type ( cx) ) ;
125126 offset = target_offset + field. size ;
126127 prev_effective_align = effective_field_align;
@@ -130,14 +131,15 @@ fn struct_llfields<'a, 'tcx>(
130131 bug ! ( "layout: {:#?} stride: {:?} offset: {:?}" , layout, layout. size, offset) ;
131132 }
132133 let padding = layout. size - offset;
133- let padding_align = prev_effective_align;
134- assert_eq ! ( offset. align_to( padding_align) + padding, layout. size) ;
135- debug ! (
136- "struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}" ,
137- padding, offset, layout. size
138- ) ;
139- result. push ( cx. type_padding_filler ( padding, padding_align) ) ;
140- assert_eq ! ( result. len( ) , 1 + field_count * 2 ) ;
134+ if padding != Size :: ZERO {
135+ let padding_align = prev_effective_align;
136+ assert_eq ! ( offset. align_to( padding_align) + padding, layout. size) ;
137+ debug ! (
138+ "struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}" ,
139+ padding, offset, layout. size
140+ ) ;
141+ result. push ( cx. type_padding_filler ( padding, padding_align) ) ;
142+ }
141143 } else {
142144 debug ! ( "struct_llfields: offset: {:?} stride: {:?}" , offset, layout. size) ;
143145 }
@@ -177,7 +179,7 @@ pub trait LayoutLlvmExt<'tcx> {
177179 index : usize ,
178180 immediate : bool ,
179181 ) -> & ' a Type ;
180- fn llvm_field_index ( & self , index : usize ) -> u64 ;
182+ fn llvm_field_index < ' a > ( & self , cx : & CodegenCx < ' a , ' tcx > , index : usize ) -> u64 ;
181183 fn pointee_info_at < ' a > ( & self , cx : & CodegenCx < ' a , ' tcx > , offset : Size ) -> Option < PointeeInfo > ;
182184}
183185
@@ -340,7 +342,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
340342 self . scalar_llvm_type_at ( cx, scalar, offset)
341343 }
342344
343- fn llvm_field_index ( & self , index : usize ) -> u64 {
345+ fn llvm_field_index < ' a > ( & self , cx : & CodegenCx < ' a , ' tcx > , index : usize ) -> u64 {
344346 match self . abi {
345347 Abi :: Scalar ( _) | Abi :: ScalarPair ( ..) => {
346348 bug ! ( "TyAndLayout::llvm_field_index({:?}): not applicable" , self )
@@ -354,7 +356,24 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
354356
355357 FieldsShape :: Array { .. } => index as u64 ,
356358
357- FieldsShape :: Arbitrary { .. } => 1 + ( self . fields . memory_index ( index) as u64 ) * 2 ,
359+ FieldsShape :: Arbitrary { .. } => {
360+ let mut llvm_index = 0 ;
361+ let mut offset = Size :: ZERO ;
362+ for i in self . fields . index_by_increasing_offset ( ) {
363+ let target_offset = self . fields . offset ( i as usize ) ;
364+ let field = self . field ( cx, i) ;
365+ let padding = target_offset - offset;
366+ if padding != Size :: ZERO {
367+ llvm_index += 1 ;
368+ }
369+ if i == index {
370+ return llvm_index;
371+ }
372+ offset = target_offset + field. size ;
373+ llvm_index += 1 ;
374+ }
375+ bug ! ( "TyAndLayout::llvm_field_index({:?}): index {} out of range" , self , index)
376+ }
358377 }
359378 }
360379
0 commit comments