diff options
| author | Erik Desjardins <erikdesjardins@users.noreply.github.com> | 2023-06-11 13:43:49 -0400 |
|---|---|---|
| committer | Erik Desjardins <erikdesjardins@users.noreply.github.com> | 2023-07-10 19:19:39 -0400 |
| commit | 00b3eca0dfab4ccebbfb6614b83235cc82f9245f (patch) | |
| tree | a985425ec577fd3beaf124db9af85f18de99f299 | |
| parent | 65d11b5c6562c57d61bf0db88736da06b8b77423 (diff) | |
| download | rust-00b3eca0dfab4ccebbfb6614b83235cc82f9245f.tar.gz rust-00b3eca0dfab4ccebbfb6614b83235cc82f9245f.zip | |
move has_repr to layout, handle repr(transparent) properly
| -rw-r--r-- | compiler/rustc_abi/src/layout.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_abi/src/lib.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/layout.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_target/src/abi/call/x86.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_target/src/abi/mod.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/layout.rs | 5 |
6 files changed, 34 insertions, 25 deletions
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index f6875d895d3..efae34e95df 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -40,6 +40,7 @@ pub trait LayoutCalculator { largest_niche, align, size, + has_repr_align: false, } } @@ -122,6 +123,7 @@ pub trait LayoutCalculator { largest_niche: None, align: dl.i8_align, size: Size::ZERO, + has_repr_align: false, } } @@ -422,6 +424,7 @@ pub trait LayoutCalculator { largest_niche, size, align, + has_repr_align: repr.align.is_some(), }; Some(TmpLayout { layout, variants: variant_layouts }) @@ -691,6 +694,7 @@ pub trait LayoutCalculator { abi, align, size, + has_repr_align: repr.align.is_some(), }; let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants }; @@ -809,6 +813,7 @@ pub trait LayoutCalculator { largest_niche: None, align, size: size.align_to(align.abi), + has_repr_align: repr.align.is_some(), }) } } @@ -1036,6 +1041,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 +1051,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 +1110,11 @@ fn univariant( if fields.iter().any(|f| f.abi().is_uninhabited()) { abi = Abi::Uninhabited; } + + let has_repr_align = repr.align.is_some() + || repr.transparent() + && layout_of_single_non_zst_field.map_or(false, |l| l.has_repr_align()); + Some(LayoutS { variants: Variants::Single { index: FIRST_VARIANT }, fields: FieldsShape::Arbitrary { offsets, memory_index }, @@ -1109,6 +1122,7 @@ fn univariant( largest_niche, align, size, + has_repr_align, }) } diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index e1b9987f578..4cf6289ae00 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1531,6 +1531,11 @@ pub struct LayoutS { pub align: AbiAndPrefAlign, pub size: Size, + + /// True if the alignment was explicitly requested with `repr(align)`. + /// Only used on i686-windows, where the argument passing ABI is different when alignment is + /// requested, even if the requested alignment is equal to or less than the natural alignment. + pub has_repr_align: bool, } impl LayoutS { @@ -1545,6 +1550,7 @@ impl LayoutS { largest_niche, size, align, + has_repr_align: false, } } } @@ -1554,7 +1560,7 @@ 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, has_repr_align } = self; f.debug_struct("Layout") .field("size", size) .field("align", align) @@ -1562,6 +1568,7 @@ impl fmt::Debug for LayoutS { .field("fields", fields) .field("largest_niche", largest_niche) .field("variants", variants) + .field("has_repr_align", has_repr_align) .finish() } } @@ -1602,6 +1609,10 @@ impl<'a> Layout<'a> { self.0.0.size } + pub fn has_repr_align(self) -> bool { + self.0.0.has_repr_align + } + /// Whether the layout is from a type that implements [`std::marker::PointerLike`]. /// /// Currently, that means that the type is pointer-sized, pointer-aligned, diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index dc116e616fa..cdf9cd8c809 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -755,6 +755,7 @@ where largest_niche: None, align: tcx.data_layout.i8_align, size: Size::ZERO, + has_repr_align: false, }) } @@ -1104,15 +1105,6 @@ where fn is_unit(this: TyAndLayout<'tcx>) -> bool { matches!(this.ty.kind(), ty::Tuple(list) if list.len() == 0) } - - fn repr_options(this: TyAndLayout<'tcx>) -> ReprOptions { - match *this.ty.kind() { - ty::Adt(def, ..) => def.repr(), - _ => { - bug!("TyAndLayout::repr_options({:?}): not applicable", this) - } - } - } } /// Calculates whether a function's ABI can unwind or not. diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs index dd52b3cb520..9d3f9413afd 100644 --- a/compiler/rustc_target/src/abi/call/x86.rs +++ b/compiler/rustc_target/src/abi/call/x86.rs @@ -63,8 +63,8 @@ where if t.is_like_msvc && arg.layout.is_adt() - && let Some(requested_align) = arg.layout.repr_options().align - && requested_align > align_4 + && arg.layout.has_repr_align + && arg.layout.align.abi > align_4 { // MSVC has special rules for overaligned arguments: https://reviews.llvm.org/D72114. // Summarized here: @@ -72,11 +72,6 @@ where // - For backwards compatibility, arguments with natural alignment > 4 are still passed // on stack (via `byval`). For example, this includes `double`, `int64_t`, // and structs containing them, provided they lack an explicit alignment attribute. - assert!(arg.layout.align.abi >= requested_align, - "abi alignment {:?} less than requested alignment {:?}", - arg.layout.align.abi, - requested_align - ); arg.make_indirect(); } else if arg.layout.is_aggregate() { // We need to compute the alignment of the `byval` argument. The rules can be found in diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index aecf8b339f0..589cd3cf96b 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -55,7 +55,6 @@ pub trait TyAbiInterface<'a, C>: Sized { fn is_never(this: TyAndLayout<'a, Self>) -> bool; fn is_tuple(this: TyAndLayout<'a, Self>) -> bool; fn is_unit(this: TyAndLayout<'a, Self>) -> bool; - fn repr_options(this: TyAndLayout<'a, Self>) -> ReprOptions; } impl<'a, Ty> TyAndLayout<'a, Ty> { @@ -126,13 +125,6 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { Ty::is_unit(self) } - pub fn repr_options<C>(self) -> ReprOptions - where - Ty: TyAbiInterface<'a, C>, - { - Ty::repr_options(self) - } - pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>) -> Size where Ty: TyAbiInterface<'a, C>, diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index b67cd96a734..f693263ac95 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -258,6 +258,7 @@ fn layout_of_uncached<'tcx>( largest_niche, align: element.align, size, + has_repr_align: false, }) } ty::Slice(element) => { @@ -269,6 +270,7 @@ fn layout_of_uncached<'tcx>( largest_niche: None, align: element.align, size: Size::ZERO, + has_repr_align: false, }) } ty::Str => tcx.mk_layout(LayoutS { @@ -278,6 +280,7 @@ fn layout_of_uncached<'tcx>( largest_niche: None, align: dl.i8_align, size: Size::ZERO, + has_repr_align: false, }), // Odd unit types. @@ -431,6 +434,7 @@ fn layout_of_uncached<'tcx>( largest_niche: e_ly.largest_niche, size, align, + has_repr_align: false, }) } @@ -879,6 +883,7 @@ fn generator_layout<'tcx>( largest_niche: prefix.largest_niche, size, align, + has_repr_align: false, }); debug!("generator layout ({:?}): {:#?}", ty, layout); Ok(layout) |
