Skip to content
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

debuginfo: Composite type reform and enum support. #7710

Closed
wants to merge 26 commits into from

Conversation

michaelwoerister
Copy link
Member

This pull request includes various improvements:

  • Composite types (structs, tuples, boxes, etc) are now handled more cleanly by debuginfo generation. Most notably, field offsets are now extracted directly from LLVM types, as opposed to trying to reconstruct them. This leads to more stable handling of edge cases (e.g. packed structs or structs implementing drop).
  • debuginfo.rs in general has seen a major cleanup. This includes better formatting, more readable variable and function names, removal of dead code, and better factoring of functionality.
  • Handling of VariantInfo in ty.rs has been improved. That is, the type VariantInfo = @VariantInfo_ typedef has been replaced with explicit uses of @VariantInfo, and the duplicated logic for creating VariantInfo instances in ty::enum_variants() and typeck::check::mod::check_enum_variants() has been unified into a single constructor function. Both function now look nicer too :)
  • Debug info generation for enum types is now mostly supported. This includes:
    • Good support for C-style enums. Both DWARF and gdb know how to handle them.
    • Proper description of tuple- and struct-style enum variants as unions of structs.
    • Proper handling of univariant enums without discriminator field.
    • Unfortunately gdb always prints all possible interpretations of a union, so debug output of enums is verbose and unintuitive. Neither LLVM nor gdb support DWARF's DW_TAG_variant which allows to properly describe tagged unions. Adding support for this to LLVM seems doable. gdb however is another story. In the future we might be able to use gdb's Python scripting support to alleviate this problem. In agreement with @jdm this is not a high priority for now.
  • The debuginfo test suite has been extended with 14 test files including tests for packed structs (with Drop), boxed structs, boxed vecs, vec slices, c-style enums (standalone and embedded), empty enums, tuple- and struct-style enums, and various pointer types to the above.

What is not yet included is DI support for some enum edge-cases represented as described in trans::adt::NullablePointer.

Cheers,
Michael

PS: closes #7819, fixes #7712

@jdm
Copy link
Contributor

jdm commented Jul 11, 2013

\o/

I'll work my way through this today, hopefully.

@jdm
Copy link
Contributor

jdm commented Jul 12, 2013

One general naming comment: it seems like some functions now use a get_or_create prefix, while others just use create. Is this reflecting the caching nature of their implementation? That doesn't seem important to distinguish to me, and I think names like block_metadata and file_metadata would be descriptive of their purpose.

@jdm
Copy link
Contributor

jdm commented Jul 12, 2013

Style nits: I'd like to move away from multi-line unsafe blocks opening on the same line as existing code.

@michaelwoerister
Copy link
Member Author

Style nits: I'd like to move away from multi-line unsafe blocks opening on the same line as existing code.

You mean something like this:

do member_name.as_c_str |member_name| { unsafe {
    llvm::LLVMDIBuilderCreateMemberType(
        DIB(cx),
        file_metadata,
        ...,
        0,
        member_type_metadata[i])
}}

would turn into the following?

do member_name.as_c_str |member_name| { 
    unsafe {
        llvm::LLVMDIBuilderCreateMemberType(
            DIB(cx),
            file_metadata,
            ...,
            0,
            member_type_metadata[i])
    }
}

@michaelwoerister
Copy link
Member Author

...and I think names like block_metadata and file_metadata would be descriptive of their purpose.

Yeah, I definitely went for verbosity in the naming style. This was certainly influenced by my recent experiences of having to try to understand this code without much prior knowledge or documentation. My thinking behind this was that one should be able to get some insight into what's going on by just reading part of the code, because often a newcomer (or someone doing a quick fix in some code otherwise not known to them) will not be aware of the internal workings of these functions (such as that LLVM will merge duplicate metadata anyway and it is thus no semantic difference whether caching happens or not).

