4
4
use crate :: attr:: { AggregatedSpirvAttributes , IntrinsicType } ;
5
5
use crate :: codegen_cx:: CodegenCx ;
6
6
use crate :: spirv_type:: SpirvType ;
7
+ use itertools:: Itertools ;
7
8
use rspirv:: spirv:: { Dim , ImageFormat , StorageClass , Word } ;
8
9
use rustc_data_structures:: fx:: FxHashMap ;
9
10
use rustc_errors:: ErrorGuaranteed ;
@@ -22,7 +23,8 @@ use rustc_span::def_id::DefId;
22
23
use rustc_span:: { Span , Symbol } ;
23
24
use rustc_target:: abi:: call:: { ArgAbi , ArgAttributes , FnAbi , PassMode } ;
24
25
use rustc_target:: abi:: {
25
- Abi , Align , FieldsShape , LayoutS , Primitive , Scalar , Size , TagEncoding , VariantIdx , Variants ,
26
+ Abi , Align , FieldsShape , LayoutS , Primitive , ReprFlags , ReprOptions , Scalar , Size , TagEncoding ,
27
+ VariantIdx , Variants ,
26
28
} ;
27
29
use rustc_target:: spec:: abi:: Abi as SpecAbi ;
28
30
use std:: cell:: RefCell ;
@@ -157,6 +159,7 @@ pub(crate) fn provide(providers: &mut Providers) {
157
159
unadjusted_abi_align,
158
160
}
159
161
}
162
+
160
163
providers. layout_of = |tcx, key| {
161
164
let TyAndLayout { ty, mut layout } =
162
165
( rustc_interface:: DEFAULT_QUERY_PROVIDERS . layout_of ) ( tcx, key) ?;
@@ -176,6 +179,90 @@ pub(crate) fn provide(providers: &mut Providers) {
176
179
177
180
Ok ( TyAndLayout { ty, layout } )
178
181
} ;
182
+
183
+ // HACK(eddyb) work around https://github.com/rust-lang/rust/pull/129403
184
+ // banning "struct-style" `#[repr(simd)]` (in favor of "array-newtype-style"),
185
+ // by simply bypassing "type definition WF checks" for affected types, which:
186
+ // - can only really be sound for types with trivial field types, that are
187
+ // either completely non-generic (covering most `#[repr(simd)]` `struct`s),
188
+ // or *at most* one generic type parameter with no bounds/where clause
189
+ // - relies on upstream `layout_of` not having had the non-array logic removed
190
+ //
191
+ // FIXME(eddyb) remove this once migrating beyond `#[repr(simd)]` becomes
192
+ // an option (may require Rust-GPU distinguishing between "SPIR-V interface"
193
+ // and "Rust-facing" types, which is even worse when the `OpTypeVector`s
194
+ // may be e.g. nested in `struct`s/arrays/etc. - at least buffers are easy).
195
+ providers. check_well_formed = |tcx, def_id| {
196
+ let trivial_struct = match tcx. hir_node_by_def_id ( def_id) {
197
+ rustc_hir:: Node :: Item ( item) => match item. kind {
198
+ rustc_hir:: ItemKind :: Struct (
199
+ _,
200
+ & rustc_hir:: Generics {
201
+ params :
202
+ & [ ]
203
+ | & [
204
+ rustc_hir:: GenericParam {
205
+ kind :
206
+ rustc_hir:: GenericParamKind :: Type {
207
+ default : None ,
208
+ synthetic : false ,
209
+ } ,
210
+ ..
211
+ } ,
212
+ ] ,
213
+ predicates : & [ ] ,
214
+ has_where_clause_predicates : false ,
215
+ where_clause_span : _,
216
+ span : _,
217
+ } ,
218
+ ) => Some ( tcx. adt_def ( def_id) ) ,
219
+ _ => None ,
220
+ } ,
221
+ _ => None ,
222
+ } ;
223
+ let valid_non_array_simd_struct = trivial_struct. is_some_and ( |adt_def| {
224
+ let ReprOptions {
225
+ int : None ,
226
+ align : None ,
227
+ pack : None ,
228
+ flags : ReprFlags :: IS_SIMD ,
229
+ field_shuffle_seed : _,
230
+ } = adt_def. repr ( )
231
+ else {
232
+ return false ;
233
+ } ;
234
+ if adt_def. destructor ( tcx) . is_some ( ) {
235
+ return false ;
236
+ }
237
+
238
+ let field_types = adt_def
239
+ . non_enum_variant ( )
240
+ . fields
241
+ . iter ( )
242
+ . map ( |f| tcx. type_of ( f. did ) . instantiate_identity ( ) ) ;
243
+ field_types. dedup ( ) . exactly_one ( ) . is_ok_and ( |elem_ty| {
244
+ matches ! (
245
+ elem_ty. kind( ) ,
246
+ ty:: Bool | ty:: Int ( _) | ty:: Uint ( _) | ty:: Float ( _) | ty:: Param ( _)
247
+ )
248
+ } )
249
+ } ) ;
250
+
251
+ if valid_non_array_simd_struct {
252
+ tcx. dcx ( )
253
+ . struct_span_warn (
254
+ tcx. def_span ( def_id) ,
255
+ "[Rust-GPU] temporarily re-allowing old-style `#[repr(simd)]` (with fields)" ,
256
+ )
257
+ . with_note ( "removed upstream by https://github.com/rust-lang/rust/pull/129403" )
258
+ . with_note ( "in favor of the new `#[repr(simd)] struct TxN([T; N]);` style" )
259
+ . with_note ( "(taking effect since `nightly-2024-09-12` / `1.83.0` stable)" )
260
+ . emit ( ) ;
261
+ return Ok ( ( ) ) ;
262
+ }
263
+
264
+ ( rustc_interface:: DEFAULT_QUERY_PROVIDERS . check_well_formed ) ( tcx, def_id)
265
+ } ;
179
266
}
180
267
181
268
/// If a struct contains a pointer to itself, even indirectly, then doing a naiive recursive walk
@@ -458,7 +545,7 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> {
458
545
}
459
546
}
460
547
461
- /// Only pub for `LayoutTypeMethods ::scalar_pair_element_backend_type`. Think about what you're
548
+ /// Only pub for `LayoutTypeCodegenMethods ::scalar_pair_element_backend_type`. Think about what you're
462
549
/// doing before calling this.
463
550
pub fn scalar_pair_element_backend_type < ' tcx > (
464
551
cx : & CodegenCx < ' tcx > ,
0 commit comments