@@ -687,34 +687,117 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
687687 }
688688
689689 // 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+ ) ) ;
700715 }
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 )
701753 } ;
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)
703776 . ok_or ( LayoutError :: SizeOverflow ( ty) ) ?;
704777 let align = dl. vector_align ( size) ;
705778 let size = size. align_to ( align. abi ) ;
706779
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+
707793 tcx. intern_layout ( LayoutDetails {
708794 variants : Variants :: Single { index : VariantIdx :: new ( 0 ) } ,
709- fields : FieldPlacement :: Array {
710- stride : element. size ,
711- count
712- } ,
795+ fields,
713796 abi : Abi :: Vector {
714- element : scalar ,
715- count
797+ element : e_abi ,
798+ count : e_len ,
716799 } ,
717- largest_niche : element . largest_niche . clone ( ) ,
800+ largest_niche : e_ly . largest_niche . clone ( ) ,
718801 size,
719802 align,
720803 } )
@@ -2170,11 +2253,6 @@ where
21702253
21712254 ty:: Tuple ( tys) => tys[ i] . expect_ty ( ) ,
21722255
2173- // SIMD vector types.
2174- ty:: Adt ( def, ..) if def. repr . simd ( ) => {
2175- this. ty . simd_type ( tcx)
2176- }
2177-
21782256 // ADTs.
21792257 ty:: Adt ( def, substs) => {
21802258 match this. variants {
0 commit comments