Skip to content

Commit 02eca34

Browse files
committed
also sanity-check Abi::Vector, and slight refactoring
1 parent 04fb922 commit 02eca34

File tree

1 file changed

+43
-26
lines changed

1 file changed

+43
-26
lines changed

compiler/rustc_middle/src/ty/layout.rs

+43-26
Original file line numberDiff line numberDiff line change
@@ -248,16 +248,36 @@ fn sanity_check_layout<'tcx>(
248248
"size mismatch between ABI and layout in {layout:#?}"
249249
);*/
250250
}
251+
Abi::Vector { count, element } => {
252+
// No padding in vectors. Alignment can be strengthened, though.
253+
assert!(
254+
layout.align().abi >= element.align(&tcx).abi,
255+
"alignment mismatch between ABI and layout in {layout:#?}"
256+
);
257+
let size = element.size(&tcx) * count;
258+
assert_eq!(
259+
layout.size(),
260+
size.align_to(tcx.data_layout().vector_align(size).abi),
261+
"size mismatch between ABI and layout in {layout:#?}"
262+
);
263+
}
251264
Abi::ScalarPair(scalar1, scalar2) => {
252-
// Sanity-check scalar pair size.
253-
let field2_offset = scalar1.size(&tcx).align_to(scalar2.align(&tcx).abi);
254-
let total = field2_offset + scalar2.size(&tcx);
265+
// Sanity-check scalar pairs. These are a bit more flexible and support
266+
// padding, but we can at least ensure both fields actually fit into the layout
267+
// and the alignment requirement has not been weakened.
268+
let align1 = scalar1.align(&tcx).abi;
269+
let align2 = scalar2.align(&tcx).abi;
255270
assert!(
256-
layout.size() >= total,
271+
layout.align().abi >= cmp::max(align1, align2),
272+
"alignment mismatch between ABI and layout in {layout:#?}",
273+
);
274+
let field2_offset = scalar1.size(&tcx).align_to(align2);
275+
assert!(
276+
layout.size() >= field2_offset + scalar2.size(&tcx),
257277
"size mismatch between ABI and layout in {layout:#?}"
258278
);
259279
}
260-
_ => {}
280+
Abi::Uninhabited | Abi::Aggregate { .. } => {} // Nothing to check.
261281
}
262282
}
263283

@@ -1401,16 +1421,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
14011421
// Without latter check aligned enums with custom discriminant values
14021422
// Would result in ICE see the issue #92464 for more info
14031423
abi = Abi::Scalar(tag);
1404-
// Make sure the variants with fields have the same ABI as the enum itself
1405-
// (since downcasting to them is a NOP).
1406-
for variant in &mut layout_variants {
1407-
if variant.fields.count() > 0
1408-
&& matches!(variant.abi, Abi::Aggregate { .. })
1409-
{
1410-
assert_eq!(variant.size, size);
1411-
variant.abi = abi;
1412-
}
1413-
}
14141424
} else {
14151425
// Try to use a ScalarPair for all tagged enums.
14161426
let mut common_prim = None;
@@ -1479,17 +1489,24 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
14791489
// We can use `ScalarPair` only when it matches our
14801490
// already computed layout (including `#[repr(C)]`).
14811491
abi = pair.abi;
1482-
// Make sure the variants with fields have the same ABI as the enum itself
1483-
// (since downcasting to them is a NOP).
1484-
for variant in &mut layout_variants {
1485-
if variant.fields.count() > 0
1486-
&& matches!(variant.abi, Abi::Aggregate { .. })
1487-
{
1488-
variant.abi = abi;
1489-
// Also need to bump up the size, so that the pair fits inside.
1490-
variant.size = size;
1491-
}
1492-
}
1492+
}
1493+
}
1494+
}
1495+
1496+
// If we pick a "clever" (by-value) ABI, we might have to adjust the ABI of the
1497+
// variants to ensure they are consistent. This is because a downcast is
1498+
// semantically a NOP, and thus should not affect layout.
1499+
if matches!(abi, Abi::Scalar(..) | Abi::ScalarPair(..)) {
1500+
for variant in &mut layout_variants {
1501+
// We only do this for variants with fields; the others are not accessed anyway.
1502+
// Also do not overwrite any already existing "clever" ABIs.
1503+
if variant.fields.count() > 0
1504+
&& matches!(variant.abi, Abi::Aggregate { .. })
1505+
{
1506+
variant.abi = abi;
1507+
// Also need to bump up the size and alignment, so that the entire value fits in here.
1508+
variant.size = cmp::max(variant.size, size);
1509+
variant.align.abi = cmp::max(variant.align.abi, align.abi);
14931510
}
14941511
}
14951512
}

0 commit comments

Comments
 (0)