#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFDEBUG_H
#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFDEBUG_H
#include "AsmPrinterHandler.h"
#include "DbgValueHistoryCalculator.h"
#include "DebugLocStream.h"
#include "DwarfAccelTable.h"
#include "DwarfFile.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/CodeGen/LexicalScopes.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/Support/Allocator.h"
#include <memory>
namespace llvm {
class AsmPrinter;
class ByteStreamer;
class ConstantInt;
class ConstantFP;
class DebugLocEntry;
class DwarfCompileUnit;
class DwarfDebug;
class DwarfTypeUnit;
class DwarfUnit;
class MachineModuleInfo;
class SrcLineInfo {
unsigned Line; unsigned Column; unsigned SourceID; MCSymbol *Label; public:
SrcLineInfo(unsigned L, unsigned C, unsigned S, MCSymbol *label)
: Line(L), Column(C), SourceID(S), Label(label) {}
unsigned getLine() const { return Line; }
unsigned getColumn() const { return Column; }
unsigned getSourceID() const { return SourceID; }
MCSymbol *getLabel() const { return Label; }
};
class DbgVariable {
const DILocalVariable *Var; const DILocation *IA; SmallVector<const DIExpression *, 1>
Expr; DIE *TheDIE; unsigned DebugLocListIndex; const MachineInstr *MInsn; SmallVector<int, 1> FrameIndex; DwarfDebug *DD;
public:
DbgVariable(const DILocalVariable *V, const DILocation *IA,
const DIExpression *E, DwarfDebug *DD, int FI = ~0)
: Var(V), IA(IA), Expr(1, E), TheDIE(nullptr), DebugLocListIndex(~0U),
MInsn(nullptr), DD(DD) {
FrameIndex.push_back(FI);
assert(!E || E->isValid());
}
DbgVariable(const MachineInstr *DbgValue, DwarfDebug *DD)
: Var(DbgValue->getDebugVariable()),
IA(DbgValue->getDebugLoc()->getInlinedAt()),
Expr(1, DbgValue->getDebugExpression()), TheDIE(nullptr),
DebugLocListIndex(~0U), MInsn(DbgValue), DD(DD) {
FrameIndex.push_back(~0);
}
const DILocalVariable *getVariable() const { return Var; }
const DILocation *getInlinedAt() const { return IA; }
const ArrayRef<const DIExpression *> getExpression() const { return Expr; }
void setDIE(DIE &D) { TheDIE = &D; }
DIE *getDIE() const { return TheDIE; }
void setDebugLocListIndex(unsigned O) { DebugLocListIndex = O; }
unsigned getDebugLocListIndex() const { return DebugLocListIndex; }
StringRef getName() const { return Var->getName(); }
const MachineInstr *getMInsn() const { return MInsn; }
const ArrayRef<int> getFrameIndex() const { return FrameIndex; }
void addMMIEntry(const DbgVariable &V) {
assert(DebugLocListIndex == ~0U && !MInsn && "not an MMI entry");
assert(V.DebugLocListIndex == ~0U && !V.MInsn && "not an MMI entry");
assert(V.Var == Var && "conflicting variable");
assert(V.IA == IA && "conflicting inlined-at location");
if (V.getFrameIndex().back() != ~0) {
auto E = V.getExpression();
auto FI = V.getFrameIndex();
Expr.append(E.begin(), E.end());
FrameIndex.append(FI.begin(), FI.end());
}
assert(Expr.size() > 1 ? std::all_of(Expr.begin(), Expr.end(),
[](const DIExpression *E) {
return E->isBitPiece();
})
: (true && "conflicting locations for variable"));
}
dwarf::Tag getTag() const {
if (Var->getTag() == dwarf::DW_TAG_arg_variable)
return dwarf::DW_TAG_formal_parameter;
return dwarf::DW_TAG_variable;
}
bool isArtificial() const {
if (Var->isArtificial())
return true;
if (getType()->isArtificial())
return true;
return false;
}
bool isObjectPointer() const {
if (Var->isObjectPointer())
return true;
if (getType()->isObjectPointer())
return true;
return false;
}
bool variableHasComplexAddress() const {
assert(Var && "Invalid complex DbgVariable!");
assert(Expr.size() == 1 &&
"variableHasComplexAddress() invoked on multi-FI variable");
return Expr.back()->getNumElements() > 0;
}
bool isBlockByrefVariable() const;
const DIType *getType() const;
private:
template <typename T> T *resolve(TypedDINodeRef<T> Ref) const;
};
struct SymbolCU {
SymbolCU(DwarfCompileUnit *CU, const MCSymbol *Sym) : Sym(Sym), CU(CU) {}
const MCSymbol *Sym;
DwarfCompileUnit *CU;
};
class DwarfDebug : public AsmPrinterHandler {
AsmPrinter *Asm;
MachineModuleInfo *MMI;
BumpPtrAllocator DIEValueAllocator;
MapVector<const MDNode *, DwarfCompileUnit *> CUMap;
MapVector<const MDNode *, DwarfCompileUnit *> SPMap;
DenseMap<const DIE *, DwarfCompileUnit *> CUDieMap;
std::vector<SymbolCU> ArangeLabels;
DenseMap<const MCSymbol *, uint64_t> SymSize;
LexicalScopes LScopes;
DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> AbstractVariables;
SmallVector<std::unique_ptr<DbgVariable>, 64> ConcreteVariables;
DebugLocStream DebugLocs;
SmallPtrSet<const MDNode *, 16> ProcessedSPNodes;
DenseMap<const MachineInstr *, MCSymbol *> LabelsBeforeInsn;
DenseMap<const MachineInstr *, MCSymbol *> LabelsAfterInsn;
DbgValueHistoryMap DbgValues;
DebugLoc PrevInstLoc;
MCSymbol *PrevLabel;
DebugLoc PrologEndLoc;
const MachineFunction *CurFn;
const MachineInstr *CurMI;
const DwarfCompileUnit *PrevCU;
StringRef CompilationDir;
unsigned GlobalRangeCount;
DwarfFile InfoHolder;
typedef SmallVector<std::pair<const MDNode *, const MDNode *>, 32>
ImportedEntityMap;
ImportedEntityMap ScopesWithImportedEntities;
DenseMap<const MDNode *, const DwarfTypeUnit *> DwarfTypeUnits;
SmallVector<
std::pair<std::unique_ptr<DwarfTypeUnit>, const DICompositeType *>, 1>
TypeUnitsUnderConstruction;
bool HasDwarfPubSections;
bool HasCURanges;
bool UsedNonDefaultText;
bool UseGNUTLSOpcode;
unsigned DwarfVersion;
DITypeIdentifierMap TypeIdentifierMap;
bool HasDwarfAccelTables;
bool HasSplitDwarf;
DwarfFile SkeletonHolder;
MCDwarfDwoLineTable SplitTypeUnitFileTable;
bool SingleCU;
bool IsDarwin;
bool IsPS4;
AddressPool AddrPool;
DwarfAccelTable AccelNames;
DwarfAccelTable AccelObjC;
DwarfAccelTable AccelNamespace;
DwarfAccelTable AccelTypes;
DwarfAccelTable AccelExternalTypes;
DenseMap<const Function *, DISubprogram *> FunctionDIs;
MCDwarfDwoLineTable *getDwoLineTable(const DwarfCompileUnit &);
const SmallVectorImpl<std::unique_ptr<DwarfUnit>> &getUnits() {
return InfoHolder.getUnits();
}
typedef DbgValueHistoryMap::InlinedVariable InlinedVariable;
DbgVariable *getExistingAbstractVariable(InlinedVariable IV,
const DILocalVariable *&Cleansed);
DbgVariable *getExistingAbstractVariable(InlinedVariable IV);
void createAbstractVariable(const DILocalVariable *DV, LexicalScope *Scope);
void ensureAbstractVariableIsCreated(InlinedVariable Var,
const MDNode *Scope);
void ensureAbstractVariableIsCreatedIfScoped(InlinedVariable Var,
const MDNode *Scope);
void constructAbstractSubprogramScopeDIE(LexicalScope *Scope);
void emitSectionLabels();
unsigned computeSizeAndOffset(DIE *Die, unsigned Offset);
void computeSizeAndOffsets();
void collectDeadVariables();
void finishVariableDefinitions();
void finishSubprogramDefinitions();
void finalizeModuleInfo();
void emitDebugInfo();
void emitAbbreviations();
void emitEndOfLineMatrix(unsigned SectionEnd);
void emitAccel(DwarfAccelTable &Accel, const MCSection *Section,
StringRef TableName, StringRef SymName);
void emitAccelNames();
void emitAccelObjC();
void emitAccelNamespaces();
void emitAccelTypes();
void emitAccelExternalTypes();
void emitDebugPubNames(bool GnuStyle = false);
void emitDebugPubTypes(bool GnuStyle = false);
void emitDebugPubSection(
bool GnuStyle, const MCSection *PSec, StringRef Name,
const StringMap<const DIE *> &(DwarfCompileUnit::*Accessor)() const);
void emitDebugStr();
void emitDebugLoc();
void emitDebugLocDWO();
void emitDebugARanges();
void emitDebugRanges();
void emitDebugInlineInfo();
void initSkeletonUnit(const DwarfUnit &U, DIE &Die,
std::unique_ptr<DwarfUnit> NewU);
DwarfCompileUnit &constructSkeletonCU(const DwarfCompileUnit &CU);
DwarfTypeUnit &constructSkeletonTU(DwarfTypeUnit &TU);
void emitDebugInfoDWO();
void emitDebugAbbrevDWO();
void emitDebugLineDWO();
void emitDebugStrDWO();
void addGnuPubAttributes(DwarfUnit &U, DIE &D) const;
DwarfCompileUnit &constructDwarfCompileUnit(const DICompileUnit *DIUnit);
void constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU,
const DIImportedEntity *N);
void recordSourceLine(unsigned Line, unsigned Col, const MDNode *Scope,
unsigned Flags);
void identifyScopeMarkers();
void collectVariableInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP,
DenseSet<InlinedVariable> &ProcessedVars);
void buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
const DbgValueHistoryMap::InstrRanges &Ranges);
void collectVariableInfoFromMMITable(DenseSet<InlinedVariable> &P);
void requestLabelBeforeInsn(const MachineInstr *MI) {
LabelsBeforeInsn.insert(std::make_pair(MI, nullptr));
}
void requestLabelAfterInsn(const MachineInstr *MI) {
LabelsAfterInsn.insert(std::make_pair(MI, nullptr));
}
public:
DwarfDebug(AsmPrinter *A, Module *M);
~DwarfDebug() override;
void beginModule();
void endModule() override;
void beginFunction(const MachineFunction *MF) override;
void endFunction(const MachineFunction *MF) override;
void beginInstruction(const MachineInstr *MI) override;
void endInstruction() override;
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 useGNUTLSOpcode() const { return UseGNUTLSOpcode; }
bool useDwarfAccelTables() const { return HasDwarfAccelTables; }
bool useSplitDwarf() const { return HasSplitDwarf; }
unsigned getDwarfVersion() const { return DwarfVersion; }
const DwarfCompileUnit *getPrevCU() const { return PrevCU; }
void setPrevCU(const DwarfCompileUnit *PrevCU) { this->PrevCU = PrevCU; }
const DebugLocStream &getDebugLocs() const { return DebugLocs; }
void emitDebugLocEntry(ByteStreamer &Streamer,
const DebugLocStream::Entry &Entry);
void emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry);
template <typename T> T *resolve(TypedDINodeRef<T> Ref) const {
return Ref.resolve(TypeIdentifierMap);
}
const DITypeIdentifierMap &getTypeIdentifierMap() const {
return TypeIdentifierMap;
}
DwarfCompileUnit *lookupUnit(const DIE *CU) const {
return CUDieMap.lookup(CU);
}
bool isSubprogramContext(const MDNode *Context);
void addSubprogramNames(const DISubprogram *SP, DIE &Die);
AddressPool &getAddressPool() { return AddrPool; }
void addAccelName(StringRef Name, const DIE &Die);
void addAccelObjC(StringRef Name, const DIE &Die);
void addAccelNamespace(StringRef Name, const DIE &Die);
void addAccelType(StringRef Name, const DIE &Die, char Flags);
void addAccelExternalType(StringRef UID, StringRef Module);
const MachineFunction *getCurrentFunction() const { return CurFn; }
iterator_range<ImportedEntityMap::const_iterator>
findImportedEntitiesForScope(const MDNode *Scope) const {
return make_range(std::equal_range(
ScopesWithImportedEntities.begin(), ScopesWithImportedEntities.end(),
std::pair<const MDNode *, const MDNode *>(Scope, nullptr),
less_first()));
}
bool isLexicalScopeDIENull(LexicalScope *Scope);
MCSymbol *getLabelBeforeInsn(const MachineInstr *MI);
MCSymbol *getLabelAfterInsn(const MachineInstr *MI);
static uint64_t makeTypeSignature(StringRef Identifier);
unsigned getNextRangeNumber() { return GlobalRangeCount++; }
SmallPtrSet<const MDNode *, 16> &getProcessedSPNodes() {
return ProcessedSPNodes;
}
};
}
#endif