Rollup merge of #110610 - spastorino:smir-terminator, r=oli-obk
Add Terminator conversion from MIR to SMIR, part #1 This adds internal MIR TerminatorKind to SMIR Terminator conversion. r? ```@oli-obk```
This commit is contained in:
commit
77004eafea
@ -4093,6 +4093,7 @@ dependencies = [
|
||||
name = "rustc_smir"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_hir",
|
||||
"rustc_middle",
|
||||
"rustc_span",
|
||||
"tracing",
|
||||
|
@ -4,6 +4,7 @@ version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_middle = { path = "../rustc_middle", optional = true }
|
||||
rustc_span = { path = "../rustc_span", optional = true }
|
||||
tracing = "0.1"
|
||||
|
@ -93,10 +93,10 @@ fn rustc_statement_to_statement(
|
||||
}
|
||||
}
|
||||
|
||||
fn rustc_rvalue_to_rvalue(rvalue: &rustc_middle::mir::Rvalue<'_>) -> stable_mir::mir::Operand {
|
||||
fn rustc_rvalue_to_rvalue(rvalue: &rustc_middle::mir::Rvalue<'_>) -> stable_mir::mir::Rvalue {
|
||||
use rustc_middle::mir::Rvalue::*;
|
||||
match rvalue {
|
||||
Use(op) => rustc_op_to_op(op),
|
||||
Use(op) => stable_mir::mir::Rvalue::Use(rustc_op_to_op(op)),
|
||||
Repeat(_, _) => todo!(),
|
||||
Ref(_, _, _) => todo!(),
|
||||
ThreadLocalRef(_) => todo!(),
|
||||
@ -104,9 +104,15 @@ fn rustc_rvalue_to_rvalue(rvalue: &rustc_middle::mir::Rvalue<'_>) -> stable_mir:
|
||||
Len(_) => todo!(),
|
||||
Cast(_, _, _) => todo!(),
|
||||
BinaryOp(_, _) => todo!(),
|
||||
CheckedBinaryOp(_, _) => todo!(),
|
||||
CheckedBinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::CheckedBinaryOp(
|
||||
rustc_bin_op_to_bin_op(bin_op),
|
||||
rustc_op_to_op(&ops.0),
|
||||
rustc_op_to_op(&ops.1),
|
||||
),
|
||||
NullaryOp(_, _) => todo!(),
|
||||
UnaryOp(_, _) => todo!(),
|
||||
UnaryOp(un_op, op) => {
|
||||
stable_mir::mir::Rvalue::UnaryOp(rustc_un_op_to_un_op(un_op), rustc_op_to_op(op))
|
||||
}
|
||||
Discriminant(_) => todo!(),
|
||||
Aggregate(_, _) => todo!(),
|
||||
ShallowInitBox(_, _) => todo!(),
|
||||
@ -124,8 +130,10 @@ fn rustc_op_to_op(op: &rustc_middle::mir::Operand<'_>) -> stable_mir::mir::Opera
|
||||
}
|
||||
|
||||
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() }
|
||||
stable_mir::mir::Place {
|
||||
local: place.local.as_usize(),
|
||||
projection: format!("{:?}", place.projection),
|
||||
}
|
||||
}
|
||||
|
||||
fn rustc_unwind_to_unwind(
|
||||
@ -140,6 +148,96 @@ fn rustc_unwind_to_unwind(
|
||||
}
|
||||
}
|
||||
|
||||
fn rustc_assert_msg_to_msg<'tcx>(
|
||||
assert_message: &rustc_middle::mir::AssertMessage<'tcx>,
|
||||
) -> stable_mir::mir::AssertMessage {
|
||||
use rustc_middle::mir::AssertKind;
|
||||
match assert_message {
|
||||
AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck {
|
||||
len: rustc_op_to_op(len),
|
||||
index: rustc_op_to_op(index),
|
||||
},
|
||||
AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow(
|
||||
rustc_bin_op_to_bin_op(bin_op),
|
||||
rustc_op_to_op(op1),
|
||||
rustc_op_to_op(op2),
|
||||
),
|
||||
AssertKind::OverflowNeg(op) => {
|
||||
stable_mir::mir::AssertMessage::OverflowNeg(rustc_op_to_op(op))
|
||||
}
|
||||
AssertKind::DivisionByZero(op) => {
|
||||
stable_mir::mir::AssertMessage::DivisionByZero(rustc_op_to_op(op))
|
||||
}
|
||||
AssertKind::RemainderByZero(op) => {
|
||||
stable_mir::mir::AssertMessage::RemainderByZero(rustc_op_to_op(op))
|
||||
}
|
||||
AssertKind::ResumedAfterReturn(generator) => {
|
||||
stable_mir::mir::AssertMessage::ResumedAfterReturn(rustc_generator_to_generator(
|
||||
generator,
|
||||
))
|
||||
}
|
||||
AssertKind::ResumedAfterPanic(generator) => {
|
||||
stable_mir::mir::AssertMessage::ResumedAfterPanic(rustc_generator_to_generator(
|
||||
generator,
|
||||
))
|
||||
}
|
||||
AssertKind::MisalignedPointerDereference { required, found } => {
|
||||
stable_mir::mir::AssertMessage::MisalignedPointerDereference {
|
||||
required: rustc_op_to_op(required),
|
||||
found: rustc_op_to_op(found),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rustc_bin_op_to_bin_op(bin_op: &rustc_middle::mir::BinOp) -> stable_mir::mir::BinOp {
|
||||
use rustc_middle::mir::BinOp;
|
||||
match bin_op {
|
||||
BinOp::Add => stable_mir::mir::BinOp::Add,
|
||||
BinOp::Sub => stable_mir::mir::BinOp::Sub,
|
||||
BinOp::Mul => stable_mir::mir::BinOp::Mul,
|
||||
BinOp::Div => stable_mir::mir::BinOp::Div,
|
||||
BinOp::Rem => stable_mir::mir::BinOp::Rem,
|
||||
BinOp::BitXor => stable_mir::mir::BinOp::BitXor,
|
||||
BinOp::BitAnd => stable_mir::mir::BinOp::BitAnd,
|
||||
BinOp::BitOr => stable_mir::mir::BinOp::BitOr,
|
||||
BinOp::Shl => stable_mir::mir::BinOp::Shl,
|
||||
BinOp::Shr => stable_mir::mir::BinOp::Shr,
|
||||
BinOp::Eq => stable_mir::mir::BinOp::Eq,
|
||||
BinOp::Lt => stable_mir::mir::BinOp::Lt,
|
||||
BinOp::Le => stable_mir::mir::BinOp::Le,
|
||||
BinOp::Ne => stable_mir::mir::BinOp::Ne,
|
||||
BinOp::Ge => stable_mir::mir::BinOp::Ge,
|
||||
BinOp::Gt => stable_mir::mir::BinOp::Gt,
|
||||
BinOp::Offset => stable_mir::mir::BinOp::Offset,
|
||||
}
|
||||
}
|
||||
|
||||
fn rustc_un_op_to_un_op(unary_op: &rustc_middle::mir::UnOp) -> stable_mir::mir::UnOp {
|
||||
use rustc_middle::mir::UnOp;
|
||||
match unary_op {
|
||||
UnOp::Not => stable_mir::mir::UnOp::Not,
|
||||
UnOp::Neg => stable_mir::mir::UnOp::Neg,
|
||||
}
|
||||
}
|
||||
|
||||
fn rustc_generator_to_generator(
|
||||
generator: &rustc_hir::GeneratorKind,
|
||||
) -> stable_mir::mir::GeneratorKind {
|
||||
use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
|
||||
match generator {
|
||||
GeneratorKind::Async(async_gen) => {
|
||||
let async_gen = match async_gen {
|
||||
AsyncGeneratorKind::Block => stable_mir::mir::AsyncGeneratorKind::Block,
|
||||
AsyncGeneratorKind::Closure => stable_mir::mir::AsyncGeneratorKind::Closure,
|
||||
AsyncGeneratorKind::Fn => stable_mir::mir::AsyncGeneratorKind::Fn,
|
||||
};
|
||||
stable_mir::mir::GeneratorKind::Async(async_gen)
|
||||
}
|
||||
GeneratorKind::Gen => stable_mir::mir::GeneratorKind::Gen,
|
||||
}
|
||||
}
|
||||
|
||||
fn rustc_terminator_to_terminator(
|
||||
terminator: &rustc_middle::mir::Terminator<'_>,
|
||||
) -> stable_mir::mir::Terminator {
|
||||
@ -162,7 +260,11 @@ fn rustc_terminator_to_terminator(
|
||||
Terminate => Terminator::Abort,
|
||||
Return => Terminator::Return,
|
||||
Unreachable => Terminator::Unreachable,
|
||||
Drop { .. } => todo!(),
|
||||
Drop { place, target, unwind } => Terminator::Drop {
|
||||
place: rustc_place_to_place(place),
|
||||
target: target.as_usize(),
|
||||
unwind: rustc_unwind_to_unwind(unwind),
|
||||
},
|
||||
Call { func, args, destination, target, unwind, from_hir_call: _, fn_span: _ } => {
|
||||
Terminator::Call {
|
||||
func: rustc_op_to_op(func),
|
||||
@ -172,9 +274,15 @@ fn rustc_terminator_to_terminator(
|
||||
unwind: rustc_unwind_to_unwind(unwind),
|
||||
}
|
||||
}
|
||||
Assert { .. } => todo!(),
|
||||
Assert { cond, expected, msg, target, unwind } => Terminator::Assert {
|
||||
cond: rustc_op_to_op(cond),
|
||||
expected: *expected,
|
||||
msg: rustc_assert_msg_to_msg(msg),
|
||||
target: target.as_usize(),
|
||||
unwind: rustc_unwind_to_unwind(unwind),
|
||||
},
|
||||
Yield { .. } => todo!(),
|
||||
GeneratorDrop => todo!(),
|
||||
GeneratorDrop => Terminator::GeneratorDrop,
|
||||
FalseEdge { .. } => todo!(),
|
||||
FalseUnwind { .. } => todo!(),
|
||||
InlineAsm { .. } => todo!(),
|
||||
|
@ -26,7 +26,7 @@ pub enum Terminator {
|
||||
Drop {
|
||||
place: Place,
|
||||
target: usize,
|
||||
unwind: Option<usize>,
|
||||
unwind: UnwindAction,
|
||||
},
|
||||
Call {
|
||||
func: Operand,
|
||||
@ -38,10 +38,11 @@ pub enum Terminator {
|
||||
Assert {
|
||||
cond: Operand,
|
||||
expected: bool,
|
||||
msg: String,
|
||||
msg: AssertMessage,
|
||||
target: usize,
|
||||
cleanup: Option<usize>,
|
||||
unwind: UnwindAction,
|
||||
},
|
||||
GeneratorDrop,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -52,12 +53,72 @@ pub enum UnwindAction {
|
||||
Cleanup(usize),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum AssertMessage {
|
||||
BoundsCheck { len: Operand, index: Operand },
|
||||
Overflow(BinOp, Operand, Operand),
|
||||
OverflowNeg(Operand),
|
||||
DivisionByZero(Operand),
|
||||
RemainderByZero(Operand),
|
||||
ResumedAfterReturn(GeneratorKind),
|
||||
ResumedAfterPanic(GeneratorKind),
|
||||
MisalignedPointerDereference { required: Operand, found: Operand },
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum BinOp {
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Rem,
|
||||
BitXor,
|
||||
BitAnd,
|
||||
BitOr,
|
||||
Shl,
|
||||
Shr,
|
||||
Eq,
|
||||
Lt,
|
||||
Le,
|
||||
Ne,
|
||||
Ge,
|
||||
Gt,
|
||||
Offset,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum UnOp {
|
||||
Not,
|
||||
Neg,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum GeneratorKind {
|
||||
Async(AsyncGeneratorKind),
|
||||
Gen,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum AsyncGeneratorKind {
|
||||
Block,
|
||||
Closure,
|
||||
Fn,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Statement {
|
||||
Assign(Place, Operand),
|
||||
Assign(Place, Rvalue),
|
||||
Nop,
|
||||
}
|
||||
|
||||
// FIXME this is incomplete
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Rvalue {
|
||||
Use(Operand),
|
||||
CheckedBinaryOp(BinOp, Operand, Operand),
|
||||
UnaryOp(UnOp, Operand),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Operand {
|
||||
Copy(Place),
|
||||
@ -68,6 +129,7 @@ pub enum Operand {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Place {
|
||||
pub local: usize,
|
||||
pub projection: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -60,6 +60,24 @@ fn test_stable_mir(tcx: TyCtxt<'_>) {
|
||||
stable_mir::mir::Terminator::Call { .. } => {}
|
||||
other => panic!("{other:?}"),
|
||||
}
|
||||
|
||||
let drop = get_item(tcx, &items, (DefKind::Fn, "drop")).unwrap();
|
||||
let body = drop.body();
|
||||
assert_eq!(body.blocks.len(), 2);
|
||||
let block = &body.blocks[0];
|
||||
match &block.terminator {
|
||||
stable_mir::mir::Terminator::Drop { .. } => {}
|
||||
other => panic!("{other:?}"),
|
||||
}
|
||||
|
||||
let assert = get_item(tcx, &items, (DefKind::Fn, "assert")).unwrap();
|
||||
let body = assert.body();
|
||||
assert_eq!(body.blocks.len(), 2);
|
||||
let block = &body.blocks[0];
|
||||
match &block.terminator {
|
||||
stable_mir::mir::Terminator::Assert { .. } => {}
|
||||
other => panic!("{other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
// Use internal API to find a function in a crate.
|
||||
@ -131,6 +149,12 @@ fn generate_input(path: &str) -> std::io::Result<()> {
|
||||
let x_64 = foo::bar(x);
|
||||
let y_64 = foo::bar(y);
|
||||
x_64.wrapping_add(y_64)
|
||||
}}
|
||||
|
||||
pub fn drop(_: String) {{}}
|
||||
|
||||
pub fn assert(x: i32) -> i32 {{
|
||||
x + 1
|
||||
}}"#
|
||||
)?;
|
||||
Ok(())
|
||||
|
Loading…
x
Reference in New Issue
Block a user