@@ -779,16 +779,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
779779 }
780780 mir:: Rvalue :: Use ( ref operand) => self . codegen_operand ( bx, operand) ,
781781 mir:: Rvalue :: Repeat ( ..) => bug ! ( "{rvalue:?} in codegen_rvalue_operand" ) ,
782- mir:: Rvalue :: Aggregate ( _ , ref fields) => {
782+ mir:: Rvalue :: Aggregate ( ref kind , ref fields) => {
783783 let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
784784 let ty = self . monomorphize ( ty) ;
785785 let layout = self . cx . layout_of ( ty) ;
786786
787+ let variant_idx = match * * kind {
788+ mir:: AggregateKind :: Adt ( _, vi, _, _, None ) => vi,
789+ mir:: AggregateKind :: RawPtr ( ..)
790+ | mir:: AggregateKind :: Closure ( ..)
791+ | mir:: AggregateKind :: Tuple => FIRST_VARIANT ,
792+ _ => bug ! ( "{rvalue:?} in codegen_rvalue_operand" ) ,
793+ } ;
794+ let variant_layout = layout. for_variant ( self . cx , variant_idx) ;
795+
787796 // `rvalue_creates_operand` has arranged that we only get here if
788797 // we can build the aggregate immediate from the field immediates.
789798 let mut inputs = ArrayVec :: < Bx :: Value , 2 > :: new ( ) ;
790799 let mut input_scalars = ArrayVec :: < abi:: Scalar , 2 > :: new ( ) ;
791- for field_idx in layout . fields . index_by_increasing_offset ( ) {
800+ for field_idx in variant_layout . fields . index_by_increasing_offset ( ) {
792801 let field_idx = FieldIdx :: from_usize ( field_idx) ;
793802 let op = self . codegen_operand ( bx, & fields[ field_idx] ) ;
794803 let values = op. val . immediates_or_place ( ) . left_or_else ( |p| {
@@ -801,12 +810,66 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
801810 }
802811
803812 let output_scalars = self . value_kind ( layout) . scalars ( ) . unwrap ( ) ;
813+ match layout. variants {
814+ abi:: Variants :: Empty => bug ! ( ) ,
815+ abi:: Variants :: Single { index } => assert_eq ! ( index, variant_idx) ,
816+ abi:: Variants :: Multiple { tag, ref tag_encoding, tag_field, .. } => {
817+ match * tag_encoding {
818+ abi:: TagEncoding :: Direct => {
819+ assert_eq ! ( layout. fields. offset( tag_field) , abi:: Size :: ZERO ) ;
820+
821+ let discr = ty
822+ . discriminant_for_variant ( self . cx . tcx ( ) , variant_idx)
823+ . unwrap ( ) ;
824+ let discr_layout = bx. cx ( ) . layout_of ( discr. ty ) ;
825+ let discr_ibty = self . cx . immediate_backend_type ( discr_layout) ;
826+ let discr_const = self . cx . const_uint_big ( discr_ibty, discr. val ) ;
827+
828+ let tag_layout = layout. field ( self . cx , tag_field) ;
829+ let tag_ibty = self . cx . immediate_backend_type ( tag_layout) ;
830+ let tag_const = bx. intcast ( discr_const, tag_ibty, tag. is_signed ( ) ) ;
831+
832+ inputs. insert ( 0 , tag_const) ;
833+ input_scalars. insert ( 0 , tag) ;
834+
835+ // If this variant has fewer payloads, add the extra `undef`s.
836+ if input_scalars. len ( ) != output_scalars. len ( ) {
837+ // Since we just inserted a tag, this can only happen
838+ // if we're missing the second thing in a pair.
839+ assert_eq ! ( input_scalars. len( ) , 1 ) ;
840+ assert_eq ! ( output_scalars. len( ) , 2 ) ;
841+
842+ let ibty =
843+ self . cx . scalar_pair_element_backend_type ( layout, 1 , true ) ;
844+ let undef = self . cx . const_undef ( ibty) ;
845+ inputs. push ( undef) ;
846+ input_scalars. push ( output_scalars[ 1 ] ) ;
847+ }
848+ }
849+ abi:: TagEncoding :: Niche { untagged_variant, .. } => {
850+ // For now we only handle variants where the niche is automatic,
851+ // but catch it if `rvalue_creates_operand` changes.
852+ assert_eq ! ( untagged_variant, variant_idx) ;
853+ }
854+ }
855+ }
856+ }
857+
804858 itertools:: izip!( & mut inputs, input_scalars, output_scalars) . for_each (
805859 |( v, in_s, out_s) | {
806860 if in_s != out_s {
807861 // We have to be really careful about bool here, because
808862 // `(bool,)` stays i1 but `Cell<bool>` becomes i8.
809863 * v = bx. from_immediate ( * v) ;
864+
865+ // Also we might be storing `usize` into a pointer field,
866+ // in which case we have to `without_provenance` it.
867+ if let abi:: Primitive :: Int ( ..) = in_s. primitive ( )
868+ && let abi:: Primitive :: Pointer ( ..) = out_s. primitive ( )
869+ {
870+ * v = bx. ptradd ( bx. const_null ( bx. type_ptr ( ) ) , * v) ;
871+ }
872+
810873 * v = bx. to_immediate_scalar ( * v, out_s) ;
811874 }
812875 } ,
@@ -1146,14 +1209,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11461209 // (If it's really `[(); N]` or `[T; 0]` and we use the place path, fine.)
11471210 mir:: Rvalue :: Repeat ( ..) => false ,
11481211 mir:: Rvalue :: Aggregate ( ref kind, _) => {
1212+ let mut variant_idx = None ;
11491213 let allowed_kind = match * * kind {
11501214 // This always produces a `ty::RawPtr`, so will be Immediate or Pair
11511215 mir:: AggregateKind :: RawPtr ( ..) => true ,
11521216 mir:: AggregateKind :: Array ( ..) => false ,
11531217 mir:: AggregateKind :: Tuple => true ,
1154- mir:: AggregateKind :: Adt ( def_id, ..) => {
1218+ mir:: AggregateKind :: Adt ( def_id, vidx, ..) => {
1219+ variant_idx = Some ( vidx) ;
11551220 let adt_def = self . cx . tcx ( ) . adt_def ( def_id) ;
1156- adt_def. is_struct ( ) && !adt_def. repr ( ) . simd ( )
1221+ ( adt_def. is_struct ( ) || adt_def. is_enum ( ) )
1222+ && !adt_def. repr ( ) . simd ( )
11571223 }
11581224 mir:: AggregateKind :: Closure ( ..) => true ,
11591225 // FIXME: Can we do this for simple coroutines too?
@@ -1163,7 +1229,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11631229 let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
11641230 let ty = self . monomorphize ( ty) ;
11651231 let layout = self . cx . spanned_layout_of ( ty, span) ;
1166- !self . cx . is_backend_ref ( layout)
1232+
1233+ variant_idx. is_none_or ( |v| !layout. for_variant ( self . cx , v) . uninhabited )
1234+ && !self . cx . is_backend_ref ( layout)
1235+ && match & layout. variants {
1236+ abi:: Variants :: Empty => bug ! ( ) ,
1237+ abi:: Variants :: Single { .. } => true ,
1238+ abi:: Variants :: Multiple { tag_encoding, ..} => match * tag_encoding {
1239+ abi:: TagEncoding :: Direct => true ,
1240+ abi:: TagEncoding :: Niche { untagged_variant, ..} => Some ( untagged_variant) == variant_idx,
1241+ }
1242+ }
11671243 }
11681244 }
11691245 }
0 commit comments