@@ -73,21 +73,21 @@ When compiling with `-C instrument-coverage`,
73
73
Coverage instrumentation is performed on the MIR with a [ MIR pass] [ mir-passes ]
74
74
called [ ` InstrumentCoverage ` ] [ mir-instrument-coverage ] . This MIR pass analyzes
75
75
the control flow graph (CFG)--represented by MIR ` BasicBlock ` s--to identify
76
- code branches, and injects additional [ ` Coverage ` ] [ coverage-statement ]
77
- statements into the ` BasicBlock ` s.
76
+ code branches, attaches [ ` FunctionCoverageInfo ` ] to the function's body,
77
+ and injects additional [ ` Coverage ` ] [ coverage-statement ] statements into the
78
+ ` BasicBlock ` s.
78
79
79
80
A MIR ` Coverage ` statement is a virtual instruction that indicates a counter
80
81
should be incremented when its adjacent statements are executed, to count
81
82
a span of code ([ ` CodeRegion ` ] [ code-region ] ). It counts the number of times a
82
- branch is executed, and also specifies the exact location of that code span in
83
- the Rust source code .
83
+ branch is executed, and is referred to by coverage mappings in the function's
84
+ coverage-info struct .
84
85
85
- Note that many of these ` Coverage ` statements will _ not_ be converted into
86
+ Note that many coverage counters will _ not_ be converted into
86
87
physical counters (or any other executable instructions) in the final binary.
87
- Some of them will be (see [ ` CoverageKind::Counter ` ] ),
88
+ Some of them will be (see [ ` CoverageKind::CounterIncrement ` ] ),
88
89
but other counters can be computed on the fly, when generating a coverage
89
- report, by mapping a ` CodeRegion ` to a
90
- [ ` CoverageKind::Expression ` ] .
90
+ report, by mapping a ` CodeRegion ` to a coverage-counter _ expression_ .
91
91
92
92
As an example:
93
93
@@ -121,18 +121,18 @@ determines when to break out of a loop (a `while` condition, or an `if` or
121
121
` match ` with a ` break ` ). In MIR, this is typically lowered to a ` SwitchInt ` ,
122
122
with one branch to stay in the loop, and another branch to break out of the
123
123
loop. The branch that breaks out will almost always execute less often,
124
- so ` InstrumentCoverage ` chooses to add a ` Counter ` to that branch, and an
125
- ` Expression(continue) = Counter(loop) - Counter(break)` to the branch that
124
+ so ` InstrumentCoverage ` chooses to add a ` CounterIncrement ` to that branch, and
125
+ uses an expression ( ` Counter(loop) - Counter(break) ` ) for the branch that
126
126
continues.
127
127
128
128
The ` InstrumentCoverage ` MIR pass is documented in
129
129
[ more detail below] [ instrument-coverage-pass-details ] .
130
130
131
131
[ mir-passes ] : mir/passes.md
132
132
[ mir-instrument-coverage ] : https://github.com/rust-lang/rust/tree/master/compiler/rustc_mir_transform/src/coverage
133
+ [ `FunctionCoverageInfo` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/struct.FunctionCoverageInfo.html
133
134
[ code-region ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/struct.CodeRegion.html
134
- [ `CoverageKind::Counter` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.Counter
135
- [ `CoverageKind::Expression` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.Expression
135
+ [ `CoverageKind::CounterIncrement` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.CounterIncrement
136
136
[ coverage-statement ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.StatementKind.html#variant.Coverage
137
137
[ instrument-coverage-pass-details ] : #implementation-details-of-the-instrumentcoverage-mir-pass
138
138
@@ -150,40 +150,38 @@ MIR `Statement` into some backend-specific action or instruction.
150
150
match statement . kind {
151
151
...
152
152
mir :: StatementKind :: Coverage (box ref coverage ) => {
153
- self . codegen_coverage (& mut bx , coverage . clone (), statement . source_info. scope);
154
- bx
153
+ self . codegen_coverage (bx , coverage , statement . source_info. scope);
155
154
}
156
155
```
157
156
158
- ` codegen_coverage() ` handles each ` CoverageKind ` as follows:
157
+ ` codegen_coverage() ` handles inlined statements and then forwards the coverage
158
+ statement to [ ` Builder::add_coverage ` ] , which handles each ` CoverageKind ` as
159
+ follows:
159
160
160
- - For all ` CoverageKind ` s, Coverage data (counter ID, expression equation
161
- and ID, and code regions) are passed to the backend's ` Builder ` , to
162
- populate data structures that will be used to generate the crate's
163
- "Coverage Map". (See the [ ` FunctionCoverage ` ] [ function-coverage ] ` struct ` .)
164
- - For ` CoverageKind::Counter ` s, an instruction is injected in the backend
161
+
162
+ - For both ` CounterIncrement ` and ` ExpressionUsed ` , the underlying counter or
163
+ expression ID is passed through to the corresponding [ ` FunctionCoverage ` ]
164
+ struct to indicate that the corresponding regions of code were not removed
165
+ by MIR optimizations.
166
+ - For ` CoverageKind::CounterIncrement ` s, an instruction is injected in the backend
165
167
IR to increment the physical counter, by calling the ` BuilderMethod `
166
168
[ ` instrprof_increment() ` ] [ instrprof-increment ] .
167
169
168
170
``` rust
169
- pub fn codegen_coverage ( & self , bx : & mut Bx , coverage : Coverage , scope : SourceScope ) {
171
+ fn add_coverage ( & mut self , instance : Instance <' tcx > , coverage : & Coverage ) {
170
172
...
171
- let instance = ... // the scoped instance (current or inlined function)
172
- let Coverage { kind , code_region } = coverage ;
173
- match kind {
174
- CoverageKind :: Counter { function_source_hash , id } => {
175
- ...
176
- bx . add_coverage_counter (instance , id , code_region );
173
+ let Coverage { kind } = coverage ;
174
+ match * kind {
175
+ CoverageKind :: CounterIncrement { id } => {
176
+ func_coverage . mark_counter_id_seen (id );
177
177
...
178
178
bx . instrprof_increment (fn_name , hash , num_counters , index );
179
179
}
180
- CoverageKind :: Expression { id , lhs , op , rhs } => {
181
- bx . add_coverage_counter_expression ( instance , id , lhs , op , rhs , code_region );
180
+ CoverageKind :: ExpressionUsed { id } => {
181
+ func_coverage . mark_expression_id_seen ( id );
182
182
}
183
- CoverageKind :: Unreachable => {
184
- bx . add_coverage_unreachable (
185
- instance ,
186
- code_region . expect (...
183
+ }
184
+ }
187
185
```
188
186
189
187
> The function name ` instrprof_increment() ` is taken from the LLVM intrinsic
@@ -199,7 +197,8 @@ statements is only implemented for LLVM, at this time.
199
197
[ backend-lowering-mir ] : backend/lowering-mir.md
200
198
[ codegen-statement ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/struct.FunctionCx.html#method.codegen_statement
201
199
[ codegen-coverage ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/struct.FunctionCx.html#method.codegen_coverage
202
- [function - coverage ]: https : // doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/coverageinfo/map_data/struct.FunctionCoverage.html
200
+ [ `Builder::add_coverage` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/builder/struct.Builder.html#method.add_coverage
201
+ [ `FunctionCoverage` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/coverageinfo/map_data/struct.FunctionCoverage.html
203
202
[ instrprof-increment ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/traits/trait.BuilderMethods.html#tymethod.instrprof_increment
204
203
205
204
### Coverage Map Generation
@@ -327,9 +326,10 @@ Instrumentor::new(&self.name(), tcx, mir_body).inject_counters();
327
326
The ` CoverageGraph ` is a coverage-specific simplification of the MIR control
328
327
flow graph (CFG). Its nodes are [ ` BasicCoverageBlock ` s] [ bcb ] , which
329
328
encompass one or more sequentially-executed MIR ` BasicBlock ` s
330
- (with no internal branching), plus a ` CoverageKind ` counter (to
331
- be added, via coverage analysis), and an optional set of additional counters
332
- to count incoming edges (if there are more than one).
329
+ (with no internal branching).
330
+
331
+ Nodes and edges in the graph can have associated [ ` BcbCounter ` ] s, which are
332
+ stored in [ ` CoverageCounters ` ] .
333
333
334
334
The ` Instrumentor ` 's ` inject_counters() ` uses the ` CoverageGraph ` to
335
335
compute the best places to inject coverage counters, as MIR ` Statement ` s,
@@ -338,16 +338,15 @@ with the following steps:
338
338
1 . [ ` generate_coverage_spans() ` ] [ generate-coverage-spans ] computes the minimum set of distinct,
339
339
non-branching code regions, from the MIR. These ` CoverageSpan ` s
340
340
represent a span of code that must be counted.
341
- 2 . [ ` make_bcb_counters() ` ] [ make-bcb-counters ] generates ` CoverageKind::Counter ` s and
342
- ` CoverageKind::Expression ` s for each ` CoverageSpan ` , plus additional
343
- ` intermediate_expressions ` [ ^ intermediate-expressions ] , not associated with any ` CodeRegion ` , but
341
+ 2 . [ ` make_bcb_counters() ` ] [ make-bcb-counters ] generates ` BcbCounter::Counter ` s and
342
+ ` BcbCounter::Expression ` s for each ` CoverageSpan ` , plus additional
343
+ _ intermediate expressions_ [ ^ intermediate-expressions ] that are not associated
344
+ with any ` CodeRegion ` , but
344
345
are required to compute a final ` Expression ` value for a ` CodeRegion ` .
345
346
3 . Inject the new counters into the MIR, as new ` StatementKind::Coverage `
346
- statements. This is done by three distinct functions:
347
- - ` inject_coverage_span_counters() `
348
- - ` inject_indirect_counters() `
349
- - ` inject_intermediate_expression() ` , called for each intermediate expression
350
- returned from ` make_bcb_counters() `
347
+ statements.
348
+ 4 . Attach all other necessary coverage information to the function's body as
349
+ [ ` FunctionCoverageInfo ` ] .
351
350
352
351
[ ^ intermediate-expressions ] : Intermediate expressions are sometimes required
353
352
because ` Expression ` s are limited to binary additions or subtractions. For
@@ -359,7 +358,8 @@ intermediate expression for `B - C`.
359
358
[ coverage-graph ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html
360
359
[ inject-counters ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_counters
361
360
[ bcb ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.BasicCoverageBlock.html
362
- [ debug ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/debug
361
+ [ `BcbCounter` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/counters/enum.BcbCounter.html
362
+ [ `CoverageCounters` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/counters/struct.CoverageCounters.html
363
363
[ generate-coverage-spans ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpans.html#method.generate_coverage_spans
364
364
[ make-bcb-counters ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/counters/struct.BcbCounters.html#method.make_bcb_counters
365
365
@@ -505,34 +505,3 @@ its `Counter` or `Expression`.
505
505
506
506
[ bcb-counters ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/counters/struct.BcbCounters.html
507
507
[ traverse-coverage-graph-with-loops ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.TraverseCoverageGraphWithLoops.html
508
-
509
- ### Injecting counters into a MIR ` BasicBlock `
510
-
511
- With the refined ` CoverageSpan ` s, and after all ` Counter ` s and ` Expression ` s are
512
- created, the final step is to inject the ` StatementKind::Coverage ` statements
513
- into the MIR. There are three distinct sources, handled by the following
514
- functions:
515
-
516
- - [ ` inject_coverage_span_counters() ` ] [ inject-coverage-span-counters ] injects the
517
- counter from each ` CoverageSpan ` 's BCB.
518
- - [ ` inject_indirect_counters() ` ] [ inject-indirect-counters ] injects counters
519
- for any BCB not assigned to a ` CoverageSpan ` , and for all edge counters.
520
- These counters don't have ` CoverageSpan ` s.
521
- - [ ` inject_intermediate_expression() ` ] [ inject-intermediate-expression ] injects
522
- the intermediate expressions returned from ` make_bcb_counters() ` . These
523
- counters aren't associated with any BCB, edge, or ` CoverageSpan ` .
524
-
525
- These three functions inject the ` Coverage ` statements into the MIR.
526
- ` Counter ` s and ` Expression ` s with ` CoverageSpan ` s add ` Coverage ` statements
527
- to a corresponding ` BasicBlock ` , with a ` CodeRegion ` computed from the
528
- refined ` Span ` and current ` SourceMap ` .
529
-
530
- All other ` Coverage ` statements have a ` CodeRegion ` of ` None ` , but they
531
- still must be injected because they contribute to other ` Expression ` s.
532
-
533
- Finally, edge's with a ` CoverageKind::Counter ` require a new ` BasicBlock ` ,
534
- so the counter is only incremented when traversing the branch edge.
535
-
536
- [ inject-coverage-span-counters ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_coverage_span_counters
537
- [ inject-indirect-counters ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_indirect_counters
538
- [ inject-intermediate-expression ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/fn.inject_intermediate_expression.html
0 commit comments