@@ -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