@@ -116,11 +116,12 @@ fn struct_llfields<'a, 'tcx>(
116
116
) ;
117
117
assert ! ( target_offset >= offset) ;
118
118
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
+ }
124
125
result. push ( field. llvm_type ( cx) ) ;
125
126
offset = target_offset + field. size ;
126
127
prev_effective_align = effective_field_align;
@@ -130,14 +131,15 @@ fn struct_llfields<'a, 'tcx>(
130
131
bug ! ( "layout: {:#?} stride: {:?} offset: {:?}" , layout, layout. size, offset) ;
131
132
}
132
133
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
+ }
141
143
} else {
142
144
debug ! ( "struct_llfields: offset: {:?} stride: {:?}" , offset, layout. size) ;
143
145
}
@@ -177,7 +179,7 @@ pub trait LayoutLlvmExt<'tcx> {
177
179
index : usize ,
178
180
immediate : bool ,
179
181
) -> & ' 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 ;
181
183
fn pointee_info_at < ' a > ( & self , cx : & CodegenCx < ' a , ' tcx > , offset : Size ) -> Option < PointeeInfo > ;
182
184
}
183
185
@@ -340,7 +342,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
340
342
self . scalar_llvm_type_at ( cx, scalar, offset)
341
343
}
342
344
343
- fn llvm_field_index ( & self , index : usize ) -> u64 {
345
+ fn llvm_field_index < ' a > ( & self , cx : & CodegenCx < ' a , ' tcx > , index : usize ) -> u64 {
344
346
match self . abi {
345
347
Abi :: Scalar ( _) | Abi :: ScalarPair ( ..) => {
346
348
bug ! ( "TyAndLayout::llvm_field_index({:?}): not applicable" , self )
@@ -354,7 +356,24 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
354
356
355
357
FieldsShape :: Array { .. } => index as u64 ,
356
358
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
+ }
358
377
}
359
378
}
360
379
0 commit comments