Path: blob/main/cranelift/codegen/src/print_errors.rs
1693 views
//! Utility routines for pretty-printing error messages.12use crate::entity::SecondaryMap;3use crate::ir;4use crate::ir::entities::{AnyEntity, Block, Inst, Value};5use crate::ir::function::Function;6use crate::ir::pcc::Fact;7use crate::result::CodegenError;8use crate::verifier::{VerifierError, VerifierErrors};9use crate::write::{FuncWriter, PlainWriter, decorate_function};10use alloc::boxed::Box;11use alloc::string::{String, ToString};12use alloc::vec::Vec;13use core::fmt;14use core::fmt::Write;1516/// Pretty-print a verifier error.17pub fn pretty_verifier_error<'a>(18func: &ir::Function,19func_w: Option<Box<dyn FuncWriter + 'a>>,20errors: VerifierErrors,21) -> String {22let mut errors = errors.0;23let mut w = String::new();24let num_errors = errors.len();2526decorate_function(27&mut PrettyVerifierError(func_w.unwrap_or_else(|| Box::new(PlainWriter)), &mut errors),28&mut w,29func,30)31.unwrap();3233writeln!(34w,35"\n; {} verifier error{} detected (see above). Compilation aborted.",36num_errors,37if num_errors == 1 { "" } else { "s" }38)39.unwrap();4041w42}4344struct PrettyVerifierError<'a>(Box<dyn FuncWriter + 'a>, &'a mut Vec<VerifierError>);4546impl<'a> FuncWriter for PrettyVerifierError<'a> {47fn write_block_header(48&mut self,49w: &mut dyn Write,50func: &Function,51block: Block,52indent: usize,53) -> fmt::Result {54pretty_block_header_error(w, func, block, indent, &mut *self.0, self.1)55}5657fn write_instruction(58&mut self,59w: &mut dyn Write,60func: &Function,61aliases: &SecondaryMap<Value, Vec<Value>>,62inst: Inst,63indent: usize,64) -> fmt::Result {65pretty_instruction_error(w, func, aliases, inst, indent, &mut *self.0, self.1)66}6768fn write_entity_definition(69&mut self,70w: &mut dyn Write,71func: &Function,72entity: AnyEntity,73value: &dyn fmt::Display,74maybe_fact: Option<&Fact>,75) -> fmt::Result {76pretty_preamble_error(w, func, entity, value, maybe_fact, &mut *self.0, self.1)77}78}7980/// Pretty-print a function verifier error for a given block.81fn pretty_block_header_error(82w: &mut dyn Write,83func: &Function,84cur_block: Block,85indent: usize,86func_w: &mut dyn FuncWriter,87errors: &mut Vec<VerifierError>,88) -> fmt::Result {89let mut s = String::new();90func_w.write_block_header(&mut s, func, cur_block, indent)?;91write!(w, "{s}")?;9293// TODO: Use drain_filter here when it gets stabilized94let mut i = 0;95let mut printed_error = false;96while i != errors.len() {97match errors[i].location {98ir::entities::AnyEntity::Block(block) if block == cur_block => {99if !printed_error {100print_arrow(w, &s)?;101printed_error = true;102}103let err = errors.remove(i);104print_error(w, err)?;105}106_ => i += 1,107}108}109110if printed_error {111w.write_char('\n')?;112}113114Ok(())115}116117/// Pretty-print a function verifier error for a given instruction.118fn pretty_instruction_error(119w: &mut dyn Write,120func: &Function,121aliases: &SecondaryMap<Value, Vec<Value>>,122cur_inst: Inst,123indent: usize,124func_w: &mut dyn FuncWriter,125errors: &mut Vec<VerifierError>,126) -> fmt::Result {127let mut s = String::new();128func_w.write_instruction(&mut s, func, aliases, cur_inst, indent)?;129write!(w, "{s}")?;130131// TODO: Use drain_filter here when it gets stabilized132let mut i = 0;133let mut printed_error = false;134while i != errors.len() {135match errors[i].location {136ir::entities::AnyEntity::Inst(inst) if inst == cur_inst => {137if !printed_error {138print_arrow(w, &s)?;139printed_error = true;140}141let err = errors.remove(i);142print_error(w, err)?;143}144_ => i += 1,145}146}147148if printed_error {149w.write_char('\n')?;150}151152Ok(())153}154155fn pretty_preamble_error(156w: &mut dyn Write,157func: &Function,158entity: AnyEntity,159value: &dyn fmt::Display,160maybe_fact: Option<&Fact>,161func_w: &mut dyn FuncWriter,162errors: &mut Vec<VerifierError>,163) -> fmt::Result {164let mut s = String::new();165func_w.write_entity_definition(&mut s, func, entity, value, maybe_fact)?;166write!(w, "{s}")?;167168// TODO: Use drain_filter here when it gets stabilized169let mut i = 0;170let mut printed_error = false;171while i != errors.len() {172if entity == errors[i].location {173if !printed_error {174print_arrow(w, &s)?;175printed_error = true;176}177let err = errors.remove(i);178print_error(w, err)?;179} else {180i += 1181}182}183184if printed_error {185w.write_char('\n')?;186}187188Ok(())189}190191/// Prints:192/// ; ^~~~~~193fn print_arrow(w: &mut dyn Write, entity: &str) -> fmt::Result {194write!(w, ";")?;195196let indent = entity.len() - entity.trim_start().len();197if indent != 0 {198write!(w, "{1:0$}^", indent - 1, "")?;199}200201for _ in 0..entity.trim().len() - 1 {202write!(w, "~")?;203}204205writeln!(w)206}207208/// Prints:209/// ; error: [ERROR BODY]210fn print_error(w: &mut dyn Write, err: VerifierError) -> fmt::Result {211writeln!(w, "; error: {}", err.to_string())?;212Ok(())213}214215/// Pretty-print a Cranelift error.216pub fn pretty_error(func: &ir::Function, err: CodegenError) -> String {217if let CodegenError::Verifier(e) = err {218pretty_verifier_error(func, None, e)219} else {220err.to_string()221}222}223224225