1
- ** Note: This is copied from the
1
+ ** Note: This is copied from the
2
2
[ rust-forge] ( https://github.com/rust-lang-nursery/rust-forge ) . If anything needs
3
3
updating, please open an issue or make a PR on the github repo.**
4
4
@@ -16,7 +16,7 @@ normal Rust programs. IIRC backtraces **don't work** on Mac and on MinGW,
16
16
sorry. If you have trouble or the backtraces are full of ` unknown ` ,
17
17
you might want to find some way to use Linux or MSVC on Windows.
18
18
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
20
20
backtrace looks like this:
21
21
22
22
``` text
@@ -36,8 +36,8 @@ stack backtrace:
36
36
37: rustc_driver::run_compiler
37
37
```
38
38
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
41
41
compiler. Then the backtrace will look like this:
42
42
43
43
``` text
@@ -110,16 +110,16 @@ note: rustc 1.24.0-dev running on x86_64-unknown-linux-gnu
110
110
111
111
note: run with ` RUST_BACKTRACE=1` for a backtrace
112
112
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' ,
114
114
/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
116
116
backtrace.
117
117
stack backtrace:
118
118
(~~~ 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,
120
120
' tcx>>::report_selection_error
121
121
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,
123
123
' tcx>> ::report_fulfillment_errors
124
124
at /home/user/rust/src/librustc/traits/error_reporting.rs:160
125
125
at /home/user/rust/src/librustc/traits/error_reporting.rs:112
@@ -136,7 +136,7 @@ $ # Cool, now I have a backtrace for the error
136
136
137
137
The compiler has a lot of ` debug! ` calls, which print out logging information
138
138
at 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
140
140
compiler is doing a particular thing.
141
141
142
142
To 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.
191
191
### Logging etiquette
192
192
193
193
Because 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
197
197
different one.
198
198
199
199
However, there are still a few concerns that you might care about:
200
200
201
201
### Expensive operations in logs
202
202
203
203
A 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
205
205
that if in the module `rustc::foo` you have a statement
206
206
207
207
```Rust
208
208
debug!("{:?}", random_operation(tcx));
209
209
```
210
210
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
213
213
needed!
214
214
215
215
This 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
219
219
until someone tries to use logging to find * another* bug.
220
220
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
225
225
run unless your log is enabled:
226
226
227
227
` ` ` Rust
@@ -246,7 +246,7 @@ debug!("{:?}", ExpensiveOperationContainer { tcx });
246
246
# # Formatting Graphviz output (.dot files)
247
247
[formatting-graphviz-output]: # formatting-graphviz-output
248
248
249
- Some compiler options for debugging specific features yield graphviz graphs -
249
+ Some compiler options for debugging specific features yield graphviz graphs -
250
250
e.g. the ` # [rustc_mir(borrowck_graphviz_postflow="suffix.dot")]` attribute
251
251
dumps various borrow-checker dataflow graphs.
252
252
@@ -261,30 +261,66 @@ $ firefox maybe_init_suffix.pdf # Or your favorite pdf viewer
261
261
# # Debugging LLVM
262
262
[debugging-llvm]: # debugging-llvm
263
263
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` )
267
287
268
288
The official compilers (including nightlies) have LLVM assertions disabled,
269
289
which means that LLVM assertion failures can show up as compiler crashes (not
270
290
ICEs but " real" crashes) and other sorts of weird behavior. If you are
271
291
encountering these, it is a good idea to try using a compiler with LLVM
272
292
assertions 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.
275
295
276
- The rustc build process builds the LLVM tools into
296
+ The rustc build process builds the LLVM tools into
277
297
` ./build/< host-triple> /llvm/bin` . They can be called directly.
278
298
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,
288
324
you should:
289
325
290
326
` ` ` bash
@@ -295,21 +331,21 @@ $ $OPT -S -O2 < my-file.ll > my
295
331
` ` `
296
332
297
333
If 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.
313
349
314
350
` ` ` bash
315
351
$ ./build/$TRIPLE /llvm/bin/llvm-extract \
@@ -319,4 +355,32 @@ $ ./build/$TRIPLE/llvm/bin/llvm-extract \
319
355
> extracted.ll
320
356
` ` `
321
357
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
+
322
386
[env-logger]: https://docs.rs/env_logger/0.4.3/env_logger/
0 commit comments