@@ -687,34 +687,117 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
687
687
}
688
688
689
689
// SIMD vector types.
690
- ty:: Adt ( def, ..) if def. repr . simd ( ) => {
691
- let element = self . layout_of ( ty. simd_type ( tcx) ) ?;
692
- let count = ty. simd_size ( tcx) as u64 ;
693
- assert ! ( count > 0 ) ;
694
- let scalar = match element. abi {
695
- Abi :: Scalar ( ref scalar) => scalar. clone ( ) ,
696
- _ => {
697
- tcx. sess . fatal ( & format ! ( "monomorphising SIMD type `{}` with \
698
- a non-machine element type `{}`",
699
- ty, element. ty) ) ;
690
+ ty:: Adt ( def, substs) if def. repr . simd ( ) => {
691
+ // Supported SIMD vectors are homogeneous ADTs with at least one field:
692
+ //
693
+ // * #[repr(simd)] struct S(T, T, T, T);
694
+ // * #[repr(simd)] struct S { x: T, y: T, z: T, w: T }
695
+ // * #[repr(simd)] struct S([T; 4])
696
+ //
697
+ // where T is a "machine type", e.g., `f32`, `i64`, `*mut _`.
698
+
699
+ // SIMD vectors with zero fields are not supported:
700
+ if def. non_enum_variant ( ) . fields . is_empty ( ) {
701
+ tcx. sess . fatal ( & format ! (
702
+ "monomorphising SIMD type `{}` of zero length" , ty
703
+ ) ) ;
704
+ }
705
+
706
+ // Type of the first ADT field:
707
+ let f0_ty = def. non_enum_variant ( ) . fields [ 0 ] . ty ( tcx, substs) ;
708
+
709
+ // Heterogeneous SIMD vectors are not supported:
710
+ for fi in & def. non_enum_variant ( ) . fields {
711
+ if fi. ty ( tcx, substs) != f0_ty {
712
+ tcx. sess . fatal ( & format ! (
713
+ "monomorphising heterogeneous SIMD type `{}`" , ty
714
+ ) ) ;
700
715
}
716
+ }
717
+
718
+ // The element type and number of elements of the SIMD vector
719
+ // are obtained from:
720
+ //
721
+ // * the element type and length of the single array field, if
722
+ // the first field is of array type, or
723
+ //
724
+ // * the homogenous field type and the number of fields.
725
+ let ( e_ty, e_len, is_array) = if let ty:: Array ( e_ty, _) = f0_ty. sty {
726
+ // First ADT field is an array:
727
+
728
+ // SIMD vectors with multiple array fields are not supported:
729
+ if def. non_enum_variant ( ) . fields . len ( ) != 1 {
730
+ tcx. sess . fatal ( & format ! (
731
+ "monomorphising SIMD type `{}` with more than one array field" ,
732
+ ty
733
+ ) ) ;
734
+ }
735
+
736
+ // Extract the number of elements from the layout of the array field:
737
+ let len = if let Ok ( TyLayout {
738
+ details : LayoutDetails {
739
+ fields : FieldPlacement :: Array {
740
+ count, ..
741
+ } , ..
742
+ } , ..
743
+ } ) = self . layout_of ( f0_ty) {
744
+ count
745
+ } else {
746
+ unreachable ! ( ) ;
747
+ } ;
748
+
749
+ ( e_ty, * len, true )
750
+ } else {
751
+ // First ADT field is not an array:
752
+ ( f0_ty, def. non_enum_variant ( ) . fields . len ( ) as _ , false )
701
753
} ;
702
- let size = element. size . checked_mul ( count, dl)
754
+
755
+ // SIMD vectors of zero length are not supported:
756
+ if e_len == 0 {
757
+ tcx. sess . fatal ( & format ! (
758
+ "monomorphising SIMD type `{}` of zero length" , ty
759
+ ) ) ;
760
+ }
761
+
762
+ // Compute the ABI of the element type:
763
+ let e_ly = self . layout_of ( e_ty) ?;
764
+ let e_abi = if let Abi :: Scalar ( ref scalar) = e_ly. abi {
765
+ scalar. clone ( )
766
+ } else {
767
+ tcx. sess . fatal ( & format ! (
768
+ "monomorphising SIMD type `{}` with a non-machine element type `{}`" ,
769
+ ty, e_ty
770
+ ) )
771
+ } ;
772
+
773
+
774
+ // Compute the size and alignment of the vector:
775
+ let size = e_ly. size . checked_mul ( e_len, dl)
703
776
. ok_or ( LayoutError :: SizeOverflow ( ty) ) ?;
704
777
let align = dl. vector_align ( size) ;
705
778
let size = size. align_to ( align. abi ) ;
706
779
780
+ // Compute the placement of the vector fields:
781
+ let fields = if is_array {
782
+ FieldPlacement :: Arbitrary {
783
+ offsets : vec ! [ Size :: ZERO ] ,
784
+ memory_index : vec ! [ 0 ] ,
785
+ }
786
+ } else {
787
+ FieldPlacement :: Array {
788
+ stride : e_ly. size ,
789
+ count : e_len,
790
+ }
791
+ } ;
792
+
707
793
tcx. intern_layout ( LayoutDetails {
708
794
variants : Variants :: Single { index : VariantIdx :: new ( 0 ) } ,
709
- fields : FieldPlacement :: Array {
710
- stride : element. size ,
711
- count
712
- } ,
795
+ fields,
713
796
abi : Abi :: Vector {
714
- element : scalar ,
715
- count
797
+ element : e_abi ,
798
+ count : e_len ,
716
799
} ,
717
- largest_niche : element . largest_niche . clone ( ) ,
800
+ largest_niche : e_ly . largest_niche . clone ( ) ,
718
801
size,
719
802
align,
720
803
} )
@@ -2170,11 +2253,6 @@ where
2170
2253
2171
2254
ty:: Tuple ( tys) => tys[ i] . expect_ty ( ) ,
2172
2255
2173
- // SIMD vector types.
2174
- ty:: Adt ( def, ..) if def. repr . simd ( ) => {
2175
- this. ty . simd_type ( tcx)
2176
- }
2177
-
2178
2256
// ADTs.
2179
2257
ty:: Adt ( def, substs) => {
2180
2258
match this. variants {
0 commit comments