@@ -7,7 +7,7 @@ use hir_def::{
77 Abi , FieldsShape , Integer , LayoutCalculator , LayoutS , Primitive , ReprOptions , Scalar , Size ,
88 StructKind , TargetDataLayout , WrappingRange ,
99 } ,
10- LocalEnumVariantId , LocalFieldId ,
10+ LocalEnumVariantId , LocalFieldId , StructId ,
1111} ;
1212use la_arena:: { Idx , RawIdx } ;
1313use stdx:: never;
@@ -77,6 +77,78 @@ impl<'a> LayoutCalculator for LayoutCx<'a> {
7777 }
7878}
7979
80+ // FIXME: move this to the `rustc_abi`.
81+ fn layout_of_simd_ty (
82+ db : & dyn HirDatabase ,
83+ id : StructId ,
84+ subst : & Substitution ,
85+ krate : CrateId ,
86+ dl : & TargetDataLayout ,
87+ ) -> Result < Arc < Layout > , LayoutError > {
88+ let fields = db. field_types ( id. into ( ) ) ;
89+
90+ // Supported SIMD vectors are homogeneous ADTs with at least one field:
91+ //
92+ // * #[repr(simd)] struct S(T, T, T, T);
93+ // * #[repr(simd)] struct S { x: T, y: T, z: T, w: T }
94+ // * #[repr(simd)] struct S([T; 4])
95+ //
96+ // where T is a primitive scalar (integer/float/pointer).
97+
98+ let f0_ty = match fields. iter ( ) . next ( ) {
99+ Some ( x) => x. 1 . clone ( ) . substitute ( Interner , subst) ,
100+ None => {
101+ user_error ! ( "simd type with zero fields" ) ;
102+ }
103+ } ;
104+
105+ // The element type and number of elements of the SIMD vector
106+ // are obtained from:
107+ //
108+ // * the element type and length of the single array field, if
109+ // the first field is of array type, or
110+ //
111+ // * the homogeneous field type and the number of fields.
112+ let ( e_ty, e_len, is_array) = if let TyKind :: Array ( e_ty, _) = f0_ty. kind ( Interner ) {
113+ // Extract the number of elements from the layout of the array field:
114+ let FieldsShape :: Array { count, .. } = db. layout_of_ty ( f0_ty. clone ( ) , krate) ?. fields else {
115+ user_error ! ( "Array with non array layout" ) ;
116+ } ;
117+
118+ ( e_ty. clone ( ) , count, true )
119+ } else {
120+ // First ADT field is not an array:
121+ ( f0_ty, fields. iter ( ) . count ( ) as u64 , false )
122+ } ;
123+
124+ // Compute the ABI of the element type:
125+ let e_ly = db. layout_of_ty ( e_ty, krate) ?;
126+ let Abi :: Scalar ( e_abi) = e_ly. abi else {
127+ user_error ! ( "simd type with inner non scalar type" ) ;
128+ } ;
129+
130+ // Compute the size and alignment of the vector:
131+ let size = e_ly. size . checked_mul ( e_len, dl) . ok_or ( LayoutError :: SizeOverflow ) ?;
132+ let align = dl. vector_align ( size) ;
133+ let size = size. align_to ( align. abi ) ;
134+
135+ // Compute the placement of the vector fields:
136+ let fields = if is_array {
137+ FieldsShape :: Arbitrary { offsets : [ Size :: ZERO ] . into ( ) , memory_index : [ 0 ] . into ( ) }
138+ } else {
139+ FieldsShape :: Array { stride : e_ly. size , count : e_len }
140+ } ;
141+
142+ Ok ( Arc :: new ( Layout {
143+ variants : Variants :: Single { index : struct_variant_idx ( ) } ,
144+ fields,
145+ abi : Abi :: Vector { element : e_abi, count : e_len } ,
146+ largest_niche : e_ly. largest_niche ,
147+ size,
148+ align,
149+ } ) )
150+ }
151+
80152pub fn layout_of_ty_query (
81153 db : & dyn HirDatabase ,
82154 ty : Ty ,
@@ -88,7 +160,16 @@ pub fn layout_of_ty_query(
88160 let trait_env = Arc :: new ( TraitEnvironment :: empty ( krate) ) ;
89161 let ty = normalize ( db, trait_env, ty. clone ( ) ) ;
90162 let result = match ty. kind ( Interner ) {
91- TyKind :: Adt ( AdtId ( def) , subst) => return db. layout_of_adt ( * def, subst. clone ( ) , krate) ,
163+ TyKind :: Adt ( AdtId ( def) , subst) => {
164+ if let hir_def:: AdtId :: StructId ( s) = def {
165+ let data = db. struct_data ( * s) ;
166+ let repr = data. repr . unwrap_or_default ( ) ;
167+ if repr. simd ( ) {
168+ return layout_of_simd_ty ( db, * s, subst, krate, & target) ;
169+ }
170+ } ;
171+ return db. layout_of_adt ( * def, subst. clone ( ) , krate) ;
172+ }
92173 TyKind :: Scalar ( s) => match s {
93174 chalk_ir:: Scalar :: Bool => Layout :: scalar (
94175 dl,
0 commit comments