X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FIR%2FDebugInfoMetadata.h;h=c09b7d0477db539d5ead4e23de5a338b9e027b32;hb=b4c1547749853c584a1988069f8c3e9d594475c7;hp=28f29ec8353e1320f4b4d13ccd30b50f0a6a12b6;hpb=ca8d3bf8af0bd32076e4a60b1f997ee48c3187d8;p=oota-llvm.git diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index 28f29ec8353..c09b7d0477d 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -15,6 +15,29 @@ #define LLVM_IR_DEBUGINFOMETADATA_H #include "llvm/IR/Metadata.h" +#include "llvm/Support/Dwarf.h" + +// Helper macros for defining get() overrides. +#define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__ +#define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS +#define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS) \ + static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued); \ + } \ + static CLASS *getIfExists(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued, \ + /* ShouldCreate */ false); \ + } \ + static CLASS *getDistinct(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct); \ + } \ + static Temp##CLASS getTemporary(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return Temp##CLASS( \ + getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary)); \ + } namespace llvm { @@ -40,30 +63,13 @@ class MDLocation : public MDNode { } // Disallow replacing operands. - void replaceOperandWith(unsigned I, Metadata *New) LLVM_DELETED_FUNCTION; + void replaceOperandWith(unsigned I, Metadata *New) = delete; public: - static MDLocation *get(LLVMContext &Context, unsigned Line, unsigned Column, - Metadata *Scope, Metadata *InlinedAt = nullptr) { - return getImpl(Context, Line, Column, Scope, InlinedAt, Uniqued); - } - static MDLocation *getIfExists(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt = nullptr) { - return getImpl(Context, Line, Column, Scope, InlinedAt, Uniqued, - /* ShouldCreate */ false); - } - static MDLocation *getDistinct(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt = nullptr) { - return getImpl(Context, Line, Column, Scope, InlinedAt, Distinct); - } - static TempMDLocation getTemporary(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt = nullptr) { - return TempMDLocation( - getImpl(Context, Line, Column, Scope, InlinedAt, Temporary)); - } + DEFINE_MDNODE_GET(MDLocation, + (unsigned Line, unsigned Column, Metadata *Scope, + Metadata *InlinedAt = nullptr), + (Line, Column, Scope, InlinedAt)) /// \brief Return a (temporary) clone of this. TempMDLocation clone() const { return cloneImpl(); } @@ -100,11 +106,51 @@ protected: } ~DebugNode() {} + template Ty *getOperandAs(unsigned I) const { + return cast_or_null(getOperand(I)); + } + + StringRef getStringOperand(unsigned I) const { + if (auto *S = getOperandAs(I)) + return S->getString(); + return StringRef(); + } + + static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { + if (S.empty()) + return nullptr; + return MDString::get(Context, S); + } + public: unsigned getTag() const { return SubclassData16; } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == GenericDebugNodeKind; + switch (MD->getMetadataID()) { + default: + return false; + case GenericDebugNodeKind: + case MDSubrangeKind: + case MDEnumeratorKind: + case MDBasicTypeKind: + case MDDerivedTypeKind: + case MDCompositeTypeKind: + case MDSubroutineTypeKind: + case MDFileKind: + case MDCompileUnitKind: + case MDSubprogramKind: + case MDLexicalBlockKind: + case MDLexicalBlockFileKind: + case MDNamespaceKind: + case MDTemplateTypeParameterKind: + case MDTemplateValueParameterKind: + case MDGlobalVariableKind: + case MDLocalVariableKind: + case MDExpressionKind: + case MDObjCPropertyKind: + case MDImportedEntityKind: + return true; + } } }; @@ -133,6 +179,15 @@ class GenericDebugNode : public DebugNode { StringRef Header, ArrayRef DwarfOps, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Header), + DwarfOps, Storage, ShouldCreate); + } + + static GenericDebugNode *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Header, + ArrayRef DwarfOps, + StorageType Storage, bool ShouldCreate = true); TempGenericDebugNode cloneImpl() const { @@ -144,38 +199,18 @@ class GenericDebugNode : public DebugNode { public: unsigned getHash() const { return SubclassData32; } - static GenericDebugNode *get(LLVMContext &Context, unsigned Tag, - StringRef Header, - ArrayRef DwarfOps) { - return getImpl(Context, Tag, Header, DwarfOps, Uniqued); - } - static GenericDebugNode *getIfExists(LLVMContext &Context, unsigned Tag, - StringRef Header, - ArrayRef DwarfOps) { - return getImpl(Context, Tag, Header, DwarfOps, Uniqued, - /* ShouldCreate */ false); - } - static GenericDebugNode *getDistinct(LLVMContext &Context, unsigned Tag, - StringRef Header, - ArrayRef DwarfOps) { - return getImpl(Context, Tag, Header, DwarfOps, Distinct); - } - static TempGenericDebugNode getTemporary(LLVMContext &Context, unsigned Tag, - StringRef Header, - ArrayRef DwarfOps) { - return TempGenericDebugNode( - getImpl(Context, Tag, Header, DwarfOps, Temporary)); - } + DEFINE_MDNODE_GET(GenericDebugNode, (unsigned Tag, StringRef Header, + ArrayRef DwarfOps), + (Tag, Header, DwarfOps)) + DEFINE_MDNODE_GET(GenericDebugNode, (unsigned Tag, MDString *Header, + ArrayRef DwarfOps), + (Tag, Header, DwarfOps)) /// \brief Return a (temporary) clone of this. TempGenericDebugNode clone() const { return cloneImpl(); } unsigned getTag() const { return SubclassData16; } - StringRef getHeader() const { - if (auto *S = cast_or_null(getOperand(0))) - return S->getString(); - return StringRef(); - } + StringRef getHeader() const { return getStringOperand(0); } op_iterator dwarf_op_begin() const { return op_begin() + 1; } op_iterator dwarf_op_end() const { return op_end(); } @@ -196,6 +231,1471 @@ public: } }; +/// \brief Array subrange. +/// +/// TODO: Merge into node for DW_TAG_array_type, which should have a custom +/// type. +class MDSubrange : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + int64_t Count; + int64_t Lo; + + MDSubrange(LLVMContext &C, StorageType Storage, int64_t Count, int64_t Lo) + : DebugNode(C, MDSubrangeKind, Storage, dwarf::DW_TAG_subrange_type, + None), + Count(Count), Lo(Lo) {} + ~MDSubrange() {} + + static MDSubrange *getImpl(LLVMContext &Context, int64_t Count, int64_t Lo, + StorageType Storage, bool ShouldCreate = true); + + TempMDSubrange cloneImpl() const { + return getTemporary(getContext(), getCount(), getLo()); + } + +public: + DEFINE_MDNODE_GET(MDSubrange, (int64_t Count, int64_t Lo = 0), (Count, Lo)) + + TempMDSubrange clone() const { return cloneImpl(); } + + int64_t getLo() const { return Lo; } + int64_t getCount() const { return Count; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDSubrangeKind; + } +}; + +/// \brief Enumeration value. +/// +/// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no +/// longer creates a type cycle. +class MDEnumerator : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + int64_t Value; + + MDEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, + ArrayRef Ops) + : DebugNode(C, MDEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), + Value(Value) {} + ~MDEnumerator() {} + + static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value, + StringRef Name, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Value, getCanonicalMDString(Context, Name), Storage, + ShouldCreate); + } + static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value, + MDString *Name, StorageType Storage, + bool ShouldCreate = true); + + TempMDEnumerator cloneImpl() const { + return getTemporary(getContext(), getValue(), getName()); + } + +public: + DEFINE_MDNODE_GET(MDEnumerator, (int64_t Value, StringRef Name), + (Value, Name)) + DEFINE_MDNODE_GET(MDEnumerator, (int64_t Value, MDString *Name), + (Value, Name)) + + TempMDEnumerator clone() const { return cloneImpl(); } + + int64_t getValue() const { return Value; } + StringRef getName() const { return getStringOperand(0); } + + MDString *getRawName() const { return getOperandAs(0); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDEnumeratorKind; + } +}; + +/// \brief Base class for scope-like contexts. +/// +/// Base class for lexical scopes and types (which are also declaration +/// contexts). +/// +/// TODO: Separate the concepts of declaration contexts and lexical scopes. +class MDScope : public DebugNode { +protected: + MDScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef Ops) + : DebugNode(C, ID, Storage, Tag, Ops) {} + ~MDScope() {} + +public: + /// \brief Return the 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 { + return isa(this) ? const_cast(this) + : static_cast(getOperand(0)); + } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case MDBasicTypeKind: + case MDDerivedTypeKind: + case MDCompositeTypeKind: + case MDSubroutineTypeKind: + case MDFileKind: + case MDCompileUnitKind: + case MDSubprogramKind: + case MDLexicalBlockKind: + case MDLexicalBlockFileKind: + case MDNamespaceKind: + return true; + } + } +}; + +/// \brief Base class for types. +/// +/// TODO: Remove the hardcoded name and context, since many types don't use +/// them. +/// TODO: Split up flags. +class MDType : public MDScope { + unsigned Line; + unsigned Flags; + uint64_t SizeInBits; + uint64_t AlignInBits; + uint64_t OffsetInBits; + +protected: + MDType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, ArrayRef Ops) + : MDScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags), + SizeInBits(SizeInBits), AlignInBits(AlignInBits), + OffsetInBits(OffsetInBits) {} + ~MDType() {} + +public: + TempMDType clone() const { + return TempMDType(cast(MDNode::clone().release())); + } + + unsigned getLine() const { return Line; } + uint64_t getSizeInBits() const { return SizeInBits; } + uint64_t getAlignInBits() const { return AlignInBits; } + uint64_t getOffsetInBits() const { return OffsetInBits; } + unsigned getFlags() const { return Flags; } + + Metadata *getScope() const { return getOperand(1); } + StringRef getName() const { return getStringOperand(2); } + + MDString *getRawName() const { return getOperandAs(2); } + + void setFlags(unsigned NewFlags) { + assert(!isUniqued() && "Cannot set flags on uniqued nodes"); + Flags = NewFlags; + } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case MDBasicTypeKind: + case MDDerivedTypeKind: + case MDCompositeTypeKind: + case MDSubroutineTypeKind: + return true; + } + } +}; + +/// \brief Basic type. +/// +/// TODO: Split out DW_TAG_unspecified_type. +/// TODO: Drop unused accessors. +class MDBasicType : public MDType { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Encoding; + + MDBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, + uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding, + ArrayRef Ops) + : MDType(C, MDBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, + 0, Ops), + Encoding(Encoding) {} + ~MDBasicType() {} + + static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), + SizeInBits, AlignInBits, Encoding, Storage, ShouldCreate); + } + static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding, + StorageType Storage, bool ShouldCreate = true); + + TempMDBasicType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), + getAlignInBits(), getEncoding()); + } + +public: + DEFINE_MDNODE_GET(MDBasicType, (unsigned Tag, StringRef Name), + (Tag, Name, 0, 0, 0)) + DEFINE_MDNODE_GET(MDBasicType, + (unsigned Tag, StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding), + (Tag, Name, SizeInBits, AlignInBits, Encoding)) + DEFINE_MDNODE_GET(MDBasicType, + (unsigned Tag, MDString *Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding), + (Tag, Name, SizeInBits, AlignInBits, Encoding)) + + TempMDBasicType clone() const { return cloneImpl(); } + + unsigned getEncoding() const { return Encoding; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDBasicTypeKind; + } +}; + +/// \brief Base class for MDDerivedType and MDCompositeType. +/// +/// TODO: Delete; they're not really related. +class MDDerivedTypeBase : public MDType { +protected: + MDDerivedTypeBase(LLVMContext &C, unsigned ID, StorageType Storage, + unsigned Tag, unsigned Line, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + ArrayRef Ops) + : MDType(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, + Flags, Ops) {} + ~MDDerivedTypeBase() {} + +public: + Metadata *getBaseType() const { return getOperand(3); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDDerivedTypeKind || + MD->getMetadataID() == MDCompositeTypeKind || + MD->getMetadataID() == MDSubroutineTypeKind; + } +}; + +/// \brief Derived types. +/// +/// This includes qualified types, pointers, references, friends, typedefs, and +/// class members. +/// +/// TODO: Split out members (inheritance, fields, methods, etc.). +class MDDerivedType : public MDDerivedTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + MDDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, ArrayRef Ops) + : MDDerivedTypeBase(C, MDDerivedTypeKind, Storage, Tag, Line, SizeInBits, + AlignInBits, OffsetInBits, Flags, Ops) {} + ~MDDerivedType() {} + + static MDDerivedType *getImpl(LLVMContext &Context, 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, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, + Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, + Flags, ExtraData, Storage, ShouldCreate); + } + static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, Metadata *File, unsigned Line, + Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData, StorageType Storage, + bool ShouldCreate = true); + + TempMDDerivedType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), + getScope(), getBaseType(), getSizeInBits(), + getAlignInBits(), getOffsetInBits(), getFlags(), + getExtraData()); + } + +public: + DEFINE_MDNODE_GET(MDDerivedType, + (unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *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)) + 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), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, ExtraData)) + + TempMDDerivedType clone() const { return cloneImpl(); } + + /// \brief Get extra data associated with this derived type. + /// + /// Class type for pointer-to-members, objective-c property node for ivars, + /// or global constant wrapper for static members. + /// + /// 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); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDDerivedTypeKind; + } +}; + +/// \brief Base class for MDCompositeType and MDSubroutineType. +/// +/// TODO: Delete; they're not really related. +class MDCompositeTypeBase : public MDDerivedTypeBase { + unsigned RuntimeLang; + +protected: + MDCompositeTypeBase(LLVMContext &C, unsigned ID, StorageType Storage, + unsigned Tag, unsigned Line, unsigned RuntimeLang, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + ArrayRef Ops) + : MDDerivedTypeBase(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, + OffsetInBits, Flags, Ops), + RuntimeLang(RuntimeLang) {} + ~MDCompositeTypeBase() {} + +public: + Metadata *getElements() const { return getOperand(4); } + Metadata *getVTableHolder() const { return getOperand(5); } + Metadata *getTemplateParams() const { return getOperand(6); } + StringRef getIdentifier() const { return getStringOperand(7); } + unsigned getRuntimeLang() const { return RuntimeLang; } + + MDString *getRawIdentifier() const { return getOperandAs(7); } + + /// \brief Replace operands. + /// + /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision + /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track + /// of its movement if necessary. + /// @{ + void replaceElements(MDTuple *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"); +#endif + replaceOperandWith(4, Elements); + } + void replaceVTableHolder(Metadata *VTableHolder) { + replaceOperandWith(5, VTableHolder); + } + void replaceTemplateParams(MDTuple *TemplateParams) { + replaceOperandWith(6, TemplateParams); + } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDCompositeTypeKind || + MD->getMetadataID() == MDSubroutineTypeKind; + } +}; + +/// \brief Composite types. +/// +/// TODO: Detach from DerivedTypeBase (split out MDEnumType?). +/// TODO: Create a custom, unrelated node for DW_TAG_array_type. +class MDCompositeType : public MDCompositeTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + MDCompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + ArrayRef Ops) + : MDCompositeTypeBase(C, MDCompositeTypeKind, Storage, Tag, Line, + RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, + Flags, Ops) {} + ~MDCompositeType() {} + + static MDCompositeType * + getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + uint64_t Flags, Metadata *Elements, unsigned RuntimeLang, + Metadata *VTableHolder, Metadata *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); + } + static MDCompositeType * + getImpl(LLVMContext &Context, unsigned Tag, MDString *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, + MDString *Identifier, StorageType Storage, bool ShouldCreate = true); + + TempMDCompositeType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), + getScope(), getBaseType(), getSizeInBits(), + getAlignInBits(), getOffsetInBits(), getFlags(), + getElements(), getRuntimeLang(), getVTableHolder(), + getTemplateParams(), getIdentifier()); + } + +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, + StringRef Identifier = ""), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)) + DEFINE_MDNODE_GET(MDCompositeType, + (unsigned Tag, MDString *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, + MDString *Identifier = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)) + + TempMDCompositeType clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDCompositeTypeKind; + } +}; + +/// \brief Type array for a subprogram. +/// +/// TODO: Detach from CompositeType, and fold the array of types in directly +/// as operands. +class MDSubroutineType : public MDCompositeTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + MDSubroutineType(LLVMContext &C, StorageType Storage, unsigned Flags, + ArrayRef Ops) + : MDCompositeTypeBase(C, MDSubroutineTypeKind, Storage, + dwarf::DW_TAG_subroutine_type, 0, 0, 0, 0, 0, Flags, + Ops) {} + ~MDSubroutineType() {} + + static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags, + Metadata *TypeArray, StorageType Storage, + bool ShouldCreate = true); + + TempMDSubroutineType cloneImpl() const { + return getTemporary(getContext(), getFlags(), getTypeArray()); + } + +public: + DEFINE_MDNODE_GET(MDSubroutineType, (unsigned Flags, Metadata *TypeArray), + (Flags, TypeArray)) + + TempMDSubroutineType clone() const { return cloneImpl(); } + + Metadata *getTypeArray() const { return getElements(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDSubroutineTypeKind; + } +}; + +/// \brief File. +/// +/// TODO: Merge with directory/file node (including users). +/// TODO: Canonicalize paths on creation. +class MDFile : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + MDFile(LLVMContext &C, StorageType Storage, ArrayRef Ops) + : MDScope(C, MDFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {} + ~MDFile() {} + + static MDFile *getImpl(LLVMContext &Context, StringRef Filename, + StringRef Directory, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Filename), + getCanonicalMDString(Context, Directory), Storage, + ShouldCreate); + } + static MDFile *getImpl(LLVMContext &Context, MDString *Filename, + MDString *Directory, StorageType Storage, + bool ShouldCreate = true); + + TempMDFile cloneImpl() const { + return getTemporary(getContext(), getFilename(), getDirectory()); + } + +public: + DEFINE_MDNODE_GET(MDFile, (StringRef Filename, StringRef Directory), + (Filename, Directory)) + DEFINE_MDNODE_GET(MDFile, (MDString * Filename, MDString *Directory), + (Filename, Directory)) + + TempMDFile clone() const { return cloneImpl(); } + + StringRef getFilename() const { return getStringOperand(0); } + StringRef getDirectory() const { return getStringOperand(1); } + + MDString *getRawFilename() const { return getOperandAs(0); } + MDString *getRawDirectory() const { return getOperandAs(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDFileKind; + } +}; + +/// \brief Compile unit. +class MDCompileUnit : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned SourceLanguage; + bool IsOptimized; + unsigned RuntimeVersion; + unsigned EmissionKind; + + MDCompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, + bool IsOptimized, unsigned RuntimeVersion, + unsigned EmissionKind, ArrayRef Ops) + : MDScope(C, MDCompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), + SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), + RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind) {} + ~MDCompileUnit() {} + + static MDCompileUnit * + getImpl(LLVMContext &Context, 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, 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); + } + static MDCompileUnit * + getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + MDString *Producer, bool IsOptimized, MDString *Flags, + unsigned RuntimeVersion, MDString *SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, + Metadata *Subprograms, Metadata *GlobalVariables, + Metadata *ImportedEntities, StorageType Storage, + bool ShouldCreate = true); + + TempMDCompileUnit cloneImpl() const { + return getTemporary( + getContext(), getSourceLanguage(), getFile(), getProducer(), + isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(), + getEmissionKind(), getEnumTypes(), getRetainedTypes(), getSubprograms(), + getGlobalVariables(), getImportedEntities()); + } + +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), + (SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, + EnumTypes, RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)) + DEFINE_MDNODE_GET(MDCompileUnit, + (unsigned SourceLanguage, Metadata *File, + MDString *Producer, bool IsOptimized, MDString *Flags, + unsigned RuntimeVersion, MDString *SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, + Metadata *RetainedTypes, Metadata *Subprograms, + Metadata *GlobalVariables, Metadata *ImportedEntities), + (SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, + EnumTypes, RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)) + + TempMDCompileUnit clone() const { return cloneImpl(); } + + unsigned getSourceLanguage() const { return SourceLanguage; } + bool isOptimized() const { return IsOptimized; } + unsigned getRuntimeVersion() const { return RuntimeVersion; } + unsigned getEmissionKind() const { return EmissionKind; } + 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); } + + MDString *getRawProducer() const { return getOperandAs(1); } + MDString *getRawFlags() const { return getOperandAs(2); } + MDString *getRawSplitDebugFilename() const { + return getOperandAs(3); + } + + /// \brief Replace arrays. + /// + /// If this \a isUniqued() and not \a isResolved(), it will be RAUW'ed and + /// 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); } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDCompileUnitKind; + } +}; + +/// \brief Subprogram description. +/// +/// TODO: Remove DisplayName. It's always equal to Name. +/// TODO: Split up flags. +class MDSubprogram : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned ScopeLine; + unsigned Virtuality; + unsigned VirtualIndex; + unsigned Flags; + bool IsLocalToUnit; + bool IsDefinition; + bool IsOptimized; + + MDSubprogram(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned ScopeLine, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsLocalToUnit, bool IsDefinition, + bool IsOptimized, ArrayRef Ops) + : MDScope(C, MDSubprogramKind, Storage, dwarf::DW_TAG_subprogram, Ops), + Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality), + VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit), + IsDefinition(IsDefinition), IsOptimized(IsOptimized) {} + ~MDSubprogram() {} + + 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, + 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, + ShouldCreate); + } + static MDSubprogram * + getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, + MDString *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, + StorageType Storage, bool ShouldCreate = true); + + TempMDSubprogram cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), getLinkageName(), + getFile(), getLine(), getType(), isLocalToUnit(), + isDefinition(), getScopeLine(), getContainingType(), + getVirtuality(), getVirtualIndex(), getFlags(), + isOptimized(), getFunction(), 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, + (Metadata * Scope, MDString *Name, MDString *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)) + + TempMDSubprogram clone() const { return cloneImpl(); } + +public: + unsigned getLine() const { return Line; } + unsigned getVirtuality() const { return Virtuality; } + unsigned getVirtualIndex() const { return VirtualIndex; } + unsigned getScopeLine() const { return ScopeLine; } + unsigned getFlags() const { return Flags; } + bool isLocalToUnit() const { return IsLocalToUnit; } + bool isDefinition() const { return IsDefinition; } + bool isOptimized() const { return IsOptimized; } + + Metadata *getScope() const { return getOperand(1); } + + StringRef getName() const { return getStringOperand(2); } + StringRef getDisplayName() const { return getStringOperand(3); } + StringRef getLinkageName() const { return getStringOperand(4); } + + MDString *getRawName() const { return getOperandAs(2); } + MDString *getRawLinkageName() const { return getOperandAs(4); } + + Metadata *getType() const { return getOperand(5); } + Metadata *getContainingType() const { return getOperand(6); } + + Metadata *getFunction() const { return getOperand(7); } + Metadata *getTemplateParams() const { return getOperand(8); } + Metadata *getDeclaration() const { return getOperand(9); } + Metadata *getVariables() const { return getOperand(10); } + + /// \brief Replace the function. + /// + /// If \a isUniqued() and not \a isResolved(), this could node will be + /// RAUW'ed and deleted out from under the caller. Use a \a TrackingMDRef if + /// that's a problem. + /// @{ + void replaceFunction(Function *F); + void replaceFunction(ConstantAsMetadata *MD) { replaceOperandWith(7, MD); } + void replaceFunction(std::nullptr_t) { replaceOperandWith(7, nullptr); } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDSubprogramKind; + } +}; + +class MDLexicalBlockBase : public MDScope { +protected: + MDLexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, + ArrayRef Ops) + : MDScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} + ~MDLexicalBlockBase() {} + +public: + Metadata *getScope() const { return getOperand(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLexicalBlockKind || + MD->getMetadataID() == MDLexicalBlockFileKind; + } +}; + +class MDLexicalBlock : public MDLexicalBlockBase { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned Column; + + MDLexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column, ArrayRef Ops) + : MDLexicalBlockBase(C, MDLexicalBlockKind, Storage, Ops), Line(Line), + Column(Column) {} + ~MDLexicalBlock() {} + + static MDLexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, unsigned Line, unsigned Column, + StorageType Storage, bool ShouldCreate = true); + + TempMDLexicalBlock cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), getLine(), + getColumn()); + } + +public: + DEFINE_MDNODE_GET(MDLexicalBlock, (Metadata * Scope, Metadata *File, + unsigned Line, unsigned Column), + (Scope, File, Line, Column)) + + TempMDLexicalBlock clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + unsigned getColumn() const { return Column; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLexicalBlockKind; + } +}; + +class MDLexicalBlockFile : public MDLexicalBlockBase { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Discriminator; + + MDLexicalBlockFile(LLVMContext &C, StorageType Storage, + unsigned Discriminator, ArrayRef Ops) + : MDLexicalBlockBase(C, MDLexicalBlockFileKind, Storage, Ops), + Discriminator(Discriminator) {} + ~MDLexicalBlockFile() {} + + static MDLexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, unsigned Discriminator, + StorageType Storage, + bool ShouldCreate = true); + + TempMDLexicalBlockFile cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), + getDiscriminator()); + } + +public: + DEFINE_MDNODE_GET(MDLexicalBlockFile, + (Metadata * Scope, Metadata *File, unsigned Discriminator), + (Scope, File, Discriminator)) + + TempMDLexicalBlockFile clone() const { return cloneImpl(); } + + unsigned getDiscriminator() const { return Discriminator; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLexicalBlockFileKind; + } +}; + +class MDNamespace : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + MDNamespace(LLVMContext &Context, StorageType Storage, unsigned Line, + ArrayRef Ops) + : MDScope(Context, MDNamespaceKind, Storage, dwarf::DW_TAG_namespace, + Ops), + Line(Line) {} + ~MDNamespace() {} + + static MDNamespace *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, StringRef Name, unsigned Line, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Scope, File, getCanonicalMDString(Context, Name), + Line, Storage, ShouldCreate); + } + static MDNamespace *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, MDString *Name, unsigned Line, + StorageType Storage, bool ShouldCreate = true); + + TempMDNamespace cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), getName(), + getLine()); + } + +public: + DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, + StringRef Name, unsigned Line), + (Scope, File, Name, Line)) + DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, + MDString *Name, unsigned Line), + (Scope, File, Name, Line)) + + TempMDNamespace clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + Metadata *getScope() const { return getOperand(1); } + StringRef getName() const { return getStringOperand(2); } + + MDString *getRawName() const { return getOperandAs(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDNamespaceKind; + } +}; + +/// \brief Base class for template parameters. +class MDTemplateParameter : public DebugNode { +protected: + MDTemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, + unsigned Tag, ArrayRef Ops) + : DebugNode(Context, ID, Storage, Tag, Ops) {} + ~MDTemplateParameter() {} + +public: + StringRef getName() const { return getStringOperand(0); } + Metadata *getType() const { return getOperand(1); } + + MDString *getRawName() const { return getOperandAs(0); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTemplateTypeParameterKind || + MD->getMetadataID() == MDTemplateValueParameterKind; + } +}; + +class MDTemplateTypeParameter : public MDTemplateParameter { + friend class LLVMContextImpl; + friend class MDNode; + + MDTemplateTypeParameter(LLVMContext &Context, StorageType Storage, + ArrayRef Ops) + : MDTemplateParameter(Context, MDTemplateTypeParameterKind, Storage, + dwarf::DW_TAG_template_type_parameter, Ops) {} + ~MDTemplateTypeParameter() {} + + static MDTemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, + Metadata *Type, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage, + ShouldCreate); + } + static MDTemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name, + Metadata *Type, StorageType Storage, + bool ShouldCreate = true); + + TempMDTemplateTypeParameter cloneImpl() const { + return getTemporary(getContext(), getName(), getType()); + } + +public: + DEFINE_MDNODE_GET(MDTemplateTypeParameter, (StringRef Name, Metadata *Type), + (Name, Type)) + DEFINE_MDNODE_GET(MDTemplateTypeParameter, (MDString * Name, Metadata *Type), + (Name, Type)) + + TempMDTemplateTypeParameter clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTemplateTypeParameterKind; + } +}; + +class MDTemplateValueParameter : public MDTemplateParameter { + friend class LLVMContextImpl; + friend class MDNode; + + MDTemplateValueParameter(LLVMContext &Context, StorageType Storage, + unsigned Tag, ArrayRef Ops) + : MDTemplateParameter(Context, MDTemplateValueParameterKind, Storage, Tag, + Ops) {} + ~MDTemplateValueParameter() {} + + static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, Metadata *Type, + Metadata *Value, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, + Value, Storage, ShouldCreate); + } + static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, Metadata *Type, + Metadata *Value, StorageType Storage, + bool ShouldCreate = true); + + TempMDTemplateValueParameter cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getType(), + getValue()); + } + +public: + DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, StringRef Name, + Metadata *Type, Metadata *Value), + (Tag, Name, Type, Value)) + DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, MDString *Name, + Metadata *Type, Metadata *Value), + (Tag, Name, Type, Value)) + + TempMDTemplateValueParameter clone() const { return cloneImpl(); } + + Metadata *getValue() const { return getOperand(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTemplateValueParameterKind; + } +}; + +/// \brief Base class for variables. +/// +/// TODO: Hardcode to DW_TAG_variable. +class MDVariable : public DebugNode { + unsigned Line; + +protected: + MDVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + unsigned Line, ArrayRef Ops) + : DebugNode(C, ID, Storage, Tag, Ops), Line(Line) {} + ~MDVariable() {} + +public: + unsigned getLine() const { return Line; } + Metadata *getScope() const { return getOperand(0); } + StringRef getName() const { return getStringOperand(1); } + Metadata *getFile() const { return getOperand(2); } + Metadata *getType() const { return getOperand(3); } + + MDString *getRawName() const { return getOperandAs(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLocalVariableKind || + MD->getMetadataID() == MDGlobalVariableKind; + } +}; + +/// \brief Global variables. +/// +/// TODO: Remove DisplayName. It's always equal to Name. +class MDGlobalVariable : public MDVariable { + friend class LLVMContextImpl; + friend class MDNode; + + bool IsLocalToUnit; + bool IsDefinition; + + MDGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, + bool IsLocalToUnit, bool IsDefinition, + ArrayRef Ops) + : MDVariable(C, MDGlobalVariableKind, Storage, dwarf::DW_TAG_variable, + Line, Ops), + IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} + ~MDGlobalVariable() {} + + 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, + bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), + getCanonicalMDString(Context, LinkageName), File, Line, Type, + IsLocalToUnit, IsDefinition, Variable, + StaticDataMemberDeclaration, Storage, ShouldCreate); + } + static MDGlobalVariable * + getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, + MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration, StorageType Storage, + bool ShouldCreate = true); + + TempMDGlobalVariable cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), getLinkageName(), + getFile(), getLine(), getType(), isLocalToUnit(), + isDefinition(), getVariable(), + getStaticDataMemberDeclaration()); + } + +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), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, Variable, StaticDataMemberDeclaration)) + DEFINE_MDNODE_GET(MDGlobalVariable, + (Metadata * Scope, MDString *Name, MDString *LinkageName, + Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, Variable, StaticDataMemberDeclaration)) + + TempMDGlobalVariable clone() const { return cloneImpl(); } + + bool isLocalToUnit() const { return IsLocalToUnit; } + 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); } + + MDString *getRawLinkageName() const { return getOperandAs(5); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDGlobalVariableKind; + } +}; + +/// \brief Local variable. +/// +/// TODO: Split between arguments and otherwise. +/// TODO: Use \c DW_TAG_variable instead of fake tags. +/// TODO: Split up flags. +class MDLocalVariable : public MDVariable { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Arg; + unsigned Flags; + + MDLocalVariable(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, unsigned Arg, unsigned Flags, + ArrayRef Ops) + : MDVariable(C, MDLocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg), + Flags(Flags) {} + ~MDLocalVariable() {} + + 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, + bool ShouldCreate = true) { + return getImpl(Context, Tag, Scope, getCanonicalMDString(Context, Name), + File, Line, Type, Arg, Flags, InlinedAt, 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); + + TempMDLocalVariable cloneImpl() const { + return getTemporary(getContext(), getTag(), getScope(), getName(), + getFile(), getLine(), getType(), getArg(), getFlags(), + getInlinedAt()); + } + +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)) + 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)) + + TempMDLocalVariable clone() const { return cloneImpl(); } + + unsigned getArg() const { return Arg; } + unsigned getFlags() const { return Flags; } + Metadata *getInlinedAt() const { return getOperand(4); } + + /// \brief Get an inlined version of 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)); + } + MDLocalVariable *withoutInline() const { return withInline(nullptr); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLocalVariableKind; + } +}; + +/// \brief DWARF expression. +/// +/// TODO: Co-allocate the expression elements. +/// TODO: Drop fake DW_TAG_expression and separate from DebugNode. +/// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary +/// storage types. +class MDExpression : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + std::vector Elements; + + MDExpression(LLVMContext &C, StorageType Storage, ArrayRef Elements) + : DebugNode(C, MDExpressionKind, Storage, dwarf::DW_TAG_expression, None), + Elements(Elements.begin(), Elements.end()) {} + ~MDExpression() {} + + static MDExpression *getImpl(LLVMContext &Context, + ArrayRef Elements, StorageType Storage, + bool ShouldCreate = true); + + TempMDExpression cloneImpl() const { + return getTemporary(getContext(), getElements()); + } + +public: + DEFINE_MDNODE_GET(MDExpression, (ArrayRef Elements), (Elements)) + + TempMDExpression clone() const { return cloneImpl(); } + + ArrayRef getElements() const { return Elements; } + + unsigned getNumElements() const { return Elements.size(); } + uint64_t getElement(unsigned I) const { + assert(I < Elements.size() && "Index out of range"); + return Elements[I]; + } + + typedef ArrayRef::iterator element_iterator; + element_iterator elements_begin() const { return getElements().begin(); } + element_iterator elements_end() const { return getElements().end(); } + + /// \brief A lightweight wrapper around an expression operand. + /// + /// TODO: Store arguments directly and change \a MDExpression to store a + /// range of these. + class ExprOperand { + const uint64_t *Op; + + public: + explicit ExprOperand(const uint64_t *Op) : Op(Op) {} + + const uint64_t *get() const { return Op; } + + /// \brief Get the operand code. + uint64_t getOp() const { return *Op; } + + /// \brief Get an argument to the operand. + /// + /// Never returns the operand itself. + uint64_t getArg(unsigned I) const { return Op[I + 1]; } + + unsigned getNumArgs() const { return getSize() - 1; } + + /// \brief Return the size of the operand. + /// + /// Return the number of elements in the operand (1 + args). + unsigned getSize() const; + }; + + /// \brief An iterator for expression operands. + class expr_op_iterator + : public std::iterator { + ExprOperand Op; + + public: + explicit expr_op_iterator(element_iterator I) : Op(I) {} + + element_iterator getBase() const { return Op.get(); } + const ExprOperand &operator*() const { return Op; } + const ExprOperand *operator->() const { return &Op; } + + expr_op_iterator &operator++() { + increment(); + return *this; + } + expr_op_iterator operator++(int) { + expr_op_iterator T(*this); + increment(); + return T; + } + + bool operator==(const expr_op_iterator &X) const { + return getBase() == X.getBase(); + } + bool operator!=(const expr_op_iterator &X) const { + return getBase() != X.getBase(); + } + + private: + void increment() { Op = ExprOperand(getBase() + Op.getSize()); } + }; + + /// \brief Visit the elements via ExprOperand wrappers. + /// + /// These range iterators visit elements through \a ExprOperand wrappers. + /// This is not guaranteed to be a valid range unless \a isValid() gives \c + /// true. + /// + /// \pre \a isValid() gives \c true. + /// @{ + expr_op_iterator expr_op_begin() const { + return expr_op_iterator(elements_begin()); + } + expr_op_iterator expr_op_end() const { + return expr_op_iterator(elements_end()); + } + /// @} + + bool isValid() const; + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDExpressionKind; + } +}; + +class MDObjCProperty : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned Attributes; + + MDObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Attributes, ArrayRef Ops) + : DebugNode(C, MDObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, + Ops), + Line(Line), Attributes(Attributes) {} + ~MDObjCProperty() {} + + static MDObjCProperty * + getImpl(LLVMContext &Context, StringRef Name, Metadata *File, unsigned Line, + StringRef GetterName, StringRef SetterName, unsigned Attributes, + Metadata *Type, StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, + getCanonicalMDString(Context, GetterName), + getCanonicalMDString(Context, SetterName), Attributes, Type, + Storage, ShouldCreate); + } + static MDObjCProperty *getImpl(LLVMContext &Context, MDString *Name, + Metadata *File, unsigned Line, + MDString *GetterName, MDString *SetterName, + unsigned Attributes, Metadata *Type, + StorageType Storage, bool ShouldCreate = true); + + TempMDObjCProperty cloneImpl() const { + return getTemporary(getContext(), getName(), getFile(), getLine(), + getGetterName(), getSetterName(), getAttributes(), + getType()); + } + +public: + DEFINE_MDNODE_GET(MDObjCProperty, + (StringRef Name, Metadata *File, unsigned Line, + StringRef GetterName, StringRef SetterName, + unsigned Attributes, Metadata *Type), + (Name, File, Line, GetterName, SetterName, Attributes, + Type)) + DEFINE_MDNODE_GET(MDObjCProperty, + (MDString * Name, Metadata *File, unsigned Line, + MDString *GetterName, MDString *SetterName, + unsigned Attributes, Metadata *Type), + (Name, File, Line, GetterName, SetterName, Attributes, + Type)) + + TempMDObjCProperty clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + unsigned getAttributes() const { return Attributes; } + StringRef getName() const { return getStringOperand(0); } + Metadata *getFile() const { return getOperand(1); } + StringRef getGetterName() const { return getStringOperand(2); } + StringRef getSetterName() const { return getStringOperand(3); } + Metadata *getType() const { return getOperand(4); } + + MDString *getRawName() const { return getOperandAs(0); } + MDString *getRawGetterName() const { return getOperandAs(2); } + MDString *getRawSetterName() const { return getOperandAs(3); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDObjCPropertyKind; + } +}; + +class MDImportedEntity : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + MDImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, ArrayRef Ops) + : DebugNode(C, MDImportedEntityKind, Storage, Tag, Ops), Line(Line) {} + ~MDImportedEntity() {} + + static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, Metadata *Entity, + unsigned Line, StringRef Name, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, Scope, Entity, Line, + getCanonicalMDString(Context, Name), Storage, ShouldCreate); + } + static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, Metadata *Entity, + unsigned Line, MDString *Name, + StorageType Storage, + bool ShouldCreate = true); + + TempMDImportedEntity cloneImpl() const { + return getTemporary(getContext(), getTag(), getScope(), getEntity(), + getLine(), getName()); + } + +public: + DEFINE_MDNODE_GET(MDImportedEntity, + (unsigned Tag, Metadata *Scope, Metadata *Entity, + unsigned Line, StringRef Name = ""), + (Tag, Scope, Entity, Line, Name)) + DEFINE_MDNODE_GET(MDImportedEntity, + (unsigned Tag, Metadata *Scope, Metadata *Entity, + unsigned Line, MDString *Name), + (Tag, Scope, Entity, Line, Name)) + + TempMDImportedEntity clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + Metadata *getScope() const { return getOperand(0); } + Metadata *getEntity() const { return getOperand(1); } + StringRef getName() const { return getStringOperand(2); } + + MDString *getRawName() const { return getOperandAs(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDImportedEntityKind; + } +}; + } // end namespace llvm +#undef DEFINE_MDNODE_GET_UNPACK_IMPL +#undef DEFINE_MDNODE_GET_UNPACK +#undef DEFINE_MDNODE_GET + #endif