@@ -28,11 +28,12 @@ them), and generate various reports for analysis, for example:
2828<br />
2929
3030Detailed instructions and examples are documented in the
31- [ Rust Unstable Book (under _ source-based-code-coverage_ )] [ unstable-book-sbcc ] .
31+ [ Rust Unstable Book (under
32+ _ compiler-flags/instrument-coverage_ )] [ unstable-book-instrument-coverage ] .
3233
3334[ llvm-instrprof-increment ] : https://llvm.org/docs/LangRef.html#llvm-instrprof-increment-intrinsic
34- [ Coverage Map ] : https://llvm.org/docs/CoverageMappingFormat.html
35- [ unstable-book-sbcc ] : https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/source-based-code -coverage.html
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
3637
3738## Rust symbol mangling
3839
@@ -82,7 +83,7 @@ a span of code ([`CodeRegion`][code-region]). It counts the number of times a
8283branch is executed, and also specifies the exact location of that code span in
8384the Rust source code.
8485
85- Note that many of these ` Coverage ` statements will * not * be converted into
86+ Note that many of these ` Coverage ` statements will _ not _ be converted into
8687physical counters (or any other executable instructions) in the final binary.
8788Some of them will be (see ` CoverageKind:: ` [ ` Counter ` ] [ counter-coverage-kind ] ),
8889but other counters can be computed on the fly, when generating a coverage
@@ -111,7 +112,7 @@ fn some_func(flag: bool) {
111112In this example, four contiguous code regions are counted while only
112113incrementing two counters.
113114
114- CFG analysis is used to not only determine * where * the branches are, for
115+ CFG analysis is used to not only determine _ where _ the branches are, for
115116conditional expressions like ` if ` , ` else ` , ` match ` , and ` loop ` , but also to
116117determine where expressions can be used in place of physical counters.
117118
@@ -150,40 +151,41 @@ MIR `Statement` into some backend-specific action or instruction.
150151 match statement . kind {
151152 ...
152153 mir :: StatementKind :: Coverage (box ref coverage ) => {
153- self . codegen_coverage (& mut bx , coverage . clone ());
154+ self . codegen_coverage (& mut bx , coverage . clone (), statement . source_info . scope );
154155 bx
155156 }
156157```
157158
158-
159159` codegen_coverage() ` handles each ` CoverageKind ` as follows:
160160
161- * For all ` CoverageKind ` s, Coverage data (counter ID, expression equation
161+ - For all ` CoverageKind ` s, Coverage data (counter ID, expression equation
162162 and ID, and code regions) are passed to the backend's ` Builder ` , to
163163 populate data structures that will be used to generate the crate's
164164 "Coverage Map". (See the [ ` FunctionCoverage ` ] [ function-coverage ] ` struct ` .)
165- * For ` CoverageKind::Counter ` s, an instruction is injected in the backend
165+ - For ` CoverageKind::Counter ` s, an instruction is injected in the backend
166166 IR to increment the physical counter, by calling the ` BuilderMethod `
167167 [ ` instrprof_increment() ` ] [ instrprof-increment ] .
168168
169169``` rust
170- pub fn codegen_coverage (& self , bx : & mut Bx , coverage : Coverage ) {
170+ pub fn codegen_coverage (& self , bx : & mut Bx , coverage : Coverage , scope : SourceScope ) {
171+ ...
172+ let instance = ... // the scoped instance (current or inlined function)
171173 let Coverage { kind , code_region } = coverage ;
172174 match kind {
173175 CoverageKind :: Counter { function_source_hash , id } => {
174- if let Some (code_region ) = code_region {
175- bx . add_coverage_counter (self . instance, id , code_region );
176- }
176+ ...
177+ bx . add_coverage_counter (instance , id , code_region );
177178 ...
178179 bx . instrprof_increment (fn_name , hash , num_counters , index );
179180 }
180181 CoverageKind :: Expression { id , lhs , op , rhs } => {
181- bx . add_coverage_counter_expression (self . instance, id , lhs , op , rhs , code_region );
182+ bx . add_coverage_counter_expression (instance , id , lhs , op , rhs , code_region );
182183 }
183184 CoverageKind :: Unreachable => {
184- ...
185+ bx . add_coverage_unreachable (
186+ instance ,
187+ code_region . expect (...
185188```
186- _ code snippet trimmed for brevity_
187189
188190> The function name `instrprof_increment ()` is taken from the LLVM intrinsic
189191call of the same name ([`llvm . instrprof. increment`][llvm - instrprof - increment ]),
@@ -221,7 +223,7 @@ properly-configured variables in LLVM IR, according to very specific
221223details of the [_LLVM Coverage Mapping Format_ ][coverage - mapping - format ]
222224(Version 4 ). [^ llvm - and - covmap - versions ]
223225
224- [ ^ llvm-and-covmap-versions ] : The Rust compiler (as of <!-- date: 2021-01 -->
226+ [^ llvm - and - covmap - versions ]: The Rust compiler (as of
225227January 2021 ) supports _LLVM Coverage Mapping Format_ Version 4 (the most
226228up - to - date version of the format , at the time of this writing ) for improved
227229compatibility with other LLVM - based compilers (like _Clang_ ), and to take
@@ -233,13 +235,16 @@ instrument-coverage` will generate an error message.
233235
234236```rust
235237pub 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+
236243 let mut function_coverage_map = match cx . coverage_context () {
237244 Some (ctx ) => ctx . take_function_coverage_map (),
238245 None => return ,
239246 };
240247 ...
241- add_unreachable_coverage (tcx , & mut function_coverage_map );
242-
243248 let mut mapgen = CoverageMapGenerator :: new ();
244249
245250 for (instance , function_coverage ) in function_coverage_map {
@@ -250,56 +255,51 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
250255```
251256_ code snippet trimmed for brevity_
252257
253- One notable step, performed by ` mapgen::finalize() ` before processing the
254- ` Instance ` s and their ` FunctionCoverage ` s, is the call to
255- [ ` add_unreachable_functions() ` ] [ add-unreachable-coverage ] .
258+ One notable first step performed by ` mapgen::finalize() ` is the call to
259+ [ ` add_unused_functions() ` ] [ add-unused-functions ] :
256260
257- When finalizing the coverage map, ` FunctionCoverage ` only has the ` CodeRegion ` s and counters for
258- the functions that went through codegen; such as public functions and "used" functions
259- (functions referenced by other "used" or public items). Any other functions (considered unused
260- or "Unreachable") were still parsed and processed through the MIR stage.
261+ When finalizing the coverage map, ` FunctionCoverage ` only has the ` CodeRegion ` s
262+ and counters for the functions that went through codegen; such as public
263+ functions and "used" functions (functions referenced by other "used" or public
264+ items). Any other functions (considered unused) were still parsed and processed
265+ through the MIR stage.
261266
262- The set of unreachable functions is computed via the set difference of all MIR
263- ` DefId ` s (` tcx ` query ` mir_keys ` ) minus the codegenned ` DefId ` s
264- (` tcx ` query ` collect_and_partition_mono_items ` ). ` add_unreachable_functions() `
265- computes the set of unreachable functions, queries the ` tcx ` for the
266- previously-computed ` CodeRegions ` , for each unreachable MIR, and adds those code
267- regions to one of the non-generic codegenned functions (non-generic avoids
268- potentially injecting the unreachable coverage multiple times for multiple
269- instantiations).
267+ The 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
270+ unused functions, queries the ` tcx ` for the previously-computed ` CodeRegions ` ,
271+ for each unused MIR, synthesizes an LLVM function (with no internal statements,
272+ since it will not be called), and adds a new ` FunctionCoverage ` , with
273+ ` Unreachable ` code regions.
270274
271275[ compile-codegen-unit ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/base/fn.compile_codegen_unit.html
272276[ coverageinfo-finalize ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/context/struct.CodegenCx.html#method.coverageinfo_finalize
273277[ mapgen-finalize ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/coverageinfo/mapgen/fn.finalize.html
274278[ coverage-mapping-format ] : https://llvm.org/docs/CoverageMappingFormat.html
275- [ add-unreachable-coverage ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/coverageinfo/mapgen/fn.add_unreachable_coverage .html
279+ [ add-unused-functions ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/coverageinfo/mapgen/fn.add_unused_functions .html
276280
277281## Testing LLVM Coverage
278282
279283Coverage instrumentation in the MIR is validated by a ` mir-opt ` test:
280284[ ` instrument-coverage ` ] [ mir-opt-test ] .
281285
282- More complete testing of end-to-end coverage instrumentation and reports are done
283- in the ` run-make-fulldeps ` tests, with sample Rust programs (to be instrumented)
284- in the [ ` coverage ` ] [ coverage-test-samples ] directory, and the actual tests and expected
285- results in [ ` coverage-reports ` ] .
286-
287- In addition to testing the final result, two intermediate results are also validated
288- to catch potential regression errors early: Minimum ` CoverageSpan ` s computed during
289- the ` InstrumentCoverage ` MIR pass are saved in ` mir_dump ` [ Spanview] [ spanview-debugging ]
290- files and compared to expected results in [ ` coverage-spanview ` ] .
286+ More complete testing of end-to-end coverage instrumentation and reports are
287+ done in the ` run-make-fulldeps ` tests, with sample Rust programs (to be
288+ instrumented) in the [ ` coverage ` ] [ coverage-test-samples ] directory, and the
289+ actual tests and expected results in [ ` coverage-reports ` ] .
291290
292- Finally, the [ ` coverage-llvmir ` ] test compares compiles a simple Rust program with
293- ` -Z instrument-coverage ` and compares the compiled program's LLVM IR to expected
294- LLVM IR instructions and structured data for a coverage-enabled program, including
295- various checks for Coverage Map-related metadata and the LLVM intrinsic calls to
296- increment the runtime counters.
291+ Finally, the [ ` coverage-llvmir ` ] test compares compiles a simple Rust program
292+ with ` -Z instrument-coverage ` and compares the compiled program's LLVM IR to
293+ expected LLVM IR instructions and structured data for a coverage-enabled
294+ program, including various checks for Coverage Map-related metadata and the LLVM
295+ intrinsic calls to increment the runtime counters.
297296
298297Expected results for both the ` mir-opt ` tests and the ` coverage* ` tests under
299298` run-make-fulldeps ` can be refreshed by running:
300299
301300``` shell
302- $ ./x.py test src/test/< test-type> --blessed
301+ $ ./x.py test mir-opt --blessed
302+ $ ./x.py test src/test/run-make-fulldeps/coverage --blessed
303303```
304304
305305[ mir-opt-test ] : https://github.com/rust-lang/rust/blob/master/src/test/mir-opt/instrument_coverage.rs
@@ -396,16 +396,18 @@ contrast with the [`SimplifyCfg`][simplify-cfg] MIR pass, this step does
396396not alter the MIR itself, because the ` CoverageGraph ` aggressively simplifies
397397the CFG, and ignores nodes that are not relevant to coverage. For example:
398398
399- * The BCB CFG ignores (excludes) branches considered not relevant
399+ - The BCB CFG ignores (excludes) branches considered not relevant
400400 to the current coverage solution. It excludes unwind-related code[ ^ 78544 ]
401401 that is injected by the Rust compiler but has no physical source
402402 code to count, which allows a ` Call ` -terminated BasicBlock
403403 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 ` BasicBlock ` .
406- * Some BasicBlock terminators support Rust-specific concerns--like borrow-checking--that are
407- not relevant to coverage analysis. ` FalseUnwind ` , for example, can be treated the same as
408- a ` Goto ` (potentially merged with its successor into the same 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).
409411
410412[ ^ 78544 ] : (Note, however, that Issue [ #78544 ] [ rust-lang/rust#78544 ] considers
411413providing future support for coverage of programs that intentionally
@@ -448,24 +450,24 @@ directional edges (the arrows) leading from each node to its `successors()`.
448450The nodes contain information in sections:
449451
4504521 . The gray header has a label showing the BCB ID (or _ index_ for looking up
451- its ` BasicCoverageBlockData ` ).
453+ its ` BasicCoverageBlockData ` ).
4524542 . The first content section shows the assigned ` Counter ` or ` Expression ` for
453- each contiguous section of code. (There may be more than one ` Expression `
454- incremented by the same ` Counter ` for discontiguous sections of code representing
455- the same sequential actions.) Note the code is represented by the line and
456- column ranges (for example: ` 52:28-52:33 ` , representing the original source
457- line 52, for columns 28-33). These are followed by the MIR ` Statement ` or
458- ` Terminator ` represented by that source range. (How these coverage regions
459- are determined is discussed in the following section.)
455+ each contiguous section of code. (There may be more than one ` Expression `
456+ incremented by the same ` Counter ` for discontiguous 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.)
4604623 . The final section(s) show the MIR ` BasicBlock ` s (by ID/index and its
461- ` TerminatorKind ` ) contained in this BCB. The last BCB is separated out because
462- its ` successors() ` determine the edges leading out of the BCB, and into
463- the ` leading_bb() ` (first ` BasicBlock ` ) of each successor BCB.
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.
464466
465467Note, to find the ` BasicCoverageBlock ` from a final BCB ` Terminator ` 's
466468successor ` BasicBlock ` , there is an index and helper
467- function--[ ` bcb_from_bb() ` ] [ bcb-from-bb ] --to look up a ` BasicCoverageBlock ` from _ any _
468- contained ` BasicBlock ` .
469+ function--[ ` bcb_from_bb() ` ] [ bcb-from-bb ] --to look up a ` BasicCoverageBlock ` from
470+ * any * contained ` BasicBlock ` .
469471
470472[ directed-graph ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/trait.DirectedGraph.html
471473[ graph-traits ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/index.html#traits
@@ -572,7 +574,7 @@ incoming edges. Given the following graph, for example, the count for
572574
573575In this situation, BCB node ` B ` may require an edge counter for its
574576"edge from A", and that edge might be computed from an ` Expression ` ,
575- ` Counter(A) - Counter(C) ` . But an expression for the BCB _ node_ ` B `
577+ ` Counter(A) - Counter(C) ` . But an expression for the BCB _ node_ ` B `
576578would be the sum of all incoming edges:
577579
578580``` text
0 commit comments