diff options
Diffstat (limited to 'compiler/rustc_smir/src/rustc_smir/mod.rs')
-rw-r--r-- | compiler/rustc_smir/src/rustc_smir/mod.rs | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs new file mode 100644 index 000000000..4dad3c6bc --- /dev/null +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -0,0 +1,162 @@ +//! Module that implements what will become the rustc side of Stable MIR. +//! +//! This module is responsible for building Stable MIR components from internal components. +//! +//! This module is not intended to be invoked directly by users. It will eventually +//! become the public API of rustc that will be invoked by the `stable_mir` crate. +//! +//! For now, we are developing everything inside `rustc`, thus, we keep this module private. + +use crate::{ + rustc_internal::{crate_item, item_def_id}, + stable_mir::{self}, +}; +use rustc_middle::ty::{tls::with, TyCtxt}; +use rustc_span::def_id::{CrateNum, LOCAL_CRATE}; +use tracing::debug; + +/// Get information about the local crate. +pub fn local_crate() -> stable_mir::Crate { + with(|tcx| smir_crate(tcx, LOCAL_CRATE)) +} + +/// Retrieve a list of all external crates. +pub fn external_crates() -> Vec<stable_mir::Crate> { + with(|tcx| tcx.crates(()).iter().map(|crate_num| smir_crate(tcx, *crate_num)).collect()) +} + +/// Find a crate with the given name. +pub fn find_crate(name: &str) -> Option<stable_mir::Crate> { + with(|tcx| { + [LOCAL_CRATE].iter().chain(tcx.crates(()).iter()).find_map(|crate_num| { + let crate_name = tcx.crate_name(*crate_num).to_string(); + (name == crate_name).then(|| smir_crate(tcx, *crate_num)) + }) + }) +} + +/// Retrieve all items of the local crate that have a MIR associated with them. +pub fn all_local_items() -> stable_mir::CrateItems { + with(|tcx| tcx.mir_keys(()).iter().map(|item| crate_item(item.to_def_id())).collect()) +} + +pub fn entry_fn() -> Option<stable_mir::CrateItem> { + with(|tcx| Some(crate_item(tcx.entry_fn(())?.0))) +} + +/// Build a stable mir crate from a given crate number. +fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate { + let crate_name = tcx.crate_name(crate_num).to_string(); + let is_local = crate_num == LOCAL_CRATE; + debug!(?crate_name, ?crate_num, "smir_crate"); + stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local } +} + +pub fn mir_body(item: &stable_mir::CrateItem) -> stable_mir::mir::Body { + with(|tcx| { + let def_id = item_def_id(item); + let mir = tcx.optimized_mir(def_id); + stable_mir::mir::Body { + blocks: mir + .basic_blocks + .iter() + .map(|block| stable_mir::mir::BasicBlock { + terminator: rustc_terminator_to_terminator(block.terminator()), + statements: block.statements.iter().map(rustc_statement_to_statement).collect(), + }) + .collect(), + } + }) +} + +fn rustc_statement_to_statement( + s: &rustc_middle::mir::Statement<'_>, +) -> stable_mir::mir::Statement { + use rustc_middle::mir::StatementKind::*; + match &s.kind { + Assign(assign) => stable_mir::mir::Statement::Assign( + rustc_place_to_place(&assign.0), + rustc_rvalue_to_rvalue(&assign.1), + ), + FakeRead(_) => todo!(), + SetDiscriminant { .. } => todo!(), + Deinit(_) => todo!(), + StorageLive(_) => todo!(), + StorageDead(_) => todo!(), + Retag(_, _) => todo!(), + PlaceMention(_) => todo!(), + AscribeUserType(_, _) => todo!(), + Coverage(_) => todo!(), + Intrinsic(_) => todo!(), + ConstEvalCounter => todo!(), + Nop => stable_mir::mir::Statement::Nop, + } +} + +fn rustc_rvalue_to_rvalue(rvalue: &rustc_middle::mir::Rvalue<'_>) -> stable_mir::mir::Operand { + use rustc_middle::mir::Rvalue::*; + match rvalue { + Use(op) => rustc_op_to_op(op), + Repeat(_, _) => todo!(), + Ref(_, _, _) => todo!(), + ThreadLocalRef(_) => todo!(), + AddressOf(_, _) => todo!(), + Len(_) => todo!(), + Cast(_, _, _) => todo!(), + BinaryOp(_, _) => todo!(), + CheckedBinaryOp(_, _) => todo!(), + NullaryOp(_, _) => todo!(), + UnaryOp(_, _) => todo!(), + Discriminant(_) => todo!(), + Aggregate(_, _) => todo!(), + ShallowInitBox(_, _) => todo!(), + CopyForDeref(_) => todo!(), + } +} + +fn rustc_op_to_op(op: &rustc_middle::mir::Operand<'_>) -> stable_mir::mir::Operand { + use rustc_middle::mir::Operand::*; + match op { + Copy(place) => stable_mir::mir::Operand::Copy(rustc_place_to_place(place)), + Move(place) => stable_mir::mir::Operand::Move(rustc_place_to_place(place)), + Constant(c) => stable_mir::mir::Operand::Constant(c.to_string()), + } +} + +fn rustc_place_to_place(place: &rustc_middle::mir::Place<'_>) -> stable_mir::mir::Place { + assert_eq!(&place.projection[..], &[]); + stable_mir::mir::Place { local: place.local.as_usize() } +} + +fn rustc_terminator_to_terminator( + terminator: &rustc_middle::mir::Terminator<'_>, +) -> stable_mir::mir::Terminator { + use rustc_middle::mir::TerminatorKind::*; + use stable_mir::mir::Terminator; + match &terminator.kind { + Goto { target } => Terminator::Goto { target: target.as_usize() }, + SwitchInt { discr, targets } => Terminator::SwitchInt { + discr: rustc_op_to_op(discr), + targets: targets + .iter() + .map(|(value, target)| stable_mir::mir::SwitchTarget { + value, + target: target.as_usize(), + }) + .collect(), + otherwise: targets.otherwise().as_usize(), + }, + Resume => Terminator::Resume, + Terminate => Terminator::Abort, + Return => Terminator::Return, + Unreachable => Terminator::Unreachable, + Drop { .. } => todo!(), + Call { .. } => todo!(), + Assert { .. } => todo!(), + Yield { .. } => todo!(), + GeneratorDrop => todo!(), + FalseEdge { .. } => todo!(), + FalseUnwind { .. } => todo!(), + InlineAsm { .. } => todo!(), + } +} |