@@ -8,14 +8,16 @@ use crate::traits::*;
88use crate :: MemFlags ;
99
1010use rustc_hir as hir;
11- use rustc_middle:: mir:: { self , AggregateKind , Operand } ;
11+ use rustc_middle:: mir;
1212use rustc_middle:: ty:: cast:: { CastTy , IntTy } ;
1313use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , TyAndLayout } ;
1414use rustc_middle:: ty:: { self , adjustment:: PointerCoercion , Instance , Ty , TyCtxt } ;
1515use rustc_middle:: { bug, span_bug} ;
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 } ;
19+
20+ use arrayvec:: ArrayVec ;
1921
2022impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > FunctionCx < ' a , ' tcx , Bx > {
2123 #[ instrument( level = "trace" , skip( self , bx) ) ]
@@ -579,7 +581,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
579581 self . codegen_place_to_pointer ( bx, place, mk_ref)
580582 }
581583
582- mir:: Rvalue :: CopyForDeref ( place) => self . codegen_operand ( bx, & Operand :: Copy ( place) ) ,
584+ mir:: Rvalue :: CopyForDeref ( place) => {
585+ self . codegen_operand ( bx, & mir:: Operand :: Copy ( place) )
586+ }
583587 mir:: Rvalue :: AddressOf ( mutability, place) => {
584588 let mk_ptr =
585589 move |tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > | Ty :: new_ptr ( tcx, ty, mutability) ;
@@ -736,11 +740,41 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
736740 _ => bug ! ( "RawPtr operands {data:?} {meta:?}" ) ,
737741 }
738742 }
739- mir:: Rvalue :: Repeat ( ..) | mir:: Rvalue :: Aggregate ( ..) => {
740- // According to `rvalue_creates_operand`, only ZST
741- // aggregate rvalues are allowed to be operands.
743+ mir:: Rvalue :: Repeat ( ..) => bug ! ( "{rvalue:?} in codegen_rvalue_operand" ) ,
744+ mir:: Rvalue :: Aggregate ( _, ref fields) => {
742745 let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
743- OperandRef :: zero_sized ( self . cx . layout_of ( self . monomorphize ( ty) ) )
746+ let ty = self . monomorphize ( ty) ;
747+ let layout = self . cx . layout_of ( ty) ;
748+
749+ // `rvalue_creates_operand` has arranged that we only get here if
750+ // we can build the aggregate immediate from the field immediates.
751+ let mut inputs = ArrayVec :: < Bx :: Value , 2 > :: new ( ) ;
752+ let mut input_scalars = ArrayVec :: < abi:: Scalar , 2 > :: new ( ) ;
753+ for field_idx in layout. fields . index_by_increasing_offset ( ) {
754+ let field_idx = FieldIdx :: from_usize ( field_idx) ;
755+ let op = self . codegen_operand ( bx, & fields[ field_idx] ) ;
756+ let values = op. val . immediates_or_place ( ) . left_or_else ( |p| {
757+ bug ! ( "Field {field_idx:?} is {p:?} making {layout:?}" ) ;
758+ } ) ;
759+ inputs. extend ( values) ;
760+ let scalars = self . value_kind ( op. layout ) . scalars ( ) . unwrap ( ) ;
761+ input_scalars. extend ( scalars) ;
762+ }
763+
764+ let output_scalars = self . value_kind ( layout) . scalars ( ) . unwrap ( ) ;
765+ itertools:: izip!( & mut inputs, input_scalars, output_scalars) . for_each (
766+ |( v, in_s, out_s) | {
767+ if in_s != out_s {
768+ // We have to be really careful about bool here, because
769+ // `(bool,)` stays i1 but `Cell<bool>` becomes i8.
770+ * v = bx. from_immediate ( * v) ;
771+ * v = bx. to_immediate_scalar ( * v, out_s) ;
772+ }
773+ } ,
774+ ) ;
775+
776+ let val = OperandValue :: from_immediates ( inputs) ;
777+ OperandRef { val, layout }
744778 }
745779 mir:: Rvalue :: ShallowInitBox ( ref operand, content_ty) => {
746780 let operand = self . codegen_operand ( bx, operand) ;
@@ -1047,14 +1081,29 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10471081 mir:: Rvalue :: ThreadLocalRef ( _) |
10481082 mir:: Rvalue :: Use ( ..) => // (*)
10491083 true ,
1050- // This always produces a `ty::RawPtr`, so will be Immediate or Pair
1051- mir:: Rvalue :: Aggregate ( box AggregateKind :: RawPtr ( ..) , ..) => true ,
1052- mir:: Rvalue :: Repeat ( ..) |
1053- mir:: Rvalue :: Aggregate ( ..) => {
1084+ // Arrays are always aggregates, so it's not worth checking anything here.
1085+ // (If it's really `[(); N]` or `[T; 0]` and we use the place path, fine.)
1086+ mir:: Rvalue :: Repeat ( ..) => false ,
1087+ mir:: Rvalue :: Aggregate ( ref kind, _) => {
1088+ let allowed_kind = match * * kind {
1089+ // This always produces a `ty::RawPtr`, so will be Immediate or Pair
1090+ mir:: AggregateKind :: RawPtr ( ..) => true ,
1091+ mir:: AggregateKind :: Array ( ..) => false ,
1092+ mir:: AggregateKind :: Tuple => true ,
1093+ mir:: AggregateKind :: Adt ( def_id, ..) => {
1094+ let adt_def = self . cx . tcx ( ) . adt_def ( def_id) ;
1095+ adt_def. is_struct ( ) && !adt_def. repr ( ) . simd ( )
1096+ }
1097+ mir:: AggregateKind :: Closure ( ..) => true ,
1098+ // FIXME: Can we do this for simple coroutines too?
1099+ mir:: AggregateKind :: Coroutine ( ..) | mir:: AggregateKind :: CoroutineClosure ( ..) => false ,
1100+ } ;
1101+ allowed_kind && {
10541102 let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
10551103 let ty = self . monomorphize ( ty) ;
1056- // For ZST this can be `OperandValueKind::ZeroSized`.
1057- self . cx . spanned_layout_of ( ty, span) . is_zst ( )
1104+ let layout = self . cx . spanned_layout_of ( ty, span) ;
1105+ !self . cx . is_backend_ref ( layout)
1106+ }
10581107 }
10591108 }
10601109
@@ -1096,3 +1145,14 @@ enum OperandValueKind {
10961145 Pair ( abi:: Scalar , abi:: Scalar ) ,
10971146 ZeroSized ,
10981147}
1148+
1149+ impl OperandValueKind {
1150+ fn scalars ( self ) -> Option < ArrayVec < abi:: Scalar , 2 > > {
1151+ Some ( match self {
1152+ OperandValueKind :: ZeroSized => ArrayVec :: new ( ) ,
1153+ OperandValueKind :: Immediate ( a) => ArrayVec :: from_iter ( [ a] ) ,
1154+ OperandValueKind :: Pair ( a, b) => [ a, b] . into ( ) ,
1155+ OperandValueKind :: Ref => return None ,
1156+ } )
1157+ }
1158+ }
0 commit comments