@@ -5,11 +5,11 @@ use arrayvec::ArrayVec;
55use  either:: Either ; 
66use  rustc_abi as  abi; 
77use  rustc_abi:: { Align ,  BackendRepr ,  Size } ; 
8- use  rustc_middle:: bug; 
98use  rustc_middle:: mir:: interpret:: { Pointer ,  Scalar ,  alloc_range} ; 
109use  rustc_middle:: mir:: { self ,  ConstValue } ; 
1110use  rustc_middle:: ty:: Ty ; 
1211use  rustc_middle:: ty:: layout:: { LayoutOf ,  TyAndLayout } ; 
12+ use  rustc_middle:: { bug,  span_bug} ; 
1313use  tracing:: debug; 
1414
1515use  super :: place:: { PlaceRef ,  PlaceValue } ; 
@@ -352,79 +352,81 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
352352
353353    pub ( crate )  fn  extract_field < Bx :  BuilderMethods < ' a ,  ' tcx ,  Value  = V > > ( 
354354        & self , 
355+         fx :  & mut  FunctionCx < ' a ,  ' tcx ,  Bx > , 
355356        bx :  & mut  Bx , 
356357        i :  usize , 
357358    )  -> Self  { 
358359        let  field = self . layout . field ( bx. cx ( ) ,  i) ; 
359360        let  offset = self . layout . fields . offset ( i) ; 
360361
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+                 } 
364382
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+                 } 
372387
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 ) 
382390                } 
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  {  .. } ) ; 
384416
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) ; 
389418
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+             } ) 
391428        } ; 
392429
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- 
428430        OperandRef  {  val,  layout :  field } 
429431    } 
430432} 
@@ -587,7 +589,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
587589                                "Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \  
588590, 
589591                            ) ; 
590-                             o = o. extract_field ( bx,  f. index ( ) ) ; 
592+                             o = o. extract_field ( self ,   bx,  f. index ( ) ) ; 
591593                        } 
592594                        mir:: ProjectionElem :: Index ( _) 
593595                        | mir:: ProjectionElem :: ConstantIndex  {  .. }  => { 
0 commit comments