summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_abi/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
commitd1b2d29528b7794b41e66fc2136e395a02f8529b (patch)
treea4a17504b260206dec3cf55b2dca82929a348ac2 /compiler/rustc_abi/src
parentReleasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz
rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_abi/src')
-rw-r--r--compiler/rustc_abi/src/layout.rs73
-rw-r--r--compiler/rustc_abi/src/lib.rs54
2 files changed, 103 insertions, 24 deletions
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index f6875d895..a8a1a9057 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -40,6 +40,8 @@ pub trait LayoutCalculator {
largest_niche,
align,
size,
+ max_repr_align: None,
+ unadjusted_abi_align: align.abi,
}
}
@@ -122,6 +124,8 @@ pub trait LayoutCalculator {
largest_niche: None,
align: dl.i8_align,
size: Size::ZERO,
+ max_repr_align: None,
+ unadjusted_abi_align: dl.i8_align.abi,
}
}
@@ -256,8 +260,7 @@ pub trait LayoutCalculator {
}
_ => assert!(
start == Bound::Unbounded && end == Bound::Unbounded,
- "nonscalar layout for layout_scalar_valid_range type: {:#?}",
- st,
+ "nonscalar layout for layout_scalar_valid_range type: {st:#?}",
),
}
@@ -289,6 +292,9 @@ pub trait LayoutCalculator {
}
let mut align = dl.aggregate_align;
+ let mut max_repr_align = repr.align;
+ let mut unadjusted_abi_align = align.abi;
+
let mut variant_layouts = variants
.iter_enumerated()
.map(|(j, v)| {
@@ -296,6 +302,8 @@ pub trait LayoutCalculator {
st.variants = Variants::Single { index: j };
align = align.max(st.align);
+ max_repr_align = max_repr_align.max(st.max_repr_align);
+ unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align);
Some(st)
})
@@ -422,6 +430,8 @@ pub trait LayoutCalculator {
largest_niche,
size,
align,
+ max_repr_align,
+ unadjusted_abi_align,
};
Some(TmpLayout { layout, variants: variant_layouts })
@@ -452,10 +462,13 @@ pub trait LayoutCalculator {
min = 0;
max = 0;
}
- assert!(min <= max, "discriminant range is {}...{}", min, max);
+ assert!(min <= max, "discriminant range is {min}...{max}");
let (min_ity, signed) = discr_range_of_repr(min, max); //Integer::repr_discr(tcx, ty, &repr, min, max);
let mut align = dl.aggregate_align;
+ let mut max_repr_align = repr.align;
+ let mut unadjusted_abi_align = align.abi;
+
let mut size = Size::ZERO;
// We're interested in the smallest alignment, so start large.
@@ -498,6 +511,8 @@ pub trait LayoutCalculator {
}
size = cmp::max(size, st.size);
align = align.max(st.align);
+ max_repr_align = max_repr_align.max(st.max_repr_align);
+ unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align);
Some(st)
})
.collect::<Option<IndexVec<VariantIdx, _>>>()?;
@@ -521,8 +536,7 @@ pub trait LayoutCalculator {
// space necessary to represent would have to be discarded (or layout is wrong
// on thinking it needs 16 bits)
panic!(
- "layout decided on a larger discriminant type ({:?}) than typeck ({:?})",
- min_ity, typeck_ity
+ "layout decided on a larger discriminant type ({min_ity:?}) than typeck ({typeck_ity:?})"
);
// However, it is fine to make discr type however large (as an optimisation)
// after this point – we’ll just truncate the value we load in codegen.
@@ -691,6 +705,8 @@ pub trait LayoutCalculator {
abi,
align,
size,
+ max_repr_align,
+ unadjusted_abi_align,
};
let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants };
@@ -730,10 +746,7 @@ pub trait LayoutCalculator {
let dl = self.current_data_layout();
let dl = dl.borrow();
let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
-
- if let Some(repr_align) = repr.align {
- align = align.max(AbiAndPrefAlign::new(repr_align));
- }
+ let mut max_repr_align = repr.align;
// If all the non-ZST fields have the same ABI and union ABI optimizations aren't
// disabled, we can use that common ABI for the union as a whole.
@@ -748,9 +761,12 @@ pub trait LayoutCalculator {
let mut size = Size::ZERO;
let only_variant = &variants[FIRST_VARIANT];
for field in only_variant {
- assert!(field.0.is_sized());
+ if field.0.is_unsized() {
+ self.delay_bug("unsized field in union".to_string());
+ }
align = align.max(field.align());
+ max_repr_align = max_repr_align.max(field.max_repr_align());
size = cmp::max(size, field.size());
if field.0.is_zst() {
@@ -787,6 +803,14 @@ pub trait LayoutCalculator {
if let Some(pack) = repr.pack {
align = align.min(AbiAndPrefAlign::new(pack));
}
+ // The unadjusted ABI alignment does not include repr(align), but does include repr(pack).
+ // See documentation on `LayoutS::unadjusted_abi_align`.
+ let unadjusted_abi_align = align.abi;
+ if let Some(repr_align) = repr.align {
+ align = align.max(AbiAndPrefAlign::new(repr_align));
+ }
+ // `align` must not be modified after this, or `unadjusted_abi_align` could be inaccurate.
+ let align = align;
// If all non-ZST fields have the same ABI, we may forward that ABI
// for the union as a whole, unless otherwise inhibited.
@@ -809,6 +833,8 @@ pub trait LayoutCalculator {
largest_niche: None,
align,
size: size.align_to(align.abi),
+ max_repr_align,
+ unadjusted_abi_align,
})
}
}
@@ -829,6 +855,7 @@ fn univariant(
) -> Option<LayoutS> {
let pack = repr.pack;
let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
+ let mut max_repr_align = repr.align;
let mut inverse_memory_index: IndexVec<u32, FieldIdx> = fields.indices().collect();
let optimize = !repr.inhibit_struct_field_reordering_opt();
if optimize && fields.len() > 1 {
@@ -997,6 +1024,7 @@ fn univariant(
};
offset = offset.align_to(field_align.abi);
align = align.max(field_align);
+ max_repr_align = max_repr_align.max(field.max_repr_align());
debug!("univariant offset: {:?} field: {:#?}", offset, field);
offsets[i] = offset;
@@ -1018,9 +1046,16 @@ fn univariant(
offset = offset.checked_add(field.size(), dl)?;
}
+
+ // The unadjusted ABI alignment does not include repr(align), but does include repr(pack).
+ // See documentation on `LayoutS::unadjusted_abi_align`.
+ let unadjusted_abi_align = align.abi;
if let Some(repr_align) = repr.align {
align = align.max(AbiAndPrefAlign::new(repr_align));
}
+ // `align` must not be modified after this point, or `unadjusted_abi_align` could be inaccurate.
+ let align = align;
+
debug!("univariant min_size: {:?}", offset);
let min_size = offset;
// As stated above, inverse_memory_index holds field indices by increasing offset.
@@ -1036,6 +1071,7 @@ fn univariant(
inverse_memory_index.into_iter().map(FieldIdx::as_u32).collect()
};
let size = min_size.align_to(align.abi);
+ let mut layout_of_single_non_zst_field = None;
let mut abi = Abi::Aggregate { sized };
// Unpack newtype ABIs and find scalar pairs.
if sized && size.bytes() > 0 {
@@ -1045,6 +1081,8 @@ fn univariant(
match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
// We have exactly one non-ZST field.
(Some((i, field)), None, None) => {
+ layout_of_single_non_zst_field = Some(field);
+
// Field fills the struct and it has a scalar or scalar pair ABI.
if offsets[i].bytes() == 0 && align.abi == field.align().abi && size == field.size()
{
@@ -1102,6 +1140,19 @@ fn univariant(
if fields.iter().any(|f| f.abi().is_uninhabited()) {
abi = Abi::Uninhabited;
}
+
+ let unadjusted_abi_align = if repr.transparent() {
+ match layout_of_single_non_zst_field {
+ Some(l) => l.unadjusted_abi_align(),
+ None => {
+ // `repr(transparent)` with all ZST fields.
+ align.abi
+ }
+ }
+ } else {
+ unadjusted_abi_align
+ };
+
Some(LayoutS {
variants: Variants::Single { index: FIRST_VARIANT },
fields: FieldsShape::Arbitrary { offsets, memory_index },
@@ -1109,6 +1160,8 @@ fn univariant(
largest_niche,
align,
size,
+ max_repr_align,
+ unadjusted_abi_align,
})
}
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index e1b9987f5..12dd1542d 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1,4 +1,5 @@
#![cfg_attr(feature = "nightly", feature(step_trait, rustc_attrs, min_specialization))]
+#![cfg_attr(all(not(bootstrap), feature = "nightly"), allow(internal_features))]
use std::fmt;
#[cfg(feature = "nightly")]
@@ -332,7 +333,7 @@ impl TargetDataLayout {
16 => 1 << 15,
32 => 1 << 31,
64 => 1 << 47,
- bits => panic!("obj_size_bound: unknown pointer bit size {}", bits),
+ bits => panic!("obj_size_bound: unknown pointer bit size {bits}"),
}
}
@@ -342,7 +343,7 @@ impl TargetDataLayout {
16 => I16,
32 => I32,
64 => I64,
- bits => panic!("ptr_sized_integer: unknown pointer bit size {}", bits),
+ bits => panic!("ptr_sized_integer: unknown pointer bit size {bits}"),
}
}
@@ -399,7 +400,7 @@ impl FromStr for Endian {
match s {
"little" => Ok(Self::Little),
"big" => Ok(Self::Big),
- _ => Err(format!(r#"unknown endian: "{}""#, s)),
+ _ => Err(format!(r#"unknown endian: "{s}""#)),
}
}
}
@@ -456,7 +457,7 @@ impl Size {
pub fn bits(self) -> u64 {
#[cold]
fn overflow(bytes: u64) -> ! {
- panic!("Size::bits: {} bytes in bits doesn't fit in u64", bytes)
+ panic!("Size::bits: {bytes} bytes in bits doesn't fit in u64")
}
self.bytes().checked_mul(8).unwrap_or_else(|| overflow(self.bytes()))
@@ -1179,17 +1180,12 @@ impl FieldsShape {
unreachable!("FieldsShape::offset: `Primitive`s have no fields")
}
FieldsShape::Union(count) => {
- assert!(
- i < count.get(),
- "tried to access field {} of union with {} fields",
- i,
- count
- );
+ assert!(i < count.get(), "tried to access field {i} of union with {count} fields");
Size::ZERO
}
FieldsShape::Array { stride, count } => {
let i = u64::try_from(i).unwrap();
- assert!(i < count);
+ assert!(i < count, "tried to access field {i} of array with {count} fields");
stride * i
}
FieldsShape::Arbitrary { ref offsets, .. } => offsets[FieldIdx::from_usize(i)],
@@ -1294,7 +1290,7 @@ impl Abi {
Primitive::Int(_, signed) => signed,
_ => false,
},
- _ => panic!("`is_signed` on non-scalar ABI {:?}", self),
+ _ => panic!("`is_signed` on non-scalar ABI {self:?}"),
}
}
@@ -1345,7 +1341,6 @@ impl Abi {
/// Discard validity range information and allow undef.
pub fn to_union(&self) -> Self {
- assert!(self.is_sized());
match *self {
Abi::Scalar(s) => Abi::Scalar(s.to_union()),
Abi::ScalarPair(s1, s2) => Abi::ScalarPair(s1.to_union(), s2.to_union()),
@@ -1531,6 +1526,16 @@ pub struct LayoutS {
pub align: AbiAndPrefAlign,
pub size: Size,
+
+ /// The largest alignment explicitly requested with `repr(align)` on this type or any field.
+ /// Only used on i686-windows, where the argument passing ABI is different when alignment is
+ /// requested, even if the requested alignment is equal to the natural alignment.
+ pub max_repr_align: Option<Align>,
+
+ /// The alignment the type would have, ignoring any `repr(align)` but including `repr(packed)`.
+ /// Only used on aarch64-linux, where the argument passing ABI ignores the requested alignment
+ /// in some cases.
+ pub unadjusted_abi_align: Align,
}
impl LayoutS {
@@ -1545,6 +1550,8 @@ impl LayoutS {
largest_niche,
size,
align,
+ max_repr_align: None,
+ unadjusted_abi_align: align.abi,
}
}
}
@@ -1554,7 +1561,16 @@ impl fmt::Debug for LayoutS {
// This is how `Layout` used to print before it become
// `Interned<LayoutS>`. We print it like this to avoid having to update
// expected output in a lot of tests.
- let LayoutS { size, align, abi, fields, largest_niche, variants } = self;
+ let LayoutS {
+ size,
+ align,
+ abi,
+ fields,
+ largest_niche,
+ variants,
+ max_repr_align,
+ unadjusted_abi_align,
+ } = self;
f.debug_struct("Layout")
.field("size", size)
.field("align", align)
@@ -1562,6 +1578,8 @@ impl fmt::Debug for LayoutS {
.field("fields", fields)
.field("largest_niche", largest_niche)
.field("variants", variants)
+ .field("max_repr_align", max_repr_align)
+ .field("unadjusted_abi_align", unadjusted_abi_align)
.finish()
}
}
@@ -1602,6 +1620,14 @@ impl<'a> Layout<'a> {
self.0.0.size
}
+ pub fn max_repr_align(self) -> Option<Align> {
+ self.0.0.max_repr_align
+ }
+
+ pub fn unadjusted_abi_align(self) -> Align {
+ self.0.0.unadjusted_abi_align
+ }
+
/// Whether the layout is from a type that implements [`std::marker::PointerLike`].
///
/// Currently, that means that the type is pointer-sized, pointer-aligned,