Skip to content

Commit f42a31f

Browse files
Zalathardavidtwco
authored andcommitted
Update some outdated descriptions of coverage instrumentation
1 parent cd0eabf commit f42a31f

File tree

1 file changed

+46
-77
lines changed

1 file changed

+46
-77
lines changed

src/llvm-coverage-instrumentation.md

+46-77
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,21 @@ When compiling with `-C instrument-coverage`,
7373
Coverage instrumentation is performed on the MIR with a [MIR pass][mir-passes]
7474
called [`InstrumentCoverage`][mir-instrument-coverage]. This MIR pass analyzes
7575
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.
7879

7980
A MIR `Coverage` statement is a virtual instruction that indicates a counter
8081
should be incremented when its adjacent statements are executed, to count
8182
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.
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
8687
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`]),
8889
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_.
9191

9292
As 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`,
122122
with one branch to stay in the loop, and another branch to break out of the
123123
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
126126
continues.
127127

128128
The `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();
327326
The `CoverageGraph` is a coverage-specific simplification of the MIR control
328327
flow graph (CFG). Its nodes are [`BasicCoverageBlock`s][bcb], which
329328
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`].
333333

334334
The `Instrumentor`'s `inject_counters()` uses the `CoverageGraph` to
335335
compute the best places to inject coverage counters, as MIR `Statement`s,
@@ -338,16 +338,15 @@ with the following steps:
338338
1. [`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`.
345346
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`].
351350

352351
[^intermediate-expressions]: Intermediate expressions are sometimes required
353352
because `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

Comments
 (0)