#ifndef LLVM_LIB_TARGET_BPF_BTFDEBUG_H
#define LLVM_LIB_TARGET_BPF_BTFDEBUG_H
#include "llvm/ADT/StringMap.h"
#include "llvm/CodeGen/DebugHandlerBase.h"
#include <cstdint>
#include <map>
#include <set>
#include <unordered_map>
#include "BTF.h"
namespace llvm {
class AsmPrinter;
class BTFDebug;
class DIType;
class GlobalVariable;
class MachineFunction;
class MachineInstr;
class MachineOperand;
class MCInst;
class MCStreamer;
class MCSymbol;
class BTFTypeBase {
protected:
uint8_t Kind;
bool IsCompleted;
uint32_t Id;
struct BTF::CommonType BTFType;
public:
BTFTypeBase() : IsCompleted(false) {}
virtual ~BTFTypeBase() = default;
void setId(uint32_t Id) { this->Id = Id; }
uint32_t getId() { return Id; }
uint32_t roundupToBytes(uint32_t NumBits) { return (NumBits + 7) >> 3; }
virtual uint32_t getSize() { return BTF::CommonTypeSize; }
virtual void completeType(BTFDebug &BDebug) {}
virtual void emitType(MCStreamer &OS);
};
class BTFTypeDerived : public BTFTypeBase {
const DIDerivedType *DTy;
bool NeedsFixup;
StringRef Name;
public:
BTFTypeDerived(const DIDerivedType *Ty, unsigned Tag, bool NeedsFixup);
BTFTypeDerived(unsigned NextTypeId, unsigned Tag, StringRef Name);
void completeType(BTFDebug &BDebug) override;
void emitType(MCStreamer &OS) override;
void setPointeeType(uint32_t PointeeType);
};
class BTFTypeFwd : public BTFTypeBase {
StringRef Name;
public:
BTFTypeFwd(StringRef Name, bool IsUnion);
void completeType(BTFDebug &BDebug) override;
void emitType(MCStreamer &OS) override;
};
class BTFTypeInt : public BTFTypeBase {
StringRef Name;
uint32_t IntVal;
public:
BTFTypeInt(uint32_t Encoding, uint32_t SizeInBits, uint32_t OffsetInBits,
StringRef TypeName);
uint32_t getSize() override { return BTFTypeBase::getSize() + sizeof(uint32_t); }
void completeType(BTFDebug &BDebug) override;
void emitType(MCStreamer &OS) override;
};
class BTFTypeEnum : public BTFTypeBase {
const DICompositeType *ETy;
std::vector<struct BTF::BTFEnum> EnumValues;
public:
BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned);
uint32_t getSize() override {
return BTFTypeBase::getSize() + EnumValues.size() * BTF::BTFEnumSize;
}
void completeType(BTFDebug &BDebug) override;
void emitType(MCStreamer &OS) override;
};
class BTFTypeArray : public BTFTypeBase {
struct BTF::BTFArray ArrayInfo;
public:
BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems);
uint32_t getSize() override { return BTFTypeBase::getSize() + BTF::BTFArraySize; }
void completeType(BTFDebug &BDebug) override;
void emitType(MCStreamer &OS) override;
};
class BTFTypeStruct : public BTFTypeBase {
const DICompositeType *STy;
bool HasBitField;
std::vector<struct BTF::BTFMember> Members;
public:
BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField,
uint32_t NumMembers);
uint32_t getSize() override {
return BTFTypeBase::getSize() + Members.size() * BTF::BTFMemberSize;
}
void completeType(BTFDebug &BDebug) override;
void emitType(MCStreamer &OS) override;
std::string getName();
};
class BTFTypeFuncProto : public BTFTypeBase {
const DISubroutineType *STy;
std::unordered_map<uint32_t, StringRef> FuncArgNames;
std::vector<struct BTF::BTFParam> Parameters;
public:
BTFTypeFuncProto(const DISubroutineType *STy, uint32_t NumParams,
const std::unordered_map<uint32_t, StringRef> &FuncArgNames);
uint32_t getSize() override {
return BTFTypeBase::getSize() + Parameters.size() * BTF::BTFParamSize;
}
void completeType(BTFDebug &BDebug) override;
void emitType(MCStreamer &OS) override;
};
class BTFTypeFunc : public BTFTypeBase {
StringRef Name;
public:
BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId, uint32_t Scope);
uint32_t getSize() override { return BTFTypeBase::getSize(); }
void completeType(BTFDebug &BDebug) override;
void emitType(MCStreamer &OS) override;
};
class BTFKindVar : public BTFTypeBase {
StringRef Name;
uint32_t Info;
public:
BTFKindVar(StringRef VarName, uint32_t TypeId, uint32_t VarInfo);
uint32_t getSize() override { return BTFTypeBase::getSize() + 4; }
void completeType(BTFDebug &BDebug) override;
void emitType(MCStreamer &OS) override;
};
class BTFKindDataSec : public BTFTypeBase {
AsmPrinter *Asm;
std::string Name;
std::vector<std::tuple<uint32_t, const MCSymbol *, uint32_t>> Vars;
public:
BTFKindDataSec(AsmPrinter *AsmPrt, std::string SecName);
uint32_t getSize() override {
return BTFTypeBase::getSize() + BTF::BTFDataSecVarSize * Vars.size();
}
void addDataSecEntry(uint32_t Id, const MCSymbol *Sym, uint32_t Size) {
Vars.push_back(std::make_tuple(Id, Sym, Size));
}
std::string getName() { return Name; }
void completeType(BTFDebug &BDebug) override;
void emitType(MCStreamer &OS) override;
};
class BTFTypeFloat : public BTFTypeBase {
StringRef Name;
public:
BTFTypeFloat(uint32_t SizeInBits, StringRef TypeName);
void completeType(BTFDebug &BDebug) override;
};
class BTFTypeDeclTag : public BTFTypeBase {
uint32_t Info;
StringRef Tag;
public:
BTFTypeDeclTag(uint32_t BaseTypeId, int ComponentId, StringRef Tag);
uint32_t getSize() override { return BTFTypeBase::getSize() + 4; }
void completeType(BTFDebug &BDebug) override;
void emitType(MCStreamer &OS) override;
};
class BTFTypeEnum64 : public BTFTypeBase {
const DICompositeType *ETy;
std::vector<struct BTF::BTFEnum64> EnumValues;
public:
BTFTypeEnum64(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned);
uint32_t getSize() override {
return BTFTypeBase::getSize() + EnumValues.size() * BTF::BTFEnum64Size;
}
void completeType(BTFDebug &BDebug) override;
void emitType(MCStreamer &OS) override;
};
class BTFTypeTypeTag : public BTFTypeBase {
const DIDerivedType *DTy;
StringRef Tag;
public:
BTFTypeTypeTag(uint32_t NextTypeId, StringRef Tag);
BTFTypeTypeTag(const DIDerivedType *DTy, StringRef Tag);
void completeType(BTFDebug &BDebug) override;
};
class BTFStringTable {
uint32_t Size;
std::map<uint32_t, uint32_t> OffsetToIdMap;
std::vector<std::string> Table;
public:
BTFStringTable() : Size(0) {}
uint32_t getSize() { return Size; }
std::vector<std::string> &getTable() { return Table; }
uint32_t addString(StringRef S);
};
struct BTFFuncInfo {
const MCSymbol *Label; uint32_t TypeId; };
struct BTFLineInfo {
MCSymbol *Label; uint32_t FileNameOff; uint32_t LineOff; uint32_t LineNum; uint32_t ColumnNum; };
struct BTFFieldReloc {
const MCSymbol *Label; uint32_t TypeID; uint32_t OffsetNameOff; uint32_t RelocKind; };
class BTFDebug : public DebugHandlerBase {
MCStreamer &OS;
bool SkipInstruction;
bool LineInfoGenerated;
uint32_t SecNameOff;
uint32_t ArrayIndexTypeId;
bool MapDefNotCollected;
BTFStringTable StringTable;
std::vector<std::unique_ptr<BTFTypeBase>> TypeEntries;
std::unordered_map<const DIType *, uint32_t> DIToIdMap;
std::map<uint32_t, std::vector<BTFFuncInfo>> FuncInfoTable;
std::map<uint32_t, std::vector<BTFLineInfo>> LineInfoTable;
std::map<uint32_t, std::vector<BTFFieldReloc>> FieldRelocTable;
StringMap<std::vector<std::string>> FileContent;
std::map<std::string, std::unique_ptr<BTFKindDataSec>> DataSecEntries;
std::vector<BTFTypeStruct *> StructTypes;
std::map<const GlobalVariable *, std::pair<int64_t, uint32_t>> PatchImms;
std::map<const DICompositeType *,
std::vector<std::pair<const DIDerivedType *, BTFTypeDerived *>>>
FixupDerivedTypes;
std::set<const Function *>ProtoFunctions;
uint32_t addType(std::unique_ptr<BTFTypeBase> TypeEntry, const DIType *Ty);
uint32_t addType(std::unique_ptr<BTFTypeBase> TypeEntry);
void visitTypeEntry(const DIType *Ty);
void visitTypeEntry(const DIType *Ty, uint32_t &TypeId, bool CheckPointer,
bool SeenPointer);
void visitBasicType(const DIBasicType *BTy, uint32_t &TypeId);
void visitSubroutineType(
const DISubroutineType *STy, bool ForSubprog,
const std::unordered_map<uint32_t, StringRef> &FuncArgNames,
uint32_t &TypeId);
void visitFwdDeclType(const DICompositeType *CTy, bool IsUnion,
uint32_t &TypeId);
void visitCompositeType(const DICompositeType *CTy, uint32_t &TypeId);
void visitStructType(const DICompositeType *STy, bool IsStruct,
uint32_t &TypeId);
void visitArrayType(const DICompositeType *ATy, uint32_t &TypeId);
void visitEnumType(const DICompositeType *ETy, uint32_t &TypeId);
void visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId,
bool CheckPointer, bool SeenPointer);
void visitMapDefType(const DIType *Ty, uint32_t &TypeId);
std::string populateFileContent(const DISubprogram *SP);
void constructLineInfo(const DISubprogram *SP, MCSymbol *Label, uint32_t Line,
uint32_t Column);
void processGlobals(bool ProcessingMapDef);
void processFuncPrototypes(const Function *);
void processDeclAnnotations(DINodeArray Annotations, uint32_t BaseTypeId,
int ComponentId);
int genBTFTypeTags(const DIDerivedType *DTy, int BaseTypeId);
void generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId,
const GlobalVariable *, bool IsAma);
unsigned populateType(const DIType *Ty);
void processGlobalValue(const MachineOperand &MO);
void emitCommonHeader();
void emitBTFSection();
void emitBTFExtSection();
protected:
void beginFunctionImpl(const MachineFunction *MF) override;
void endFunctionImpl(const MachineFunction *MF) override;
public:
BTFDebug(AsmPrinter *AP);
bool InstLower(const MachineInstr *MI, MCInst &OutMI);
uint32_t getArrayIndexTypeId() {
assert(ArrayIndexTypeId);
return ArrayIndexTypeId;
}
size_t addString(StringRef S) { return StringTable.addString(S); }
uint32_t getTypeId(const DIType *Ty) {
assert(Ty && "Invalid null Type");
assert(DIToIdMap.find(Ty) != DIToIdMap.end() &&
"DIType not added in the BDIToIdMap");
return DIToIdMap[Ty];
}
void setSymbolSize(const MCSymbol *Symbol, uint64_t Size) override {}
void beginInstruction(const MachineInstr *MI) override;
void endModule() override;
};
}
#endif