@@ -779,16 +779,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
779
779
}
780
780
mir:: Rvalue :: Use ( ref operand) => self . codegen_operand ( bx, operand) ,
781
781
mir:: Rvalue :: Repeat ( ..) => bug ! ( "{rvalue:?} in codegen_rvalue_operand" ) ,
782
- mir:: Rvalue :: Aggregate ( _ , ref fields) => {
782
+ mir:: Rvalue :: Aggregate ( ref kind , ref fields) => {
783
783
let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
784
784
let ty = self . monomorphize ( ty) ;
785
785
let layout = self . cx . layout_of ( ty) ;
786
786
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
+
787
796
// `rvalue_creates_operand` has arranged that we only get here if
788
797
// we can build the aggregate immediate from the field immediates.
789
798
let mut inputs = ArrayVec :: < Bx :: Value , 2 > :: new ( ) ;
790
799
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 ( ) {
792
801
let field_idx = FieldIdx :: from_usize ( field_idx) ;
793
802
let op = self . codegen_operand ( bx, & fields[ field_idx] ) ;
794
803
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> {
801
810
}
802
811
803
812
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
+
804
858
itertools:: izip!( & mut inputs, input_scalars, output_scalars) . for_each (
805
859
|( v, in_s, out_s) | {
806
860
if in_s != out_s {
807
861
// We have to be really careful about bool here, because
808
862
// `(bool,)` stays i1 but `Cell<bool>` becomes i8.
809
863
* 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
+
810
873
* v = bx. to_immediate_scalar ( * v, out_s) ;
811
874
}
812
875
} ,
@@ -1146,14 +1209,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1146
1209
// (If it's really `[(); N]` or `[T; 0]` and we use the place path, fine.)
1147
1210
mir:: Rvalue :: Repeat ( ..) => false ,
1148
1211
mir:: Rvalue :: Aggregate ( ref kind, _) => {
1212
+ let mut variant_idx = None ;
1149
1213
let allowed_kind = match * * kind {
1150
1214
// This always produces a `ty::RawPtr`, so will be Immediate or Pair
1151
1215
mir:: AggregateKind :: RawPtr ( ..) => true ,
1152
1216
mir:: AggregateKind :: Array ( ..) => false ,
1153
1217
mir:: AggregateKind :: Tuple => true ,
1154
- mir:: AggregateKind :: Adt ( def_id, ..) => {
1218
+ mir:: AggregateKind :: Adt ( def_id, vidx, ..) => {
1219
+ variant_idx = Some ( vidx) ;
1155
1220
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 ( )
1157
1223
}
1158
1224
mir:: AggregateKind :: Closure ( ..) => true ,
1159
1225
// FIXME: Can we do this for simple coroutines too?
@@ -1163,7 +1229,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1163
1229
let ty = rvalue. ty ( self . mir , self . cx . tcx ( ) ) ;
1164
1230
let ty = self . monomorphize ( ty) ;
1165
1231
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
+ }
1167
1243
}
1168
1244
}
1169
1245
}
0 commit comments