1747ad3c4Slazypassion //! Utility routines for pretty-printing error messages. 2747ad3c4Slazypassion 3747ad3c4Slazypassion use crate::entity::SecondaryMap; 4747ad3c4Slazypassion use crate::ir; 5747ad3c4Slazypassion use crate::ir::entities::{AnyEntity, Ebb, Inst, Value}; 6747ad3c4Slazypassion use crate::ir::function::Function; 7747ad3c4Slazypassion use crate::isa::TargetIsa; 8747ad3c4Slazypassion use crate::result::CodegenError; 9747ad3c4Slazypassion use crate::verifier::{VerifierError, VerifierErrors}; 10747ad3c4Slazypassion use crate::write::{decorate_function, FuncWriter, PlainWriter}; 1110e226f9Sbjorn3 use alloc::boxed::Box; 1210e226f9Sbjorn3 use alloc::string::{String, ToString}; 1310e226f9Sbjorn3 use alloc::vec::Vec; 14*bb8fa40eSbjorn3 use core::fmt; 15*bb8fa40eSbjorn3 use core::fmt::Write; 16747ad3c4Slazypassion 17747ad3c4Slazypassion /// Pretty-print a verifier error. 18747ad3c4Slazypassion pub fn pretty_verifier_error<'a>( 19747ad3c4Slazypassion func: &ir::Function, 20d7d48d5cSBenjamin Bouvier isa: Option<&dyn TargetIsa>, 21d7d48d5cSBenjamin Bouvier func_w: Option<Box<dyn FuncWriter + 'a>>, 22747ad3c4Slazypassion errors: VerifierErrors, 23747ad3c4Slazypassion ) -> String { 24747ad3c4Slazypassion let mut errors = errors.0; 25747ad3c4Slazypassion let mut w = String::new(); 26747ad3c4Slazypassion let num_errors = errors.len(); 27747ad3c4Slazypassion 28747ad3c4Slazypassion decorate_function( 29747ad3c4Slazypassion &mut PrettyVerifierError(func_w.unwrap_or_else(|| Box::new(PlainWriter)), &mut errors), 30747ad3c4Slazypassion &mut w, 31747ad3c4Slazypassion func, 328f95c517SYury Delendik &isa.into(), 33747ad3c4Slazypassion ) 34747ad3c4Slazypassion .unwrap(); 35747ad3c4Slazypassion 36747ad3c4Slazypassion writeln!( 37747ad3c4Slazypassion w, 38747ad3c4Slazypassion "\n; {} verifier error{} detected (see above). Compilation aborted.", 39747ad3c4Slazypassion num_errors, 40747ad3c4Slazypassion if num_errors == 1 { "" } else { "s" } 41747ad3c4Slazypassion ) 42747ad3c4Slazypassion .unwrap(); 43747ad3c4Slazypassion 44747ad3c4Slazypassion w 45747ad3c4Slazypassion } 46747ad3c4Slazypassion 47d7d48d5cSBenjamin Bouvier struct PrettyVerifierError<'a>(Box<dyn FuncWriter + 'a>, &'a mut Vec<VerifierError>); 48747ad3c4Slazypassion 49747ad3c4Slazypassion impl<'a> FuncWriter for PrettyVerifierError<'a> { 50747ad3c4Slazypassion fn write_ebb_header( 51747ad3c4Slazypassion &mut self, 52d7d48d5cSBenjamin Bouvier w: &mut dyn Write, 53747ad3c4Slazypassion func: &Function, 54d7d48d5cSBenjamin Bouvier isa: Option<&dyn TargetIsa>, 55747ad3c4Slazypassion ebb: Ebb, 56747ad3c4Slazypassion indent: usize, 57747ad3c4Slazypassion ) -> fmt::Result { 58747ad3c4Slazypassion pretty_ebb_header_error(w, func, isa, ebb, indent, &mut *self.0, self.1) 59747ad3c4Slazypassion } 60747ad3c4Slazypassion 61747ad3c4Slazypassion fn write_instruction( 62747ad3c4Slazypassion &mut self, 63d7d48d5cSBenjamin Bouvier w: &mut dyn Write, 64747ad3c4Slazypassion func: &Function, 65747ad3c4Slazypassion aliases: &SecondaryMap<Value, Vec<Value>>, 66d7d48d5cSBenjamin Bouvier isa: Option<&dyn TargetIsa>, 67747ad3c4Slazypassion inst: Inst, 68747ad3c4Slazypassion indent: usize, 69747ad3c4Slazypassion ) -> fmt::Result { 70747ad3c4Slazypassion pretty_instruction_error(w, func, aliases, isa, inst, indent, &mut *self.0, self.1) 71747ad3c4Slazypassion } 72747ad3c4Slazypassion 73747ad3c4Slazypassion fn write_entity_definition( 74747ad3c4Slazypassion &mut self, 75d7d48d5cSBenjamin Bouvier w: &mut dyn Write, 76747ad3c4Slazypassion func: &Function, 77747ad3c4Slazypassion entity: AnyEntity, 78d7d48d5cSBenjamin Bouvier value: &dyn fmt::Display, 79747ad3c4Slazypassion ) -> fmt::Result { 80747ad3c4Slazypassion pretty_preamble_error(w, func, entity, value, &mut *self.0, self.1) 81747ad3c4Slazypassion } 82747ad3c4Slazypassion } 83747ad3c4Slazypassion 84747ad3c4Slazypassion /// Pretty-print a function verifier error for a given EBB. 85747ad3c4Slazypassion fn pretty_ebb_header_error( 86d7d48d5cSBenjamin Bouvier w: &mut dyn Write, 87747ad3c4Slazypassion func: &Function, 88d7d48d5cSBenjamin Bouvier isa: Option<&dyn TargetIsa>, 89747ad3c4Slazypassion cur_ebb: Ebb, 90747ad3c4Slazypassion indent: usize, 91d7d48d5cSBenjamin Bouvier func_w: &mut dyn FuncWriter, 92747ad3c4Slazypassion errors: &mut Vec<VerifierError>, 93747ad3c4Slazypassion ) -> fmt::Result { 94747ad3c4Slazypassion let mut s = String::new(); 95747ad3c4Slazypassion func_w.write_ebb_header(&mut s, func, isa, cur_ebb, indent)?; 96747ad3c4Slazypassion write!(w, "{}", s)?; 97747ad3c4Slazypassion 98747ad3c4Slazypassion // TODO: Use drain_filter here when it gets stabilized 99747ad3c4Slazypassion let mut i = 0; 100747ad3c4Slazypassion let mut printed_error = false; 101747ad3c4Slazypassion while i != errors.len() { 102747ad3c4Slazypassion match errors[i].location { 103747ad3c4Slazypassion ir::entities::AnyEntity::Ebb(ebb) if ebb == cur_ebb => { 104747ad3c4Slazypassion if !printed_error { 105747ad3c4Slazypassion print_arrow(w, &s)?; 106747ad3c4Slazypassion printed_error = true; 107747ad3c4Slazypassion } 108747ad3c4Slazypassion let err = errors.remove(i); 109747ad3c4Slazypassion print_error(w, err)?; 110747ad3c4Slazypassion } 111747ad3c4Slazypassion _ => i += 1, 112747ad3c4Slazypassion } 113747ad3c4Slazypassion } 114747ad3c4Slazypassion 115747ad3c4Slazypassion if printed_error { 116747ad3c4Slazypassion w.write_char('\n')?; 117747ad3c4Slazypassion } 118747ad3c4Slazypassion 119747ad3c4Slazypassion Ok(()) 120747ad3c4Slazypassion } 121747ad3c4Slazypassion 122747ad3c4Slazypassion /// Pretty-print a function verifier error for a given instruction. 123747ad3c4Slazypassion fn pretty_instruction_error( 124d7d48d5cSBenjamin Bouvier w: &mut dyn Write, 125747ad3c4Slazypassion func: &Function, 126747ad3c4Slazypassion aliases: &SecondaryMap<Value, Vec<Value>>, 127d7d48d5cSBenjamin Bouvier isa: Option<&dyn TargetIsa>, 128747ad3c4Slazypassion cur_inst: Inst, 129747ad3c4Slazypassion indent: usize, 130d7d48d5cSBenjamin Bouvier func_w: &mut dyn FuncWriter, 131747ad3c4Slazypassion errors: &mut Vec<VerifierError>, 132747ad3c4Slazypassion ) -> fmt::Result { 133747ad3c4Slazypassion let mut s = String::new(); 134747ad3c4Slazypassion func_w.write_instruction(&mut s, func, aliases, isa, cur_inst, indent)?; 135747ad3c4Slazypassion write!(w, "{}", s)?; 136747ad3c4Slazypassion 137747ad3c4Slazypassion // TODO: Use drain_filter here when it gets stabilized 138747ad3c4Slazypassion let mut i = 0; 139747ad3c4Slazypassion let mut printed_error = false; 140747ad3c4Slazypassion while i != errors.len() { 141747ad3c4Slazypassion match errors[i].location { 142747ad3c4Slazypassion ir::entities::AnyEntity::Inst(inst) if inst == cur_inst => { 143747ad3c4Slazypassion if !printed_error { 144747ad3c4Slazypassion print_arrow(w, &s)?; 145747ad3c4Slazypassion printed_error = true; 146747ad3c4Slazypassion } 147747ad3c4Slazypassion let err = errors.remove(i); 148747ad3c4Slazypassion print_error(w, err)?; 149747ad3c4Slazypassion } 150747ad3c4Slazypassion _ => i += 1, 151747ad3c4Slazypassion } 152747ad3c4Slazypassion } 153747ad3c4Slazypassion 154747ad3c4Slazypassion if printed_error { 155747ad3c4Slazypassion w.write_char('\n')?; 156747ad3c4Slazypassion } 157747ad3c4Slazypassion 158747ad3c4Slazypassion Ok(()) 159747ad3c4Slazypassion } 160747ad3c4Slazypassion 161747ad3c4Slazypassion fn pretty_preamble_error( 162d7d48d5cSBenjamin Bouvier w: &mut dyn Write, 163747ad3c4Slazypassion func: &Function, 164747ad3c4Slazypassion entity: AnyEntity, 165d7d48d5cSBenjamin Bouvier value: &dyn fmt::Display, 166d7d48d5cSBenjamin Bouvier func_w: &mut dyn FuncWriter, 167747ad3c4Slazypassion errors: &mut Vec<VerifierError>, 168747ad3c4Slazypassion ) -> fmt::Result { 169747ad3c4Slazypassion let mut s = String::new(); 170747ad3c4Slazypassion func_w.write_entity_definition(&mut s, func, entity, value)?; 171747ad3c4Slazypassion write!(w, "{}", s)?; 172747ad3c4Slazypassion 173747ad3c4Slazypassion // TODO: Use drain_filter here when it gets stabilized 174747ad3c4Slazypassion let mut i = 0; 175747ad3c4Slazypassion let mut printed_error = false; 176747ad3c4Slazypassion while i != errors.len() { 177747ad3c4Slazypassion if entity == errors[i].location { 178747ad3c4Slazypassion if !printed_error { 179747ad3c4Slazypassion print_arrow(w, &s)?; 180747ad3c4Slazypassion printed_error = true; 181747ad3c4Slazypassion } 182747ad3c4Slazypassion let err = errors.remove(i); 183747ad3c4Slazypassion print_error(w, err)?; 184747ad3c4Slazypassion } else { 185747ad3c4Slazypassion i += 1 186747ad3c4Slazypassion } 187747ad3c4Slazypassion } 188747ad3c4Slazypassion 189747ad3c4Slazypassion if printed_error { 190747ad3c4Slazypassion w.write_char('\n')?; 191747ad3c4Slazypassion } 192747ad3c4Slazypassion 193747ad3c4Slazypassion Ok(()) 194747ad3c4Slazypassion } 195747ad3c4Slazypassion 196747ad3c4Slazypassion /// Prints: 197747ad3c4Slazypassion /// ; ^~~~~~ 198d7d48d5cSBenjamin Bouvier fn print_arrow(w: &mut dyn Write, entity: &str) -> fmt::Result { 199747ad3c4Slazypassion write!(w, ";")?; 200747ad3c4Slazypassion 201747ad3c4Slazypassion let indent = entity.len() - entity.trim_start().len(); 202747ad3c4Slazypassion if indent != 0 { 203747ad3c4Slazypassion write!(w, "{1:0$}^", indent - 1, "")?; 204747ad3c4Slazypassion } 205747ad3c4Slazypassion 206747ad3c4Slazypassion for _ in 0..entity.trim().len() - 1 { 207747ad3c4Slazypassion write!(w, "~")?; 208747ad3c4Slazypassion } 209747ad3c4Slazypassion 210747ad3c4Slazypassion writeln!(w) 211747ad3c4Slazypassion } 212747ad3c4Slazypassion 213747ad3c4Slazypassion /// Prints: 214747ad3c4Slazypassion /// ; error: [ERROR BODY] 215d7d48d5cSBenjamin Bouvier fn print_error(w: &mut dyn Write, err: VerifierError) -> fmt::Result { 216747ad3c4Slazypassion writeln!(w, "; error: {}", err.to_string())?; 217747ad3c4Slazypassion Ok(()) 218747ad3c4Slazypassion } 219747ad3c4Slazypassion 220747ad3c4Slazypassion /// Pretty-print a Cranelift error. 221d7d48d5cSBenjamin Bouvier pub fn pretty_error(func: &ir::Function, isa: Option<&dyn TargetIsa>, err: CodegenError) -> String { 222747ad3c4Slazypassion if let CodegenError::Verifier(e) = err { 223747ad3c4Slazypassion pretty_verifier_error(func, isa, None, e) 224747ad3c4Slazypassion } else { 225747ad3c4Slazypassion err.to_string() 226747ad3c4Slazypassion } 227747ad3c4Slazypassion } 228