@@ -8,7 +8,7 @@ mod spans;
88mod tests;
99
1010use self :: counters:: { BcbCounter , CoverageCounters } ;
11- use self :: graph:: CoverageGraph ;
11+ use self :: graph:: { BasicCoverageBlock , CoverageGraph } ;
1212use self :: spans:: CoverageSpans ;
1313
1414use crate :: MirPass ;
@@ -70,7 +70,6 @@ struct Instrumentor<'a, 'tcx> {
7070 mir_body : & ' a mut mir:: Body < ' tcx > ,
7171 hir_info : ExtractedHirInfo ,
7272 basic_coverage_blocks : CoverageGraph ,
73- coverage_counters : CoverageCounters ,
7473}
7574
7675impl < ' a , ' tcx > Instrumentor < ' a , ' tcx > {
@@ -80,9 +79,8 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
8079 debug ! ( ?hir_info, "instrumenting {:?}" , mir_body. source. def_id( ) ) ;
8180
8281 let basic_coverage_blocks = CoverageGraph :: from_mir ( mir_body) ;
83- let coverage_counters = CoverageCounters :: new ( & basic_coverage_blocks) ;
8482
85- Self { tcx, mir_body, hir_info, basic_coverage_blocks, coverage_counters }
83+ Self { tcx, mir_body, hir_info, basic_coverage_blocks }
8684 }
8785
8886 fn inject_counters ( & ' a mut self ) {
@@ -103,25 +101,31 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
103101 // and all `Expression` dependencies (operands) are also generated, for any other
104102 // `BasicCoverageBlock`s not already associated with a coverage span.
105103 let bcb_has_coverage_spans = |bcb| coverage_spans. bcb_has_coverage_spans ( bcb) ;
106- self . coverage_counters
107- . make_bcb_counters ( & self . basic_coverage_blocks , bcb_has_coverage_spans) ;
104+ let coverage_counters = CoverageCounters :: make_bcb_counters (
105+ & self . basic_coverage_blocks ,
106+ bcb_has_coverage_spans,
107+ ) ;
108108
109- let mappings = self . create_mappings_and_inject_coverage_statements ( & coverage_spans) ;
109+ let mappings = self . create_mappings ( & coverage_spans, & coverage_counters) ;
110+ self . inject_coverage_statements ( bcb_has_coverage_spans, & coverage_counters) ;
110111
111112 self . mir_body . function_coverage_info = Some ( Box :: new ( FunctionCoverageInfo {
112113 function_source_hash : self . hir_info . function_source_hash ,
113- num_counters : self . coverage_counters . num_counters ( ) ,
114- expressions : self . coverage_counters . take_expressions ( ) ,
114+ num_counters : coverage_counters. num_counters ( ) ,
115+ expressions : coverage_counters. into_expressions ( ) ,
115116 mappings,
116117 } ) ) ;
117118 }
118119
119- /// For each [`BcbCounter`] associated with a BCB node or BCB edge, create
120- /// any corresponding mappings (for BCB nodes only), and inject any necessary
121- /// coverage statements into MIR.
122- fn create_mappings_and_inject_coverage_statements (
123- & mut self ,
120+ /// For each coverage span extracted from MIR, create a corresponding
121+ /// mapping.
122+ ///
123+ /// Precondition: All BCBs corresponding to those spans have been given
124+ /// coverage counters.
125+ fn create_mappings (
126+ & self ,
124127 coverage_spans : & CoverageSpans ,
128+ coverage_counters : & CoverageCounters ,
125129 ) -> Vec < Mapping > {
126130 let source_map = self . tcx . sess . source_map ( ) ;
127131 let body_span = self . hir_info . body_span ;
@@ -131,30 +135,42 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
131135 let file_name =
132136 Symbol :: intern ( & source_file. name . for_codegen ( self . tcx . sess ) . to_string_lossy ( ) ) ;
133137
134- let mut mappings = Vec :: new ( ) ;
135-
136- // Process the counters and spans associated with BCB nodes.
137- for ( bcb, counter_kind) in self . coverage_counters . bcb_node_counters ( ) {
138- let spans = coverage_spans. spans_for_bcb ( bcb) ;
139- let has_mappings = !spans. is_empty ( ) ;
140-
141- // If this BCB has any coverage spans, add corresponding mappings to
142- // the mappings table.
143- if has_mappings {
144- let term = counter_kind. as_term ( ) ;
145- mappings. extend ( spans. iter ( ) . map ( |& span| {
146- let code_region = make_code_region ( source_map, file_name, span, body_span) ;
147- Mapping { code_region, term }
148- } ) ) ;
149- }
138+ coverage_spans
139+ . bcbs_with_coverage_spans ( )
140+ // For each BCB with spans, get a coverage term for its counter.
141+ . map ( |( bcb, spans) | {
142+ let term = coverage_counters
143+ . bcb_counter ( bcb)
144+ . expect ( "all BCBs with spans were given counters" )
145+ . as_term ( ) ;
146+ ( term, spans)
147+ } )
148+ // Flatten the spans into individual term/span pairs.
149+ . flat_map ( |( term, spans) | spans. iter ( ) . map ( move |& span| ( term, span) ) )
150+ // Convert each span to a code region, and create the final mapping.
151+ . map ( |( term, span) | {
152+ let code_region = make_code_region ( source_map, file_name, span, body_span) ;
153+ Mapping { term, code_region }
154+ } )
155+ . collect :: < Vec < _ > > ( )
156+ }
150157
158+ /// For each BCB node or BCB edge that has an associated coverage counter,
159+ /// inject any necessary coverage statements into MIR.
160+ fn inject_coverage_statements (
161+ & mut self ,
162+ bcb_has_coverage_spans : impl Fn ( BasicCoverageBlock ) -> bool ,
163+ coverage_counters : & CoverageCounters ,
164+ ) {
165+ // Process the counters associated with BCB nodes.
166+ for ( bcb, counter_kind) in coverage_counters. bcb_node_counters ( ) {
151167 let do_inject = match counter_kind {
152168 // Counter-increment statements always need to be injected.
153169 BcbCounter :: Counter { .. } => true ,
154170 // The only purpose of expression-used statements is to detect
155171 // when a mapping is unreachable, so we only inject them for
156172 // expressions with one or more mappings.
157- BcbCounter :: Expression { .. } => has_mappings ,
173+ BcbCounter :: Expression { .. } => bcb_has_coverage_spans ( bcb ) ,
158174 } ;
159175 if do_inject {
160176 inject_statement (
@@ -166,7 +182,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
166182 }
167183
168184 // Process the counters associated with BCB edges.
169- for ( from_bcb, to_bcb, counter_kind) in self . coverage_counters . bcb_edge_counters ( ) {
185+ for ( from_bcb, to_bcb, counter_kind) in coverage_counters. bcb_edge_counters ( ) {
170186 let do_inject = match counter_kind {
171187 // Counter-increment statements always need to be injected.
172188 BcbCounter :: Counter { .. } => true ,
@@ -192,8 +208,6 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
192208 // Inject a counter into the newly-created BB.
193209 inject_statement ( self . mir_body , self . make_mir_coverage_kind ( counter_kind) , new_bb) ;
194210 }
195-
196- mappings
197211 }
198212
199213 fn make_mir_coverage_kind ( & self , counter_kind : & BcbCounter ) -> CoverageKind {
0 commit comments