@@ -8,12 +8,10 @@ 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 , HasDataLayout as _, LayoutData , Primitive ,
12
- ReprFlags , ReprOptions , Scalar , Size , TagEncoding , VariantIdx , Variants ,
11
+ Align , BackendRepr , FieldIdx , FieldsShape , Primitive , Scalar , Size , VariantIdx , Variants ,
13
12
} ;
14
13
use rustc_data_structures:: fx:: FxHashMap ;
15
14
use rustc_errors:: ErrorGuaranteed ;
16
- use rustc_hashes:: Hash64 ;
17
15
use rustc_index:: Idx ;
18
16
use rustc_middle:: query:: Providers ;
19
17
use rustc_middle:: ty:: layout:: { FnAbiOf , LayoutOf , TyAndLayout } ;
@@ -98,267 +96,6 @@ pub(crate) fn provide(providers: &mut Providers) {
98
96
Ok ( readjust_fn_abi ( tcx, result?) )
99
97
} ;
100
98
101
- // FIXME(eddyb) remove this by deriving `Clone` for `LayoutData` upstream.
102
- fn clone_layout < FieldIdx : Idx , VariantIdx : Idx > (
103
- layout : & LayoutData < FieldIdx , VariantIdx > ,
104
- ) -> LayoutData < FieldIdx , VariantIdx > {
105
- let LayoutData {
106
- ref fields,
107
- ref variants,
108
- backend_repr,
109
- largest_niche,
110
- uninhabited,
111
- align,
112
- size,
113
- max_repr_align,
114
- unadjusted_abi_align,
115
- randomization_seed,
116
- } = * layout;
117
- LayoutData {
118
- fields : match * fields {
119
- FieldsShape :: Primitive => FieldsShape :: Primitive ,
120
- FieldsShape :: Union ( count) => FieldsShape :: Union ( count) ,
121
- FieldsShape :: Array { stride, count } => FieldsShape :: Array { stride, count } ,
122
- FieldsShape :: Arbitrary {
123
- ref offsets,
124
- ref memory_index,
125
- } => FieldsShape :: Arbitrary {
126
- offsets : offsets. clone ( ) ,
127
- memory_index : memory_index. clone ( ) ,
128
- } ,
129
- } ,
130
- variants : match * variants {
131
- Variants :: Empty => Variants :: Empty ,
132
- Variants :: Single { index } => Variants :: Single { index } ,
133
- Variants :: Multiple {
134
- tag,
135
- ref tag_encoding,
136
- tag_field,
137
- ref variants,
138
- } => Variants :: Multiple {
139
- tag,
140
- tag_encoding : match * tag_encoding {
141
- TagEncoding :: Direct => TagEncoding :: Direct ,
142
- TagEncoding :: Niche {
143
- untagged_variant,
144
- ref niche_variants,
145
- niche_start,
146
- } => TagEncoding :: Niche {
147
- untagged_variant,
148
- niche_variants : niche_variants. clone ( ) ,
149
- niche_start,
150
- } ,
151
- } ,
152
- tag_field,
153
- variants : variants. clone ( ) ,
154
- } ,
155
- } ,
156
- backend_repr,
157
- largest_niche,
158
- uninhabited,
159
- align,
160
- size,
161
- max_repr_align,
162
- unadjusted_abi_align,
163
- randomization_seed,
164
- }
165
- }
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
-
247
- let TyAndLayout { ty, mut layout } =
248
- ( rustc_interface:: DEFAULT_QUERY_PROVIDERS . layout_of ) ( tcx, key) ?;
249
-
250
- #[ allow( clippy:: match_like_matches_macro) ]
251
- let hide_niche = match ty. kind ( ) {
252
- ty:: Bool => {
253
- // HACK(eddyb) we can't bypass e.g. `Option<bool>` being a byte,
254
- // due to `core` PR https://github.com/rust-lang/rust/pull/138881
255
- // (which adds a new `transmute`, from `ControlFlow<bool>` to `u8`).
256
- let libcore_needs_bool_niche = true ;
257
-
258
- !libcore_needs_bool_niche
259
- }
260
- _ => false ,
261
- } ;
262
-
263
- if hide_niche {
264
- layout = tcx. mk_layout ( LayoutData {
265
- largest_niche : None ,
266
- ..clone_layout ( layout. 0 . 0 )
267
- } ) ;
268
- }
269
-
270
- Ok ( TyAndLayout { ty, layout } )
271
- } ;
272
-
273
- // HACK(eddyb) work around https://github.com/rust-lang/rust/pull/129403
274
- // banning "struct-style" `#[repr(simd)]` (in favor of "array-newtype-style"),
275
- // by simply bypassing "type definition WF checks" for affected types, which:
276
- // - can only really be sound for types with trivial field types, that are
277
- // either completely non-generic (covering most `#[repr(simd)]` `struct`s),
278
- // or *at most* one generic type parameter with no bounds/where clause
279
- // - relies on upstream `layout_of` not having had the non-array logic removed
280
- //
281
- // FIXME(eddyb) remove this once migrating beyond `#[repr(simd)]` becomes
282
- // an option (may require Rust-GPU distinguishing between "SPIR-V interface"
283
- // and "Rust-facing" types, which is even worse when the `OpTypeVector`s
284
- // may be e.g. nested in `struct`s/arrays/etc. - at least buffers are easy).
285
- //
286
- // FIXME(eddyb) maybe using `#[spirv(vector)]` and `BackendRepr::Memory`,
287
- // no claims at `rustc`-understood SIMD whatsoever, would be enough?
288
- // (i.e. only SPIR-V caring about such a type vs a struct/array)
289
- providers. check_well_formed = |tcx, def_id| {
290
- let trivial_struct = match tcx. hir_node_by_def_id ( def_id) {
291
- rustc_hir:: Node :: Item ( item) => match item. kind {
292
- rustc_hir:: ItemKind :: Struct (
293
- _,
294
- & rustc_hir:: Generics {
295
- params :
296
- & [ ]
297
- | & [
298
- rustc_hir:: GenericParam {
299
- kind :
300
- rustc_hir:: GenericParamKind :: Type {
301
- default : None ,
302
- synthetic : false ,
303
- } ,
304
- ..
305
- } ,
306
- ] ,
307
- predicates : & [ ] ,
308
- has_where_clause_predicates : false ,
309
- where_clause_span : _,
310
- span : _,
311
- } ,
312
- _,
313
- ) => Some ( tcx. adt_def ( def_id) ) ,
314
- _ => None ,
315
- } ,
316
- _ => None ,
317
- } ;
318
- let valid_non_array_simd_struct = trivial_struct. is_some_and ( |adt_def| {
319
- let ReprOptions {
320
- int : None ,
321
- align : None ,
322
- pack : None ,
323
- flags : ReprFlags :: IS_SIMD ,
324
- field_shuffle_seed : _,
325
- } = adt_def. repr ( )
326
- else {
327
- return false ;
328
- } ;
329
- if adt_def. destructor ( tcx) . is_some ( ) {
330
- return false ;
331
- }
332
-
333
- let field_types = adt_def
334
- . non_enum_variant ( )
335
- . fields
336
- . iter ( )
337
- . map ( |f| tcx. type_of ( f. did ) . instantiate_identity ( ) ) ;
338
- field_types. dedup ( ) . exactly_one ( ) . is_ok_and ( |elem_ty| {
339
- matches ! (
340
- elem_ty. kind( ) ,
341
- ty:: Bool | ty:: Int ( _) | ty:: Uint ( _) | ty:: Float ( _) | ty:: Param ( _)
342
- )
343
- } )
344
- } ) ;
345
-
346
- if valid_non_array_simd_struct {
347
- tcx. dcx ( )
348
- . struct_span_warn (
349
- tcx. def_span ( def_id) ,
350
- "[Rust-GPU] temporarily re-allowing old-style `#[repr(simd)]` (with fields)" ,
351
- )
352
- . with_note ( "removed upstream by https://github.com/rust-lang/rust/pull/129403" )
353
- . with_note ( "in favor of the new `#[repr(simd)] struct TxN([T; N]);` style" )
354
- . with_note ( "(taking effect since `nightly-2024-09-12` / `1.83.0` stable)" )
355
- . emit ( ) ;
356
- return Ok ( ( ) ) ;
357
- }
358
-
359
- ( rustc_interface:: DEFAULT_QUERY_PROVIDERS . check_well_formed ) ( tcx, def_id)
360
- } ;
361
-
362
99
// HACK(eddyb) work around https://github.com/rust-lang/rust/pull/132173
363
100
// (and further changes from https://github.com/rust-lang/rust/pull/132843)
364
101
// starting to ban SIMD ABI misuse (or at least starting to warn about it).
0 commit comments