@@ -15,7 +15,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
15
15
use rustc_middle:: ty:: { self , adjustment:: PointerCoercion , Instance , Ty , TyCtxt } ;
16
16
use rustc_session:: config:: OptLevel ;
17
17
use rustc_span:: { Span , DUMMY_SP } ;
18
- use rustc_target:: abi:: { self , FIRST_VARIANT } ;
18
+ use rustc_target:: abi:: { self , FieldIdx , FIRST_VARIANT } ;
19
19
20
20
impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > FunctionCx < ' a , ' tcx , Bx > {
21
21
#[ instrument( level = "trace" , skip( self , bx) ) ]
@@ -720,12 +720,47 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
720
720
OperandRef { val : OperandValue :: Immediate ( static_) , layout }
721
721
}
722
722
mir:: Rvalue :: Use ( ref operand) => self . codegen_operand ( bx, operand) ,
723
- mir:: Rvalue :: Repeat ( ..) | mir :: Rvalue :: Aggregate ( .. ) => {
723
+ mir:: Rvalue :: Repeat ( ..) => {
724
724
// According to `rvalue_creates_operand`, only ZST
725
- // aggregate rvalues are allowed to be operands.
725
+ // repat rvalues are allowed to be operands.
726
726
let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
727
727
OperandRef :: zero_sized ( self . cx . layout_of ( self . monomorphize ( ty) ) )
728
728
}
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
+ }
729
764
mir:: Rvalue :: ShallowInitBox ( ref operand, content_ty) => {
730
765
let operand = self . codegen_operand ( bx, operand) ;
731
766
let val = operand. immediate ( ) ;
@@ -1032,12 +1067,37 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1032
1067
mir:: Rvalue :: ThreadLocalRef ( _) |
1033
1068
mir:: Rvalue :: Use ( ..) => // (*)
1034
1069
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) => {
1037
1077
let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
1038
1078
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
+ }
1041
1101
}
1042
1102
}
1043
1103
0 commit comments