From 2c3e0051c31c3f5b2328b447eadf1cf9c4427442 Mon Sep 17 00:00:00 2001 From: Pirama Arumuga Nainar Date: Wed, 6 May 2015 11:46:36 -0700 Subject: Update aosp/master LLVM for rebase to r235153 Change-Id: I9bf53792f9fc30570e81a8d80d296c681d005ea7 (cherry picked from commit 0c7f116bb6950ef819323d855415b2f2b0aad987) --- include/llvm/IR/DebugInfoMetadata.h | 884 ++++++++++++++++++++++++++++-------- 1 file changed, 689 insertions(+), 195 deletions(-) (limited to 'include/llvm/IR/DebugInfoMetadata.h') diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index d7563fc..62373c4 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -41,6 +41,101 @@ namespace llvm { +/// \brief Pointer union between a subclass of DebugNode and MDString. +/// +/// \a MDCompositeType can be referenced via an \a MDString unique identifier. +/// This class allows some type safety in the face of that, requiring either a +/// node of a particular type or an \a MDString. +template class TypedDebugNodeRef { + const Metadata *MD = nullptr; + +public: + TypedDebugNodeRef() = default; + TypedDebugNodeRef(std::nullptr_t) {} + + /// \brief Construct from a raw pointer. + explicit TypedDebugNodeRef(const Metadata *MD) : MD(MD) { + assert((!MD || isa(MD) || isa(MD)) && "Expected valid ref"); + } + + template + TypedDebugNodeRef( + const TypedDebugNodeRef &X, + typename std::enable_if::value>::type * = + nullptr) + : MD(X) {} + + operator Metadata *() const { return const_cast(MD); } + + bool operator==(const TypedDebugNodeRef &X) const { return MD == X.MD; }; + bool operator!=(const TypedDebugNodeRef &X) const { return MD != X.MD; }; + + /// \brief Create a reference. + /// + /// Get a reference to \c N, using an \a MDString reference if available. + static TypedDebugNodeRef get(const T *N); + + template T *resolve(const MapTy &Map) const { + if (!MD) + return nullptr; + + if (auto *Typed = dyn_cast(MD)) + return const_cast(Typed); + + auto *S = cast(MD); + auto I = Map.find(S); + assert(I != Map.end() && "Missing identifier in type map"); + return cast(I->second); + } +}; + +typedef TypedDebugNodeRef DebugNodeRef; +typedef TypedDebugNodeRef MDScopeRef; +typedef TypedDebugNodeRef MDTypeRef; + +class MDTypeRefArray { + const MDTuple *N = nullptr; + +public: + MDTypeRefArray(const MDTuple *N) : N(N) {} + + explicit operator bool() const { return get(); } + explicit operator MDTuple *() const { return get(); } + + MDTuple *get() const { return const_cast(N); } + MDTuple *operator->() const { return get(); } + MDTuple &operator*() const { return *get(); } + + // FIXME: Fix callers and remove condition on N. + unsigned size() const { return N ? N->getNumOperands() : 0u; } + MDTypeRef operator[](unsigned I) const { return MDTypeRef(N->getOperand(I)); } + + class iterator : std::iterator { + MDNode::op_iterator I = nullptr; + + public: + iterator() = default; + explicit iterator(MDNode::op_iterator I) : I(I) {} + MDTypeRef operator*() const { return MDTypeRef(*I); } + iterator &operator++() { + ++I; + return *this; + } + iterator operator++(int) { + iterator Temp(*this); + ++I; + return Temp; + } + bool operator==(const iterator &X) const { return I == X.I; } + bool operator!=(const iterator &X) const { return I != X.I; } + }; + + // FIXME: Fix callers and remove condition on N. + iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } + iterator end() const { return N ? iterator(N->op_end()) : iterator(); } +}; + /// \brief Tagged DWARF-like metadata node. /// /// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, @@ -57,7 +152,7 @@ protected: assert(Tag < 1u << 16); SubclassData16 = Tag; } - ~DebugNode() {} + ~DebugNode() = default; template Ty *getOperandAs(unsigned I) const { return cast_or_null(getOperand(I)); @@ -78,6 +173,28 @@ protected: public: unsigned getTag() const { return SubclassData16; } + /// \brief Debug info flags. + /// + /// The three accessibility flags are mutually exclusive and rolled together + /// in the first two bits. + enum DIFlags { +#define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, +#include "llvm/IR/DebugInfoFlags.def" + FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic + }; + + static unsigned getFlag(StringRef Flag); + static const char *getFlagString(unsigned Flag); + + /// \brief Split up a flags bitfield. + /// + /// Split \c Flags into \c SplitFlags, a vector of its components. Returns + /// any remaining (unrecognized) bits. + static unsigned splitFlags(unsigned Flags, + SmallVectorImpl &SplitFlags); + + DebugNodeRef getRef() const { return DebugNodeRef::get(this); } + static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: @@ -106,6 +223,18 @@ public: } }; +template +struct simplify_type> { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const TypedDebugNodeRef &MD) { + return MD; + } +}; + +template +struct simplify_type> + : simplify_type> {}; + /// \brief Generic tagged DWARF-like metadata node. /// /// An un-specialized DWARF-like metadata node. The first operand is a @@ -192,27 +321,30 @@ class MDSubrange : public DebugNode { friend class MDNode; int64_t Count; - int64_t Lo; + int64_t LowerBound; - MDSubrange(LLVMContext &C, StorageType Storage, int64_t Count, int64_t Lo) + MDSubrange(LLVMContext &C, StorageType Storage, int64_t Count, + int64_t LowerBound) : DebugNode(C, MDSubrangeKind, Storage, dwarf::DW_TAG_subrange_type, None), - Count(Count), Lo(Lo) {} - ~MDSubrange() {} + Count(Count), LowerBound(LowerBound) {} + ~MDSubrange() = default; - static MDSubrange *getImpl(LLVMContext &Context, int64_t Count, int64_t Lo, - StorageType Storage, bool ShouldCreate = true); + static MDSubrange *getImpl(LLVMContext &Context, int64_t Count, + int64_t LowerBound, StorageType Storage, + bool ShouldCreate = true); TempMDSubrange cloneImpl() const { - return getTemporary(getContext(), getCount(), getLo()); + return getTemporary(getContext(), getCount(), getLowerBound()); } public: - DEFINE_MDNODE_GET(MDSubrange, (int64_t Count, int64_t Lo = 0), (Count, Lo)) + DEFINE_MDNODE_GET(MDSubrange, (int64_t Count, int64_t LowerBound = 0), + (Count, LowerBound)) TempMDSubrange clone() const { return cloneImpl(); } - int64_t getLo() const { return Lo; } + int64_t getLowerBound() const { return LowerBound; } int64_t getCount() const { return Count; } static bool classof(const Metadata *MD) { @@ -234,7 +366,7 @@ class MDEnumerator : public DebugNode { ArrayRef Ops) : DebugNode(C, MDEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), Value(Value) {} - ~MDEnumerator() {} + ~MDEnumerator() = default; static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value, StringRef Name, StorageType Storage, @@ -279,20 +411,30 @@ protected: MDScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef Ops) : DebugNode(C, ID, Storage, Tag, Ops) {} - ~MDScope() {} + ~MDScope() = default; public: - /// \brief Return the underlying file. + MDFile *getFile() const { return cast_or_null(getRawFile()); } + + inline StringRef getFilename() const; + inline StringRef getDirectory() const; + + StringRef getName() const; + MDScopeRef getScope() const; + + /// \brief Return the raw underlying file. /// /// An \a MDFile is an \a MDScope, but it doesn't point at a separate file /// (it\em is the file). If \c this is an \a MDFile, we need to return \c /// this. Otherwise, return the first operand, which is where all other /// subclasses store their file pointer. - Metadata *getFile() const { + Metadata *getRawFile() const { return isa(this) ? const_cast(this) : static_cast(getOperand(0)); } + MDScopeRef getRef() const { return MDScopeRef::get(this); } + static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: @@ -322,7 +464,7 @@ class MDFile : public MDScope { MDFile(LLVMContext &C, StorageType Storage, ArrayRef Ops) : MDScope(C, MDFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {} - ~MDFile() {} + ~MDFile() = default; static MDFile *getImpl(LLVMContext &Context, StringRef Filename, StringRef Directory, StorageType Storage, @@ -358,6 +500,18 @@ public: } }; +StringRef MDScope::getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; +} + +StringRef MDScope::getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; +} + /// \brief Base class for types. /// /// TODO: Remove the hardcoded name and context, since many types don't use @@ -377,7 +531,7 @@ protected: : MDScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags), SizeInBits(SizeInBits), AlignInBits(AlignInBits), OffsetInBits(OffsetInBits) {} - ~MDType() {} + ~MDType() = default; public: TempMDType clone() const { @@ -390,9 +544,11 @@ public: uint64_t getOffsetInBits() const { return OffsetInBits; } unsigned getFlags() const { return Flags; } - Metadata *getScope() const { return getOperand(1); } + MDScopeRef getScope() const { return MDScopeRef(getRawScope()); } StringRef getName() const { return getStringOperand(2); } + + Metadata *getRawScope() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs(2); } void setFlags(unsigned NewFlags) { @@ -400,6 +556,31 @@ public: Flags = NewFlags; } + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } + bool isForwardDecl() const { return getFlags() & FlagFwdDecl; } + bool isAppleBlockExtension() const { return getFlags() & FlagAppleBlock; } + bool isBlockByrefStruct() const { return getFlags() & FlagBlockByrefStruct; } + bool isVirtual() const { return getFlags() & FlagVirtual; } + bool isArtificial() const { return getFlags() & FlagArtificial; } + bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } + bool isObjcClassComplete() const { + return getFlags() & FlagObjcClassComplete; + } + bool isVector() const { return getFlags() & FlagVector; } + bool isStaticMember() const { return getFlags() & FlagStaticMember; } + bool isLValueReference() const { return getFlags() & FlagLValueReference; } + bool isRValueReference() const { return getFlags() & FlagRValueReference; } + + MDTypeRef getRef() const { return MDTypeRef::get(this); } + static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: @@ -413,7 +594,7 @@ public: } }; -/// \brief Basic type. +/// \brief Basic type, like 'int' or 'float'. /// /// TODO: Split out DW_TAG_unspecified_type. /// TODO: Drop unused accessors. @@ -429,7 +610,7 @@ class MDBasicType : public MDType { : MDType(C, MDBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, 0, Ops), Encoding(Encoding) {} - ~MDBasicType() {} + ~MDBasicType() = default; static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, uint64_t SizeInBits, @@ -480,10 +661,11 @@ protected: ArrayRef Ops) : MDType(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags, Ops) {} - ~MDDerivedTypeBase() {} + ~MDDerivedTypeBase() = default; public: - Metadata *getBaseType() const { return getOperand(3); } + MDTypeRef getBaseType() const { return MDTypeRef(getRawBaseType()); } + Metadata *getRawBaseType() const { return getOperand(3); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDDerivedTypeKind || @@ -507,11 +689,11 @@ class MDDerivedType : public MDDerivedTypeBase { uint64_t OffsetInBits, unsigned Flags, ArrayRef Ops) : MDDerivedTypeBase(C, MDDerivedTypeKind, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags, Ops) {} - ~MDDerivedType() {} + ~MDDerivedType() = default; static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Name, Metadata *File, unsigned Line, - Metadata *Scope, Metadata *BaseType, + StringRef Name, MDFile *File, unsigned Line, + MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, Metadata *ExtraData, StorageType Storage, @@ -545,11 +727,10 @@ public: (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, ExtraData)) DEFINE_MDNODE_GET(MDDerivedType, - (unsigned Tag, StringRef Name, Metadata *File, - unsigned Line, Metadata *Scope, Metadata *BaseType, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - Metadata *ExtraData = nullptr), + (unsigned Tag, StringRef Name, MDFile *File, unsigned Line, + MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, Metadata *ExtraData = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, ExtraData)) @@ -562,7 +743,25 @@ public: /// /// TODO: Separate out types that need this extra operand: pointer-to-member /// types and member fields (static members and ivars). - Metadata *getExtraData() const { return getOperand(4); } + Metadata *getExtraData() const { return getRawExtraData(); } + Metadata *getRawExtraData() const { return getOperand(4); } + + /// \brief Get casted version of extra data. + /// @{ + MDTypeRef getClassType() const { + assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); + return MDTypeRef(getExtraData()); + } + MDObjCProperty *getObjCProperty() const { + return dyn_cast_or_null(getExtraData()); + } + Constant *getConstant() const { + assert(getTag() == dwarf::DW_TAG_member && isStaticMember()); + if (auto *C = cast_or_null(getExtraData())) + return C->getValue(); + return nullptr; + } + /// @} static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDDerivedTypeKind; @@ -584,15 +783,28 @@ protected: : MDDerivedTypeBase(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags, Ops), RuntimeLang(RuntimeLang) {} - ~MDCompositeTypeBase() {} + ~MDCompositeTypeBase() = default; public: - Metadata *getElements() const { return getOperand(4); } - Metadata *getVTableHolder() const { return getOperand(5); } - Metadata *getTemplateParams() const { return getOperand(6); } + /// \brief Get the elements of the composite type. + /// + /// \note Calling this is only valid for \a MDCompositeType. This assertion + /// can be removed once \a MDSubroutineType has been separated from + /// "composite types". + DebugNodeArray getElements() const { + assert(!isa(this) && "no elements for DISubroutineType"); + return cast_or_null(getRawElements()); + } + MDTypeRef getVTableHolder() const { return MDTypeRef(getRawVTableHolder()); } + MDTemplateParameterArray getTemplateParams() const { + return cast_or_null(getRawTemplateParams()); + } StringRef getIdentifier() const { return getStringOperand(7); } unsigned getRuntimeLang() const { return RuntimeLang; } + Metadata *getRawElements() const { return getOperand(4); } + Metadata *getRawVTableHolder() const { return getOperand(5); } + Metadata *getRawTemplateParams() const { return getOperand(6); } MDString *getRawIdentifier() const { return getOperandAs(7); } /// \brief Replace operands. @@ -601,20 +813,19 @@ public: /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track /// of its movement if necessary. /// @{ - void replaceElements(MDTuple *Elements) { + void replaceElements(DebugNodeArray Elements) { #ifndef NDEBUG - if (auto *Old = cast_or_null(getElements())) - for (const auto &Op : Old->operands()) - assert(std::find(Elements->op_begin(), Elements->op_end(), Op) && - "Lost a member during member list replacement"); + for (DebugNode *Op : getElements()) + assert(std::find(Elements->op_begin(), Elements->op_end(), Op) && + "Lost a member during member list replacement"); #endif - replaceOperandWith(4, Elements); + replaceOperandWith(4, Elements.get()); } - void replaceVTableHolder(Metadata *VTableHolder) { + void replaceVTableHolder(MDTypeRef VTableHolder) { replaceOperandWith(5, VTableHolder); } - void replaceTemplateParams(MDTuple *TemplateParams) { - replaceOperandWith(6, TemplateParams); + void replaceTemplateParams(MDTemplateParameterArray TemplateParams) { + replaceOperandWith(6, TemplateParams.get()); } /// @} @@ -639,20 +850,20 @@ class MDCompositeType : public MDCompositeTypeBase { : MDCompositeTypeBase(C, MDCompositeTypeKind, Storage, Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, Flags, Ops) {} - ~MDCompositeType() {} + ~MDCompositeType() = default; static MDCompositeType * getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, - unsigned Line, Metadata *Scope, Metadata *BaseType, + unsigned Line, MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, - uint64_t Flags, Metadata *Elements, unsigned RuntimeLang, - Metadata *VTableHolder, Metadata *TemplateParams, + uint64_t Flags, DebugNodeArray Elements, unsigned RuntimeLang, + MDTypeRef VTableHolder, MDTemplateParameterArray TemplateParams, StringRef Identifier, StorageType Storage, bool ShouldCreate = true) { - return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, - Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, - Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, - getCanonicalMDString(Context, Identifier), Storage, - ShouldCreate); + return getImpl( + Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, + BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), + RuntimeLang, VTableHolder, TemplateParams.get(), + getCanonicalMDString(Context, Identifier), Storage, ShouldCreate); } static MDCompositeType * getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, @@ -672,12 +883,12 @@ class MDCompositeType : public MDCompositeTypeBase { public: DEFINE_MDNODE_GET(MDCompositeType, - (unsigned Tag, StringRef Name, Metadata *File, - unsigned Line, Metadata *Scope, Metadata *BaseType, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, Metadata *Elements, - unsigned RuntimeLang, Metadata *VTableHolder, - Metadata *TemplateParams = nullptr, + (unsigned Tag, StringRef Name, MDFile *File, unsigned Line, + MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DebugNodeArray Elements, + unsigned RuntimeLang, MDTypeRef VTableHolder, + MDTemplateParameterArray TemplateParams = nullptr, StringRef Identifier = ""), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, @@ -701,6 +912,14 @@ public: } }; +template TypedDebugNodeRef TypedDebugNodeRef::get(const T *N) { + if (N) + if (auto *Composite = dyn_cast(N)) + if (auto *S = Composite->getRawIdentifier()) + return TypedDebugNodeRef(S); + return TypedDebugNodeRef(N); +} + /// \brief Type array for a subprogram. /// /// TODO: Detach from CompositeType, and fold the array of types in directly @@ -714,9 +933,15 @@ class MDSubroutineType : public MDCompositeTypeBase { : MDCompositeTypeBase(C, MDSubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type, 0, 0, 0, 0, 0, Flags, Ops) {} - ~MDSubroutineType() {} + ~MDSubroutineType() = default; static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags, + MDTypeRefArray TypeArray, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Flags, TypeArray.get(), Storage, ShouldCreate); + } + static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags, Metadata *TypeArray, StorageType Storage, bool ShouldCreate = true); @@ -725,12 +950,18 @@ class MDSubroutineType : public MDCompositeTypeBase { } public: + DEFINE_MDNODE_GET(MDSubroutineType, + (unsigned Flags, MDTypeRefArray TypeArray), + (Flags, TypeArray)) DEFINE_MDNODE_GET(MDSubroutineType, (unsigned Flags, Metadata *TypeArray), (Flags, TypeArray)) TempMDSubroutineType clone() const { return cloneImpl(); } - Metadata *getTypeArray() const { return getElements(); } + MDTypeRefArray getTypeArray() const { + return cast_or_null(getRawTypeArray()); + } + Metadata *getRawTypeArray() const { return getRawElements(); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDSubroutineTypeKind; @@ -753,22 +984,23 @@ class MDCompileUnit : public MDScope { : MDScope(C, MDCompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind) {} - ~MDCompileUnit() {} + ~MDCompileUnit() = default; static MDCompileUnit * - getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + getImpl(LLVMContext &Context, unsigned SourceLanguage, MDFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, - unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, - Metadata *Subprograms, Metadata *GlobalVariables, - Metadata *ImportedEntities, StorageType Storage, + unsigned EmissionKind, MDCompositeTypeArray EnumTypes, + MDTypeArray RetainedTypes, MDSubprogramArray Subprograms, + MDGlobalVariableArray GlobalVariables, + MDImportedEntityArray ImportedEntities, StorageType Storage, bool ShouldCreate = true) { - return getImpl(Context, SourceLanguage, File, - getCanonicalMDString(Context, Producer), IsOptimized, - getCanonicalMDString(Context, Flags), RuntimeVersion, - getCanonicalMDString(Context, SplitDebugFilename), - EmissionKind, EnumTypes, RetainedTypes, Subprograms, - GlobalVariables, ImportedEntities, Storage, ShouldCreate); + return getImpl( + Context, SourceLanguage, File, getCanonicalMDString(Context, Producer), + IsOptimized, getCanonicalMDString(Context, Flags), RuntimeVersion, + getCanonicalMDString(Context, SplitDebugFilename), EmissionKind, + EnumTypes.get(), RetainedTypes.get(), Subprograms.get(), + GlobalVariables.get(), ImportedEntities.get(), Storage, ShouldCreate); } static MDCompileUnit * getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, @@ -789,12 +1021,13 @@ class MDCompileUnit : public MDScope { public: DEFINE_MDNODE_GET(MDCompileUnit, - (unsigned SourceLanguage, Metadata *File, - StringRef Producer, bool IsOptimized, StringRef Flags, - unsigned RuntimeVersion, StringRef SplitDebugFilename, - unsigned EmissionKind, Metadata *EnumTypes, - Metadata *RetainedTypes, Metadata *Subprograms, - Metadata *GlobalVariables, Metadata *ImportedEntities), + (unsigned SourceLanguage, MDFile *File, StringRef Producer, + bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, + StringRef SplitDebugFilename, unsigned EmissionKind, + MDCompositeTypeArray EnumTypes, MDTypeArray RetainedTypes, + MDSubprogramArray Subprograms, + MDGlobalVariableArray GlobalVariables, + MDImportedEntityArray ImportedEntities), (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms, GlobalVariables, @@ -820,17 +1053,32 @@ public: StringRef getProducer() const { return getStringOperand(1); } StringRef getFlags() const { return getStringOperand(2); } StringRef getSplitDebugFilename() const { return getStringOperand(3); } - Metadata *getEnumTypes() const { return getOperand(4); } - Metadata *getRetainedTypes() const { return getOperand(5); } - Metadata *getSubprograms() const { return getOperand(6); } - Metadata *getGlobalVariables() const { return getOperand(7); } - Metadata *getImportedEntities() const { return getOperand(8); } + MDCompositeTypeArray getEnumTypes() const { + return cast_or_null(getRawEnumTypes()); + } + MDTypeArray getRetainedTypes() const { + return cast_or_null(getRawRetainedTypes()); + } + MDSubprogramArray getSubprograms() const { + return cast_or_null(getRawSubprograms()); + } + MDGlobalVariableArray getGlobalVariables() const { + return cast_or_null(getRawGlobalVariables()); + } + MDImportedEntityArray getImportedEntities() const { + return cast_or_null(getRawImportedEntities()); + } MDString *getRawProducer() const { return getOperandAs(1); } MDString *getRawFlags() const { return getOperandAs(2); } MDString *getRawSplitDebugFilename() const { return getOperandAs(3); } + Metadata *getRawEnumTypes() const { return getOperand(4); } + Metadata *getRawRetainedTypes() const { return getOperand(5); } + Metadata *getRawSubprograms() const { return getOperand(6); } + Metadata *getRawGlobalVariables() const { return getOperand(7); } + Metadata *getRawImportedEntities() const { return getOperand(8); } /// \brief Replace arrays. /// @@ -838,8 +1086,12 @@ public: /// deleted on a uniquing collision. In practice, uniquing collisions on \a /// MDCompileUnit should be fairly rare. /// @{ - void replaceSubprograms(MDTuple *N) { replaceOperandWith(6, N); } - void replaceGlobalVariables(MDTuple *N) { replaceOperandWith(7, N); } + void replaceSubprograms(MDSubprogramArray N) { + replaceOperandWith(6, N.get()); + } + void replaceGlobalVariables(MDGlobalVariableArray N) { + replaceOperandWith(7, N.get()); + } /// @} static bool classof(const Metadata *MD) { @@ -857,9 +1109,15 @@ protected: MDLocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef Ops) : MDScope(C, ID, Storage, Tag, Ops) {} - ~MDLocalScope() {} + ~MDLocalScope() = default; public: + /// \brief Get the subprogram for this scope. + /// + /// Return this if it's an \a MDSubprogram; otherwise, look up the scope + /// chain. + MDSubprogram *getSubprogram() const; + static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDSubprogramKind || MD->getMetadataID() == MDLexicalBlockKind || @@ -914,12 +1172,58 @@ public: unsigned getLine() const { return SubclassData32; } unsigned getColumn() const { return SubclassData16; } MDLocalScope *getScope() const { - return cast_or_null(getRawScope()); + return cast(getRawScope()); } MDLocation *getInlinedAt() const { return cast_or_null(getRawInlinedAt()); } + MDFile *getFile() const { return getScope()->getFile(); } + StringRef getFilename() const { return getScope()->getFilename(); } + StringRef getDirectory() const { return getScope()->getDirectory(); } + + /// \brief Get the scope where this is inlined. + /// + /// Walk through \a getInlinedAt() and return \a getScope() from the deepest + /// location. + MDLocalScope *getInlinedAtScope() const { + if (auto *IA = getInlinedAt()) + return IA->getInlinedAtScope(); + return getScope(); + } + + /// \brief Check whether this can be discriminated from another location. + /// + /// Check \c this can be discriminated from \c RHS in a linetable entry. + /// Scope and inlined-at chains are not recorded in the linetable, so they + /// cannot be used to distinguish basic blocks. + /// + /// The current implementation is weaker than it should be, since it just + /// checks filename and line. + /// + /// FIXME: Add a check for getDiscriminator(). + /// FIXME: Add a check for getColumn(). + /// FIXME: Change the getFilename() check to getFile() (or add one for + /// getDirectory()). + bool canDiscriminate(const MDLocation &RHS) const { + return getFilename() != RHS.getFilename() || getLine() != RHS.getLine(); + } + + /// \brief Get the DWARF discriminator. + /// + /// DWARF discriminators distinguish identical file locations between + /// instructions that are on different basic blocks. + inline unsigned getDiscriminator() const; + + /// \brief Compute new discriminator in the given context. + /// + /// This modifies the \a LLVMContext that \c this is in to increment the next + /// discriminator for \c this's line/filename combination. + /// + /// FIXME: Delete this. See comments in implementation and at the only call + /// site in \a AddDiscriminators::runOnFunction(). + unsigned computeNewDiscriminator() const; + Metadata *getRawScope() const { return getOperand(0); } Metadata *getRawInlinedAt() const { if (getNumOperands() == 2) @@ -958,21 +1262,23 @@ class MDSubprogram : public MDLocalScope { Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality), VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), IsOptimized(IsOptimized) {} - ~MDSubprogram() {} + ~MDSubprogram() = default; static MDSubprogram * - getImpl(LLVMContext &Context, Metadata *Scope, StringRef Name, - StringRef LinkageName, Metadata *File, unsigned Line, Metadata *Type, - bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, - Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, - unsigned Flags, bool IsOptimized, Metadata *Function, - Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, + getImpl(LLVMContext &Context, MDScopeRef Scope, StringRef Name, + StringRef LinkageName, MDFile *File, unsigned Line, + MDSubroutineType *Type, bool IsLocalToUnit, bool IsDefinition, + unsigned ScopeLine, MDTypeRef ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Constant *Function, MDTemplateParameterArray TemplateParams, + MDSubprogram *Declaration, MDLocalVariableArray Variables, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, - Virtuality, VirtualIndex, Flags, IsOptimized, Function, - TemplateParams, Declaration, Variables, Storage, + Virtuality, VirtualIndex, Flags, IsOptimized, + Function ? ConstantAsMetadata::get(Function) : nullptr, + TemplateParams.get(), Declaration, Variables.get(), Storage, ShouldCreate); } static MDSubprogram * @@ -989,22 +1295,25 @@ class MDSubprogram : public MDLocalScope { getFile(), getLine(), getType(), isLocalToUnit(), isDefinition(), getScopeLine(), getContainingType(), getVirtuality(), getVirtualIndex(), getFlags(), - isOptimized(), getFunction(), getTemplateParams(), - getDeclaration(), getVariables()); + isOptimized(), getFunctionConstant(), + getTemplateParams(), getDeclaration(), getVariables()); } public: - DEFINE_MDNODE_GET( - MDSubprogram, - (Metadata * Scope, StringRef Name, StringRef LinkageName, Metadata *File, - unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, - unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, - unsigned VirtualIndex, unsigned Flags, bool IsOptimized, - Metadata *Function = nullptr, Metadata *TemplateParams = nullptr, - Metadata *Declaration = nullptr, Metadata *Variables = nullptr), - (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized, - Function, TemplateParams, Declaration, Variables)) + DEFINE_MDNODE_GET(MDSubprogram, + (MDScopeRef Scope, StringRef Name, StringRef LinkageName, + MDFile *File, unsigned Line, MDSubroutineType *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + MDTypeRef ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Constant *Function = nullptr, + MDTemplateParameterArray TemplateParams = nullptr, + MDSubprogram *Declaration = nullptr, + MDLocalVariableArray Variables = nullptr), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, ScopeLine, ContainingType, Virtuality, + VirtualIndex, Flags, IsOptimized, Function, TemplateParams, + Declaration, Variables)) DEFINE_MDNODE_GET( MDSubprogram, (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, @@ -1029,7 +1338,36 @@ public: bool isDefinition() const { return IsDefinition; } bool isOptimized() const { return IsOptimized; } - Metadata *getScope() const { return getOperand(1); } + unsigned isArtificial() const { return getFlags() & FlagArtificial; } + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } + bool isExplicit() const { return getFlags() & FlagExplicit; } + bool isPrototyped() const { return getFlags() & FlagPrototyped; } + + /// \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; + } + + /// \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; + } + + MDScopeRef getScope() const { return MDScopeRef(getRawScope()); } StringRef getName() const { return getStringOperand(2); } StringRef getDisplayName() const { return getStringOperand(3); } @@ -1038,13 +1376,42 @@ public: MDString *getRawName() const { return getOperandAs(2); } MDString *getRawLinkageName() const { return getOperandAs(4); } - Metadata *getType() const { return getOperand(5); } - Metadata *getContainingType() const { return getOperand(6); } + MDSubroutineType *getType() const { + return cast_or_null(getRawType()); + } + MDTypeRef getContainingType() const { + return MDTypeRef(getRawContainingType()); + } - Metadata *getFunction() const { return getOperand(7); } - Metadata *getTemplateParams() const { return getOperand(8); } - Metadata *getDeclaration() const { return getOperand(9); } - Metadata *getVariables() const { return getOperand(10); } + Constant *getFunctionConstant() const { + if (auto *C = cast_or_null(getRawFunction())) + return C->getValue(); + return nullptr; + } + MDTemplateParameterArray getTemplateParams() const { + return cast_or_null(getRawTemplateParams()); + } + MDSubprogram *getDeclaration() const { + return cast_or_null(getRawDeclaration()); + } + MDLocalVariableArray getVariables() const { + return cast_or_null(getRawVariables()); + } + + Metadata *getRawScope() const { return getOperand(1); } + Metadata *getRawType() const { return getOperand(5); } + Metadata *getRawContainingType() const { return getOperand(6); } + Metadata *getRawFunction() const { return getOperand(7); } + Metadata *getRawTemplateParams() const { return getOperand(8); } + Metadata *getRawDeclaration() const { return getOperand(9); } + Metadata *getRawVariables() const { return getOperand(10); } + + /// \brief Get a pointer to the function this subprogram describes. + /// + /// This dyn_casts \a getFunctionConstant() to \a Function. + /// + /// FIXME: Should this be looking through bitcasts? + Function *getFunction() const; /// \brief Replace the function. /// @@ -1057,6 +1424,11 @@ public: void replaceFunction(std::nullptr_t) { replaceOperandWith(7, nullptr); } /// @} + /// \brief Check if this subprogram decribes the given function. + /// + /// FIXME: Should this be looking through bitcasts? + bool describes(const Function *F) const; + static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDSubprogramKind; } @@ -1067,11 +1439,20 @@ protected: MDLexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, ArrayRef Ops) : MDLocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} - ~MDLexicalBlockBase() {} + ~MDLexicalBlockBase() = default; public: - Metadata *getScope() const { return getOperand(1); } + MDLocalScope *getScope() const { return cast(getRawScope()); } + Metadata *getRawScope() const { return getOperand(1); } + + /// \brief Forwarding accessors to LexicalBlock. + /// + /// TODO: Remove these and update code to use \a MDLexicalBlock directly. + /// @{ + inline unsigned getLine() const; + inline unsigned getColumn() const; + /// @} static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDLexicalBlockKind || MD->getMetadataID() == MDLexicalBlockFileKind; @@ -1089,7 +1470,16 @@ class MDLexicalBlock : public MDLexicalBlockBase { unsigned Column, ArrayRef Ops) : MDLexicalBlockBase(C, MDLexicalBlockKind, Storage, Ops), Line(Line), Column(Column) {} - ~MDLexicalBlock() {} + ~MDLexicalBlock() = default; + + static MDLexicalBlock *getImpl(LLVMContext &Context, MDLocalScope *Scope, + MDFile *File, unsigned Line, unsigned Column, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, static_cast(Scope), + static_cast(File), Line, Column, Storage, + ShouldCreate); + } static MDLexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, Metadata *File, unsigned Line, unsigned Column, @@ -1101,6 +1491,9 @@ class MDLexicalBlock : public MDLexicalBlockBase { } public: + DEFINE_MDNODE_GET(MDLexicalBlock, (MDLocalScope * Scope, MDFile *File, + unsigned Line, unsigned Column), + (Scope, File, Line, Column)) DEFINE_MDNODE_GET(MDLexicalBlock, (Metadata * Scope, Metadata *File, unsigned Line, unsigned Column), (Scope, File, Line, Column)) @@ -1115,6 +1508,18 @@ public: } }; +unsigned MDLexicalBlockBase::getLine() const { + if (auto *N = dyn_cast(this)) + return N->getLine(); + return 0; +} + +unsigned MDLexicalBlockBase::getColumn() const { + if (auto *N = dyn_cast(this)) + return N->getColumn(); + return 0; +} + class MDLexicalBlockFile : public MDLexicalBlockBase { friend class LLVMContextImpl; friend class MDNode; @@ -1125,7 +1530,16 @@ class MDLexicalBlockFile : public MDLexicalBlockBase { unsigned Discriminator, ArrayRef Ops) : MDLexicalBlockBase(C, MDLexicalBlockFileKind, Storage, Ops), Discriminator(Discriminator) {} - ~MDLexicalBlockFile() {} + ~MDLexicalBlockFile() = default; + + static MDLexicalBlockFile *getImpl(LLVMContext &Context, MDLocalScope *Scope, + MDFile *File, unsigned Discriminator, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, static_cast(Scope), + static_cast(File), Discriminator, Storage, + ShouldCreate); + } static MDLexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, Metadata *File, unsigned Discriminator, @@ -1138,12 +1552,19 @@ class MDLexicalBlockFile : public MDLexicalBlockBase { } public: + DEFINE_MDNODE_GET(MDLexicalBlockFile, (MDLocalScope * Scope, MDFile *File, + unsigned Discriminator), + (Scope, File, Discriminator)) DEFINE_MDNODE_GET(MDLexicalBlockFile, (Metadata * Scope, Metadata *File, unsigned Discriminator), (Scope, File, Discriminator)) TempMDLexicalBlockFile clone() const { return cloneImpl(); } + // TODO: Remove these once they're gone from MDLexicalBlockBase. + unsigned getLine() const = delete; + unsigned getColumn() const = delete; + unsigned getDiscriminator() const { return Discriminator; } static bool classof(const Metadata *MD) { @@ -1151,6 +1572,12 @@ public: } }; +unsigned MDLocation::getDiscriminator() const { + if (auto *F = dyn_cast(getScope())) + return F->getDiscriminator(); + return 0; +} + class MDNamespace : public MDScope { friend class LLVMContextImpl; friend class MDNode; @@ -1162,10 +1589,10 @@ class MDNamespace : public MDScope { : MDScope(Context, MDNamespaceKind, Storage, dwarf::DW_TAG_namespace, Ops), Line(Line) {} - ~MDNamespace() {} + ~MDNamespace() = default; - static MDNamespace *getImpl(LLVMContext &Context, Metadata *Scope, - Metadata *File, StringRef Name, unsigned Line, + static MDNamespace *getImpl(LLVMContext &Context, MDScope *Scope, + MDFile *File, StringRef Name, unsigned Line, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, File, getCanonicalMDString(Context, Name), Line, Storage, ShouldCreate); @@ -1180,8 +1607,8 @@ class MDNamespace : public MDScope { } public: - DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, - StringRef Name, unsigned Line), + DEFINE_MDNODE_GET(MDNamespace, (MDScope * Scope, MDFile *File, StringRef Name, + unsigned Line), (Scope, File, Name, Line)) DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, MDString *Name, unsigned Line), @@ -1190,9 +1617,10 @@ public: TempMDNamespace clone() const { return cloneImpl(); } unsigned getLine() const { return Line; } - Metadata *getScope() const { return getOperand(1); } + MDScope *getScope() const { return cast_or_null(getRawScope()); } StringRef getName() const { return getStringOperand(2); } + Metadata *getRawScope() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs(2); } static bool classof(const Metadata *MD) { @@ -1206,13 +1634,14 @@ protected: MDTemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef Ops) : DebugNode(Context, ID, Storage, Tag, Ops) {} - ~MDTemplateParameter() {} + ~MDTemplateParameter() = default; public: StringRef getName() const { return getStringOperand(0); } - Metadata *getType() const { return getOperand(1); } + MDTypeRef getType() const { return MDTypeRef(getRawType()); } MDString *getRawName() const { return getOperandAs(0); } + Metadata *getRawType() const { return getOperand(1); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDTemplateTypeParameterKind || @@ -1228,10 +1657,10 @@ class MDTemplateTypeParameter : public MDTemplateParameter { ArrayRef Ops) : MDTemplateParameter(Context, MDTemplateTypeParameterKind, Storage, dwarf::DW_TAG_template_type_parameter, Ops) {} - ~MDTemplateTypeParameter() {} + ~MDTemplateTypeParameter() = default; static MDTemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, - Metadata *Type, StorageType Storage, + MDTypeRef Type, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage, ShouldCreate); @@ -1245,7 +1674,7 @@ class MDTemplateTypeParameter : public MDTemplateParameter { } public: - DEFINE_MDNODE_GET(MDTemplateTypeParameter, (StringRef Name, Metadata *Type), + DEFINE_MDNODE_GET(MDTemplateTypeParameter, (StringRef Name, MDTypeRef Type), (Name, Type)) DEFINE_MDNODE_GET(MDTemplateTypeParameter, (MDString * Name, Metadata *Type), (Name, Type)) @@ -1265,10 +1694,10 @@ class MDTemplateValueParameter : public MDTemplateParameter { unsigned Tag, ArrayRef Ops) : MDTemplateParameter(Context, MDTemplateValueParameterKind, Storage, Tag, Ops) {} - ~MDTemplateValueParameter() {} + ~MDTemplateValueParameter() = default; static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Name, Metadata *Type, + StringRef Name, MDTypeRef Type, Metadata *Value, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, @@ -1286,7 +1715,7 @@ class MDTemplateValueParameter : public MDTemplateParameter { public: DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, StringRef Name, - Metadata *Type, Metadata *Value), + MDTypeRef Type, Metadata *Value), (Tag, Name, Type, Value)) DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, MDString *Name, Metadata *Type, Metadata *Value), @@ -1311,16 +1740,30 @@ protected: MDVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, unsigned Line, ArrayRef Ops) : DebugNode(C, ID, Storage, Tag, Ops), Line(Line) {} - ~MDVariable() {} + ~MDVariable() = default; public: unsigned getLine() const { return Line; } - Metadata *getScope() const { return getOperand(0); } + MDScope *getScope() const { return cast_or_null(getRawScope()); } StringRef getName() const { return getStringOperand(1); } - Metadata *getFile() const { return getOperand(2); } - Metadata *getType() const { return getOperand(3); } + MDFile *getFile() const { return cast_or_null(getRawFile()); } + MDTypeRef getType() const { return MDTypeRef(getRawType()); } + + StringRef getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; + } + StringRef getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; + } + Metadata *getRawScope() const { return getOperand(0); } MDString *getRawName() const { return getOperandAs(1); } + Metadata *getRawFile() const { return getOperand(2); } + Metadata *getRawType() const { return getOperand(3); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDLocalVariableKind || @@ -1344,17 +1787,18 @@ class MDGlobalVariable : public MDVariable { : MDVariable(C, MDGlobalVariableKind, Storage, dwarf::DW_TAG_variable, Line, Ops), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} - ~MDGlobalVariable() {} + ~MDGlobalVariable() = default; static MDGlobalVariable * - getImpl(LLVMContext &Context, Metadata *Scope, StringRef Name, - StringRef LinkageName, Metadata *File, unsigned Line, Metadata *Type, - bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, - Metadata *StaticDataMemberDeclaration, StorageType Storage, + getImpl(LLVMContext &Context, MDScope *Scope, StringRef Name, + StringRef LinkageName, MDFile *File, unsigned Line, MDTypeRef Type, + bool IsLocalToUnit, bool IsDefinition, Constant *Variable, + MDDerivedType *StaticDataMemberDeclaration, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, - IsLocalToUnit, IsDefinition, Variable, + IsLocalToUnit, IsDefinition, + Variable ? ConstantAsMetadata::get(Variable) : nullptr, StaticDataMemberDeclaration, Storage, ShouldCreate); } static MDGlobalVariable * @@ -1373,10 +1817,10 @@ class MDGlobalVariable : public MDVariable { public: DEFINE_MDNODE_GET(MDGlobalVariable, - (Metadata * Scope, StringRef Name, StringRef LinkageName, - Metadata *File, unsigned Line, Metadata *Type, - bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, - Metadata *StaticDataMemberDeclaration), + (MDScope * Scope, StringRef Name, StringRef LinkageName, + MDFile *File, unsigned Line, MDTypeRef Type, + bool IsLocalToUnit, bool IsDefinition, Constant *Variable, + MDDerivedType *StaticDataMemberDeclaration), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, Variable, StaticDataMemberDeclaration)) DEFINE_MDNODE_GET(MDGlobalVariable, @@ -1393,10 +1837,18 @@ public: bool isDefinition() const { return IsDefinition; } StringRef getDisplayName() const { return getStringOperand(4); } StringRef getLinkageName() const { return getStringOperand(5); } - Metadata *getVariable() const { return getOperand(6); } - Metadata *getStaticDataMemberDeclaration() const { return getOperand(7); } + Constant *getVariable() const { + if (auto *C = cast_or_null(getRawVariable())) + return dyn_cast(C->getValue()); + return nullptr; + } + MDDerivedType *getStaticDataMemberDeclaration() const { + return cast_or_null(getRawStaticDataMemberDeclaration()); + } MDString *getRawLinkageName() const { return getOperandAs(5); } + Metadata *getRawVariable() const { return getOperand(6); } + Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(7); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDGlobalVariableKind; @@ -1420,62 +1872,61 @@ class MDLocalVariable : public MDVariable { ArrayRef Ops) : MDVariable(C, MDLocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg), Flags(Flags) {} - ~MDLocalVariable() {} + ~MDLocalVariable() = default; static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag, - Metadata *Scope, StringRef Name, - Metadata *File, unsigned Line, Metadata *Type, - unsigned Arg, unsigned Flags, - Metadata *InlinedAt, StorageType Storage, + MDScope *Scope, StringRef Name, MDFile *File, + unsigned Line, MDTypeRef Type, unsigned Arg, + unsigned Flags, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, Scope, getCanonicalMDString(Context, Name), - File, Line, Type, Arg, Flags, InlinedAt, Storage, - ShouldCreate); + File, Line, Type, Arg, Flags, Storage, ShouldCreate); } - static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag, - Metadata *Scope, MDString *Name, - Metadata *File, unsigned Line, Metadata *Type, - unsigned Arg, unsigned Flags, - Metadata *InlinedAt, StorageType Storage, - bool ShouldCreate = true); + static MDLocalVariable * + getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, Metadata *Type, unsigned Arg, + unsigned Flags, StorageType Storage, bool ShouldCreate = true); TempMDLocalVariable cloneImpl() const { return getTemporary(getContext(), getTag(), getScope(), getName(), - getFile(), getLine(), getType(), getArg(), getFlags(), - getInlinedAt()); + getFile(), getLine(), getType(), getArg(), getFlags()); } public: DEFINE_MDNODE_GET(MDLocalVariable, - (unsigned Tag, Metadata *Scope, StringRef Name, - Metadata *File, unsigned Line, Metadata *Type, - unsigned Arg, unsigned Flags, - Metadata *InlinedAt = nullptr), - (Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt)) + (unsigned Tag, MDLocalScope *Scope, StringRef Name, + MDFile *File, unsigned Line, MDTypeRef Type, unsigned Arg, + unsigned Flags), + (Tag, Scope, Name, File, Line, Type, Arg, Flags)) DEFINE_MDNODE_GET(MDLocalVariable, (unsigned Tag, Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, Metadata *Type, - unsigned Arg, unsigned Flags, - Metadata *InlinedAt = nullptr), - (Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt)) + unsigned Arg, unsigned Flags), + (Tag, Scope, Name, File, Line, Type, Arg, Flags)) TempMDLocalVariable clone() const { return cloneImpl(); } + /// \brief Get the local scope for this variable. + /// + /// Variables must be defined in a local scope. + MDLocalScope *getScope() const { + return cast(MDVariable::getScope()); + } + unsigned getArg() const { return Arg; } unsigned getFlags() const { return Flags; } - Metadata *getInlinedAt() const { return getOperand(4); } - /// \brief Get an inlined version of this variable. + bool isArtificial() const { return getFlags() & FlagArtificial; } + bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } + + /// \brief Check that a location is valid for this variable. /// - /// Returns a version of this with \a getAlinedAt() set to \c InlinedAt. - MDLocalVariable *withInline(MDLocation *InlinedAt) const { - if (InlinedAt == getInlinedAt()) - return const_cast(this); - auto Temp = clone(); - Temp->replaceOperandWith(4, InlinedAt); - return replaceWithUniqued(std::move(Temp)); + /// Check that \c DL exists, is in the same subprogram, and has the same + /// inlined-at location as \c this. (Otherwise, it's not a valid attachemnt + /// to a \a DbgInfoIntrinsic.) + bool isValidLocationForIntrinsic(const MDLocation *DL) const { + return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); } - MDLocalVariable *withoutInline() const { return withInline(nullptr); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDLocalVariableKind; @@ -1484,6 +1935,12 @@ public: /// \brief DWARF expression. /// +/// 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. +/// /// TODO: Co-allocate the expression elements. /// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary /// storage types. @@ -1496,7 +1953,7 @@ class MDExpression : public MDNode { MDExpression(LLVMContext &C, StorageType Storage, ArrayRef Elements) : MDNode(C, MDExpressionKind, Storage, None), Elements(Elements.begin(), Elements.end()) {} - ~MDExpression() {} + ~MDExpression() = default; static MDExpression *getImpl(LLVMContext &Context, ArrayRef Elements, StorageType Storage, @@ -1519,6 +1976,15 @@ public: return Elements[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; + typedef ArrayRef::iterator element_iterator; element_iterator elements_begin() const { return getElements().begin(); } element_iterator elements_end() const { return getElements().end(); } @@ -1573,6 +2039,13 @@ public: return T; } + /// \brief Get the next iterator. + /// + /// \a std::next() doesn't work because this is technically an + /// input_iterator, but it's a perfectly valid operation. This is an + /// accessor to provide the same functionality. + expr_op_iterator getNext() const { return ++expr_op_iterator(*this); } + bool operator==(const expr_op_iterator &X) const { return getBase() == X.getBase(); } @@ -1619,12 +2092,12 @@ class MDObjCProperty : public DebugNode { : DebugNode(C, MDObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, Ops), Line(Line), Attributes(Attributes) {} - ~MDObjCProperty() {} + ~MDObjCProperty() = default; static MDObjCProperty * - getImpl(LLVMContext &Context, StringRef Name, Metadata *File, unsigned Line, + getImpl(LLVMContext &Context, StringRef Name, MDFile *File, unsigned Line, StringRef GetterName, StringRef SetterName, unsigned Attributes, - Metadata *Type, StorageType Storage, bool ShouldCreate = true) { + MDType *Type, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, getCanonicalMDString(Context, GetterName), getCanonicalMDString(Context, SetterName), Attributes, Type, @@ -1644,9 +2117,9 @@ class MDObjCProperty : public DebugNode { public: DEFINE_MDNODE_GET(MDObjCProperty, - (StringRef Name, Metadata *File, unsigned Line, + (StringRef Name, MDFile *File, unsigned Line, StringRef GetterName, StringRef SetterName, - unsigned Attributes, Metadata *Type), + unsigned Attributes, MDType *Type), (Name, File, Line, GetterName, SetterName, Attributes, Type)) DEFINE_MDNODE_GET(MDObjCProperty, @@ -1661,20 +2134,39 @@ public: unsigned getLine() const { return Line; } unsigned getAttributes() const { return Attributes; } StringRef getName() const { return getStringOperand(0); } - Metadata *getFile() const { return getOperand(1); } + MDFile *getFile() const { return cast_or_null(getRawFile()); } StringRef getGetterName() const { return getStringOperand(2); } StringRef getSetterName() const { return getStringOperand(3); } - Metadata *getType() const { return getOperand(4); } + + /// \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. + MDType *getType() const { return cast_or_null(getRawType()); } + + StringRef getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; + } + StringRef getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; + } MDString *getRawName() const { return getOperandAs(0); } + Metadata *getRawFile() const { return getOperand(1); } MDString *getRawGetterName() const { return getOperandAs(2); } MDString *getRawSetterName() const { return getOperandAs(3); } + Metadata *getRawType() const { return getOperand(4); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDObjCPropertyKind; } }; +/// \brief An imported module (C++ using directive or similar). class MDImportedEntity : public DebugNode { friend class LLVMContextImpl; friend class MDNode; @@ -1684,10 +2176,10 @@ class MDImportedEntity : public DebugNode { MDImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, unsigned Line, ArrayRef Ops) : DebugNode(C, MDImportedEntityKind, Storage, Tag, Ops), Line(Line) {} - ~MDImportedEntity() {} + ~MDImportedEntity() = default; static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, - Metadata *Scope, Metadata *Entity, + MDScope *Scope, DebugNodeRef Entity, unsigned Line, StringRef Name, StorageType Storage, bool ShouldCreate = true) { @@ -1707,7 +2199,7 @@ class MDImportedEntity : public DebugNode { public: DEFINE_MDNODE_GET(MDImportedEntity, - (unsigned Tag, Metadata *Scope, Metadata *Entity, + (unsigned Tag, MDScope *Scope, DebugNodeRef Entity, unsigned Line, StringRef Name = ""), (Tag, Scope, Entity, Line, Name)) DEFINE_MDNODE_GET(MDImportedEntity, @@ -1718,10 +2210,12 @@ public: TempMDImportedEntity clone() const { return cloneImpl(); } unsigned getLine() const { return Line; } - Metadata *getScope() const { return getOperand(0); } - Metadata *getEntity() const { return getOperand(1); } + MDScope *getScope() const { return cast_or_null(getRawScope()); } + DebugNodeRef getEntity() const { return DebugNodeRef(getRawEntity()); } StringRef getName() const { return getStringOperand(2); } + Metadata *getRawScope() const { return getOperand(0); } + Metadata *getRawEntity() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs(2); } static bool classof(const Metadata *MD) { -- cgit v1.1