Skip to content

Commit

Permalink
Add Assert terminator to SMIR
Browse files Browse the repository at this point in the history
  • Loading branch information
spastorino committed May 5, 2023
1 parent 7dd59fc commit 4b85bea
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 11 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4090,6 +4090,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
118 changes: 111 additions & 7 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 Down Expand Up @@ -176,7 +274,13 @@ 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!(),
FalseEdge { .. } => todo!(),
Expand Down
67 changes: 64 additions & 3 deletions compiler/rustc_smir/src/stable_mir/mir/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ pub enum Terminator {
Assert {
cond: Operand,
expected: bool,
msg: String,
msg: AssertMessage,
target: usize,
cleanup: Option<usize>,
unwind: UnwindAction,
},
}

Expand All @@ -52,12 +52,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 +128,7 @@ pub enum Operand {
#[derive(Clone, Debug)]
pub struct Place {
pub local: usize,
pub projection: String,
}

#[derive(Clone, Debug)]
Expand Down
15 changes: 14 additions & 1 deletion tests/ui-fulldeps/stable-mir/crate-info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ fn test_stable_mir(tcx: TyCtxt<'_>) {
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 @@ -142,7 +151,11 @@ fn generate_input(path: &str) -> std::io::Result<()> {
x_64.wrapping_add(y_64)
}}
pub fn drop(_: String) {{}}"#
pub fn drop(_: String) {{}}
pub fn assert(x: i32) -> i32 {{
x + 1
}}"#
)?;
Ok(())
}

0 comments on commit 4b85bea

Please sign in to comment.