1747ad3c4Slazypassion //! Utility routines for pretty-printing error messages.
2747ad3c4Slazypassion
3747ad3c4Slazypassion use crate::entity::SecondaryMap;
4747ad3c4Slazypassion use crate::ir;
5832666c4SRyan Hunt use crate::ir::entities::{AnyEntity, Block, Inst, Value};
6747ad3c4Slazypassion use crate::ir::function::Function;
7747ad3c4Slazypassion use crate::result::CodegenError;
8747ad3c4Slazypassion use crate::verifier::{VerifierError, VerifierErrors};
990ac295eSAlex Crichton use crate::write::{FuncWriter, PlainWriter, decorate_function};
1010e226f9Sbjorn3 use alloc::boxed::Box;
1110e226f9Sbjorn3 use alloc::string::{String, ToString};
1210e226f9Sbjorn3 use alloc::vec::Vec;
13bb8fa40eSbjorn3 use core::fmt;
14bb8fa40eSbjorn3 use core::fmt::Write;
15747ad3c4Slazypassion
16747ad3c4Slazypassion /// Pretty-print a verifier error.
pretty_verifier_error<'a>( func: &ir::Function, func_w: Option<Box<dyn FuncWriter + 'a>>, errors: VerifierErrors, ) -> String17747ad3c4Slazypassion pub fn pretty_verifier_error<'a>(
18747ad3c4Slazypassion func: &ir::Function,
19d7d48d5cSBenjamin Bouvier func_w: Option<Box<dyn FuncWriter + 'a>>,
20747ad3c4Slazypassion errors: VerifierErrors,
21747ad3c4Slazypassion ) -> String {
22747ad3c4Slazypassion let mut errors = errors.0;
23747ad3c4Slazypassion let mut w = String::new();
24747ad3c4Slazypassion let num_errors = errors.len();
25747ad3c4Slazypassion
26747ad3c4Slazypassion decorate_function(
27747ad3c4Slazypassion &mut PrettyVerifierError(func_w.unwrap_or_else(|| Box::new(PlainWriter)), &mut errors),
28747ad3c4Slazypassion &mut w,
29747ad3c4Slazypassion func,
30747ad3c4Slazypassion )
31747ad3c4Slazypassion .unwrap();
32747ad3c4Slazypassion
33747ad3c4Slazypassion writeln!(
34747ad3c4Slazypassion w,
35747ad3c4Slazypassion "\n; {} verifier error{} detected (see above). Compilation aborted.",
36747ad3c4Slazypassion num_errors,
37747ad3c4Slazypassion if num_errors == 1 { "" } else { "s" }
38747ad3c4Slazypassion )
39747ad3c4Slazypassion .unwrap();
40747ad3c4Slazypassion
41747ad3c4Slazypassion w
42747ad3c4Slazypassion }
43747ad3c4Slazypassion
44d7d48d5cSBenjamin Bouvier struct PrettyVerifierError<'a>(Box<dyn FuncWriter + 'a>, &'a mut Vec<VerifierError>);
45747ad3c4Slazypassion
46747ad3c4Slazypassion impl<'a> FuncWriter for PrettyVerifierError<'a> {
write_block_header( &mut self, w: &mut dyn Write, func: &Function, block: Block, indent: usize, ) -> fmt::Result47832666c4SRyan Hunt fn write_block_header(
48747ad3c4Slazypassion &mut self,
49d7d48d5cSBenjamin Bouvier w: &mut dyn Write,
50747ad3c4Slazypassion func: &Function,
51832666c4SRyan Hunt block: Block,
52747ad3c4Slazypassion indent: usize,
53747ad3c4Slazypassion ) -> fmt::Result {
5443a86f14SBenjamin Bouvier pretty_block_header_error(w, func, block, indent, &mut *self.0, self.1)
55747ad3c4Slazypassion }
56747ad3c4Slazypassion
write_instruction( &mut self, w: &mut dyn Write, func: &Function, aliases: &SecondaryMap<Value, Vec<Value>>, inst: Inst, indent: usize, ) -> fmt::Result57747ad3c4Slazypassion fn write_instruction(
58747ad3c4Slazypassion &mut self,
59d7d48d5cSBenjamin Bouvier w: &mut dyn Write,
60747ad3c4Slazypassion func: &Function,
61747ad3c4Slazypassion aliases: &SecondaryMap<Value, Vec<Value>>,
62747ad3c4Slazypassion inst: Inst,
63747ad3c4Slazypassion indent: usize,
64747ad3c4Slazypassion ) -> fmt::Result {
6543a86f14SBenjamin Bouvier pretty_instruction_error(w, func, aliases, inst, indent, &mut *self.0, self.1)
66747ad3c4Slazypassion }
67747ad3c4Slazypassion
write_entity_definition( &mut self, w: &mut dyn Write, func: &Function, entity: AnyEntity, value: &dyn fmt::Display, ) -> fmt::Result68747ad3c4Slazypassion fn write_entity_definition(
69747ad3c4Slazypassion &mut self,
70d7d48d5cSBenjamin Bouvier w: &mut dyn Write,
71747ad3c4Slazypassion func: &Function,
72747ad3c4Slazypassion entity: AnyEntity,
73d7d48d5cSBenjamin Bouvier value: &dyn fmt::Display,
74747ad3c4Slazypassion ) -> fmt::Result {
75*2f7dbd61SChris Fallin pretty_preamble_error(w, func, entity, value, &mut *self.0, self.1)
76747ad3c4Slazypassion }
77747ad3c4Slazypassion }
78747ad3c4Slazypassion
79832666c4SRyan Hunt /// Pretty-print a function verifier error for a given block.
pretty_block_header_error( w: &mut dyn Write, func: &Function, cur_block: Block, indent: usize, func_w: &mut dyn FuncWriter, errors: &mut Vec<VerifierError>, ) -> fmt::Result80832666c4SRyan Hunt fn pretty_block_header_error(
81d7d48d5cSBenjamin Bouvier w: &mut dyn Write,
82747ad3c4Slazypassion func: &Function,
83832666c4SRyan Hunt cur_block: Block,
84747ad3c4Slazypassion indent: usize,
85d7d48d5cSBenjamin Bouvier func_w: &mut dyn FuncWriter,
86747ad3c4Slazypassion errors: &mut Vec<VerifierError>,
87747ad3c4Slazypassion ) -> fmt::Result {
88747ad3c4Slazypassion let mut s = String::new();
8943a86f14SBenjamin Bouvier func_w.write_block_header(&mut s, func, cur_block, indent)?;
90a0442ea0SHamir Mahal write!(w, "{s}")?;
91747ad3c4Slazypassion
92747ad3c4Slazypassion // TODO: Use drain_filter here when it gets stabilized
93747ad3c4Slazypassion let mut i = 0;
94747ad3c4Slazypassion let mut printed_error = false;
95747ad3c4Slazypassion while i != errors.len() {
96747ad3c4Slazypassion match errors[i].location {
97832666c4SRyan Hunt ir::entities::AnyEntity::Block(block) if block == cur_block => {
98747ad3c4Slazypassion if !printed_error {
99747ad3c4Slazypassion print_arrow(w, &s)?;
100747ad3c4Slazypassion printed_error = true;
101747ad3c4Slazypassion }
102747ad3c4Slazypassion let err = errors.remove(i);
103747ad3c4Slazypassion print_error(w, err)?;
104747ad3c4Slazypassion }
105747ad3c4Slazypassion _ => i += 1,
106747ad3c4Slazypassion }
107747ad3c4Slazypassion }
108747ad3c4Slazypassion
109747ad3c4Slazypassion if printed_error {
110747ad3c4Slazypassion w.write_char('\n')?;
111747ad3c4Slazypassion }
112747ad3c4Slazypassion
113747ad3c4Slazypassion Ok(())
114747ad3c4Slazypassion }
115747ad3c4Slazypassion
116747ad3c4Slazypassion /// Pretty-print a function verifier error for a given instruction.
pretty_instruction_error( w: &mut dyn Write, func: &Function, aliases: &SecondaryMap<Value, Vec<Value>>, cur_inst: Inst, indent: usize, func_w: &mut dyn FuncWriter, errors: &mut Vec<VerifierError>, ) -> fmt::Result117747ad3c4Slazypassion fn pretty_instruction_error(
118d7d48d5cSBenjamin Bouvier w: &mut dyn Write,
119747ad3c4Slazypassion func: &Function,
120747ad3c4Slazypassion aliases: &SecondaryMap<Value, Vec<Value>>,
121747ad3c4Slazypassion cur_inst: Inst,
122747ad3c4Slazypassion indent: usize,
123d7d48d5cSBenjamin Bouvier func_w: &mut dyn FuncWriter,
124747ad3c4Slazypassion errors: &mut Vec<VerifierError>,
125747ad3c4Slazypassion ) -> fmt::Result {
126747ad3c4Slazypassion let mut s = String::new();
12743a86f14SBenjamin Bouvier func_w.write_instruction(&mut s, func, aliases, cur_inst, indent)?;
128a0442ea0SHamir Mahal write!(w, "{s}")?;
129747ad3c4Slazypassion
130747ad3c4Slazypassion // TODO: Use drain_filter here when it gets stabilized
131747ad3c4Slazypassion let mut i = 0;
132747ad3c4Slazypassion let mut printed_error = false;
133747ad3c4Slazypassion while i != errors.len() {
134747ad3c4Slazypassion match errors[i].location {
135747ad3c4Slazypassion ir::entities::AnyEntity::Inst(inst) if inst == cur_inst => {
136747ad3c4Slazypassion if !printed_error {
137747ad3c4Slazypassion print_arrow(w, &s)?;
138747ad3c4Slazypassion printed_error = true;
139747ad3c4Slazypassion }
140747ad3c4Slazypassion let err = errors.remove(i);
141747ad3c4Slazypassion print_error(w, err)?;
142747ad3c4Slazypassion }
143747ad3c4Slazypassion _ => i += 1,
144747ad3c4Slazypassion }
145747ad3c4Slazypassion }
146747ad3c4Slazypassion
147747ad3c4Slazypassion if printed_error {
148747ad3c4Slazypassion w.write_char('\n')?;
149747ad3c4Slazypassion }
150747ad3c4Slazypassion
151747ad3c4Slazypassion Ok(())
152747ad3c4Slazypassion }
153747ad3c4Slazypassion
pretty_preamble_error( w: &mut dyn Write, func: &Function, entity: AnyEntity, value: &dyn fmt::Display, func_w: &mut dyn FuncWriter, errors: &mut Vec<VerifierError>, ) -> fmt::Result154747ad3c4Slazypassion fn pretty_preamble_error(
155d7d48d5cSBenjamin Bouvier w: &mut dyn Write,
156747ad3c4Slazypassion func: &Function,
157747ad3c4Slazypassion entity: AnyEntity,
158d7d48d5cSBenjamin Bouvier value: &dyn fmt::Display,
159d7d48d5cSBenjamin Bouvier func_w: &mut dyn FuncWriter,
160747ad3c4Slazypassion errors: &mut Vec<VerifierError>,
161747ad3c4Slazypassion ) -> fmt::Result {
162747ad3c4Slazypassion let mut s = String::new();
163*2f7dbd61SChris Fallin func_w.write_entity_definition(&mut s, func, entity, value)?;
164a0442ea0SHamir Mahal write!(w, "{s}")?;
165747ad3c4Slazypassion
166747ad3c4Slazypassion // TODO: Use drain_filter here when it gets stabilized
167747ad3c4Slazypassion let mut i = 0;
168747ad3c4Slazypassion let mut printed_error = false;
169747ad3c4Slazypassion while i != errors.len() {
170747ad3c4Slazypassion if entity == errors[i].location {
171747ad3c4Slazypassion if !printed_error {
172747ad3c4Slazypassion print_arrow(w, &s)?;
173747ad3c4Slazypassion printed_error = true;
174747ad3c4Slazypassion }
175747ad3c4Slazypassion let err = errors.remove(i);
176747ad3c4Slazypassion print_error(w, err)?;
177747ad3c4Slazypassion } else {
178747ad3c4Slazypassion i += 1
179747ad3c4Slazypassion }
180747ad3c4Slazypassion }
181747ad3c4Slazypassion
182747ad3c4Slazypassion if printed_error {
183747ad3c4Slazypassion w.write_char('\n')?;
184747ad3c4Slazypassion }
185747ad3c4Slazypassion
186747ad3c4Slazypassion Ok(())
187747ad3c4Slazypassion }
188747ad3c4Slazypassion
189747ad3c4Slazypassion /// Prints:
190747ad3c4Slazypassion /// ; ^~~~~~
print_arrow(w: &mut dyn Write, entity: &str) -> fmt::Result191d7d48d5cSBenjamin Bouvier fn print_arrow(w: &mut dyn Write, entity: &str) -> fmt::Result {
192747ad3c4Slazypassion write!(w, ";")?;
193747ad3c4Slazypassion
194747ad3c4Slazypassion let indent = entity.len() - entity.trim_start().len();
195747ad3c4Slazypassion if indent != 0 {
196747ad3c4Slazypassion write!(w, "{1:0$}^", indent - 1, "")?;
197747ad3c4Slazypassion }
198747ad3c4Slazypassion
199747ad3c4Slazypassion for _ in 0..entity.trim().len() - 1 {
200747ad3c4Slazypassion write!(w, "~")?;
201747ad3c4Slazypassion }
202747ad3c4Slazypassion
203747ad3c4Slazypassion writeln!(w)
204747ad3c4Slazypassion }
205747ad3c4Slazypassion
206747ad3c4Slazypassion /// Prints:
207747ad3c4Slazypassion /// ; error: [ERROR BODY]
print_error(w: &mut dyn Write, err: VerifierError) -> fmt::Result208d7d48d5cSBenjamin Bouvier fn print_error(w: &mut dyn Write, err: VerifierError) -> fmt::Result {
209747ad3c4Slazypassion writeln!(w, "; error: {}", err.to_string())?;
210747ad3c4Slazypassion Ok(())
211747ad3c4Slazypassion }
212747ad3c4Slazypassion
213747ad3c4Slazypassion /// Pretty-print a Cranelift error.
pretty_error(func: &ir::Function, err: CodegenError) -> String21443a86f14SBenjamin Bouvier pub fn pretty_error(func: &ir::Function, err: CodegenError) -> String {
215747ad3c4Slazypassion if let CodegenError::Verifier(e) = err {
21643a86f14SBenjamin Bouvier pretty_verifier_error(func, None, e)
217747ad3c4Slazypassion } else {
218747ad3c4Slazypassion err.to_string()
219747ad3c4Slazypassion }
220747ad3c4Slazypassion }
221