@@ -8,11 +8,12 @@ use itertools::Itertools;
8
8
use rspirv:: spirv:: { Dim , ImageFormat , StorageClass , Word } ;
9
9
use rustc_abi:: ExternAbi as Abi ;
10
10
use rustc_abi:: {
11
- Align , BackendRepr , FieldIdx , FieldsShape , LayoutData , Primitive , ReprFlags , ReprOptions ,
12
- Scalar , Size , TagEncoding , VariantIdx , Variants ,
11
+ Align , BackendRepr , FieldIdx , FieldsShape , HasDataLayout as _ , LayoutData , Primitive ,
12
+ ReprFlags , ReprOptions , Scalar , Size , TagEncoding , VariantIdx , Variants ,
13
13
} ;
14
14
use rustc_data_structures:: fx:: FxHashMap ;
15
15
use rustc_errors:: ErrorGuaranteed ;
16
+ use rustc_hashes:: Hash64 ;
16
17
use rustc_index:: Idx ;
17
18
use rustc_middle:: query:: Providers ;
18
19
use rustc_middle:: ty:: layout:: { FnAbiOf , LayoutOf , TyAndLayout } ;
@@ -164,6 +165,85 @@ pub(crate) fn provide(providers: &mut Providers) {
164
165
}
165
166
166
167
providers. layout_of = |tcx, key| {
168
+ // HACK(eddyb) to special-case any types at all, they must be normalized,
169
+ // but when normalization would be needed, `layout_of`'s default provider
170
+ // recurses (supposedly for caching reasons), i.e. its calls `layout_of`
171
+ // w/ the normalized type in input, which once again reaches this hook,
172
+ // without ever needing any explicit normalization here.
173
+ let ty = key. value ;
174
+
175
+ // HACK(eddyb) bypassing upstream `#[repr(simd)]` changes (see also
176
+ // the later comment above `check_well_formed`, for more details).
177
+ let reimplement_old_style_repr_simd = match ty. kind ( ) {
178
+ ty:: Adt ( def, args) if def. repr ( ) . simd ( ) && !def. repr ( ) . packed ( ) && def. is_struct ( ) => {
179
+ Some ( def. non_enum_variant ( ) ) . and_then ( |v| {
180
+ let ( count, e_ty) = v
181
+ . fields
182
+ . iter ( )
183
+ . map ( |f| f. ty ( tcx, args) )
184
+ . dedup_with_count ( )
185
+ . exactly_one ( )
186
+ . ok ( ) ?;
187
+ let e_len = u64:: try_from ( count) . ok ( ) . filter ( |& e_len| e_len > 1 ) ?;
188
+ Some ( ( def, e_ty, e_len) )
189
+ } )
190
+ }
191
+ _ => None ,
192
+ } ;
193
+
194
+ // HACK(eddyb) tweaked copy of the old upstream logic for `#[repr(simd)]`:
195
+ // https://github.com/rust-lang/rust/blob/1.86.0/compiler/rustc_ty_utils/src/layout.rs#L464-L590
196
+ if let Some ( ( adt_def, e_ty, e_len) ) = reimplement_old_style_repr_simd {
197
+ let cx = rustc_middle:: ty:: layout:: LayoutCx :: new (
198
+ tcx,
199
+ key. typing_env . with_post_analysis_normalized ( tcx) ,
200
+ ) ;
201
+ let dl = cx. data_layout ( ) ;
202
+
203
+ // Compute the ABI of the element type:
204
+ let e_ly = cx. layout_of ( e_ty) ?;
205
+ let BackendRepr :: Scalar ( e_repr) = e_ly. backend_repr else {
206
+ // This error isn't caught in typeck, e.g., if
207
+ // the element type of the vector is generic.
208
+ tcx. dcx ( ) . span_fatal (
209
+ tcx. def_span ( adt_def. did ( ) ) ,
210
+ format ! (
211
+ "SIMD type `{ty}` with a non-primitive-scalar \
212
+ (integer/float/pointer) element type `{}`",
213
+ e_ly. ty
214
+ ) ,
215
+ ) ;
216
+ } ;
217
+
218
+ // Compute the size and alignment of the vector:
219
+ let size = e_ly. size . checked_mul ( e_len, dl) . unwrap ( ) ;
220
+ let align = dl. llvmlike_vector_align ( size) ;
221
+ let size = size. align_to ( align. abi ) ;
222
+
223
+ let layout = tcx. mk_layout ( LayoutData {
224
+ variants : Variants :: Single {
225
+ index : rustc_abi:: FIRST_VARIANT ,
226
+ } ,
227
+ fields : FieldsShape :: Array {
228
+ stride : e_ly. size ,
229
+ count : e_len,
230
+ } ,
231
+ backend_repr : BackendRepr :: SimdVector {
232
+ element : e_repr,
233
+ count : e_len,
234
+ } ,
235
+ largest_niche : e_ly. largest_niche ,
236
+ uninhabited : false ,
237
+ size,
238
+ align,
239
+ max_repr_align : None ,
240
+ unadjusted_abi_align : align. abi ,
241
+ randomization_seed : e_ly. randomization_seed . wrapping_add ( Hash64 :: new ( e_len) ) ,
242
+ } ) ;
243
+
244
+ return Ok ( TyAndLayout { ty, layout } ) ;
245
+ }
246
+
167
247
let TyAndLayout { ty, mut layout } =
168
248
( rustc_interface:: DEFAULT_QUERY_PROVIDERS . layout_of ) ( tcx, key) ?;
169
249
0 commit comments