@@ -23,14 +23,13 @@ pub struct FunctionCoverage<'tcx> {
2323 function_coverage_info : & ' tcx FunctionCoverageInfo ,
2424 is_used : bool ,
2525
26- /// Tracks which counters have been seen, to avoid duplicate mappings
27- /// that might be introduced by MIR inlining .
26+ /// Tracks which counters have been seen, so that we can identify mappings
27+ /// to counters that were optimized out, and set them to zero .
2828 counters_seen : BitSet < CounterId > ,
2929 expressions : IndexVec < ExpressionId , Option < Expression > > ,
3030 /// Tracks which expressions are known to always have a value of zero.
3131 /// Only updated during the finalize step.
3232 zero_expressions : FxIndexSet < ExpressionId > ,
33- mappings : Vec < Mapping > ,
3433}
3534
3635impl < ' tcx > FunctionCoverage < ' tcx > {
@@ -67,7 +66,6 @@ impl<'tcx> FunctionCoverage<'tcx> {
6766 counters_seen : BitSet :: new_empty ( num_counters) ,
6867 expressions : IndexVec :: from_elem_n ( None , num_expressions) ,
6968 zero_expressions : FxIndexSet :: default ( ) ,
70- mappings : Vec :: new ( ) ,
7169 }
7270 }
7371
@@ -76,28 +74,20 @@ impl<'tcx> FunctionCoverage<'tcx> {
7674 self . is_used
7775 }
7876
79- /// Adds code regions to be counted by an injected counter intrinsic .
77+ /// Marks a counter ID as having been seen in a counter-increment statement .
8078 #[ instrument( level = "debug" , skip( self ) ) ]
81- pub ( crate ) fn add_counter ( & mut self , id : CounterId , code_regions : & [ CodeRegion ] ) {
82- if self . counters_seen . insert ( id) {
83- self . add_mappings ( CovTerm :: Counter ( id) , code_regions) ;
84- }
79+ pub ( crate ) fn add_counter ( & mut self , id : CounterId ) {
80+ self . counters_seen . insert ( id) ;
8581 }
8682
87- /// Adds information about a coverage expression, along with zero or more
88- /// code regions mapped to that expression.
89- ///
90- /// Both counters and "counter expressions" (or simply, "expressions") can be operands in other
91- /// expressions. These are tracked as separate variants of `CovTerm`, so there is no ambiguity
92- /// between operands that are counter IDs and operands that are expression IDs.
83+ /// Adds information about a coverage expression.
9384 #[ instrument( level = "debug" , skip( self ) ) ]
9485 pub ( crate ) fn add_counter_expression (
9586 & mut self ,
9687 expression_id : ExpressionId ,
9788 lhs : CovTerm ,
9889 op : Op ,
9990 rhs : CovTerm ,
100- code_regions : & [ CodeRegion ] ,
10191 ) {
10292 debug_assert ! (
10393 expression_id. as_usize( ) < self . expressions. len( ) ,
@@ -111,10 +101,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
111101 let expression = Expression { lhs, op, rhs } ;
112102 let slot = & mut self . expressions [ expression_id] ;
113103 match slot {
114- None => {
115- * slot = Some ( expression) ;
116- self . add_mappings ( CovTerm :: Expression ( expression_id) , code_regions) ;
117- }
104+ None => * slot = Some ( expression) ,
118105 // If this expression ID slot has already been filled, it should
119106 // contain identical information.
120107 Some ( ref previous_expression) => assert_eq ! (
@@ -124,25 +111,8 @@ impl<'tcx> FunctionCoverage<'tcx> {
124111 }
125112 }
126113
127- /// Adds regions that will be marked as "unreachable", with a constant "zero counter".
128- #[ instrument( level = "debug" , skip( self ) ) ]
129- pub ( crate ) fn add_unreachable_regions ( & mut self , code_regions : & [ CodeRegion ] ) {
130- assert ! ( !code_regions. is_empty( ) , "unreachable regions always have code regions" ) ;
131- self . add_mappings ( CovTerm :: Zero , code_regions) ;
132- }
133-
134- #[ instrument( level = "debug" , skip( self ) ) ]
135- fn add_mappings ( & mut self , term : CovTerm , code_regions : & [ CodeRegion ] ) {
136- self . mappings
137- . extend ( code_regions. iter ( ) . cloned ( ) . map ( |code_region| Mapping { term, code_region } ) ) ;
138- }
139-
140114 pub ( crate ) fn finalize ( & mut self ) {
141115 self . update_zero_expressions ( ) ;
142-
143- // Sort all of the collected mappings into a predictable order.
144- // (Mappings have a total order, so an unstable sort should be fine.)
145- self . mappings . sort_unstable ( ) ;
146116 }
147117
148118 /// Identify expressions that will always have a value of zero, and note
@@ -249,8 +219,17 @@ impl<'tcx> FunctionCoverage<'tcx> {
249219 /// Converts this function's coverage mappings into an intermediate form
250220 /// that will be used by `mapgen` when preparing for FFI.
251221 pub ( crate ) fn mappings_for_ffi ( & self ) -> impl Iterator < Item = ( Counter , & CodeRegion ) > {
252- self . mappings . iter ( ) . map ( |& Mapping { term, ref code_region } | {
253- let counter = Counter :: from_term ( term) ;
222+ self . function_coverage_info . mappings . iter ( ) . map ( |& Mapping { term, ref code_region } | {
223+ // Historically, mappings were stored directly in counter/expression
224+ // statements in MIR, and MIR optimizations would sometimes remove them.
225+ // That's mostly no longer true, so now we detect cases where that would
226+ // have happened, and zero out the corresponding mappings here instead.
227+ let force_to_zero = match term {
228+ CovTerm :: Counter ( id) => !self . counters_seen . contains ( id) ,
229+ CovTerm :: Expression ( id) => self . zero_expressions . contains ( & id) ,
230+ CovTerm :: Zero => false ,
231+ } ;
232+ let counter = if force_to_zero { Counter :: ZERO } else { Counter :: from_term ( term) } ;
254233 ( counter, code_region)
255234 } )
256235 }
0 commit comments