blob: 0befff894ef31e6f28a4c9cd6df15a90116708cf [file] [log] [blame]
//! 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())
}
/// 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!(),
}
}