Skip to content

Commit dabed33

Browse files
committed
Implement representation options to smir
1 parent 2fc3dee commit dabed33

File tree

6 files changed

+132
-6
lines changed

6 files changed

+132
-6
lines changed

compiler/rustc_smir/src/rustc_smir/context.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_middle::ty::{
1616
};
1717
use rustc_middle::{mir, ty};
1818
use rustc_span::def_id::LOCAL_CRATE;
19-
use stable_mir::abi::{FnAbi, Layout, LayoutShape};
19+
use stable_mir::abi::{FnAbi, Layout, LayoutShape, ReprOptions};
2020
use stable_mir::mir::alloc::GlobalAlloc;
2121
use stable_mir::mir::mono::{InstanceDef, StaticDef};
2222
use stable_mir::mir::{BinOp, Body, Place, UnOp};
@@ -397,6 +397,13 @@ impl<'tcx> SmirCtxt<'tcx> {
397397
tables.tcx.is_lang_item(def_id, LangItem::CStr)
398398
}
399399

400+
/// Returns the representation options for this ADT
401+
pub fn adt_repr(&self, def: AdtDef) -> ReprOptions {
402+
let mut tables = self.0.borrow_mut();
403+
let tcx = tables.tcx;
404+
def.internal(&mut *tables, tcx).repr().stable(&mut *tables)
405+
}
406+
400407
/// Retrieve the function signature for the given generic arguments.
401408
pub fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
402409
let mut tables = self.0.borrow_mut();

compiler/rustc_smir/src/rustc_smir/convert/abi.rs

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
use rustc_middle::ty;
66
use rustc_target::callconv::{self, Conv};
77
use stable_mir::abi::{
8-
AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength, Layout,
9-
LayoutShape, PassMode, Primitive, Scalar, TagEncoding, TyAndLayout, ValueAbi, VariantsShape,
10-
WrappingRange,
8+
AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength,
9+
IntegerType, Layout, LayoutShape, PassMode, Primitive, ReprFlags, ReprOptions, Scalar,
10+
TagEncoding, TyAndLayout, ValueAbi, VariantsShape, WrappingRange,
1111
};
1212
use stable_mir::opaque;
1313
use stable_mir::target::MachineSize as Size;
@@ -303,3 +303,42 @@ impl<'tcx> Stable<'tcx> for rustc_abi::WrappingRange {
303303
WrappingRange { start: self.start, end: self.end }
304304
}
305305
}
306+
307+
impl<'tcx> Stable<'tcx> for rustc_abi::ReprFlags {
308+
type T = ReprFlags;
309+
310+
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
311+
ReprFlags {
312+
is_simd: self.intersects(Self::IS_SIMD),
313+
is_c: self.intersects(Self::IS_C),
314+
is_transparent: self.intersects(Self::IS_TRANSPARENT),
315+
is_linear: self.intersects(Self::IS_LINEAR),
316+
}
317+
}
318+
}
319+
320+
impl<'tcx> Stable<'tcx> for rustc_abi::IntegerType {
321+
type T = IntegerType;
322+
323+
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
324+
match self {
325+
rustc_abi::IntegerType::Pointer(signed) => IntegerType::Pointer { is_signed: *signed },
326+
rustc_abi::IntegerType::Fixed(integer, signed) => {
327+
IntegerType::Fixed { length: integer.stable(tables), is_signed: *signed }
328+
}
329+
}
330+
}
331+
}
332+
333+
impl<'tcx> Stable<'tcx> for rustc_abi::ReprOptions {
334+
type T = ReprOptions;
335+
336+
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
337+
ReprOptions {
338+
int: self.int.map(|int| int.stable(tables)),
339+
align: self.align.map(|align| align.stable(tables)),
340+
pack: self.pack.map(|pack| pack.stable(tables)),
341+
flags: self.flags.stable(tables),
342+
}
343+
}
344+
}

compiler/rustc_smir/src/stable_mir/abi.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,3 +455,38 @@ pub enum CallConvention {
455455

456456
RiscvInterrupt,
457457
}
458+
459+
#[non_exhaustive]
460+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)]
461+
pub struct ReprFlags {
462+
pub is_simd: bool,
463+
pub is_c: bool,
464+
pub is_transparent: bool,
465+
pub is_linear: bool,
466+
}
467+
468+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)]
469+
pub enum IntegerType {
470+
/// Pointer-sized integer type, i.e. `isize` and `usize`.
471+
Pointer {
472+
/// Signedness. e.g. `true` for `isize`
473+
is_signed: bool,
474+
},
475+
/// Fixed-sized integer type, e.g. `i8`, `u32`, `i128`.
476+
Fixed {
477+
/// Length of this integer type. e.g. `IntegerLength::I8` for `u8`.
478+
length: IntegerLength,
479+
/// Signedness. e.g. `false` for `u8`
480+
is_signed: bool,
481+
},
482+
}
483+
484+
/// Representation options provided by the user
485+
#[non_exhaustive]
486+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)]
487+
pub struct ReprOptions {
488+
pub int: Option<IntegerType>,
489+
pub align: Option<Align>,
490+
pub pack: Option<Align>,
491+
pub flags: ReprFlags,
492+
}

compiler/rustc_smir/src/stable_mir/compiler_interface.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use std::cell::Cell;
77

