32#define HANDLE_BTF_KIND(ID, NAME) "BTF_KIND_" #NAME,
48 : DTy(DTy), NeedsFixup(NeedsFixup),
Name(DTy->
getName()) {
50 case dwarf::DW_TAG_pointer_type:
51 Kind = BTF::BTF_KIND_PTR;
53 case dwarf::DW_TAG_const_type:
54 Kind = BTF::BTF_KIND_CONST;
56 case dwarf::DW_TAG_volatile_type:
57 Kind = BTF::BTF_KIND_VOLATILE;
59 case dwarf::DW_TAG_typedef:
60 Kind = BTF::BTF_KIND_TYPEDEF;
62 case dwarf::DW_TAG_restrict_type:
63 Kind = BTF::BTF_KIND_RESTRICT;
75 Kind = BTF::BTF_KIND_PTR;
87 if (NeedsFixup || !DTy)
91 const DIType *ResolvedType = DTy->getBaseType();
93 assert((
Kind == BTF::BTF_KIND_PTR ||
Kind == BTF::BTF_KIND_CONST ||
94 Kind == BTF::BTF_KIND_VOLATILE) &&
95 "Invalid null basetype");
110 Kind = BTF::BTF_KIND_FWD;
131 case dwarf::DW_ATE_boolean:
134 case dwarf::DW_ATE_signed:
135 case dwarf::DW_ATE_signed_char:
138 case dwarf::DW_ATE_unsigned:
139 case dwarf::DW_ATE_unsigned_char:
146 Kind = BTF::BTF_KIND_INT;
149 IntVal = (BTFEncoding << 24) | OffsetInBits << 16 | SizeInBits;
167 bool IsSigned) : ETy(ETy) {
168 Kind = BTF::BTF_KIND_ENUM;
181 for (
const auto Element : Elements) {
182 const auto *Enum = cast<DIEnumerator>(Element);
188 if (Enum->isUnsigned())
189 Value =
static_cast<uint32_t>(Enum->getValue().getZExtValue());
191 Value =
static_cast<uint32_t>(Enum->getValue().getSExtValue());
193 EnumValues.push_back(BTFEnum);
199 for (
const auto &Enum : EnumValues) {
206 bool IsSigned) : ETy(ETy) {
207 Kind = BTF::BTF_KIND_ENUM64;
220 for (
const auto Element : Elements) {
221 const auto *Enum = cast<DIEnumerator>(Element);
226 if (Enum->isUnsigned())
227 Value =
static_cast<uint64_t>(Enum->getValue().getZExtValue());
229 Value =
static_cast<uint64_t>(Enum->getValue().getSExtValue());
232 EnumValues.push_back(BTFEnum);
238 for (
const auto &Enum : EnumValues) {
248 Kind = BTF::BTF_KIND_ARRAY;
254 ArrayInfo.
Nelems = NumElems;
280 : STy(STy), HasBitField(HasBitField) {
281 Kind = IsStruct ? BTF::BTF_KIND_STRUCT : BTF::BTF_KIND_UNION;
295 for (
const auto *Element : Elements) {
297 const auto *DDTy = cast<DIDerivedType>(Element);
301 uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0;
302 BTFMember.
Offset = BitFieldSize << 24 | DDTy->getOffsetInBits();
304 BTFMember.
Offset = DDTy->getOffsetInBits();
306 const auto *
BaseTy = DDTy->getBaseType();
308 Members.push_back(BTFMember);
314 for (
const auto &Member : Members) {
331 const std::unordered_map<uint32_t, StringRef> &FuncArgNames)
332 : STy(STy), FuncArgNames(FuncArgNames) {
333 Kind = BTF::BTF_KIND_FUNC_PROTO;
343 auto RetType = Elements[0];
349 for (
unsigned I = 1,
N = Elements.size();
I <
N; ++
I) {
351 auto Element = Elements[
I];
353 Param.NameOff = BDebug.
addString(FuncArgNames[
I]);
359 Parameters.push_back(Param);
365 for (
const auto &Param : Parameters) {
374 Kind = BTF::BTF_KIND_FUNC;
391 Kind = BTF::BTF_KIND_VAR;
407 : Asm(AsmPrt),
Name(SecName) {
408 Kind = BTF::BTF_KIND_DATASEC;
421 for (
const auto &V : Vars) {
430 Kind = BTF::BTF_KIND_FLOAT;
446 Kind = BTF::BTF_KIND_DECL_TAG;
466 : DTy(nullptr),
Tag(
Tag) {
467 Kind = BTF::BTF_KIND_TYPE_TAG;
474 Kind = BTF::BTF_KIND_TYPE_TAG;
484 const DIType *ResolvedType = DTy->getBaseType();
494 for (
auto &OffsetM : OffsetToIdMap) {
495 if (Table[OffsetM.second] == S)
496 return OffsetM.first;
500 OffsetToIdMap[
Offset] = Table.size();
501 Table.push_back(std::string(S));
508 LineInfoGenerated(
false), SecNameOff(0), ArrayIndexTypeId(0),
509 MapDefNotCollected(
true) {
513uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry,
515 TypeEntry->setId(TypeEntries.size() + 1);
518 TypeEntries.push_back(std::move(TypeEntry));
522uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry) {
523 TypeEntry->setId(TypeEntries.size() + 1);
525 TypeEntries.push_back(std::move(TypeEntry));
532 std::unique_ptr<BTFTypeBase> TypeEntry;
534 case dwarf::DW_ATE_boolean:
535 case dwarf::DW_ATE_signed:
536 case dwarf::DW_ATE_signed_char:
537 case dwarf::DW_ATE_unsigned:
538 case dwarf::DW_ATE_unsigned_char:
541 TypeEntry = std::make_unique<BTFTypeInt>(
544 case dwarf::DW_ATE_float:
552 TypeId = addType(std::move(TypeEntry), BTy);
556void BTFDebug::visitSubroutineType(
558 const std::unordered_map<uint32_t, StringRef> &FuncArgNames,
569 auto TypeEntry = std::make_unique<BTFTypeFuncProto>(STy, VLen, FuncArgNames);
571 TypeId = addType(std::move(TypeEntry));
573 TypeId = addType(std::move(TypeEntry), STy);
576 for (
const auto Element : Elements) {
577 visitTypeEntry(Element);
581void BTFDebug::processDeclAnnotations(DINodeArray
Annotations,
588 const MDNode *MD = cast<MDNode>(Annotation);
590 if (!
Name->getString().equals(
"btf_decl_tag"))
594 auto TypeEntry = std::make_unique<BTFTypeDeclTag>(BaseTypeId, ComponentIdx,
596 addType(std::move(TypeEntry));
601 uint32_t ProtoTypeId, uint8_t Scope) {
603 std::make_unique<BTFTypeFunc>(SP->
getName(), ProtoTypeId, Scope);
607 for (
const DINode *DN : SP->getRetainedNodes()) {
608 if (
const auto *DV = dyn_cast<DILocalVariable>(DN)) {
611 processDeclAnnotations(DV->getAnnotations(),
FuncId,
Arg - 1);
614 processDeclAnnotations(SP->getAnnotations(),
FuncId, -1);
620int BTFDebug::genBTFTypeTags(
const DIDerivedType *DTy,
int BaseTypeId) {
622 DINodeArray Annots = DTy->getAnnotations();
629 if (!
Name->getString().equals(
"btf_type_tag"))
635 if (MDStrs.
size() == 0)
643 std::unique_ptr<BTFTypeTypeTag> TypeEntry;
646 std::make_unique<BTFTypeTypeTag>(BaseTypeId, MDStrs[0]->getString());
648 TypeEntry = std::make_unique<BTFTypeTypeTag>(DTy, MDStrs[0]->getString());
649 TmpTypeId = addType(std::move(TypeEntry));
651 for (
unsigned I = 1;
I < MDStrs.
size();
I++) {
653 TypeEntry = std::make_unique<BTFTypeTypeTag>(TmpTypeId,
Value->getString());
654 TmpTypeId = addType(std::move(TypeEntry));
660void BTFDebug::visitStructType(
const DICompositeType *CTy,
bool IsStruct,
668 bool HasBitField =
false;
669 for (
const auto *Element : Elements) {
670 auto E = cast<DIDerivedType>(Element);
671 if (
E->isBitField()) {
678 std::make_unique<BTFTypeStruct>(CTy, IsStruct, HasBitField, VLen);
679 StructTypes.push_back(TypeEntry.get());
680 TypeId = addType(std::move(TypeEntry), CTy);
687 for (
const auto *Element : Elements) {
688 const auto Elem = cast<DIDerivedType>(Element);
689 visitTypeEntry(Elem);
690 processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo);
699 visitTypeEntry(ElemType, ElemTypeId,
false,
false);
704 if (
auto *Element = dyn_cast_or_null<DINode>(Elements[
I]))
705 if (Element->getTag() == dwarf::DW_TAG_subrange_type) {
706 const DISubrange *SR = cast<DISubrange>(Element);
713 std::make_unique<BTFTypeArray>(ElemTypeId,
714 Count >= 0 ? Count : 0);
716 ElemTypeId = addType(std::move(TypeEntry), CTy);
718 ElemTypeId = addType(std::move(TypeEntry));
727 if (!ArrayIndexTypeId) {
728 auto TypeEntry = std::make_unique<BTFTypeInt>(dwarf::DW_ATE_unsigned, 32,
729 0,
"__ARRAY_SIZE_TYPE__");
730 ArrayIndexTypeId = addType(std::move(TypeEntry));
740 bool IsSigned =
false;
741 unsigned NumBits = 32;
745 const auto *BTy = cast<DIBasicType>(CTy->
getBaseType());
746 IsSigned = BTy->
getEncoding() == dwarf::DW_ATE_signed ||
752 auto TypeEntry = std::make_unique<BTFTypeEnum>(CTy, VLen, IsSigned);
753 TypeId = addType(std::move(TypeEntry), CTy);
756 auto TypeEntry = std::make_unique<BTFTypeEnum64>(CTy, VLen, IsSigned);
757 TypeId = addType(std::move(TypeEntry), CTy);
763void BTFDebug::visitFwdDeclType(
const DICompositeType *CTy,
bool IsUnion,
765 auto TypeEntry = std::make_unique<BTFTypeFwd>(CTy->
getName(), IsUnion);
766 TypeId = addType(std::move(TypeEntry), CTy);
773 if (
Tag == dwarf::DW_TAG_structure_type ||
Tag == dwarf::DW_TAG_union_type) {
776 visitFwdDeclType(CTy,
Tag == dwarf::DW_TAG_union_type, TypeId);
778 visitStructType(CTy,
Tag == dwarf::DW_TAG_structure_type, TypeId);
779 }
else if (
Tag == dwarf::DW_TAG_array_type)
780 visitArrayType(CTy, TypeId);
781 else if (
Tag == dwarf::DW_TAG_enumeration_type)
782 visitEnumType(CTy, TypeId);
787 bool CheckPointer,
bool SeenPointer) {
792 if (CheckPointer && !SeenPointer) {
793 SeenPointer =
Tag == dwarf::DW_TAG_pointer_type;
796 if (CheckPointer && SeenPointer) {
799 if (
const auto *CTy = dyn_cast<DICompositeType>(
Base)) {
800 auto CTag = CTy->
getTag();
801 if ((CTag == dwarf::DW_TAG_structure_type ||
802 CTag == dwarf::DW_TAG_union_type) &&
807 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
true);
808 auto &
Fixup = FixupDerivedTypes[CTy];
809 Fixup.push_back(std::make_pair(DTy, TypeEntry.get()));
810 TypeId = addType(std::move(TypeEntry), DTy);
817 if (
Tag == dwarf::DW_TAG_pointer_type) {
818 int TmpTypeId = genBTFTypeTags(DTy, -1);
819 if (TmpTypeId >= 0) {
821 std::make_unique<BTFTypeDerived>(TmpTypeId,
Tag, DTy->
getName());
822 TypeId = addType(std::move(TypeDEntry), DTy);
824 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
false);
825 TypeId = addType(std::move(TypeEntry), DTy);
827 }
else if (
Tag == dwarf::DW_TAG_typedef ||
Tag == dwarf::DW_TAG_const_type ||
828 Tag == dwarf::DW_TAG_volatile_type ||
829 Tag == dwarf::DW_TAG_restrict_type) {
830 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
false);
831 TypeId = addType(std::move(TypeEntry), DTy);
832 if (
Tag == dwarf::DW_TAG_typedef)
833 processDeclAnnotations(DTy->getAnnotations(), TypeId, -1);
834 }
else if (
Tag != dwarf::DW_TAG_member) {
841 if (
Tag == dwarf::DW_TAG_member)
842 visitTypeEntry(DTy->getBaseType(), TempTypeId,
true,
false);
844 visitTypeEntry(DTy->getBaseType(), TempTypeId, CheckPointer, SeenPointer);
848 bool CheckPointer,
bool SeenPointer) {
849 if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
850 TypeId = DIToIdMap[Ty];
881 if (Ty && (!CheckPointer || !SeenPointer)) {
882 if (
const auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
888 if (DIToIdMap.find(
BaseTy) != DIToIdMap.end()) {
889 DTy = dyn_cast<DIDerivedType>(
BaseTy);
892 visitTypeEntry(
BaseTy, TmpTypeId, CheckPointer, SeenPointer);
902 if (
const auto *BTy = dyn_cast<DIBasicType>(Ty))
903 visitBasicType(BTy, TypeId);
904 else if (
const auto *STy = dyn_cast<DISubroutineType>(Ty))
905 visitSubroutineType(STy,
false, std::unordered_map<uint32_t, StringRef>(),
907 else if (
const auto *CTy = dyn_cast<DICompositeType>(Ty))
908 visitCompositeType(CTy, TypeId);
909 else if (
const auto *DTy = dyn_cast<DIDerivedType>(Ty))
910 visitDerivedType(DTy, TypeId, CheckPointer, SeenPointer);
915void BTFDebug::visitTypeEntry(
const DIType *Ty) {
917 visitTypeEntry(Ty, TypeId,
false,
false);
920void BTFDebug::visitMapDefType(
const DIType *Ty,
uint32_t &TypeId) {
921 if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
922 TypeId = DIToIdMap[Ty];
927 const DIType *OrigTy = Ty;
928 while (
auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
930 if (
Tag != dwarf::DW_TAG_typedef &&
Tag != dwarf::DW_TAG_const_type &&
931 Tag != dwarf::DW_TAG_volatile_type &&
932 Tag != dwarf::DW_TAG_restrict_type)
934 Ty = DTy->getBaseType();
937 const auto *CTy = dyn_cast<DICompositeType>(Ty);
947 for (
const auto *Element : Elements) {
948 const auto *MemberType = cast<DIDerivedType>(Element);
949 visitTypeEntry(MemberType->getBaseType());
953 visitTypeEntry(OrigTy, TypeId,
false,
false);
957std::string BTFDebug::populateFileContent(
const DISubprogram *SP) {
959 std::string FileName;
961 if (!
File->getFilename().startswith(
"/") &&
File->getDirectory().size())
962 FileName =
File->getDirectory().str() +
"/" +
File->getFilename().str();
964 FileName = std::string(
File->getFilename());
967 if (FileContent.
find(FileName) != FileContent.
end())
970 std::vector<std::string>
Content;
974 std::unique_ptr<MemoryBuffer> Buf;
978 else if (
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
980 Buf = std::move(*BufOrErr);
985 FileContent[FileName] =
Content;
991 std::string FileName = populateFileContent(SP);
997 if (Line < FileContent[FileName].
size())
1003 LineInfoTable[SecNameOff].push_back(LineInfo);
1006void BTFDebug::emitCommonHeader() {
1013void BTFDebug::emitBTFSection() {
1015 if (!TypeEntries.size() && StringTable.
getSize() == 1)
1028 for (
const auto &TypeEntry : TypeEntries)
1029 TypeLen += TypeEntry->getSize();
1030 StrLen = StringTable.
getSize();
1038 for (
const auto &TypeEntry : TypeEntries)
1039 TypeEntry->emitType(OS);
1043 for (
const auto &S : StringTable.
getTable()) {
1044 OS.
AddComment(
"string offset=" + std::to_string(StringOffset));
1047 StringOffset += S.size() + 1;
1051void BTFDebug::emitBTFExtSection() {
1054 if (!FuncInfoTable.size() && !LineInfoTable.size() &&
1055 !FieldRelocTable.size())
1071 for (
const auto &FuncSec : FuncInfoTable) {
1075 for (
const auto &LineSec : LineInfoTable) {
1079 for (
const auto &FieldRelocSec : FieldRelocTable) {
1097 for (
const auto &FuncSec : FuncInfoTable) {
1098 OS.
AddComment(
"FuncInfo section string offset=" +
1099 std::to_string(FuncSec.first));
1102 for (
const auto &FuncInfo : FuncSec.second) {
1111 for (
const auto &LineSec : LineInfoTable) {
1112 OS.
AddComment(
"LineInfo section string offset=" +
1113 std::to_string(LineSec.first));
1116 for (
const auto &LineInfo : LineSec.second) {
1127 if (FieldRelocLen) {
1130 for (
const auto &FieldRelocSec : FieldRelocTable) {
1131 OS.
AddComment(
"Field reloc section string offset=" +
1132 std::to_string(FieldRelocSec.first));
1134 OS.
emitInt32(FieldRelocSec.second.size());
1135 for (
const auto &FieldRelocInfo : FieldRelocSec.second) {
1138 OS.
emitInt32(FieldRelocInfo.OffsetNameOff);
1147 auto *Unit = SP->getUnit();
1150 SkipInstruction =
true;
1153 SkipInstruction =
false;
1174 if (MapDefNotCollected) {
1175 processGlobals(
true);
1176 MapDefNotCollected =
false;
1182 std::unordered_map<uint32_t, StringRef> FuncArgNames;
1183 for (
const DINode *DN : SP->getRetainedNodes()) {
1184 if (
const auto *DV = dyn_cast<DILocalVariable>(DN)) {
1188 visitTypeEntry(DV->getType());
1189 FuncArgNames[
Arg] = DV->getName();
1196 visitSubroutineType(SP->getType(),
true, FuncArgNames, ProtoTypeId);
1200 uint32_t FuncTypeId = processDISubprogram(SP, ProtoTypeId, Scope);
1202 for (
const auto &TypeEntry : TypeEntries)
1203 TypeEntry->completeType(*
this);
1208 FuncInfo.
Label = FuncLabel;
1209 FuncInfo.
TypeId = FuncTypeId;
1212 const MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section);
1213 assert(SectionELF &&
"Null section for Function Label");
1218 FuncInfoTable[SecNameOff].push_back(FuncInfo);
1222 SkipInstruction =
false;
1223 LineInfoGenerated =
false;
1229unsigned BTFDebug::populateType(
const DIType *Ty) {
1231 visitTypeEntry(Ty, Id,
false,
false);
1232 for (
const auto &TypeEntry : TypeEntries)
1233 TypeEntry->completeType(*
this);
1238void BTFDebug::generatePatchImmReloc(
const MCSymbol *ORSym,
uint32_t RootId,
1241 FieldReloc.
Label = ORSym;
1242 FieldReloc.
TypeID = RootId;
1248 size_t SecondColon = AccessPattern.
find_first_of(
':', FirstColon + 1);
1251 SecondColon - FirstColon);
1253 FirstDollar - SecondColon);
1256 FieldReloc.
RelocKind = std::stoull(std::string(RelocKindStr));
1257 PatchImms[GVar] = std::make_pair(std::stoll(std::string(PatchImmStr)),
1262 FieldReloc.
RelocKind = std::stoull(std::string(RelocStr));
1263 PatchImms[GVar] = std::make_pair(RootId, FieldReloc.
RelocKind);
1265 FieldRelocTable[SecNameOff].push_back(FieldReloc);
1272 auto *GVar = dyn_cast<GlobalVariable>(GVal);
1275 processFuncPrototypes(dyn_cast<Function>(GVal));
1287 uint32_t RootId = populateType(dyn_cast<DIType>(MDN));
1288 generatePatchImmReloc(ORSym, RootId, GVar,
1296 if (SkipInstruction ||
MI->isMetaInstruction() ||
1300 if (
MI->isInlineAsm()) {
1302 unsigned NumDefs = 0;
1303 for (;
MI->getOperand(NumDefs).
isReg() &&
MI->getOperand(NumDefs).isDef();
1308 const char *AsmStr =
MI->getOperand(NumDefs).getSymbolName();
1313 if (
MI->getOpcode() == BPF::LD_imm64) {
1328 processGlobalValue(
MI->getOperand(1));
1329 }
else if (
MI->getOpcode() == BPF::CORE_MEM ||
1330 MI->getOpcode() == BPF::CORE_ALU32_MEM ||
1331 MI->getOpcode() == BPF::CORE_SHIFT) {
1333 processGlobalValue(
MI->getOperand(3));
1334 }
else if (
MI->getOpcode() == BPF::JAL) {
1338 processFuncPrototypes(dyn_cast<Function>(MO.
getGlobal()));
1351 if (LineInfoGenerated ==
false) {
1352 auto *S =
MI->getMF()->getFunction().getSubprogram();
1354 constructLineInfo(S, FuncLabel, S->getLine(), 0);
1355 LineInfoGenerated =
true;
1366 auto SP =
DL->getScope()->getSubprogram();
1367 constructLineInfo(SP, LineSym,
DL.getLine(),
DL.getCol());
1369 LineInfoGenerated =
true;
1373void BTFDebug::processGlobals(
bool ProcessingMapDef) {
1379 std::optional<SectionKind> GVKind;
1381 if (!
Global.isDeclarationForLinker())
1384 if (
Global.isDeclarationForLinker())
1385 SecName =
Global.hasSection() ?
Global.getSection() :
"";
1386 else if (GVKind->isCommon())
1394 if (ProcessingMapDef != SecName.
startswith(
".maps"))
1400 if (SecName ==
".rodata" &&
Global.hasPrivateLinkage() &&
1401 DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1403 if (!GVKind->isMergeableCString() && !GVKind->isMergeableConst()) {
1404 DataSecEntries[std::string(SecName)] =
1405 std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1410 Global.getDebugInfo(GVs);
1413 if (GVs.
size() == 0)
1418 for (
auto *GVE : GVs) {
1421 visitMapDefType(
DIGlobal->getType(), GVTypeId);
1423 visitTypeEntry(
DIGlobal->getType(), GVTypeId,
false,
false);
1445 }
else if (
Global.hasInitializer()) {
1452 std::make_unique<BTFKindVar>(
Global.getName(), GVTypeId, GVarInfo);
1453 uint32_t VarId = addType(std::move(VarEntry));
1455 processDeclAnnotations(
DIGlobal->getAnnotations(), VarId, -1);
1458 if (SecName.
empty())
1462 if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1463 DataSecEntries[std::string(SecName)] =
1464 std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1471 DataSecEntries[std::string(SecName)]->addDataSecEntry(VarId,
1478 if (
MI->getOpcode() == BPF::LD_imm64) {
1482 auto *GVar = dyn_cast<GlobalVariable>(GVal);
1489 Imm = PatchImms[GVar].first;
1490 Reloc = PatchImms[GVar].second;
1507 }
else if (
MI->getOpcode() == BPF::CORE_MEM ||
1508 MI->getOpcode() == BPF::CORE_ALU32_MEM ||
1509 MI->getOpcode() == BPF::CORE_SHIFT) {
1513 auto *GVar = dyn_cast<GlobalVariable>(GVal);
1515 uint32_t Imm = PatchImms[GVar].first;
1517 if (
MI->getOperand(0).isImm())
1530void BTFDebug::processFuncPrototypes(
const Function *
F) {
1535 if (!SP || SP->isDefinition())
1539 if (!ProtoFunctions.insert(
F).second)
1543 const std::unordered_map<uint32_t, StringRef> FuncArgNames;
1544 visitSubroutineType(SP->getType(),
false, FuncArgNames, ProtoTypeId);
1547 if (
F->hasSection()) {
1550 if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1551 DataSecEntries[std::string(SecName)] =
1552 std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1556 DataSecEntries[std::string(SecName)]->addDataSecEntry(
FuncId,
1563 if (MapDefNotCollected) {
1564 processGlobals(
true);
1565 MapDefNotCollected =
false;
1569 processGlobals(
false);
1571 for (
auto &DataSec : DataSecEntries)
1572 addType(std::move(DataSec.second));
1575 for (
auto &
Fixup : FixupDerivedTypes) {
1578 bool IsUnion = CTy->
getTag() == dwarf::DW_TAG_union_type;
1589 if (StructTypeId == 0) {
1590 auto FwdTypeEntry = std::make_unique<BTFTypeFwd>(TypeName, IsUnion);
1591 StructTypeId = addType(std::move(FwdTypeEntry));
1594 for (
auto &TypeInfo :
Fixup.second) {
1598 int TmpTypeId = genBTFTypeTags(DTy, StructTypeId);
1607 for (
const auto &TypeEntry : TypeEntries)
1608 TypeEntry->completeType(*
this);
1612 emitBTFExtSection();
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
static const char * BTFKindStr[]
This file contains support for writing BTF debug info.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
static bool isReg(const MCInst &MI, unsigned OpNo)
return ToRemove size() > 0
PowerPC TLS Dynamic Call Fixup
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Annotations lets you mark points and ranges inside source code, for tests:
This class is intended to be used as a driving class for all asm writers.
MCSymbol * getSymbol(const GlobalValue *GV) const
TargetMachine & TM
Target machine description.
MCSymbol * getFunctionBegin() const
void emitLabelReference(const MCSymbol *Label, unsigned Size, bool IsSectionRelative=false) const
Emit something like ".long Label" where the size in bytes of the directive is specified by Size and L...
static constexpr StringRef TypeIdAttr
The attribute attached to globals representing a type id.
static constexpr StringRef AmaAttr
The attribute attached to globals representing a field access.
Collect and emit BTF information.
void endFunctionImpl(const MachineFunction *MF) override
Post process after all instructions in this function are processed.
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
bool InstLower(const MachineInstr *MI, MCInst &OutMI)
Emit proper patchable instructions.
size_t addString(StringRef S)
Add string to the string table.
uint32_t getArrayIndexTypeId()
Get the special array index type id.
uint32_t getTypeId(const DIType *Ty)
Get the type id for a particular DIType.
void endModule() override
Complete all the types and emit the BTF sections.
void beginFunctionImpl(const MachineFunction *MF) override
Gather pre-function debug information.
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFKindDataSec(AsmPrinter *AsmPrt, std::string SecName)
BTFKindVar(StringRef VarName, uint32_t TypeId, uint32_t VarInfo)
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
uint32_t addString(StringRef S)
Add a string to the string table and returns its offset in the table.
std::vector< std::string > & getTable()
BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems)
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Represent a BTF array.
struct BTF::CommonType BTFType
virtual void emitType(MCStreamer &OS)
Emit types for this BTF type entry.
uint32_t roundupToBytes(uint32_t NumBits)
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeDeclTag(uint32_t BaseTypeId, int ComponentId, StringRef Tag)
Handle several derived types include pointer, const, volatile, typedef and restrict.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void setPointeeType(uint32_t PointeeType)
BTFTypeDerived(const DIDerivedType *Ty, unsigned Tag, bool NeedsFixup)
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFTypeEnum64(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned)
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned)
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFTypeFloat(uint32_t SizeInBits, StringRef TypeName)
BTFTypeFuncProto(const DISubroutineType *STy, uint32_t NumParams, const std::unordered_map< uint32_t, StringRef > &FuncArgNames)
The Func kind represents both subprogram and pointee of function pointers.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId, uint32_t Scope)
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeFwd(StringRef Name, bool IsUnion)
Represent a struct/union forward declaration.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeInt(uint32_t Encoding, uint32_t SizeInBits, uint32_t OffsetInBits, StringRef TypeName)
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField, uint32_t NumMembers)
Represent either a struct or a union.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFTypeTypeTag(uint32_t NextTypeId, StringRef Tag)
This is the shared class of boolean and integer constants.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Basic type, like 'int' or 'float'.
unsigned getEncoding() const
DINodeArray getElements() const
DINodeArray getAnnotations() const
DIType * getBaseType() const
Tagged DWARF-like metadata node.
dwarf::Tag getTag() const
StringRef getName() const
BoundType getCount() const
Type array for a subprogram.
DITypeRefArray getTypeArray() const
uint64_t getOffsetInBits() const
StringRef getName() const
bool isForwardDecl() const
uint64_t getSizeInBits() const
A parsed version of the target data layout string in and methods for querying it.
Base class for debug information backends.
const MachineInstr * CurMI
If nonnull, stores the current machine instruction we're processing.
AsmPrinter * Asm
Target of debug info emission.
MachineModuleInfo * MMI
Collected machine module information.
DebugLoc PrevInstLoc
Previous instruction's location information.
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
Represents either an error or a value T.
DISubprogram * getSubprogram() const
Get the attached subprogram.
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
@ InternalLinkage
Rename collisions when linking (static functions).
@ WeakODRLinkage
Same, but only replaced by something equivalent.
@ ExternalLinkage
Externally visible function.
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
@ ExternalWeakLinkage
ExternalWeak linkage description.
bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists.
Context object for machine code objects.
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
static MCOperand createReg(unsigned Reg)
static MCOperand createImm(int64_t Val)
This represents a section on linux, lots of unix variants and some bare metal systems.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
void setAlignment(Align Value)
StringRef getName() const
Streaming machine code generation interface.
MCContext & getContext() const
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers.
virtual void switchSection(MCSection *Section, const MCExpr *Subsection=nullptr)
Set the current section where code is being emitted to Section.
void emitInt32(uint64_t Value)
void emitInt8(uint64_t Value)
virtual void emitBytes(StringRef Data)
Emit the bytes in Data into the output.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
bool isInSection() const
isInSection - Check if this symbol is defined in some section (i.e., it is defined but not absolute).
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
const MDOperand & getOperand(unsigned I) const
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
const Module * getModule() const
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
A Module instance is used to store all the information related to an LLVM module.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
iterator find(StringRef Key)
StringRef - Represent a constant reference to a string, i.e.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
bool startswith(StringRef Prefix) const
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
Class to represent struct types.
StringRef getName() const
Return the name for this struct type if it has an identity.
static SectionKind getKindForGlobal(const GlobalObject *GO, const TargetMachine &TM)
Classify the specified global variable into a set of target independent categories embodied in Sectio...
MCSection * SectionForGlobal(const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const
This method computes the appropriate section to emit the specified global variable or function defini...
virtual TargetLoweringObjectFile * getObjFileLowering() const
static Twine utohexstr(const uint64_t &Val)
LLVM Value Representation.
StringRef getName() const
Return a constant reference to the value's name.
A forward iterator which reads text lines from a buffer.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MAX_VLEN
Max # of struct/union/enum members or func args.
@ VAR_GLOBAL_ALLOCATED
Linkage: ExternalLinkage.
@ VAR_STATIC
Linkage: InternalLinkage.
@ VAR_GLOBAL_EXTERNAL
Linkage: ExternalLinkage.
Linkage
Describes symbol linkage.
This is an optimization pass for GlobalISel generic memory operations.
@ Global
Append to llvm.global_dtors.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Represent one field relocation.
uint32_t RelocKind
What to patch the instruction.
const MCSymbol * Label
MCSymbol identifying insn for the reloc.
uint32_t OffsetNameOff
The string to traverse types.
Represent one func and its type id.
uint32_t TypeId
Type id referring to .BTF type section.
const MCSymbol * Label
Func MCSymbol.
uint32_t LineOff
line offset in the .BTF string table
MCSymbol * Label
MCSymbol identifying insn for the lineinfo.
uint32_t ColumnNum
the column number
uint32_t FileNameOff
file name offset in the .BTF string table
uint32_t LineNum
the line number
uint32_t Nelems
Number of elements for this array.
uint32_t IndexType
Index type.
uint32_t ElemType
Element type.
BTF_KIND_ENUM64 is followed by multiple "struct BTFEnum64".
uint32_t NameOff
Enum name offset in the string table.
uint32_t Val_Hi32
Enum member hi32 value.
uint32_t Val_Lo32
Enum member lo32 value.
BTF_KIND_ENUM is followed by multiple "struct BTFEnum".
int32_t Val
Enum member value.
uint32_t NameOff
Enum name offset in the string table.
BTF_KIND_STRUCT and BTF_KIND_UNION are followed by multiple "struct BTFMember".
uint32_t NameOff
Member name offset in the string table.
uint32_t Offset
BitOffset or BitFieldSize+BitOffset.
uint32_t Type
Member type.
BTF_KIND_FUNC_PROTO are followed by multiple "struct BTFParam".
uint32_t NameOff
Type name offset in the string table.
uint32_t Info
"Info" bits arrangement: Bits 0-15: vlen (e.g.
Container for description of a global variable.