about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-06-11 07:45:07 +0000
committerbors <bors@rust-lang.org>2025-06-11 07:45:07 +0000
commit0a39445252ac076ef573bcacee63bbdc59497b52 (patch)
tree839fbf3a61ba5ad419db9bdb3fba0e623ab4cbb0
parent2b0274c71dba0e24370ebf65593da450e2e91868 (diff)
parentdabed3372c9f57398ac9a33f2c9d03ab3d4ab43f (diff)
downloadrust-0a39445252ac076ef573bcacee63bbdc59497b52.tar.gz
rust-0a39445252ac076ef573bcacee63bbdc59497b52.zip
Auto merge of #141942 - ShoyuVanilla:smir-repr, r=oli-obk
Implement representation options to smir

Resolves rust-lang/project-stable-mir#89
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs9
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/abi.rs45
-rw-r--r--compiler/rustc_smir/src/stable_mir/abi.rs35
-rw-r--r--compiler/rustc_smir/src/stable_mir/compiler_interface.rs7
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs5
-rw-r--r--tests/ui-fulldeps/stable-mir/check_abi.rs37
6 files changed, 132 insertions, 6 deletions
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index bac5c9066f1..ef8c88355f6 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -16,7 +16,7 @@ use rustc_middle::ty::{
 };
 use rustc_middle::{mir, ty};
 use rustc_span::def_id::LOCAL_CRATE;
-use stable_mir::abi::{FnAbi, Layout, LayoutShape};
+use stable_mir::abi::{FnAbi, Layout, LayoutShape, ReprOptions};
 use stable_mir::mir::alloc::GlobalAlloc;
 use stable_mir::mir::mono::{InstanceDef, StaticDef};
 use stable_mir::mir::{BinOp, Body, Place, UnOp};
@@ -397,6 +397,13 @@ impl<'tcx> SmirCtxt<'tcx> {
         tables.tcx.is_lang_item(def_id, LangItem::CStr)
     }
 
+    /// Returns the representation options for this ADT
+    pub fn adt_repr(&self, def: AdtDef) -> ReprOptions {
+        let mut tables = self.0.borrow_mut();
+        let tcx = tables.tcx;
+        def.internal(&mut *tables, tcx).repr().stable(&mut *tables)
+    }
+
     /// Retrieve the function signature for the given generic arguments.
     pub fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
         let mut tables = self.0.borrow_mut();
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
index 64901ee0502..46f1ca61cec 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
@@ -6,9 +6,9 @@ use rustc_abi::{ArmCall, CanonAbi, InterruptKind, X86Call};
 use rustc_middle::ty;
 use rustc_target::callconv;
 use stable_mir::abi::{
-    AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength, Layout,
-    LayoutShape, PassMode, Primitive, Scalar, TagEncoding, TyAndLayout, ValueAbi, VariantsShape,
-    WrappingRange,
+    AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength,
+    IntegerType, Layout, LayoutShape, PassMode, Primitive, ReprFlags, ReprOptions, Scalar,
+    TagEncoding, TyAndLayout, ValueAbi, VariantsShape, WrappingRange,
 };
 use stable_mir::opaque;
 use stable_mir::target::MachineSize as Size;
@@ -310,3 +310,42 @@ impl<'tcx> Stable<'tcx> for rustc_abi::WrappingRange {
         WrappingRange { start: self.start, end: self.end }
     }
 }
+
+impl<'tcx> Stable<'tcx> for rustc_abi::ReprFlags {
+    type T = ReprFlags;
+
+    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+        ReprFlags {
+            is_simd: self.intersects(Self::IS_SIMD),
+            is_c: self.intersects(Self::IS_C),
+            is_transparent: self.intersects(Self::IS_TRANSPARENT),
+            is_linear: self.intersects(Self::IS_LINEAR),
+        }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for rustc_abi::IntegerType {
+    type T = IntegerType;
+
+    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+        match self {
+            rustc_abi::IntegerType::Pointer(signed) => IntegerType::Pointer { is_signed: *signed },
+            rustc_abi::IntegerType::Fixed(integer, signed) => {
+                IntegerType::Fixed { length: integer.stable(tables), is_signed: *signed }
+            }
+        }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for rustc_abi::ReprOptions {
+    type T = ReprOptions;
+
+    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+        ReprOptions {
+            int: self.int.map(|int| int.stable(tables)),
+            align: self.align.map(|align| align.stable(tables)),
+            pack: self.pack.map(|pack| pack.stable(tables)),
+            flags: self.flags.stable(tables),
+        }
+    }
+}
diff --git a/compiler/rustc_smir/src/stable_mir/abi.rs b/compiler/rustc_smir/src/stable_mir/abi.rs
index 3842cb7e653..347c6ed16a2 100644
--- a/compiler/rustc_smir/src/stable_mir/abi.rs
+++ b/compiler/rustc_smir/src/stable_mir/abi.rs
@@ -455,3 +455,38 @@ pub enum CallConvention {
 
     RiscvInterrupt,
 }
+
+#[non_exhaustive]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)]
+pub struct ReprFlags {
+    pub is_simd: bool,
+    pub is_c: bool,
+    pub is_transparent: bool,
+    pub is_linear: bool,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)]
+pub enum IntegerType {
+    /// Pointer-sized integer type, i.e. `isize` and `usize`.
+    Pointer {
+        /// Signedness. e.g. `true` for `isize`
+        is_signed: bool,
+    },
+    /// Fixed-sized integer type, e.g. `i8`, `u32`, `i128`.
+    Fixed {
+        /// Length of this integer type. e.g. `IntegerLength::I8` for `u8`.
+        length: IntegerLength,
+        /// Signedness. e.g. `false` for `u8`
+        is_signed: bool,
+    },
+}
+
+/// Representation options provided by the user
+#[non_exhaustive]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)]
+pub struct ReprOptions {
+    pub int: Option<IntegerType>,
+    pub align: Option<Align>,
+    pub pack: Option<Align>,
+    pub flags: ReprFlags,
+}
diff --git a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs
index bb35e23a728..3967ad13eeb 100644
--- a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs
+++ b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs
@@ -6,7 +6,7 @@
 use std::cell::Cell;
 
 use rustc_smir::context::SmirCtxt;
