[PATCH] D42082: Add DWARF for discriminated unions
Tom Tromey via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 17 07:27:28 PST 2018
tromey added a comment.
In https://reviews.llvm.org/D42082#977666, @probinson wrote:
> As I poke around the web looking for how a Rust enum-with-value works, it appears that Rust has what in Pascal would be a tagged variant record with no invariant part and no default variant.
The Rust compiler can introduce a default variant by optimizing out other variants. The test case in this patch is a reduced version of output from a case where that happened.
Recent versions of the compiler can do this in more situations, but the "non-zero" optimization goes back quite a ways. Code looks like:
enum NonZero {
None,
Some(String),
}
Because the string cannot be zero, the two variants share space and zero is used as the discriminant for `None`.
> DW_TAG_struct_type // type entry for the enum-with-fields
> DW_TAG_variant_part // because DWARF says variant_part is owned by the struct_type
> DW_AT_discr // reference to the discriminator field
> DW_TAG_member // this is the discriminator field, where the enum value is stored
> DW_TAG_variant // wrapper for the first variant
> DW_AT_discr_value // first discriminant value
> DW_TAG_member ... // member(s) for the first variant
> DW_TAG_variant // wrapper for the second variant
> DW_AT_discr_value // second discriminant value
> DW_TAG_member ... // member(s) for the second variant
> // etc
>
>
> Is that what you are trying to produce?
Almost; in DWARF the discriminant has to be a member of the outer structure. So the output ends up a little funny. Here's one from a test case:
<3><444>: Abbrev Number: 6 (DW_TAG_structure_type)
<445> DW_AT_name : (indirect string, offset: 0xa7f7f): Option<&u8>
<449> DW_AT_byte_size : 8
<44a> DW_AT_alignment : 8
<4><44b>: Abbrev Number: 9 (DW_TAG_member)
<44c> DW_AT_type : <0x509>
<450> DW_AT_alignment : 8
<451> DW_AT_data_member_location: 0
<452> DW_AT_artificial : 1
<4><452>: Abbrev Number: 10 (DW_TAG_variant_part)
<453> DW_AT_discr : <0x44b>
<5><457>: Abbrev Number: 11 (DW_TAG_variant)
<458> DW_AT_discr_value : 0
<6><459>: Abbrev Number: 12 (DW_TAG_member)
<45a> DW_AT_type : <0x46b>
<45e> DW_AT_alignment : 8
<45f> DW_AT_data_member_location: 0
<6><460>: Abbrev Number: 0
<5><461>: Abbrev Number: 13 (DW_TAG_variant)
<6><462>: Abbrev Number: 12 (DW_TAG_member)
<463> DW_AT_type : <0x472>
<467> DW_AT_alignment : 8
<468> DW_AT_data_member_location: 0
Here the discriminant member is DIE 0x44b; the rest is as you wrote.
DWARF allows some other constructs, like extra members in the outer struct, and lists of discriminant values. However, Rust doesn't need this, so I did not implement them. This is also why the interface talks about "discriminated unions" and not variants -- it is more limited.
Another approach I've considered is to just not use the DWARF variant record support at all and instead introduce a new `DW_TAG_Rust_enum`. This would be simpler in some ways, but I figured I'd first try to use what DWARF provides.
Repository:
rL LLVM
https://reviews.llvm.org/D42082
More information about the llvm-commits
mailing list