@@ -73,21 +73,21 @@ When compiling with `-C instrument-coverage`,
7373Coverage instrumentation is performed on the MIR with a [ MIR pass] [ mir-passes ]
7474called [ ` InstrumentCoverage ` ] [ mir-instrument-coverage ] . This MIR pass analyzes
7575the 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.
7879
7980A MIR ` Coverage ` statement is a virtual instruction that indicates a counter
8081should be incremented when its adjacent statements are executed, to count
8182a 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 .
8485
85- Note that many of these ` Coverage ` statements will _ not_ be converted into
86+ Note that many coverage counters will _ not_ be converted into
8687physical 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 ` ] ),
8889but 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_ .
9191
9292As an example:
9393
@@ -121,18 +121,18 @@ determines when to break out of a loop (a `while` condition, or an `if` or
121121` match ` with a ` break ` ). In MIR, this is typically lowered to a ` SwitchInt ` ,
122122with one branch to stay in the loop, and another branch to break out of the
123123loop. 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
126126continues.
127127
128128The ` InstrumentCoverage ` MIR pass is documented in
129129[ more detail below] [ instrument-coverage-pass-details ] .
130130
131131[ mir-passes ] : mir/passes.md
132132[ 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
133134[ 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
136136[ coverage-statement ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.StatementKind.html#variant.Coverage
137137[ instrument-coverage-pass-details ] : #implementation-details-of-the-instrumentcoverage-mir-pass
138138
@@ -150,40 +150,38 @@ MIR `Statement` into some backend-specific action or instruction.
150150 match statement . kind {
151151 ...
152152 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);
155154 }
156155```
157156
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:
159160
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
165167 IR to increment the physical counter, by calling the ` BuilderMethod `
166168 [ ` instrprof_increment() ` ] [ instrprof-increment ] .
167169
168170``` 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 ) {
170172 ...
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 );
177177 ...
178178 bx . instrprof_increment (fn_name , hash , num_counters , index );
179179 }
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 );
182182 }
183- CoverageKind :: Unreachable => {
184- bx . add_coverage_unreachable (
185- instance ,
186- code_region . expect (...
183+ }
184+ }
187185```
188186
189187> The function name ` instrprof_increment() ` is taken from the LLVM intrinsic
@@ -199,7 +197,8 @@ statements is only implemented for LLVM, at this time.
199197[ backend-lowering-mir ] : backend/lowering-mir.md
200198[ codegen-statement ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/struct.FunctionCx.html#method.codegen_statement
201199[ 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
203202[ instrprof-increment ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/traits/trait.BuilderMethods.html#tymethod.instrprof_increment
204203
205204### Coverage Map Generation
@@ -327,9 +326,10 @@ Instrumentor::new(&self.name(), tcx, mir_body).inject_counters();
327326The ` CoverageGraph ` is a coverage-specific simplification of the MIR control
328327flow graph (CFG). Its nodes are [ ` BasicCoverageBlock ` s] [ bcb ] , which
329328encompass 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 ` ] .
333333
334334The ` Instrumentor ` 's ` inject_counters() ` uses the ` CoverageGraph ` to
335335compute the best places to inject coverage counters, as MIR ` Statement ` s,
@@ -338,16 +338,15 @@ with the following steps:
3383381 . [ ` generate_coverage_spans() ` ] [ generate-coverage-spans ] computes the minimum set of distinct,
339339 non-branching code regions, from the MIR. These ` CoverageSpan ` s
340340 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
344345 are required to compute a final ` Expression ` value for a ` CodeRegion ` .
3453463 . 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 ` ] .
351350
352351[ ^ intermediate-expressions ] : Intermediate expressions are sometimes required
353352because ` Expression ` s are limited to binary additions or subtractions. For
@@ -359,7 +358,8 @@ intermediate expression for `B - C`.
359358[ coverage-graph ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html
360359[ inject-counters ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_counters
361360[ 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
363363[ generate-coverage-spans ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpans.html#method.generate_coverage_spans
364364[ make-bcb-counters ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/counters/struct.BcbCounters.html#method.make_bcb_counters
365365
@@ -505,34 +505,3 @@ its `Counter` or `Expression`.
505505
506506[ bcb-counters ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/counters/struct.BcbCounters.html
507507[ 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