@@ -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,44 @@ 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+ immediates. try_push ( v) . unwrap_or_else ( |_| {
746+ bug ! ( "Too many immediates at {field_idx:?} in {layout:?}" )
747+ } )
748+ } ;
749+
750+ let op = self . codegen_operand ( bx, field) ;
751+ match op. val {
752+ OperandValue :: ZeroSized => { }
753+ OperandValue :: Immediate ( v) => push ( v) ,
754+ OperandValue :: Pair ( v, w) => {
755+ push ( v) ;
756+ push ( w) ;
757+ }
758+ OperandValue :: Ref ( _) => {
759+ bug ! ( "reference operand for field {field_idx:?} in {layout:?}" )
760+ }
761+ }
762+ }
763+ let [ a, b] = immediates. into_inner ( ) . unwrap ( ) ;
764+ let val = OperandValue :: Pair ( a, b) ;
744765 OperandRef { val, layout }
745766 }
746767 mir:: AggregateKind :: Adt ( ..) => {
@@ -1070,23 +1091,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10701091 let layout = self . cx . spanned_layout_of ( ty, span) ;
10711092 layout. is_zst ( )
10721093 }
1073- mir:: Rvalue :: Aggregate ( ref kind, ref fields ) => {
1094+ mir:: Rvalue :: Aggregate ( ref kind, _ ) => {
10741095 let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
10751096 let ty = self . monomorphize ( ty) ;
10761097 let layout = self . cx . spanned_layout_of ( ty, span) ;
10771098 match * * kind {
10781099 // OperandValue::ZeroSized is easy
10791100 _ if layout. is_zst ( ) => true ,
1080- // 2-Tuple of scalars is an easy scalar pair
1101+ // If a tuple is a scalar pair, we can grab the immediates from the operands
10811102 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- } )
1103+ self . cx . is_backend_scalar_pair ( layout)
10901104 }
10911105 // If a non-union is transparent, we can pass it along
10921106 mir:: AggregateKind :: Adt ( _, _, _, _, None ) => {
0 commit comments