11use crate :: abi:: FnAbi ;
22use crate :: common:: * ;
3+ use crate :: context:: TypeLowering ;
34use crate :: type_:: Type ;
45use rustc_codegen_ssa:: traits:: * ;
56use rustc_middle:: bug;
@@ -17,6 +18,7 @@ fn uncached_llvm_type<'a, 'tcx>(
1718 cx : & CodegenCx < ' a , ' tcx > ,
1819 layout : TyAndLayout < ' tcx > ,
1920 defer : & mut Option < ( & ' a Type , TyAndLayout < ' tcx > ) > ,
21+ field_remapping : & mut Option < Box < [ u32 ] > > ,
2022) -> & ' a Type {
2123 match layout. abi {
2224 Abi :: Scalar ( _) => bug ! ( "handled elsewhere" ) ,
@@ -75,7 +77,8 @@ fn uncached_llvm_type<'a, 'tcx>(
7577 FieldsShape :: Array { count, .. } => cx. type_array ( layout. field ( cx, 0 ) . llvm_type ( cx) , count) ,
7678 FieldsShape :: Arbitrary { .. } => match name {
7779 None => {
78- let ( llfields, packed) = struct_llfields ( cx, layout) ;
80+ let ( llfields, packed, new_field_remapping) = struct_llfields ( cx, layout) ;
81+ * field_remapping = new_field_remapping;
7982 cx. type_struct ( & llfields, packed)
8083 }
8184 Some ( ref name) => {
@@ -90,7 +93,7 @@ fn uncached_llvm_type<'a, 'tcx>(
9093fn struct_llfields < ' a , ' tcx > (
9194 cx : & CodegenCx < ' a , ' tcx > ,
9295 layout : TyAndLayout < ' tcx > ,
93- ) -> ( Vec < & ' a Type > , bool ) {
96+ ) -> ( Vec < & ' a Type > , bool , Option < Box < [ u32 ] > > ) {
9497 debug ! ( "struct_llfields: {:#?}" , layout) ;
9598 let field_count = layout. fields . count ( ) ;
9699
@@ -147,11 +150,8 @@ fn struct_llfields<'a, 'tcx>(
147150 } else {
148151 debug ! ( "struct_llfields: offset: {:?} stride: {:?}" , offset, layout. size) ;
149152 }
150- if padding_used {
151- cx. field_projection_cache . borrow_mut ( ) . insert ( layout, projection) ;
152- }
153153
154- ( result, packed)
154+ ( result, packed, padding_used . then_some ( projection . into_boxed_slice ( ) ) )
155155}
156156
157157impl < ' a , ' tcx > CodegenCx < ' a , ' tcx > {
@@ -243,8 +243,8 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
243243 Variants :: Single { index } => Some ( index) ,
244244 _ => None ,
245245 } ;
246- if let Some ( & llty) = cx. lltypes . borrow ( ) . get ( & ( self . ty , variant_index) ) {
247- return llty;
246+ if let Some ( ref llty) = cx. type_lowering . borrow ( ) . get ( & ( self . ty , variant_index) ) {
247+ return llty. lltype ;
248248 }
249249
250250 debug ! ( "llvm_type({:#?})" , self ) ;
@@ -256,24 +256,29 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
256256 let normal_ty = cx. tcx . erase_regions ( self . ty ) ;
257257
258258 let mut defer = None ;
259+ let mut field_remapping = None ;
259260 let llty = if self . ty != normal_ty {
260261 let mut layout = cx. layout_of ( normal_ty) ;
261262 if let Some ( v) = variant_index {
262263 layout = layout. for_variant ( cx, v) ;
263264 }
264265 layout. llvm_type ( cx)
265266 } else {
266- uncached_llvm_type ( cx, * self , & mut defer)
267+ uncached_llvm_type ( cx, * self , & mut defer, & mut field_remapping )
267268 } ;
268269 debug ! ( "--> mapped {:#?} to llty={:?}" , self , llty) ;
269270
270- cx. lltypes . borrow_mut ( ) . insert ( ( self . ty , variant_index) , llty) ;
271+ cx. type_lowering
272+ . borrow_mut ( )
273+ . insert ( ( self . ty , variant_index) , TypeLowering { lltype : llty, field_remapping : None } ) ;
271274
272275 if let Some ( ( llty, layout) ) = defer {
273- let ( llfields, packed) = struct_llfields ( cx, layout) ;
274- cx. set_struct_body ( llty, & llfields, packed)
276+ let ( llfields, packed, new_field_remapping) = struct_llfields ( cx, layout) ;
277+ cx. set_struct_body ( llty, & llfields, packed) ;
278+ field_remapping = new_field_remapping;
275279 }
276-
280+ cx. type_lowering . borrow_mut ( ) . get_mut ( & ( self . ty , variant_index) ) . unwrap ( ) . field_remapping =
281+ field_remapping;
277282 llty
278283 }
279284
@@ -363,12 +368,23 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
363368
364369 FieldsShape :: Array { .. } => index as u64 ,
365370
366- // Look up llvm field index in projection cache if present. If no projection cache
367- // is present no padding is used and the llvm field index matches the memory index.
368- FieldsShape :: Arbitrary { .. } => match cx. field_projection_cache . borrow ( ) . get ( self ) {
369- Some ( projection) => projection[ index] as u64 ,
370- None => self . fields . memory_index ( index) as u64 ,
371- } ,
371+ FieldsShape :: Arbitrary { .. } => {
372+ let variant_index = match self . variants {
373+ Variants :: Single { index } => Some ( index) ,
374+ _ => None ,
375+ } ;
376+
377+ // Look up llvm field if indexes do not match memory order due to padding. If
378+ // `field_remapping` is `None` no padding was used and the llvm field index
379+ // matches the memory index.
380+ match cx. type_lowering . borrow ( ) . get ( & ( self . ty , variant_index) ) {
381+ Some ( TypeLowering { field_remapping : Some ( ref prj) , .. } ) => prj[ index] as u64 ,
382+ Some ( _) => self . fields . memory_index ( index) as u64 ,
383+ None => {
384+ bug ! ( "TyAndLayout::llvm_field_index({:?}): type info not found" , self )
385+ }
386+ }
387+ }
372388 }
373389 }
374390
0 commit comments