@@ -23,11 +23,10 @@ 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 > > ,
30- mappings : Vec < Mapping > ,
3130}
3231
3332impl < ' tcx > FunctionCoverage < ' tcx > {
@@ -63,7 +62,6 @@ impl<'tcx> FunctionCoverage<'tcx> {
6362 is_used,
6463 counters_seen : BitSet :: new_empty ( num_counters) ,
6564 expressions : IndexVec :: from_elem_n ( None , num_expressions) ,
66- mappings : Vec :: new ( ) ,
6765 }
6866 }
6967
@@ -72,28 +70,20 @@ impl<'tcx> FunctionCoverage<'tcx> {
7270 self . is_used
7371 }
7472
75- /// Adds code regions to be counted by an injected counter intrinsic .
73+ /// Marks a counter ID as having been seen in a counter-increment statement .
7674 #[ instrument( level = "debug" , skip( self ) ) ]
77- pub ( crate ) fn add_counter ( & mut self , id : CounterId , code_regions : & [ CodeRegion ] ) {
78- if self . counters_seen . insert ( id) {
79- self . add_mappings ( CovTerm :: Counter ( id) , code_regions) ;
80- }
75+ pub ( crate ) fn mark_counter_id_seen ( & mut self , id : CounterId ) {
76+ self . counters_seen . insert ( id) ;
8177 }
8278
83- /// Adds information about a coverage expression, along with zero or more
84- /// code regions mapped to that expression.
85- ///
86- /// Both counters and "counter expressions" (or simply, "expressions") can be operands in other
87- /// expressions. These are tracked as separate variants of `CovTerm`, so there is no ambiguity
88- /// between operands that are counter IDs and operands that are expression IDs.
79+ /// Adds information about a coverage expression.
8980 #[ instrument( level = "debug" , skip( self ) ) ]
9081 pub ( crate ) fn add_counter_expression (
9182 & mut self ,
9283 expression_id : ExpressionId ,
9384 lhs : CovTerm ,
9485 op : Op ,
9586 rhs : CovTerm ,
96- code_regions : & [ CodeRegion ] ,
9787 ) {
9888 debug_assert ! (
9989 expression_id. as_usize( ) < self . expressions. len( ) ,
@@ -107,10 +97,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
10797 let expression = Expression { lhs, op, rhs } ;
10898 let slot = & mut self . expressions [ expression_id] ;
10999 match slot {
110- None => {
111- * slot = Some ( expression) ;
112- self . add_mappings ( CovTerm :: Expression ( expression_id) , code_regions) ;
113- }
100+ None => * slot = Some ( expression) ,
114101 // If this expression ID slot has already been filled, it should
115102 // contain identical information.
116103 Some ( ref previous_expression) => assert_eq ! (
@@ -120,29 +107,6 @@ impl<'tcx> FunctionCoverage<'tcx> {
120107 }
121108 }
122109
123- /// Adds regions that will be marked as "unreachable", with a constant "zero counter".
124- #[ instrument( level = "debug" , skip( self ) ) ]
125- pub ( crate ) fn add_unreachable_regions ( & mut self , code_regions : & [ CodeRegion ] ) {
126- assert ! ( !code_regions. is_empty( ) , "unreachable regions always have code regions" ) ;
127- self . add_mappings ( CovTerm :: Zero , code_regions) ;
128- }
129-
130- #[ instrument( level = "debug" , skip( self ) ) ]
131- fn add_mappings ( & mut self , term : CovTerm , code_regions : & [ CodeRegion ] ) {
132- self . mappings
133- . extend ( code_regions. iter ( ) . cloned ( ) . map ( |code_region| Mapping { term, code_region } ) ) ;
134- }
135-
136- pub ( crate ) fn finalize ( & mut self ) {
137- // Reorder the collected mappings so that counter mappings are first and
138- // zero mappings are last, matching the historical order.
139- self . mappings . sort_by_key ( |mapping| match mapping. term {
140- CovTerm :: Counter ( _) => 0 ,
141- CovTerm :: Expression ( _) => 1 ,
142- CovTerm :: Zero => u8:: MAX ,
143- } ) ;
144- }
145-
146110 /// Identify expressions that will always have a value of zero, and note
147111 /// their IDs in `zero_expressions`. Mappings that refer to a zero expression
148112 /// can instead become mappings to a constant zero value.
@@ -222,7 +186,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
222186 // the two vectors should correspond 1:1.
223187 assert_eq ! ( self . expressions. len( ) , counter_expressions. len( ) ) ;
224188
225- let counter_regions = self . counter_regions ( ) ;
189+ let counter_regions = self . counter_regions ( zero_expressions ) ;
226190
227191 ( counter_expressions, counter_regions)
228192 }
@@ -267,9 +231,26 @@ impl<'tcx> FunctionCoverage<'tcx> {
267231
268232 /// Converts this function's coverage mappings into an intermediate form
269233 /// that will be used by `mapgen` when preparing for FFI.
270- fn counter_regions ( & self ) -> impl Iterator < Item = ( Counter , & CodeRegion ) > {
271- self . mappings . iter ( ) . map ( |& Mapping { term, ref code_region } | {
272- let counter = Counter :: from_term ( term) ;
234+ fn counter_regions (
235+ & self ,
236+ zero_expressions : ZeroExpressions ,
237+ ) -> impl Iterator < Item = ( Counter , & CodeRegion ) > {
238+ // Historically, mappings were stored directly in counter/expression
239+ // statements in MIR, and MIR optimizations would sometimes remove them.
240+ // That's mostly no longer true, so now we detect cases where that would
241+ // have happened, and zero out the corresponding mappings here instead.
242+ let counter_for_term = move |term : CovTerm | {
243+ let force_to_zero = match term {
244+ CovTerm :: Counter ( id) => !self . counters_seen . contains ( id) ,
245+ CovTerm :: Expression ( id) => zero_expressions. contains ( id) ,
246+ CovTerm :: Zero => false ,
247+ } ;
248+ if force_to_zero { Counter :: ZERO } else { Counter :: from_term ( term) }
249+ } ;
250+
251+ self . function_coverage_info . mappings . iter ( ) . map ( move |mapping| {
252+ let & Mapping { term, ref code_region } = mapping;
253+ let counter = counter_for_term ( term) ;
273254 ( counter, code_region)
274255 } )
275256 }
0 commit comments