Adds decoration to the verifier errors. (#375)

* Adds decoration to the verifier errors.

example:

function %bad(i32) fast {
ebb0(v0: i32):
    brnz.i32 v0, ebb1
    return
    ^~~~~~

verifier inst1: Internal return not allowed with return_at_end=1

ebb1:
    trapz.i32 v0, user6
    return
}

Fixes #68
This commit is contained in:
Caroline Cullen
2018-06-28 10:17:27 -07:00
committed by Dan Gohman
parent c5aad1eb5f
commit 7bed3426a7
2 changed files with 88 additions and 8 deletions

View File

@@ -1,11 +1,15 @@
//! Utility routines for pretty-printing error messages.
use ir;
use ir::entities::Inst;
use ir::function::Function;
use isa::TargetIsa;
use result::CodegenError;
use std::fmt;
use std::fmt::Write;
use std::string::{String, ToString};
use verifier::VerifierError;
use write::decorate_function;
/// Pretty-print a verifier error.
pub fn pretty_verifier_error(
@@ -13,15 +17,52 @@ pub fn pretty_verifier_error(
isa: Option<&TargetIsa>,
err: &VerifierError,
) -> String {
let mut msg = err.to_string();
let mut w = String::new();
decorate_function(
&mut |w, func, isa, inst, indent| pretty_function_error(w, func, isa, inst, indent, err),
&mut w,
func,
isa,
).unwrap();
w
}
/// Pretty-print a function verifier error.
fn pretty_function_error(
w: &mut Write,
func: &Function,
isa: Option<&TargetIsa>,
cur_inst: Inst,
indent: usize,
err: &VerifierError,
) -> fmt::Result {
match err.location {
ir::entities::AnyEntity::Inst(inst) => {
write!(msg, "\n{}: {}\n\n", inst, func.dfg.display_inst(inst, isa)).unwrap()
if inst == cur_inst {
write!(
w,
"{1:0$}{2}\n",
indent,
"",
func.dfg.display_inst(cur_inst, isa)
)?;
write!(w, "{1:0$}{2}", indent, "", "^")?;
for _c in cur_inst.to_string().chars() {
write!(w, "~")?;
}
write!(w, "\n\nverifier {}\n\n", err.to_string())
} else {
write!(
w,
"{1:0$}{2}\n",
indent,
"",
func.dfg.display_inst(cur_inst, isa)
)
}
}
_ => msg.push('\n'),
_ => write!(w, "{}", "\n"),
}
write!(msg, "{}", func.display(isa)).unwrap();
msg
}
/// Pretty-print a Cretonne error.

View File

@@ -9,9 +9,39 @@ use packed_option::ReservedValue;
use std::fmt::{self, Write};
use std::string::String;
fn write_function_plain(
w: &mut Write,
func: &Function,
isa: Option<&TargetIsa>,
inst: Inst,
indent: usize,
) -> fmt::Result {
write_instruction(w, func, isa, inst, indent)?;
Ok(())
}
/// Write `func` to `w` as equivalent text.
/// Use `isa` to emit ISA-dependent annotations.
pub fn write_function(w: &mut Write, func: &Function, isa: Option<&TargetIsa>) -> fmt::Result {
decorate_function(
&mut |w, func, isa, inst, indent| write_function_plain(w, func, isa, inst, indent),
w,
func,
isa,
)
}
/// Writes 'func' to 'w' as text.
/// write_function_plain is passed as 'closure' to print instructions as text.
/// pretty_function_error is passed as 'closure' to add error decoration.
pub fn decorate_function<
WL: FnMut(&mut Write, &Function, Option<&TargetIsa>, Inst, usize) -> fmt::Result,
>(
closure: &mut WL,
w: &mut Write,
func: &Function,
isa: Option<&TargetIsa>,
) -> fmt::Result {
let regs = isa.map(TargetIsa::register_info);
let regs = regs.as_ref();
@@ -23,7 +53,7 @@ pub fn write_function(w: &mut Write, func: &Function, isa: Option<&TargetIsa>) -
if any {
writeln!(w)?;
}
write_ebb(w, func, isa, ebb)?;
decorate_ebb(closure, w, func, isa, ebb)?;
any = true;
}
writeln!(w, "}}")
@@ -141,7 +171,15 @@ pub fn write_ebb_header(
writeln!(w, "):")
}
pub fn write_ebb(w: &mut Write, func: &Function, isa: Option<&TargetIsa>, ebb: Ebb) -> fmt::Result {
pub fn decorate_ebb<
WL: FnMut(&mut Write, &Function, Option<&TargetIsa>, Inst, usize) -> fmt::Result,
>(
closure: &mut WL,
w: &mut Write,
func: &Function,
isa: Option<&TargetIsa>,
ebb: Ebb,
) -> fmt::Result {
// Indent all instructions if any encodings are present.
let indent = if func.encodings.is_empty() && func.srclocs.is_empty() {
4
@@ -151,8 +189,9 @@ pub fn write_ebb(w: &mut Write, func: &Function, isa: Option<&TargetIsa>, ebb: E
write_ebb_header(w, func, isa, ebb, indent)?;
for inst in func.layout.ebb_insts(ebb) {
write_instruction(w, func, isa, inst, indent)?;
closure(w, func, isa, inst, indent)?;
}
Ok(())
}