[llvm] [BPF] Support for `DW_TAG_variant_part` in BTF generation (PR #155783)

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 12 10:56:31 PDT 2025


https://github.com/eddyz87 requested changes to this pull request.

I think this change is fine, but just realized an unfortunate quirk regarding discriminator handling. Consider the following example:

```rust
pub enum Adt {
    First { a: u32, b: i32 },
    Second(u32, i32),
}

pub static X: Adt = Adt::First{a:0, b:0};
```

With corresponding IR:

```
!7 = !DICompositeType(tag: DW_TAG_variant_part, scope: !4, file: !5, size: 96, align: 32, elements: !8, ..., discriminator: !22)
  !8 = !{!9, !17}
  !9 = !DIDerivedType(tag: DW_TAG_member, name: "First", scope: !7, file: !5, baseType: !10, size: 96, align: 32, extraData: i32 0)
  !10 = !DICompositeType(tag: DW_TAG_structure_type, name: "First", ..., elements: !11, ...)
    !11 = !{!12, !14}
    !12 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !10, file: !5, baseType: !13, size: 32, align: 32, offset: 32, flags: DIFlagPublic)
      ...

  !22 = !DIDerivedType(tag: DW_TAG_member, scope: !4, file: !5, baseType: !13, size: 32, align: 32, flags: DIFlagArtificial)
```

And corresponding DWARF:

```c
0x0000003d:     DW_TAG_structure_type
                  DW_AT_name    ("Adt")
                  DW_AT_byte_size       (0x0c)
                  DW_AT_accessibility   (DW_ACCESS_public)
                  DW_AT_alignment       (4)

0x00000045:       DW_TAG_variant_part
                    DW_AT_discr (0x0000004a)

0x0000004a:         DW_TAG_member
                      DW_AT_type        (0x000000b2 "u32")
                      DW_AT_alignment   (4)
                      DW_AT_data_member_location        (0x00)
                      DW_AT_artificial  (true)

0x00000051:         DW_TAG_variant
                      DW_AT_discr_value (0x00)

0x00000053:           DW_TAG_member
                        DW_AT_name      ("First")
                        DW_AT_type      (0x0000006e "test_debug_info::Adt::First")
                        DW_AT_alignment (4)
                        DW_AT_data_member_location      (0x00)

0x0000005e:           NULL

0x0000005f:         DW_TAG_variant
                      DW_AT_discr_value (0x01)

0x00000061:           DW_TAG_member
                        DW_AT_name      ("Second")
                        DW_AT_type      (0x0000008f "test_debug_info::Adt::Second")
                        DW_AT_alignment (4)
                        DW_AT_data_member_location      (0x00)

0x0000006c:           NULL

0x0000006d:         NULL

0x0000006e:       DW_TAG_structure_type
                    DW_AT_name  ("First")
                    DW_AT_byte_size     (0x0c)
                    DW_AT_accessibility (DW_ACCESS_public)
                    DW_AT_alignment     (4)

0x00000076:         DW_TAG_member
                      DW_AT_name        ("a")
                      DW_AT_type        (0x000000b2 "u32")
                      DW_AT_alignment   (4)
                      DW_AT_data_member_location        (0x04)
                      DW_AT_accessibility       (DW_ACCESS_public)

0x00000082:         DW_TAG_member
                      DW_AT_name        ("b")
                      DW_AT_type        (0x000000b9 "i32")
                      DW_AT_alignment   (4)
                      DW_AT_data_member_location        (0x08)
                      DW_AT_accessibility       (DW_ACCESS_public)

0x0000008e:         NULL
```

Note how offsets for `a` and `b` are shifted by 4 bytes and variant part itself has three members, beside First and Second there is also an anonymous member `0x0000004a`, representing a descriminator at offset 0.

Meaning that in BTF union representing the variant part has to have three members, not two. Which is a bit inconvenient, as it is not a part of "elements", but instead a separate "discriminator" reference.

Wdyt?

https://github.com/llvm/llvm-project/pull/155783


More information about the llvm-commits mailing list