Auto merge of #141942 - ShoyuVanilla:smir-repr, r=oli-obk
Implement representation options to smir Resolves rust-lang/project-stable-mir#89
This commit is contained in:
commit
0a39445252
6 changed files with 132 additions and 6 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue