@@ -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,42 @@ 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_ 
189+ _code  snippet  abbreviated  for  brevity_ 
187190
188191> The  function  name  `instrprof_increment ()` is  taken  from  the  LLVM  intrinsic 
189192call  of  the  same  name  ([`llvm . instrprof. increment`][llvm - instrprof - increment ]),
@@ -221,7 +224,7 @@ properly-configured variables in LLVM IR, according to very specific
221224details  of  the  [_LLVM  Coverage  Mapping  Format_ ][coverage - mapping - format ]
222225(Version  4 ). [^ llvm - and - covmap - versions ]
223226
224- [ ^ llvm-and-covmap-versions ] : The Rust compiler (as of  <!--  date: 2021-01  --> 
227+ [^ llvm - and - covmap - versions ]:  The  Rust  compiler  (as  of 
225228January  2021 ) supports  _LLVM  Coverage  Mapping  Format_  Version  4  (the  most 
226229up - to - date  version  of  the  format , at  the  time  of  this  writing ) for  improved 
227230compatibility  with  other  LLVM - based  compilers  (like  _Clang_ ), and  to  take 
@@ -233,13 +236,16 @@ instrument-coverage` will generate an error message.
233236
234237```rust
235238pub  fn  finalize<'ll, 'tcx>(cx:  & CodegenCx <'ll , 'tcx >) {
239+     ... 
240+     if  ! tcx. sess. instrument_coverage_except_unused_functions() {
241+         add_unused_functions(cx);
242+     }
243+ 
236244    let  mut  function_coverage_map  =  match  cx . coverage_context () {
237245        Some (ctx ) =>  ctx . take_function_coverage_map (),
238246        None  =>  return ,
239247    };
240248    ... 
241-     add_unreachable_coverage (tcx , & mut  function_coverage_map );
242- 
243249    let  mut  mapgen  =  CoverageMapGenerator :: new ();
244250
245251    for  (instance , function_coverage ) in  function_coverage_map  {
@@ -250,64 +256,59 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
250256``` 
251257_ code snippet trimmed for brevity_ 
252258
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 ] .
259+ One notable first step performed by ` mapgen::finalize() `  is the call to
260+ [ ` add_unused_functions() ` ] [ add-unused-functions ] :
256261
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.
262+ When finalizing the coverage map, ` FunctionCoverage `  only has the ` CodeRegion ` s
263+ and counters for the functions that went through codegen; such as public
264+ functions and "used" functions (functions referenced by other "used" or public
265+ items). Any other functions (considered unused) were still parsed and processed
266+ through the MIR stage.
261267
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).
268+ The set of unused functions is computed via the set difference of all MIR
269+ ` DefId ` s (` tcx `  query ` mir_keys ` ) minus the codegenned ` DefId ` s (` tcx `  query
270+ ` codegened_and_inlined_items ` ). ` add_unused_functions() `  computes the set of
271+ unused functions, queries the ` tcx `  for the previously-computed ` CodeRegions ` ,
272+ for each unused MIR, synthesizes an LLVM function (with no internal statements,
273+ since it will not be called), and adds a new ` FunctionCoverage ` , with
274+ ` Unreachable `  code regions.
270275
271276[ compile-codegen-unit ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/base/fn.compile_codegen_unit.html 
272277[ coverageinfo-finalize ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/context/struct.CodegenCx.html#method.coverageinfo_finalize 
273278[ mapgen-finalize ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/coverageinfo/mapgen/fn.finalize.html 
274279[ 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 
280+ [ add-unused-functions  ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/coverageinfo/mapgen/fn.add_unused_functions .html 
276281
277282## Testing LLVM Coverage  
278283
279284Coverage instrumentation in the MIR is validated by a ` mir-opt `  test:
280285[ ` instrument-coverage ` ] [ mir-opt-test ] .
281286
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 ` ] .
287+ More complete testing of end-to-end coverage instrumentation and reports are
288+ done in the ` run-make `  tests, with sample Rust programs (to be instrumented) in
289+ the [ ` coverage ` ] [ coverage-test-samples ]  directory, and the actual tests and
290+ expected results in [ ` coverage-reports ` ] .
291291
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.
292+ Finally, the [ ` coverage-llvmir ` ]  test compares compiles a simple Rust program
293+ with  ` -Z instrument-coverage `  and compares the compiled program's LLVM IR to
294+ expected  LLVM IR instructions and structured data for a coverage-enabled
295+ program, including  various checks for Coverage Map-related metadata and the LLVM
296+ intrinsic calls to  increment the runtime counters.
297297
298298Expected results for both the ` mir-opt `  tests and the ` coverage* `  tests under
299- ` run-make-fulldeps  `  can be refreshed by running:
299+ ` run-make `  can be refreshed by running:
300300
301301``` shell 
302- $ ./x.py test  src/test/< test-type>  --blessed
302+ $ ./x.py test  mir-opt --blessed
303+ $ ./x.py test  src/test/run-make/coverage --blessed
303304``` 
304305
305306[ 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 
307+ [ coverage-test-samples ] : https://github.com/rust-lang/rust/tree/master/src/test/run-make/coverage 
308+ [ `coverage-reports` ] : https://github.com/rust-lang/rust/tree/master/src/test/run-make/coverage-reports 
309+ [ `coverage-spanview` ] : https://github.com/rust-lang/rust/tree/master/src/test/run-make/coverage-spanview 
309310[ 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+ [ `coverage-llvmir` ] : https://github.com/rust-lang/rust/tree/master/src/test/run-make/coverage-llvmir 
311312
312313## Implementation Details of the ` InstrumentCoverage `  MIR Pass  
313314
@@ -396,16 +397,18 @@ contrast with the [`SimplifyCfg`][simplify-cfg] MIR pass, this step does
396397not alter the MIR itself, because the ` CoverageGraph `  aggressively simplifies
397398the CFG, and ignores nodes that are not relevant to coverage. For example:
398399
399-   *  The BCB CFG ignores (excludes) branches considered not relevant
400+   -  The BCB CFG ignores (excludes) branches considered not relevant
400401    to the current coverage solution. It excludes unwind-related code[ ^ 78544 ] 
401402    that is injected by the Rust compiler but has no physical source
402403    code to count, which allows a ` Call ` -terminated BasicBlock
403404    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).
405+   -  A ` Goto ` -terminated ` BasicBlock `  can be merged with its successor
406+     ** _ as long as_ **  it has the only incoming edge to the successor
407+     ` BasicBlock ` .
408+   -  Some BasicBlock terminators support Rust-specific concerns--like
409+     borrow-checking--that are not relevant to coverage analysis. ` FalseUnwind ` ,
410+     for example, can be treated the same as a ` Goto `  (potentially merged with
411+     its successor into the same BCB).
409412
410413[ ^ 78544 ] : (Note, however, that Issue [ #78544  ] [ rust-lang/rust#78544 ]  considers
411414providing future support for coverage of programs that intentionally
@@ -448,24 +451,24 @@ directional edges (the arrows) leading from each node to its `successors()`.
448451The nodes contain information in sections:
449452
4504531 .  The gray header has a label showing the BCB ID (or _ index_  for looking up
451- its ` BasicCoverageBlockData ` ).
454+     its ` BasicCoverageBlockData ` ).
4524552 .  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.)
456+     each contiguous section of code. (There may be more than one ` Expression ` 
457+     incremented by the same ` Counter `  for discontiguous sections of code
458+    representing  the same sequential actions.) Note the code is represented by
459+    the line and  column ranges (for example: ` 52:28-52:33 ` , representing the
460+    original source  line 52, for columns 28-33). These are followed by the MIR
461+     ` Statement `  or  ` Terminator `  represented by that source range. (How these
462+    coverage regions  are determined is discussed in the following section.)
4604633 .  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.
464+     ` TerminatorKind ` ) contained in this BCB. The last BCB is separated out
465+    because  its ` successors() `  determine the edges leading out of the BCB, and
466+    into  the ` leading_bb() `  (first ` BasicBlock ` ) of each successor BCB.
464467
465468Note, to find the ` BasicCoverageBlock `  from a final BCB ` Terminator ` 's
466469successor ` 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 ` .
470+ function--[ ` bcb_from_bb() ` ] [ bcb-from-bb ] --to look up a ` BasicCoverageBlock `  from
471+ * any *   contained ` BasicBlock ` .
469472
470473[ directed-graph ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/trait.DirectedGraph.html 
471474[ graph-traits ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/index.html#traits 
@@ -572,7 +575,7 @@ incoming edges. Given the following graph, for example, the count for
572575
573576In this situation, BCB node ` B `  may require an edge counter for its
574577"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 ` 
578+ ` Counter(A) - Counter(C) ` . But an expression for the BCB _ node_  ` B ` 
576579would be the sum of all incoming edges:
577580
578581``` text 
0 commit comments