@@ -15,7 +15,9 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
1515use rustc_middle:: ty:: { self , adjustment:: PointerCoercion , Instance , Ty , TyCtxt } ;
1616use rustc_session:: config:: OptLevel ;
1717use rustc_span:: { Span , DUMMY_SP } ;
18- use rustc_target:: abi:: { self , FieldIdx , FIRST_VARIANT } ;
18+ use rustc_target:: abi:: { self , FIRST_VARIANT } ;
19+
20+ use arrayvec:: ArrayVec ;
1921
2022impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > FunctionCx < ' a , ' tcx , Bx > {
2123 #[ instrument( level = "trace" , skip( self , bx) ) ]
@@ -722,25 +724,41 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
722724 mir:: Rvalue :: Use ( ref operand) => self . codegen_operand ( bx, operand) ,
723725 mir:: Rvalue :: Repeat ( ..) => {
724726 // According to `rvalue_creates_operand`, only ZST
725- // repat rvalues are allowed to be operands.
727+ // repeat rvalues are allowed to be operands.
726728 let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
727729 OperandRef :: zero_sized ( self . cx . layout_of ( self . monomorphize ( ty) ) )
728730 }
729731 mir:: Rvalue :: Aggregate ( ref kind, ref fields) => {
730732 let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
731733 let ty = self . monomorphize ( ty) ;
732- let layout = self . cx . layout_of ( self . monomorphize ( ty ) ) ;
734+ let layout = self . cx . layout_of ( ty ) ;
733735 match * * kind {
734736 _ if layout. is_zst ( ) => OperandRef :: zero_sized ( layout) ,
735737 mir:: AggregateKind :: Tuple => {
736- debug_assert_eq ! (
737- fields. len( ) ,
738- 2 ,
739- "We should only get pairs, but got {rvalue:?}"
738+ debug_assert ! (
739+ self . cx. is_backend_scalar_pair( layout) ,
740+ "Expected a scalar pair, but this isn't: {layout:?}" ,
740741 ) ;
741- let a = self . codegen_operand ( bx, & fields[ FieldIdx :: ZERO ] ) ;
742- let b = self . codegen_operand ( bx, & fields[ FieldIdx :: from_u32 ( 1 ) ] ) ;
743- let val = OperandValue :: Pair ( a. immediate ( ) , b. immediate ( ) ) ;
742+ let mut immediates = ArrayVec :: < Bx :: Value , 2 > :: new ( ) ;
743+ for ( field_idx, field) in fields. iter_enumerated ( ) {
744+ let mut push = |v| {
745+ let Ok ( ( ) ) = immediates. try_push ( v) else {
746+ bug ! ( "Already had 2 immediates when pushing {field_idx:?} in {layout:?}" ) ;
747+ } ;
748+ } ;
749+ let op = self . codegen_operand ( bx, field) ;
750+ match op. val {
751+ OperandValue :: ZeroSized => { } ,
752+ OperandValue :: Immediate ( v) => push ( v) ,
753+ OperandValue :: Pair ( v, w) => {
754+ push ( v) ;
755+ push ( w) ;
756+ }
757+ OperandValue :: Ref ( _) => bug ! ( "reference operand for field {field_idx:?} in {layout:?}" ) ,
758+ }
759+ }
760+ let [ a, b] = immediates. into_inner ( ) . unwrap ( ) ;
761+ let val = OperandValue :: Pair ( a, b) ;
744762 OperandRef { val, layout }
745763 }
746764 mir:: AggregateKind :: Adt ( ..) => {
@@ -1070,23 +1088,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10701088 let layout = self . cx . spanned_layout_of ( ty, span) ;
10711089 layout. is_zst ( )
10721090 }
1073- mir:: Rvalue :: Aggregate ( ref kind, ref fields ) => {
1091+ mir:: Rvalue :: Aggregate ( ref kind, _ ) => {
10741092 let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
10751093 let ty = self . monomorphize ( ty) ;
10761094 let layout = self . cx . spanned_layout_of ( ty, span) ;
10771095 match * * kind {
10781096 // OperandValue::ZeroSized is easy
10791097 _ if layout. is_zst ( ) => true ,
1080- // 2-Tuple of scalars is an easy scalar pair
1098+ // If a tuple is a scalar pair, we can grab the immediates from the operands
10811099 mir:: AggregateKind :: Tuple => {
1082- fields. len ( ) == 2
1083- && self . cx . is_backend_scalar_pair ( layout)
1084- && fields. iter ( ) . all ( |field| {
1085- let field_ty = field. ty ( self . mir , self . cx . tcx ( ) ) ;
1086- let field_ty = self . monomorphize ( field_ty) ;
1087- let field_layout = self . cx . spanned_layout_of ( field_ty, span) ;
1088- self . cx . is_backend_immediate ( field_layout)
1089- } )
1100+ self . cx . is_backend_scalar_pair ( layout)
10901101 }
10911102 // If a non-union is transparent, we can pass it along
10921103 mir:: AggregateKind :: Adt ( _, _, _, _, None ) => {
0 commit comments