@@ -8,7 +8,7 @@ mod spans;
8
8
mod tests;
9
9
10
10
use self :: counters:: { BcbCounter , CoverageCounters } ;
11
- use self :: graph:: CoverageGraph ;
11
+ use self :: graph:: { BasicCoverageBlock , CoverageGraph } ;
12
12
use self :: spans:: CoverageSpans ;
13
13
14
14
use crate :: MirPass ;
@@ -70,7 +70,6 @@ struct Instrumentor<'a, 'tcx> {
70
70
mir_body : & ' a mut mir:: Body < ' tcx > ,
71
71
hir_info : ExtractedHirInfo ,
72
72
basic_coverage_blocks : CoverageGraph ,
73
- coverage_counters : CoverageCounters ,
74
73
}
75
74
76
75
impl < ' a , ' tcx > Instrumentor < ' a , ' tcx > {
@@ -80,9 +79,8 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
80
79
debug ! ( ?hir_info, "instrumenting {:?}" , mir_body. source. def_id( ) ) ;
81
80
82
81
let basic_coverage_blocks = CoverageGraph :: from_mir ( mir_body) ;
83
- let coverage_counters = CoverageCounters :: new ( & basic_coverage_blocks) ;
84
82
85
- Self { tcx, mir_body, hir_info, basic_coverage_blocks, coverage_counters }
83
+ Self { tcx, mir_body, hir_info, basic_coverage_blocks }
86
84
}
87
85
88
86
fn inject_counters ( & ' a mut self ) {
@@ -103,25 +101,31 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
103
101
// and all `Expression` dependencies (operands) are also generated, for any other
104
102
// `BasicCoverageBlock`s not already associated with a coverage span.
105
103
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
+ ) ;
108
108
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) ;
110
111
111
112
self . mir_body . function_coverage_info = Some ( Box :: new ( FunctionCoverageInfo {
112
113
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 ( ) ,
115
116
mappings,
116
117
} ) ) ;
117
118
}
118
119
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 ,
124
127
coverage_spans : & CoverageSpans ,
128
+ coverage_counters : & CoverageCounters ,
125
129
) -> Vec < Mapping > {
126
130
let source_map = self . tcx . sess . source_map ( ) ;
127
131
let body_span = self . hir_info . body_span ;
@@ -131,30 +135,42 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
131
135
let file_name =
132
136
Symbol :: intern ( & source_file. name . for_codegen ( self . tcx . sess ) . to_string_lossy ( ) ) ;
133
137
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
+ }
150
157
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 ( ) {
151
167
let do_inject = match counter_kind {
152
168
// Counter-increment statements always need to be injected.
153
169
BcbCounter :: Counter { .. } => true ,
154
170
// The only purpose of expression-used statements is to detect
155
171
// when a mapping is unreachable, so we only inject them for
156
172
// expressions with one or more mappings.
157
- BcbCounter :: Expression { .. } => has_mappings ,
173
+ BcbCounter :: Expression { .. } => bcb_has_coverage_spans ( bcb ) ,
158
174
} ;
159
175
if do_inject {
160
176
inject_statement (
@@ -166,7 +182,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
166
182
}
167
183
168
184
// 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 ( ) {
170
186
let do_inject = match counter_kind {
171
187
// Counter-increment statements always need to be injected.
172
188
BcbCounter :: Counter { .. } => true ,
@@ -192,8 +208,6 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
192
208
// Inject a counter into the newly-created BB.
193
209
inject_statement ( self . mir_body , self . make_mir_coverage_kind ( counter_kind) , new_bb) ;
194
210
}
195
-
196
- mappings
197
211
}
198
212
199
213
fn make_mir_coverage_kind ( & self , counter_kind : & BcbCounter ) -> CoverageKind {
0 commit comments