88
use rustc_smir::context::SmirCtxt;
9-
use stable_mir::abi::{FnAbi, Layout, LayoutShape};
9+
use stable_mir::abi::{FnAbi, Layout, LayoutShape, ReprOptions};
1010
use stable_mir::crate_def::Attribute;
1111
use stable_mir::mir::alloc::{AllocId, GlobalAlloc};
1212
use stable_mir::mir::mono::{Instance, InstanceDef, StaticDef};
@@ -200,6 +200,11 @@ impl<'tcx> SmirInterface<'tcx> {
200200
self.cx.adt_is_cstr(def)
201201
}
202202

203+
/// Returns the representation options for this ADT
204+
pub(crate) fn adt_repr(&self, def: AdtDef) -> ReprOptions {
205+
self.cx.adt_repr(def)
206+
}
207+
203208
/// Retrieve the function signature for the given generic arguments.
204209
pub(crate) fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
205210
self.cx.fn_sig(def, args)

compiler/rustc_smir/src/stable_mir/ty.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use stable_mir::mir::mono::StaticDef;
99
use stable_mir::target::MachineInfo;
1010
use stable_mir::{Filename, Opaque};
1111

12+
use super::abi::ReprOptions;
1213
use super::mir::{Body, Mutability, Safety};
1314
use super::{DefId, Error, Symbol, with};
1415
use crate::stable_mir;
@@ -818,6 +819,10 @@ impl AdtDef {
818819
pub fn variant(&self, idx: VariantIdx) -> Option<VariantDef> {
819820
(idx.to_index() < self.num_variants()).then_some(VariantDef { idx, adt_def: *self })
820821
}
822+
823+
pub fn repr(&self) -> ReprOptions {
824+
with(|cx| cx.adt_repr(*self))
825+
}
821826
}
822827

823828
/// Definition of a variant, which can be either a struct / union field or an enum variant.

tests/ui-fulldeps/stable-mir/check_abi.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@ use stable_mir::abi::{
2121
ArgAbi, CallConvention, FieldsShape, IntegerLength, PassMode, Primitive, Scalar, ValueAbi,
2222
VariantsShape,
2323
};
24+
use stable_mir::mir::MirVisitor;
2425
use stable_mir::mir::mono::Instance;
2526
use stable_mir::target::MachineInfo;
27+
use stable_mir::ty::{AdtDef, RigidTy, Ty, TyKind};
2628
use stable_mir::{CrateDef, CrateItem, CrateItems, ItemKind};
2729
use std::assert_matches::assert_matches;
30+
use std::collections::HashSet;
2831
use std::convert::TryFrom;
2932
use std::io::Write;
3033
use std::ops::ControlFlow;
@@ -67,6 +70,17 @@ fn test_stable_mir() -> ControlFlow<()> {
6770
assert!(ptr_variadic_fn_abi.c_variadic);
6871
assert_eq!(ptr_variadic_fn_abi.args.len(), 1);
6972

73+
let entry = stable_mir::entry_fn().unwrap();
74+
let main_fn = Instance::try_from(entry).unwrap();
75+
let mut visitor = AdtDefVisitor::default();
76+
visitor.visit_body(&main_fn.body().unwrap());
77+
let AdtDefVisitor { adt_defs } = visitor;
78+
assert_eq!(adt_defs.len(), 1);
79+
80+
// Test ADT representation options
81+
let repr_c_struct = adt_defs.iter().find(|def| def.trimmed_name() == "ReprCStruct").unwrap();
82+
assert!(repr_c_struct.repr().flags.is_c);
83+
7084
ControlFlow::Continue(())
7185
}
7286

@@ -138,6 +152,20 @@ fn get_item<'a>(
138152
items.iter().find(|crate_item| (item.0 == crate_item.kind()) && crate_item.name() == item.1)
139153
}
140154

155+
#[derive(Default)]
156+
struct AdtDefVisitor {
157+
adt_defs: HashSet<AdtDef>,
158+
}
159+
160+
impl MirVisitor for AdtDefVisitor {
161+
fn visit_ty(&mut self, ty: &Ty, _location: stable_mir::mir::visit::Location) {
162+
if let TyKind::RigidTy(RigidTy::Adt(adt, _)) = ty.kind() {
163+
self.adt_defs.insert(adt);
164+
}
165+
self.super_ty(ty)
166+
}
167+
}
168+
141169
/// This test will generate and analyze a dummy crate using the stable mir.
142170
/// For that, it will first write the dummy crate into a file.
143171
/// Then it will create a `StableMir` using custom arguments and then
@@ -147,7 +175,7 @@ fn main() {
147175
generate_input(&path).unwrap();
148176
let args = &[
149177
"rustc".to_string(),
150-
"--crate-type=lib".to_string(),
178+
"-Cpanic=abort".to_string(),
151179
"--crate-name".to_string(),
152180
CRATE_NAME.to_string(),
153181
path.to_string(),
@@ -185,6 +213,13 @@ fn generate_input(path: &str) -> std::io::Result<()> {
185213
// We only care about the signature.
186214
todo!()
187215
}}
216+
217+
fn main() {{
218+
#[repr(C)]
219+
struct ReprCStruct;
220+
221+
let _s = ReprCStruct;
222+
}}
188223
"#
189224
)?;
190225
Ok(())

0 commit comments

Comments
 (0)