X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FIR%2FDebugInfo.h;h=1972526b340e82b38a2b0426f8ab36d199e96858;hb=2b8aee8cfab4399e94b5530dbadab1a831b564ca;hp=c3a8ea2e10c09ce2b26065bc79fb9aafec093d1e;hpb=076fd5dfc1f0600183bbc7db974dc7b39086136d;p=oota-llvm.git diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index c3a8ea2e10c..1972526b340 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -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 namespace llvm { class BasicBlock; @@ -37,6 +39,7 @@ class Value; class DbgDeclareInst; class DbgValueInst; class Instruction; +class Metadata; class MDNode; class MDString; class NamedMDNode; @@ -52,166 +55,213 @@ class DIType; class DIScope; class DIObjCProperty; -/// Maps from type identifier to the actual MDNode. +/// \brief Maps from type identifier to the actual MDNode. typedef DenseMap 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. +/// \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. template friend class DIRef; public: - /// The three accessibility flags are mutually exclusive and rolled - /// together in the first two bits. + /// \brief Duplicated debug info flags. + /// + /// \see DebugNode::DIFlags. 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 = DebugNode::Flag##NAME, +#include "llvm/IR/DebugInfoFlags.def" + FlagAccessibility = DebugNode::FlagAccessibility }; + 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 &SplitFlags); + protected: const MDNode *DbgNode; - StringRef getStringField(unsigned Elt) const; - unsigned getUnsignedField(unsigned Elt) const { - return (unsigned)getUInt64Field(Elt); - } - uint64_t getUInt64Field(unsigned Elt) const; - int64_t getInt64Field(unsigned Elt) const; DIDescriptor getDescriptorField(unsigned Elt) const; - template DescTy getFieldAs(unsigned Elt) const { return DescTy(getDescriptorField(Elt)); } - GlobalVariable *getGlobalVariableField(unsigned Elt) const; - Constant *getConstantField(unsigned Elt) const; - Function *getFunctionField(unsigned Elt) const; - void replaceFunctionField(unsigned Elt, Function *F); - public: explicit DIDescriptor(const MDNode *N = nullptr) : DbgNode(N) {} - bool Verify() const; - - operator MDNode *() const { return const_cast(DbgNode); } - MDNode *operator->() const { return const_cast(DbgNode); } + MDNode *get() const { return const_cast(DbgNode); } + operator MDNode *() const { return get(); } + MDNode *operator->() const { return get(); } + MDNode &operator*() const { + assert(get() && "Expected valid pointer"); + 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; - } - - bool isDerivedType() const; - bool isCompositeType() const; - bool isSubroutineType() const; - bool isBasicType() const; - bool isVariable() const; - bool isSubprogram() const; - bool isGlobalVariable() const; - bool isScope() const; - bool isFile() const; - bool isCompileUnit() const; - bool isNameSpace() const; - bool isLexicalBlockFile() const; - bool isLexicalBlock() const; - bool isSubrange() const; - bool isEnumerator() const; - bool isType() const; - bool isTemplateTypeParameter() const; - bool isTemplateValueParameter() const; - bool isObjCProperty() const; - bool isImportedEntity() const; - bool isExpression() const; - - /// print - print descriptor. - void print(raw_ostream &OS) const; + if (auto *N = dyn_cast_or_null(get())) + return N->getTag(); + return 0; + } - /// dump - print descriptor to dbgs() with a newline. + bool isDerivedType() const { return get() && isa(get()); } + bool isCompositeType() const { + return get() && isa(get()); + } + bool isSubroutineType() const { + return get() && isa(get()); + } + bool isBasicType() const { return get() && isa(get()); } + bool isVariable() const { return get() && isa(get()); } + bool isSubprogram() const { return get() && isa(get()); } + bool isGlobalVariable() const { + return get() && isa(get()); + } + bool isScope() const { return get() && isa(get()); } + bool isFile() const { return get() && isa(get()); } + bool isCompileUnit() const { return get() && isa(get()); } + bool isNameSpace() const{ return get() && isa(get()); } + bool isLexicalBlockFile() const { + return get() && isa(get()); + } + bool isLexicalBlock() const { + return get() && isa(get()); + } + bool isSubrange() const { return get() && isa(get()); } + bool isEnumerator() const { return get() && isa(get()); } + bool isType() const { return get() && isa(get()); } + bool isTemplateTypeParameter() const { + return get() && isa(get()); + } + bool isTemplateValueParameter() const { + return get() && isa(get()); + } + bool isObjCProperty() const { return get() && isa(get()); } + bool isImportedEntity() const { + return get() && isa(get()); + } + bool isExpression() const { return get() && isa(get()); } + + void print(raw_ostream &OS) const; void dump() const; - /// replaceAllUsesWith - Replace all uses of debug info referenced by - /// this descriptor. + /// \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. +#define DECLARE_SIMPLIFY_DESCRIPTOR(DESC) \ + class DESC; \ + template <> struct simplify_type; \ + template <> struct simplify_type; +DECLARE_SIMPLIFY_DESCRIPTOR(DIDescriptor) +DECLARE_SIMPLIFY_DESCRIPTOR(DISubrange) +DECLARE_SIMPLIFY_DESCRIPTOR(DIEnumerator) +DECLARE_SIMPLIFY_DESCRIPTOR(DIScope) +DECLARE_SIMPLIFY_DESCRIPTOR(DIType) +DECLARE_SIMPLIFY_DESCRIPTOR(DIBasicType) +DECLARE_SIMPLIFY_DESCRIPTOR(DIDerivedType) +DECLARE_SIMPLIFY_DESCRIPTOR(DICompositeType) +DECLARE_SIMPLIFY_DESCRIPTOR(DISubroutineType) +DECLARE_SIMPLIFY_DESCRIPTOR(DIFile) +DECLARE_SIMPLIFY_DESCRIPTOR(DICompileUnit) +DECLARE_SIMPLIFY_DESCRIPTOR(DISubprogram) +DECLARE_SIMPLIFY_DESCRIPTOR(DILexicalBlock) +DECLARE_SIMPLIFY_DESCRIPTOR(DILexicalBlockFile) +DECLARE_SIMPLIFY_DESCRIPTOR(DINameSpace) +DECLARE_SIMPLIFY_DESCRIPTOR(DITemplateTypeParameter) +DECLARE_SIMPLIFY_DESCRIPTOR(DITemplateValueParameter) +DECLARE_SIMPLIFY_DESCRIPTOR(DIGlobalVariable) +DECLARE_SIMPLIFY_DESCRIPTOR(DIVariable) +DECLARE_SIMPLIFY_DESCRIPTOR(DIExpression) +DECLARE_SIMPLIFY_DESCRIPTOR(DILocation) +DECLARE_SIMPLIFY_DESCRIPTOR(DIObjCProperty) +DECLARE_SIMPLIFY_DESCRIPTOR(DIImportedEntity) +#undef DECLARE_SIMPLIFY_DESCRIPTOR + +/// \brief This is used to represent ranges, for array bounds. class DISubrange : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: explicit DISubrange(const MDNode *N = nullptr) : DIDescriptor(N) {} + DISubrange(const MDSubrange *N) : DIDescriptor(N) {} + + MDSubrange *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDSubrange *() const { return get(); } + MDSubrange *operator->() const { return get(); } + MDSubrange &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } - int64_t getLo() const { return getInt64Field(1); } - int64_t getCount() const { return getInt64Field(2); } - bool Verify() const; + int64_t getLo() const { return get()->getLo(); } + int64_t getCount() const { return get()->getCount(); } }; -/// DITypedArray - This descriptor holds an array of nodes with type T. +/// \brief This descriptor holds an array of nodes with type T. template class DITypedArray : public DIDescriptor { public: explicit DITypedArray(const MDNode *N = nullptr) : DIDescriptor(N) {} + operator MDTuple *() const { + return const_cast(cast_or_null(DbgNode)); + } unsigned getNumElements() const { return DbgNode ? DbgNode->getNumOperands() : 0; } - T getElement(unsigned Idx) const { - return getFieldAs(Idx); - } + T getElement(unsigned Idx) const { return getFieldAs(Idx); } }; typedef DITypedArray 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 { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: explicit DIEnumerator(const MDNode *N = nullptr) : DIDescriptor(N) {} + DIEnumerator(const MDEnumerator *N) : DIDescriptor(N) {} - StringRef getName() const { return getStringField(1); } - int64_t getEnumValue() const { return getInt64Field(2); } - bool Verify() const; + MDEnumerator *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDEnumerator *() const { return get(); } + MDEnumerator *operator->() const { return get(); } + MDEnumerator &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } + + StringRef getName() const { return get()->getName(); } + int64_t getEnumValue() const { return get()->getValue(); } }; template class DIRef; +typedef DIRef DIDescriptorRef; typedef DIRef DIScopeRef; typedef DIRef DITypeRef; typedef DITypedArray 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 @@ -220,28 +270,40 @@ typedef DITypedArray DITypeArray; /// DIScopes that are scopes in the strict lexical scope sense /// (DICompileUnit, DISubprogram, etc.), but not for, e.g., a DIType. class DIScope : public DIDescriptor { -protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: explicit DIScope(const MDNode *N = nullptr) : DIDescriptor(N) {} + DIScope(const MDScope *N) : DIDescriptor(N) {} + + MDScope *get() const { return cast_or_null(DIDescriptor::get()); } + operator MDScope *() const { return get(); } + MDScope *operator->() const { return get(); } + MDScope &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } - /// 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 class DIRef { template friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const; @@ -249,83 +311,73 @@ template class DIRef { 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(Val); } -}; - -template -T DIRef::resolve(const DITypeIdentifierMap &Map) const { - if (!Val) - return T(); + template + DIRef(const TypedDebugNodeRef &Ref, + typename std::enable_if::value>::type * = + nullptr) + : Val(Ref) {} - if (const MDNode *MD = dyn_cast(Val)) - return T(MD); - - const MDString *MS = cast(Val); - // Find the corresponding MDNode. - DITypeIdentifierMap::const_iterator Iter = Map.find(MS); - assert(Iter != Map.end() && "Identifier not in the type map?"); - assert(DIDescriptor(Iter->second).isType() && - "MDNode in DITypeIdentifierMap should be a DIType."); - return T(Iter->second); -} + T resolve(const DITypeIdentifierMap &Map) const; + operator Metadata *() const { return const_cast(Val); } -template StringRef DIRef::getName() const { - if (!Val) - return StringRef(); + static DIRef get(const Metadata *MD) { return DIRef(MD); } +}; - if (const MDNode *MD = dyn_cast(Val)) - return T(MD).getName(); +template <> +DIDescriptor DIRef::resolve(const DITypeIdentifierMap &Map) const; +template <> +DIScope DIRef::resolve(const DITypeIdentifierMap &Map) const; +template <> DIType DIRef::resolve(const DITypeIdentifierMap &Map) const; - const MDString *MS = cast(Val); - return MS->getString(); -} +/// \brief Handle fields that are references to DIDescriptors. +template <> +DIDescriptorRef DIDescriptor::getFieldAs(unsigned Elt) const; +/// \brief Specialize DIRef constructor for DIDescriptorRef. +template <> DIRef::DIRef(const Metadata *V); -/// Specialize getFieldAs to handle fields that are references to DIScopes. +/// \brief Handle fields that are references to DIScopes. template <> DIScopeRef DIDescriptor::getFieldAs(unsigned Elt) const; -/// Specialize DIRef constructor for DIScopeRef. -template <> DIRef::DIRef(const Value *V); +/// \brief Specialize DIRef constructor for DIScopeRef. +template <> DIRef::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(unsigned Elt) const; -/// Specialize DIRef constructor for DITypeRef. -template <> DIRef::DIRef(const Value *V); +/// \brief Specialize DIRef constructor for DITypeRef. +template <> DIRef::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 { -protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: explicit DIType(const MDNode *N = nullptr) : DIScope(N) {} - operator DITypeRef () const { - assert(isType() && - "constructing DITypeRef from an MDNode that is not a type"); - return DITypeRef(&*getRef()); + DIType(const MDType *N) : DIScope(N) {} + + MDType *get() const { return cast_or_null(DIDescriptor::get()); } + operator MDType *() const { return get(); } + MDType *operator->() const { return get(); } + MDType &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); } - /// Verify - Verify that a type descriptor is well formed. - bool Verify() const; - - DIScopeRef getContext() const { return getFieldAs(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); } + DIScopeRef getContext() const { return DIScopeRef::get(get()->getScope()); } + StringRef getName() const { return get()->getName(); } + unsigned getLineNumber() const { return get()->getLine(); } + uint64_t getSizeInBits() const { return get()->getSizeInBits(); } + uint64_t getAlignInBits() const { return get()->getAlignInBits(); } // 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 get()->getOffsetInBits(); } + unsigned getFlags() const { return get()->getFlags(); } bool isPrivate() const { return (getFlags() & FlagAccessibility) == FlagPrivate; } @@ -336,7 +388,6 @@ public: 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; } @@ -360,541 +411,813 @@ public: bool isValid() const { return DbgNode && isType(); } }; -/// 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) {} + DIBasicType(const MDBasicType *N) : DIType(N) {} - unsigned getEncoding() const { return getUnsignedField(9); } + MDBasicType *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDBasicType *() const { return get(); } + MDBasicType *operator->() const { return get(); } + MDBasicType &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } - /// Verify - Verify that a basic type descriptor is well formed. - bool Verify() const; + unsigned getEncoding() const { return get()->getEncoding(); } }; -/// 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; - public: explicit DIDerivedType(const MDNode *N = nullptr) : DIType(N) {} + DIDerivedType(const MDDerivedTypeBase *N) : DIType(N) {} - DITypeRef getTypeDerivedFrom() const { return getFieldAs(9); } + MDDerivedTypeBase *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDDerivedTypeBase *() const { return get(); } + MDDerivedTypeBase *operator->() const { return get(); } + MDDerivedTypeBase &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } - /// getObjCProperty - Return property node, if this ivar is - /// associated with one. - MDNode *getObjCProperty() const; + DITypeRef getTypeDerivedFrom() const { + return DITypeRef::get(get()->getBaseType()); + } + + /// \brief Return property node, if this ivar is associated with one. + MDNode *getObjCProperty() const { + if (auto *N = dyn_cast(get())) + return dyn_cast_or_null(N->getExtraData()); + return nullptr; + } DITypeRef getClassType() const { assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - return getFieldAs(10); + if (auto *N = dyn_cast(get())) + return DITypeRef::get(N->getExtraData()); + return DITypeRef::get(nullptr); } Constant *getConstant() const { assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); - return getConstantField(10); - } + if (auto *N = dyn_cast(get())) + if (auto *C = dyn_cast_or_null(N->getExtraData())) + return C->getValue(); - /// Verify - Verify that a derived type descriptor is well formed. - bool Verify() const; + return nullptr; + } }; -/// 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 DIDescriptor; - void printInternal(raw_ostream &OS) const; + friend class DIBuilder; + + /// \brief Set the array of member DITypes. void setArraysHelper(MDNode *Elements, MDNode *TParams); public: explicit DICompositeType(const MDNode *N = nullptr) : DIDerivedType(N) {} + DICompositeType(const MDCompositeTypeBase *N) : DIDerivedType(N) {} + + MDCompositeTypeBase *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDCompositeTypeBase *() const { return get(); } + MDCompositeTypeBase *operator->() const { return get(); } + MDCompositeTypeBase &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } DIArray getElements() const { assert(!isSubroutineType() && "no elements for DISubroutineType"); - return getFieldAs(10); + return DIArray(get()->getElements()); } + +private: template void setArrays(DITypedArray 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(12); } + +public: + unsigned getRunTimeLang() const { return get()->getRuntimeLang(); } + DITypeRef getContainingType() const { + return DITypeRef::get(get()->getVTableHolder()); + } + +private: + /// \brief Set the containing type. void setContainingType(DICompositeType ContainingType); - DIArray getTemplateParams() const { return getFieldAs(13); } - MDString *getIdentifier() const; - /// Verify - Verify that a composite type descriptor is well formed. - bool Verify() const; +public: + DIArray getTemplateParams() const { + return DIArray(get()->getTemplateParams()); + } + MDString *getIdentifier() const { return get()->getRawIdentifier(); } }; class DISubroutineType : public DICompositeType { public: explicit DISubroutineType(const MDNode *N = nullptr) : DICompositeType(N) {} + DISubroutineType(const MDSubroutineType *N) : DICompositeType(N) {} + + MDSubroutineType *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDSubroutineType *() const { return get(); } + MDSubroutineType *operator->() const { return get(); } + MDSubroutineType &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } + DITypedArray getTypeArray() const { - return getFieldAs>(10); + return DITypedArray(get()->getTypeArray()); } }; -/// 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) {} - MDNode *getFileNode() const; - bool Verify() const; + DIFile(const MDFile *N) : DIScope(N) {} + + MDFile *get() const { return cast_or_null(DIDescriptor::get()); } + operator MDFile *() const { return get(); } + MDFile *operator->() const { return get(); } + MDFile &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } + + /// \brief Retrieve the MDNode for the directory/file pair. + MDNode *getFileNode() const { return get(); } }; -/// 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; - public: explicit DICompileUnit(const MDNode *N = nullptr) : DIScope(N) {} + DICompileUnit(const MDCompileUnit *N) : DIScope(N) {} - dwarf::SourceLanguage getLanguage() const { - return static_cast(getUnsignedField(2)); + MDCompileUnit *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDCompileUnit *() const { return get(); } + MDCompileUnit *operator->() const { return get(); } + MDCompileUnit &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); } - StringRef getProducer() const { return getStringField(3); } - - bool isOptimized() const { return getUnsignedField(4) != 0; } - StringRef getFlags() const { return getStringField(5); } - unsigned getRunTimeVersion() const { return getUnsignedField(6); } - DIArray getEnumTypes() const; - DIArray getRetainedTypes() const; - DIArray getSubprograms() const; - DIArray getGlobalVariables() const; - DIArray getImportedEntities() const; + dwarf::SourceLanguage getLanguage() const { + return static_cast(get()->getSourceLanguage()); + } + StringRef getProducer() const { return get()->getProducer(); } + bool isOptimized() const { return get()->isOptimized(); } + StringRef getFlags() const { return get()->getFlags(); } + unsigned getRunTimeVersion() const { return get()->getRuntimeVersion(); } + + DIArray getEnumTypes() const { return DIArray(get()->getEnumTypes()); } + DIArray getRetainedTypes() const { + return DIArray(get()->getRetainedTypes()); + } + DIArray getSubprograms() const { return DIArray(get()->getSubprograms()); } + DIArray getGlobalVariables() const { + return DIArray(get()->getGlobalVariables()); + } + DIArray getImportedEntities() const { + return DIArray(get()->getImportedEntities()); + } - 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. - bool Verify() const; + StringRef getSplitDebugFilename() const { + return get()->getSplitDebugFilename(); + } + unsigned getEmissionKind() const { return get()->getEmissionKind(); } }; -/// 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; - public: explicit DISubprogram(const MDNode *N = nullptr) : DIScope(N) {} + DISubprogram(const MDSubprogram *N) : DIScope(N) {} + + MDSubprogram *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDSubprogram *() const { return get(); } + MDSubprogram *operator->() const { return get(); } + MDSubprogram &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } + + StringRef getName() const { return get()->getName(); } + StringRef getDisplayName() const { return get()->getDisplayName(); } + StringRef getLinkageName() const { return get()->getLinkageName(); } + unsigned getLineNumber() const { return get()->getLine(); } - DIScopeRef getContext() const { return getFieldAs(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(7); } + /// \brief Check if this is local (like 'static' in C). + unsigned isLocalToUnit() const { return get()->isLocalToUnit(); } + unsigned isDefinition() const { return get()->isDefinition(); } - /// 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); } + unsigned getVirtuality() const { return get()->getVirtuality(); } + unsigned getVirtualIndex() const { return get()->getVirtualIndex(); } - unsigned getVirtuality() const { return getUnsignedField(10); } - unsigned getVirtualIndex() const { return getUnsignedField(11); } + unsigned getFlags() const { return get()->getFlags(); } - DITypeRef getContainingType() const { return getFieldAs(12); } + unsigned isOptimized() const { return get()->isOptimized(); } - unsigned getFlags() const { return getUnsignedField(13); } + /// \brief Get the beginning of the scope of the function (not the name). + unsigned getScopeLineNumber() const { return get()->getScopeLine(); } - unsigned isArtificial() const { - return (getUnsignedField(13) & FlagArtificial) != 0; + DIScopeRef getContext() const { return DIScopeRef::get(get()->getScope()); } + DISubroutineType getType() const { + return DISubroutineType(get()->getType()); } - /// isPrivate - Return true if this subprogram has "private" - /// access specifier. + + DITypeRef getContainingType() const { + return DITypeRef::get(get()->getContainingType()); + } + + /// \brief Check if this provides debugging information for the function F. + bool describes(const Function *F); + + Function *getFunction() const; + + void replaceFunction(Function *F) { + if (auto *N = get()) + N->replaceFunction(F); + } + DIArray getTemplateParams() const { + return DIArray(get()->getTemplateParams()); + } + DISubprogram getFunctionDeclaration() const { + return DISubprogram(get()->getDeclaration()); + } + MDNode *getVariablesNodes() const { return getVariables(); } + DIArray getVariables() const { return DIArray(get()->getVariables()); } + + unsigned isArtificial() const { return (getFlags() & FlagArtificial) != 0; } + /// \brief Check for the "private" access specifier. bool isPrivate() const { return (getFlags() & FlagAccessibility) == FlagPrivate; } - /// isProtected - Return true if this subprogram has "protected" - /// access specifier. + /// \brief Check for the "protected" access specifier. bool isProtected() const { return (getFlags() & FlagAccessibility) == FlagProtected; } - /// isPublic - Return true if this subprogram has "public" - /// access specifier. + /// \brief Check for the "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; - } - - /// Return true if this subprogram is a C++11 reference-qualified - /// non-static member function (void foo() &). + /// \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 (getUnsignedField(13) & FlagLValueReference) != 0; + return (getFlags() & FlagLValueReference) != 0; } - /// Return true if this subprogram is a C++11 - /// rvalue-reference-qualified non-static member function - /// (void foo() &&). + /// \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 (getUnsignedField(13) & FlagRValueReference) != 0; - } - - unsigned isOptimized() const; - - /// 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. - bool describes(const Function *F); - - Function *getFunction() const { return getFunctionField(15); } - void replaceFunction(Function *F) { replaceFunctionField(15, F); } - DIArray getTemplateParams() const { return getFieldAs(16); } - DISubprogram getFunctionDeclaration() const { - return getFieldAs(17); + return (getFlags() & FlagRValueReference) != 0; } - 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); } }; -/// 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(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - unsigned getColumnNumber() const { return getUnsignedField(4); } - bool Verify() const; + DILexicalBlock(const MDLexicalBlockBase *N) : DIScope(N) {} + + MDLexicalBlockBase *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDLexicalBlockBase *() const { return get(); } + MDLexicalBlockBase *operator->() const { return get(); } + MDLexicalBlockBase &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } + + DIScope getContext() const { return DIScope(get()->getScope()); } + unsigned getLineNumber() const { + if (auto *N = dyn_cast(get())) + return N->getLine(); + return 0; + } + unsigned getColumnNumber() const { + if (auto *N = dyn_cast(get())) + return N->getColumn(); + return 0; + } }; -/// 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 { - if (getScope().isSubprogram()) - return getScope(); - return getScope().getContext(); - } - unsigned getLineNumber() const { return getScope().getLineNumber(); } - unsigned getColumnNumber() const { return getScope().getColumnNumber(); } - DILexicalBlock getScope() const { return getFieldAs(2); } - unsigned getDiscriminator() const { return getUnsignedField(3); } - bool Verify() const; + DILexicalBlockFile(const MDLexicalBlockFile *N) : DIScope(N) {} + + MDLexicalBlockFile *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDLexicalBlockFile *() const { return get(); } + MDLexicalBlockFile *operator->() const { return get(); } + MDLexicalBlockFile &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } + + DIScope getContext() const { return get()->getScope(); } + unsigned getDiscriminator() const { return get()->getDiscriminator(); } }; -/// 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) {} - DIScope getContext() const { return getFieldAs(2); } - StringRef getName() const { return getStringField(3); } - unsigned getLineNumber() const { return getUnsignedField(4); } - bool Verify() const; + DINameSpace(const MDNamespace *N) : DIScope(N) {} + + MDNamespace *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDNamespace *() const { return get(); } + MDNamespace *operator->() const { return get(); } + MDNamespace &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } + + StringRef getName() const { return get()->getName(); } + unsigned getLineNumber() const { return get()->getLine(); } + DIScope getContext() const { return DIScope(get()->getScope()); } }; -/// 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) {} - - DIScopeRef getContext() const { return getFieldAs(1); } - StringRef getName() const { return getStringField(2); } - DITypeRef getType() const { return getFieldAs(3); } - StringRef getFilename() const { return getFieldAs(4).getFilename(); } - StringRef getDirectory() const { - return getFieldAs(4).getDirectory(); - } - unsigned getLineNumber() const { return getUnsignedField(5); } - unsigned getColumnNumber() const { return getUnsignedField(6); } - bool Verify() const; + : DIDescriptor(N) {} + DITemplateTypeParameter(const MDTemplateTypeParameter *N) : DIDescriptor(N) {} + + MDTemplateTypeParameter *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDTemplateTypeParameter *() const { return get(); } + MDTemplateTypeParameter *operator->() const { return get(); } + MDTemplateTypeParameter &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } + + StringRef getName() const { return get()->getName(); } + + DITypeRef getType() const { return DITypeRef::get(get()->getType()); } }; -/// 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) {} - - DIScopeRef getContext() const { return getFieldAs(1); } - StringRef getName() const { return getStringField(2); } - DITypeRef getType() const { return getFieldAs(3); } - Value *getValue() const; - StringRef getFilename() const { return getFieldAs(5).getFilename(); } - StringRef getDirectory() const { - return getFieldAs(5).getDirectory(); - } - unsigned getLineNumber() const { return getUnsignedField(6); } - unsigned getColumnNumber() const { return getUnsignedField(7); } - bool Verify() const; + : DIDescriptor(N) {} + DITemplateValueParameter(const MDTemplateValueParameter *N) + : DIDescriptor(N) {} + + MDTemplateValueParameter *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDTemplateValueParameter *() const { return get(); } + MDTemplateValueParameter *operator->() const { return get(); } + MDTemplateValueParameter &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } + + StringRef getName() const { return get()->getName(); } + DITypeRef getType() const { return DITypeRef::get(get()->getType()); } + Metadata *getValue() const { return get()->getValue(); } }; -/// 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; + DIFile getFile() const { return DIFile(get()->getFile()); } public: explicit DIGlobalVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} + DIGlobalVariable(const MDGlobalVariable *N) : DIDescriptor(N) {} - DIScope getContext() const { return getFieldAs(2); } - StringRef getName() const { return getStringField(3); } - StringRef getDisplayName() const { return getStringField(4); } - StringRef getLinkageName() const { return getStringField(5); } - StringRef getFilename() const { return getFieldAs(6).getFilename(); } - StringRef getDirectory() const { - return getFieldAs(6).getDirectory(); + MDGlobalVariable *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDGlobalVariable *() const { return get(); } + MDGlobalVariable *operator->() const { return get(); } + MDGlobalVariable &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); } - unsigned getLineNumber() const { return getUnsignedField(7); } - DITypeRef getType() const { return getFieldAs(8); } - unsigned isLocalToUnit() const { return getUnsignedField(9); } - unsigned isDefinition() const { return getUnsignedField(10); } + StringRef getName() const { return get()->getName(); } + StringRef getDisplayName() const { return get()->getDisplayName(); } + StringRef getLinkageName() const { return get()->getLinkageName(); } + unsigned getLineNumber() const { return get()->getLine(); } + unsigned isLocalToUnit() const { return get()->isLocalToUnit(); } + unsigned isDefinition() const { return get()->isDefinition(); } + + DIScope getContext() const { return DIScope(get()->getScope()); } + StringRef getFilename() const { return getFile().getFilename(); } + StringRef getDirectory() const { return getFile().getDirectory(); } + DITypeRef getType() const { return DITypeRef::get(get()->getType()); } - GlobalVariable *getGlobal() const { return getGlobalVariableField(11); } - Constant *getConstant() const { return getConstantField(11); } + GlobalVariable *getGlobal() const; + Constant *getConstant() const { + if (auto *N = get()) + if (auto *C = dyn_cast_or_null(N->getVariable())) + return C->getValue(); + return nullptr; + } DIDerivedType getStaticDataMemberDeclaration() const { - return getFieldAs(12); + return DIDerivedType(get()->getStaticDataMemberDeclaration()); } - - /// 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; + unsigned getFlags() const { return get()->getFlags(); } public: explicit DIVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} + DIVariable(const MDLocalVariable *N) : DIDescriptor(N) {} - DIScope getContext() const { return getFieldAs(1); } - StringRef getName() const { return getStringField(2); } - DIFile getFile() const { return getFieldAs(3); } - unsigned getLineNumber() const { return (getUnsignedField(4) << 8) >> 8; } - unsigned getArgNumber() const { - unsigned L = getUnsignedField(4); - return L >> 24; + MDLocalVariable *get() const { + return cast_or_null(DIDescriptor::get()); } - DITypeRef getType() const { return getFieldAs(5); } + operator MDLocalVariable *() const { return get(); } + MDLocalVariable *operator->() const { return get(); } + MDLocalVariable &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } + + StringRef getName() const { return get()->getName(); } + unsigned getLineNumber() const { return get()->getLine(); } + unsigned getArgNumber() const { return get()->getArg(); } - /// isArtificial - Return true if this variable is marked as "artificial". + DIScope getContext() const { return DIScope(get()->getScope()); } + DIFile getFile() const { return DIFile(get()->getFile()); } + DITypeRef getType() const { return DITypeRef::get(get()->getType()); } + + /// \brief Return true if this variable is marked as "artificial". bool isArtificial() const { - return (getUnsignedField(6) & FlagArtificial) != 0; + return (getFlags() & FlagArtificial) != 0; } bool isObjectPointer() const { - return (getUnsignedField(6) & FlagObjectPointer) != 0; + return (getFlags() & FlagObjectPointer) != 0; } - /// \brief Return true if this variable is represented as a pointer. - bool isIndirect() const { - return (getUnsignedField(6) & FlagIndirectVariable) != 0; - } + /// \brief If this variable is inlined then return inline location. + MDNode *getInlinedAt() const { return DIDescriptor(get()->getInlinedAt()); } - /// getInlinedAt - If this variable is inlined then return inline location. - MDNode *getInlinedAt() const; - - /// Verify - Verify that a variable descriptor is well formed. - bool Verify() 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); - /// 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; }; -/// DIExpression - 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; - public: explicit DIExpression(const MDNode *N = nullptr) : DIDescriptor(N) {} + DIExpression(const MDExpression *N) : DIDescriptor(N) {} - /// Verify - Verify that a variable descriptor is well formed. - bool Verify() const; + MDExpression *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDExpression *() const { return get(); } + MDExpression *operator->() const { return get(); } + MDExpression &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } /// \brief Return the number of elements in the complex expression. - unsigned getNumElements() const { - if (!DbgNode) - return 0; - unsigned N = DbgNode->getNumOperands(); - assert(N > 0 && "missing tag"); - return N - 1; - } + unsigned getNumElements() const { return get()->getNumElements(); } /// \brief return the Idx'th complex address element. - uint64_t getElement(unsigned Idx) const; - - /// 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; + uint64_t getElement(unsigned I) const { return get()->getElement(I); } + + /// \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; + MDExpression::element_iterator I; + Operand() {} + Operand(MDExpression::element_iterator 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 { + MDExpression::element_iterator In = I; + std::advance(In, N); + return *In; + } + operator uint64_t () const { return *I; } + /// \brief Returns underlying MDExpression::element_iterator. + const MDExpression::element_iterator &getBase() const { return I; } + /// \brief Returns the next operand. + iterator getNext() const; + }; + + /// \brief An iterator for DIExpression elements. + class iterator : public std::iterator { + friend class Operand; + MDExpression::element_iterator I; + Operand Tmp; + + public: + iterator(MDExpression::element_iterator I) : I(I) {} + 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 { return get()->elements_begin(); } + iterator end() const { return get()->elements_end(); } }; -/// DILocation - This object holds location information. This object -/// is not associated with any DWARF tag. +/// \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) {} + DILocation(const MDLocation *N) : DIDescriptor(N) {} + + MDLocation *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDLocation *() const { return get(); } + MDLocation *operator->() const { return get(); } + MDLocation &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } - unsigned getLineNumber() const { return getUnsignedField(0); } - unsigned getColumnNumber() const { return getUnsignedField(1); } - DIScope getScope() const { return getFieldAs(2); } - DILocation getOrigLocation() const { return getFieldAs(3); } + unsigned getLineNumber() const { return get()->getLine(); } + unsigned getColumnNumber() const { return get()->getColumn(); } + DIScope getScope() const { return DIScope(get()->getScope()); } + DILocation getOrigLocation() const { + return DILocation(get()->getInlinedAt()); + } StringRef getFilename() const { return getScope().getFilename(); } StringRef getDirectory() const { return getScope().getDirectory(); } - bool Verify() const; bool atSameLineAs(const DILocation &Other) const { 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(2).getDiscriminator() - : 0; + if (auto *F = dyn_cast(get()->getScope())) + return F->getDiscriminator(); + return 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); }; class DIObjCProperty : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {} + DIObjCProperty(const MDObjCProperty *N) : DIDescriptor(N) {} - StringRef getObjCPropertyName() const { return getStringField(1); } - DIFile getFile() const { return getFieldAs(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } + MDObjCProperty *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDObjCProperty *() const { return get(); } + MDObjCProperty *operator->() const { return get(); } + MDObjCProperty &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } + + StringRef getObjCPropertyName() const { return get()->getName(); } + DIFile getFile() const { return DIFile(get()->getFile()); } + unsigned getLineNumber() const { return get()->getLine(); } - StringRef getObjCPropertyGetterName() const { return getStringField(4); } - StringRef getObjCPropertySetterName() const { return getStringField(5); } + StringRef getObjCPropertyGetterName() const { return get()->getGetterName(); } + StringRef getObjCPropertySetterName() const { return get()->getSetterName(); } + unsigned getAttributes() const { return get()->getAttributes(); } 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(7); } - - /// Verify - Verify that a derived type descriptor is well formed. - bool Verify() const; + DIType getType() const { return DIType(get()->getType()); } }; /// \brief An imported module (C++ using directive or similar). class DIImportedEntity : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: + DIImportedEntity() = default; explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} - DIScope getContext() const { return getFieldAs(1); } - DIScopeRef getEntity() const { return getFieldAs(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - StringRef getName() const { return getStringField(4); } - bool Verify() const; + DIImportedEntity(const MDImportedEntity *N) : DIDescriptor(N) {} + + MDImportedEntity *get() const { + return cast_or_null(DIDescriptor::get()); + } + operator MDImportedEntity *() const { return get(); } + MDImportedEntity *operator->() const { return get(); } + MDImportedEntity &operator*() const { + assert(get() && "Expected valid pointer"); + return *get(); + } + + DIScope getContext() const { return DIScope(get()->getScope()); } + DIDescriptorRef getEntity() const { + return DIDescriptorRef::get(get()->getEntity()); + } + unsigned getLineNumber() const { return get()->getLine(); } + StringRef getName() const { return get()->getName(); } }; -/// getDISubprogram - Find subprogram that is enclosing this scope. +#define SIMPLIFY_DESCRIPTOR(DESC) \ + template <> struct simplify_type { \ + typedef Metadata *SimpleType; \ + static SimpleType getSimplifiedValue(const DESC &DI) { return DI; } \ + }; \ + template <> struct simplify_type : simplify_type {}; +SIMPLIFY_DESCRIPTOR(DIDescriptor) +SIMPLIFY_DESCRIPTOR(DISubrange) +SIMPLIFY_DESCRIPTOR(DIEnumerator) +SIMPLIFY_DESCRIPTOR(DIScope) +SIMPLIFY_DESCRIPTOR(DIType) +SIMPLIFY_DESCRIPTOR(DIBasicType) +SIMPLIFY_DESCRIPTOR(DIDerivedType) +SIMPLIFY_DESCRIPTOR(DICompositeType) +SIMPLIFY_DESCRIPTOR(DISubroutineType) +SIMPLIFY_DESCRIPTOR(DIFile) +SIMPLIFY_DESCRIPTOR(DICompileUnit) +SIMPLIFY_DESCRIPTOR(DISubprogram) +SIMPLIFY_DESCRIPTOR(DILexicalBlock) +SIMPLIFY_DESCRIPTOR(DILexicalBlockFile) +SIMPLIFY_DESCRIPTOR(DINameSpace) +SIMPLIFY_DESCRIPTOR(DITemplateTypeParameter) +SIMPLIFY_DESCRIPTOR(DITemplateValueParameter) +SIMPLIFY_DESCRIPTOR(DIGlobalVariable) +SIMPLIFY_DESCRIPTOR(DIVariable) +SIMPLIFY_DESCRIPTOR(DIExpression) +SIMPLIFY_DESCRIPTOR(DILocation) +SIMPLIFY_DESCRIPTOR(DIObjCProperty) +SIMPLIFY_DESCRIPTOR(DIImportedEntity) +#undef SIMPLIFY_DESCRIPTOR + +/// \brief Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); -/// getDICompositeType - 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); +/// \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); -/// getFnSpecificMDNode - Return a NameMDNode, if available, that is -/// suitable to hold function specific information. -NamedMDNode *getFnSpecificMDNode(const Module &M, DISubprogram SP); +/// \brief Find underlying composite type. +DICompositeType getDICompositeType(DIType T); -/// 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); -/// 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); +bool stripDebugInfo(Function &F); -/// 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, @@ -905,50 +1228,36 @@ class DebugInfoFinder { 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 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::const_iterator compile_unit_iterator; typedef SmallVectorImpl::const_iterator subprogram_iterator; - typedef SmallVectorImpl::const_iterator global_variable_iterator; + typedef SmallVectorImpl::const_iterator + global_variable_iterator; typedef SmallVectorImpl::const_iterator type_iterator; typedef SmallVectorImpl::const_iterator scope_iterator; @@ -979,14 +1288,15 @@ public: unsigned scope_count() const { return Scopes.size(); } private: - SmallVector CUs; // Compile Units - SmallVector SPs; // Subprograms - SmallVector GVs; // Global Variables; - SmallVector TYs; // Types - SmallVector Scopes; // Scopes + SmallVector CUs; + SmallVector SPs; + SmallVector GVs; + SmallVector TYs; + SmallVector Scopes; SmallPtrSet NodesSeen; DITypeIdentifierMap TypeIdentifierMap; - /// Specify if TypeIdentifierMap is initialized. + + /// \brief Specify if TypeIdentifierMap is initialized. bool TypeMapInitialized; };