#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFDEBUG_H
#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFDEBUG_H
#include "AddressPool.h"
#include "DebugLocEntry.h"
#include "DebugLocStream.h"
#include "DwarfFile.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/AccelTable.h"
#include "llvm/CodeGen/DbgEntityHistoryCalculator.h"
#include "llvm/CodeGen/DebugHandlerBase.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Metadata.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Target/TargetOptions.h"
#include <cassert>
#include <cstdint>
#include <limits>
#include <memory>
#include <utility>
#include <vector>
namespace llvm {
class AsmPrinter;
class ByteStreamer;
class DIE;
class DwarfCompileUnit;
class DwarfExpression;
class DwarfTypeUnit;
class DwarfUnit;
class LexicalScope;
class MachineFunction;
class MCSection;
class MCSymbol;
class Module;
class DbgEntity {
public:
enum DbgEntityKind {
DbgVariableKind,
DbgLabelKind
};
private:
const DINode *Entity;
const DILocation *InlinedAt;
DIE *TheDIE = nullptr;
const DbgEntityKind SubclassID;
public:
DbgEntity(const DINode *N, const DILocation *IA, DbgEntityKind ID)
: Entity(N), InlinedAt(IA), SubclassID(ID) {}
virtual ~DbgEntity() = default;
const DINode *getEntity() const { return Entity; }
const DILocation *getInlinedAt() const { return InlinedAt; }
DIE *getDIE() const { return TheDIE; }
DbgEntityKind getDbgEntityID() const { return SubclassID; }
void setDIE(DIE &D) { TheDIE = &D; }
static bool classof(const DbgEntity *N) {
switch (N->getDbgEntityID()) {
case DbgVariableKind:
case DbgLabelKind:
return true;
}
llvm_unreachable("Invalid DbgEntityKind");
}
};
class DbgVariable : public DbgEntity {
unsigned DebugLocListIndex = ~0u;
Optional<uint8_t> DebugLocListTagOffset;
std::unique_ptr<DbgValueLoc> ValueLoc = nullptr;
struct FrameIndexExpr {
int FI;
const DIExpression *Expr;
};
mutable SmallVector<FrameIndexExpr, 1>
FrameIndexExprs;
public:
DbgVariable(const DILocalVariable *V, const DILocation *IA)
: DbgEntity(V, IA, DbgVariableKind) {}
void initializeMMI(const DIExpression *E, int FI) {
assert(FrameIndexExprs.empty() && "Already initialized?");
assert(!ValueLoc.get() && "Already initialized?");
assert((!E || E->isValid()) && "Expected valid expression");
assert(FI != std::numeric_limits<int>::max() && "Expected valid index");
FrameIndexExprs.push_back({FI, E});
}
void initializeDbgValue(DbgValueLoc Value) {
assert(FrameIndexExprs.empty() && "Already initialized?");
assert(!ValueLoc && "Already initialized?");
assert(!Value.getExpression()->isFragment() && "Fragments not supported.");
ValueLoc = std::make_unique<DbgValueLoc>(Value);
if (auto *E = ValueLoc->getExpression())
if (E->getNumElements())
FrameIndexExprs.push_back({0, E});
}
void initializeDbgValue(const MachineInstr *DbgValue);
const DILocalVariable *getVariable() const {
return cast<DILocalVariable>(getEntity());
}
const DIExpression *getSingleExpression() const {
assert(ValueLoc.get() && FrameIndexExprs.size() <= 1);
return FrameIndexExprs.size() ? FrameIndexExprs[0].Expr : nullptr;
}
void setDebugLocListIndex(unsigned O) { DebugLocListIndex = O; }
unsigned getDebugLocListIndex() const { return DebugLocListIndex; }
void setDebugLocListTagOffset(uint8_t O) { DebugLocListTagOffset = O; }
Optional<uint8_t> getDebugLocListTagOffset() const { return DebugLocListTagOffset; }
StringRef getName() const { return getVariable()->getName(); }
const DbgValueLoc *getValueLoc() const { return ValueLoc.get(); }
ArrayRef<FrameIndexExpr> getFrameIndexExprs() const;
bool hasFrameIndexExprs() const { return !FrameIndexExprs.empty(); }
void addMMIEntry(const DbgVariable &V);
dwarf::Tag getTag() const {
if (getVariable()->isParameter())
return dwarf::DW_TAG_formal_parameter;
return dwarf::DW_TAG_variable;
}
bool isArtificial() const {
if (getVariable()->isArtificial())
return true;
if (getType()->isArtificial())
return true;
return false;
}
bool isObjectPointer() const {
if (getVariable()->isObjectPointer())
return true;
if (getType()->isObjectPointer())
return true;
return false;
}
bool hasComplexAddress() const {
assert(ValueLoc.get() && "Expected DBG_VALUE, not MMI variable");
assert((FrameIndexExprs.empty() ||
(FrameIndexExprs.size() == 1 &&
FrameIndexExprs[0].Expr->getNumElements())) &&
"Invalid Expr for DBG_VALUE");
return !FrameIndexExprs.empty();
}
const DIType *getType() const;
static bool classof(const DbgEntity *N) {
return N->getDbgEntityID() == DbgVariableKind;
}
};
class DbgLabel : public DbgEntity {
const MCSymbol *Sym;
public:
DbgLabel(const DILabel *L, const DILocation *IA, const MCSymbol *Sym = nullptr)
: DbgEntity(L, IA, DbgLabelKind), Sym(Sym) {}
const DILabel *getLabel() const { return cast<DILabel>(getEntity()); }
const MCSymbol *getSymbol() const { return Sym; }
StringRef getName() const { return getLabel()->getName(); }
dwarf::Tag getTag() const {
return dwarf::DW_TAG_label;
}
static bool classof(const DbgEntity *N) {
return N->getDbgEntityID() == DbgLabelKind;
}
};
class DbgCallSiteParam {
private:
unsigned Register; DbgValueLoc Value; public:
DbgCallSiteParam(unsigned Reg, DbgValueLoc Val)
: Register(Reg), Value(Val) {
assert(Reg && "Parameter register cannot be undef");
}
unsigned getRegister() const { return Register; }
DbgValueLoc getValue() const { return Value; }
};
using ParamSet = SmallVector<DbgCallSiteParam, 4>;
struct SymbolCU {
SymbolCU(DwarfCompileUnit *CU, const MCSymbol *Sym) : Sym(Sym), CU(CU) {}
const MCSymbol *Sym;
DwarfCompileUnit *CU;
};
enum class AccelTableKind {
Default, None, Apple, Dwarf, };
class DwarfDebug : public DebugHandlerBase {
BumpPtrAllocator DIEValueAllocator;
MapVector<const MDNode *, DwarfCompileUnit *> CUMap;
DenseMap<const DIE *, DwarfCompileUnit *> CUDieMap;
std::vector<SymbolCU> ArangeLabels;
DenseMap<const MCSymbol *, uint64_t> SymSize;
SmallVector<std::unique_ptr<DbgEntity>, 64> ConcreteEntities;
DebugLocStream DebugLocs;
SetVector<const DISubprogram *, SmallVector<const DISubprogram *, 16>,
SmallPtrSet<const DISubprogram *, 16>>
ProcessedSPNodes;
const MachineFunction *CurFn = nullptr;
const DwarfCompileUnit *PrevCU = nullptr;
StringRef CompilationDir;
DwarfFile InfoHolder;
DenseMap<const MDNode *, uint64_t> TypeSignatures;
DenseMap<const MCSection *, const MCSymbol *> SectionLabels;
SmallVector<
std::pair<std::unique_ptr<DwarfTypeUnit>, const DICompositeType *>, 1>
TypeUnitsUnderConstruction;
bool UseGNUTLSOpcode;
bool UseDWARF2Bitfields;
bool UseAllLinkageNames;
bool UseInlineStrings = false;
bool UseRangesSection = true;
bool UseSectionsAsReferences = false;
bool UseLocSection = true;
bool GenerateTypeUnits;
bool UseDebugMacroSection;
bool EnableOpConvert;
public:
enum class MinimizeAddrInV5 {
Default,
Disabled,
Ranges,
Expressions,
Form,
};
private:
MinimizeAddrInV5 MinimizeAddr = MinimizeAddrInV5::Disabled;
AccelTableKind TheAccelTableKind;
bool HasAppleExtensionAttributes;
bool HasSplitDwarf;
bool UseSegmentedStringOffsetsTable;
bool EmitDebugEntryValues;
DwarfFile SkeletonHolder;
MCDwarfDwoLineTable SplitTypeUnitFileTable;
bool SingleCU;
bool IsDarwin;
DenseMap<const DIStringType *, unsigned> StringTypeLocMap;
AddressPool AddrPool;
AccelTable<DWARF5AccelTableData> AccelDebugNames;
AccelTable<AppleAccelTableOffsetData> AccelNames;
AccelTable<AppleAccelTableOffsetData> AccelObjC;
AccelTable<AppleAccelTableOffsetData> AccelNamespace;
AccelTable<AppleAccelTableTypeData> AccelTypes;
DebuggerKind DebuggerTuning = DebuggerKind::Default;
MCDwarfDwoLineTable *getDwoLineTable(const DwarfCompileUnit &);
const SmallVectorImpl<std::unique_ptr<DwarfCompileUnit>> &getUnits() {
return InfoHolder.getUnits();
}
using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
void ensureAbstractEntityIsCreated(DwarfCompileUnit &CU,
const DINode *Node,
const MDNode *Scope);
void ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU,
const DINode *Node,
const MDNode *Scope);
DbgEntity *createConcreteEntity(DwarfCompileUnit &TheCU,
LexicalScope &Scope,
const DINode *Node,
const DILocation *Location,
const MCSymbol *Sym = nullptr);
void constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, LexicalScope *Scope);
void constructCallSiteEntryDIEs(const DISubprogram &SP, DwarfCompileUnit &CU,
DIE &ScopeDIE, const MachineFunction &MF);
template <typename DataT>
void addAccelNameImpl(const DICompileUnit &CU, AccelTable<DataT> &AppleAccel,
StringRef Name, const DIE &Die);
void finishEntityDefinitions();
void finishSubprogramDefinitions();
void finalizeModuleInfo();
void emitDebugInfo();
void emitAbbreviations();
void emitStringOffsetsTableHeader();
template <typename AccelTableT>
void emitAccel(AccelTableT &Accel, MCSection *Section, StringRef TableName);
void emitAccelDebugNames();
void emitAccelNames();
void emitAccelObjC();
void emitAccelNamespaces();
void emitAccelTypes();
void emitDebugPubSections();
void emitDebugPubSection(bool GnuStyle, StringRef Name,
DwarfCompileUnit *TheU,
const StringMap<const DIE *> &Globals);
void emitDebugStr();
void emitDebugLoc();
void emitDebugLocDWO();
void emitDebugLocImpl(MCSection *Sec);
void emitDebugARanges();
void emitDebugRanges();
void emitDebugRangesDWO();
void emitDebugRangesImpl(const DwarfFile &Holder, MCSection *Section);
void emitDebugMacinfo();
void emitDebugMacinfoDWO();
void emitDebugMacinfoImpl(MCSection *Section);
void emitMacro(DIMacro &M);
void emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U);
void emitMacroFileImpl(DIMacroFile &F, DwarfCompileUnit &U,
unsigned StartFile, unsigned EndFile,
StringRef (*MacroFormToString)(unsigned Form));
void handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U);
void initSkeletonUnit(const DwarfUnit &U, DIE &Die,
std::unique_ptr<DwarfCompileUnit> NewU);
DwarfCompileUnit &constructSkeletonCU(const DwarfCompileUnit &CU);
void emitDebugInfoDWO();
void emitDebugAbbrevDWO();
void emitDebugLineDWO();
void emitStringOffsetsTableHeaderDWO();
void emitDebugStrDWO();
void emitDebugAddr();
void addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const;
DwarfCompileUnit &getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit);
void finishUnitAttributes(const DICompileUnit *DIUnit,
DwarfCompileUnit &NewCU);
void constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU,
const DIImportedEntity *N);
void recordSourceLine(unsigned Line, unsigned Col, const MDNode *Scope,
unsigned Flags);
void collectEntityInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP,
DenseSet<InlinedEntity> &ProcessedVars);
bool buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
const DbgValueHistoryMap::Entries &Entries);
void collectVariableInfoFromMFTable(DwarfCompileUnit &TheCU,
DenseSet<InlinedEntity> &P);
void emitSectionReference(const DwarfCompileUnit &CU);
protected:
void beginFunctionImpl(const MachineFunction *MF) override;
void endFunctionImpl(const MachineFunction *MF) override;
unsigned getDwarfCompileUnitIDForLineTable(const DwarfCompileUnit &CU);
void skippedNonDebugFunction() override;
public:
DwarfDebug(AsmPrinter *A);
~DwarfDebug() override;
void beginModule(Module *M) override;
void endModule() override;
DebugLoc emitInitialLocDirective(const MachineFunction &MF, unsigned CUID);
void beginInstruction(const MachineInstr *MI) override;
static uint64_t makeTypeSignature(StringRef Identifier);
void addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier,
DIE &Die, const DICompositeType *CTy);
void addArangeLabel(SymbolCU SCU) { ArangeLabels.push_back(SCU); }
void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {
SymSize[Sym] = Size;
}
bool useAllLinkageNames() const { return UseAllLinkageNames; }
bool useGNUTLSOpcode() const { return UseGNUTLSOpcode; }
bool useDWARF2Bitfields() const { return UseDWARF2Bitfields; }
bool useInlineStrings() const { return UseInlineStrings; }
bool useRangesSection() const { return UseRangesSection; }
bool alwaysUseRanges() const {
return MinimizeAddr == MinimizeAddrInV5::Ranges;
}
bool useAddrOffsetExpressions() const {
return MinimizeAddr == MinimizeAddrInV5::Expressions;
}
bool useAddrOffsetForm() const {
return MinimizeAddr == MinimizeAddrInV5::Form;
}
bool useSectionsAsReferences() const {
return UseSectionsAsReferences;
}
bool useLocSection() const { return UseLocSection; }
bool generateTypeUnits() const { return GenerateTypeUnits; }
AccelTableKind getAccelTableKind() const { return TheAccelTableKind; }
bool useAppleExtensionAttributes() const {
return HasAppleExtensionAttributes;
}
bool useSplitDwarf() const { return HasSplitDwarf; }
bool useSegmentedStringOffsetsTable() const {
return UseSegmentedStringOffsetsTable;
}
bool emitDebugEntryValues() const {
return EmitDebugEntryValues;
}
bool useOpConvert() const {
return EnableOpConvert;
}
bool shareAcrossDWOCUs() const;
uint16_t getDwarfVersion() const;
dwarf::Form getDwarfSectionOffsetForm() const;
const DwarfCompileUnit *getPrevCU() const { return PrevCU; }
void setPrevCU(const DwarfCompileUnit *PrevCU) { this->PrevCU = PrevCU; }
void terminateLineTable(const DwarfCompileUnit *CU);
const DebugLocStream &getDebugLocs() const { return DebugLocs; }
void emitDebugLocEntry(ByteStreamer &Streamer,
const DebugLocStream::Entry &Entry,
const DwarfCompileUnit *CU);
void emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry,
const DwarfCompileUnit *CU);
void addSubprogramNames(const DICompileUnit &CU, const DISubprogram *SP,
DIE &Die);
AddressPool &getAddressPool() { return AddrPool; }
void addAccelName(const DICompileUnit &CU, StringRef Name, const DIE &Die);
void addAccelObjC(const DICompileUnit &CU, StringRef Name, const DIE &Die);
void addAccelNamespace(const DICompileUnit &CU, StringRef Name,
const DIE &Die);
void addAccelType(const DICompileUnit &CU, StringRef Name, const DIE &Die,
char Flags);
const MachineFunction *getCurrentFunction() const { return CurFn; }
bool isLexicalScopeDIENull(LexicalScope *Scope);
DwarfCompileUnit *lookupCU(const DIE *Die) { return CUDieMap.lookup(Die); }
const DwarfCompileUnit *lookupCU(const DIE *Die) const {
return CUDieMap.lookup(Die);
}
unsigned getStringTypeLoc(const DIStringType *ST) const {
return StringTypeLocMap.lookup(ST);
}
void addStringTypeLoc(const DIStringType *ST, unsigned Loc) {
assert(ST);
if (Loc)
StringTypeLocMap[ST] = Loc;
}
bool tuneForGDB() const { return DebuggerTuning == DebuggerKind::GDB; }
bool tuneForLLDB() const { return DebuggerTuning == DebuggerKind::LLDB; }
bool tuneForSCE() const { return DebuggerTuning == DebuggerKind::SCE; }
bool tuneForDBX() const { return DebuggerTuning == DebuggerKind::DBX; }
const MCSymbol *getSectionLabel(const MCSection *S);
void insertSectionLabel(const MCSymbol *S);
static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
const DbgValueLoc &Value,
DwarfExpression &DwarfExpr);
Optional<MD5::MD5Result> getMD5AsBytes(const DIFile *File) const;
};
}
#endif