@@ -23,11 +23,10 @@ pub struct FunctionCoverage<'tcx> {
23
23
function_coverage_info : & ' tcx FunctionCoverageInfo ,
24
24
is_used : bool ,
25
25
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 .
28
28
counters_seen : BitSet < CounterId > ,
29
29
expressions : IndexVec < ExpressionId , Option < Expression > > ,
30
- mappings : Vec < Mapping > ,
31
30
}
32
31
33
32
impl < ' tcx > FunctionCoverage < ' tcx > {
@@ -63,7 +62,6 @@ impl<'tcx> FunctionCoverage<'tcx> {
63
62
is_used,
64
63
counters_seen : BitSet :: new_empty ( num_counters) ,
65
64
expressions : IndexVec :: from_elem_n ( None , num_expressions) ,
66
- mappings : Vec :: new ( ) ,
67
65
}
68
66
}
69
67
@@ -72,28 +70,20 @@ impl<'tcx> FunctionCoverage<'tcx> {
72
70
self . is_used
73
71
}
74
72
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 .
76
74
#[ 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 add_counter ( & mut self , id : CounterId ) {
76
+ self . counters_seen . insert ( id) ;
81
77
}
82
78
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.
89
80
#[ instrument( level = "debug" , skip( self ) ) ]
90
81
pub ( crate ) fn add_counter_expression (
91
82
& mut self ,
92
83
expression_id : ExpressionId ,
93
84
lhs : CovTerm ,
94
85
op : Op ,
95
86
rhs : CovTerm ,
96
- code_regions : & [ CodeRegion ] ,
97
87
) {
98
88
debug_assert ! (
99
89
expression_id. as_usize( ) < self . expressions. len( ) ,
@@ -107,10 +97,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
107
97
let expression = Expression { lhs, op, rhs } ;
108
98
let slot = & mut self . expressions [ expression_id] ;
109
99
match slot {
110
- None => {
111
- * slot = Some ( expression) ;
112
- self . add_mappings ( CovTerm :: Expression ( expression_id) , code_regions) ;
113
- }
100
+ None => * slot = Some ( expression) ,
114
101
// If this expression ID slot has already been filled, it should
115
102
// contain identical information.
116
103
Some ( ref previous_expression) => assert_eq ! (
@@ -120,29 +107,6 @@ impl<'tcx> FunctionCoverage<'tcx> {
120
107
}
121
108
}
122
109
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
-
146
110
/// Identify expressions that will always have a value of zero, and note
147
111
/// their IDs in `zero_expressions`. Mappings that refer to a zero expression
148
112
/// can instead become mappings to a constant zero value.
@@ -222,7 +186,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
222
186
// the two vectors should correspond 1:1.
223
187
assert_eq ! ( self . expressions. len( ) , counter_expressions. len( ) ) ;
224
188
225
- let counter_regions = self . counter_regions ( ) ;
189
+ let counter_regions = self . counter_regions ( zero_expressions ) ;
226
190
227
191
( counter_expressions, counter_regions)
228
192
}
@@ -267,9 +231,26 @@ impl<'tcx> FunctionCoverage<'tcx> {
267
231
268
232
/// Converts this function's coverage mappings into an intermediate form
269
233
/// 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) ;
273
254
( counter, code_region)
274
255
} )
275
256
}
0 commit comments