summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_smir/src/rustc_smir/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_smir/src/rustc_smir/mod.rs')
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs162
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!(),
+ }
+}