Skip to content

Commit c600075

Browse files
compiler: BackendRepr::inherent_{size,align} -> scalar_{size,align}
This pair of fn was introduced to perform invariant checks for scalars. Their current behavior doesn't mesh as well with checking SIMD types, so change the name of the fn to reflect their actual use-case and refactor the corresponding checks. Also simplify the returns from Option<AbiAndPrefAlign> to Option<Align>, because every site was mapping away the "preferred" alignment anyways.
1 parent 8cf4c76 commit c600075

File tree

3 files changed

+77
-71
lines changed

3 files changed

+77
-71
lines changed

compiler/rustc_abi/src/layout.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -308,10 +308,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
308308
let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
309309
let mut max_repr_align = repr.align;
310310

311-
// If all the non-ZST fields have the same ABI and union ABI optimizations aren't
312-
// disabled, we can use that common ABI for the union as a whole.
311+
// If all the non-ZST fields have the same repr and union repr optimizations aren't
312+
// disabled, we can use that common repr for the union as a whole.
313313
struct AbiMismatch;
314-
let mut common_non_zst_abi_and_align = if repr.inhibits_union_abi_opt() {
314+
let mut common_non_zst_repr_and_align = if repr.inhibits_union_abi_opt() {
315315
// Can't optimize
316316
Err(AbiMismatch)
317317
} else {
@@ -335,14 +335,14 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
335335
continue;
336336
}
337337

338-
if let Ok(common) = common_non_zst_abi_and_align {
338+
if let Ok(common) = common_non_zst_repr_and_align {
339339
// Discard valid range information and allow undef
340340
let field_abi = field.backend_repr.to_union();
341341

342342
if let Some((common_abi, common_align)) = common {
343343
if common_abi != field_abi {
344344
// Different fields have different ABI: disable opt
345-
common_non_zst_abi_and_align = Err(AbiMismatch);
345+
common_non_zst_repr_and_align = Err(AbiMismatch);
346346
} else {
347347
// Fields with the same non-Aggregate ABI should also
348348
// have the same alignment
@@ -355,7 +355,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
355355
}
356356
} else {
357357
// First non-ZST field: record its ABI and alignment
358-
common_non_zst_abi_and_align = Ok(Some((field_abi, field.align.abi)));
358+
common_non_zst_repr_and_align = Ok(Some((field_abi, field.align.abi)));
359359
}
360360
}
361361
}
@@ -374,16 +374,15 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
374374

375375
// If all non-ZST fields have the same ABI, we may forward that ABI
376376
// for the union as a whole, unless otherwise inhibited.
377-
let abi = match common_non_zst_abi_and_align {
377+
let backend_repr = match common_non_zst_repr_and_align {
378378
Err(AbiMismatch) | Ok(None) => BackendRepr::Memory { sized: true },
379-
Ok(Some((abi, _))) => {
380-
if abi.inherent_align(dl).map(|a| a.abi) != Some(align.abi) {
381-
// Mismatched alignment (e.g. union is #[repr(packed)]): disable opt
382-
BackendRepr::Memory { sized: true }
383-
} else {
384-
abi
385-
}
379+
Ok(Some((repr, _)))
380+
// Mismatched alignment (e.g. union is #[repr(packed)]): disable opt
381+
if repr.scalar_align(dl).is_some_and(|scalar_align| scalar_align != align.abi) =>
382+
{
383+
BackendRepr::Memory { sized: true }
386384
}
385+
Ok(Some((repr, _))) => repr,
387386
};
388387

389388
let Some(union_field_count) = NonZeroUsize::new(only_variant.len()) else {
@@ -398,7 +397,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
398397
Ok(LayoutData {
399398
variants: Variants::Single { index: only_variant_idx },
400399
fields: FieldsShape::Union(union_field_count),
401-
backend_repr: abi,
400+
backend_repr,
402401
largest_niche: None,
403402
align,
404403
size: size.align_to(align.abi),

compiler/rustc_abi/src/lib.rs

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,13 +1178,10 @@ impl Scalar {
11781178
#[inline]
11791179
pub fn is_bool(&self) -> bool {
11801180
use Integer::*;
1181-
matches!(
1182-
self,
1183-
Scalar::Initialized {
1184-
value: Primitive::Int(I8, false),
1185-
valid_range: WrappingRange { start: 0, end: 1 }
1186-
}
1187-
)
1181+
matches!(self, Scalar::Initialized {
1182+
value: Primitive::Int(I8, false),
1183+
valid_range: WrappingRange { start: 0, end: 1 }
1184+
})
11881185
}
11891186

11901187
/// Get the primitive representation of this type, ignoring the valid range and whether the
@@ -1462,37 +1459,42 @@ impl BackendRepr {
14621459
matches!(*self, BackendRepr::Scalar(s) if s.is_bool())
14631460
}
14641461

1465-
/// Returns the fixed alignment of this ABI, if any is mandated.
1466-
pub fn inherent_align<C: HasDataLayout>(&self, cx: &C) -> Option<AbiAndPrefAlign> {
1467-
Some(match *self {
1468-
BackendRepr::Scalar(s) => s.align(cx),
1469-
BackendRepr::ScalarPair(s1, s2) => s1.align(cx).max(s2.align(cx)),
1470-
BackendRepr::Vector { element, count } => {
1471-
cx.data_layout().vector_align(element.size(cx) * count)
1472-
}
1473-
BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None,
1474-
})
1462+
/// The psABI alignment for a `Scalar` or `ScalarPair`
1463+
///
1464+
/// `None` for other variants.
1465+
pub fn scalar_align<C: HasDataLayout>(&self, cx: &C) -> Option<Align> {
1466+
match *self {
1467+
BackendRepr::Scalar(s) => Some(s.align(cx).abi),
1468+
BackendRepr::ScalarPair(s1, s2) => Some(s1.align(cx).max(s2.align(cx)).abi),
1469+
// The align of a Vector can vary in surprising ways
1470+
BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => None,
1471+
// FIXME: rebased away soon
1472+
BackendRepr::Uninhabited => None,
1473+
}
14751474
}
14761475

1477-
/// Returns the fixed size of this ABI, if any is mandated.
1478-
pub fn inherent_size<C: HasDataLayout>(&self, cx: &C) -> Option<Size> {
1479-
Some(match *self {
1480-
BackendRepr::Scalar(s) => {
1481-
// No padding in scalars.
1482-
s.size(cx)
1483-
}
1476+
/// The psABI size for a `Scalar` or `ScalarPair`
1477+
///
1478+
/// `None` for other variants
1479+
pub fn scalar_size<C: HasDataLayout>(&self, cx: &C) -> Option<Size> {
1480+
match *self {
1481+
// No padding in scalars.
1482+
BackendRepr::Scalar(s) => Some(s.size(cx)),
1483+
// May have some padding between the pair.
14841484
BackendRepr::ScalarPair(s1, s2) => {
1485-
// May have some padding between the pair.
14861485
let field2_offset = s1.size(cx).align_to(s2.align(cx).abi);
1487-
(field2_offset + s2.size(cx)).align_to(self.inherent_align(cx)?.abi)
1486+
let size = (field2_offset + s2.size(cx)).align_to(
1487+
self.scalar_align(cx)
1488+
// We absolutely must have an answer here or everything is FUBAR.
1489+
.unwrap(),
1490+
);
1491+
Some(size)
14881492
}
1489-
BackendRepr::Vector { element, count } => {
1490-
// No padding in vectors, except possibly for trailing padding
1491-
// to make the size a multiple of align (e.g. for vectors of size 3).
1492-
(element.size(cx) * count).align_to(self.inherent_align(cx)?.abi)
1493-
}
1494-
BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None,
1495-
})
1493+
// The size of a Vector can vary in surprising ways
1494+
BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => None,
1495+
// FIXME: rebased away soon
1496+
BackendRepr::Uninhabited => None,
1497+
}
14961498
}
14971499

14981500
/// Discard validity range information and allow undef.

compiler/rustc_ty_utils/src/layout/invariant.rs

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -65,31 +65,30 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
6565
}
6666

6767
fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) {
68-
// Verify the ABI mandated alignment and size.
69-
let align = layout.backend_repr.inherent_align(cx).map(|align| align.abi);
70-
let size = layout.backend_repr.inherent_size(cx);
71-
let Some((align, size)) = align.zip(size) else {
72-
assert_matches!(
73-
layout.layout.backend_repr(),
74-
BackendRepr::Uninhabited | BackendRepr::Memory { .. },
75-
"ABI unexpectedly missing alignment and/or size in {layout:#?}"
68+
// Verify the ABI-mandated alignment and size for scalars.
69+
let align = layout.backend_repr.scalar_align(cx);
70+
let size = layout.backend_repr.scalar_size(cx);
71+
if let Some(align) = align {
72+
assert_eq!(
73+
layout.layout.align().abi,
74+
align,
75+
"alignment mismatch between ABI and layout in {layout:#?}"
7676
);
77-
return;
78-
};
79-
assert_eq!(
80-
layout.layout.align().abi,
81-
align,
82-
"alignment mismatch between ABI and layout in {layout:#?}"
83-
);
84-
assert_eq!(
85-
layout.layout.size(),
86-
size,
87-
"size mismatch between ABI and layout in {layout:#?}"
88-
);
77+
}
78+
if let Some(size) = size {
79+
assert_eq!(
80+
layout.layout.size(),
81+
size,
82+
"size mismatch between ABI and layout in {layout:#?}"
83+
);
84+
}
8985

9086
// Verify per-ABI invariants
9187
match layout.layout.backend_repr() {
9288
BackendRepr::Scalar(_) => {
89+
// we already asserted this
90+
let align = align.unwrap();
91+
let size = size.unwrap();
9392
// Check that this matches the underlying field.
9493
let inner = skip_newtypes(cx, layout);
9594
assert!(
@@ -231,9 +230,15 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
231230
"`ScalarPair` second field with bad ABI in {inner:#?}",
232231
);
233232
}
234-
BackendRepr::Vector { element, .. } => {
235-
assert!(align >= element.align(cx).abi); // just sanity-checking `vector_align`.
236-
// FIXME: Do some kind of check of the inner type, like for Scalar and ScalarPair.
233+
BackendRepr::Vector { element, count } => {
234+
let align = layout.align.abi;
235+
let size = layout.size;
236+
let element_align = element.align(cx).abi;
237+
let element_size = element.size(cx);
238+
// Currently, vectors must always be aligned to at least their elements:
239+
assert!(align >= element_align);
240+
// And the size has to be element * count, of course
241+
assert!(size >= (element_size * count).align_to(align));
237242
}
238243
BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {} // Nothing to check.
239244
}

0 commit comments

Comments
 (0)