1414#include " BPF.h"
1515#include " BPFCORE.h"
1616#include " MCTargetDesc/BPFMCTargetDesc.h"
17+ #include " llvm/BinaryFormat/Dwarf.h"
1718#include " llvm/BinaryFormat/ELF.h"
1819#include " llvm/CodeGen/AsmPrinter.h"
1920#include " llvm/CodeGen/MachineModuleInfo.h"
2324#include " llvm/MC/MCObjectFileInfo.h"
2425#include " llvm/MC/MCSectionELF.h"
2526#include " llvm/MC/MCStreamer.h"
27+ #include " llvm/Support/ErrorHandling.h"
2628#include " llvm/Support/LineIterator.h"
2729#include " llvm/Support/MemoryBuffer.h"
2830#include " llvm/Target/TargetLoweringObjectFile.h"
@@ -301,21 +303,59 @@ void BTFTypeStruct::completeType(BTFDebug &BDebug) {
301303
302304 BTFType.NameOff = BDebug.addString (STy->getName ());
303305
306+ if (STy->getTag () == dwarf::DW_TAG_variant_part) {
307+ // Variant parts might have a discriminator, which has its own memory
308+ // location, and variants, which share the memory location afterwards. LLVM
309+ // DI doesn't consider discriminator as an element and instead keeps
310+ // it as a separate reference.
311+ // To keep BTF simple, let's represent the structure as an union with
312+ // discriminator as the first element.
313+ // The offsets inside variant types are already handled correctly in the
314+ // DI.
315+ const auto *DTy = STy->getDiscriminator ();
316+ if (DTy) {
317+ struct BTF ::BTFMember Discriminator;
318+
319+ Discriminator.NameOff = BDebug.addString (DTy->getName ());
320+ Discriminator.Offset = DTy->getOffsetInBits ();
321+ const auto *BaseTy = DTy->getBaseType ();
322+ Discriminator.Type = BDebug.getTypeId (BaseTy);
323+
324+ Members.push_back (Discriminator);
325+ }
326+ }
327+
304328 // Add struct/union members.
305329 const DINodeArray Elements = STy->getElements ();
306330 for (const auto *Element : Elements) {
307331 struct BTF ::BTFMember BTFMember;
308- const auto *DDTy = cast<DIDerivedType>(Element);
309332
310- BTFMember.NameOff = BDebug.addString (DDTy->getName ());
311- if (HasBitField) {
312- uint8_t BitFieldSize = DDTy->isBitField () ? DDTy->getSizeInBits () : 0 ;
313- BTFMember.Offset = BitFieldSize << 24 | DDTy->getOffsetInBits ();
314- } else {
315- BTFMember.Offset = DDTy->getOffsetInBits ();
333+ switch (Element->getTag ()) {
334+ case dwarf::DW_TAG_member: {
335+ const auto *DDTy = cast<DIDerivedType>(Element);
336+
337+ BTFMember.NameOff = BDebug.addString (DDTy->getName ());
338+ if (HasBitField) {
339+ uint8_t BitFieldSize = DDTy->isBitField () ? DDTy->getSizeInBits () : 0 ;
340+ BTFMember.Offset = BitFieldSize << 24 | DDTy->getOffsetInBits ();
341+ } else {
342+ BTFMember.Offset = DDTy->getOffsetInBits ();
343+ }
344+ const auto *BaseTy = tryRemoveAtomicType (DDTy->getBaseType ());
345+ BTFMember.Type = BDebug.getTypeId (BaseTy);
346+ break ;
347+ }
348+ case dwarf::DW_TAG_variant_part: {
349+ const auto *DCTy = dyn_cast<DICompositeType>(Element);
350+
351+ BTFMember.NameOff = BDebug.addString (DCTy->getName ());
352+ BTFMember.Offset = DCTy->getOffsetInBits ();
353+ BTFMember.Type = BDebug.getTypeId (DCTy);
354+ break ;
355+ }
356+ default :
357+ llvm_unreachable (" Unexpected DI tag of a struct/union element" );
316358 }
317- const auto *BaseTy = tryRemoveAtomicType (DDTy->getBaseType ());
318- BTFMember.Type = BDebug.getTypeId (BaseTy);
319359 Members.push_back (BTFMember);
320360 }
321361}
@@ -672,16 +712,28 @@ void BTFDebug::visitStructType(const DICompositeType *CTy, bool IsStruct,
672712 uint32_t &TypeId) {
673713 const DINodeArray Elements = CTy->getElements ();
674714 uint32_t VLen = Elements.size ();
715+ // Variant parts might have a discriminator. LLVM DI doesn't consider it as
716+ // an element and instead keeps it as a separate reference. But we represent
717+ // it as an element in BTF.
718+ if (CTy->getTag () == dwarf::DW_TAG_variant_part) {
719+ const auto *DTy = CTy->getDiscriminator ();
720+ if (DTy) {
721+ visitTypeEntry (DTy);
722+ VLen++;
723+ }
724+ }
675725 if (VLen > BTF::MAX_VLEN)
676726 return ;
677727
678728 // Check whether we have any bitfield members or not
679729 bool HasBitField = false ;
680730 for (const auto *Element : Elements) {
681- auto E = cast<DIDerivedType>(Element);
682- if (E->isBitField ()) {
683- HasBitField = true ;
684- break ;
731+ if (Element->getTag () == dwarf::DW_TAG_member) {
732+ auto E = cast<DIDerivedType>(Element);
733+ if (E->isBitField ()) {
734+ HasBitField = true ;
735+ break ;
736+ }
685737 }
686738 }
687739
@@ -696,9 +748,22 @@ void BTFDebug::visitStructType(const DICompositeType *CTy, bool IsStruct,
696748 // Visit all struct members.
697749 int FieldNo = 0 ;
698750 for (const auto *Element : Elements) {
699- const auto Elem = cast<DIDerivedType>(Element);
700- visitTypeEntry (Elem);
701- processDeclAnnotations (Elem->getAnnotations (), TypeId, FieldNo);
751+ switch (Element->getTag ()) {
752+ case dwarf::DW_TAG_member: {
753+ const auto Elem = cast<DIDerivedType>(Element);
754+ visitTypeEntry (Elem);
755+ processDeclAnnotations (Elem->getAnnotations (), TypeId, FieldNo);
756+ break ;
757+ }
758+ case dwarf::DW_TAG_variant_part: {
759+ const auto Elem = cast<DICompositeType>(Element);
760+ visitTypeEntry (Elem);
761+ processDeclAnnotations (Elem->getAnnotations (), TypeId, FieldNo);
762+ break ;
763+ }
764+ default :
765+ llvm_unreachable (" Unexpected DI tag of a struct/union element" );
766+ }
702767 FieldNo++;
703768 }
704769}
@@ -781,16 +846,25 @@ void BTFDebug::visitFwdDeclType(const DICompositeType *CTy, bool IsUnion,
781846void BTFDebug::visitCompositeType (const DICompositeType *CTy,
782847 uint32_t &TypeId) {
783848 auto Tag = CTy->getTag ();
784- if (Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) {
849+ switch (Tag) {
850+ case dwarf::DW_TAG_structure_type:
851+ case dwarf::DW_TAG_union_type:
852+ case dwarf::DW_TAG_variant_part:
785853 // Handle forward declaration differently as it does not have members.
786854 if (CTy->isForwardDecl ())
787855 visitFwdDeclType (CTy, Tag == dwarf::DW_TAG_union_type, TypeId);
788856 else
789857 visitStructType (CTy, Tag == dwarf::DW_TAG_structure_type, TypeId);
790- } else if (Tag == dwarf::DW_TAG_array_type)
858+ break ;
859+ case dwarf::DW_TAG_array_type:
791860 visitArrayType (CTy, TypeId);
792- else if (Tag == dwarf::DW_TAG_enumeration_type)
861+ break ;
862+ case dwarf::DW_TAG_enumeration_type:
793863 visitEnumType (CTy, TypeId);
864+ break ;
865+ default :
866+ llvm_unreachable (" Unexpected DI tag of a composite type" );
867+ }
794868}
795869
796870bool BTFDebug::IsForwardDeclCandidate (const DIType *Base) {
0 commit comments