@@ -14,6 +14,23 @@ pub struct Expression {
1414 region : Option < CodeRegion > ,
1515}
1616
17+ pub struct CoverageCounterAndRegion < ' a > {
18+ pub ( crate ) kind : CoverageCounterKind ,
19+ pub ( crate ) region : & ' a CodeRegion ,
20+ }
21+
22+ pub enum CoverageCounterKind {
23+ Counter ( Counter ) ,
24+ Branch { true_counter : Counter , false_counter : Counter } ,
25+ }
26+
27+ #[ derive( Debug ) ]
28+ struct CoverageBranch {
29+ true_ : Operand ,
30+ false_ : Operand ,
31+ region : CodeRegion ,
32+ }
33+
1734/// Collects all of the coverage regions associated with (a) injected counters, (b) counter
1835/// expressions (additions or subtraction), and (c) unreachable regions (always counted as zero),
1936/// for a given Function. This struct also stores the `function_source_hash`,
@@ -32,6 +49,7 @@ pub struct FunctionCoverage<'tcx> {
3249 is_used : bool ,
3350 counters : IndexVec < CounterId , Option < CodeRegion > > ,
3451 expressions : IndexVec < ExpressionId , Option < Expression > > ,
52+ branches : Vec < CoverageBranch > ,
3553 unreachable_regions : Vec < CodeRegion > ,
3654}
3755
@@ -58,6 +76,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
5876 is_used,
5977 counters : IndexVec :: from_elem_n ( None , coverageinfo. num_counters as usize ) ,
6078 expressions : IndexVec :: from_elem_n ( None , coverageinfo. num_expressions as usize ) ,
79+ branches : Vec :: new ( ) ,
6180 unreachable_regions : Vec :: new ( ) ,
6281 }
6382 }
@@ -84,6 +103,11 @@ impl<'tcx> FunctionCoverage<'tcx> {
84103 }
85104 }
86105
106+ /// Adds a branch region using the two provided true/false operands
107+ pub fn add_branch_counter ( & mut self , true_ : Operand , false_ : Operand , region : CodeRegion ) {
108+ self . branches . push ( CoverageBranch { true_, false_, region } )
109+ }
110+
87111 /// Both counters and "counter expressions" (or simply, "expressions") can be operands in other
88112 /// expressions. These are tracked as separate variants of `Operand`, so there is no ambiguity
89113 /// between operands that are counter IDs and operands that are expression IDs.
@@ -185,7 +209,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
185209 /// `CoverageMapGenerator` will create `CounterMappingRegion`s.
186210 pub fn get_expressions_and_counter_regions (
187211 & self ,
188- ) -> ( Vec < CounterExpression > , Vec < ( Counter , & CodeRegion ) > ) {
212+ ) -> ( Vec < CounterExpression > , Vec < CoverageCounterAndRegion < ' _ > > ) {
189213 assert ! (
190214 self . source_hash != 0 || !self . is_used,
191215 "No counters provided the source_hash for used function: {:?}" ,
@@ -201,26 +225,43 @@ impl<'tcx> FunctionCoverage<'tcx> {
201225 let counter_regions = self . counters . iter_enumerated ( ) . filter_map ( |( index, entry) | {
202226 // Option::map() will return None to filter out missing counters. This may happen
203227 // if, for example, a MIR-instrumented counter is removed during an optimization.
204- entry. as_ref ( ) . map ( |region| ( Counter :: counter_value_reference ( index) , region) )
228+ entry. as_ref ( ) . map ( |region| CoverageCounterAndRegion {
229+ kind : CoverageCounterKind :: Counter ( Counter :: counter_value_reference ( index) ) ,
230+ region,
231+ } )
205232 } ) ;
206233
207234 // Find all of the expression IDs that weren't optimized out AND have
208235 // an attached code region, and return the corresponding mapping as a
209236 // counter/region pair.
210237 let expression_regions =
211238 self . expressions . iter_enumerated ( ) . filter_map ( |( id, expression) | {
212- let code_region = expression. as_ref ( ) ?. region . as_ref ( ) ?;
213- Some ( ( Counter :: expression ( id) , code_region) )
239+ let region = expression. as_ref ( ) ?. region . as_ref ( ) ?;
240+ Some ( CoverageCounterAndRegion {
241+ kind : CoverageCounterKind :: Counter ( Counter :: expression ( id) ) ,
242+ region,
243+ } )
214244 } ) ;
215- let unreachable_regions =
216- self . unreachable_regions . iter ( ) . map ( |region| ( Counter :: ZERO , region) ) ;
245+
246+ let unreachable_regions = self . unreachable_regions . iter ( ) . map ( |region| {
247+ CoverageCounterAndRegion { kind : CoverageCounterKind :: Counter ( Counter :: ZERO ) , region }
248+ } ) ;
249+
250+ let branch_regions = self . branches . iter ( ) . map ( |branch| CoverageCounterAndRegion {
251+ kind : CoverageCounterKind :: Branch {
252+ true_counter : Counter :: from_operand ( branch. true_ ) ,
253+ false_counter : Counter :: from_operand ( branch. false_ ) ,
254+ } ,
255+ region : & branch. region ,
256+ } ) ;
217257
218258 let mut all_regions: Vec < _ > = expression_regions. collect ( ) ;
219259 all_regions. extend ( counter_regions) ;
220260 all_regions. extend ( unreachable_regions) ;
261+ all_regions. extend ( branch_regions) ;
221262
222263 // make sure all the regions are sorted
223- all_regions. sort_unstable_by_key ( |( _counter , region ) | * region) ;
264+ all_regions. sort_unstable_by_key ( |coverage_region| coverage_region . region ) ;
224265
225266 ( counter_expressions, all_regions)
226267 }
0 commit comments