@@ -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,44 @@ 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_idx, _) = layout
748+ . non_1zst_field ( self . cx )
749+ . expect ( "only transparent non-ZST structs should get here" ) ;
750+ let field = self . codegen_operand ( bx, & fields[ field_idx] ) ;
751+ // While the size is the same, since the struct is transparent,
752+ // calling transmute here handles the `i1`-vs-`i8` issues for `bool`.
753+ let Some ( val) = self . codegen_transmute_operand ( bx, field, layout) else {
754+ bug ! ( "Couldn't transmute {field:?} to {layout:?}" ) ;
755+ } ;
756+ OperandRef { val, layout }
757+ }
758+ _ => bug ! ( "Unexpected in codegen_rvalue_operand: {rvalue:?}" ) ,
759+ }
760+ }
729761 mir:: Rvalue :: ShallowInitBox ( ref operand, content_ty) => {
730762 let operand = self . codegen_operand ( bx, operand) ;
731763 let val = operand. immediate ( ) ;
@@ -1032,12 +1064,37 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10321064 mir:: Rvalue :: ThreadLocalRef ( _) |
10331065 mir:: Rvalue :: Use ( ..) => // (*)
10341066 true ,
1035- mir:: Rvalue :: Repeat ( ..) |
1036- mir:: Rvalue :: Aggregate ( ..) => {
1067+ mir:: Rvalue :: Repeat ( ..) => {
10371068 let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
10381069 let ty = self . monomorphize ( ty) ;
1039- // For ZST this can be `OperandValueKind::ZeroSized`.
1040- self . cx . spanned_layout_of ( ty, span) . is_zst ( )
1070+ let layout = self . cx . spanned_layout_of ( ty, span) ;
1071+ layout. is_zst ( )
1072+ }
1073+ mir:: Rvalue :: Aggregate ( ref kind, ref fields) => {
1074+ let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
1075+ let ty = self . monomorphize ( ty) ;
1076+ let layout = self . cx . spanned_layout_of ( ty, span) ;
1077+ match * * kind {
1078+ // OperandValue::ZeroSized is easy
1079+ _ if layout. is_zst ( ) => true ,
1080+ // 2-Tuple of scalars is an easy scalar pair
1081+ 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+ } )
1090+ }
1091+ // If a non-union is transparent, we can pass it along
1092+ mir:: AggregateKind :: Adt ( _, _, _, _, None ) => {
1093+ ty. ty_adt_def ( ) . is_some_and ( |def| def. repr ( ) . transparent ( ) )
1094+ && !self . cx . is_backend_ref ( layout)
1095+ }
1096+ _ => false ,
1097+ }
10411098 }
10421099 }
10431100
0 commit comments