-use stable_mir::abi::{FnAbi, Layout, LayoutShape};
+use stable_mir::abi::{FnAbi, Layout, LayoutShape, ReprOptions};
 use stable_mir::crate_def::Attribute;
 use stable_mir::mir::alloc::{AllocId, GlobalAlloc};
 use stable_mir::mir::mono::{Instance, InstanceDef, StaticDef};
@@ -200,6 +200,11 @@ impl<'tcx> SmirInterface<'tcx> {
         self.cx.adt_is_cstr(def)
     }
 
+    /// Returns the representation options for this ADT
+    pub(crate) fn adt_repr(&self, def: AdtDef) -> ReprOptions {
+        self.cx.adt_repr(def)
+    }
+
     /// Retrieve the function signature for the given generic arguments.
     pub(crate) fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
         self.cx.fn_sig(def, args)
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index e331e593471..4461b4ae125 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -9,6 +9,7 @@ use stable_mir::mir::mono::StaticDef;
 use stable_mir::target::MachineInfo;
 use stable_mir::{Filename, Opaque};
 
+use super::abi::ReprOptions;
 use super::mir::{Body, Mutability, Safety};
 use super::{DefId, Error, Symbol, with};
 use crate::stable_mir;
@@ -818,6 +819,10 @@ impl AdtDef {
     pub fn variant(&self, idx: VariantIdx) -> Option<VariantDef> {
         (idx.to_index() < self.num_variants()).then_some(VariantDef { idx, adt_def: *self })
     }
+
+    pub fn repr(&self) -> ReprOptions {
+        with(|cx| cx.adt_repr(*self))
+    }
 }
 
 /// Definition of a variant, which can be either a struct / union field or an enum variant.
diff --git a/tests/ui-fulldeps/stable-mir/check_abi.rs b/tests/ui-fulldeps/stable-mir/check_abi.rs
index 71edf813a7b..15ef583709b 100644
--- a/tests/ui-fulldeps/stable-mir/check_abi.rs
+++ b/tests/ui-fulldeps/stable-mir/check_abi.rs
@@ -21,10 +21,13 @@ use stable_mir::abi::{
     ArgAbi, CallConvention, FieldsShape, IntegerLength, PassMode, Primitive, Scalar, ValueAbi,
     VariantsShape,
 };
+use stable_mir::mir::MirVisitor;
 use stable_mir::mir::mono::Instance;
 use stable_mir::target::MachineInfo;
+use stable_mir::ty::{AdtDef, RigidTy, Ty, TyKind};
 use stable_mir::{CrateDef, CrateItem, CrateItems, ItemKind};
 use std::assert_matches::assert_matches;
+use std::collections::HashSet;
 use std::convert::TryFrom;
 use std::io::Write;
 use std::ops::ControlFlow;
@@ -67,6 +70,17 @@ fn test_stable_mir() -> ControlFlow<()> {
     assert!(ptr_variadic_fn_abi.c_variadic);
     assert_eq!(ptr_variadic_fn_abi.args.len(), 1);
 
+    let entry = stable_mir::entry_fn().unwrap();
+    let main_fn = Instance::try_from(entry).unwrap();
+    let mut visitor = AdtDefVisitor::default();
+    visitor.visit_body(&main_fn.body().unwrap());
+    let AdtDefVisitor { adt_defs } = visitor;
+    assert_eq!(adt_defs.len(), 1);
+
+    // Test ADT representation options
+    let repr_c_struct = adt_defs.iter().find(|def| def.trimmed_name() == "ReprCStruct").unwrap();
+    assert!(repr_c_struct.repr().flags.is_c);
+
     ControlFlow::Continue(())
 }
 
@@ -138,6 +152,20 @@ fn get_item<'a>(
     items.iter().find(|crate_item| (item.0 == crate_item.kind()) && crate_item.name() == item.1)
 }
 
+#[derive(Default)]
+struct AdtDefVisitor {
+    adt_defs: HashSet<AdtDef>,
+}
+
+impl MirVisitor for AdtDefVisitor {
+    fn visit_ty(&mut self, ty: &Ty, _location: stable_mir::mir::visit::Location) {
+        if let TyKind::RigidTy(RigidTy::Adt(adt, _)) = ty.kind() {
+            self.adt_defs.insert(adt);
+        }
+        self.super_ty(ty)
+    }
+}
+
 /// This test will generate and analyze a dummy crate using the stable mir.
 /// For that, it will first write the dummy crate into a file.
 /// Then it will create a `StableMir` using custom arguments and then
@@ -147,7 +175,7 @@ fn main() {
     generate_input(&path).unwrap();
     let args = &[
         "rustc".to_string(),
-        "--crate-type=lib".to_string(),
+        "-Cpanic=abort".to_string(),
         "--crate-name".to_string(),
         CRATE_NAME.to_string(),
         path.to_string(),
@@ -185,6 +213,13 @@ fn generate_input(path: &str) -> std::io::Result<()> {
             // We only care about the signature.
             todo!()
         }}
+
+        fn main() {{
+            #[repr(C)]
+            struct ReprCStruct;
+
+            let _s = ReprCStruct;
+        }}
         "#
     )?;
     Ok(())