Skip to content

Commit

Permalink
Rollup merge of rust-lang#110610 - spastorino:smir-terminator, r=oli-obk
Browse files Browse the repository at this point in the history
Add Terminator conversion from MIR to SMIR, part #1

This adds internal MIR TerminatorKind to SMIR Terminator conversion.

r? `@oli-obk`
  • Loading branch information
matthiaskrgr authored May 5, 2023
2 parents 4b94c23 + 698acc6 commit ac712b4
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 13 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4093,6 +4093,7 @@ dependencies = [
name = "rustc_smir"
version = "0.0.0"
dependencies = [
"rustc_hir",
"rustc_middle",
"rustc_span",
"tracing",
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_smir/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
126 changes: 117 additions & 9 deletions compiler/rustc_smir/src/rustc_smir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,20 +93,26 @@ 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!(),
AddressOf(_, _) => todo!(),
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!(),
Expand All @@ -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(
Expand All @@ -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 {
Expand All @@ -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),
Expand All @@ -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!(),
Expand Down
70 changes: 66 additions & 4 deletions compiler/rustc_smir/src/stable_mir/mir/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub enum Terminator {
Drop {
place: Place,
target: usize,
unwind: Option<usize>,
unwind: UnwindAction,
},
Call {
func: Operand,
Expand All @@ -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)]
Expand All @@ -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),
Expand All @@ -68,6 +129,7 @@ pub enum Operand {
#[derive(Clone, Debug)]
pub struct Place {
pub local: usize,
pub projection: String,
}

#[derive(Clone, Debug)]
Expand Down
24 changes: 24 additions & 0 deletions tests/ui-fulldeps/stable-mir/crate-info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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(())
Expand Down

0 comments on commit ac712b4

Please sign in to comment.