@@ -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,148 +166,99 @@ 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
216
195
use rustc_session:: RemapFileNameExt ;
217
196
let file_name =
218
197
Symbol :: intern ( & self . source_file . name . for_codegen ( self . tcx . sess ) . to_string_lossy ( ) ) ;
219
198
220
- for ( bcb, spans) in coverage_spans. bcbs_with_coverage_spans ( ) {
221
- let counter_kind = self . coverage_counters . take_bcb_counter ( bcb) . unwrap_or_else ( || {
222
- bug ! ( "Every BasicCoverageBlock should have a Counter or Expression" ) ;
223
- } ) ;
224
-
225
- let term = counter_kind. as_term ( ) ;
226
- self . mappings . extend ( spans. iter ( ) . map ( |& span| {
227
- let code_region = make_code_region ( source_map, file_name, span, body_span) ;
228
- Mapping { code_region, term }
229
- } ) ) ;
230
-
231
- inject_statement (
232
- self . mir_body ,
233
- self . make_mir_coverage_kind ( & counter_kind) ,
234
- self . bcb_leader_bb ( bcb) ,
235
- ) ;
236
- }
237
- }
199
+ let mut mappings = Vec :: new ( ) ;
200
+
201
+ // Process the counters and spans associated with BCB nodes.
202
+ for ( bcb, counter_kind) in self . coverage_counters . bcb_node_counters ( ) {
203
+ let spans = coverage_spans. spans_for_bcb ( bcb) ;
204
+ let has_mappings = !spans. is_empty ( ) ;
205
+
206
+ // If this BCB has any coverage spans, add corresponding mappings to
207
+ // the mappings table.
208
+ if has_mappings {
209
+ let term = counter_kind. as_term ( ) ;
210
+ mappings. extend ( spans. iter ( ) . map ( |& span| {
211
+ let code_region = make_code_region ( source_map, file_name, span, body_span) ;
212
+ Mapping { code_region, term }
213
+ } ) ) ;
214
+ }
238
215
239
- /// At this point, any BCB with coverage counters has already had its counter injected
240
- /// into MIR, and had its counter removed from `coverage_counters` (via `take_counter()`).
241
- ///
242
- /// Any other counter associated with a `BasicCoverageBlock`, or its incoming edge, but not
243
- /// associated with a coverage span, should only exist if the counter is an `Expression`
244
- /// dependency (one of the expression operands). Collect them, and inject the additional
245
- /// counters into the MIR, without a reportable coverage span.
246
- fn inject_indirect_counters ( & mut self ) {
247
- let mut bcb_counters_without_direct_coverage_spans = Vec :: new ( ) ;
248
- for ( target_bcb, counter_kind) in self . coverage_counters . drain_bcb_counters ( ) {
249
- bcb_counters_without_direct_coverage_spans. push ( ( None , target_bcb, counter_kind) ) ;
250
- }
251
- for ( ( from_bcb, target_bcb) , counter_kind) in
252
- self . coverage_counters . drain_bcb_edge_counters ( )
253
- {
254
- bcb_counters_without_direct_coverage_spans. push ( (
255
- Some ( from_bcb) ,
256
- target_bcb,
257
- counter_kind,
258
- ) ) ;
216
+ let do_inject = match counter_kind {
217
+ // Counter-increment statements always need to be injected.
218
+ BcbCounter :: Counter { .. } => true ,
219
+ // The only purpose of expression-used statements is to detect
220
+ // when a mapping is unreachable, so we only inject them for
221
+ // expressions with one or more mappings.
222
+ BcbCounter :: Expression { .. } => has_mappings,
223
+ } ;
224
+ if do_inject {
225
+ inject_statement (
226
+ self . mir_body ,
227
+ self . make_mir_coverage_kind ( counter_kind) ,
228
+ self . basic_coverage_blocks [ bcb] . leader_bb ( ) ,
229
+ ) ;
230
+ }
259
231
}
260
232
261
- for ( edge_from_bcb, target_bcb, counter_kind) in bcb_counters_without_direct_coverage_spans
262
- {
263
- match counter_kind {
264
- BcbCounter :: Counter { .. } => {
265
- let inject_to_bb = if let Some ( from_bcb) = edge_from_bcb {
266
- // The MIR edge starts `from_bb` (the outgoing / last BasicBlock in
267
- // `from_bcb`) and ends at `to_bb` (the incoming / first BasicBlock in the
268
- // `target_bcb`; also called the `leader_bb`).
269
- let from_bb = self . bcb_last_bb ( from_bcb) ;
270
- let to_bb = self . bcb_leader_bb ( target_bcb) ;
271
-
272
- let new_bb = inject_edge_counter_basic_block ( self . mir_body , from_bb, to_bb) ;
273
- debug ! (
274
- "Edge {:?} (last {:?}) -> {:?} (leader {:?}) requires a new MIR \
275
- BasicBlock {:?}, for unclaimed edge counter {:?}",
276
- edge_from_bcb, from_bb, target_bcb, to_bb, new_bb, counter_kind,
277
- ) ;
278
- new_bb
279
- } else {
280
- let target_bb = self . bcb_last_bb ( target_bcb) ;
281
- debug ! (
282
- "{:?} ({:?}) gets a new Coverage statement for unclaimed counter {:?}" ,
283
- target_bcb, target_bb, counter_kind,
284
- ) ;
285
- target_bb
286
- } ;
287
-
288
- inject_statement (
289
- self . mir_body ,
290
- self . make_mir_coverage_kind ( & counter_kind) ,
291
- inject_to_bb,
292
- ) ;
293
- }
294
- // Experessions with no associated spans don't need to inject a statement.
295
- BcbCounter :: Expression { .. } => { }
233
+ // Process the counters associated with BCB edges.
234
+ for ( ( from_bcb, to_bcb) , counter_kind) in self . coverage_counters . bcb_edge_counters ( ) {
235
+ let do_inject = match counter_kind {
236
+ // Counter-increment statements always need to be injected.
237
+ BcbCounter :: Counter { .. } => true ,
238
+ // BCB-edge expressions never have mappings, so they never need
239
+ // a corresponding statement.
240
+ BcbCounter :: Expression { .. } => false ,
241
+ } ;
242
+ if !do_inject {
243
+ continue ;
296
244
}
297
- }
298
- }
299
245
300
- # [ inline ]
301
- fn bcb_leader_bb ( & self , bcb : BasicCoverageBlock ) -> BasicBlock {
302
- self . bcb_data ( bcb ) . leader_bb ( )
303
- }
246
+ // We need to inject a coverage statement into a new BB between the
247
+ // last BB of `from_bcb` and the first BB of `to_bcb`.
248
+ let from_bb = self . basic_coverage_blocks [ from_bcb ] . last_bb ( ) ;
249
+ let to_bb = self . basic_coverage_blocks [ to_bcb ] . leader_bb ( ) ;
304
250
305
- #[ inline]
306
- fn bcb_last_bb ( & self , bcb : BasicCoverageBlock ) -> BasicBlock {
307
- self . bcb_data ( bcb) . last_bb ( )
308
- }
251
+ let new_bb = inject_edge_counter_basic_block ( self . mir_body , from_bb, to_bb) ;
252
+ debug ! (
253
+ "Edge {from_bcb:?} (last {from_bb:?}) -> {to_bcb:?} (leader {to_bb:?}) \
254
+ requires a new MIR BasicBlock {new_bb:?} for edge counter {counter_kind:?}",
255
+ ) ;
256
+
257
+ // Inject a counter into the newly-created BB.
258
+ inject_statement ( self . mir_body , self . make_mir_coverage_kind ( & counter_kind) , new_bb) ;
259
+ }
309
260
310
- #[ inline]
311
- fn bcb_data ( & self , bcb : BasicCoverageBlock ) -> & BasicCoverageBlockData {
312
- & self . basic_coverage_blocks [ bcb]
261
+ mappings
313
262
}
314
263
315
264
fn make_mir_coverage_kind ( & self , counter_kind : & BcbCounter ) -> CoverageKind {
0 commit comments