@@ -15,7 +15,7 @@ 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 , FIRST_VARIANT } ;
18+ use rustc_target:: abi:: { self , FieldIdx , FIRST_VARIANT } ;
1919
2020impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > FunctionCx < ' a , ' tcx , Bx > {
2121 #[ instrument( level = "trace" , skip( self , bx) ) ]
@@ -720,12 +720,47 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
720720 OperandRef { val : OperandValue :: Immediate ( static_) , layout }
721721 }
722722 mir:: Rvalue :: Use ( ref operand) => self . codegen_operand ( bx, operand) ,
723- mir:: Rvalue :: Repeat ( ..) | mir :: Rvalue :: Aggregate ( .. ) => {
723+ mir:: Rvalue :: Repeat ( ..) => {
724724 // According to `rvalue_creates_operand`, only ZST
725- // aggregate rvalues are allowed to be operands.
725+ // repat rvalues are allowed to be operands.
726726 let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
727727 OperandRef :: zero_sized ( self . cx . layout_of ( self . monomorphize ( ty) ) )
728728 }
729+ mir:: Rvalue :: Aggregate ( ref kind, ref fields) => {
730+ let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
731+ let ty = self . monomorphize ( ty) ;
732+ let layout = self . cx . layout_of ( self . monomorphize ( ty) ) ;
733+ match * * kind {
734+ _ if layout. is_zst ( ) => OperandRef :: zero_sized ( layout) ,
735+ mir:: AggregateKind :: Tuple => {
736+ debug_assert_eq ! (
737+ fields. len( ) ,
738+ 2 ,
739+ "We should only get pairs, but got {rvalue:?}"
740+ ) ;
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 ( ) ) ;
744+ OperandRef { val, layout }
745+ }
746+ mir:: AggregateKind :: Adt ( ..) => {
747+ let ( field, _) = layout
748+ . non_1zst_field ( self . cx )
749+ . expect ( "only transparent non-ZST structs should get here" ) ;
750+ let val = match self . codegen_operand ( bx, & fields[ field] ) . val {
751+ OperandValue :: Immediate ( a) => {
752+ OperandValue :: Immediate ( bx. from_immediate ( a) )
753+ }
754+ OperandValue :: Pair ( a, b) => {
755+ OperandValue :: Pair ( bx. from_immediate ( a) , bx. from_immediate ( b) )
756+ }
757+ other => bug ! ( "Unexpected operand {other:?}" ) ,
758+ } ;
759+ OperandRef { val, layout }
760+ }
761+ _ => bug ! ( "Unexpected in codegen_rvalue_operand: {rvalue:?}" ) ,
762+ }
763+ }
729764 mir:: Rvalue :: ShallowInitBox ( ref operand, content_ty) => {
730765 let operand = self . codegen_operand ( bx, operand) ;
731766 let val = operand. immediate ( ) ;
@@ -1032,12 +1067,37 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10321067 mir:: Rvalue :: ThreadLocalRef ( _) |
10331068 mir:: Rvalue :: Use ( ..) => // (*)
10341069 true ,
1035- mir:: Rvalue :: Repeat ( ..) |
1036- mir:: Rvalue :: Aggregate ( ..) => {
1070+ mir:: Rvalue :: Repeat ( ..) => {
1071+ let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
1072+ let ty = self . monomorphize ( ty) ;
1073+ let layout = self . cx . spanned_layout_of ( ty, span) ;
1074+ layout. is_zst ( )
1075+ }
1076+ mir:: Rvalue :: Aggregate ( ref kind, ref fields) => {
10371077 let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
10381078 let ty = self . monomorphize ( ty) ;
1039- // For ZST this can be `OperandValueKind::ZeroSized`.
1040- self . cx . spanned_layout_of ( ty, span) . is_zst ( )
1079+ let layout = self . cx . spanned_layout_of ( ty, span) ;
1080+ match * * kind {
1081+ // OperandValue::ZeroSized is easy
1082+ _ if layout. is_zst ( ) => true ,
1083+ // 2-Tuple of scalars is an easy scalar pair
1084+ mir:: AggregateKind :: Tuple => {
1085+ fields. len ( ) == 2
1086+ && self . cx . is_backend_scalar_pair ( layout)
1087+ && fields. iter ( ) . all ( |field| {
1088+ let field_ty = field. ty ( self . mir , self . cx . tcx ( ) ) ;
1089+ let field_ty = self . monomorphize ( field_ty) ;
1090+ let field_layout = self . cx . spanned_layout_of ( field_ty, span) ;
1091+ self . cx . is_backend_immediate ( field_layout)
1092+ } )
1093+ }
1094+ // If a non-union is transparent, we can pass it along
1095+ mir:: AggregateKind :: Adt ( _, _, _, _, None ) => {
1096+ ty. ty_adt_def ( ) . is_some_and ( |def| def. repr ( ) . transparent ( ) )
1097+ && !self . cx . is_backend_ref ( layout)
1098+ }
1099+ _ => false ,
1100+ }
10411101 }
10421102 }
10431103
0 commit comments