1
1
use crate :: abi:: FnAbi ;
2
2
use crate :: common:: * ;
3
+ use crate :: context:: TypeLowering ;
3
4
use crate :: type_:: Type ;
4
5
use rustc_codegen_ssa:: traits:: * ;
5
6
use rustc_middle:: bug;
@@ -17,6 +18,7 @@ fn uncached_llvm_type<'a, 'tcx>(
17
18
cx : & CodegenCx < ' a , ' tcx > ,
18
19
layout : TyAndLayout < ' tcx > ,
19
20
defer : & mut Option < ( & ' a Type , TyAndLayout < ' tcx > ) > ,
21
+ field_remapping : & mut Option < Box < [ u32 ] > > ,
20
22
) -> & ' a Type {
21
23
match layout. abi {
22
24
Abi :: Scalar ( _) => bug ! ( "handled elsewhere" ) ,
@@ -75,7 +77,8 @@ fn uncached_llvm_type<'a, 'tcx>(
75
77
FieldsShape :: Array { count, .. } => cx. type_array ( layout. field ( cx, 0 ) . llvm_type ( cx) , count) ,
76
78
FieldsShape :: Arbitrary { .. } => match name {
77
79
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;
79
82
cx. type_struct ( & llfields, packed)
80
83
}
81
84
Some ( ref name) => {
@@ -90,7 +93,7 @@ fn uncached_llvm_type<'a, 'tcx>(
90
93
fn struct_llfields < ' a , ' tcx > (
91
94
cx : & CodegenCx < ' a , ' tcx > ,
92
95
layout : TyAndLayout < ' tcx > ,
93
- ) -> ( Vec < & ' a Type > , bool ) {
96
+ ) -> ( Vec < & ' a Type > , bool , Option < Box < [ u32 ] > > ) {
94
97
debug ! ( "struct_llfields: {:#?}" , layout) ;
95
98
let field_count = layout. fields . count ( ) ;
96
99
@@ -147,11 +150,8 @@ fn struct_llfields<'a, 'tcx>(
147
150
} else {
148
151
debug ! ( "struct_llfields: offset: {:?} stride: {:?}" , offset, layout. size) ;
149
152
}
150
- if padding_used {
151
- cx. field_projection_cache . borrow_mut ( ) . insert ( layout, projection) ;
152
- }
153
153
154
- ( result, packed)
154
+ ( result, packed, padding_used . then_some ( projection . into_boxed_slice ( ) ) )
155
155
}
156
156
157
157
impl < ' a , ' tcx > CodegenCx < ' a , ' tcx > {
@@ -243,8 +243,8 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
243
243
Variants :: Single { index } => Some ( index) ,
244
244
_ => None ,
245
245
} ;
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 ;
248
248
}
249
249
250
250
debug ! ( "llvm_type({:#?})" , self ) ;
@@ -256,24 +256,29 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
256
256
let normal_ty = cx. tcx . erase_regions ( self . ty ) ;
257
257
258
258
let mut defer = None ;
259
+ let mut field_remapping = None ;
259
260
let llty = if self . ty != normal_ty {
260
261
let mut layout = cx. layout_of ( normal_ty) ;
261
262
if let Some ( v) = variant_index {
262
263
layout = layout. for_variant ( cx, v) ;
263
264
}
264
265
layout. llvm_type ( cx)
265
266
} else {
266
- uncached_llvm_type ( cx, * self , & mut defer)
267
+ uncached_llvm_type ( cx, * self , & mut defer, & mut field_remapping )
267
268
} ;
268
269
debug ! ( "--> mapped {:#?} to llty={:?}" , self , llty) ;
269
270
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 } ) ;
271
274
272
275
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;
275
279
}
276
-
280
+ cx. type_lowering . borrow_mut ( ) . get_mut ( & ( self . ty , variant_index) ) . unwrap ( ) . field_remapping =
281
+ field_remapping;
277
282
llty
278
283
}
279
284
@@ -363,12 +368,23 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
363
368
364
369
FieldsShape :: Array { .. } => index as u64 ,
365
370
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
+ }
372
388
}
373
389
}
374
390
0 commit comments