Fix DWARF generation for enums#54004
Conversation
|
(rust_highfive has picked a reviewer for you, use r? to override) |
There was a problem hiding this comment.
You can get the size and alignment from niche.value directly.
There was a problem hiding this comment.
Is there no method on Integer to do this conversion?
There was a problem hiding this comment.
Not directly (that I could find) but I can use Integer::fit_unsigned.
There was a problem hiding this comment.
Oh, I think you should match on Primitive, convert floats to I32 / I64, and pointers to cx.data_layout().ptr_sized_integer(). That way you don't need to turn an integer back into itself by looking at its size.
|
This definitely wants a test or two. EDIT: though I won’t block this PR if they aren’t easy to write. |
|
I can write more tests but note that there are existing debuginfo tests that already cover the ordinary cases. The new test is testing the case that could not be made to work previously. |
This comment has been minimized.
This comment has been minimized.
|
Still investigating that failure. I'd tried things out with llvm 6 but not 5. I somewhat recall having to make a change here for 6; I will try all 3 ways again but if something has to regress, I think we should let it be 5. |
|
I built rust against LLVM 5, 6, and rust-llvm; and then I tested each one against gdb 7.11, 8.1, and 8.2. This found a crash in 8.2, filed: https://sourceware.org/bugzilla/show_bug.cgi?id=23626. I'll fix this before 8.2.1. I couldn't reproduce the bot's failure; but the bot is using 7.11, and my feeling is that a minor output regression there is nothing to worry about. So, if it persists and there are no objections, I'll just bump the minimum gdb version for the test. |
I rebased & tried again and now it failed. |
At some point I thought I needed to give the variants names, but reverting this and re-testing didn't show any problems. |
8f6ce23 to
1bf986e
Compare
While testing my Rust compiler patch to fix the DWARF representation of Rust enums (rust-lang/rust#54004), I found a gdb crash coming from one of the Rust test cases. The bug here is that the new variant support in gdb does not handle the case where there are no variants in the enum. This patch fixes the problem in a straightforward way. Note that the new tests are somewhat lax because I did not want to try to fully fix this corner case for older compilers. If you think that's unacceptable, let meknow. Tested on x86-64 Fedora 28 using several versions of the Rust compiler. I intend to push this to the 8.2 branch as well. gdb/ChangeLog 2018-09-11 Tom Tromey <tom@tromey.com> PR rust/23626: * rust-lang.c (rust_enum_variant): Now static. (rust_empty_enum_p): New function. (rust_print_enum, rust_evaluate_subexp, rust_print_struct_def): Handle empty enum. gdb/testsuite/ChangeLog 2018-09-11 Tom Tromey <tom@tromey.com> PR rust/23626: * gdb.rust/simple.rs (EmptyEnum): New type. (main): Use it. * gdb.rust/simple.exp (test_one_slice): Add empty enum test.
|
@eddyb can you re-review? I don't think I have sufficient permissions to mark it. Thanks. |
|
@tromey Is the compiler-builtins submodule change intentional? |
There was a problem hiding this comment.
Hmm, I think if you do this then we're "insured" from weird 128-bit bugs:
let niche = (i as u128)
.wrapping_sub(*niche_variants.start() as u128)
.wrapping_add(niche_start);
assert_eq!(niche as u64 as u128, niche);
Some(niche as u64)Note that other than the assert, you also had an overflow bug: if niche_variants.start() is larger than i, subtracting u64s and casting the "negative" result to u128 puts you close to 1 << 64 (because it zero-extends), instead of being a "negative" 128-bit integer.
There was a problem hiding this comment.
Hmm, do all variants use these size/alignment values? Because each variant has its own "sub-layout" that "fits" inside the enum's layout, and it might make more sense to use those individual ones. Also, instead of UNKNOWN_LINE_NUMBER, you can get each variant's declaration span.
There was a problem hiding this comment.
This part is just a bit of DWARF formalism. This is emitting a DW_TAG_variant_part, which according to DWARF is the part of an enclosing structure that can vary. For Rust, the entire thing can vary, so we emit a structure wrapping a variant part, which wraps the variants. Since there can only be one variant part, it makes sense for it to fill the enclosing structure. And, the location of this thing is unimportant as it is basically entirely artificial -- a synthetic construct only necessary because this is how DWARF mandates it.
Nope. |
1bf986e to
8d0df1c
Compare
While testing my Rust compiler patch to fix the DWARF representation of Rust enums (rust-lang/rust#54004), I found a gdb crash coming from one of the Rust test cases. The bug here is that the new variant support in gdb does not handle the case where there are no variants in the enum. This patch fixes the problem in a straightforward way. Note that the new tests are somewhat lax because I did not want to try to fully fix this corner case for older compilers. If you think that's unacceptable, let meknow. Tested on x86-64 Fedora 28 using several versions of the Rust compiler. I intend to push this to the 8.2 branch as well. gdb/ChangeLog 2018-09-13 Tom Tromey <tom@tromey.com> PR rust/23626: * rust-lang.c (rust_enum_variant): Now static. (rust_empty_enum_p): New function. (rust_print_enum, rust_evaluate_subexp, rust_print_struct_def): Handle empty enum. gdb/testsuite/ChangeLog 2018-09-13 Tom Tromey <tom@tromey.com> PR rust/23626: * gdb.rust/simple.rs (EmptyEnum): New type. (main): Use it. * gdb.rust/simple.exp (test_one_slice): Add empty enum test.
While testing my Rust compiler patch to fix the DWARF representation of Rust enums (rust-lang/rust#54004), I found a gdb crash coming from one of the Rust test cases. The bug here is that the new variant support in gdb does not handle the case where there are no variants in the enum. This patch fixes the problem in a straightforward way. Note that the new tests are somewhat lax because I did not want to try to fully fix this corner case for older compilers. If you think that's unacceptable, let meknow. Tested on x86-64 Fedora 28 using several versions of the Rust compiler. I intend to push this to the 8.2 branch as well. 2018-09-13 Tom Tromey <tom@tromey.com> PR rust/23626: * rust-lang.c (rust_enum_variant): Now static. (rust_empty_enum_p): New function. (rust_print_enum, rust_evaluate_subexp, rust_print_struct_def): Handle empty enum. gdb/testsuite/ChangeLog 2018-09-13 Tom Tromey <tom@tromey.com> PR rust/23626: * gdb.rust/simple.rs (EmptyEnum): New type. (main): Use it. * gdb.rust/simple.exp (test_one_slice): Add empty enum test.
|
@tromey should this be approved? I think you're approved to merge this as well? |
|
Yes, it should be approved. I'll try. @bors r+ |
|
📌 Commit 09009d386de739bccc2763e37feb9d5426cf162d has been approved by |
|
⌛ Testing commit 09009d386de739bccc2763e37feb9d5426cf162d with merge fc5cf77a07f3bc8db8db5912b39ee3b27380a4bf... |
|
💔 Test failed - status-travis |
|
The job Click to expand the log.I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
|
Some difference between the apple lldb and the (non-rust-enabled) linux lldb I suppose. Will do another macOS build next week. |
|
Forgot to make those tests rust-lldb-only. |
The DWARF generated for Rust enums was always somewhat unusual. Rather than using DWARF constructs directly, it would emit magic field names like "RUST$ENCODED$ENUM$0$Name" and "RUST$ENUM$DISR". Since PR rust-lang#45225, though, even this has not worked -- the ad hoc scheme was not updated to handle the wider variety of niche-filling layout optimizations now available. This patch changes the generated DWARF to use the standard tags meant for this purpose; namely, DW_TAG_variant and DW_TAG_variant_part. The patch to implement this went in to LLVM 7. In order to work with older versions of LLVM, and because LLVM doesn't do anything here for PDB, the existing code is kept as a fallback mode. Support for this DWARF is in the Rust lldb and in gdb 8.2. Closes rust-lang#32920 Closes rust-lang#32924 Closes rust-lang#52762 Closes rust-lang#53153
This fixes the issues pointed out in review.
Update the new enum-debug to ensure that field "D" does not have a discrimnant.
Rename the previous enum debug info test, and add more tests to cover c-like enums and tagged (ordinary) enums.
@eddyb pointed out in review that the niche value computation had a possible integer overflow problem, fixed here as he suggested.
Bug rust-lang#52452 notes some debuginfo test regressions when moving to gdb 8.1. This series will also cause versions of gdb before 8.2 to fail when a recent LLVM is used -- DW_TAG_variant_part support was not added until 8.2. This patch updates one of the builders to a later version of Ubuntu, which comes with gdb 8.2. It updates the relevant tests to require both a new-enough LLVM and a new-enough gdb; the subsequent patch arranges to continue testing the fallback mode. The "gdbg" results are removed from these tests because the tests now require a rust-enabled gdb. If you read closely, you'll see that some of the lldb results in this patch still look a bit strange. This will be addressed in a subsequent patch; I believe the fix is to disable the Python pretty-printers when lldb is rust-enabled.
The enum debuginfo patch includes a legacy mode that is used when building against LLVM 5 and LLVM 6. The main enum debuginfo tests have been updated to rely on the new approach and a new-enough gdb. This patch makes a copy of these tests so that the fallback mode will continue to be tested. Note that nil-enum.rs is not copied; it seemed not to provide enough value to bother. A new header directive is added, "ignore-llvm-version". I will send a patch to update the rustc documentation once this lands.
Update src/tools/lldb to pick up a needed bug fix in the DW_TAG_variant_part handling.
|
@bors r+ |
|
📌 Commit 98b2688 has been approved by |
|
☀️ Test successful - status-appveyor, status-travis |
|
🎉 🎉 🎉 ! |
The DWARF generated for Rust enums was always somewhat unusual.
Rather than using DWARF constructs directly, it would emit magic field
names like "RUST$ENCODED$ENUM$0$Name" and "RUST$ENUM$DISR". Since
PR #45225, though, even this has not worked -- the ad hoc scheme was
not updated to handle the wider variety of niche-filling layout
optimizations now available.
This patch changes the generated DWARF to use the standard tags meant
for this purpose; namely, DW_TAG_variant and DW_TAG_variant_part.
The patch to implement this went in to LLVM 7. In order to work with
older versions of LLVM, and because LLVM doesn't do anything here for
PDB, the existing code is kept as a fallback mode.
Support for this DWARF is in the Rust lldb and in gdb 8.2.
Closes #32920
Closes #32924
Closes #52762
Closes #53153