1- ** Note: This is copied from the
1+ ** Note: This is copied from the
22[ rust-forge] ( https://github.com/rust-lang-nursery/rust-forge ) . If anything needs
33 updating, please open an issue or make a PR on the github repo.**
44
@@ -16,7 +16,7 @@ normal Rust programs. IIRC backtraces **don't work** on Mac and on MinGW,
1616sorry. If you have trouble or the backtraces are full of ` unknown ` ,
1717you might want to find some way to use Linux or MSVC on Windows.
1818
19- In the default configuration, you don't have line numbers enabled, so the
19+ In the default configuration, you don't have line numbers enabled, so the
2020backtrace looks like this:
2121
2222``` text
@@ -36,8 +36,8 @@ stack backtrace:
3636 37: rustc_driver::run_compiler
3737```
3838
39- If you want line numbers for the stack trace, you can enable
40- ` debuginfo-lines=true ` or ` debuginfo=true ` in your config.toml and rebuild the
39+ If you want line numbers for the stack trace, you can enable
40+ ` debuginfo-lines=true ` or ` debuginfo=true ` in your config.toml and rebuild the
4141compiler. Then the backtrace will look like this:
4242
4343``` text
@@ -110,16 +110,16 @@ note: rustc 1.24.0-dev running on x86_64-unknown-linux-gnu
110110
111111note: run with ` RUST_BACKTRACE=1` for a backtrace
112112
113- thread ' rustc' panicked at ' encountered error with `-Z treat_err_as_bug' ,
113+ thread ' rustc' panicked at ' encountered error with `-Z treat_err_as_bug' ,
114114/home/user/rust/src/librustc_errors/lib.rs:411:12
115- note: Some details are omitted, run with ` RUST_BACKTRACE=full` for a verbose
115+ note: Some details are omitted, run with ` RUST_BACKTRACE=full` for a verbose
116116backtrace.
117117stack backtrace:
118118 (~~~ IRRELEVANT PART OF BACKTRACE REMOVED BY ME ~ ~~)
119- 7: rustc::traits::error_reporting::< impl rustc::infer::InferCtxt< ' a, ' gcx,
119+ 7: rustc::traits::error_reporting::< impl rustc::infer::InferCtxt< ' a, ' gcx,
120120 ' tcx>>::report_selection_error
121121 at /home/user/rust/src/librustc/traits/error_reporting.rs:823
122- 8: rustc::traits::error_reporting::<impl rustc::infer::InferCtxt<' a, ' gcx,
122+ 8: rustc::traits::error_reporting::<impl rustc::infer::InferCtxt<' a, ' gcx,
123123 ' tcx>> ::report_fulfillment_errors
124124 at /home/user/rust/src/librustc/traits/error_reporting.rs:160
125125 at /home/user/rust/src/librustc/traits/error_reporting.rs:112
@@ -136,7 +136,7 @@ $ # Cool, now I have a backtrace for the error
136136
137137The compiler has a lot of ` debug! ` calls, which print out logging information
138138at many points. These are very useful to at least narrow down the location of
139- a bug if not to find it entirely, or just to orient yourself as to why the
139+ a bug if not to find it entirely, or just to orient yourself as to why the
140140compiler is doing a particular thing.
141141
142142To see the logs, you need to set the ` RUST_LOG` environment variable to
@@ -191,37 +191,37 @@ want to call `x.py clean` to force one.
191191### Logging etiquette
192192
193193Because calls to `debug!` are removed by default, in most cases, don' t worry
194- about adding " unnecessary" calls to ` debug! ` and leaving them in code you
195- commit - they won' t slow down the performance of what we ship, and if they
196- helped you pinning down a bug, they will probably help someone else with a
194+ about adding " unnecessary" calls to ` debug! ` and leaving them in code you
195+ commit - they won' t slow down the performance of what we ship, and if they
196+ helped you pinning down a bug, they will probably help someone else with a
197197different one.
198198
199199However, there are still a few concerns that you might care about:
200200
201201### Expensive operations in logs
202202
203203A note of caution: the expressions *within* the `debug!` call are run
204- whenever RUST_LOG is set, even if the filter would exclude the log. This means
204+ whenever RUST_LOG is set, even if the filter would exclude the log. This means
205205that if in the module `rustc::foo` you have a statement
206206
207207```Rust
208208debug!("{:?}", random_operation(tcx));
209209```
210210
211- Then if someone runs a debug `rustc` with `RUST_LOG=rustc::bar`, then
212- `random_operation()` will still run - even while it' s output will never be
211+ Then if someone runs a debug `rustc` with `RUST_LOG=rustc::bar`, then
212+ `random_operation()` will still run - even while it' s output will never be
213213needed!
214214
215215This means that you should not put anything too expensive or likely
216- to crash there - that would annoy anyone who wants to use logging for their own
217- module. Note that if ` RUST_LOG` is unset (the default), then the code will not
218- run - this means that if your logging code panics, then no-one will know it
216+ to crash there - that would annoy anyone who wants to use logging for their own
217+ module. Note that if ` RUST_LOG` is unset (the default), then the code will not
218+ run - this means that if your logging code panics, then no-one will know it
219219until someone tries to use logging to find * another* bug.
220220
221- If you * need* to do an expensive operation in a log, be aware that while log
222- expressions are * evaluated* even if logging is not enabled in your module,
223- they are not * formatted* unless it * is* . This means you can put your
224- expensive/crashy operations inside an ` fmt::Debug` impl, and they will not be
221+ If you * need* to do an expensive operation in a log, be aware that while log
222+ expressions are * evaluated* even if logging is not enabled in your module,
223+ they are not * formatted* unless it * is* . This means you can put your
224+ expensive/crashy operations inside an ` fmt::Debug` impl, and they will not be
225225run unless your log is enabled:
226226
227227` ` ` Rust
@@ -246,7 +246,7 @@ debug!("{:?}", ExpensiveOperationContainer { tcx });
246246# # Formatting Graphviz output (.dot files)
247247[formatting-graphviz-output]: # formatting-graphviz-output
248248
249- Some compiler options for debugging specific features yield graphviz graphs -
249+ Some compiler options for debugging specific features yield graphviz graphs -
250250e.g. the ` # [rustc_mir(borrowck_graphviz_postflow="suffix.dot")]` attribute
251251dumps various borrow-checker dataflow graphs.
252252
@@ -261,30 +261,66 @@ $ firefox maybe_init_suffix.pdf # Or your favorite pdf viewer
261261# # Debugging LLVM
262262[debugging-llvm]: # debugging-llvm
263263
264- LLVM is a big project on its own that probably needs to have its own debugging
265- document (not that I could find one). But here are some tips that are important
266- in a rustc context:
264+ > NOTE: If you are looking for info about code generation, please see [this
265+ > chapter][codegen] instead.
266+
267+ [codegen]: codegen.html
268+
269+ This section is about debugging compiler bugs in code generation (e.g. why the
270+ compiler generated some piece of code or crashed in LLVM). LLVM is a big
271+ project on its own that probably needs to have its own debugging document (not
272+ that I could find one). But here are some tips that are important in a rustc
273+ context:
274+
275+ As a general rule, compilers generate lots of information from analyzing code.
276+ Thus, a useful first step is usually to find a minimal example. One way to do
277+ this is to
278+
279+ 1. create a new crate that reproduces the issue (e.g. adding whatever crate is
280+ at fault as a dependency, and using it from there)
281+
282+ 2. minimize the crate by removing external dependencies; that is, moving
283+ everything relevant to the new crate
284+
285+ 3. further minimize the issue by making the code shorter (there are tools that
286+ help with this like ` creduce` )
267287
268288The official compilers (including nightlies) have LLVM assertions disabled,
269289which means that LLVM assertion failures can show up as compiler crashes (not
270290ICEs but " real" crashes) and other sorts of weird behavior. If you are
271291encountering these, it is a good idea to try using a compiler with LLVM
272292assertions enabled - either an " alt" nightly or a compiler you build yourself
273- by setting ` [llvm] assertions=true` in your config.toml - and
274- see whether anything turns up.
293+ by setting ` [llvm] assertions=true` in your config.toml - and see whether
294+ anything turns up.
275295
276- The rustc build process builds the LLVM tools into
296+ The rustc build process builds the LLVM tools into
277297` ./build/< host-triple> /llvm/bin` . They can be called directly.
278298
279- The default rustc compilation pipeline has multiple codegen units, which is hard
280- to replicate manually and means that LLVM is called multiple times in parallel.
281- If you can get away with it (i.e. if it doesn' t make your bug disappear),
282- passing `-C codegen-units=1` to rustc will make debugging easier.
283-
284- If you want to play with the optimization pipeline, you can use the opt tool
285- from `./build/<host-triple>/llvm/bin/` with the the LLVM IR emitted by rustc.
286- Note that rustc emits different IR depending on whether `-O` is enabled, even
287- without LLVM' s optimizations, so if you want to play with the IR rustc emits,
299+ The default rustc compilation pipeline has multiple codegen units, which is
300+ hard to replicate manually and means that LLVM is called multiple times in
301+ parallel. If you can get away with it (i.e. if it doesn' t make your bug
302+ disappear), passing `-C codegen-units=1` to rustc will make debugging easier.
303+
304+ To rustc to generate LLVM IR, you need to pass the `--emit=llvm-ir` flag. If
305+ you are building via cargo, use the `RUSTFLAGS` environment variable (e.g.
306+ `RUSTFLAGS=' --emit=llvm-ir' `). This causes rustc to spit out LLVM IR into the
307+ target directory.
308+
309+ `cargo llvm-ir [options] path` spits out the LLVM IR for a particular function
310+ at `path`. (`cargo install cargo-asm` installs `cargo asm` and `cargo
311+ llvm-ir`). `--build-type=debug` emits code for debug builds. There are also
312+ other useful options. Also, debug info in LLVM IR can clutter the output a lot:
313+ `RUSTFLAGS="-C debuginfo=0"` is really useful.
314+
315+ `RUSTFLAGS="-C save-temps"` outputs LLVM bitcode (not the same as IR) at
316+ different stages during compilation, which is sometimes useful. One just needs
317+ to convert the bitcode files to `.ll` files using `llvm-dis` which should be in
318+ the target local compilation of rustc.
319+
320+ If you want to play with the optimization pipeline, you can use the `opt` tool
321+ from `./build/<host-triple>/llvm/bin/` with the LLVM IR emitted by rustc. Note
322+ that rustc emits different IR depending on whether `-O` is enabled, even
323+ without LLVM' s optimizations, so if you want to play with the IR rustc emits,
288324you should:
289325
290326` ` ` bash
@@ -295,21 +331,21 @@ $ $OPT -S -O2 < my-file.ll > my
295331` ` `
296332
297333If you just want to get the LLVM IR during the LLVM pipeline, to e.g. see which
298- IR causes an optimization-time assertion to fail, or to see when
299- LLVM performs a particular optimization, you can pass the rustc flag
300- ` -C llvm-args=-print-after-all` , and possibly add
301- ` -C llvm-args=' -filter-print-funcs=EXACT_FUNCTION_NAME` (e.g.
302- `-C llvm-args=' -filter-print-funcs=_ZN11collections3str21_$LT$impl$u20$str$GT $\
303- 7replace17hbe10ea2e7c809b0bE' `).
304-
305- That produces a lot of output into standard error, so you' ll want to pipe
306- that to some file. Also, if you are using neither ` -filter-print-funcs` nor
307- ` -C codegen-units=1` , then, because the multiple codegen units run in parallel,
308- the printouts will mix together and you won' t be able to read anything.
309-
310- If you want just the IR for a specific function (say, you want to see
311- why it causes an assertion or doesn' t optimize correctly), you can use
312- ` llvm-extract ` , e.g.
334+ IR causes an optimization-time assertion to fail, or to see when LLVM performs
335+ a particular optimization, you can pass the rustc flag ` -C
336+ llvm-args=-print-after-all` , and possibly add ` -C
337+ llvm-args=' -filter-print-funcs=EXACT_FUNCTION_NAME` (e.g. `-C
338+ llvm-args=' -filter-print-funcs=_ZN11collections3str21_$LT$impl$u20$str$GT $\
339+ 7replace17hbe10ea2e7c809b0bE' `).
340+
341+ That produces a lot of output into standard error, so you' ll want to pipe that
342+ to some file. Also, if you are using neither ` -filter-print-funcs` nor ` -C
343+ codegen-units=1` , then, because the multiple codegen units run in parallel, the
344+ printouts will mix together and you won' t be able to read anything.
345+
346+ If you want just the IR for a specific function (say, you want to see why it
347+ causes an assertion or doesn' t optimize correctly), you can use ` llvm-extract ` ,
348+ e.g.
313349
314350` ` ` bash
315351$ ./build/$TRIPLE /llvm/bin/llvm-extract \
@@ -319,4 +355,32 @@ $ ./build/$TRIPLE/llvm/bin/llvm-extract \
319355 > extracted.ll
320356` ` `
321357
358+ # ## Filing LLVM bug reports
359+
360+ When filing an LLVM bug report, you will probably want some sort of minimal
361+ working example that demonstrates the problem. The Godbolt compiler explorer is
362+ really helpful for this.
363+
364+ 1. Once you have some LLVM IR for the problematic code (see above), you can
365+ create a minimal working example with Godbolt. Go to
366+ [gcc.godbolt.org](https://gcc.godbolt.org).
367+
368+ 2. Choose ` LLVM-IR` as programming language.
369+
370+ 3. Use ` llc` to compile the IR to a particular target as is:
371+ - There are some useful flags: ` -mattr` enables target features, ` -march=`
372+ selects the target, ` -mcpu=` selects the CPU, etc.
373+ - Commands like ` llc -march=help` output all architectures available, which
374+ is useful because sometimes the Rust arch names and the LLVM names do not
375+ match.
376+ - If you have compiled rustc yourself somewhere, in the target directory
377+ you have binaries for ` llc` , ` opt` , etc.
378+
379+ 4. If you want to optimize the LLVM-IR, you can use ` opt` to see how the LLVM
380+ optimizations transform it.
381+
382+ 5. Once you have a godbolt link demonstrating the issue, it is pretty easy to
383+ fill in an LLVM bug.
384+
385+
322386[env-logger]: https://docs.rs/env_logger/0.4.3/env_logger/
0 commit comments