@@ -8,7 +8,7 @@ mod spans;
8
8
mod tests;
9
9
10
10
use self :: counters:: { BcbCounter , CoverageCounters } ;
11
- use self :: graph:: { BasicCoverageBlock , BasicCoverageBlockData , CoverageGraph } ;
11
+ use self :: graph:: CoverageGraph ;
12
12
use self :: spans:: CoverageSpans ;
13
13
14
14
use crate :: MirPass ;
@@ -104,7 +104,6 @@ struct Instrumentor<'a, 'tcx> {
104
104
function_source_hash : u64 ,
105
105
basic_coverage_blocks : CoverageGraph ,
106
106
coverage_counters : CoverageCounters ,
107
- mappings : Vec < Mapping > ,
108
107
}
109
108
110
109
impl < ' a , ' tcx > Instrumentor < ' a , ' tcx > {
@@ -145,7 +144,6 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
145
144
function_source_hash,
146
145
basic_coverage_blocks,
147
146
coverage_counters,
148
- mappings : Vec :: new ( ) ,
149
147
}
150
148
}
151
149
@@ -168,145 +166,96 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
168
166
// and all `Expression` dependencies (operands) are also generated, for any other
169
167
// `BasicCoverageBlock`s not already associated with a coverage span.
170
168
let bcb_has_coverage_spans = |bcb| coverage_spans. bcb_has_coverage_spans ( bcb) ;
171
- let result = self
172
- . coverage_counters
173
- . make_bcb_counters ( & mut self . basic_coverage_blocks , bcb_has_coverage_spans) ;
174
-
175
- if let Ok ( ( ) ) = result {
176
- ////////////////////////////////////////////////////
177
- // Remove the counter or edge counter from of each coverage cpan's associated
178
- // `BasicCoverageBlock`, and inject a `Coverage` statement into the MIR.
179
- //
180
- // `Coverage` statements injected from coverage spans will include the code regions
181
- // (source code start and end positions) to be counted by the associated counter.
182
- //
183
- // These coverage-span-associated counters are removed from their associated
184
- // `BasicCoverageBlock`s so that the only remaining counters in the `CoverageGraph`
185
- // are indirect counters (to be injected next, without associated code regions).
186
- self . inject_coverage_span_counters ( & coverage_spans) ;
187
-
188
- ////////////////////////////////////////////////////
189
- // For any remaining `BasicCoverageBlock` counters (that were not associated with
190
- // any coverage span), inject `Coverage` statements (_without_ code region spans)
191
- // to ensure `BasicCoverageBlock` counters that other `Expression`s may depend on
192
- // are in fact counted, even though they don't directly contribute to counting
193
- // their own independent code region's coverage.
194
- self . inject_indirect_counters ( ) ;
195
- } ;
169
+ self . coverage_counters
170
+ . make_bcb_counters ( & mut self . basic_coverage_blocks , bcb_has_coverage_spans)
171
+ . unwrap_or_else ( |e| {
172
+ bug ! ( "Error processing: {:?}: {:?}" , self . mir_body. source. def_id( ) , e. message)
173
+ } ) ;
196
174
197
- if let Err ( e) = result {
198
- bug ! ( "Error processing: {:?}: {:?}" , self . mir_body. source. def_id( ) , e. message)
199
- } ;
175
+ let mappings = self . create_mappings_and_inject_coverage_statements ( & coverage_spans) ;
200
176
201
177
self . mir_body . function_coverage_info = Some ( Box :: new ( FunctionCoverageInfo {
202
178
function_source_hash : self . function_source_hash ,
203
179
num_counters : self . coverage_counters . num_counters ( ) ,
204
180
expressions : self . coverage_counters . take_expressions ( ) ,
205
- mappings : std :: mem :: take ( & mut self . mappings ) ,
181
+ mappings,
206
182
} ) ) ;
207
183
}
208
184
209
- /// Injects a single [`StatementKind::Coverage`] for each BCB that has one
210
- /// or more coverage spans.
211
- fn inject_coverage_span_counters ( & mut self , coverage_spans : & CoverageSpans ) {
212
- let tcx = self . tcx ;
213
- let source_map = tcx. sess . source_map ( ) ;
185
+ /// For each [`BcbCounter`] associated with a BCB node or BCB edge, create
186
+ /// any corresponding mappings (for BCB nodes only), and inject any necessary
187
+ /// coverage statements into MIR.
188
+ fn create_mappings_and_inject_coverage_statements (
189
+ & mut self ,
190
+ coverage_spans : & CoverageSpans ,
191
+ ) -> Vec < Mapping > {
192
+ let source_map = self . tcx . sess . source_map ( ) ;
214
193
let body_span = self . body_span ;
215
194
let file_name = Symbol :: intern ( & self . source_file . name . prefer_remapped ( ) . to_string_lossy ( ) ) ;
216
195
217
- for ( bcb, spans) in coverage_spans. bcbs_with_coverage_spans ( ) {
218
- let counter_kind = self . coverage_counters . take_bcb_counter ( bcb) . unwrap_or_else ( || {
219
- bug ! ( "Every BasicCoverageBlock should have a Counter or Expression" ) ;
220
- } ) ;
221
-
222
- let term = counter_kind. as_term ( ) ;
223
- self . mappings . extend ( spans. iter ( ) . map ( |& span| {
224
- let code_region = make_code_region ( source_map, file_name, span, body_span) ;
225
- Mapping { code_region, term }
226
- } ) ) ;
227
-
228
- inject_statement (
229
- self . mir_body ,
230
- self . make_mir_coverage_kind ( & counter_kind) ,
231
- self . bcb_leader_bb ( bcb) ,
232
- ) ;
233
- }
234
- }
196
+ let mut mappings = Vec :: new ( ) ;
197
+
198
+ // Process the counters and spans associated with BCB nodes.
199
+ for ( bcb, counter_kind) in self . coverage_counters . bcb_node_counters ( ) {
200
+ let spans = coverage_spans. spans_for_bcb ( bcb) ;
201
+ let has_mappings = !spans. is_empty ( ) ;
202
+
203
+ // If this BCB has any coverage spans, add corresponding mappings to
204
+ // the mappings table.
205
+ if has_mappings {
206
+ let term = counter_kind. as_term ( ) ;
207
+ mappings. extend ( spans. iter ( ) . map ( |& span| {
208
+ let code_region = make_code_region ( source_map, file_name, span, body_span) ;
209
+ Mapping { code_region, term }
210
+ } ) ) ;
211
+ }
235
212
236
- /// At this point, any BCB with coverage counters has already had its counter injected
237
- /// into MIR, and had its counter removed from `coverage_counters` (via `take_counter()`).
238
- ///
239
- /// Any other counter associated with a `BasicCoverageBlock`, or its incoming edge, but not
240
- /// associated with a coverage span, should only exist if the counter is an `Expression`
241
- /// dependency (one of the expression operands). Collect them, and inject the additional
242
- /// counters into the MIR, without a reportable coverage span.
243
- fn inject_indirect_counters ( & mut self ) {
244
- let mut bcb_counters_without_direct_coverage_spans = Vec :: new ( ) ;
245
- for ( target_bcb, counter_kind) in self . coverage_counters . drain_bcb_counters ( ) {
246
- bcb_counters_without_direct_coverage_spans. push ( ( None , target_bcb, counter_kind) ) ;
247
- }
248
- for ( ( from_bcb, target_bcb) , counter_kind) in
249
- self . coverage_counters . drain_bcb_edge_counters ( )
250
- {
251
- bcb_counters_without_direct_coverage_spans. push ( (
252
- Some ( from_bcb) ,
253
- target_bcb,
254
- counter_kind,
255
- ) ) ;
213
+ let do_inject = match counter_kind {
214
+ // Counter-increment statements always need to be injected.
215
+ BcbCounter :: Counter { .. } => true ,
216
+ // The only purpose of expression-used statements is to detect
217
+ // when a mapping is unreachable, so we only inject them for
218
+ // expressions with one or more mappings.
219
+ BcbCounter :: Expression { .. } => has_mappings,
220
+ } ;
221
+ if do_inject {
222
+ inject_statement (
223
+ self . mir_body ,
224
+ self . make_mir_coverage_kind ( counter_kind) ,
225
+ self . basic_coverage_blocks [ bcb] . leader_bb ( ) ,
226
+ ) ;
227
+ }
256
228
}
257
229
258
- for ( edge_from_bcb, target_bcb, counter_kind) in bcb_counters_without_direct_coverage_spans
259
- {
260
- match counter_kind {
261
- BcbCounter :: Counter { .. } => {
262
- let inject_to_bb = if let Some ( from_bcb) = edge_from_bcb {
263
- // The MIR edge starts `from_bb` (the outgoing / last BasicBlock in
264
- // `from_bcb`) and ends at `to_bb` (the incoming / first BasicBlock in the
265
- // `target_bcb`; also called the `leader_bb`).
266
- let from_bb = self . bcb_last_bb ( from_bcb) ;
267
- let to_bb = self . bcb_leader_bb ( target_bcb) ;
268
-
269
- let new_bb = inject_edge_counter_basic_block ( self . mir_body , from_bb, to_bb) ;
270
- debug ! (
271
- "Edge {:?} (last {:?}) -> {:?} (leader {:?}) requires a new MIR \
272
- BasicBlock {:?}, for unclaimed edge counter {:?}",
273
- edge_from_bcb, from_bb, target_bcb, to_bb, new_bb, counter_kind,
274
- ) ;
275
- new_bb
276
- } else {
277
- let target_bb = self . bcb_last_bb ( target_bcb) ;
278
- debug ! (
279
- "{:?} ({:?}) gets a new Coverage statement for unclaimed counter {:?}" ,
280
- target_bcb, target_bb, counter_kind,
281
- ) ;
282
- target_bb
283
- } ;
284
-
285
- inject_statement (
286
- self . mir_body ,
287
- self . make_mir_coverage_kind ( & counter_kind) ,
288
- inject_to_bb,
289
- ) ;
290
- }
291
- // Experessions with no associated spans don't need to inject a statement.
292
- BcbCounter :: Expression { .. } => { }
230
+ // Process the counters associated with BCB edges.
231
+ for ( ( from_bcb, to_bcb) , counter_kind) in self . coverage_counters . bcb_edge_counters ( ) {
232
+ let do_inject = match counter_kind {
233
+ // Counter-increment statements always need to be injected.
234
+ BcbCounter :: Counter { .. } => true ,
235
+ // BCB-edge expressions never have mappings, so they never need
236
+ // a corresponding statement.
237
+ BcbCounter :: Expression { .. } => false ,
238
+ } ;
239
+ if !do_inject {
240
+ continue ;
293
241
}
294
- }
295
- }
296
242
297
- # [ inline ]
298
- fn bcb_leader_bb ( & self , bcb : BasicCoverageBlock ) -> BasicBlock {
299
- self . bcb_data ( bcb ) . leader_bb ( )
300
- }
243
+ // We need to inject a coverage statement into a new BB between the
244
+ // last BB of `from_bcb` and the first BB of `to_bcb`.
245
+ let from_bb = self . basic_coverage_blocks [ from_bcb ] . last_bb ( ) ;
246
+ let to_bb = self . basic_coverage_blocks [ to_bcb ] . leader_bb ( ) ;
301
247
302
- #[ inline]
303
- fn bcb_last_bb ( & self , bcb : BasicCoverageBlock ) -> BasicBlock {
304
- self . bcb_data ( bcb) . last_bb ( )
305
- }
248
+ let new_bb = inject_edge_counter_basic_block ( self . mir_body , from_bb, to_bb) ;
249
+ debug ! (
250
+ "Edge {from_bcb:?} (last {from_bb:?}) -> {to_bcb:?} (leader {to_bb:?}) \
251
+ requires a new MIR BasicBlock {new_bb:?} for edge counter {counter_kind:?}",
252
+ ) ;
253
+
254
+ // Inject a counter into the newly-created BB.
255
+ inject_statement ( self . mir_body , self . make_mir_coverage_kind ( & counter_kind) , new_bb) ;
256
+ }
306
257
307
- #[ inline]
308
- fn bcb_data ( & self , bcb : BasicCoverageBlock ) -> & BasicCoverageBlockData {
309
- & self . basic_coverage_blocks [ bcb]
258
+ mappings
310
259
}
311
260
312
261
fn make_mir_coverage_kind ( & self , counter_kind : & BcbCounter ) -> CoverageKind {
0 commit comments