@@ -8,7 +8,7 @@ mod spans;
88mod tests;
99
1010use self :: counters:: { BcbCounter , CoverageCounters } ;
11- use self :: graph:: { BasicCoverageBlock , BasicCoverageBlockData , CoverageGraph } ;
11+ use self :: graph:: CoverageGraph ;
1212use self :: spans:: CoverageSpans ;
1313
1414use crate :: MirPass ;
@@ -104,7 +104,6 @@ struct Instrumentor<'a, 'tcx> {
104104 function_source_hash : u64 ,
105105 basic_coverage_blocks : CoverageGraph ,
106106 coverage_counters : CoverageCounters ,
107- mappings : Vec < Mapping > ,
108107}
109108
110109impl < ' a , ' tcx > Instrumentor < ' a , ' tcx > {
@@ -145,7 +144,6 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
145144 function_source_hash,
146145 basic_coverage_blocks,
147146 coverage_counters,
148- mappings : Vec :: new ( ) ,
149147 }
150148 }
151149
@@ -168,148 +166,99 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
168166 // and all `Expression` dependencies (operands) are also generated, for any other
169167 // `BasicCoverageBlock`s not already associated with a coverage span.
170168 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+ } ) ;
196174
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) ;
200176
201177 self . mir_body . function_coverage_info = Some ( Box :: new ( FunctionCoverageInfo {
202178 function_source_hash : self . function_source_hash ,
203179 num_counters : self . coverage_counters . num_counters ( ) ,
204180 expressions : self . coverage_counters . take_expressions ( ) ,
205- mappings : std :: mem :: take ( & mut self . mappings ) ,
181+ mappings,
206182 } ) ) ;
207183 }
208184
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 ( ) ;
214193 let body_span = self . body_span ;
215194
216195 use rustc_session:: RemapFileNameExt ;
217196 let file_name =
218197 Symbol :: intern ( & self . source_file . name . for_codegen ( self . tcx . sess ) . to_string_lossy ( ) ) ;
219198
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+ }
238215
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+ }
259231 }
260232
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 ;
296244 }
297- }
298- }
299245
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 ( ) ;
304250
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+ }
309260
310- #[ inline]
311- fn bcb_data ( & self , bcb : BasicCoverageBlock ) -> & BasicCoverageBlockData {
312- & self . basic_coverage_blocks [ bcb]
261+ mappings
313262 }
314263
315264 fn make_mir_coverage_kind ( & self , counter_kind : & BcbCounter ) -> CoverageKind {
0 commit comments