summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_target/src/abi/mod.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_target/src/abi/mod.rs
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_target/src/abi/mod.rs')
-rw-r--r--compiler/rustc_target/src/abi/mod.rs117
1 files changed, 113 insertions, 4 deletions
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index 74fe98920..b00567e87 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -1,3 +1,4 @@
+use rustc_data_structures::intern::Interned;
pub use Integer::*;
pub use Primitive::*;
@@ -18,6 +19,111 @@ impl ToJson for Endian {
}
}
+rustc_index::newtype_index! {
+ /// The *source-order* index of a field in a variant.
+ ///
+ /// This is how most code after type checking refers to fields, rather than
+ /// using names (as names have hygiene complications and more complex lookup).
+ ///
+ /// Particularly for `repr(Rust)` types, this may not be the same as *layout* order.
+ /// (It is for `repr(C)` `struct`s, however.)
+ ///
+ /// For example, in the following types,
+ /// ```rust
+ /// # enum Never {}
+ /// # #[repr(u16)]
+ /// enum Demo1 {
+ /// Variant0 { a: Never, b: i32 } = 100,
+ /// Variant1 { c: u8, d: u64 } = 10,
+ /// }
+ /// struct Demo2 { e: u8, f: u16, g: u8 }
+ /// ```
+ /// `b` is `FieldIdx(1)` in `VariantIdx(0)`,
+ /// `d` is `FieldIdx(1)` in `VariantIdx(1)`, and
+ /// `f` is `FieldIdx(1)` in `VariantIdx(0)`.
+ #[derive(HashStable_Generic)]
+ pub struct FieldIdx {}
+}
+
+rustc_index::newtype_index! {
+ /// The *source-order* index of a variant in a type.
+ ///
+ /// For enums, these are always `0..variant_count`, regardless of any
+ /// custom discriminants that may have been defined, and including any
+ /// variants that may end up uninhabited due to field types. (Some of the
+ /// variants may not be present in a monomorphized ABI [`Variants`], but
+ /// those skipped variants are always counted when determining the *index*.)
+ ///
+ /// `struct`s, `tuples`, and `unions`s are considered to have a single variant
+ /// with variant index zero, aka [`FIRST_VARIANT`].
+ #[derive(HashStable_Generic)]
+ pub struct VariantIdx {
+ /// Equivalent to `VariantIdx(0)`.
+ const FIRST_VARIANT = 0;
+ }
+}
+#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
+#[rustc_pass_by_value]
+pub struct Layout<'a>(pub Interned<'a, LayoutS<FieldIdx, VariantIdx>>);
+
+impl<'a> fmt::Debug for Layout<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // See comment on `<LayoutS as Debug>::fmt` above.
+ self.0.0.fmt(f)
+ }
+}
+
+impl<'a> Deref for Layout<'a> {
+ type Target = &'a LayoutS<FieldIdx, VariantIdx>;
+ fn deref(&self) -> &&'a LayoutS<FieldIdx, VariantIdx> {
+ &self.0.0
+ }
+}
+
+impl<'a> Layout<'a> {
+ pub fn fields(self) -> &'a FieldsShape<FieldIdx> {
+ &self.0.0.fields
+ }
+
+ pub fn variants(self) -> &'a Variants<FieldIdx, VariantIdx> {
+ &self.0.0.variants
+ }
+
+ pub fn abi(self) -> Abi {
+ self.0.0.abi
+ }
+
+ pub fn largest_niche(self) -> Option<Niche> {
+ self.0.0.largest_niche
+ }
+
+ pub fn align(self) -> AbiAndPrefAlign {
+ self.0.0.align
+ }
+
+ pub fn size(self) -> Size {
+ 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,
+ /// and has a scalar ABI.
+ pub fn is_pointer_like(self, data_layout: &TargetDataLayout) -> bool {
+ self.size() == data_layout.pointer_size
+ && self.align().abi == data_layout.pointer_align.abi
+ && matches!(self.abi(), Abi::Scalar(..))
+ }
+}
+
/// The layout of a type, alongside the type itself.
/// Provides various type traversal APIs (e.g., recursing into fields).
///
@@ -42,8 +148,8 @@ impl<'a, Ty: fmt::Display> fmt::Debug for TyAndLayout<'a, Ty> {
}
impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
- type Target = &'a LayoutS;
- fn deref(&self) -> &&'a LayoutS {
+ type Target = &'a LayoutS<FieldIdx, VariantIdx>;
+ fn deref(&self) -> &&'a LayoutS<FieldIdx, VariantIdx> {
&self.layout.0.0
}
}
@@ -144,14 +250,17 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
Ty::is_transparent(self)
}
- pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>) -> Size
+ pub fn offset_of_subfield<C, I>(self, cx: &C, indices: I) -> Size
where
Ty: TyAbiInterface<'a, C>,
+ I: Iterator<Item = (VariantIdx, FieldIdx)>,
{
let mut layout = self;
let mut offset = Size::ZERO;
- for index in indices {
+ for (variant, field) in indices {
+ layout = layout.for_variant(cx, variant);
+ let index = field.index();
offset += layout.fields.offset(index);
layout = layout.field(cx, index);
assert!(