@@ -8,12 +8,10 @@ use itertools::Itertools;
88use  rspirv:: spirv:: { Dim ,  ImageFormat ,  StorageClass ,  Word } ; 
99use  rustc_abi:: ExternAbi  as  Abi ; 
1010use  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 , 
1312} ; 
1413use  rustc_data_structures:: fx:: FxHashMap ; 
1514use  rustc_errors:: ErrorGuaranteed ; 
16- use  rustc_hashes:: Hash64 ; 
1715use  rustc_index:: Idx ; 
1816use  rustc_middle:: query:: Providers ; 
1917use  rustc_middle:: ty:: layout:: { FnAbiOf ,  LayoutOf ,  TyAndLayout } ; 
@@ -98,267 +96,6 @@ pub(crate) fn provide(providers: &mut Providers) {
9896        Ok ( readjust_fn_abi ( tcx,  result?) ) 
9997    } ; 
10098
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- , 
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- 
36299    // HACK(eddyb) work around https://github.com/rust-lang/rust/pull/132173 
363100    // (and further changes from https://github.com/rust-lang/rust/pull/132843) 
364101    // starting to ban SIMD ABI misuse (or at least starting to warn about it). 
0 commit comments