@@ -16,6 +16,23 @@ pub struct Expression {
1616 region : Option < CodeRegion > ,
1717}
1818
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+
1936/// Collects all of the coverage regions associated with (a) injected counters, (b) counter
2037/// expressions (additions or subtraction), and (c) unreachable regions (always counted as zero),
2138/// for a given Function. This struct also stores the `function_source_hash`,
@@ -34,6 +51,7 @@ pub struct FunctionCoverage<'tcx> {
3451 is_used : bool ,
3552 counters : IndexVec < CounterId , Option < CodeRegion > > ,
3653 expressions : IndexVec < ExpressionId , Option < Expression > > ,
54+ branches : Vec < CoverageBranch > ,
3755 unreachable_regions : Vec < CodeRegion > ,
3856}
3957
@@ -60,6 +78,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
6078 is_used,
6179 counters : IndexVec :: from_elem_n ( None , coverageinfo. num_counters as usize ) ,
6280 expressions : IndexVec :: from_elem_n ( None , coverageinfo. num_expressions as usize ) ,
81+ branches : Vec :: new ( ) ,
6382 unreachable_regions : Vec :: new ( ) ,
6483 }
6584 }
@@ -86,6 +105,11 @@ impl<'tcx> FunctionCoverage<'tcx> {
86105 }
87106 }
88107
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+
89113 /// Both counters and "counter expressions" (or simply, "expressions") can be operands in other
90114 /// expressions. These are tracked as separate variants of `Operand`, so there is no ambiguity
91115 /// between operands that are counter IDs and operands that are expression IDs.
@@ -139,7 +163,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
139163 /// `CoverageMapGenerator` will create `CounterMappingRegion`s.
140164 pub fn get_expressions_and_counter_regions (
141165 & self ,
142- ) -> ( Vec < CounterExpression > , Vec < ( Counter , & CodeRegion ) > ) {
166+ ) -> ( Vec < CounterExpression > , Vec < CoverageCounterAndRegion < ' _ > > ) {
143167 assert ! (
144168 self . source_hash != 0 || !self . is_used,
145169 "No counters provided the source_hash for used function: {:?}" ,
@@ -153,22 +177,25 @@ impl<'tcx> FunctionCoverage<'tcx> {
153177 let mut collected_counter_regions = expression_regions;
154178 collected_counter_regions. extend ( counter_regions) ;
155179 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 ) ;
157181
158182 ( counter_expressions, collected_counter_regions)
159183 }
160184
161- fn counter_regions ( & self ) -> impl Iterator < Item = ( Counter , & CodeRegion ) > {
185+ fn counter_regions ( & self ) -> impl Iterator < Item = CoverageCounterAndRegion < ' _ > > {
162186 self . counters . iter_enumerated ( ) . filter_map ( |( index, entry) | {
163187 // Option::map() will return None to filter out missing counters. This may happen
164188 // 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+ } )
166193 } )
167194 }
168195
169196 fn expressions_with_regions (
170197 & self ,
171- ) -> ( Vec < CounterExpression > , Vec < ( Counter , & CodeRegion ) > ) {
198+ ) -> ( Vec < CounterExpression > , Vec < CoverageCounterAndRegion < ' _ > > ) {
172199 let mut counter_expressions = Vec :: with_capacity ( self . expressions . len ( ) ) ;
173200 let mut expression_regions = Vec :: with_capacity ( self . expressions . len ( ) ) ;
174201 let mut new_indexes = IndexVec :: from_elem_n ( None , self . expressions . len ( ) ) ;
@@ -291,7 +318,12 @@ impl<'tcx> FunctionCoverage<'tcx> {
291318 counter_expressions. push ( expression) ;
292319 new_indexes[ original_index] = Some ( mapped_expression_index) ;
293320 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+ } ) ;
295327 }
296328 } else {
297329 bug ! (
@@ -305,10 +337,36 @@ impl<'tcx> FunctionCoverage<'tcx> {
305337 ) ;
306338 }
307339 }
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+
308363 ( counter_expressions, expression_regions)
309364 }
310365
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+ } )
313371 }
314372}
0 commit comments