================
@@ -301,21 +303,62 @@ 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();
+
+ Discriminator.NameOff = BDebug.addString(DDTy->getName());
+ Discriminator.Offset = DDTy->getOffsetInBits();
+ const auto *BaseTy = tryRemoveAtomicType(DDTy->getBaseType());
+ Discriminator.Type = BDebug.getTypeId(BaseTy);
+
+ Members.push_back(Discriminator);
+ }
+
// Add struct/union members.
const DINodeArray Elements = STy->getElements();
for (const auto *Element : Elements) {
struct BTF::BTFMember BTFMember;
- const auto *DDTy = cast<DIDerivedType>(Element);
- BTFMember.NameOff = BDebug.addString(DDTy->getName());
- if (HasBitField) {
- uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0;
- BTFMember.Offset = BitFieldSize << 24 | DDTy->getOffsetInBits();
- } else {
- BTFMember.Offset = DDTy->getOffsetInBits();
+ switch (Element->getTag()) {
+ case dwarf::DW_TAG_member: {
+ const auto *DDTy = cast<DIDerivedType>(Element);
+
+ BTFMember.NameOff = BDebug.addString(DDTy->getName());
+ uint64_t Offset;
+ if (HasBitField) {
+ uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0;
+ Offset = BitFieldSize << 24 | DDTy->getOffsetInBits();
+ } else {
+ Offset = DDTy->getOffsetInBits();
+ }
+ BTFMember.Offset = InitialOffset + Offset;
+ const auto *BaseTy = tryRemoveAtomicType(DDTy->getBaseType());
+ BTFMember.Type = BDebug.getTypeId(BaseTy);
+ break;
+ }
+ case dwarf::DW_TAG_variant_part: {
+ const auto *DCTy = dyn_cast<DICompositeType>(Element);
+
+ BTFMember.NameOff = BDebug.addString(DCTy->getName());
+ BTFMember.Offset = InitialOffset + DCTy->getOffsetInBits();
+ const auto *DTy = cast<DIType>(DCTy);
+ BTFMember.Type = BDebug.getTypeId(DTy);
----------------
yonghong-song wrote:
DTy is not needed. Directly using BDebug.getTypeId(DCTy).
https://github.com/llvm/llvm-project/pull/155783