@@ -16,6 +16,23 @@ pub struct Expression {
16
16
region : Option < CodeRegion > ,
17
17
}
18
18
19
+ pub struct CoverageCounterAndRegion < ' a > {
20
+ pub ( crate ) kind : CoverageCounterKind ,
21
+ pub ( crate ) region : & ' a CodeRegion ,
22
+ }
23
+
24
+ pub enum CoverageCounterKind {
25
+ Counter ( Counter ) ,
26
+ Branch { true_counter : Counter , false_counter : Counter } ,
27
+ }
28
+
29
+ #[ derive( Debug ) ]
30
+ struct CoverageBranch {
31
+ true_op : Operand ,
32
+ false_op : Operand ,
33
+ region : CodeRegion ,
34
+ }
35
+
19
36
/// Collects all of the coverage regions associated with (a) injected counters, (b) counter
20
37
/// expressions (additions or subtraction), and (c) unreachable regions (always counted as zero),
21
38
/// for a given Function. This struct also stores the `function_source_hash`,
@@ -34,6 +51,7 @@ pub struct FunctionCoverage<'tcx> {
34
51
is_used : bool ,
35
52
counters : IndexVec < CounterId , Option < CodeRegion > > ,
36
53
expressions : IndexVec < ExpressionId , Option < Expression > > ,
54
+ branches : Vec < CoverageBranch > ,
37
55
unreachable_regions : Vec < CodeRegion > ,
38
56
}
39
57
@@ -60,6 +78,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
60
78
is_used,
61
79
counters : IndexVec :: from_elem_n ( None , coverageinfo. num_counters as usize ) ,
62
80
expressions : IndexVec :: from_elem_n ( None , coverageinfo. num_expressions as usize ) ,
81
+ branches : Vec :: new ( ) ,
63
82
unreachable_regions : Vec :: new ( ) ,
64
83
}
65
84
}
@@ -86,6 +105,11 @@ impl<'tcx> FunctionCoverage<'tcx> {
86
105
}
87
106
}
88
107
108
+ /// Adds a branch region using the two provided true/false operands
109
+ pub fn add_branch_counter ( & mut self , true_op : Operand , false_op : Operand , region : CodeRegion ) {
110
+ self . branches . push ( CoverageBranch { true_op, false_op, region } )
111
+ }
112
+
89
113
/// Both counters and "counter expressions" (or simply, "expressions") can be operands in other
90
114
/// expressions. These are tracked as separate variants of `Operand`, so there is no ambiguity
91
115
/// between operands that are counter IDs and operands that are expression IDs.
@@ -139,7 +163,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
139
163
/// `CoverageMapGenerator` will create `CounterMappingRegion`s.
140
164
pub fn get_expressions_and_counter_regions (
141
165
& self ,
142
- ) -> ( Vec < CounterExpression > , Vec < ( Counter , & CodeRegion ) > ) {
166
+ ) -> ( Vec < CounterExpression > , Vec < CoverageCounterAndRegion < ' _ > > ) {
143
167
assert ! (
144
168
self . source_hash != 0 || !self . is_used,
145
169
"No counters provided the source_hash for used function: {:?}" ,
@@ -153,22 +177,25 @@ impl<'tcx> FunctionCoverage<'tcx> {
153
177
let mut collected_counter_regions = expression_regions;
154
178
collected_counter_regions. extend ( counter_regions) ;
155
179
collected_counter_regions. extend ( unreachable_regions) ;
156
- collected_counter_regions. sort_unstable_by_key ( |( _counter , region ) | * region) ;
180
+ collected_counter_regions. sort_unstable_by_key ( |counter| counter . region ) ;
157
181
158
182
( counter_expressions, collected_counter_regions)
159
183
}
160
184
161
- fn counter_regions ( & self ) -> impl Iterator < Item = ( Counter , & CodeRegion ) > {
185
+ fn counter_regions ( & self ) -> impl Iterator < Item = CoverageCounterAndRegion < ' _ > > {
162
186
self . counters . iter_enumerated ( ) . filter_map ( |( index, entry) | {
163
187
// Option::map() will return None to filter out missing counters. This may happen
164
188
// if, for example, a MIR-instrumented counter is removed during an optimization.
165
- entry. as_ref ( ) . map ( |region| ( Counter :: counter_value_reference ( index) , region) )
189
+ entry. as_ref ( ) . map ( |region| CoverageCounterAndRegion {
190
+ kind : CoverageCounterKind :: Counter ( Counter :: counter_value_reference ( index) ) ,
191
+ region,
192
+ } )
166
193
} )
167
194
}
168
195
169
196
fn expressions_with_regions (
170
197
& self ,
171
- ) -> ( Vec < CounterExpression > , Vec < ( Counter , & CodeRegion ) > ) {
198
+ ) -> ( Vec < CounterExpression > , Vec < CoverageCounterAndRegion < ' _ > > ) {
172
199
let mut counter_expressions = Vec :: with_capacity ( self . expressions . len ( ) ) ;
173
200
let mut expression_regions = Vec :: with_capacity ( self . expressions . len ( ) ) ;
174
201
let mut new_indexes = IndexVec :: from_elem_n ( None , self . expressions . len ( ) ) ;
@@ -291,7 +318,12 @@ impl<'tcx> FunctionCoverage<'tcx> {
291
318
counter_expressions. push ( expression) ;
292
319
new_indexes[ original_index] = Some ( mapped_expression_index) ;
293
320
if let Some ( region) = optional_region {
294
- expression_regions. push ( ( Counter :: expression ( mapped_expression_index) , region) ) ;
321
+ expression_regions. push ( CoverageCounterAndRegion {
322
+ kind : CoverageCounterKind :: Counter ( Counter :: expression (
323
+ mapped_expression_index,
324
+ ) ) ,
325
+ region,
326
+ } ) ;
295
327
}
296
328
} else {
297
329
bug ! (
@@ -305,10 +337,36 @@ impl<'tcx> FunctionCoverage<'tcx> {
305
337
) ;
306
338
}
307
339
}
340
+
341
+ for branch in & self . branches {
342
+ if let Some ( Some ( ( true_counter, false_counter) ) ) =
343
+ id_to_counter ( & new_indexes, branch. true_op ) . map ( |true_counter| {
344
+ id_to_counter ( & new_indexes, branch. false_op )
345
+ . map ( |false_counter| ( true_counter, false_counter) )
346
+ } )
347
+ {
348
+ expression_regions. push ( CoverageCounterAndRegion {
349
+ kind : CoverageCounterKind :: Branch { true_counter, false_counter } ,
350
+ region : & branch. region ,
351
+ } ) ;
352
+ } else {
353
+ bug ! (
354
+ "branch has one or more missing operands \
355
+ true={:?}, false={:?}, region={:?}",
356
+ branch. true_op,
357
+ branch. false_op,
358
+ branch. region,
359
+ ) ;
360
+ }
361
+ }
362
+
308
363
( counter_expressions, expression_regions)
309
364
}
310
365
311
- fn unreachable_regions ( & self ) -> impl Iterator < Item = ( Counter , & CodeRegion ) > {
312
- self . unreachable_regions . iter ( ) . map ( |region| ( Counter :: zero ( ) , region) )
366
+ fn unreachable_regions ( & self ) -> impl Iterator < Item = CoverageCounterAndRegion < ' _ > > {
367
+ self . unreachable_regions . iter ( ) . map ( |region| CoverageCounterAndRegion {
368
+ kind : CoverageCounterKind :: Counter ( Counter :: zero ( ) ) ,
369
+ region,
370
+ } )
313
371
}
314
372
}
0 commit comments