-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix DWARF generation for enums #54004
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
|
||
&layout::Variants::NicheFilling { ref niche, .. } => { | ||
// Find the integer type of the correct size. | ||
let discr_type = niche.value.to_ty(cx.tcx); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can get the size and alignment from niche.value
directly.
16 => Integer::I16, | ||
32 => Integer::I32, | ||
64 => Integer::I64, | ||
bits => bug!("prepare_enum_metadata: unknown niche bit size {}", bits), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there no method on Integer
to do this conversion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not directly (that I could find) but I can use Integer::fit_unsigned
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r=me with nits fixed
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 <[email protected]> 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 <[email protected]> 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? |
None | ||
} else { | ||
Some((i.wrapping_sub(*niche_variants.start()) as u128) | ||
.wrapping_add(niche_start) as u64) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 u64
s 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.
file_metadata, | ||
UNKNOWN_LINE_NUMBER, | ||
enum_type_size.bits(), | ||
enum_type_align.abi_bits() as u32, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, so it's not per-variant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope.
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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> PR rust/23626: * gdb.rust/simple.rs (EmptyEnum): New type. (main): Use it. * gdb.rust/simple.exp (test_one_slice): Add empty enum test.
09009d3
to
98b2688
Compare
@bors r+ |
📌 Commit 98b2688 has been approved by |
Fix DWARF generation for enums 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
☀️ Test successful - status-appveyor, status-travis |
🎉 🎉 🎉 ! |
Bug rust-lang#55606 points out a regression introduced by rust-lang#54004; namely that an assertion can erroneously fire when a niche-filling discriminant value is emitted. This fixes the bug by removing the assertion, and furthermore by arranging for the discriminant value to be masked according to the size of the niche. This makes handling the discriminant a bit simpler for debuggers. The test case is from Jonathan Turner. Closes rust-lang#55606
Fix emission of niche-filling discriminant values Bug #55606 points out a regression introduced by #54004; namely that an assertion can erroneously fire when a niche-filling discriminant value is emitted. This fixes the bug by removing the assertion, and furthermore by arranging for the discriminant value to be masked according to the size of the niche. This makes handling the discriminant a bit simpler for debuggers. The test case is from Jonathan Turner. Closes #55606
A rust-enabled gdb already knows how to display string slices, structs, tuples, and enums (and after rust-lang#54004, the pretty-printers can't handle enums at all). This patch disables these pretty-printers when gdb is rust-enabled. The "gdb-pretty-struct-and-enums-pre-gdb-7-7.rs" test is renamed, because it does not seem to depend on any behavior of that version of gdb, and because gdb 7.7 is 4 years old now.
…, r=nikomatsakis Disable some pretty-printers when gdb is rust-enabled A rust-enabled gdb already knows how to display string slices, structs, tuples, and enums (and after rust-lang#54004, the pretty-printers can't handle enums at all). This patch disables these pretty-printers when gdb is rust-enabled. The "gdb-pretty-struct-and-enums-pre-gdb-7-7.rs" test is renamed, because it does not seem to depend on any behavior of that version of gdb, and because gdb 7.7 is 4 years old now.
A rust-enabled gdb already knows how to display string slices, structs, tuples, and enums (and after rust-lang#54004, the pretty-printers can't handle enums at all). This patch disables these pretty-printers when gdb is rust-enabled. The "gdb-pretty-struct-and-enums-pre-gdb-7-7.rs" test is renamed, because it does not seem to depend on any behavior of that version of gdb, and because gdb 7.7 is 4 years old now.
…, r=alexcrichton Disable some pretty-printers when gdb is rust-enabled A rust-enabled gdb already knows how to display string slices, structs, tuples, and enums (and after rust-lang#54004, the pretty-printers can't handle enums at all). This patch disables these pretty-printers when gdb is rust-enabled. The "gdb-pretty-struct-and-enums-pre-gdb-7-7.rs" test is renamed, because it does not seem to depend on any behavior of that version of gdb, and because gdb 7.7 is 4 years old now.
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