@@ -2,7 +2,7 @@ use crate::parser::{unescape_llvm_string_contents, Parser};
2
2
use anyhow:: { anyhow, Context } ;
3
3
use regex:: Regex ;
4
4
use std:: collections:: HashMap ;
5
- use std:: fmt:: { self , Debug } ;
5
+ use std:: fmt:: { self , Debug , Write as _ } ;
6
6
use std:: sync:: OnceLock ;
7
7
8
8
pub ( crate ) fn dump_covfun_mappings (
@@ -46,10 +46,12 @@ pub(crate) fn dump_covfun_mappings(
46
46
let num_expressions = parser. read_uleb128_u32 ( ) ?;
47
47
println ! ( "Number of expressions: {num_expressions}" ) ;
48
48
49
+ let mut expression_resolver = ExpressionResolver :: new ( ) ;
49
50
for i in 0 ..num_expressions {
50
51
let lhs = parser. read_simple_operand ( ) ?;
51
52
let rhs = parser. read_simple_operand ( ) ?;
52
53
println ! ( "- expression {i} operands: lhs = {lhs:?}, rhs = {rhs:?}" ) ;
54
+ expression_resolver. push_operands ( lhs, rhs) ;
53
55
}
54
56
55
57
for i in 0 ..num_files {
@@ -59,6 +61,16 @@ pub(crate) fn dump_covfun_mappings(
59
61
for _ in 0 ..num_mappings {
60
62
let ( kind, region) = parser. read_mapping_kind_and_region ( ) ?;
61
63
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
+ } ) ;
62
74
}
63
75
}
64
76
@@ -163,15 +175,15 @@ impl<'a> Parser<'a> {
163
175
164
176
// Represents an expression operand (lhs/rhs), branch region operand (true/false),
165
177
// or the value used by a code region or gap region.
166
- #[ derive( Debug ) ]
178
+ #[ derive( Clone , Copy , Debug ) ]
167
179
pub ( crate ) enum Operand {
168
180
Zero ,
169
181
Counter ( u32 ) ,
170
182
Expression ( u32 , Op ) ,
171
183
}
172
184
173
185
/// Operator (addition or subtraction) used by an expression.
174
- #[ derive( Debug ) ]
186
+ #[ derive( Clone , Copy , Debug ) ]
175
187
pub ( crate ) enum Op {
176
188
Sub ,
177
189
Add ,
@@ -201,12 +213,24 @@ enum MappingKind {
201
213
Gap ( Operand ) ,
202
214
Expansion ( u32 ) ,
203
215
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
+ }
210
234
}
211
235
212
236
struct MappingRegion {
@@ -234,3 +258,45 @@ impl Debug for MappingRegion {
234
258
)
235
259
}
236
260
}
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