66[ codegen ] : ./codegen.md
77
88This section is about debugging compiler bugs in code generation (e.g. why the
9- compiler generated some piece of code or crashed in LLVM). LLVM is a big
10- project on its own that probably needs to have its own debugging document (not
11- that I could find one). But here are some tips that are important in a rustc
12- context:
9+ compiler generated some piece of code or crashed in LLVM).
10+ LLVM is a big project that probably needs to have its own debugging document,
11+ but following are some tips that are important in a rustc context.
1312
1413### Minimize the example
1514
1615As a general rule, compilers generate lots of information from analyzing code.
17- Thus, a useful first step is usually to find a minimal example. One way to do
18- this is to
16+ Thus, a useful first step is usually to find a minimal example.
17+ One way to do this is to
1918
20191 . create a new crate that reproduces the issue (e.g. adding whatever crate is
2120at fault as a dependency, and using it from there)
@@ -35,14 +34,13 @@ For more discussion on methodology for steps 2 and 3 above, there is an
3534
3635The official compilers (including nightlies) have LLVM assertions disabled,
3736which means that LLVM assertion failures can show up as compiler crashes (not
38- ICEs but "real" crashes) and other sorts of weird behavior. If you are
39- encountering these, it is a good idea to try using a compiler with LLVM
37+ ICEs but "real" crashes) and other sorts of weird behavior.
38+ If you are encountering these, it is a good idea to try using a compiler with LLVM
4039assertions enabled - either an "alt" nightly or a compiler you build yourself
41- by setting ` [llvm] assertions=true ` in your bootstrap.toml - and see whether
42- anything turns up.
40+ by setting ` llvm.assertions = true ` in your bootstrap.toml - and see whether anything turns up.
4341
44- The rustc build process builds the LLVM tools into
45- ` ./build/<host-triple>/llvm/bin ` . They can be called directly.
42+ The rustc build process builds the LLVM tools into ` build/host/llvm/bin ` .
43+ They can be called directly.
4644These tools include:
4745 * [ ` llc ` ] , which compiles bitcode (` .bc ` files) to executable code; this can be used to
4846 replicate LLVM backend bugs.
@@ -55,9 +53,10 @@ These tools include:
5553[ `bugpoint` ] : https://llvm.org/docs/Bugpoint.html
5654
5755By default, the Rust build system does not check for changes to the LLVM source code or
58- its build configuration settings. So, if you need to rebuild the LLVM that is linked
56+ its build configuration settings.
57+ So, if you need to rebuild the LLVM that is linked
5958into ` rustc ` , first delete the file ` .llvm-stamp ` , which should be located
60- in ` build/< host-triple> /llvm/ ` .
59+ in ` build/host/llvm/ ` .
6160
6261The default rustc compilation pipeline has multiple codegen units, which is
6362hard to replicate manually and means that LLVM is called multiple times in
@@ -66,26 +65,27 @@ disappear), passing `-C codegen-units=1` to rustc will make debugging easier.
6665
6766### Get your hands on raw LLVM input
6867
69- For rustc to generate LLVM IR, you need to pass the ` --emit=llvm-ir ` flag. If
70- you are building via cargo, use the ` RUSTFLAGS ` environment variable (e.g.
71- ` RUSTFLAGS='--emit=llvm-ir' ` ). This causes rustc to spit out LLVM IR into the
72- target directory.
68+ For rustc to generate LLVM IR, you need to pass the ` --emit=llvm-ir ` flag.
69+ If you are building via cargo,
70+ use the ` RUSTFLAGS ` environment variable (e.g. ` RUSTFLAGS ='--emit=llvm-ir'` ).
71+ This causes rustc to spit out LLVM IR into the target directory.
7372
74- ` cargo llvm-ir [options] path ` spits out the LLVM IR for a particular function
75- at ` path ` . (` cargo install cargo-asm ` installs ` cargo asm ` and `cargo
76- llvm-ir` ). ` --build-type=debug` emits code for debug builds. There are also
77- other useful options. Also, debug info in LLVM IR can clutter the output a lot:
73+ ` cargo llvm-ir [options] path ` spits out the LLVM IR for a particular function at ` path ` .
74+ (` cargo install cargo-asm ` installs ` cargo asm ` and ` cargo llvm-ir ` ).
75+ ` --build-type=debug ` emits code for debug builds.
76+ There are also other useful options.
77+ Also, debug info in LLVM IR can clutter the output a lot:
7878` RUSTFLAGS="-C debuginfo=0" ` is really useful.
7979
8080` RUSTFLAGS="-C save-temps" ` outputs LLVM bitcode at
81- different stages during compilation, which is sometimes useful. The output LLVM
82- bitcode will be in ` .bc ` files in the compiler's output directory, set via the
81+ different stages during compilation, which is sometimes useful.
82+ The output LLVM bitcode will be in ` .bc ` files in the compiler's output directory, set via the
8383` --out-dir DIR ` argument to ` rustc ` .
8484
8585 * If you are hitting an assertion failure or segmentation fault from the LLVM
8686 backend when invoking ` rustc ` itself, it is a good idea to try passing each
87- of these ` .bc ` files to the ` llc ` command, and see if you get the same
88- failure. (LLVM developers often prefer a bug reduced to a ` .bc ` file over one
87+ of these ` .bc ` files to the ` llc ` command, and see if you get the same failure.
88+ (LLVM developers often prefer a bug reduced to a ` .bc ` file over one
8989 that uses a Rust crate for its minimized reproduction.)
9090
9191 * To get human readable versions of the LLVM bitcode, one just needs to convert
@@ -100,7 +100,7 @@ you should:
100100``` bash
101101$ rustc +local my-file.rs --emit=llvm-ir -O -C no-prepopulate-passes \
102102 -C codegen-units=1
103- $ OPT=./ build/$TRIPLE /llvm/bin/opt
103+ $ OPT=build/$TRIPLE /llvm/bin/opt
104104$ $OPT -S -O2 < my-file.ll > my
105105```
106106
@@ -112,8 +112,8 @@ llvm-args='-filter-print-funcs=EXACT_FUNCTION_NAME` (e.g. `-C
112112llvm-args='-filter-print-funcs=_ ZN11collections3str21_ $LT$impl$u20$str$GT$\
1131137replace17hbe10ea2e7c809b0bE'`).
114114
115- That produces a lot of output into standard error, so you'll want to pipe that
116- to some file. Also, if you are using neither ` -filter-print-funcs ` nor `-C
115+ That produces a lot of output into standard error, so you'll want to pipe that to some file.
116+ Also, if you are using neither ` -filter-print-funcs ` nor `-C
117117codegen-units=1`, then, because the multiple codegen units run in parallel, the
118118printouts will mix together and you won't be able to read anything.
119119
@@ -125,8 +125,8 @@ printouts will mix together and you won't be able to read anything.
125125
126126 * Within LLVM itself, calling ` F.getParent()->dump() ` at the beginning of
127127 ` SafeStackLegacyPass::runOnFunction ` will dump the whole module, which
128- may provide better basis for reproduction. (However, you
129- should be able to get that same dump from the ` .bc ` files dumped by
128+ may provide better basis for reproduction.
129+ (However, you should be able to get that same dump from the ` .bc ` files dumped by
130130 ` -C save-temps ` .)
131131
132132If you want just the IR for a specific function (say, you want to see why it
@@ -145,29 +145,29 @@ $ ./build/$TRIPLE/llvm/bin/llvm-extract \
145145
146146If you are seeing incorrect behavior due to an optimization pass, a very handy
147147LLVM option is ` -opt-bisect-limit ` , which takes an integer denoting the index
148- value of the highest pass to run. Index values for taken passes are stable
148+ value of the highest pass to run.
149+ Index values for taken passes are stable
149150from run to run; by coupling this with software that automates bisecting the
150- search space based on the resulting program, an errant pass can be quickly
151- determined. When an ` -opt-bisect-limit ` is specified, all runs are displayed
151+ search space based on the resulting program, an errant pass can be quickly determined.
152+ When an ` -opt-bisect-limit ` is specified, all runs are displayed
152153to standard error, along with their index and output indicating if the
153154pass was run or skipped. Setting the limit to an index of -1 (e.g.,
154155` RUSTFLAGS="-C llvm-args=-opt-bisect-limit=-1" ` ) will show all passes and
155156their corresponding index values.
156157
157158If you want to play with the optimization pipeline, you can use the [ ` opt ` ] tool
158- from ` ./build/< host-triple> /llvm/bin/ ` with the LLVM IR emitted by rustc.
159+ from ` ./build/host/llvm/bin/ ` with the LLVM IR emitted by rustc.
159160
160161When investigating the implementation of LLVM itself, you should be
161162aware of its [ internal debug infrastructure] [ llvm-debug ] .
162163This is provided in LLVM Debug builds, which you enable for rustc
163164LLVM builds by changing this setting in the bootstrap.toml:
164165```
165- [llvm]
166166# Indicates whether the LLVM assertions are enabled or not
167- assertions = true
167+ llvm. assertions = true
168168
169169# Indicates whether the LLVM build is a Release or Debug build
170- optimize = false
170+ llvm. optimize = false
171171```
172172The quick summary is:
173173 * Setting ` assertions=true ` enables coarse-grain debug messaging.
@@ -190,8 +190,8 @@ specifically the `#t-compiler/wg-llvm` channel.
190190### Compiler options to know and love
191191
192192The ` -C help ` and ` -Z help ` compiler switches will list out a variety
193- of interesting options you may find useful. Here are a few of the most
194- common that pertain to LLVM development (some of them are employed in the
193+ of interesting options you may find useful.
194+ Here are a few of the most common that pertain to LLVM development (some of them are employed in the
195195tutorial above):
196196
197197- The ` --emit llvm-ir ` option emits a ` <filename>.ll ` file with LLVM IR in textual format
@@ -201,7 +201,8 @@ tutorial above):
201201 e.g. ` -C llvm-args=-print-before-all ` to print IR before every LLVM
202202 pass.
203203- The ` -C no-prepopulate-passes ` will avoid pre-populate the LLVM pass
204- manager with a list of passes. This will allow you to view the LLVM
204+ manager with a list of passes.
205+ This will allow you to view the LLVM
205206 IR that rustc generates, not the LLVM IR after optimizations.
206207- The ` -C passes=val ` option allows you to supply a space separated list of extra LLVM passes to run
207208- The ` -C save-temps ` option saves all temporary output files during compilation
@@ -211,35 +212,34 @@ tutorial above):
211212- The ` -Z no-parallel-backend ` will disable parallel compilation of distinct compilation units
212213- The ` -Z llvm-time-trace ` option will output a Chrome profiler compatible JSON file
213214 which contains details and timings for LLVM passes.
214- - The ` -C llvm-args=-opt-bisect-limit=<index> ` option allows for bisecting LLVM
215- optimizations.
215+ - The ` -C llvm-args=-opt-bisect-limit=<index> ` option allows for bisecting LLVM optimizations.
216216
217217### Filing LLVM bug reports
218218
219219When filing an LLVM bug report, you will probably want some sort of minimal
220- working example that demonstrates the problem. The Godbolt compiler explorer is
221- really helpful for this.
220+ working example that demonstrates the problem.
221+ The Godbolt compiler explorer is really helpful for this.
222222
2232231 . Once you have some LLVM IR for the problematic code (see above), you can
224- create a minimal working example with Godbolt. Go to
225- [ llvm.godbolt.org] ( https://llvm.godbolt.org ) .
224+ create a minimal working example with Godbolt.
225+ Go to [ llvm.godbolt.org] ( https://llvm.godbolt.org ) .
226226
2272272 . Choose ` LLVM-IR ` as programming language.
228228
2292293 . Use ` llc ` to compile the IR to a particular target as is:
230230 - There are some useful flags: ` -mattr ` enables target features, ` -march= `
231231 selects the target, ` -mcpu= ` selects the CPU, etc.
232232 - Commands like ` llc -march=help ` output all architectures available, which
233- is useful because sometimes the Rust arch names and the LLVM names do not
234- match.
233+ is useful because sometimes the Rust arch names and the LLVM names do not match.
235234 - If you have compiled rustc yourself somewhere, in the target directory
236235 you have binaries for ` llc ` , ` opt ` , etc.
237236
2382374 . If you want to optimize the LLVM-IR, you can use ` opt ` to see how the LLVM
239238 optimizations transform it.
240239
2412405 . Once you have a godbolt link demonstrating the issue, it is pretty easy to
242- fill in an LLVM bug. Just visit their [ github issues page] [ llvm-issues ] .
241+ fill in an LLVM bug.
242+ Just visit their [ github issues page] [ llvm-issues ] .
243243
244244[ llvm-issues ] : https://github.com/llvm/llvm-project/issues
245245
@@ -251,8 +251,8 @@ gotten the fix yet (or perhaps you are familiar enough with LLVM to fix it yours
251251
252252In that case, we can sometimes opt to port the fix for the bug
253253directly to our own LLVM fork, so that rustc can use it more easily.
254- Our fork of LLVM is maintained in [ rust-lang/llvm-project] . Once
255- you've landed the fix there, you'll also need to land a PR modifying
254+ Our fork of LLVM is maintained in [ rust-lang/llvm-project] .
255+ Once you've landed the fix there, you'll also need to land a PR modifying
256256our submodule commits -- ask around on Zulip for help.
257257
258258[ rust-lang/llvm-project ] : https://github.com/rust-lang/llvm-project/
0 commit comments