Skip to content

Commit 05efc0f

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

File tree

6 files changed

+136
-6
lines changed

6 files changed

+136
-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: 37 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,37 @@ 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+
self.bits()
312+
}
313+
}
314+
315+
impl<'tcx> Stable<'tcx> for rustc_abi::IntegerType {
316+
type T = IntegerType;
317+
318+
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
319+
match self {
320+
rustc_abi::IntegerType::Pointer(signed) => IntegerType::Pointer(*signed),
321+
rustc_abi::IntegerType::Fixed(integer, signed) => {
322+
IntegerType::Fixed(integer.stable(tables), *signed)
323+
}
324+
}
325+
}
326+
}
327+
328+
impl<'tcx> Stable<'tcx> for rustc_abi::ReprOptions {
329+
type T = ReprOptions;
330+
331+
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
332+
ReprOptions {
333+
int: self.int.map(|int| int.stable(tables)),
334+
align: self.align.map(|align| align.stable(tables)),
335+
pack: self.pack.map(|pack| pack.stable(tables)),
336+
flags: self.flags.stable(tables),
337+
}
338+
}
339+
}

compiler/rustc_smir/src/stable_mir/abi.rs

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

456456
RiscvInterrupt,
457457
}
458+
459+
pub type ReprFlags = u8;
460+
461+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)]
462+
pub enum IntegerType {
463+
/// Pointer-sized integer type, i.e. `isize` and `usize`. The field shows signedness, e.g.
464+
/// `Pointer(true)` means `isize`.
465+
Pointer(bool),
466+
/// Fixed-sized integer type, e.g. `i8`, `u32`, `i128`. The bool field shows signedness, e.g.
467+
/// `Fixed(I8, false)` means `u8`.
468+
Fixed(IntegerLength, bool),
469+
}
470+
471+
/// Represntation options provided by the user
472+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)]
473+
pub struct ReprOptions {
474+
pub(crate) int: Option<IntegerType>,
475+
pub(crate) align: Option<Align>,
476+
pub(crate) pack: Option<Align>,
477+
pub(crate) flags: ReprFlags,
478+
}
479+
480+
impl ReprOptions {
481+
#[inline]
482+
fn contains_flags(&self, flags: rustc_abi::ReprFlags) -> bool {
483+
let self_flags = rustc_abi::ReprFlags::from_bits_retain(self.flags);
484+
self_flags.intersects(flags)
485+
}
486+
487+
#[inline]
488+
pub fn is_c(&self) -> bool {
489+
self.contains_flags(rustc_abi::ReprFlags::IS_C)
490+
}
491+
492+
#[inline]
493+
pub fn is_simd(&self) -> bool {
494+
self.contains_flags(rustc_abi::ReprFlags::IS_SIMD)
495+
}
496+
497+
#[inline]
498+
pub fn is_transparent(&self) -> bool {
499+
self.contains_flags(rustc_abi::ReprFlags::IS_TRANSPARENT)
500+
}
501+
}

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().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)