Skip to content

Commit 93378c3

Browse files
committed
vec3: SIMD to C, reusing DefId may be a bad idea?
1 parent 295c929 commit 93378c3

File tree

1 file changed

+52
-75
lines changed
  • crates/rustc_codegen_spirv/src

1 file changed

+52
-75
lines changed

crates/rustc_codegen_spirv/src/abi.rs

Lines changed: 52 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,17 @@ use itertools::Itertools;
88
use rspirv::spirv::{Dim, ImageFormat, StorageClass, Word};
99
use rustc_abi::ExternAbi as Abi;
1010
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, LayoutData, Primitive, ReprFlags, ReprOptions,
12+
Scalar, Size, TagEncoding, VariantIdx, Variants,
1313
};
1414
use rustc_data_structures::fx::FxHashMap;
1515
use rustc_errors::ErrorGuaranteed;
16-
use rustc_hashes::Hash64;
17-
use rustc_index::Idx;
16+
use rustc_index::{Idx, IndexVec};
1817
use rustc_middle::query::Providers;
1918
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
2019
use rustc_middle::ty::{
21-
self, Const, CoroutineArgs, CoroutineArgsExt as _, FloatTy, IntTy, PolyFnSig, Ty, TyCtxt,
22-
TyKind, UintTy,
20+
self, Const, CoroutineArgs, CoroutineArgsExt as _, FieldDef, FloatTy, IntTy, PolyFnSig, Ty,
21+
TyCtxt, TyKind, UintTy, VariantDef,
2322
};
2423
use rustc_middle::ty::{GenericArgsRef, ScalarInt};
2524
use rustc_middle::{bug, span_bug};
@@ -164,9 +163,12 @@ pub(crate) fn provide(providers: &mut Providers) {
164163
}
165164
}
166165

167-
providers.layout_of = |tcx: TyCtxt<'_>,
168-
key: ty::PseudoCanonicalInput<'_, Ty<'_>>|
169-
-> Result<TyAndLayout<'_>, &'_ ty::layout::LayoutError<'_>> {
166+
providers.layout_of = layout_of;
167+
168+
fn layout_of<'tcx>(
169+
tcx: TyCtxt<'tcx>,
170+
mut key: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>,
171+
) -> Result<TyAndLayout<'tcx>, &'tcx ty::layout::LayoutError<'tcx>> {
170172
// HACK(eddyb) to special-case any types at all, they must be normalized,
171173
// but when normalization would be needed, `layout_of`'s default provider
172174
// recurses (supposedly for caching reasons), i.e. its calls `layout_of`
@@ -176,76 +178,51 @@ pub(crate) fn provide(providers: &mut Providers) {
176178

177179
// HACK(eddyb) bypassing upstream `#[repr(simd)]` changes (see also
178180
// the later comment above `check_well_formed`, for more details).
179-
let reimplement_old_style_repr_simd = match ty.kind() {
181+
match ty.kind() {
180182
ty::Adt(def, args) if def.repr().simd() && !def.repr().packed() && def.is_struct() => {
181-
Some(def.non_enum_variant()).and_then(|v| {
182-
let (count, e_ty) = v
183-
.fields
183+
let def: &ty::AdtDef<'tcx> = def;
184+
let args: &ty::GenericArgs<'tcx> = args;
185+
186+
let mut repr_flags = def.repr().flags;
187+
repr_flags.remove(ReprFlags::IS_SIMD);
188+
repr_flags.insert(ReprFlags::IS_C);
189+
let def_c = tcx.mk_adt_def(
190+
def.did(),
191+
def.adt_kind(),
192+
def.variants()
184193
.iter()
185-
.map(|f| f.ty(tcx, args))
186-
.dedup_with_count()
187-
.exactly_one()
188-
.ok()?;
189-
let e_len = u64::try_from(count).ok().filter(|&e_len| e_len > 1)?;
190-
Some((def, e_ty, e_len))
191-
})
194+
.map(|v| {
195+
VariantDef::new(
196+
v.name,
197+
None,
198+
v.ctor,
199+
v.discr,
200+
v.fields
201+
.iter()
202+
.map(|f| FieldDef {
203+
did: f.did,
204+
name: f.name,
205+
vis: f.vis,
206+
safety: f.safety,
207+
value: f.value,
208+
})
209+
.collect(),
210+
v.def_id,
211+
None,
212+
v.is_field_list_non_exhaustive(),
213+
)
214+
})
215+
.collect(),
216+
ReprOptions {
217+
flags: repr_flags,
218+
..def.repr()
219+
},
220+
);
221+
key.value = Ty::new_adt(tcx, def_c, args);
192222
}
193-
_ => None,
223+
_ => (),
194224
};
195225

196-
// HACK(eddyb) tweaked copy of the old upstream logic for `#[repr(simd)]`:
197-
// https://github.com/rust-lang/rust/blob/1.86.0/compiler/rustc_ty_utils/src/layout.rs#L464-L590
198-
if let Some((adt_def, e_ty, e_len)) = reimplement_old_style_repr_simd {
199-
let cx = rustc_middle::ty::layout::LayoutCx::new(
200-
tcx,
201-
key.typing_env.with_post_analysis_normalized(tcx),
202-
);
203-
let dl = cx.data_layout();
204-
205-
// Compute the ABI of the element type:
206-
let e_ly = cx.layout_of(e_ty)?;
207-
let BackendRepr::Scalar(e_repr) = e_ly.backend_repr else {
208-
// This error isn't caught in typeck, e.g., if
209-
// the element type of the vector is generic.
210-
tcx.dcx().span_fatal(
211-
tcx.def_span(adt_def.did()),
212-
format!(
213-
"SIMD type `{ty}` with a non-primitive-scalar \
214-
(integer/float/pointer) element type `{}`",
215-
e_ly.ty
216-
),
217-
);
218-
};
219-
220-
// Compute the size and alignment of the vector:
221-
let size = e_ly.size.checked_mul(e_len, dl).unwrap();
222-
let align = dl.llvmlike_vector_align(size);
223-
let size = size.align_to(align.abi);
224-
225-
let layout = tcx.mk_layout(LayoutData {
226-
variants: Variants::Single {
227-
index: rustc_abi::FIRST_VARIANT,
228-
},
229-
fields: FieldsShape::Array {
230-
stride: e_ly.size,
231-
count: e_len,
232-
},
233-
backend_repr: BackendRepr::SimdVector {
234-
element: e_repr,
235-
count: e_len,
236-
},
237-
largest_niche: e_ly.largest_niche,
238-
uninhabited: false,
239-
size,
240-
align,
241-
max_repr_align: None,
242-
unadjusted_abi_align: align.abi,
243-
randomization_seed: e_ly.randomization_seed.wrapping_add(Hash64::new(e_len)),
244-
});
245-
246-
return Ok(TyAndLayout { ty, layout });
247-
}
248-
249226
let TyAndLayout { ty, mut layout } =
250227
(rustc_interface::DEFAULT_QUERY_PROVIDERS.layout_of)(tcx, key)?;
251228

@@ -270,7 +247,7 @@ pub(crate) fn provide(providers: &mut Providers) {
270247
}
271248

272249
Ok(TyAndLayout { ty, layout })
273-
};
250+
}
274251

275252
// HACK(eddyb) work around https://github.com/rust-lang/rust/pull/129403
276253
// banning "struct-style" `#[repr(simd)]` (in favor of "array-newtype-style"),

0 commit comments

Comments
 (0)