Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/codegen/src/print_errors.rs
1693 views
1
//! Utility routines for pretty-printing error messages.
2
3
use crate::entity::SecondaryMap;
4
use crate::ir;
5
use crate::ir::entities::{AnyEntity, Block, Inst, Value};
6
use crate::ir::function::Function;
7
use crate::ir::pcc::Fact;
8
use crate::result::CodegenError;
9
use crate::verifier::{VerifierError, VerifierErrors};
10
use crate::write::{FuncWriter, PlainWriter, decorate_function};
11
use alloc::boxed::Box;
12
use alloc::string::{String, ToString};
13
use alloc::vec::Vec;
14
use core::fmt;
15
use core::fmt::Write;
16
17
/// Pretty-print a verifier error.
18
pub fn pretty_verifier_error<'a>(
19
func: &ir::Function,
20
func_w: Option<Box<dyn FuncWriter + 'a>>,
21
errors: VerifierErrors,
22
) -> String {
23
let mut errors = errors.0;
24
let mut w = String::new();
25
let num_errors = errors.len();
26
27
decorate_function(
28
&mut PrettyVerifierError(func_w.unwrap_or_else(|| Box::new(PlainWriter)), &mut errors),
29
&mut w,
30
func,
31
)
32
.unwrap();
33
34
writeln!(
35
w,
36
"\n; {} verifier error{} detected (see above). Compilation aborted.",
37
num_errors,
38
if num_errors == 1 { "" } else { "s" }
39
)
40
.unwrap();
41
42
w
43
}
44
45
struct PrettyVerifierError<'a>(Box<dyn FuncWriter + 'a>, &'a mut Vec<VerifierError>);
46
47
impl<'a> FuncWriter for PrettyVerifierError<'a> {
48
fn write_block_header(
49
&mut self,
50
w: &mut dyn Write,
51
func: &Function,
52
block: Block,
53
indent: usize,
54
) -> fmt::Result {
55
pretty_block_header_error(w, func, block, indent, &mut *self.0, self.1)
56
}
57
58
fn write_instruction(
59
&mut self,
60
w: &mut dyn Write,
61
func: &Function,
62
aliases: &SecondaryMap<Value, Vec<Value>>,
63
inst: Inst,
64
indent: usize,
65
) -> fmt::Result {
66
pretty_instruction_error(w, func, aliases, inst, indent, &mut *self.0, self.1)
67
}
68
69
fn write_entity_definition(
70
&mut self,
71
w: &mut dyn Write,
72
func: &Function,
73
entity: AnyEntity,
74
value: &dyn fmt::Display,
75
maybe_fact: Option<&Fact>,
76
) -> fmt::Result {
77
pretty_preamble_error(w, func, entity, value, maybe_fact, &mut *self.0, self.1)
78
}
79
}
80
81
/// Pretty-print a function verifier error for a given block.
82
fn pretty_block_header_error(
83
w: &mut dyn Write,
84
func: &Function,
85
cur_block: Block,
86
indent: usize,
87
func_w: &mut dyn FuncWriter,
88
errors: &mut Vec<VerifierError>,
89
) -> fmt::Result {
90
let mut s = String::new();
91
func_w.write_block_header(&mut s, func, cur_block, indent)?;
92
write!(w, "{s}")?;
93
94
// TODO: Use drain_filter here when it gets stabilized
95
let mut i = 0;
96
let mut printed_error = false;
97
while i != errors.len() {
98
match errors[i].location {
99
ir::entities::AnyEntity::Block(block) if block == cur_block => {
100
if !printed_error {
101
print_arrow(w, &s)?;
102
printed_error = true;
103
}
104
let err = errors.remove(i);
105
print_error(w, err)?;
106
}
107
_ => i += 1,
108
}
109
}
110
111
if printed_error {
112
w.write_char('\n')?;
113
}
114
115
Ok(())
116
}
117
118
/// Pretty-print a function verifier error for a given instruction.
119
fn pretty_instruction_error(
120
w: &mut dyn Write,
121
func: &Function,
122
aliases: &SecondaryMap<Value, Vec<Value>>,
123
cur_inst: Inst,
124
indent: usize,
125
func_w: &mut dyn FuncWriter,
126
errors: &mut Vec<VerifierError>,
127
) -> fmt::Result {
128
let mut s = String::new();
129
func_w.write_instruction(&mut s, func, aliases, cur_inst, indent)?;
130
write!(w, "{s}")?;
131
132
// TODO: Use drain_filter here when it gets stabilized
133
let mut i = 0;
134
let mut printed_error = false;
135
while i != errors.len() {
136
match errors[i].location {
137
ir::entities::AnyEntity::Inst(inst) if inst == cur_inst => {
138
if !printed_error {
139
print_arrow(w, &s)?;
140
printed_error = true;
141
}
142
let err = errors.remove(i);
143
print_error(w, err)?;
144
}
145
_ => i += 1,
146
}
147
}
148
149
if printed_error {
150
w.write_char('\n')?;
151
}
152
153
Ok(())
154
}
155
156
fn pretty_preamble_error(
157
w: &mut dyn Write,
158
func: &Function,
159
entity: AnyEntity,
160
value: &dyn fmt::Display,
161
maybe_fact: Option<&Fact>,
162
func_w: &mut dyn FuncWriter,
163
errors: &mut Vec<VerifierError>,
164
) -> fmt::Result {
165
let mut s = String::new();
166
func_w.write_entity_definition(&mut s, func, entity, value, maybe_fact)?;
167
write!(w, "{s}")?;
168
169
// TODO: Use drain_filter here when it gets stabilized
170
let mut i = 0;
171
let mut printed_error = false;
172
while i != errors.len() {
173
if entity == errors[i].location {
174
if !printed_error {
175
print_arrow(w, &s)?;
176
printed_error = true;
177
}
178
let err = errors.remove(i);
179
print_error(w, err)?;
180
} else {
181
i += 1
182
}
183
}
184
185
if printed_error {
186
w.write_char('\n')?;
187
}
188
189
Ok(())
190
}
191
192
/// Prints:
193
/// ; ^~~~~~
194
fn print_arrow(w: &mut dyn Write, entity: &str) -> fmt::Result {
195
write!(w, ";")?;
196
197
let indent = entity.len() - entity.trim_start().len();
198
if indent != 0 {
199
write!(w, "{1:0$}^", indent - 1, "")?;
200
}
201
202
for _ in 0..entity.trim().len() - 1 {
203
write!(w, "~")?;
204
}
205
206
writeln!(w)
207
}
208
209
/// Prints:
210
/// ; error: [ERROR BODY]
211
fn print_error(w: &mut dyn Write, err: VerifierError) -> fmt::Result {
212
writeln!(w, "; error: {}", err.to_string())?;
213
Ok(())
214
}
215
216
/// Pretty-print a Cranelift error.
217
pub fn pretty_error(func: &ir::Function, err: CodegenError) -> String {
218
if let CodegenError::Verifier(e) = err {
219
pretty_verifier_error(func, None, e)
220
} else {
221
err.to_string()
222
}
223
}
224
225