Skip to content

Commit

Permalink
add pretty_terminator
Browse files Browse the repository at this point in the history
  • Loading branch information
ouz-a committed Nov 22, 2023
1 parent cc4bb0d commit 8b971ee
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 2 deletions.
2 changes: 1 addition & 1 deletion compiler/stable_mir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ impl std::fmt::Display for Opaque {

impl std::fmt::Debug for Opaque {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.0)
write!(f, "{}", self.0)
}
}

Expand Down
3 changes: 2 additions & 1 deletion compiler/stable_mir/src/mir/body.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::mir::pretty::{function_body, pretty_statement};
use crate::mir::pretty::{function_body, pretty_statement, pretty_terminator};
use crate::ty::{
AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
};
Expand Down Expand Up @@ -83,6 +83,7 @@ impl Body {
Ok(())
})
.collect::<Vec<_>>();
writeln!(w, "{}", pretty_terminator(&block.terminator.kind))?;
writeln!(w, " }}").unwrap();
Ok(())
})
Expand Down
131 changes: 131 additions & 0 deletions compiler/stable_mir/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use crate::mir::{Operand, Rvalue, StatementKind};
use crate::ty::{DynKind, FloatTy, IntTy, RigidTy, TyKind, UintTy};
use crate::{with, Body, CrateItem, Mutability};

use super::{AssertMessage, BinOp, TerminatorKind};

pub fn function_name(item: CrateItem) -> String {
let mut pretty_name = String::new();
let body = item.body();
Expand Down Expand Up @@ -69,6 +71,135 @@ pub fn pretty_statement(statement: &StatementKind) -> String {
pretty
}

pub fn pretty_terminator(terminator: &TerminatorKind) -> String {
let mut pretty = String::new();
match terminator {
TerminatorKind::Goto { .. } => format!(" goto"),
TerminatorKind::SwitchInt { discr, .. } => {
format!(" switch({})", pretty_operand(discr))
}
TerminatorKind::Resume => format!(" resume"),
TerminatorKind::Abort => format!(" abort"),
TerminatorKind::Return => format!(" return"),
TerminatorKind::Unreachable => format!(" unreachable"),
TerminatorKind::Drop { place, .. } => format!(" drop({:?})", place.local),
TerminatorKind::Call { func, args, destination, .. } => {
pretty.push_str(" ");
pretty.push_str(format!("{} = ", destination.local).as_str());
pretty.push_str(&pretty_operand(func));
pretty.push_str("(");
args.iter().enumerate().for_each(|(i, arg)| {
if i > 0 {
pretty.push_str(", ");
}
pretty.push_str(&pretty_operand(arg));
});
pretty.push_str(")");
pretty
}
TerminatorKind::Assert { cond, expected, msg, target: _, unwind: _ } => {
pretty.push_str(" assert(");
if !expected {
pretty.push_str("!");
}
pretty.push_str(&pretty_operand(cond));
pretty.push_str(&pretty_assert_message(msg));
pretty.push_str(")");
pretty
}
TerminatorKind::CoroutineDrop => format!(" coroutine_drop"),
TerminatorKind::InlineAsm { .. } => todo!(),
}
}

pub fn pretty_assert_message(msg: &AssertMessage) -> String {
let mut pretty = String::new();
match msg {
AssertMessage::BoundsCheck { len, index } => {
let pretty_len = pretty_operand(len);
let pretty_index = pretty_operand(index);
pretty.push_str(format!("\"index out of bounds: the length is {{}} but the index is {{}}\", {pretty_len}, {pretty_index}").as_str());
pretty
}
AssertMessage::Overflow(BinOp::Add, l, r) => {
let pretty_l = pretty_operand(l);
let pretty_r = pretty_operand(r);
pretty.push_str(format!("\"attempt to compute `{{}} + {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
pretty
}
AssertMessage::Overflow(BinOp::Sub, l, r) => {
let pretty_l = pretty_operand(l);
let pretty_r = pretty_operand(r);
pretty.push_str(format!("\"attempt to compute `{{}} - {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
pretty
}
AssertMessage::Overflow(BinOp::Mul, l, r) => {
let pretty_l = pretty_operand(l);
let pretty_r = pretty_operand(r);
pretty.push_str(format!("\"attempt to compute `{{}} * {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
pretty
}
AssertMessage::Overflow(BinOp::Div, l, r) => {
let pretty_l = pretty_operand(l);
let pretty_r = pretty_operand(r);
pretty.push_str(format!("\"attempt to compute `{{}} / {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
pretty
}
AssertMessage::Overflow(BinOp::Rem, l, r) => {
let pretty_l = pretty_operand(l);
let pretty_r = pretty_operand(r);
pretty.push_str(format!("\"attempt to compute `{{}} % {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
pretty
}
AssertMessage::Overflow(BinOp::Shr, _, r) => {
let pretty_r = pretty_operand(r);
pretty.push_str(
format!("\"attempt to shift right by `{{}}`, which would overflow\", {pretty_r}")
.as_str(),
);
pretty
}
AssertMessage::Overflow(BinOp::Shl, _, r) => {
let pretty_r = pretty_operand(r);
pretty.push_str(
format!("\"attempt to shift left by `{{}}`, which would overflow\", {pretty_r}")
.as_str(),
);
pretty
}
AssertMessage::OverflowNeg(op) => {
let pretty_op = pretty_operand(op);
pretty.push_str(
format!("\"attempt to negate `{{}}`, which would overflow\", {pretty_op}").as_str(),
);
pretty
}
AssertMessage::DivisionByZero(op) => {
let pretty_op = pretty_operand(op);
pretty.push_str(format!("\"attempt to divide `{{}}` by zero\", {pretty_op}").as_str());
pretty
}
AssertMessage::RemainderByZero(op) => {
let pretty_op = pretty_operand(op);
pretty.push_str(
format!("\"attempt to calculate the remainder of `{{}}` with a divisor of zero\", {pretty_op}").as_str(),
);
pretty
}
AssertMessage::ResumedAfterReturn(_) => {
format!("attempt to resume a generator after completion")
}
AssertMessage::ResumedAfterPanic(_) => format!("attempt to resume a panicked generator"),
AssertMessage::MisalignedPointerDereference { required, found } => {
let pretty_required = pretty_operand(required);
let pretty_found = pretty_operand(found);
pretty.push_str(format!("\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\",{pretty_required}, {pretty_found}").as_str());
pretty
}
_ => todo!(),
}
}

pub fn pretty_operand(operand: &Operand) -> String {
let mut pretty = String::new();
match operand {
Expand Down

0 comments on commit 8b971ee

Please sign in to comment.