diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
commit | d1b2d29528b7794b41e66fc2136e395a02f8529b (patch) | |
tree | a4a17504b260206dec3cf55b2dca82929a348ac2 /compiler/rustc_abi/src | |
parent | Releasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-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.rs | 73 | ||||
-rw-r--r-- | compiler/rustc_abi/src/lib.rs | 54 |
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, |