about summary refs log tree commit diff
diff options
context:
space:
mode:
authorErik Desjardins <erikdesjardins@users.noreply.github.com>2023-06-11 13:43:49 -0400
committerErik Desjardins <erikdesjardins@users.noreply.github.com>2023-07-10 19:19:39 -0400
commit00b3eca0dfab4ccebbfb6614b83235cc82f9245f (patch)
treea985425ec577fd3beaf124db9af85f18de99f299
parent65d11b5c6562c57d61bf0db88736da06b8b77423 (diff)
downloadrust-00b3eca0dfab4ccebbfb6614b83235cc82f9245f.tar.gz
rust-00b3eca0dfab4ccebbfb6614b83235cc82f9245f.zip
move has_repr to layout, handle repr(transparent) properly
-rw-r--r--compiler/rustc_abi/src/layout.rs14
-rw-r--r--compiler/rustc_abi/src/lib.rs13
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs10
-rw-r--r--compiler/rustc_target/src/abi/call/x86.rs9
-rw-r--r--compiler/rustc_target/src/abi/mod.rs8
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs5
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)