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

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 14 10:21:41 PDT 2025


================
@@ -301,21 +303,61 @@ void BTFTypeStruct::completeType(BTFDebug &BDebug) {
 
   BTFType.NameOff = BDebug.addString(STy->getName());
 
+  uint64_t InitialOffset = 0;
+  if (STy->getTag() == dwarf::DW_TAG_variant_part) {
+    // Variant parts have a discriminator, which has its own memory location at
+    // the beginning, and variants, which share the memory location afterwards.
+    // LLVM DI doesn't consider discriminator as an element and instead keeps
+    // it as a separate reference.
+    // To keep BTF simple, let's represent the structure as an union with
+    // discriminator as the first element and apply offsets to the other
+    // elements.
+    struct BTF::BTFMember Discriminator;
+    const auto *DDTy = STy->getDiscriminator();
+
+    InitialOffset += DDTy->getOffsetInBits() + DDTy->getSizeInBits();
----------------
eddyz87 wrote:

> I suspect BTF relocations to break if we don't match the offsets with the actual memory layout. The relocations of types done by BPF program loaders (libbpf or aya) have nothing to do with DWARF. They are done purely based on two BTF informations - the one tied to program and the one coming from the kernel.

Direct translation of current DWARF representation gives same correct offsets:

```c
union Adt {
  u32 discriminant;
  struct First First;
  struct Second Second;
};
struct First {
  u32 :32;
  u32 a;
  u32 b;
};
...
```

Given a pointer to `First` a relocation accessing field `First::b` will be a string `0:2`. In corresponding BTF this relocation will point to 3rd field of structure `First`, namely `b`, and use its offset, namely 8 bytes.

> Getting to the point how to solve it - in this thread https://github.com/llvm/llvm-project/pull/155783#discussion_r2396907929 @yonghong-song agrees with the idea of representing the variant part as a struct with a discriminator and an union.

To do that you have to:
- lookup offset and size of the discriminator field;
- recursively traverse types used for variant parts, looking for a field that ends up at the discriminator offset and has discriminator size (nothing guarantees that discriminator field would be first member of the variant part type, or that it would be at nesting level 1);
- delete this field (if it exists)
- adjust offsets of all fields following field found on a previous step.

Note that types referenced from variant part might be used elsewhere, so when applying transformation you need to either guarantee consistent location for the discriminator field, or clone the type.

This procedure is both *complicated* and *error prone*.

Hence, I think that BTF backend should be dumb, and encode DWARF as-is. If you'd like ADTs to look better in DWARF, then rustc frontend should be adjusted to produce DWARF of different shape.

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


More information about the llvm-commits mailing list