Skip to content

Commit b70d706

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

File tree

6 files changed

+134
-6
lines changed

6 files changed

+134
-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: 34 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,15 @@ 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+
78+
// Test ADT representation options
79+
let repr_c_struct = visitor.adt_defs.iter().find(|def| def.name() == "ReprCStruct").unwrap();
80+
assert!(repr_c_struct.repr().is_c());
81+
7082
ControlFlow::Continue(())
7183
}
7284

@@ -138,6 +150,20 @@ fn get_item<'a>(
138150
items.iter().find(|crate_item| (item.0 == crate_item.kind()) && crate_item.name() == item.1)
139151
}
140152

153+
#[derive(Default)]
154+
struct AdtDefVisitor {
155+
adt_defs: HashSet<AdtDef>,
156+
}
157+
158+
impl MirVisitor for AdtDefVisitor {
159+
fn visit_ty(&mut self, ty: &Ty, _location: stable_mir::mir::visit::Location) {
160+
if let TyKind::RigidTy(RigidTy::Adt(adt, _)) = ty.kind() {
161+
self.adt_defs.insert(adt);
162+
}
163+
self.super_ty(ty)
164+
}
165+
}
166+
141167
/// This test will generate and analyze a dummy crate using the stable mir.
142168
/// For that, it will first write the dummy crate into a file.
143169
/// Then it will create a `StableMir` using custom arguments and then
@@ -147,7 +173,7 @@ fn main() {
147173
generate_input(&path).unwrap();
148174
let args = &[
149175
"rustc".to_string(),
150-
"--crate-type=lib".to_string(),
176+
"-Cpanic=abort".to_string(),
151177
"--crate-name".to_string(),
152178
CRATE_NAME.to_string(),
153179
path.to_string(),
@@ -185,6 +211,13 @@ fn generate_input(path: &str) -> std::io::Result<()> {
185211
// We only care about the signature.
186212
todo!()
187213
}}
214+
215+
fn main() {{
216+
#[repr(C)]
217+
struct ReprCStruct;
218+
219+
let _ = ReprCStruct;
220+
}}
188221
"#
189222
)?;
190223
Ok(())

0 commit comments

Comments
 (0)