diff options
Diffstat (limited to 'contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h')
-rw-r--r-- | contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 626 |
1 files changed, 626 insertions, 0 deletions
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h new file mode 100644 index 0000000..700f736 --- /dev/null +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -0,0 +1,626 @@ +//===-- llvm/CodeGen/DwarfDebug.h - Dwarf Debug Framework ------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf debug info into asm files. +// +//===----------------------------------------------------------------------===// + +#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; + +//===----------------------------------------------------------------------===// +/// \brief This class is used to record source line correspondence. +class SrcLineInfo { + unsigned Line; // Source line number. + unsigned Column; // Source column. + unsigned SourceID; // Source ID number. + MCSymbol *Label; // Label in code ID number. +public: + SrcLineInfo(unsigned L, unsigned C, unsigned S, MCSymbol *label) + : Line(L), Column(C), SourceID(S), Label(label) {} + + // Accessors + unsigned getLine() const { return Line; } + unsigned getColumn() const { return Column; } + unsigned getSourceID() const { return SourceID; } + MCSymbol *getLabel() const { return Label; } +}; + +//===----------------------------------------------------------------------===// +/// \brief This class is used to track local variable information. +/// +/// - Variables whose location changes over time have a DebugLocListIndex and +/// the other fields are not used. +/// +/// - Variables that are described by multiple MMI table entries have multiple +/// expressions and frame indices. +class DbgVariable { + const DILocalVariable *Var; /// Variable Descriptor. + const DILocation *IA; /// Inlined at location. + SmallVector<const DIExpression *, 1> + Expr; /// Complex address location expression. + DIE *TheDIE; /// Variable DIE. + unsigned DebugLocListIndex; /// Offset in DebugLocs. + const MachineInstr *MInsn; /// DBG_VALUE instruction of the variable. + SmallVector<int, 1> FrameIndex; /// Frame index of the variable. + DwarfDebug *DD; + +public: + /// Construct a DbgVariable from a variable. + 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()); + } + + /// Construct a DbgVariable from a DEBUG_VALUE. + /// AbstractVar may be NULL. + 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); + } + + // Accessors. + 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")); + } + + // Translate tag to proper Dwarf tag. + dwarf::Tag getTag() const { + if (Var->getTag() == dwarf::DW_TAG_arg_variable) + return dwarf::DW_TAG_formal_parameter; + + return dwarf::DW_TAG_variable; + } + /// \brief Return true if DbgVariable is artificial. + 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: + /// resolve - Look in the DwarfDebug map for the MDNode that + /// corresponds to the reference. + template <typename T> T *resolve(TypedDINodeRef<T> Ref) const; +}; + + +/// \brief Helper used to pair up a symbol and its DWARF compile unit. +struct SymbolCU { + SymbolCU(DwarfCompileUnit *CU, const MCSymbol *Sym) : Sym(Sym), CU(CU) {} + const MCSymbol *Sym; + DwarfCompileUnit *CU; +}; + +/// \brief Collects and handles dwarf debug information. +class DwarfDebug : public AsmPrinterHandler { + // Target of Dwarf emission. + AsmPrinter *Asm; + + // Collected machine module information. + MachineModuleInfo *MMI; + + // All DIEValues are allocated through this allocator. + BumpPtrAllocator DIEValueAllocator; + + // Maps MDNode with its corresponding DwarfCompileUnit. + MapVector<const MDNode *, DwarfCompileUnit *> CUMap; + + // Maps subprogram MDNode with its corresponding DwarfCompileUnit. + MapVector<const MDNode *, DwarfCompileUnit *> SPMap; + + // Maps a CU DIE with its corresponding DwarfCompileUnit. + DenseMap<const DIE *, DwarfCompileUnit *> CUDieMap; + + // List of all labels used in aranges generation. + std::vector<SymbolCU> ArangeLabels; + + // Size of each symbol emitted (for those symbols that have a specific size). + DenseMap<const MCSymbol *, uint64_t> SymSize; + + LexicalScopes LScopes; + + // Collection of abstract variables. + DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> AbstractVariables; + SmallVector<std::unique_ptr<DbgVariable>, 64> ConcreteVariables; + + // Collection of DebugLocEntry. Stored in a linked list so that DIELocLists + // can refer to them in spite of insertions into this list. + DebugLocStream DebugLocs; + + // This is a collection of subprogram MDNodes that are processed to + // create DIEs. + SmallPtrSet<const MDNode *, 16> ProcessedSPNodes; + + // Maps instruction with label emitted before instruction. + DenseMap<const MachineInstr *, MCSymbol *> LabelsBeforeInsn; + + // Maps instruction with label emitted after instruction. + DenseMap<const MachineInstr *, MCSymbol *> LabelsAfterInsn; + + // History of DBG_VALUE and clobber instructions for each user variable. + // Variables are listed in order of appearance. + DbgValueHistoryMap DbgValues; + + // Previous instruction's location information. This is used to determine + // label location to indicate scope boundries in dwarf debug info. + DebugLoc PrevInstLoc; + MCSymbol *PrevLabel; + + // This location indicates end of function prologue and beginning of function + // body. + DebugLoc PrologEndLoc; + + // If nonnull, stores the current machine function we're processing. + const MachineFunction *CurFn; + + // If nonnull, stores the current machine instruction we're processing. + const MachineInstr *CurMI; + + // If nonnull, stores the CU in which the previous subprogram was contained. + const DwarfCompileUnit *PrevCU; + + // As an optimization, there is no need to emit an entry in the directory + // table for the same directory as DW_AT_comp_dir. + StringRef CompilationDir; + + // Holder for the file specific debug information. + DwarfFile InfoHolder; + + // Holders for the various debug information flags that we might need to + // have exposed. See accessor functions below for description. + + // Holder for imported entities. + typedef SmallVector<std::pair<const MDNode *, const MDNode *>, 32> + ImportedEntityMap; + ImportedEntityMap ScopesWithImportedEntities; + + // Map from MDNodes for user-defined types to the type units that describe + // them. + DenseMap<const MDNode *, const DwarfTypeUnit *> DwarfTypeUnits; + + SmallVector< + std::pair<std::unique_ptr<DwarfTypeUnit>, const DICompositeType *>, 1> + TypeUnitsUnderConstruction; + + // Whether to emit the pubnames/pubtypes sections. + bool HasDwarfPubSections; + + // Whether or not to use AT_ranges for compilation units. + bool HasCURanges; + + // Whether we emitted a function into a section other than the default + // text. + bool UsedNonDefaultText; + + // Whether to use the GNU TLS opcode (instead of the standard opcode). + bool UseGNUTLSOpcode; + + // Version of dwarf we're emitting. + unsigned DwarfVersion; + + // Maps from a type identifier to the actual MDNode. + DITypeIdentifierMap TypeIdentifierMap; + + // DWARF5 Experimental Options + bool HasDwarfAccelTables; + bool HasSplitDwarf; + + // Separated Dwarf Variables + // In general these will all be for bits that are left in the + // original object file, rather than things that are meant + // to be in the .dwo sections. + + // Holder for the skeleton information. + DwarfFile SkeletonHolder; + + /// Store file names for type units under fission in a line table header that + /// will be emitted into debug_line.dwo. + // FIXME: replace this with a map from comp_dir to table so that we can emit + // multiple tables during LTO each of which uses directory 0, referencing the + // comp_dir of all the type units that use it. + MCDwarfDwoLineTable SplitTypeUnitFileTable; + + // True iff there are multiple CUs in this module. + bool SingleCU; + bool IsDarwin; + bool IsPS4; + + AddressPool AddrPool; + + DwarfAccelTable AccelNames; + DwarfAccelTable AccelObjC; + DwarfAccelTable AccelNamespace; + DwarfAccelTable AccelTypes; + + DenseMap<const Function *, DISubprogram *> FunctionDIs; + + MCDwarfDwoLineTable *getDwoLineTable(const DwarfCompileUnit &); + + const SmallVectorImpl<std::unique_ptr<DwarfUnit>> &getUnits() { + return InfoHolder.getUnits(); + } + + typedef DbgValueHistoryMap::InlinedVariable InlinedVariable; + + /// \brief Find abstract variable associated with Var. + 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); + + /// \brief Construct a DIE for this abstract scope. + void constructAbstractSubprogramScopeDIE(LexicalScope *Scope); + + /// \brief Compute the size and offset of a DIE given an incoming Offset. + unsigned computeSizeAndOffset(DIE *Die, unsigned Offset); + + /// \brief Compute the size and offset of all the DIEs. + void computeSizeAndOffsets(); + + /// \brief Collect info for variables that were optimized out. + void collectDeadVariables(); + + void finishVariableDefinitions(); + + void finishSubprogramDefinitions(); + + /// \brief Finish off debug information after all functions have been + /// processed. + void finalizeModuleInfo(); + + /// \brief Emit the debug info section. + void emitDebugInfo(); + + /// \brief Emit the abbreviation section. + void emitAbbreviations(); + + /// \brief Emit a specified accelerator table. + void emitAccel(DwarfAccelTable &Accel, MCSection *Section, + StringRef TableName); + + /// \brief Emit visible names into a hashed accelerator table section. + void emitAccelNames(); + + /// \brief Emit objective C classes and categories into a hashed + /// accelerator table section. + void emitAccelObjC(); + + /// \brief Emit namespace dies into a hashed accelerator table. + void emitAccelNamespaces(); + + /// \brief Emit type dies into a hashed accelerator table. + void emitAccelTypes(); + + /// \brief Emit visible names into a debug pubnames section. + /// \param GnuStyle determines whether or not we want to emit + /// additional information into the table ala newer gcc for gdb + /// index. + void emitDebugPubNames(bool GnuStyle = false); + + /// \brief Emit visible types into a debug pubtypes section. + /// \param GnuStyle determines whether or not we want to emit + /// additional information into the table ala newer gcc for gdb + /// index. + void emitDebugPubTypes(bool GnuStyle = false); + + void emitDebugPubSection( + bool GnuStyle, MCSection *PSec, StringRef Name, + const StringMap<const DIE *> &(DwarfCompileUnit::*Accessor)() const); + + /// \brief Emit visible names into a debug str section. + void emitDebugStr(); + + /// \brief Emit visible names into a debug loc section. + void emitDebugLoc(); + + /// \brief Emit visible names into a debug loc dwo section. + void emitDebugLocDWO(); + + /// \brief Emit visible names into a debug aranges section. + void emitDebugARanges(); + + /// \brief Emit visible names into a debug ranges section. + void emitDebugRanges(); + + /// \brief Emit inline info using custom format. + void emitDebugInlineInfo(); + + /// DWARF 5 Experimental Split Dwarf Emitters + + /// \brief Initialize common features of skeleton units. + void initSkeletonUnit(const DwarfUnit &U, DIE &Die, + std::unique_ptr<DwarfUnit> NewU); + + /// \brief Construct the split debug info compile unit for the debug info + /// section. + DwarfCompileUnit &constructSkeletonCU(const DwarfCompileUnit &CU); + + /// \brief Construct the split debug info compile unit for the debug info + /// section. + DwarfTypeUnit &constructSkeletonTU(DwarfTypeUnit &TU); + + /// \brief Emit the debug info dwo section. + void emitDebugInfoDWO(); + + /// \brief Emit the debug abbrev dwo section. + void emitDebugAbbrevDWO(); + + /// \brief Emit the debug line dwo section. + void emitDebugLineDWO(); + + /// \brief Emit the debug str dwo section. + void emitDebugStrDWO(); + + /// Flags to let the linker know we have emitted new style pubnames. Only + /// emit it here if we don't have a skeleton CU for split dwarf. + void addGnuPubAttributes(DwarfUnit &U, DIE &D) const; + + /// \brief Create new DwarfCompileUnit for the given metadata node with tag + /// DW_TAG_compile_unit. + DwarfCompileUnit &constructDwarfCompileUnit(const DICompileUnit *DIUnit); + + /// \brief Construct imported_module or imported_declaration DIE. + void constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, + const DIImportedEntity *N); + + /// \brief Register a source line with debug info. Returns the unique + /// label that was emitted and which provides correspondence to the + /// source line list. + void recordSourceLine(unsigned Line, unsigned Col, const MDNode *Scope, + unsigned Flags); + + /// \brief Indentify instructions that are marking the beginning of or + /// ending of a scope. + void identifyScopeMarkers(); + + /// \brief Populate LexicalScope entries with variables' info. + void collectVariableInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP, + DenseSet<InlinedVariable> &ProcessedVars); + + /// \brief Build the location list for all DBG_VALUEs in the + /// function that describe the same variable. + void buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, + const DbgValueHistoryMap::InstrRanges &Ranges); + + /// \brief Collect variable information from the side table maintained + /// by MMI. + void collectVariableInfoFromMMITable(DenseSet<InlinedVariable> &P); + + /// \brief Ensure that a label will be emitted before MI. + void requestLabelBeforeInsn(const MachineInstr *MI) { + LabelsBeforeInsn.insert(std::make_pair(MI, nullptr)); + } + + /// \brief Ensure that a label will be emitted after MI. + void requestLabelAfterInsn(const MachineInstr *MI) { + LabelsAfterInsn.insert(std::make_pair(MI, nullptr)); + } + +public: + //===--------------------------------------------------------------------===// + // Main entry points. + // + DwarfDebug(AsmPrinter *A, Module *M); + + ~DwarfDebug() override; + + /// \brief Emit all Dwarf sections that should come prior to the + /// content. + void beginModule(); + + /// \brief Emit all Dwarf sections that should come after the content. + void endModule() override; + + /// \brief Gather pre-function debug information. + void beginFunction(const MachineFunction *MF) override; + + /// \brief Gather and emit post-function debug information. + void endFunction(const MachineFunction *MF) override; + + /// \brief Process beginning of an instruction. + void beginInstruction(const MachineInstr *MI) override; + + /// \brief Process end of an instruction. + void endInstruction() override; + + /// \brief Add a DIE to the set of types that we're going to pull into + /// type units. + void addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier, + DIE &Die, const DICompositeType *CTy); + + /// \brief Add a label so that arange data can be generated for it. + void addArangeLabel(SymbolCU SCU) { ArangeLabels.push_back(SCU); } + + /// \brief For symbols that have a size designated (e.g. common symbols), + /// this tracks that size. + void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override { + SymSize[Sym] = Size; + } + + /// \brief Returns whether to use DW_OP_GNU_push_tls_address, instead of the + /// standard DW_OP_form_tls_address opcode + bool useGNUTLSOpcode() const { return UseGNUTLSOpcode; } + + // Experimental DWARF5 features. + + /// \brief Returns whether or not to emit tables that dwarf consumers can + /// use to accelerate lookup. + bool useDwarfAccelTables() const { return HasDwarfAccelTables; } + + /// \brief Returns whether or not to change the current debug info for the + /// split dwarf proposal support. + bool useSplitDwarf() const { return HasSplitDwarf; } + + /// Returns the Dwarf Version. + unsigned getDwarfVersion() const { return DwarfVersion; } + + /// Returns the previous CU that was being updated + const DwarfCompileUnit *getPrevCU() const { return PrevCU; } + void setPrevCU(const DwarfCompileUnit *PrevCU) { this->PrevCU = PrevCU; } + + /// Returns the entries for the .debug_loc section. + const DebugLocStream &getDebugLocs() const { return DebugLocs; } + + /// \brief Emit an entry for the debug loc section. This can be used to + /// handle an entry that's going to be emitted into the debug loc section. + void emitDebugLocEntry(ByteStreamer &Streamer, + const DebugLocStream::Entry &Entry); + + /// Emit the location for a debug loc entry, including the size header. + void emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry); + + /// Find the MDNode for the given reference. + template <typename T> T *resolve(TypedDINodeRef<T> Ref) const { + return Ref.resolve(TypeIdentifierMap); + } + + /// \brief Return the TypeIdentifierMap. + const DITypeIdentifierMap &getTypeIdentifierMap() const { + return TypeIdentifierMap; + } + + /// Find the DwarfCompileUnit for the given CU Die. + DwarfCompileUnit *lookupUnit(const DIE *CU) const { + return CUDieMap.lookup(CU); + } + /// isSubprogramContext - Return true if Context is either a subprogram + /// or another context nested inside a subprogram. + 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); + + 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())); + } + + /// \brief A helper function to check whether the DIE for a given Scope is + /// going to be null. + bool isLexicalScopeDIENull(LexicalScope *Scope); + + /// \brief Return Label preceding the instruction. + MCSymbol *getLabelBeforeInsn(const MachineInstr *MI); + + /// \brief Return Label immediately following the instruction. + MCSymbol *getLabelAfterInsn(const MachineInstr *MI); + + // FIXME: Sink these functions down into DwarfFile/Dwarf*Unit. + + SmallPtrSet<const MDNode *, 16> &getProcessedSPNodes() { + return ProcessedSPNodes; + } +}; +} // End of namespace llvm + +#endif |