diff options
author | Hsiangkai Wang <hsiangkai@gmail.com> | 2018-08-14 13:50:59 +0000 |
---|---|---|
committer | Hsiangkai Wang <hsiangkai@gmail.com> | 2018-08-14 13:50:59 +0000 |
commit | ccae278938ac2925aea9892d43ee83415c44598f (patch) | |
tree | f2e1ca91500f85e7035579ca0a973d42a27a1337 /llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | |
parent | 5bd88cf7ddc3342c1a17578aa550e21383b4d079 (diff) | |
download | bcm5719-llvm-ccae278938ac2925aea9892d43ee83415c44598f.tar.gz bcm5719-llvm-ccae278938ac2925aea9892d43ee83415c44598f.zip |
[DebugInfo] Generate DWARF debug information for labels. (Fix leak problems)
There are two forms for label debug information in DWARF format.
1. Labels in a non-inlined function:
DW_TAG_label
DW_AT_name
DW_AT_decl_file
DW_AT_decl_line
DW_AT_low_pc
2. Labels in an inlined function:
DW_TAG_label
DW_AT_abstract_origin
DW_AT_low_pc
We will collect label information from DBG_LABEL. Before every DBG_LABEL,
we will generate a temporary symbol to denote the location of the label.
The symbol could be used to get DW_AT_low_pc afterwards. So, we create a
mapping between 'inlined label' and DBG_LABEL MachineInstr in DebugHandlerBase.
The DBG_LABEL in the mapping is used to query the symbol before it.
The AbstractLabels in DwarfCompileUnit is used to process labels in inlined
functions.
We also keep a mapping between scope and labels in DwarfFile to help to
generate correct tree structure of DIEs.
It also generates label debug information under global isel.
Differential Revision: https://reviews.llvm.org/D45556
llvm-svn: 339676
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 137 |
1 files changed, 110 insertions, 27 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index abf2e43b131..e314f8e17d6 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -15,7 +15,7 @@ #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFDEBUG_H #include "AddressPool.h" -#include "DbgValueHistoryCalculator.h" +#include "DbgEntityHistoryCalculator.h" #include "DebugHandlerBase.h" #include "DebugLocStream.h" #include "DwarfFile.h" @@ -62,6 +62,47 @@ class MDNode; class Module; //===----------------------------------------------------------------------===// +/// This class is defined as the common parent of DbgVariable and DbgLabel +/// such that it could levarage polymorphism to extract common code for +/// DbgVariable and DbgLabel. +class DbgEntity { + const DINode *Entity; + const DILocation *InlinedAt; + DIE *TheDIE = nullptr; + unsigned SubclassID; + +public: + enum DbgEntityKind { + DbgVariableKind, + DbgLabelKind + }; + + DbgEntity(const DINode *N, const DILocation *IA, unsigned ID) + : Entity(N), InlinedAt(IA), SubclassID(ID) {} + virtual ~DbgEntity() {} + + /// Accessors. + /// @{ + const DINode *getEntity() const { return Entity; } + const DILocation *getInlinedAt() const { return InlinedAt; } + DIE *getDIE() const { return TheDIE; } + unsigned getDbgEntityID() const { return SubclassID; } + /// @} + + void setDIE(DIE &D) { TheDIE = &D; } + + static bool classof(const DbgEntity *N) { + switch (N->getDbgEntityID()) { + default: + return false; + case DbgVariableKind: + case DbgLabelKind: + return true; + } + } +}; + +//===----------------------------------------------------------------------===// /// This class is used to track local variable information. /// /// Variables can be created from allocas, in which case they're generated from @@ -73,10 +114,7 @@ class Module; /// single instruction use \a MInsn and (optionally) a single entry of \a Expr. /// /// Variables that have been optimized out use none of these fields. -class DbgVariable { - const DILocalVariable *Var; /// Variable Descriptor. - const DILocation *IA; /// Inlined at location. - DIE *TheDIE = nullptr; /// Variable DIE. +class DbgVariable : public DbgEntity { unsigned DebugLocListIndex = ~0u; /// Offset in DebugLocs. const MachineInstr *MInsn = nullptr; /// DBG_VALUE instruction. @@ -93,7 +131,7 @@ public: /// Creates a variable without any DW_AT_location. Call \a initializeMMI() /// for MMI entries, or \a initializeDbgValue() for DBG_VALUE instructions. DbgVariable(const DILocalVariable *V, const DILocation *IA) - : Var(V), IA(IA) {} + : DbgEntity(V, IA, DbgVariableKind) {} /// Initialize from the MMI table. void initializeMMI(const DIExpression *E, int FI) { @@ -111,8 +149,9 @@ public: assert(FrameIndexExprs.empty() && "Already initialized?"); assert(!MInsn && "Already initialized?"); - assert(Var == DbgValue->getDebugVariable() && "Wrong variable"); - assert(IA == DbgValue->getDebugLoc()->getInlinedAt() && "Wrong inlined-at"); + assert(getVariable() == DbgValue->getDebugVariable() && "Wrong variable"); + assert(getInlinedAt() == DbgValue->getDebugLoc()->getInlinedAt() && + "Wrong inlined-at"); MInsn = DbgValue; if (auto *E = DbgValue->getDebugExpression()) @@ -121,19 +160,18 @@ public: } // Accessors. - const DILocalVariable *getVariable() const { return Var; } - const DILocation *getInlinedAt() const { return IA; } + const DILocalVariable *getVariable() const { + return cast<DILocalVariable>(getEntity()); + } const DIExpression *getSingleExpression() const { assert(MInsn && FrameIndexExprs.size() <= 1); return FrameIndexExprs.size() ? FrameIndexExprs[0].Expr : nullptr; } - 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(); } + StringRef getName() const { return getVariable()->getName(); } const MachineInstr *getMInsn() const { return MInsn; } /// Get the FI entries, sorted by fragment offset. ArrayRef<FrameIndexExpr> getFrameIndexExprs() const; @@ -143,7 +181,7 @@ public: // Translate tag to proper Dwarf tag. dwarf::Tag getTag() const { // FIXME: Why don't we just infer this tag and store it all along? - if (Var->isParameter()) + if (getVariable()->isParameter()) return dwarf::DW_TAG_formal_parameter; return dwarf::DW_TAG_variable; @@ -151,7 +189,7 @@ public: /// Return true if DbgVariable is artificial. bool isArtificial() const { - if (Var->isArtificial()) + if (getVariable()->isArtificial()) return true; if (getType()->isArtificial()) return true; @@ -159,7 +197,7 @@ public: } bool isObjectPointer() const { - if (Var->isObjectPointer()) + if (getVariable()->isObjectPointer()) return true; if (getType()->isObjectPointer()) return true; @@ -178,6 +216,45 @@ public: bool isBlockByrefVariable() const; const DIType *getType() const; + static bool classof(const DbgEntity *N) { + return N->getDbgEntityID() == DbgVariableKind; + } + +private: + template <typename T> T *resolve(TypedDINodeRef<T> Ref) const { + return Ref.resolve(); + } +}; + +//===----------------------------------------------------------------------===// +/// This class is used to track label information. +/// +/// Labels are collected from \c DBG_LABEL instructions. +class DbgLabel : public DbgEntity { + const MCSymbol *Sym; /// Symbol before DBG_LABEL instruction. + +public: + /// We need MCSymbol information to generate DW_AT_low_pc. + DbgLabel(const DILabel *L, const DILocation *IA, const MCSymbol *Sym = nullptr) + : DbgEntity(L, IA, DbgLabelKind), Sym(Sym) {} + + /// Accessors. + /// @{ + const DILabel *getLabel() const { return cast<DILabel>(getEntity()); } + const MCSymbol *getSymbol() const { return Sym; } + + StringRef getName() const { return getLabel()->getName(); } + /// @} + + /// Translate tag to proper Dwarf tag. + dwarf::Tag getTag() const { + return dwarf::DW_TAG_label; + } + + static bool classof(const DbgEntity *N) { + return N->getDbgEntityID() == DbgLabelKind; + } + private: template <typename T> T *resolve(TypedDINodeRef<T> Ref) const { return Ref.resolve(); @@ -217,8 +294,8 @@ class DwarfDebug : public DebugHandlerBase { /// Size of each symbol emitted (for those symbols that have a specific size). DenseMap<const MCSymbol *, uint64_t> SymSize; - /// Collection of abstract variables. - SmallVector<std::unique_ptr<DbgVariable>, 64> ConcreteVariables; + /// Collection of abstract variables/labels. + SmallVector<std::unique_ptr<DbgEntity>, 64> ConcreteEntities; /// Collection of DebugLocEntry. Stored in a linked list so that DIELocLists /// can refer to them in spite of insertions into this list. @@ -333,14 +410,20 @@ class DwarfDebug : public DebugHandlerBase { } using InlinedVariable = DbgValueHistoryMap::InlinedVariable; + using InlinedLabel = DbgLabelInstrMap::InlinedLabel; - void ensureAbstractVariableIsCreated(DwarfCompileUnit &CU, InlinedVariable IV, - const MDNode *Scope); - void ensureAbstractVariableIsCreatedIfScoped(DwarfCompileUnit &CU, InlinedVariable IV, - const MDNode *Scope); + void ensureAbstractEntityIsCreated(DwarfCompileUnit &CU, + const DINode *Node, + const MDNode *Scope); + void ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU, + const DINode *Node, + const MDNode *Scope); - DbgVariable *createConcreteVariable(DwarfCompileUnit &TheCU, - LexicalScope &Scope, InlinedVariable IV); + DbgEntity *createConcreteEntity(DwarfCompileUnit &TheCU, + LexicalScope &Scope, + const DINode *Node, + const DILocation *Location, + const MCSymbol *Sym = nullptr); /// Construct a DIE for this abstract scope. void constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, LexicalScope *Scope); @@ -349,7 +432,7 @@ class DwarfDebug : public DebugHandlerBase { void addAccelNameImpl(AccelTable<DataT> &AppleAccel, StringRef Name, const DIE &Die); - void finishVariableDefinitions(); + void finishEntityDefinitions(); void finishSubprogramDefinitions(); @@ -469,8 +552,8 @@ class DwarfDebug : public DebugHandlerBase { unsigned Flags); /// Populate LexicalScope entries with variables' info. - void collectVariableInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP, - DenseSet<InlinedVariable> &ProcessedVars); + void collectEntityInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP, + DenseSet<InlinedVariable> &ProcessedVars); /// Build the location list for all DBG_VALUEs in the /// function that describe the same variable. |