diff options
Diffstat (limited to 'include/llvm/IR/DebugInfo.h')
-rw-r--r-- | include/llvm/IR/DebugInfo.h | 293 |
1 files changed, 190 insertions, 103 deletions
diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 22a2138..d2e5975 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -18,11 +18,11 @@ #define LLVM_IR_DEBUGINFO_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/IR/Metadata.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" @@ -66,10 +66,10 @@ class DIHeaderFieldIterator public: DIHeaderFieldIterator() {} - DIHeaderFieldIterator(StringRef Header) + explicit DIHeaderFieldIterator(StringRef Header) : Header(Header), Current(Header.slice(0, Header.find('\0'))) {} StringRef operator*() const { return Current; } - const StringRef * operator->() const { return &Current; } + const StringRef *operator->() const { return &Current; } DIHeaderFieldIterator &operator++() { increment(); return *this; @@ -99,6 +99,16 @@ public: return Header.slice(Current.end() - Header.begin() + 1, StringRef::npos); } + /// \brief Get the current field as a number. + /// + /// Convert the current field into a number. Return \c 0 on error. + template <class T> T getNumber() const { + T Int; + if (getCurrent().getAsInteger(0, Int)) + return 0; + return Int; + } + private: void increment() { assert(Current.data() != nullptr && "Cannot increment past the end"); @@ -122,27 +132,21 @@ public: /// The three accessibility flags are mutually exclusive and rolled together /// in the first two bits. enum { - FlagAccessibility = 1 << 0 | 1 << 1, - FlagPrivate = 1, - FlagProtected = 2, - FlagPublic = 3, - - FlagFwdDecl = 1 << 2, - FlagAppleBlock = 1 << 3, - FlagBlockByrefStruct = 1 << 4, - FlagVirtual = 1 << 5, - FlagArtificial = 1 << 6, - FlagExplicit = 1 << 7, - FlagPrototyped = 1 << 8, - FlagObjcClassComplete = 1 << 9, - FlagObjectPointer = 1 << 10, - FlagVector = 1 << 11, - FlagStaticMember = 1 << 12, - FlagIndirectVariable = 1 << 13, - FlagLValueReference = 1 << 14, - FlagRValueReference = 1 << 15 +#define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, +#include "llvm/IR/DebugInfoFlags.def" + FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic }; + static unsigned getFlag(StringRef Flag); + static const char *getFlagString(unsigned Flag); + + /// \brief Split up a flags bitfield. + /// + /// Split \c Flags into \c SplitFlags, a vector of its components. Returns + /// any remaining (unrecognized) bits. + static unsigned splitFlags(unsigned Flags, + SmallVectorImpl<unsigned> &SplitFlags); + protected: const MDNode *DbgNode; @@ -168,42 +172,47 @@ public: bool Verify() const; - operator MDNode *() const { return const_cast<MDNode *>(DbgNode); } - MDNode *operator->() const { return const_cast<MDNode *>(DbgNode); } + MDNode *get() const { return const_cast<MDNode *>(DbgNode); } + operator MDNode *() const { return get(); } + MDNode *operator->() const { return get(); } // An explicit operator bool so that we can do testing of DI values // easily. // FIXME: This operator bool isn't actually protecting anything at the // moment due to the conversion operator above making DIDescriptor nodes // implicitly convertable to bool. - LLVM_EXPLICIT operator bool() const { return DbgNode != nullptr; } + explicit operator bool() const { return DbgNode != nullptr; } bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; } bool operator!=(DIDescriptor Other) const { return !operator==(Other); } - StringRef getHeader() const { - return getStringField(0); - } + StringRef getHeader() const { return getStringField(0); } size_t getNumHeaderFields() const { return std::distance(DIHeaderFieldIterator(getHeader()), DIHeaderFieldIterator()); } - StringRef getHeaderField(unsigned Index) const { + DIHeaderFieldIterator header_begin() const { + return DIHeaderFieldIterator(getHeader()); + } + DIHeaderFieldIterator header_end() const { return DIHeaderFieldIterator(); } + + DIHeaderFieldIterator getHeaderIterator(unsigned Index) const { // Since callers expect an empty string for out-of-range accesses, we can't // use std::advance() here. - for (DIHeaderFieldIterator I(getHeader()), E; I != E; ++I, --Index) + for (auto I = header_begin(), E = header_end(); I != E; ++I, --Index) if (!Index) - return *I; - return StringRef(); + return I; + return header_end(); + } + + StringRef getHeaderField(unsigned Index) const { + return *getHeaderIterator(Index); } template <class T> T getHeaderFieldAs(unsigned Index) const { - T Int; - if (getHeaderField(Index).getAsInteger(0, Int)) - return 0; - return Int; + return getHeaderIterator(Index).getNumber<T>(); } uint16_t getTag() const { return getHeaderFieldAs<uint16_t>(0); } @@ -238,6 +247,19 @@ public: void replaceAllUsesWith(MDNode *D); }; +#define RETURN_FROM_RAW(VALID, DEFAULT) \ + do { \ + if (auto *N = getRaw()) \ + return VALID; \ + return DEFAULT; \ + } while (false) +#define RETURN_DESCRIPTOR_FROM_RAW(DESC, VALID) \ + do { \ + if (auto *N = getRaw()) \ + return DESC(dyn_cast_or_null<MDNode>(VALID)); \ + return DESC(static_cast<const MDNode *>(nullptr)); \ + } while (false) + /// \brief This is used to represent ranges, for array bounds. class DISubrange : public DIDescriptor { friend class DIDescriptor; @@ -258,9 +280,7 @@ public: unsigned getNumElements() const { return DbgNode ? DbgNode->getNumOperands() : 0; } - T getElement(unsigned Idx) const { - return getFieldAs<T>(Idx); - } + T getElement(unsigned Idx) const { return getFieldAs<T>(Idx); } }; typedef DITypedArray<DIDescriptor> DIArray; @@ -282,6 +302,7 @@ public: }; template <typename T> class DIRef; +typedef DIRef<DIDescriptor> DIDescriptorRef; typedef DIRef<DIScope> DIScopeRef; typedef DIRef<DIType> DITypeRef; typedef DITypedArray<DITypeRef> DITypeArray; @@ -371,6 +392,12 @@ template <typename T> StringRef DIRef<T>::getName() const { return MS->getString(); } +/// \brief Handle fields that are references to DIDescriptors. +template <> +DIDescriptorRef DIDescriptor::getFieldAs<DIDescriptorRef>(unsigned Elt) const; +/// \brief Specialize DIRef constructor for DIDescriptorRef. +template <> DIRef<DIDescriptor>::DIRef(const Metadata *V); + /// \brief Handle fields that are references to DIScopes. template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const; /// \brief Specialize DIRef constructor for DIScopeRef. @@ -381,7 +408,7 @@ template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const; /// \brief Specialize DIRef constructor for DITypeRef. template <> DIRef<DIType>::DIRef(const Metadata *V); -/// \briefThis is a wrapper for a type. +/// \brief This is a wrapper for a type. /// /// FIXME: Types should be factored much better so that CV qualifiers and /// others do not require a huge and empty descriptor full of zeros. @@ -392,7 +419,7 @@ protected: public: explicit DIType(const MDNode *N = nullptr) : DIScope(N) {} - operator DITypeRef () const { + operator DITypeRef() const { assert(isType() && "constructing DITypeRef from an MDNode that is not a type"); return DITypeRef(&*getRef()); @@ -402,20 +429,12 @@ public: DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { - return getHeaderFieldAs<unsigned>(2); - } - uint64_t getSizeInBits() const { - return getHeaderFieldAs<unsigned>(3); - } - uint64_t getAlignInBits() const { - return getHeaderFieldAs<unsigned>(4); - } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } + uint64_t getSizeInBits() const { return getHeaderFieldAs<unsigned>(3); } + uint64_t getAlignInBits() const { return getHeaderFieldAs<unsigned>(4); } // FIXME: Offset is only used for DW_TAG_member nodes. Making every type // carry this is just plain insane. - uint64_t getOffsetInBits() const { - return getHeaderFieldAs<unsigned>(5); - } + uint64_t getOffsetInBits() const { return getHeaderFieldAs<unsigned>(5); } unsigned getFlags() const { return getHeaderFieldAs<unsigned>(6); } bool isPrivate() const { return (getFlags() & FlagAccessibility) == FlagPrivate; @@ -499,6 +518,7 @@ public: // FIXME: Make this derive from DIType directly & just store the // base type in a single DIType field. class DICompositeType : public DIDerivedType { + friend class DIBuilder; friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -512,20 +532,26 @@ public: assert(!isSubroutineType() && "no elements for DISubroutineType"); return getFieldAs<DIArray>(4); } + +private: template <typename T> void setArrays(DITypedArray<T> Elements, DIArray TParams = DIArray()) { - assert((!TParams || DbgNode->getNumOperands() == 8) && - "If you're setting the template parameters this should include a slot " - "for that!"); + assert( + (!TParams || DbgNode->getNumOperands() == 8) && + "If you're setting the template parameters this should include a slot " + "for that!"); setArraysHelper(Elements, TParams); } - unsigned getRunTimeLang() const { - return getHeaderFieldAs<unsigned>(7); - } + +public: + unsigned getRunTimeLang() const { return getHeaderFieldAs<unsigned>(7); } DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(5); } +private: /// \brief Set the containing type. void setContainingType(DICompositeType ContainingType); + +public: DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); } MDString *getIdentifier() const; @@ -663,7 +689,6 @@ public: unsigned isRValueReference() const { return (getFlags() & FlagRValueReference) != 0; } - }; /// \brief This is a wrapper for a lexical block. @@ -671,12 +696,8 @@ class DILexicalBlock : public DIScope { public: explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {} DIScope getContext() const { return getFieldAs<DIScope>(2); } - unsigned getLineNumber() const { - return getHeaderFieldAs<unsigned>(1); - } - unsigned getColumnNumber() const { - return getHeaderFieldAs<unsigned>(2); - } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); } + unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(2); } bool Verify() const; }; @@ -685,6 +706,8 @@ class DILexicalBlockFile : public DIScope { public: explicit DILexicalBlockFile(const MDNode *N = nullptr) : DIScope(N) {} DIScope getContext() const { + // FIXME: This logic is horrible. getScope() returns a DILexicalBlock, but + // then we check if it's a subprogram? WHAT?!? if (getScope().isSubprogram()) return getScope(); return getScope().getContext(); @@ -713,18 +736,11 @@ public: class DITemplateTypeParameter : public DIDescriptor { public: explicit DITemplateTypeParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} + : DIDescriptor(N) {} StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } - unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); } - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } DITypeRef getType() const { return getFieldAs<DITypeRef>(2); } - StringRef getFilename() const { return getFieldAs<DIFile>(3).getFilename(); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(3).getDirectory(); - } bool Verify() const; }; @@ -732,19 +748,12 @@ public: class DITemplateValueParameter : public DIDescriptor { public: explicit DITemplateValueParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} + : DIDescriptor(N) {} StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } - unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); } - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } DITypeRef getType() const { return getFieldAs<DITypeRef>(2); } - Value *getValue() const; - StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(4).getDirectory(); - } + Metadata *getValue() const; bool Verify() const; }; @@ -763,7 +772,7 @@ public: unsigned isLocalToUnit() const { return getHeaderFieldAs<bool>(5); } unsigned isDefinition() const { return getHeaderFieldAs<bool>(6); } - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } + DIScope getContext() const { return getFieldAs<DIScope>(1); } StringRef getFilename() const { return getFieldAs<DIFile>(2).getFilename(); } StringRef getDirectory() const { return getFieldAs<DIFile>(2).getDirectory(); @@ -807,11 +816,6 @@ public: return (getHeaderFieldAs<unsigned>(3) & FlagObjectPointer) != 0; } - /// \brief Return true if this variable is represented as a pointer. - bool isIndirect() const { - return (getHeaderFieldAs<unsigned>(3) & FlagIndirectVariable) != 0; - } - /// \brief If this variable is inlined then return inline location. MDNode *getInlinedAt() const; @@ -831,7 +835,13 @@ public: void printExtendedName(raw_ostream &OS) const; }; -/// \brief A complex location expression. +/// \brief A complex location expression in postfix notation. +/// +/// This is (almost) a DWARF expression that modifies the location of a +/// variable or (or the location of a single piece of a variable). +/// +/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const +/// and have DW_OP_plus consume the topmost elements on the stack. class DIExpression : public DIDescriptor { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -854,24 +864,91 @@ public: uint64_t getElement(unsigned Idx) const; /// \brief Return whether this is a piece of an aggregate variable. - bool isVariablePiece() const; - /// \brief Return the offset of this piece in bytes. - uint64_t getPieceOffset() const; - /// \brief Return the size of this piece in bytes. - uint64_t getPieceSize() const; + bool isBitPiece() const; + /// \brief Return the offset of this piece in bits. + uint64_t getBitPieceOffset() const; + /// \brief Return the size of this piece in bits. + uint64_t getBitPieceSize() const; + + class iterator; + /// \brief A lightweight wrapper around an element of a DIExpression. + class Operand { + friend class iterator; + DIHeaderFieldIterator I; + Operand() {} + Operand(DIHeaderFieldIterator I) : I(I) {} + public: + /// \brief Operands such as DW_OP_piece have explicit (non-stack) arguments. + /// Argument 0 is the operand itself. + uint64_t getArg(unsigned N) const { + DIHeaderFieldIterator In = I; + std::advance(In, N); + return In.getNumber<uint64_t>(); + } + operator uint64_t () const { return I.getNumber<uint64_t>(); } + /// \brief Returns underlying DIHeaderFieldIterator. + const DIHeaderFieldIterator &getBase() const { return I; } + /// \brief Returns the next operand. + Operand getNext() const; + }; + + /// \brief An iterator for DIExpression elements. + class iterator : public std::iterator<std::input_iterator_tag, StringRef, + unsigned, const Operand*, Operand> { + friend class Operand; + DIHeaderFieldIterator I; + Operand Tmp; + iterator(DIHeaderFieldIterator I) : I(I) {} + public: + iterator() {} + iterator(const DIExpression &Expr) : I(++Expr.header_begin()) {} + const Operand &operator*() { return Tmp = Operand(I); } + const Operand *operator->() { return &(Tmp = Operand(I)); } + iterator &operator++() { + increment(); + return *this; + } + iterator operator++(int) { + iterator X(*this); + increment(); + return X; + } + bool operator==(const iterator &X) const { return I == X.I; } + bool operator!=(const iterator &X) const { return !(*this == X); } + + private: + void increment() { + switch (**this) { + case dwarf::DW_OP_bit_piece: std::advance(I, 3); break; + case dwarf::DW_OP_plus: std::advance(I, 2); break; + case dwarf::DW_OP_deref: std::advance(I, 1); break; + default: + llvm_unreachable("unsupported operand"); + } + } + }; + + iterator begin() const; + iterator end() const; }; /// \brief This object holds location information. /// /// This object is not associated with any DWARF tag. class DILocation : public DIDescriptor { + MDLocation *getRaw() const { return dyn_cast_or_null<MDLocation>(get()); } + public: explicit DILocation(const MDNode *N) : DIDescriptor(N) {} - unsigned getLineNumber() const { return getUnsignedField(0); } - unsigned getColumnNumber() const { return getUnsignedField(1); } - DIScope getScope() const { return getFieldAs<DIScope>(2); } - DILocation getOrigLocation() const { return getFieldAs<DILocation>(3); } + unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } + unsigned getColumnNumber() const { RETURN_FROM_RAW(N->getColumn(), 0); } + DIScope getScope() const { + RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); + } + DILocation getOrigLocation() const { + RETURN_DESCRIPTOR_FROM_RAW(DILocation, N->getInlinedAt()); + } StringRef getFilename() const { return getScope().getFilename(); } StringRef getDirectory() const { return getScope().getDirectory(); } bool Verify() const; @@ -892,7 +969,9 @@ public: // sure this location is a lexical block before retrieving its // value. return getScope().isLexicalBlockFile() - ? getFieldAs<DILexicalBlockFile>(2).getDiscriminator() + ? DILexicalBlockFile( + cast<MDNode>(cast<MDLocation>(DbgNode)->getScope())) + .getDiscriminator() : 0; } @@ -951,14 +1030,18 @@ class DIImportedEntity : public DIDescriptor { void printInternal(raw_ostream &OS) const; public: + DIImportedEntity() = default; explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} DIScope getContext() const { return getFieldAs<DIScope>(1); } - DIScopeRef getEntity() const { return getFieldAs<DIScopeRef>(2); } + DIDescriptorRef getEntity() const { return getFieldAs<DIDescriptorRef>(2); } unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); } StringRef getName() const { return getHeaderField(2); } bool Verify() const; }; +#undef RETURN_FROM_RAW +#undef RETURN_DESCRIPTOR_FROM_RAW + /// \brief Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); @@ -1015,6 +1098,9 @@ public: /// \brief Process DILocation. void processLocation(const Module &M, DILocation Loc); + /// \brief Process DIExpression. + void processExpression(DIExpression Expr); + /// \brief Clear all lists. void reset(); @@ -1033,7 +1119,8 @@ private: public: typedef SmallVectorImpl<DICompileUnit>::const_iterator compile_unit_iterator; typedef SmallVectorImpl<DISubprogram>::const_iterator subprogram_iterator; - typedef SmallVectorImpl<DIGlobalVariable>::const_iterator global_variable_iterator; + typedef SmallVectorImpl<DIGlobalVariable>::const_iterator + global_variable_iterator; typedef SmallVectorImpl<DIType>::const_iterator type_iterator; typedef SmallVectorImpl<DIScope>::const_iterator scope_iterator; |