1# LLVM Source-Based Code Coverage
2
3<!-- toc -->
4
5`rustc` supports detailed source-based code and test coverage analysis
6with a command line option (`-Z instrument-coverage`) that instruments Rust
7libraries and binaries with additional instructions and data, at compile time.
8
9The coverage instrumentation injects calls to the LLVM intrinsic instruction
10[`llvm.instrprof.increment`][llvm-instrprof-increment] at code branches
11(based on a MIR-based control flow analysis), and LLVM converts these to
12instructions that increment static counters, when executed. The LLVM coverage
13instrumentation also requires a [Coverage Map] that encodes source metadata,
14mapping counter IDs--directly and indirectly--to the file locations (with
15start and end line and column).
16
17Rust libraries, with or without coverage instrumentation, can be linked into
18instrumented binaries. When the program is executed and cleanly terminates,
19LLVM libraries write the final counter values to a file (`default.profraw` or
20a custom file set through environment variable `LLVM_PROFILE_FILE`).
21
22Developers use existing LLVM coverage analysis tools to decode `.profraw`
23files, with corresponding Coverage Maps (from matching binaries that produced
24them), and generate various reports for analysis, for example:
25
26<img alt="Screenshot of sample `llvm-cov show` result, for function add_quoted_string"
27 src="img/llvm-cov-show-01.png" class="center"/>
28<br/>
29
30Detailed instructions and examples are documented in the
31[Rust Unstable Book (under
32_compiler-flags/instrument-coverage_)][unstable-book-instrument-coverage].
33
34[llvm-instrprof-increment]: https://llvm.org/docs/LangRef.html#llvm-instrprof-increment-intrinsic
35[coverage map]: https://llvm.org/docs/CoverageMappingFormat.html
36[unstable-book-instrument-coverage]: https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/instrument-coverage.html
37
38## Rust symbol mangling
39
40`-Z instrument-coverage` automatically enables Rust symbol mangling `v0` (as
41if the user specified `-Z symbol-mangling-version=v0` option when invoking
42`rustc`) to ensure consistent and reversible name mangling. This has two
43important benefits:
44
451. LLVM coverage tools can analyze coverage over multiple runs, including some
46   changes to source code; so mangled names must be consistent across compilations.
472. LLVM coverage reports can report coverage by function, and even separates
48   out the coverage counts of each unique instantiation of a generic function,
49   if invoked with multiple type substitution variations.
50
51## Components of LLVM Coverage Instrumentation in `rustc`
52
53### LLVM Runtime Dependency
54
55Coverage data is only generated by running the executable Rust program. `rustc`
56statically links coverage-instrumented binaries with LLVM runtime code
57([compiler-rt][compiler-rt-profile]) that implements program hooks
58(such as an `exit` hook) to write the counter values to the `.profraw` file.
59
60In the `rustc` source tree, `library/profiler_builtins` bundles the LLVM
61`compiler-rt` code into a Rust library crate. (When building `rustc`, the
62`profiler_builtins` library is only included when `profiler = true` is set
63in `rustc`'s `config.toml`.)
64
65When compiling with `-Z instrument-coverage`,
66[`CrateLoader::postprocess()`][crate-loader-postprocess] dynamically loads the
67`profiler_builtins` library by calling `inject_profiler_runtime()`.
68
69[compiler-rt-profile]: https://github.com/llvm/llvm-project/tree/main/compiler-rt/lib/profile
70[crate-loader-postprocess]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/creader/struct.CrateLoader.html#method.postprocess
71
72### MIR Pass: `InstrumentCoverage`
73
74Coverage instrumentation is performed on the MIR with a [MIR pass][mir-passes]
75called [`InstrumentCoverage`][mir-instrument-coverage]. This MIR pass analyzes
76the control flow graph (CFG)--represented by MIR `BasicBlock`s--to identify
77code branches, and injects additional [`Coverage`][coverage-statement]
78statements into the `BasicBlock`s.
79
80A MIR `Coverage` statement is a virtual instruction that indicates a counter
81should be incremented when its adjacent statements are executed, to count
82a span of code ([`CodeRegion`][code-region]). It counts the number of times a
83branch is executed, and also specifies the exact location of that code span in
84the Rust source code.
85
86Note that many of these `Coverage` statements will _not_ be converted into
87physical counters (or any other executable instructions) in the final binary.
88Some of them will be (see `CoverageKind::`[`Counter`][counter-coverage-kind]),
89but other counters can be computed on the fly, when generating a coverage
90report, by mapping a `CodeRegion` to a
91`CoverageKind`::[`Expression`][expression-coverage-kind].
92
93As an example:
94
95```rust
96fn some_func(flag: bool) {
97    // increment Counter(1)
98    ...
99    if flag {
100        // increment Counter(2)
101        ...
102    } else {
103        // count = Expression(1) = Counter(1) - Counter(2)
104        ...
105    }
106    // count = Expression(2) = Counter(1) + Zero
107    //     or, alternatively, Expression(2) = Counter(2) + Expression(1)
108    ...
109}
110```
111
112In this example, four contiguous code regions are counted while only
113incrementing two counters.
114
115CFG analysis is used to not only determine _where_ the branches are, for
116conditional expressions like `if`, `else`, `match`, and `loop`, but also to
117determine where expressions can be used in place of physical counters.
118
119The advantages of optimizing coverage through expressions are more pronounced
120with loops. Loops generally include at least one conditional branch that
121determines when to break out of a loop (a `while` condition, or an `if` or
122`match` with a `break`). In MIR, this is typically lowered to a `SwitchInt`,
123with one branch to stay in the loop, and another branch to break out of the
124loop. The branch that breaks out will almost always execute less often,
125so `InstrumentCoverage` chooses to add a `Counter` to that branch, and an
126`Expression(continue) = Counter(loop) - Counter(break)` to the branch that
127continues.
128
129The `InstrumentCoverage` MIR pass is documented in
130[more detail below][instrument-coverage-pass-details].
131
132[mir-passes]: mir/passes.md
133[mir-instrument-coverage]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_mir_transform/src/coverage
134[code-region]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/struct.CodeRegion.html
135[counter-coverage-kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.Counter
136[expression-coverage-kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.Expression
137[coverage-statement]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.StatementKind.html#variant.Coverage
138[instrument-coverage-pass-details]: #implementation-details-of-the-instrumentcoverage-mir-pass
139
140### Counter Injection and Coverage Map Pre-staging
141
142When the compiler enters [the Codegen phase][backend-lowering-mir], with a
143coverage-enabled MIR, [`codegen_statement()`][codegen-statement] converts each
144MIR `Statement` into some backend-specific action or instruction.
145`codegen_statement()` forwards `Coverage` statements to
146[`codegen_coverage()`][codegen-coverage]:
147
148```rust
149    pub fn codegen_statement(&mut self, mut bx: Bx, statement: &mir::Statement<'tcx>) -> Bx {
150        ...
151        match statement.kind {
152            ...
153            mir::StatementKind::Coverage(box ref coverage) => {
154                self.codegen_coverage(&mut bx, coverage.clone(), statement.source_info.scope);
155                bx
156            }
157```
158
159`codegen_coverage()` handles each `CoverageKind` as follows:
160
161- For all `CoverageKind`s, Coverage data (counter ID, expression equation
162  and ID, and code regions) are passed to the backend's `Builder`, to
163  populate data structures that will be used to generate the crate's
164  "Coverage Map". (See the [`FunctionCoverage`][function-coverage] `struct`.)
165- For `CoverageKind::Counter`s, an instruction is injected in the backend
166  IR to increment the physical counter, by calling the `BuilderMethod`
167  [`instrprof_increment()`][instrprof-increment].
168
169```rust
170    pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage, scope: SourceScope) {
171        ...
172        let instance = ... // the scoped instance (current or inlined function)
173        let Coverage { kind, code_region } = coverage;
174        match kind {
175            CoverageKind::Counter { function_source_hash, id } => {
176                ...
177                bx.add_coverage_counter(instance, id, code_region);
178                ...
179                bx.instrprof_increment(fn_name, hash, num_counters, index);
180            }
181            CoverageKind::Expression { id, lhs, op, rhs } => {
182                bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region);
183            }
184            CoverageKind::Unreachable => {
185                bx.add_coverage_unreachable(
186                    instance,
187                    code_region.expect(...
188```
189
190> The function name `instrprof_increment()` is taken from the LLVM intrinsic
191call of the same name ([`llvm.instrprof.increment`][llvm-instrprof-increment]),
192and uses the same arguments and types; but note that, up to and through this
193stage (even though modeled after LLVM's implementation for code coverage
194instrumentation), the data and instructions are not strictly LLVM-specific.
195>
196> But since LLVM is the only Rust-supported backend with the tooling to
197process this form of coverage instrumentation, the backend for `Coverage`
198statements is only implemented for LLVM, at this time.
199
200[backend-lowering-mir]: backend/lowering-mir.md
201[codegen-statement]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/struct.FunctionCx.html#method.codegen_statement
202[codegen-coverage]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/struct.FunctionCx.html#method.codegen_coverage
203[function-coverage]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/coverageinfo/map/struct.FunctionCoverage.html
204[instrprof-increment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/traits/trait.BuilderMethods.html#tymethod.instrprof_increment
205
206### Coverage Map Generation
207
208With the instructions to increment counters now implemented in LLVM IR,
209the last remaining step is to inject the LLVM IR variables that hold the
210static data for the coverage map.
211
212`rustc_codegen_llvm`'s [`compile_codegen_unit()`][compile-codegen-unit] calls
213[`coverageinfo_finalize()`][coverageinfo-finalize],
214which delegates its implementation to the
215[`rustc_codegen_llvm::coverageinfo::mapgen`][mapgen-finalize] module.
216
217For each function `Instance` (code-generated from MIR, including multiple
218instances of the same MIR for generic functions that have different type
219substitution combinations), `mapgen`'s `finalize()` method queries the
220`Instance`-associated `FunctionCoverage` for its `Counter`s, `Expression`s,
221and `CodeRegion`s; and calls LLVM codegen APIs to generate
222properly-configured variables in LLVM IR, according to very specific
223details of the [_LLVM Coverage Mapping Format_][coverage-mapping-format]
224(Version 4).[^llvm-and-covmap-versions]
225
226[^llvm-and-covmap-versions]: The Rust compiler (as of
227January 2021) supports _LLVM Coverage Mapping Format_ Version 4 (the most
228up-to-date version of the format, at the time of this writing) for improved
229compatibility with other LLVM-based compilers (like _Clang_), and to take
230advantage of some format optimizations. Version 4 was introduced in _LLVM 11_,
231which is currently the default LLVM version for Rust. Note that the Rust
232compiler optionally supports some earlier LLVM versions, prior to _LLVM 11_. If
233`rustc` is configured to use an incompatible version of LLVM, compiling with `-Z
234instrument-coverage` will generate an error message.
235
236```rust
237pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
238    ...
239    if !tcx.sess.instrument_coverage_except_unused_functions() {
240        add_unused_functions(cx);
241    }
242
243    let mut function_coverage_map = match cx.coverage_context() {
244        Some(ctx) => ctx.take_function_coverage_map(),
245        None => return,
246    };
247    ...
248    let mut mapgen = CoverageMapGenerator::new();
249
250    for (instance, function_coverage) in function_coverage_map {
251        ...
252        let coverage_mapping_buffer = llvm::build_byte_buffer(|coverage_mapping_buffer| {
253            mapgen.write_coverage_mapping(expressions, counter_regions, coverage_mapping_buffer);
254        });
255```
256_code snippet trimmed for brevity_
257
258One notable first step performed by `mapgen::finalize()` is the call to
259[`add_unused_functions()`][add-unused-functions]:
260
261When finalizing the coverage map, `FunctionCoverage` only has the `CodeRegion`s
262and counters for the functions that went through codegen; such as public
263functions and "used" functions (functions referenced by other "used" or public
264items). Any other functions (considered unused) were still parsed and processed
265through the MIR stage.
266
267The set of unused functions is computed via the set difference of all MIR
268`DefId`s (`tcx` query `mir_keys`) minus the codegenned `DefId`s (`tcx` query
269`codegened_and_inlined_items`). `add_unused_functions()` computes the set of
270unused functions, queries the `tcx` for the previously-computed `CodeRegions`,
271for each unused MIR, synthesizes an LLVM function (with no internal statements,
272since it will not be called), and adds a new `FunctionCoverage`, with
273`Unreachable` code regions.
274
275[compile-codegen-unit]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/base/fn.compile_codegen_unit.html
276[coverageinfo-finalize]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/context/struct.CodegenCx.html#method.coverageinfo_finalize
277[mapgen-finalize]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/coverageinfo/mapgen/fn.finalize.html
278[coverage-mapping-format]: https://llvm.org/docs/CoverageMappingFormat.html
279[add-unused-functions]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/coverageinfo/mapgen/fn.add_unused_functions.html
280
281## Testing LLVM Coverage
282
283Coverage instrumentation in the MIR is validated by a `mir-opt` test:
284[`instrument-coverage`][mir-opt-test].
285
286More complete testing of end-to-end coverage instrumentation and reports are
287done in the `run-make-fulldeps` tests, with sample Rust programs (to be
288instrumented) in the [`coverage`][coverage-test-samples] directory, and the
289actual tests and expected results in [`coverage-reports`].
290
291Finally, the [`coverage-llvmir`] test compares compiles a simple Rust program
292with `-Z instrument-coverage` and compares the compiled program's LLVM IR to
293expected LLVM IR instructions and structured data for a coverage-enabled
294program, including various checks for Coverage Map-related metadata and the LLVM
295intrinsic calls to increment the runtime counters.
296
297Expected results for both the `mir-opt` tests and the `coverage*` tests under
298`run-make-fulldeps` can be refreshed by running:
299
300```shell
301$ ./x.py test mir-opt --bless
302$ ./x.py test src/test/run-make-fulldeps/coverage --bless
303```
304
305[mir-opt-test]: https://github.com/rust-lang/rust/blob/master/src/test/mir-opt/instrument_coverage.rs
306[coverage-test-samples]: https://github.com/rust-lang/rust/tree/master/src/test/run-make-fulldeps/coverage
307[`coverage-reports`]: https://github.com/rust-lang/rust/tree/master/src/test/run-make-fulldeps/coverage-reports
308[`coverage-spanview`]: https://github.com/rust-lang/rust/tree/master/src/test/run-make-fulldeps/coverage-spanview
309[spanview-debugging]: compiler-debugging.md#viewing-spanview-output
310[`coverage-llvmir`]: https://github.com/rust-lang/rust/tree/master/src/test/run-make-fulldeps/coverage-llvmir
311
312## Implementation Details of the `InstrumentCoverage` MIR Pass
313
314The bulk of the implementation of the `InstrumentCoverage` MIR pass is performed
315by the [`Instrumentor`][instrumentor]. For each MIR (each non-const, non-inlined
316function, generic, or closure), the `Instrumentor`'s constructor prepares a
317[`CoverageGraph`][coverage-graph] and then executes
318[`inject_counters()`][inject-counters].
319
320```rust
321        Instrumentor::new(&self.name(), tcx, mir_body).inject_counters();
322```
323
324The `CoverageGraph` is a coverage-specific simplification of the MIR control
325flow graph (CFG). Its nodes are [`BasicCoverageBlock`s][bcb], which
326encompass one or more sequentially-executed MIR `BasicBlock`s
327(with no internal branching), plus a `CoverageKind` counter (to
328be added, via coverage analysis), and an optional set of additional counters
329to count incoming edges (if there are more than one).
330
331The `Instrumentor`'s `inject_counters()` uses the `CoverageGraph` to
332compute the best places to inject coverage counters, as MIR `Statement`s,
333with the following steps:
334
3351. Depending on the debugging configurations in `rustc`'s, `config.toml`,
336   and `rustc` command line flags, various debugging features may be enabled
337   to enhance `debug!()` messages in logs, and to generate various "dump" files,
338   to help developers understand the MIR transformation process for coverage.
339   Most of the debugging features are implemented in the [`debug`][debug]
340   sub-module.
3412. [`generate_coverage_spans()`][generate-coverage-spans] computes the minimum set of distinct,
342   non-branching code regions, from the MIR. These `CoverageSpan`s
343   represent a span of code that must be counted.
3443. [`make_bcb_counters()`][make-bcb-counters] generates `CoverageKind::Counter`s and
345   `CoverageKind::Expression`s for each `CoverageSpan`, plus additional
346   `intermediate_expressions`[^intermediate-expressions], not associated with any `CodeRegion`, but
347   are required to compute a final `Expression` value for a `CodeRegion`.
3484. Inject the new counters into the MIR, as new `StatementKind::Coverage`
349   statements. This is done by three distinct functions:
350   - `inject_coverage_span_counters()`
351   - `inject_indirect_counters()`
352   - `inject_intermediate_expression()`, called for each intermediate expression
353     returned from `make_bcb_counters()`
354
355[^intermediate-expressions]: Intermediate expressions are sometimes required
356because `Expression`s are limited to binary additions or subtractions. For
357example, `A + (B - C)` might represent an `Expression` count computed from three
358other counters, `A`, `B`, and `C`, but computing that value requires an
359intermediate expression for `B - C`.
360
361[instrumentor]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html
362[coverage-graph]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html
363[inject-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_counters
364[bcb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.BasicCoverageBlock.html
365[debug]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/debug
366[generate-coverage-spans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpans.html#method.generate_coverage_spans
367[make-bcb-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/counters/struct.BcbCounters.html#method.make_bcb_counters
368
369### The `CoverageGraph`
370
371The [`CoverageGraph`][coverage-graph] is derived from the MIR (`mir::Body`).
372
373```rust
374        let basic_coverage_blocks = CoverageGraph::from_mir(mir_body);
375```
376
377Like `mir::Body`, the `CoverageGraph` is also a
378[`DirectedGraph`][directed-graph]. Both graphs represent the function's
379fundamental control flow, with many of the same
380[`graph trait`][graph-traits]s, supporting `start_node()`, `num_nodes()`,
381`successors()`, `predecessors()`, and `is_dominated_by()`.
382
383For anyone that knows how to work with the [MIR, as a CFG][mir-dev-guide], the
384`CoverageGraph` will be familiar, and can be used in much the same way.
385The nodes of the `CoverageGraph` are `BasicCoverageBlock`s (BCBs), which
386index into an `IndexVec` of `BasicCoverageBlockData`. This is analogous
387to the MIR CFG of `BasicBlock`s that index `BasicBlockData`.
388
389Each `BasicCoverageBlockData` captures one or more MIR `BasicBlock`s,
390exclusively, and represents the maximal-length sequence of `BasicBlocks`
391without conditional branches.
392
393[`compute_basic_coverage_blocks()`][compute-basic-coverage-blocks] builds the
394`CoverageGraph` as a coverage-specific simplification of the MIR CFG. In
395contrast with the [`SimplifyCfg`][simplify-cfg] MIR pass, this step does
396not alter the MIR itself, because the `CoverageGraph` aggressively simplifies
397the CFG, and ignores nodes that are not relevant to coverage. For example:
398
399  - The BCB CFG ignores (excludes) branches considered not relevant
400    to the current coverage solution. It excludes unwind-related code[^78544]
401    that is injected by the Rust compiler but has no physical source
402    code to count, which allows a `Call`-terminated BasicBlock
403    to be merged with its successor, within a single BCB.
404  - A `Goto`-terminated `BasicBlock` can be merged with its successor
405    **_as long as_** it has the only incoming edge to the successor
406    `BasicBlock`.
407  - Some BasicBlock terminators support Rust-specific concerns--like
408    borrow-checking--that are not relevant to coverage analysis. `FalseUnwind`,
409    for example, can be treated the same as a `Goto` (potentially merged with
410    its successor into the same BCB).
411
412[^78544]: (Note, however, that Issue [#78544][rust-lang/rust#78544] considers
413providing future support for coverage of programs that intentionally
414`panic`, as an option, with some non-trivial cost.)
415
416The BCB CFG is critical to simplifying the coverage analysis by ensuring graph path-based
417queries (`is_dominated_by()`, `predecessors`, `successors`, etc.) have branch (control flow)
418significance.
419
420To visualize the `CoverageGraph`, you can generate a _graphviz_ `*.dot`
421file with the following `rustc` flags:[^graphviz-dark-mode]
422
423[^graphviz-dark-mode]: This image also applies `-Z graphviz-dark-mode`, to
424produce a Graphviz document with "dark mode" styling. If you use a dark mode or
425theme in your development environment, you will probably want to use this
426option so you can review the graphviz output without straining your vision.
427
428```shell
429$ rustc -Z instrument-coverage -Z dump-mir=InstrumentCoverage \
430    -Z dump-mir-graphviz some_rust_source.rs
431```
432
433The `-Z dump-mir` flag requests [MIR debugging
434output][mir-debugging] (generating `*.mir` files, by default).
435`-Z dump-mir-graphviz` additionally generates `*.dot` files.
436`-Z dump-mir=InstrumentCoverage` restricts these files to the
437`InstrumentCoverage` pass. All files are written to the `./mir_dump/`
438directory, by default.
439
440Files with names ending in `.-------.InstrumentCoverage.0.dot` contain the
441_graphviz_ representations of a `CoverageGraph` (one for each MIR, that is,
442for each function and closure):
443
444<img alt="cropped image of a sample CoverageGraph in graphviz format"
445 src="img/coverage-graphviz-01.png" style="border: 1px solid gray" class="center"/>
446<br/>
447
448This image shows each `BasicCoverageBlock` as a rectangular _node_, with
449directional edges (the arrows) leading from each node to its `successors()`.
450The nodes contain information in sections:
451
4521. The gray header has a label showing the BCB ID (or _index_ for looking up
453   its `BasicCoverageBlockData`).
4542. The first content section shows the assigned `Counter` or `Expression` for
455   each contiguous section of code. (There may be more than one `Expression`
456   incremented by the same `Counter` for noncontiguous sections of code
457   representing the same sequential actions.) Note the code is represented by
458   the line and column ranges (for example: `52:28-52:33`, representing the
459   original source line 52, for columns 28-33). These are followed by the MIR
460   `Statement` or `Terminator` represented by that source range. (How these
461   coverage regions are determined is discussed in the following section.)
4623. The final section(s) show the MIR `BasicBlock`s (by ID/index and its
463   `TerminatorKind`) contained in this BCB. The last BCB is separated out
464   because its `successors()` determine the edges leading out of the BCB, and
465   into the `leading_bb()` (first `BasicBlock`) of each successor BCB.
466
467Note, to find the `BasicCoverageBlock` from a final BCB `Terminator`'s
468successor `BasicBlock`, there is an index and helper
469function--[`bcb_from_bb()`][bcb-from-bb]--to look up a `BasicCoverageBlock` from
470*any* contained `BasicBlock`.
471
472[directed-graph]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/trait.DirectedGraph.html
473[graph-traits]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/index.html#traits
474[mir-dev-guide]: mir/index.md
475[compute-basic-coverage-blocks]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html#method.compute_basic_coverage_blocks
476[simplify-cfg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/simplify/struct.SimplifyCfg.html
477[rust-lang/rust#78544]: https://github.com/rust-lang/rust/issues/78544
478[mir-debugging]: mir/debugging.md
479[bcb-from-bb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html#method.bcb_from_bb
480
481### `CoverageSpans`
482
483The `struct` [`CoverageSpans`][coverage-spans] builds and refines a final set of
484[`CoverageSpan`][coverage-span]s, each representing the largest contiguous `Span`
485of source within a single BCB. By definition--since each `Span` falls within a
486BCB, the `Span` is also non-branching; so if any code in that `Span` has executed,
487all code in the `Span` will have executed, the same number of times.
488
489[`CoverageSpans::generate_coverage_spans()`][generate-coverage-spans] constructs
490an initial set of `CoverageSpan`s from the `Span`s associated with each MIR
491`Statement` and `Terminator`.
492
493The final stage of `generate_coverage_spans()` is handled by
494[`to_refined_spans()`][to-refined-spans], which iterates through the `CoverageSpan`s,
495merges and de-duplicates them, and returns an optimal, minimal set of `CoverageSpan`s
496that can be used to assign coverage `Counter`s or `Expression`s, one-for-one.
497
498An visual, interactive representation of the final `CoverageSpan`s can be
499generated with the following `rustc` flags:
500
501```shell
502$ rustc -Z instrument-coverage -Z dump-mir=InstrumentCoverage \
503    -Z dump-mir-spanview some_rust_source.rs
504```
505
506These flags request Spanview output for the `InstrumentCoverage` pass, and the
507resulting files (one for each MIR, that is, for each function or closure) can be
508found in the `mir_dump` directory (by default), with the extension:
509`.-------.InstrumentCoverage.0.html`.
510
511<img alt="cropped image of a sample Spanview in a browser"
512 src="img/coverage-spanview-01.png" style="border: 1px solid gray" class="center"/>
513<br/>
514
515The image above shows one such example. The orange and blue backgrounds
516highlight alternating `CoverageSpan`s from the refined set. Hovering over a
517line expands the output on that line to show the MIR `BasicBlock` IDs covered
518by each `CoverageSpan`. While hovering, the `CoverageSpan` under the pointer
519also has a _tooltip_ block of text, showing even more detail, including the
520MIR `Statement`s and `Terminator`s contributing to the `CoverageSpan`, and
521their individual `Span`s (which should be encapsulated within the code region
522of the refined `CoverageSpan`)
523
524[coverage-spans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpans.html
525[coverage-span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpan.html
526[to-refined-spans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpans.html#method.to_refined_spans
527
528### `make_bcb_counters()`
529
530[`make_bcb_counters()`][make-bcb-counters] traverses the `CoverageGraph` and adds a
531`Counter` or `Expression` to every BCB. It uses _Control Flow Analysis_
532to determine where an `Expression` can be used in place of a `Counter`.
533`Expressions` have no runtime overhead, so if a viable expression (adding or
534subtracting two other counters or expressions) can compute the same result as
535an embedded counter, an `Expression` is preferred.
536
537[`TraverseCoverageGraphWithLoops`][traverse-coverage-graph-with-loops]
538provides a traversal order that ensures all `BasicCoverageBlock` nodes in a
539loop are visited before visiting any node outside that loop. The traversal
540state includes a `context_stack`, with the current loop's context information
541(if in a loop), as well as context for nested loops.
542
543Within loops, nodes with multiple outgoing edges (generally speaking, these
544are BCBs terminated in a `SwitchInt`) can be optimized when at least one
545branch exits the loop and at least one branch stays within the loop. (For an
546`if` or `while`, there are only two branches, but a `match` may have more.)
547
548A branch that does not exit the loop should be counted by `Expression`, if
549possible. Note that some situations require assigning counters to BCBs before
550they are visited by traversal, so the `counter_kind` (`CoverageKind` for
551a `Counter` or `Expression`) may have already been assigned, in which case
552one of the other branches should get the `Expression`.
553
554For a node with more than two branches (such as for more than two
555`match` patterns), only one branch can be optimized by `Expression`. All
556others require a `Counter` (unless its BCB `counter_kind` was previously
557assigned).
558
559A branch expression is derived from the equation:
560
561```text
562Counter(branching_node) = SUM(Counter(branches))
563```
564
565It's important to
566be aware that the `branches` in this equation are the outgoing _edges_
567from the `branching_node`, but a `branch`'s target node may have other
568incoming edges. Given the following graph, for example, the count for
569`B` is the sum of its two incoming edges:
570
571<img alt="Example graph with multiple incoming edges to a branch node"
572 src="img/coverage-branch-counting-01.png" class="center" style="width: 25%">
573<br/>
574
575In this situation, BCB node `B` may require an edge counter for its
576"edge from A", and that edge might be computed from an `Expression`,
577`Counter(A) - Counter(C)`. But an expression for the BCB _node_ `B`
578would be the sum of all incoming edges:
579
580```text
581Expression((Counter(A) - Counter(C)) + SUM(Counter(remaining_edges)))
582```
583
584Note that this is only one possible configuration. The actual choice
585of `Counter` vs. `Expression` also depends on the order of counter
586assignments, and whether a BCB or incoming edge counter already has
587its `Counter` or `Expression`.
588
589[bcb-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/counters/struct.BcbCounters.html
590[traverse-coverage-graph-with-loops]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.TraverseCoverageGraphWithLoops.html
591
592### Injecting counters into a MIR `BasicBlock`
593
594With the refined `CoverageSpan`s, and after all `Counter`s and `Expression`s are
595created, the final step is to inject the `StatementKind::Coverage` statements
596into the MIR. There are three distinct sources, handled by the following
597functions:
598
599- [`inject_coverage_span_counters()`][inject-coverage-span-counters] injects the
600  counter from each `CoverageSpan`'s BCB.
601- [`inject_indirect_counters()`][inject-indirect-counters] injects counters
602  for any BCB not assigned to a `CoverageSpan`, and for all edge counters.
603  These counters don't have `CoverageSpan`s.
604- [`inject_intermediate_expression()`][inject-intermediate-expression] injects
605  the intermediate expressions returned from `make_bcb_counters()`. These
606  counters aren't associated with any BCB, edge, or `CoverageSpan`.
607
608These three functions inject the `Coverage` statements into the MIR.
609`Counter`s and `Expression`s with `CoverageSpan`s add `Coverage` statements
610to a corresponding `BasicBlock`, with a `CodeRegion` computed from the
611refined `Span` and current `SourceMap`.
612
613All other `Coverage` statements have a `CodeRegion` of `None`, but they
614still must be injected because they contribute to other `Expression`s.
615
616Finally, edge's with a `CoverageKind::Counter` require a new `BasicBlock`,
617so the counter is only incremented when traversing the branch edge.
618
619[inject-coverage-span-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_coverage_span_counters
620[inject-indirect-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_indirect_counters
621[inject-intermediate-expression]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/fn.inject_intermediate_expression.html
622
623### Additional Debugging Support
624
625See the
626[crate documentation for `rustc_mir::transform::coverage::debug`][coverage-debugging]
627for a detailed description of the debug output, logging, and configuration options
628available to developers working on the `InstrumentCoverage` pass.
629
630[coverage-debugging]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/debug/index.html
631