Mercurial > hg > CbC > CbC_llvm
diff include/llvm/IR/DebugInfo.h @ 83:60c9769439b8 LLVM3.7
LLVM 3.7
author | Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 18 Feb 2015 14:55:36 +0900 |
parents | 54457678186b |
children | afa8332a0e37 |
line wrap: on
line diff
--- a/include/llvm/IR/DebugInfo.h Mon Sep 08 22:07:30 2014 +0900 +++ b/include/llvm/IR/DebugInfo.h Wed Feb 18 14:55:36 2015 +0900 @@ -18,13 +18,15 @@ #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" +#include <iterator> namespace llvm { class BasicBlock; @@ -37,6 +39,7 @@ class DbgDeclareInst; class DbgValueInst; class Instruction; +class Metadata; class MDNode; class MDString; class NamedMDNode; @@ -52,20 +55,82 @@ class DIScope; class DIObjCProperty; -/// Maps from type identifier to the actual MDNode. +/// \brief Maps from type identifier to the actual MDNode. typedef DenseMap<const MDString *, MDNode *> DITypeIdentifierMap; -/// DIDescriptor - A thin wraper around MDNode to access encoded debug info. -/// This should not be stored in a container, because the underlying MDNode -/// may change in certain situations. +class DIHeaderFieldIterator + : public std::iterator<std::input_iterator_tag, StringRef, std::ptrdiff_t, + const StringRef *, StringRef> { + StringRef Header; + StringRef Current; + +public: + DIHeaderFieldIterator() {} + explicit DIHeaderFieldIterator(StringRef Header) + : Header(Header), Current(Header.slice(0, Header.find('\0'))) {} + StringRef operator*() const { return Current; } + const StringRef *operator->() const { return &Current; } + DIHeaderFieldIterator &operator++() { + increment(); + return *this; + } + DIHeaderFieldIterator operator++(int) { + DIHeaderFieldIterator X(*this); + increment(); + return X; + } + bool operator==(const DIHeaderFieldIterator &X) const { + return Current.data() == X.Current.data(); + } + bool operator!=(const DIHeaderFieldIterator &X) const { + return !(*this == X); + } + + StringRef getHeader() const { return Header; } + StringRef getCurrent() const { return Current; } + StringRef getPrefix() const { + if (Current.begin() == Header.begin()) + return StringRef(); + return Header.slice(0, Current.begin() - Header.begin() - 1); + } + StringRef getSuffix() const { + if (Current.end() == Header.end()) + return StringRef(); + 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"); + StringRef Suffix = getSuffix(); + Current = Suffix.slice(0, Suffix.find('\0')); + } +}; + +/// \brief A thin wraper around MDNode to access encoded debug info. +/// +/// This should not be stored in a container, because the underlying MDNode may +/// change in certain situations. class DIDescriptor { // Befriends DIRef so DIRef can befriend the protected member // function: getFieldAs<DIRef>. template <typename T> friend class DIRef; public: - /// The three accessibility flags are mutually exclusive and rolled - /// together in the first two bits. + /// \brief Accessibility flags. + /// + /// The three accessibility flags are mutually exclusive and rolled together + /// in the first two bits. enum { FlagAccessibility = 1 << 0 | 1 << 1, FlagPrivate = 1, @@ -83,9 +148,8 @@ FlagObjectPointer = 1 << 10, FlagVector = 1 << 11, FlagStaticMember = 1 << 12, - FlagIndirectVariable = 1 << 13, - FlagLValueReference = 1 << 14, - FlagRValueReference = 1 << 15 + FlagLValueReference = 1 << 13, + FlagRValueReference = 1 << 14 }; protected: @@ -113,22 +177,50 @@ 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); } - uint16_t getTag() const { - return getUnsignedField(0) & ~LLVMDebugVersionMask; + StringRef getHeader() const { return getStringField(0); } + + size_t getNumHeaderFields() const { + return std::distance(DIHeaderFieldIterator(getHeader()), + DIHeaderFieldIterator()); + } + + 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 (auto I = header_begin(), E = header_end(); I != E; ++I, --Index) + if (!Index) + return I; + return header_end(); + } + + StringRef getHeaderField(unsigned Index) const { + return *getHeaderIterator(Index); + } + + template <class T> T getHeaderFieldAs(unsigned Index) const { + return getHeaderIterator(Index).getNumber<T>(); + } + + uint16_t getTag() const { return getHeaderFieldAs<uint16_t>(0); } bool isDerivedType() const; bool isCompositeType() const; @@ -150,15 +242,17 @@ bool isTemplateValueParameter() const; bool isObjCProperty() const; bool isImportedEntity() const; + bool isExpression() const; - /// print - print descriptor. void print(raw_ostream &OS) const; + void dump() const; - /// dump - print descriptor to dbgs() with a newline. - void dump() const; + /// \brief Replace all uses of debug info referenced by this descriptor. + void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D); + void replaceAllUsesWith(MDNode *D); }; -/// DISubrange - This is used to represent ranges, for array bounds. +/// \brief This is used to represent ranges, for array bounds. class DISubrange : public DIDescriptor { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -166,26 +260,25 @@ public: explicit DISubrange(const MDNode *N = nullptr) : DIDescriptor(N) {} - int64_t getLo() const { return getInt64Field(1); } - int64_t getCount() const { return getInt64Field(2); } + int64_t getLo() const { return getHeaderFieldAs<int64_t>(1); } + int64_t getCount() const { return getHeaderFieldAs<int64_t>(2); } bool Verify() const; }; -/// DITypedArray - This descriptor holds an array of nodes with type T. +/// \brief This descriptor holds an array of nodes with type T. template <typename T> class DITypedArray : public DIDescriptor { public: explicit DITypedArray(const MDNode *N = nullptr) : DIDescriptor(N) {} 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; -/// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). +/// \brief A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). +/// /// FIXME: it seems strange that this doesn't have either a reference to the /// type/precision or a file/line pair for location info. class DIEnumerator : public DIDescriptor { @@ -195,8 +288,8 @@ public: explicit DIEnumerator(const MDNode *N = nullptr) : DIDescriptor(N) {} - StringRef getName() const { return getStringField(1); } - int64_t getEnumValue() const { return getInt64Field(2); } + StringRef getName() const { return getHeaderField(1); } + int64_t getEnumValue() const { return getHeaderFieldAs<int64_t>(2); } bool Verify() const; }; @@ -205,7 +298,7 @@ typedef DIRef<DIType> DITypeRef; typedef DITypedArray<DITypeRef> DITypeArray; -/// DIScope - A base class for various scopes. +/// \brief A base class for various scopes. /// /// Although, implementation-wise, DIScope is the parent class of most /// other DIxxx classes, including DIType and its descendants, most of @@ -221,21 +314,28 @@ public: explicit DIScope(const MDNode *N = nullptr) : DIDescriptor(N) {} - /// Gets the parent scope for this scope node or returns a - /// default constructed scope. + /// \brief Get the parent scope. + /// + /// Gets the parent scope for this scope node or returns a default + /// constructed scope. DIScopeRef getContext() const; + /// \brief Get the scope name. + /// /// If the scope node has a name, return that, else return an empty string. StringRef getName() const; StringRef getFilename() const; StringRef getDirectory() const; - /// Generate a reference to this DIScope. Uses the type identifier instead - /// of the actual MDNode if possible, to help type uniquing. + /// \brief Generate a reference to this DIScope. + /// + /// Uses the type identifier instead of the actual MDNode if possible, to + /// help type uniquing. DIScopeRef getRef() const; }; -/// Represents reference to a DIDescriptor, abstracts over direct and -/// identifier-based metadata references. +/// \brief Represents reference to a DIDescriptor. +/// +/// Abstracts over direct and identifier-based metadata references. template <typename T> class DIRef { template <typename DescTy> friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const; @@ -243,15 +343,16 @@ friend DIScopeRef DIScope::getRef() const; friend class DIType; - /// Val can be either a MDNode or a MDString, in the latter, - /// MDString specifies the type identifier. - const Value *Val; - explicit DIRef(const Value *V); + /// \brief Val can be either a MDNode or a MDString. + /// + /// In the latter, MDString specifies the type identifier. + const Metadata *Val; + explicit DIRef(const Metadata *V); public: T resolve(const DITypeIdentifierMap &Map) const; StringRef getName() const; - operator Value *() const { return const_cast<Value *>(Val); } + operator Metadata *() const { return const_cast<Metadata *>(Val); } }; template <typename T> @@ -282,17 +383,18 @@ return MS->getString(); } -/// Specialize getFieldAs to handle fields that are references to DIScopes. +/// \brief Handle fields that are references to DIScopes. template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const; -/// Specialize DIRef constructor for DIScopeRef. -template <> DIRef<DIScope>::DIRef(const Value *V); +/// \brief Specialize DIRef constructor for DIScopeRef. +template <> DIRef<DIScope>::DIRef(const Metadata *V); -/// Specialize getFieldAs to handle fields that are references to DITypes. +/// \brief Handle fields that are references to DITypes. template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const; -/// Specialize DIRef constructor for DITypeRef. -template <> DIRef<DIType>::DIRef(const Value *V); +/// \brief Specialize DIRef constructor for DITypeRef. +template <> DIRef<DIType>::DIRef(const Metadata *V); -/// DIType - This 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. class DIType : public DIScope { @@ -302,24 +404,23 @@ 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()); } - /// Verify - Verify that a type descriptor is well formed. bool Verify() const; DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } - StringRef getName() const { return getStringField(3); } - unsigned getLineNumber() const { return getUnsignedField(4); } - uint64_t getSizeInBits() const { return getUInt64Field(5); } - uint64_t getAlignInBits() const { return getUInt64Field(6); } + 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); } // FIXME: Offset is only used for DW_TAG_member nodes. Making every type // carry this is just plain insane. - uint64_t getOffsetInBits() const { return getUInt64Field(7); } - unsigned getFlags() const { return getUnsignedField(8); } + uint64_t getOffsetInBits() const { return getHeaderFieldAs<unsigned>(5); } + unsigned getFlags() const { return getHeaderFieldAs<unsigned>(6); } bool isPrivate() const { return (getFlags() & FlagAccessibility) == FlagPrivate; } @@ -330,7 +431,6 @@ return (getFlags() & FlagAccessibility) == FlagPublic; } bool isForwardDecl() const { return (getFlags() & FlagFwdDecl) != 0; } - // isAppleBlock - Return true if this is the Apple Blocks extension. bool isAppleBlockExtension() const { return (getFlags() & FlagAppleBlock) != 0; } @@ -352,27 +452,22 @@ return (getFlags() & FlagRValueReference) != 0; } bool isValid() const { return DbgNode && isType(); } - - /// replaceAllUsesWith - Replace all uses of debug info referenced by - /// this descriptor. - void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D); - void replaceAllUsesWith(MDNode *D); }; -/// DIBasicType - A basic type, like 'int' or 'float'. +/// \brief A basic type, like 'int' or 'float'. class DIBasicType : public DIType { public: explicit DIBasicType(const MDNode *N = nullptr) : DIType(N) {} - unsigned getEncoding() const { return getUnsignedField(9); } + unsigned getEncoding() const { return getHeaderFieldAs<unsigned>(7); } - /// Verify - Verify that a basic type descriptor is well formed. bool Verify() const; }; -/// DIDerivedType - A simple derived type, like a const qualified type, -/// a typedef, a pointer or reference, et cetera. Or, a data member of -/// a class/struct/union. +/// \brief A simple derived type +/// +/// Like a const qualified type, a typedef, a pointer or reference, et cetera. +/// Or, a data member of a class/struct/union. class DIDerivedType : public DIType { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -380,35 +475,39 @@ public: explicit DIDerivedType(const MDNode *N = nullptr) : DIType(N) {} - DITypeRef getTypeDerivedFrom() const { return getFieldAs<DITypeRef>(9); } + DITypeRef getTypeDerivedFrom() const { return getFieldAs<DITypeRef>(3); } - /// getObjCProperty - Return property node, if this ivar is - /// associated with one. + /// \brief Return property node, if this ivar is associated with one. MDNode *getObjCProperty() const; DITypeRef getClassType() const { assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - return getFieldAs<DITypeRef>(10); + return getFieldAs<DITypeRef>(4); } Constant *getConstant() const { assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); - return getConstantField(10); + return getConstantField(4); } - /// Verify - Verify that a derived type descriptor is well formed. bool Verify() const; }; -/// DICompositeType - This descriptor holds a type that can refer to multiple -/// other types, like a function or struct. +/// \brief Types that refer to multiple other types. +/// +/// This descriptor holds a type that can refer to multiple other types, like a +/// function or struct. +/// /// DICompositeType is derived from DIDerivedType because some /// composite types (such as enums) can be derived from basic types // 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; + + /// \brief Set the array of member DITypes. void setArraysHelper(MDNode *Elements, MDNode *TParams); public: @@ -416,22 +515,31 @@ DIArray getElements() const { assert(!isSubroutineType() && "no elements for DISubroutineType"); - return getFieldAs<DIArray>(10); + return getFieldAs<DIArray>(4); } + +private: template <typename T> void setArrays(DITypedArray<T> Elements, DIArray TParams = DIArray()) { - assert((!TParams || DbgNode->getNumOperands() == 15) && - "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 getUnsignedField(11); } - DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(12); } + +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); - DIArray getTemplateParams() const { return getFieldAs<DIArray>(13); } + +public: + DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); } MDString *getIdentifier() const; - /// Verify - Verify that a composite type descriptor is well formed. bool Verify() const; }; @@ -439,21 +547,23 @@ public: explicit DISubroutineType(const MDNode *N = nullptr) : DICompositeType(N) {} DITypedArray<DITypeRef> getTypeArray() const { - return getFieldAs<DITypedArray<DITypeRef>>(10); + return getFieldAs<DITypedArray<DITypeRef>>(4); } }; -/// DIFile - This is a wrapper for a file. +/// \brief This is a wrapper for a file. class DIFile : public DIScope { friend class DIDescriptor; public: explicit DIFile(const MDNode *N = nullptr) : DIScope(N) {} + + /// \brief Retrieve the MDNode for the directory/file pair. MDNode *getFileNode() const; bool Verify() const; }; -/// DICompileUnit - A wrapper for a compile unit. +/// \brief A wrapper for a compile unit. class DICompileUnit : public DIScope { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -462,13 +572,13 @@ explicit DICompileUnit(const MDNode *N = nullptr) : DIScope(N) {} dwarf::SourceLanguage getLanguage() const { - return static_cast<dwarf::SourceLanguage>(getUnsignedField(2)); + return static_cast<dwarf::SourceLanguage>(getHeaderFieldAs<unsigned>(1)); } - StringRef getProducer() const { return getStringField(3); } + StringRef getProducer() const { return getHeaderField(2); } - bool isOptimized() const { return getUnsignedField(4) != 0; } - StringRef getFlags() const { return getStringField(5); } - unsigned getRunTimeVersion() const { return getUnsignedField(6); } + bool isOptimized() const { return getHeaderFieldAs<bool>(3) != 0; } + StringRef getFlags() const { return getHeaderField(4); } + unsigned getRunTimeVersion() const { return getHeaderFieldAs<unsigned>(5); } DIArray getEnumTypes() const; DIArray getRetainedTypes() const; @@ -476,14 +586,16 @@ DIArray getGlobalVariables() const; DIArray getImportedEntities() const; - StringRef getSplitDebugFilename() const { return getStringField(12); } - unsigned getEmissionKind() const { return getUnsignedField(13); } + void replaceSubprograms(DIArray Subprograms); + void replaceGlobalVariables(DIArray GlobalVariables); - /// Verify - Verify that a compile unit is well formed. + StringRef getSplitDebugFilename() const { return getHeaderField(6); } + unsigned getEmissionKind() const { return getHeaderFieldAs<unsigned>(7); } + bool Verify() const; }; -/// DISubprogram - This is a wrapper for a subprogram (e.g. a function). +/// \brief This is a wrapper for a subprogram (e.g. a function). class DISubprogram : public DIScope { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -491,103 +603,96 @@ public: explicit DISubprogram(const MDNode *N = nullptr) : DIScope(N) {} - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } - StringRef getName() const { return getStringField(3); } - StringRef getDisplayName() const { return getStringField(4); } - StringRef getLinkageName() const { return getStringField(5); } - unsigned getLineNumber() const { return getUnsignedField(6); } - DISubroutineType getType() const { return getFieldAs<DISubroutineType>(7); } + StringRef getName() const { return getHeaderField(1); } + StringRef getDisplayName() const { return getHeaderField(2); } + StringRef getLinkageName() const { return getHeaderField(3); } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(4); } - /// isLocalToUnit - Return true if this subprogram is local to the current - /// compile unit, like 'static' in C. - unsigned isLocalToUnit() const { return getUnsignedField(8); } - unsigned isDefinition() const { return getUnsignedField(9); } + /// \brief Check if this is local (like 'static' in C). + unsigned isLocalToUnit() const { return getHeaderFieldAs<unsigned>(5); } + unsigned isDefinition() const { return getHeaderFieldAs<unsigned>(6); } - unsigned getVirtuality() const { return getUnsignedField(10); } - unsigned getVirtualIndex() const { return getUnsignedField(11); } - - DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(12); } - - unsigned getFlags() const { return getUnsignedField(13); } + unsigned getVirtuality() const { return getHeaderFieldAs<unsigned>(7); } + unsigned getVirtualIndex() const { return getHeaderFieldAs<unsigned>(8); } - unsigned isArtificial() const { - return (getUnsignedField(13) & FlagArtificial) != 0; - } - /// isPrivate - Return true if this subprogram has "private" - /// access specifier. - bool isPrivate() const { - return (getFlags() & FlagAccessibility) == FlagPrivate; - } - /// isProtected - Return true if this subprogram has "protected" - /// access specifier. - bool isProtected() const { - return (getFlags() & FlagAccessibility) == FlagProtected; - } - /// isPublic - Return true if this subprogram has "public" - /// access specifier. - bool isPublic() const { - return (getFlags() & FlagAccessibility) == FlagPublic; - } - /// isExplicit - Return true if this subprogram is marked as explicit. - bool isExplicit() const { return (getUnsignedField(13) & FlagExplicit) != 0; } - /// isPrototyped - Return true if this subprogram is prototyped. - bool isPrototyped() const { - return (getUnsignedField(13) & FlagPrototyped) != 0; - } + unsigned getFlags() const { return getHeaderFieldAs<unsigned>(9); } + + unsigned isOptimized() const { return getHeaderFieldAs<bool>(10); } - /// Return true if this subprogram is a C++11 reference-qualified - /// non-static member function (void foo() &). - unsigned isLValueReference() const { - return (getUnsignedField(13) & FlagLValueReference) != 0; - } + /// \brief Get the beginning of the scope of the function (not the name). + unsigned getScopeLineNumber() const { return getHeaderFieldAs<unsigned>(11); } - /// Return true if this subprogram is a C++11 - /// rvalue-reference-qualified non-static member function - /// (void foo() &&). - unsigned isRValueReference() const { - return (getUnsignedField(13) & FlagRValueReference) != 0; - } + DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } + DISubroutineType getType() const { return getFieldAs<DISubroutineType>(3); } - unsigned isOptimized() const; + DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(4); } - /// Verify - Verify that a subprogram descriptor is well formed. bool Verify() const; - /// describes - Return true if this subprogram provides debugging - /// information for the function F. + /// \brief Check if this provides debugging information for the function F. bool describes(const Function *F); - Function *getFunction() const { return getFunctionField(15); } - void replaceFunction(Function *F) { replaceFunctionField(15, F); } - DIArray getTemplateParams() const { return getFieldAs<DIArray>(16); } + Function *getFunction() const { return getFunctionField(5); } + void replaceFunction(Function *F) { replaceFunctionField(5, F); } + DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); } DISubprogram getFunctionDeclaration() const { - return getFieldAs<DISubprogram>(17); + return getFieldAs<DISubprogram>(7); } MDNode *getVariablesNodes() const; DIArray getVariables() const; - /// getScopeLineNumber - Get the beginning of the scope of the - /// function, not necessarily where the name of the program - /// starts. - unsigned getScopeLineNumber() const { return getUnsignedField(19); } + unsigned isArtificial() const { return (getFlags() & FlagArtificial) != 0; } + /// \brief Check for the "private" access specifier. + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + /// \brief Check for the "protected" access specifier. + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + /// \brief Check for the "public" access specifier. + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } + /// \brief Check for "explicit". + bool isExplicit() const { return (getFlags() & FlagExplicit) != 0; } + /// \brief Check if this is prototyped. + bool isPrototyped() const { return (getFlags() & FlagPrototyped) != 0; } + + /// \brief Check if this is reference-qualified. + /// + /// Return true if this subprogram is a C++11 reference-qualified non-static + /// member function (void foo() &). + unsigned isLValueReference() const { + return (getFlags() & FlagLValueReference) != 0; + } + + /// \brief Check if this is rvalue-reference-qualified. + /// + /// Return true if this subprogram is a C++11 rvalue-reference-qualified + /// non-static member function (void foo() &&). + unsigned isRValueReference() const { + return (getFlags() & FlagRValueReference) != 0; + } }; -/// DILexicalBlock - This is a wrapper for a lexical block. +/// \brief This is a wrapper for a lexical block. class DILexicalBlock : public DIScope { public: explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {} DIScope getContext() const { return getFieldAs<DIScope>(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - unsigned getColumnNumber() const { return getUnsignedField(4); } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); } + unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(2); } bool Verify() const; }; -/// DILexicalBlockFile - This is a wrapper for a lexical block with -/// a filename change. +/// \brief This is a wrapper for a lexical block with a filename change. 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(); @@ -595,61 +700,51 @@ unsigned getLineNumber() const { return getScope().getLineNumber(); } unsigned getColumnNumber() const { return getScope().getColumnNumber(); } DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(2); } - unsigned getDiscriminator() const { return getUnsignedField(3); } + unsigned getDiscriminator() const { return getHeaderFieldAs<unsigned>(1); } bool Verify() const; }; -/// DINameSpace - A wrapper for a C++ style name space. +/// \brief A wrapper for a C++ style name space. class DINameSpace : public DIScope { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; public: explicit DINameSpace(const MDNode *N = nullptr) : DIScope(N) {} + StringRef getName() const { return getHeaderField(1); } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } DIScope getContext() const { return getFieldAs<DIScope>(2); } - StringRef getName() const { return getStringField(3); } - unsigned getLineNumber() const { return getUnsignedField(4); } bool Verify() const; }; -/// DITemplateTypeParameter - This is a wrapper for template type parameter. +/// \brief This is a wrapper for template type parameter. class DITemplateTypeParameter : public DIDescriptor { public: explicit DITemplateTypeParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} + : DIDescriptor(N) {} + + StringRef getName() const { return getHeaderField(1); } DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } - StringRef getName() const { return getStringField(2); } - DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } - StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(4).getDirectory(); - } - unsigned getLineNumber() const { return getUnsignedField(5); } - unsigned getColumnNumber() const { return getUnsignedField(6); } + DITypeRef getType() const { return getFieldAs<DITypeRef>(2); } bool Verify() const; }; -/// DITemplateValueParameter - This is a wrapper for template value parameter. +/// \brief This is a wrapper for template value parameter. class DITemplateValueParameter : public DIDescriptor { public: explicit DITemplateValueParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} + : DIDescriptor(N) {} + + StringRef getName() const { return getHeaderField(1); } DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } - StringRef getName() const { return getStringField(2); } - DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } - Value *getValue() const; - StringRef getFilename() const { return getFieldAs<DIFile>(5).getFilename(); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(5).getDirectory(); - } - unsigned getLineNumber() const { return getUnsignedField(6); } - unsigned getColumnNumber() const { return getUnsignedField(7); } + DITypeRef getType() const { return getFieldAs<DITypeRef>(2); } + Metadata *getValue() const; bool Verify() const; }; -/// DIGlobalVariable - This is a wrapper for a global variable. +/// \brief This is a wrapper for a global variable. class DIGlobalVariable : public DIDescriptor { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -657,32 +752,30 @@ public: explicit DIGlobalVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(2); } - StringRef getName() const { return getStringField(3); } - StringRef getDisplayName() const { return getStringField(4); } - StringRef getLinkageName() const { return getStringField(5); } - StringRef getFilename() const { return getFieldAs<DIFile>(6).getFilename(); } + StringRef getName() const { return getHeaderField(1); } + StringRef getDisplayName() const { return getHeaderField(2); } + StringRef getLinkageName() const { return getHeaderField(3); } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(4); } + unsigned isLocalToUnit() const { return getHeaderFieldAs<bool>(5); } + unsigned isDefinition() const { return getHeaderFieldAs<bool>(6); } + + DIScope getContext() const { return getFieldAs<DIScope>(1); } + StringRef getFilename() const { return getFieldAs<DIFile>(2).getFilename(); } StringRef getDirectory() const { - return getFieldAs<DIFile>(6).getDirectory(); + return getFieldAs<DIFile>(2).getDirectory(); + } + DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } + + GlobalVariable *getGlobal() const { return getGlobalVariableField(4); } + Constant *getConstant() const { return getConstantField(4); } + DIDerivedType getStaticDataMemberDeclaration() const { + return getFieldAs<DIDerivedType>(5); } - unsigned getLineNumber() const { return getUnsignedField(7); } - DITypeRef getType() const { return getFieldAs<DITypeRef>(8); } - unsigned isLocalToUnit() const { return getUnsignedField(9); } - unsigned isDefinition() const { return getUnsignedField(10); } - - GlobalVariable *getGlobal() const { return getGlobalVariableField(11); } - Constant *getConstant() const { return getConstantField(11); } - DIDerivedType getStaticDataMemberDeclaration() const { - return getFieldAs<DIDerivedType>(12); - } - - /// Verify - Verify that a global variable descriptor is well formed. bool Verify() const; }; -/// DIVariable - This is a wrapper for a variable (e.g. parameter, local, -/// global etc). +/// \brief This is a wrapper for a variable (e.g. parameter, local, global etc). class DIVariable : public DIDescriptor { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -690,84 +783,169 @@ public: explicit DIVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} + StringRef getName() const { return getHeaderField(1); } + unsigned getLineNumber() const { + // FIXME: Line number and arg number shouldn't be merged together like this. + return (getHeaderFieldAs<unsigned>(2) << 8) >> 8; + } + unsigned getArgNumber() const { return getHeaderFieldAs<unsigned>(2) >> 24; } + DIScope getContext() const { return getFieldAs<DIScope>(1); } - StringRef getName() const { return getStringField(2); } - DIFile getFile() const { return getFieldAs<DIFile>(3); } - unsigned getLineNumber() const { return (getUnsignedField(4) << 8) >> 8; } - unsigned getArgNumber() const { - unsigned L = getUnsignedField(4); - return L >> 24; - } - DITypeRef getType() const { return getFieldAs<DITypeRef>(5); } + DIFile getFile() const { return getFieldAs<DIFile>(2); } + DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } - /// isArtificial - Return true if this variable is marked as "artificial". + /// \brief Return true if this variable is marked as "artificial". bool isArtificial() const { - return (getUnsignedField(6) & FlagArtificial) != 0; + return (getHeaderFieldAs<unsigned>(3) & FlagArtificial) != 0; } bool isObjectPointer() const { - return (getUnsignedField(6) & FlagObjectPointer) != 0; + return (getHeaderFieldAs<unsigned>(3) & FlagObjectPointer) != 0; } - /// \brief Return true if this variable is represented as a pointer. - bool isIndirect() const { - return (getUnsignedField(6) & FlagIndirectVariable) != 0; - } - - /// getInlinedAt - If this variable is inlined then return inline location. + /// \brief If this variable is inlined then return inline location. MDNode *getInlinedAt() const; - /// Verify - Verify that a variable descriptor is well formed. bool Verify() const; - /// HasComplexAddr - Return true if the variable has a complex address. - bool hasComplexAddress() const { return getNumAddrElements() > 0; } - - /// \brief Return the size of this variable's complex address or - /// zero if there is none. - unsigned getNumAddrElements() const { - if (DbgNode->getNumOperands() < 9) - return 0; - return getDescriptorField(8)->getNumOperands(); - } - - /// \brief return the Idx'th complex address element. - uint64_t getAddrElement(unsigned Idx) const; - - /// isBlockByrefVariable - Return true if the variable was declared as - /// a "__block" variable (Apple Blocks). + /// \brief Check if this is a "__block" variable (Apple Blocks). bool isBlockByrefVariable(const DITypeIdentifierMap &Map) const { return (getType().resolve(Map)).isBlockByrefStruct(); } - /// isInlinedFnArgument - Return true if this variable provides debugging - /// information for an inlined function arguments. + /// \brief Check if this is an inlined function argument. bool isInlinedFnArgument(const Function *CurFn); - /// isVariablePiece - Return whether this is a piece of an aggregate - /// variable. - bool isVariablePiece() const; - /// getPieceOffset - Return the offset of this piece in bytes. - uint64_t getPieceOffset() const; - /// getPieceSize - Return the size of this piece in bytes. - uint64_t getPieceSize() const; - - /// Return the size reported by the variable's type. + /// \brief Return the size reported by the variable's type. unsigned getSizeInBits(const DITypeIdentifierMap &Map); void printExtendedName(raw_ostream &OS) const; }; -/// DILocation - This object holds location information. This object -/// is not associated with any DWARF tag. +/// \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; + +public: + explicit DIExpression(const MDNode *N = nullptr) : DIDescriptor(N) {} + + bool Verify() const; + + /// \brief Return the number of elements in the complex expression. + unsigned getNumElements() const { + if (!DbgNode) + return 0; + unsigned N = getNumHeaderFields(); + assert(N > 0 && "missing tag"); + return N - 1; + } + + /// \brief return the Idx'th complex address element. + uint64_t getElement(unsigned Idx) const; + + /// \brief Return whether this is a piece of an aggregate variable. + 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 { 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 { + if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) + return L->getLine(); + return 0; + } + unsigned getColumnNumber() const { + if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) + return L->getColumn(); + return 0; + } + DIScope getScope() const { + if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) + return DIScope(dyn_cast_or_null<MDNode>(L->getScope())); + return DIScope(nullptr); + } + DILocation getOrigLocation() const { + if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) + return DILocation(dyn_cast_or_null<MDNode>(L->getInlinedAt())); + return DILocation(nullptr); + } StringRef getFilename() const { return getScope().getFilename(); } StringRef getDirectory() const { return getScope().getDirectory(); } bool Verify() const; @@ -775,22 +953,29 @@ return (getLineNumber() == Other.getLineNumber() && getFilename() == Other.getFilename()); } - /// getDiscriminator - DWARF discriminators are used to distinguish - /// identical file locations for instructions that are on different - /// basic blocks. If two instructions are inside the same lexical block - /// and are in different basic blocks, we create a new lexical block - /// with identical location as the original but with a different - /// discriminator value (lib/Transforms/Util/AddDiscriminators.cpp - /// for details). + /// \brief Get the DWAF discriminator. + /// + /// DWARF discriminators are used to distinguish identical file locations for + /// instructions that are on different basic blocks. If two instructions are + /// inside the same lexical block and are in different basic blocks, we + /// create a new lexical block with identical location as the original but + /// with a different discriminator value + /// (lib/Transforms/Util/AddDiscriminators.cpp for details). unsigned getDiscriminator() const { // Since discriminators are associated with lexical blocks, make // 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; } + + /// \brief Generate a new discriminator value for this location. unsigned computeNewDiscriminator(LLVMContext &Ctx); + + /// \brief Return a copy of this location with a different scope. DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlockFile NewScope); }; @@ -801,36 +986,38 @@ public: explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {} - StringRef getObjCPropertyName() const { return getStringField(1); } - DIFile getFile() const { return getFieldAs<DIFile>(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } + StringRef getObjCPropertyName() const { return getHeaderField(1); } + DIFile getFile() const { return getFieldAs<DIFile>(1); } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } - StringRef getObjCPropertyGetterName() const { return getStringField(4); } - StringRef getObjCPropertySetterName() const { return getStringField(5); } + StringRef getObjCPropertyGetterName() const { return getHeaderField(3); } + StringRef getObjCPropertySetterName() const { return getHeaderField(4); } + unsigned getAttributes() const { return getHeaderFieldAs<unsigned>(5); } bool isReadOnlyObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readonly) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readonly) != 0; } bool isReadWriteObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; } bool isAssignObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_assign) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_assign) != 0; } bool isRetainObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_retain) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_retain) != 0; } bool isCopyObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_copy) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_copy) != 0; } bool isNonAtomicObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; } - /// Objective-C doesn't have an ODR, so there is no benefit in storing + /// \brief Get the type. + /// + /// \note Objective-C doesn't have an ODR, so there is no benefit in storing /// the type as a DITypeRef here. - DIType getType() const { return getFieldAs<DIType>(7); } + DIType getType() const { return getFieldAs<DIType>(2); } - /// Verify - Verify that a derived type descriptor is well formed. bool Verify() const; }; @@ -843,50 +1030,47 @@ explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} DIScope getContext() const { return getFieldAs<DIScope>(1); } DIScopeRef getEntity() const { return getFieldAs<DIScopeRef>(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - StringRef getName() const { return getStringField(4); } + unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); } + StringRef getName() const { return getHeaderField(2); } bool Verify() const; }; -/// getDISubprogram - Find subprogram that is enclosing this scope. +/// \brief Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); -/// getDICompositeType - Find underlying composite type. +/// \brief Find debug info for a given function. +/// \returns a valid DISubprogram, if found. Otherwise, it returns an empty +/// DISubprogram. +DISubprogram getDISubprogram(const Function *F); + +/// \brief Find underlying composite type. DICompositeType getDICompositeType(DIType T); -/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable -/// to hold function specific information. -NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, DISubprogram SP); - -/// getFnSpecificMDNode - Return a NameMDNode, if available, that is -/// suitable to hold function specific information. -NamedMDNode *getFnSpecificMDNode(const Module &M, DISubprogram SP); - -/// createInlinedVariable - Create a new inlined variable based on current -/// variable. +/// \brief Create a new inlined variable based on current variable. +/// /// @param DV Current Variable. /// @param InlinedScope Location at current variable is inlined. DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope, LLVMContext &VMContext); -/// cleanseInlinedVariable - Remove inlined scope from the variable. +/// \brief Remove inlined scope from the variable. DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); -/// getEntireVariable - Remove OpPiece exprs from the variable. -DIVariable getEntireVariable(DIVariable DV); - -/// Construct DITypeIdentifierMap by going through retained types of each CU. +/// \brief Generate map by visiting all retained types. DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); -/// Strip debug info in the module if it exists. +/// \brief Strip debug info in the module if it exists. +/// /// To do this, we remove all calls to the debugger intrinsics and any named /// metadata for debugging. We also remove debug locations for instructions. /// Return true if module is modified. bool StripDebugInfo(Module &M); -/// Return Debug Info Metadata Version by checking module flags. +/// \brief Return Debug Info Metadata Version by checking module flags. unsigned getDebugMetadataVersionFromModule(const Module &M); +/// \brief Utility to find all debug info in a module. +/// /// DebugInfoFinder tries to list all debug info MDNodes used in a module. To /// list debug info MDNodes used by an instruction, DebugInfoFinder uses /// processDeclare, processValue and processLocation to handle DbgDeclareInst, @@ -897,50 +1081,39 @@ public: DebugInfoFinder() : TypeMapInitialized(false) {} - /// processModule - Process entire module and collect debug info - /// anchors. + /// \brief Process entire module and collect debug info anchors. void processModule(const Module &M); - /// processDeclare - Process DbgDeclareInst. + /// \brief Process DbgDeclareInst. void processDeclare(const Module &M, const DbgDeclareInst *DDI); - /// Process DbgValueInst. + /// \brief Process DbgValueInst. void processValue(const Module &M, const DbgValueInst *DVI); - /// processLocation - Process DILocation. + /// \brief Process DILocation. void processLocation(const Module &M, DILocation Loc); - /// Clear all lists. + /// \brief Process DIExpression. + void processExpression(DIExpression Expr); + + /// \brief Clear all lists. void reset(); private: - /// Initialize TypeIdentifierMap. void InitializeTypeMap(const Module &M); - /// processType - Process DIType. void processType(DIType DT); - - /// processSubprogram - Process DISubprogram. void processSubprogram(DISubprogram SP); - void processScope(DIScope Scope); - - /// addCompileUnit - Add compile unit into CUs. bool addCompileUnit(DICompileUnit CU); - - /// addGlobalVariable - Add global variable into GVs. bool addGlobalVariable(DIGlobalVariable DIG); - - // addSubprogram - Add subprogram into SPs. bool addSubprogram(DISubprogram SP); - - /// addType - Add type into Tys. bool addType(DIType DT); - bool addScope(DIScope Scope); 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; @@ -971,14 +1144,15 @@ unsigned scope_count() const { return Scopes.size(); } private: - SmallVector<DICompileUnit, 8> CUs; // Compile Units - SmallVector<DISubprogram, 8> SPs; // Subprograms - SmallVector<DIGlobalVariable, 8> GVs; // Global Variables; - SmallVector<DIType, 8> TYs; // Types - SmallVector<DIScope, 8> Scopes; // Scopes + SmallVector<DICompileUnit, 8> CUs; + SmallVector<DISubprogram, 8> SPs; + SmallVector<DIGlobalVariable, 8> GVs; + SmallVector<DIType, 8> TYs; + SmallVector<DIScope, 8> Scopes; SmallPtrSet<MDNode *, 64> NodesSeen; DITypeIdentifierMap TypeIdentifierMap; - /// Specify if TypeIdentifierMap is initialized. + + /// \brief Specify if TypeIdentifierMap is initialized. bool TypeMapInitialized; };