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"
|
name = "rustc_smir"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"rustc_hir",
|
||||||
"rustc_middle",
|
"rustc_middle",
|
||||||
"rustc_span",
|
"rustc_span",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
@ -4,6 +4,7 @@ version = "0.0.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
rustc_hir = { path = "../rustc_hir" }
|
||||||
rustc_middle = { path = "../rustc_middle", optional = true }
|
rustc_middle = { path = "../rustc_middle", optional = true }
|
||||||
rustc_span = { path = "../rustc_span", optional = true }
|
rustc_span = { path = "../rustc_span", optional = true }
|
||||||
tracing = "0.1"
|
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::*;
|
use rustc_middle::mir::Rvalue::*;
|
||||||
match rvalue {
|
match rvalue {
|
||||||
Use(op) => rustc_op_to_op(op),
|
Use(op) => stable_mir::mir::Rvalue::Use(rustc_op_to_op(op)),
|
||||||
Repeat(_, _) => todo!(),
|
Repeat(_, _) => todo!(),
|
||||||
Ref(_, _, _) => todo!(),
|
Ref(_, _, _) => todo!(),
|
||||||
ThreadLocalRef(_) => todo!(),
|
ThreadLocalRef(_) => todo!(),
|
||||||
@ -104,9 +104,15 @@ fn rustc_rvalue_to_rvalue(rvalue: &rustc_middle::mir::Rvalue<'_>) -> stable_mir:
|
|||||||
Len(_) => todo!(),
|
Len(_) => todo!(),
|
||||||
Cast(_, _, _) => todo!(),
|
Cast(_, _, _) => todo!(),
|
||||||
BinaryOp(_, _) => 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!(),
|
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!(),
|
Discriminant(_) => todo!(),
|
||||||
Aggregate(_, _) => todo!(),
|
Aggregate(_, _) => todo!(),
|
||||||
ShallowInitBox(_, _) => 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 {
|
fn rustc_place_to_place(place: &rustc_middle::mir::Place<'_>) -> stable_mir::mir::Place {
|
||||||
assert_eq!(&place.projection[..], &[]);
|
stable_mir::mir::Place {
|
||||||
stable_mir::mir::Place { local: place.local.as_usize() }
|
local: place.local.as_usize(),
|
||||||
|
projection: format!("{:?}", place.projection),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rustc_unwind_to_unwind(
|
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(
|
fn rustc_terminator_to_terminator(
|
||||||
terminator: &rustc_middle::mir::Terminator<'_>,
|
terminator: &rustc_middle::mir::Terminator<'_>,
|
||||||
) -> stable_mir::mir::Terminator {
|
) -> stable_mir::mir::Terminator {
|
||||||
@ -162,7 +260,11 @@ fn rustc_terminator_to_terminator(
|
|||||||
Terminate => Terminator::Abort,
|
Terminate => Terminator::Abort,
|
||||||
Return => Terminator::Return,
|
Return => Terminator::Return,
|
||||||
Unreachable => Terminator::Unreachable,
|
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: _ } => {
|
Call { func, args, destination, target, unwind, from_hir_call: _, fn_span: _ } => {
|
||||||
Terminator::Call {
|
Terminator::Call {
|
||||||
func: rustc_op_to_op(func),
|
func: rustc_op_to_op(func),
|
||||||
@ -172,9 +274,15 @@ fn rustc_terminator_to_terminator(
|
|||||||
unwind: rustc_unwind_to_unwind(unwind),
|
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!(),
|
Yield { .. } => todo!(),
|
||||||
GeneratorDrop => todo!(),
|
GeneratorDrop => Terminator::GeneratorDrop,
|
||||||
FalseEdge { .. } => todo!(),
|
FalseEdge { .. } => todo!(),
|
||||||
FalseUnwind { .. } => todo!(),
|
FalseUnwind { .. } => todo!(),
|
||||||
InlineAsm { .. } => todo!(),
|
InlineAsm { .. } => todo!(),
|
||||||
|
@ -26,7 +26,7 @@ pub enum Terminator {
|
|||||||
Drop {
|
Drop {
|
||||||
place: Place,
|
place: Place,
|
||||||
target: usize,
|
target: usize,
|
||||||
unwind: Option<usize>,
|
unwind: UnwindAction,
|
||||||
},
|
},
|
||||||
Call {
|
Call {
|
||||||
func: Operand,
|
func: Operand,
|
||||||
@ -38,10 +38,11 @@ pub enum Terminator {
|
|||||||
Assert {
|
Assert {
|
||||||
cond: Operand,
|
cond: Operand,
|
||||||
expected: bool,
|
expected: bool,
|
||||||
msg: String,
|
msg: AssertMessage,
|
||||||
target: usize,
|
target: usize,
|
||||||
cleanup: Option<usize>,
|
unwind: UnwindAction,
|
||||||
},
|
},
|
||||||
|
GeneratorDrop,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -52,12 +53,72 @@ pub enum UnwindAction {
|
|||||||
Cleanup(usize),
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
Assign(Place, Operand),
|
Assign(Place, Rvalue),
|
||||||
Nop,
|
Nop,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME this is incomplete
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Rvalue {
|
||||||
|
Use(Operand),
|
||||||
|
CheckedBinaryOp(BinOp, Operand, Operand),
|
||||||
|
UnaryOp(UnOp, Operand),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Operand {
|
pub enum Operand {
|
||||||
Copy(Place),
|
Copy(Place),
|
||||||
@ -68,6 +129,7 @@ pub enum Operand {
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Place {
|
pub struct Place {
|
||||||
pub local: usize,
|
pub local: usize,
|
||||||
|
pub projection: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -60,6 +60,24 @@ fn test_stable_mir(tcx: TyCtxt<'_>) {
|
|||||||
stable_mir::mir::Terminator::Call { .. } => {}
|
stable_mir::mir::Terminator::Call { .. } => {}
|
||||||
other => panic!("{other:?}"),
|
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.
|
// 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 x_64 = foo::bar(x);
|
||||||
let y_64 = foo::bar(y);
|
let y_64 = foo::bar(y);
|
||||||
x_64.wrapping_add(y_64)
|
x_64.wrapping_add(y_64)
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub fn drop(_: String) {{}}
|
||||||
|
|
||||||
|
pub fn assert(x: i32) -> i32 {{
|
||||||
|
x + 1
|
||||||
}}"#
|
}}"#
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user