@@ -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,44 @@ 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_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
+ }
729
761
mir:: Rvalue :: ShallowInitBox ( ref operand, content_ty) => {
730
762
let operand = self . codegen_operand ( bx, operand) ;
731
763
let val = operand. immediate ( ) ;
@@ -1032,12 +1064,37 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1032
1064
mir:: Rvalue :: ThreadLocalRef ( _) |
1033
1065
mir:: Rvalue :: Use ( ..) => // (*)
1034
1066
true ,
1035
- mir:: Rvalue :: Repeat ( ..) |
1036
- mir:: Rvalue :: Aggregate ( ..) => {
1067
+ mir:: Rvalue :: Repeat ( ..) => {
1037
1068
let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
1038
1069
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
+ }
1041
1098
}
1042
1099
}
1043
1100
0 commit comments