1 # codegen/coverage-experiments
2 *<h2>THIS DIRECTORY IS TEMPORARY</h2>*
4 This directory contains some work-in-progress (WIP) code used for experimental development and
5 testing of Rust Coverage feature development.
7 The code in this directory will be removed, or migrated into product tests, when the Rust
8 Coverage feature is complete.
16 config.toml probably requires (I should verify that intrinsic `llvm.instrprof.increment`
17 code generation ONLY works with this config option):
25 ./x.py build -i --stage 1 src/libstd
28 ## Incremental builds *IF POSSIBLE!*
31 ./x.py build -i --stage 1 src/libstd --keep-stage 1
34 *Note: Some changes made for Rust Coverage required the full build (without `--keep-stage 1`), and in some cases, required `./x.py clean` first!. Occassionally I would get errors when building or when compiling a test program with `--Zinstrument-coverage` that work correctly only after a full clean and build.*
36 ## Compile a test program with LLVM coverage instrumentation
38 *Note: This PR is still a work in progress. At the time of this writing, the `llvm.instrprof.increment` intrinsic is injected, and recognized by the LLVM code generation stage, but it does not appear to be included in the final binary. This is not surprising since other steps are still to be implemented, such as generating the coverage map. See the suggested additional `llvm` flags for ways to verify the `llvm` passes at least get the right intrinsic.*
40 Suggested debug configuration to confirm Rust coverage features:
42 $ export RUSTC_LOG=rustc_codegen_llvm::intrinsic,rustc_mir::transform::instrument_coverage=debug
45 Ensure the new compiled `rustc` is used (the path below, relative to the `rust` code repository root, is an example only):
48 $ build/x86_64-unknown-linux-gnu/stage1/bin/rustc \
49 src/test/codegen/coverage-experiments/just_main.rs \
53 ### About the test programs in coverage-experiments/src/
55 The `coverage-experiments/src/` directory contains some sample (and very simple) Rust programs used to analyze Rust compiler output at various stages, with or without the Rust code coverage compiler option. For now, these are only used for the in-progress development and will be removed at a future date. (These are *not* formal test programs.)
57 The src director may also contain some snapshots of mir output from experimentation, particularly if the saved snapshots highlight results that are important to the future development, individually or when compared with other output files.
59 Be aware that some of the files and/or comments may be outdated.
61 ### Additional `llvm` flags (append to the `rustc` command)
63 These optional flags generate additional files and/or terminal output. LLVM's `-print-before=all` should show the `instrprof.increment` intrinsic with arguments computed by the experimental Rust coverage feature code:
70 -Cllvm-args=-print-before-all
73 ### Additional flags for MIR analysis and transforms
75 These optional flags generate a directory with many files representing the MIR as text (`.mir` files) and as a visual graph (`.dot` files) rendered by `graphviz`. (**Some IDEs, such as `VSCode` have `graphviz` extensions.**)
82 ### Flags I've used but appear to be irrelvant to `-Zinstrument-coverage` after all:
86 # -Cinline-threshold=0
88 # -Coverflow-checks=off
91 ## Run the test program compiled with code coverage instrumentation (maybe):
93 As stated above, at the time of this writing, this work-in-progress seems to generate `llvm.instrprof.increment` intrinsic calls correctly, and are visibile in early `llvm` code generation passes, but are eventually stripped.
95 The test program should run as expected, currently does not generate any coverage output.
100 $ src/test/codegen/coverage-experiments/just_main
101 hello world! (should be covered)
104 ### Running the coverage-enabled `rustc` compiler in the `lldb` debugger:
106 For example, to verify the intrinsic is codegen'ed, set breakpoint in `lldb` where it validates a certain instruction is the `llvm.instrprof.increment` instruction.
108 First, update config.toml for debugging:
113 release-debuginfo = true
120 *(Note, in case this is relevant after all, I also have the following changes; but I don't think I need them:)*
123 # Add and uncomment these if relevant/useful:
125 # python = '/usr/bin/python3.6'
128 Run the compiler with additional flags as needed:
132 build/x86_64-unknown-linux-gnu/stage1/bin/rustc \
134 src/test/codegen/coverage-experiments/just_main.rs \
135 -Zinstrument-coverage \
140 Note the specific line numbers may be different:
143 (lldb) b lib/Transforms/Instrumentation/InstrProfiling.cpp:418
146 Process 93855 stopped
147 * thread #6, name = 'rustc', stop reason = breakpoint 2.1
148 frame #0: 0x00007fffedff7738 librustc_driver-5a0990d8d18fb2b4.so`llvm::InstrProfiling::lowerIntrinsics(this=0x00007fffcc001d40, F=0x00007fffe4552198) at InstrProfiling.cpp:418:23
149 415 auto Instr = I++;
150 416 InstrProfIncrementInst *Inc = castToIncrementInst(&*Instr);
152 -> 418 lowerIncrement(Inc);
153 419 MadeChange = true;
154 420 } else if (auto *Ind = dyn_cast<InstrProfValueProfileInst>(Instr)) {
155 421 lowerValueProfileInst(Ind);