If you find this exceedingly ugly, we can change it of course. But otherwise I would still vote for some redundancy in the naming if it improves readability (even if it impedes writeability a bit).

That being said, I'm not completely satisfied with the naming in the module either. Maybe your approach with just file_metadata (with neither create_ nor get_or_create_ prefix) plus some good documentation in the form of comments would be the best solution.

@jdm
Copy link
Contributor

jdm commented Jul 15, 2013

  •    return create_composite_type_metadata(cx, Type::nil(), enum_name, &[], &[], &[], span); 
    

Are the &s necessary here?

@jdm
Copy link
Contributor

jdm commented Jul 15, 2013

With regards to the stage0 thing, I'm inclined to just hold off merging this until we get a new snapshot that makes it irrelevant.

@jdm
Copy link
Contributor

jdm commented Jul 15, 2013

There are various instances of code like let variant_name : &str = cx.sess.str_of(variant_info.name);. The rustc style is to put the : immediately after the name.

// For empty enums there is an early exit. Just describe it as an empty struct with the
// appropriate type name
if ty::type_is_empty(cx.tcx, enum_type) {
return create_composite_type_metadata(cx, Type::nil(), enum_name, &[], &[], &[], span);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the &s necessary here?

@michaelwoerister
Copy link
Member Author

Rebased :)

@michaelwoerister
Copy link
Member Author

Sorry about that. Compilation seems to break on mac because some new C functions from RustWrapper.cpp cannot be found by the linker. I added their names to rustllvm.def.in in michaelwoerister@b52eb4a. I hope this fixes the issue. Please re-approve.

…predict for all possible platforms and configurations.
@michaelwoerister
Copy link
Member Author

Commit michaelwoerister@a1303cc should make the test cases pass on 32 bit machines. The tests removed were no particularly good idea in the first place.

@jdm
Copy link
Contributor

jdm commented Jul 20, 2013

That makes sense.

bors added a commit that referenced this pull request Jul 20, 2013
This pull request includes various improvements:

+ Composite types (structs, tuples, boxes, etc) are now handled more cleanly by debuginfo generation. Most notably, field offsets are now extracted directly from LLVM types, as opposed to trying to reconstruct them. This leads to more stable handling of edge cases (e.g. packed structs or structs implementing drop).

+ `debuginfo.rs` in general has seen a major cleanup. This includes better formatting, more readable variable and function names, removal of dead code, and better factoring of functionality.

+ Handling of `VariantInfo` in `ty.rs` has been improved. That is, the `type VariantInfo = @VariantInfo_` typedef has been replaced with explicit uses of @VariantInfo, and the duplicated logic for creating VariantInfo instances in `ty::enum_variants()` and `typeck::check::mod::check_enum_variants()` has been unified into a single constructor function. Both function now look nicer too :)

+ Debug info generation for enum types is now mostly supported. This includes:
  + Good support for C-style enums. Both DWARF and `gdb` know how to handle them.
  + Proper description of tuple- and struct-style enum variants as unions of structs.
  + Proper handling of univariant enums without discriminator field.
  + Unfortunately `gdb` always prints all possible interpretations of a union, so debug output of enums is verbose and unintuitive. Neither `LLVM` nor `gdb` support DWARF's `DW_TAG_variant` which allows to properly describe tagged unions. Adding support for this to `LLVM` seems doable. `gdb` however is another story. In the future we might be able to use `gdb`'s Python scripting support to alleviate this problem. In agreement with @jdm this is not a high priority for now.

+ The debuginfo test suite has been extended with 14 test files including tests for packed structs (with Drop), boxed structs, boxed vecs, vec slices, c-style enums (standalone and embedded), empty enums, tuple- and struct-style enums, and various pointer types to the above.

~~What is not yet included is DI support for some enum edge-cases represented as described in `trans::adt::NullablePointer`.~~

Cheers,
Michael

PS: closes #7819,  fixes #7712
@bors bors closed this Jul 20, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants