Skip to content

Commit 285c05f

Browse files
committed
🍒 Also print expressions in a resolved form
1 parent f64372b commit 285c05f

File tree

1 file changed

+75
-9
lines changed

1 file changed

+75
-9
lines changed

src/tools/coverage-dump/src/covfun.rs

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::parser::{unescape_llvm_string_contents, Parser};
22
use anyhow::{anyhow, Context};
33
use regex::Regex;
44
use std::collections::HashMap;
5-
use std::fmt::{self, Debug};
5+
use std::fmt::{self, Debug, Write as _};
66
use std::sync::OnceLock;
77

88
pub(crate) fn dump_covfun_mappings(
@@ -46,10 +46,12 @@ pub(crate) fn dump_covfun_mappings(
4646
let num_expressions = parser.read_uleb128_u32()?;
4747
println!("Number of expressions: {num_expressions}");
4848

49+
let mut expression_resolver = ExpressionResolver::new();
4950
for i in 0..num_expressions {
5051
let lhs = parser.read_simple_operand()?;
5152
let rhs = parser.read_simple_operand()?;
5253
println!("- expression {i} operands: lhs = {lhs:?}, rhs = {rhs:?}");
54+
expression_resolver.push_operands(lhs, rhs);
5355
}
5456

5557
for i in 0..num_files {
@@ -59,6 +61,16 @@ pub(crate) fn dump_covfun_mappings(
5961
for _ in 0..num_mappings {
6062
let (kind, region) = parser.read_mapping_kind_and_region()?;
6163
println!("- {kind:?} at {region:?}");
64+
65+
// If the mapping contains expressions, also print the resolved
66+
// form of those expressions
67+
kind.for_each_operand(|label, operand| {
68+
if matches!(operand, Operand::Expression { .. }) {
69+
let pad = if label.is_empty() { "" } else { " " };
70+
let resolved = expression_resolver.format_operand(operand);
71+
println!(" {label}{pad}= {resolved}");
72+
}
73+
});
6274
}
6375
}
6476

@@ -163,15 +175,15 @@ impl<'a> Parser<'a> {
163175

164176
// Represents an expression operand (lhs/rhs), branch region operand (true/false),
165177
// or the value used by a code region or gap region.
166-
#[derive(Debug)]
178+
#[derive(Clone, Copy, Debug)]
167179
pub(crate) enum Operand {
168180
Zero,
169181
Counter(u32),
170182
Expression(u32, Op),
171183
}
172184

173185
/// Operator (addition or subtraction) used by an expression.
174-
#[derive(Debug)]
186+
#[derive(Clone, Copy, Debug)]
175187
pub(crate) enum Op {
176188
Sub,
177189
Add,
@@ -201,12 +213,24 @@ enum MappingKind {
201213
Gap(Operand),
202214
Expansion(u32),
203215
Skip,
204-
Branch {
205-
#[allow(dead_code)]
206-
true_: Operand,
207-
#[allow(dead_code)]
208-
false_: Operand,
209-
},
216+
Branch { true_: Operand, false_: Operand },
217+
}
218+
219+
impl MappingKind {
220+
/// Visits each operand directly contained in this mapping, along with
221+
/// a string label (possibly empty).
222+
fn for_each_operand(&self, mut func: impl FnMut(&str, Operand)) {
223+
match *self {
224+
Self::Code(operand) => func("", operand),
225+
Self::Gap(operand) => func("", operand),
226+
Self::Expansion(_) => (),
227+
Self::Skip => (),
228+
Self::Branch { true_, false_ } => {
229+
func("true_ ", true_);
230+
func("false_", false_);
231+
}
232+
}
233+
}
210234
}
211235

212236
struct MappingRegion {
@@ -234,3 +258,45 @@ impl Debug for MappingRegion {
234258
)
235259
}
236260
}
261+
262+
/// Helper type that prints expressions in a "resolved" form, so that
263+
/// developers reading the dump don't need to resolve expressions by hand.
264+
struct ExpressionResolver {
265+
operands: Vec<(Operand, Operand)>,
266+
}
267+
268+
impl ExpressionResolver {
269+
fn new() -> Self {
270+
Self { operands: Vec::new() }
271+
}
272+
273+
fn push_operands(&mut self, lhs: Operand, rhs: Operand) {
274+
self.operands.push((lhs, rhs));
275+
}
276+
277+
fn format_operand(&self, operand: Operand) -> String {
278+
let mut output = String::new();
279+
self.write_operand(&mut output, operand);
280+
output
281+
}
282+
283+
fn write_operand(&self, output: &mut String, operand: Operand) {
284+
match operand {
285+
Operand::Zero => output.push_str("Zero"),
286+
Operand::Counter(id) => write!(output, "c{id}").unwrap(),
287+
Operand::Expression(id, op) => {
288+
let (lhs, rhs) = self.operands[id as usize];
289+
let op = match op {
290+
Op::Sub => "-",
291+
Op::Add => "+",
292+
};
293+
294+
output.push('(');
295+
self.write_operand(output, lhs);
296+
write!(output, " {op} ").unwrap();
297+
self.write_operand(output, rhs);
298+
output.push(')');
299+
}
300+
}
301+
}
302+
}

0 commit comments

Comments
 (0)