]> git.lizzy.rs Git - rust.git/blob - src/test/codegen/coverage-experiments/README-THIS-IS-TEMPORARY.md
3b69c0a406594aa7f826fe1d2ac11587e18f9a5c
[rust.git] / src / test / codegen / coverage-experiments / README-THIS-IS-TEMPORARY.md
1 # codegen/coverage-experiments
2 *<h2>THIS DIRECTORY IS TEMPORARY</h2>*
3
4 This directory contains some work-in-progress (WIP) code used for experimental development and
5 testing of Rust Coverage feature development.
6
7 The code in this directory will be removed, or migrated into product tests, when the Rust
8 Coverage feature is complete.
9
10 [TOC]
11
12 ## Development Notes
13
14 ### config.toml
15
16 config.toml probably requires (I should verify that intrinsic `llvm.instrprof.increment`
17 code generation ONLY works with this config option):
18
19   profiler = true
20
21 ## First build
22
23 ```shell
24 ./x.py clean
25 ./x.py build -i --stage 1 src/libstd
26 ```
27
28 ## Incremental builds *IF POSSIBLE!*
29
30 ```shell
31 ./x.py build -i --stage 1 src/libstd --keep-stage 1
32 ```
33
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.*
35
36 ## Compile a test program with LLVM coverage instrumentation
37
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.*
39
40 Suggested debug configuration to confirm Rust coverage features:
41 ```shell
42 $ export RUSTC_LOG=rustc_codegen_llvm::intrinsic,rustc_mir::transform::instrument_coverage=debug
43 ```
44
45 Ensure the new compiled `rustc` is used (the path below, relative to the `rust` code repository root, is an example only):
46
47 ```shell
48 $ build/x86_64-unknown-linux-gnu/stage1/bin/rustc \
49   src/test/codegen/coverage-experiments/just_main.rs \
50   -Zinstrument-coverage
51 ```
52
53 ### About the test programs in coverage-experiments/src/
54
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.)
56
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.
58
59 Be aware that some of the files and/or comments may be outdated.
60
61 ### Additional `llvm` flags (append to the `rustc` command)
62
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:
64
65 ```shell
66   --emit llvm-ir \
67   -Zverify-llvm-ir \
68   -Zprint-llvm-passes \
69   -Csave-temps \
70   -Cllvm-args=-print-before-all
71 ```
72
73 ### Additional flags for MIR analysis and transforms
74
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.**)
76
77 ```shell
78   -Zdump-mir=main \
79   -Zdump-mir-graphviz
80 ```
81
82 ### Flags I've used but appear to be irrelvant to `-Zinstrument-coverage` after all:
83 ```shell
84   # -Zprofile
85   # -Ccodegen-units=1
86   # -Cinline-threshold=0
87   # -Clink-dead-code
88   # -Coverflow-checks=off
89 ```
90
91 ## Run the test program compiled with code coverage instrumentation (maybe):
92
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.
94
95 The test program should run as expected, currently does not generate any coverage output.
96
97 *Example:*
98
99 ```shell
100   $ src/test/codegen/coverage-experiments/just_main
101   hello world! (should be covered)
102 ```
103
104 ### Running the coverage-enabled `rustc` compiler in the `lldb` debugger:
105
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.
107
108 First, update config.toml for debugging:
109
110 ```toml
111   [llvm]
112   optimize = false
113   release-debuginfo = true
114
115   [rust]
116   debug = true
117   debuginfo-level = 2
118 ```
119
120 *(Note, in case this is relevant after all, I also have the following changes; but I don't think I need them:)*
121
122 ```toml
123   # Add and uncomment these if relevant/useful:
124   # codegen-units = 0
125   # python = '/usr/bin/python3.6'
126 ```
127
128 Run the compiler with additional flags as needed:
129
130 ```shell
131 lldb \
132   build/x86_64-unknown-linux-gnu/stage1/bin/rustc \
133   -- \
134   src/test/codegen/coverage-experiments/just_main.rs \
135   -Zinstrument-coverage \
136   -Zdump-mir=main \
137   -Zdump-mir-graphviz
138 ```
139
140 Note the specific line numbers may be different:
141
142 ```c++
143 (lldb) b lib/Transforms/Instrumentation/InstrProfiling.cpp:418
144 (lldb) r
145
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);
151    417        if (Inc) {
152 -> 418          lowerIncrement(Inc);
153    419          MadeChange = true;
154    420        } else if (auto *Ind = dyn_cast<InstrProfValueProfileInst>(Instr)) {
155    421          lowerValueProfileInst(Ind);
156 (lldb)
157 ```