@@ -5,11 +5,11 @@ use arrayvec::ArrayVec;
5
5
use either:: Either ;
6
6
use rustc_abi as abi;
7
7
use rustc_abi:: { Align , BackendRepr , Size } ;
8
- use rustc_middle:: bug;
9
8
use rustc_middle:: mir:: interpret:: { Pointer , Scalar , alloc_range} ;
10
9
use rustc_middle:: mir:: { self , ConstValue } ;
11
10
use rustc_middle:: ty:: Ty ;
12
11
use rustc_middle:: ty:: layout:: { LayoutOf , TyAndLayout } ;
12
+ use rustc_middle:: { bug, span_bug} ;
13
13
use tracing:: debug;
14
14
15
15
use super :: place:: { PlaceRef , PlaceValue } ;
@@ -352,79 +352,81 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
352
352
353
353
pub ( crate ) fn extract_field < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
354
354
& self ,
355
+ fx : & mut FunctionCx < ' a , ' tcx , Bx > ,
355
356
bx : & mut Bx ,
356
357
i : usize ,
357
358
) -> Self {
358
359
let field = self . layout . field ( bx. cx ( ) , i) ;
359
360
let offset = self . layout . fields . offset ( i) ;
360
361
361
- let mut val = match ( self . val , self . layout . backend_repr ) {
362
- // If the field is ZST, it has no data.
363
- _ if field. is_zst ( ) => OperandValue :: ZeroSized ,
362
+ let val = if field. size == self . layout . size
363
+ && let Some ( field_val) = fx. codegen_transmute_operand ( bx, * self , field)
364
+ {
365
+ assert_eq ! ( offset. bytes( ) , 0 ) ;
366
+ field_val
367
+ } else if field. is_zst ( ) {
368
+ OperandValue :: ZeroSized
369
+ } else {
370
+ let ( in_scalar, imm) = match ( self . val , self . layout . backend_repr ) {
371
+ // Extract a scalar component from a pair.
372
+ ( OperandValue :: Pair ( a_llval, b_llval) , BackendRepr :: ScalarPair ( a, b) ) => {
373
+ if offset. bytes ( ) == 0 {
374
+ assert_eq ! ( field. size, a. size( bx. cx( ) ) ) ;
375
+ ( Some ( a) , a_llval)
376
+ } else {
377
+ assert_eq ! ( offset, a. size( bx. cx( ) ) . align_to( b. align( bx. cx( ) ) . abi) ) ;
378
+ assert_eq ! ( field. size, b. size( bx. cx( ) ) ) ;
379
+ ( Some ( b) , b_llval)
380
+ }
381
+ }
364
382
365
- // Newtype of a scalar, scalar pair or vector.
366
- ( OperandValue :: Immediate ( _) | OperandValue :: Pair ( ..) , _)
367
- if field. size == self . layout . size =>
368
- {
369
- assert_eq ! ( offset. bytes( ) , 0 ) ;
370
- self . val
371
- }
383
+ // `#[repr(simd)]` types are also immediate.
384
+ ( OperandValue :: Immediate ( llval) , BackendRepr :: Vector { .. } ) => {
385
+ ( None , bx. extract_element ( llval, bx. cx ( ) . const_usize ( i as u64 ) ) )
386
+ }
372
387
373
- // Extract a scalar component from a pair.
374
- ( OperandValue :: Pair ( a_llval, b_llval) , BackendRepr :: ScalarPair ( a, b) ) => {
375
- if offset. bytes ( ) == 0 {
376
- assert_eq ! ( field. size, a. size( bx. cx( ) ) ) ;
377
- OperandValue :: Immediate ( a_llval)
378
- } else {
379
- assert_eq ! ( offset, a. size( bx. cx( ) ) . align_to( b. align( bx. cx( ) ) . abi) ) ;
380
- assert_eq ! ( field. size, b. size( bx. cx( ) ) ) ;
381
- OperandValue :: Immediate ( b_llval)
388
+ _ => {
389
+ span_bug ! ( fx. mir. span, "OperandRef::extract_field({:?}): not applicable" , self )
382
390
}
383
- }
391
+ } ;
392
+ OperandValue :: Immediate ( match field. backend_repr {
393
+ BackendRepr :: Vector { .. } => imm,
394
+ BackendRepr :: Scalar ( out_scalar) => {
395
+ let Some ( in_scalar) = in_scalar else {
396
+ span_bug ! (
397
+ fx. mir. span,
398
+ "OperandRef::extract_field({:?}): missing input scalar for output scalar" ,
399
+ self
400
+ )
401
+ } ;
402
+ if in_scalar != out_scalar {
403
+ // If the backend and backend_immediate types might differ,
404
+ // flip back to the backend type then to the new immediate.
405
+ // This avoids nop truncations, but still handles things like
406
+ // Bools in union fields needs to be truncated.
407
+ let backend = bx. from_immediate ( imm) ;
408
+ bx. to_immediate_scalar ( backend, out_scalar)
409
+ } else {
410
+ imm
411
+ }
412
+ }
413
+ // Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]);
414
+ BackendRepr :: Memory { sized : true } => {
415
+ assert_matches ! ( self . layout. backend_repr, BackendRepr :: Vector { .. } ) ;
384
416
385
- // `#[repr(simd)]` types are also immediate.
386
- ( OperandValue :: Immediate ( llval) , BackendRepr :: Vector { .. } ) => {
387
- OperandValue :: Immediate ( bx. extract_element ( llval, bx. cx ( ) . const_usize ( i as u64 ) ) )
388
- }
417
+ let llfield_ty = bx. cx ( ) . backend_type ( field) ;
389
418
390
- _ => bug ! ( "OperandRef::extract_field({:?}): not applicable" , self ) ,
419
+ // Can't bitcast an aggregate, so round trip through memory.
420
+ let llptr = bx. alloca ( field. size , field. align . abi ) ;
421
+ bx. store ( imm, llptr, field. align . abi ) ;
422
+ bx. load ( llfield_ty, llptr, field. align . abi )
423
+ }
424
+ BackendRepr :: Uninhabited
425
+ | BackendRepr :: ScalarPair ( _, _)
426
+ | BackendRepr :: Memory { sized : false } => bug ! ( ) ,
427
+ } )
391
428
} ;
392
429
393
- match ( & mut val, field. backend_repr ) {
394
- ( OperandValue :: ZeroSized , _) => { }
395
- (
396
- OperandValue :: Immediate ( llval) ,
397
- BackendRepr :: Scalar ( _) | BackendRepr :: ScalarPair ( ..) | BackendRepr :: Vector { .. } ,
398
- ) => {
399
- // Bools in union fields needs to be truncated.
400
- * llval = bx. to_immediate ( * llval, field) ;
401
- }
402
- ( OperandValue :: Pair ( a, b) , BackendRepr :: ScalarPair ( a_abi, b_abi) ) => {
403
- // Bools in union fields needs to be truncated.
404
- * a = bx. to_immediate_scalar ( * a, a_abi) ;
405
- * b = bx. to_immediate_scalar ( * b, b_abi) ;
406
- }
407
- // Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]);
408
- ( OperandValue :: Immediate ( llval) , BackendRepr :: Memory { sized : true } ) => {
409
- assert_matches ! ( self . layout. backend_repr, BackendRepr :: Vector { .. } ) ;
410
-
411
- let llfield_ty = bx. cx ( ) . backend_type ( field) ;
412
-
413
- // Can't bitcast an aggregate, so round trip through memory.
414
- let llptr = bx. alloca ( field. size , field. align . abi ) ;
415
- bx. store ( * llval, llptr, field. align . abi ) ;
416
- * llval = bx. load ( llfield_ty, llptr, field. align . abi ) ;
417
- }
418
- (
419
- OperandValue :: Immediate ( _) ,
420
- BackendRepr :: Uninhabited | BackendRepr :: Memory { sized : false } ,
421
- ) => {
422
- bug ! ( )
423
- }
424
- ( OperandValue :: Pair ( ..) , _) => bug ! ( ) ,
425
- ( OperandValue :: Ref ( ..) , _) => bug ! ( ) ,
426
- }
427
-
428
430
OperandRef { val, layout : field }
429
431
}
430
432
}
@@ -587,7 +589,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
587
589
"Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \
588
590
but tried to access field {f:?} of pointer {o:?}",
589
591
) ;
590
- o = o. extract_field ( bx, f. index ( ) ) ;
592
+ o = o. extract_field ( self , bx, f. index ( ) ) ;
591
593
}
592
594
mir:: ProjectionElem :: Index ( _)
593
595
| mir:: ProjectionElem :: ConstantIndex { .. } => {
0 commit comments