@@ -2,7 +2,7 @@ use crate::parser::{unescape_llvm_string_contents, Parser};
22use anyhow:: { anyhow, Context } ;
33use regex:: Regex ;
44use std:: collections:: HashMap ;
5- use std:: fmt:: { self , Debug } ;
5+ use std:: fmt:: { self , Debug , Write as _ } ;
66use std:: sync:: OnceLock ;
77
88pub ( 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 ) ]
167179pub ( 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 ) ]
175187pub ( 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
212236struct 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