]> git.proxmox.com Git - rustc.git/blame - src/doc/rustc-dev-guide/src/codegen/debugging.md
New upstream version 1.43.0+dfsg1
[rustc.git] / src / doc / rustc-dev-guide / src / codegen / debugging.md
CommitLineData
532ac7d7
XL
1## Debugging LLVM
2
3> NOTE: If you are looking for info about code generation, please see [this
4> chapter][codegen] instead.
5
6[codegen]: ../codegen.md
7
8This section is about debugging compiler bugs in code generation (e.g. why the
9compiler generated some piece of code or crashed in LLVM). LLVM is a big
10project on its own that probably needs to have its own debugging document (not
11that I could find one). But here are some tips that are important in a rustc
12context:
13
14As a general rule, compilers generate lots of information from analyzing code.
15Thus, a useful first step is usually to find a minimal example. One way to do
16this is to
17
181. create a new crate that reproduces the issue (e.g. adding whatever crate is
19at fault as a dependency, and using it from there)
20
212. minimize the crate by removing external dependencies; that is, moving
22everything relevant to the new crate
23
243. further minimize the issue by making the code shorter (there are tools that
25help with this like `creduce`)
26
27The official compilers (including nightlies) have LLVM assertions disabled,
28which means that LLVM assertion failures can show up as compiler crashes (not
29ICEs but "real" crashes) and other sorts of weird behavior. If you are
30encountering these, it is a good idea to try using a compiler with LLVM
31assertions enabled - either an "alt" nightly or a compiler you build yourself
32by setting `[llvm] assertions=true` in your config.toml - and see whether
33anything turns up.
34
35The rustc build process builds the LLVM tools into
36`./build/<host-triple>/llvm/bin`. They can be called directly.
37
38The default rustc compilation pipeline has multiple codegen units, which is
39hard to replicate manually and means that LLVM is called multiple times in
40parallel. If you can get away with it (i.e. if it doesn't make your bug
41disappear), passing `-C codegen-units=1` to rustc will make debugging easier.
42
60c5eb7d 43For rustc to generate LLVM IR, you need to pass the `--emit=llvm-ir` flag. If
532ac7d7
XL
44you are building via cargo, use the `RUSTFLAGS` environment variable (e.g.
45`RUSTFLAGS='--emit=llvm-ir'`). This causes rustc to spit out LLVM IR into the
46target directory.
47
48`cargo llvm-ir [options] path` spits out the LLVM IR for a particular function
49at `path`. (`cargo install cargo-asm` installs `cargo asm` and `cargo
50llvm-ir`). `--build-type=debug` emits code for debug builds. There are also
51other useful options. Also, debug info in LLVM IR can clutter the output a lot:
52`RUSTFLAGS="-C debuginfo=0"` is really useful.
53
54`RUSTFLAGS="-C save-temps"` outputs LLVM bitcode (not the same as IR) at
55different stages during compilation, which is sometimes useful. One just needs
56to convert the bitcode files to `.ll` files using `llvm-dis` which should be in
57the target local compilation of rustc.
58
59If you want to play with the optimization pipeline, you can use the `opt` tool
60from `./build/<host-triple>/llvm/bin/` with the LLVM IR emitted by rustc. Note
61that rustc emits different IR depending on whether `-O` is enabled, even
62without LLVM's optimizations, so if you want to play with the IR rustc emits,
63you should:
64
65```bash
66$ rustc +local my-file.rs --emit=llvm-ir -O -C no-prepopulate-passes \
67 -C codegen-units=1
68$ OPT=./build/$TRIPLE/llvm/bin/opt
69$ $OPT -S -O2 < my-file.ll > my
70```
71
72If you just want to get the LLVM IR during the LLVM pipeline, to e.g. see which
73IR causes an optimization-time assertion to fail, or to see when LLVM performs
74a particular optimization, you can pass the rustc flag `-C
75llvm-args=-print-after-all`, and possibly add `-C
76llvm-args='-filter-print-funcs=EXACT_FUNCTION_NAME` (e.g. `-C
77llvm-args='-filter-print-funcs=_ZN11collections3str21_$LT$impl$u20$str$GT$\
787replace17hbe10ea2e7c809b0bE'`).
79
80That produces a lot of output into standard error, so you'll want to pipe that
81to some file. Also, if you are using neither `-filter-print-funcs` nor `-C
82codegen-units=1`, then, because the multiple codegen units run in parallel, the
83printouts will mix together and you won't be able to read anything.
84
85If you want just the IR for a specific function (say, you want to see why it
86causes an assertion or doesn't optimize correctly), you can use `llvm-extract`,
87e.g.
88
89```bash
90$ ./build/$TRIPLE/llvm/bin/llvm-extract \
91 -func='_ZN11collections3str21_$LT$impl$u20$str$GT$7replace17hbe10ea2e7c809b0bE' \
92 -S \
93 < unextracted.ll \
94 > extracted.ll
95```
96
60c5eb7d
XL
97### Getting help and asking questions
98
99If you have some questions, head over to the [rust-lang Zulip] and
100specifically the `#t-compiler/wg-llvm` stream.
101
102[rust-lang Zulip]: https://rust-lang.zulipchat.com/
103
104### Compiler options to know and love
105
106The `-Chelp` and `-Zhelp` compiler switches will list out a variety
107of interesting options you may find useful. Here are a few of the most
108common that pertain to LLVM development (some of them are employed in the
109tutorial above):
110
111- The `--emit llvm-ir` option emits a `<filename>.ll` file with LLVM IR in textual format
112 - The `--emit llvm-bc` option emits in bytecode format (`<filename>.bc`)
113- Passing `-Cllvm-args=<foo>` allows passing pretty much all the
114 options that tools like llc and opt would accept;
115 e.g. `-Cllvm-args=-print-before-all` to print IR before every LLVM
116 pass.
117- The `-Cno-prepopulate-passes` will avoid pre-populate the LLVM pass
118 manager with a list of passes. This will allow you to view the LLVM
119 IR that rustc generates, not the LLVM IR after optimizations.
120- The `-Cpasses=val` option allows you to supply a (space seprated) list of extra LLVM passes to run
121- The `-Csave-temps` option saves all temporary output files during compilation
122- The `-Zprint-llvm-passes` option will print out LLVM optimization passes being run
123- The `-Ztime-llvm-passes` option measures the time of each LLVM pass
124- The `-Zverify-llvm-ir` option will verify the LLVM IR for correctness
125- The `-Zno-parallel-llvm` will disable parallel compilation of distinct compilation units
74b04a01
XL
126- The `-Zllvm-time-trace` option will output a Chrome profiler compatible JSON file
127 which contains details and timings for LLVM passes.
60c5eb7d 128
532ac7d7
XL
129### Filing LLVM bug reports
130
131When filing an LLVM bug report, you will probably want some sort of minimal
132working example that demonstrates the problem. The Godbolt compiler explorer is
133really helpful for this.
134
1351. Once you have some LLVM IR for the problematic code (see above), you can
136create a minimal working example with Godbolt. Go to
137[gcc.godbolt.org](https://gcc.godbolt.org).
138
1392. Choose `LLVM-IR` as programming language.
140
1413. Use `llc` to compile the IR to a particular target as is:
142 - There are some useful flags: `-mattr` enables target features, `-march=`
143 selects the target, `-mcpu=` selects the CPU, etc.
144 - Commands like `llc -march=help` output all architectures available, which
145 is useful because sometimes the Rust arch names and the LLVM names do not
146 match.
147 - If you have compiled rustc yourself somewhere, in the target directory
148 you have binaries for `llc`, `opt`, etc.
149
1504. If you want to optimize the LLVM-IR, you can use `opt` to see how the LLVM
151 optimizations transform it.
152
1535. Once you have a godbolt link demonstrating the issue, it is pretty easy to
60c5eb7d
XL
154 fill in an LLVM bug. Just visit [bugs.llvm.org](https://bugs.llvm.org/).
155
156### Porting bug fixes from LLVM
157
158Once you've identified the bug as an LLVM bug, you will sometimes
159find that it has already been reported and fixed in LLVM, but we haven't
160gotten the fix yet (or perhaps you are familiar enough with LLVM to fix it yourself).
161
162In that case, we can sometimes opt to port the fix for the bug
163directly to our own LLVM fork, so that rustc can use it more easily.
164Our fork of LLVM is maintained in [rust-lang/llvm-project]. Once
165you've landed the fix there, you'll also need to land a PR modifying
166our submodule commits -- ask around on Zulip for help.
167
168[rust-lang/llvm-project]: https://github.com/rust-lang/llvm-project/