-template <typename T> class DIRef;
-typedef DIRef<DIDescriptor> DIDescriptorRef;
-typedef DIRef<DIScope> DIScopeRef;
-typedef DIRef<DIType> DITypeRef;
-typedef DITypedArray<DITypeRef> DITypeArray;
-
-/// \brief A base class for various scopes.
-///
-/// Although, implementation-wise, DIScope is the parent class of most
-/// other DIxxx classes, including DIType and its descendants, most of
-/// DIScope's descendants are not a substitutable subtype of
-/// DIScope. The DIDescriptor::isScope() method only is true for
-/// DIScopes that are scopes in the strict lexical scope sense
-/// (DICompileUnit, DISubprogram, etc.), but not for, e.g., a DIType.
-class DIScope : public DIDescriptor {
-protected:
- MDScope *getRaw() const { return dyn_cast_or_null<MDScope>(get()); }
-
-public:
- explicit DIScope(const MDNode *N = nullptr) : DIDescriptor(N) {}
- DIScope(const MDScope *N) : DIDescriptor(N) {}
-
- /// \brief Get the parent scope.
- ///
- /// Gets the parent scope for this scope node or returns a default
- /// constructed scope.
- DIScopeRef getContext() const;
- /// \brief Get the scope name.
- ///
- /// If the scope node has a name, return that, else return an empty string.
- StringRef getName() const;
- StringRef getFilename() const;
- StringRef getDirectory() const;
-
- /// \brief Generate a reference to this DIScope.
- ///
- /// Uses the type identifier instead of the actual MDNode if possible, to
- /// help type uniquing.
- DIScopeRef getRef() const;
-};
-
-/// \brief Represents reference to a DIDescriptor.
-///
-/// Abstracts over direct and identifier-based metadata references.
-template <typename T> class DIRef {
- template <typename DescTy>
- friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const;
- friend DIScopeRef DIScope::getContext() const;
- friend DIScopeRef DIScope::getRef() const;
- friend class DIType;
-
- /// \brief Val can be either a MDNode or a MDString.
- ///
- /// In the latter, MDString specifies the type identifier.
- const Metadata *Val;
- explicit DIRef(const Metadata *V);
-
-public:
- T resolve(const DITypeIdentifierMap &Map) const;
- StringRef getName() const;
- operator Metadata *() const { return const_cast<Metadata *>(Val); }
-
- static DIRef get(const Metadata *MD) { return DIRef(MD); }
-};
-
-template <typename T>
-T DIRef<T>::resolve(const DITypeIdentifierMap &Map) const {
- if (!Val)
- return T();
-
- if (const MDNode *MD = dyn_cast<MDNode>(Val))
- return T(MD);
-
- const MDString *MS = cast<MDString>(Val);
- // Find the corresponding MDNode.
- DITypeIdentifierMap::const_iterator Iter = Map.find(MS);
- assert(Iter != Map.end() && "Identifier not in the type map?");
- assert(DIDescriptor(Iter->second).isType() &&
- "MDNode in DITypeIdentifierMap should be a DIType.");
- return T(Iter->second);
-}
-
-template <typename T> StringRef DIRef<T>::getName() const {
- if (!Val)
- return StringRef();
-
- if (const MDNode *MD = dyn_cast<MDNode>(Val))
- return T(MD).getName();
-
- const MDString *MS = cast<MDString>(Val);
- return MS->getString();
-}
-
-/// \brief Handle fields that are references to DIDescriptors.
-template <>
-DIDescriptorRef DIDescriptor::getFieldAs<DIDescriptorRef>(unsigned Elt) const;
-/// \brief Specialize DIRef constructor for DIDescriptorRef.
-template <> DIRef<DIDescriptor>::DIRef(const Metadata *V);
-
-/// \brief Handle fields that are references to DIScopes.
-template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const;
-/// \brief Specialize DIRef constructor for DIScopeRef.
-template <> DIRef<DIScope>::DIRef(const Metadata *V);
-
-/// \brief Handle fields that are references to DITypes.
-template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const;
-/// \brief Specialize DIRef constructor for DITypeRef.
-template <> DIRef<DIType>::DIRef(const Metadata *V);
-
-/// \brief This is a wrapper for a type.
-///
-/// FIXME: Types should be factored much better so that CV qualifiers and
-/// others do not require a huge and empty descriptor full of zeros.
-class DIType : public DIScope {
- MDType *getRaw() const { return dyn_cast_or_null<MDType>(get()); }
-
-public:
- explicit DIType(const MDNode *N = nullptr) : DIScope(N) {}
- DIType(const MDType *N) : DIScope(N) {}
-
- operator DITypeRef() const {
- assert(isType() &&
- "constructing DITypeRef from an MDNode that is not a type");
- return DITypeRef(&*getRef());
- }
-
- bool Verify() const;
-
- DIScopeRef getContext() const {
- RETURN_REF_FROM_RAW(DIScopeRef, N->getScope());
- }
- StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); }
- unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); }
- uint64_t getSizeInBits() const { RETURN_FROM_RAW(N->getSizeInBits(), 0); }
- uint64_t getAlignInBits() const { RETURN_FROM_RAW(N->getAlignInBits(), 0); }
- // FIXME: Offset is only used for DW_TAG_member nodes. Making every type
- // carry this is just plain insane.
- uint64_t getOffsetInBits() const { RETURN_FROM_RAW(N->getOffsetInBits(), 0); }
- unsigned getFlags() const { RETURN_FROM_RAW(N->getFlags(), 0); }
- 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) != 0; }
- bool isAppleBlockExtension() const {
- return (getFlags() & FlagAppleBlock) != 0;
- }
- bool isBlockByrefStruct() const {
- return (getFlags() & FlagBlockByrefStruct) != 0;
- }
- bool isVirtual() const { return (getFlags() & FlagVirtual) != 0; }
- bool isArtificial() const { return (getFlags() & FlagArtificial) != 0; }
- bool isObjectPointer() const { return (getFlags() & FlagObjectPointer) != 0; }
- bool isObjcClassComplete() const {
- return (getFlags() & FlagObjcClassComplete) != 0;
- }
- bool isVector() const { return (getFlags() & FlagVector) != 0; }
- bool isStaticMember() const { return (getFlags() & FlagStaticMember) != 0; }
- bool isLValueReference() const {
- return (getFlags() & FlagLValueReference) != 0;
- }
- bool isRValueReference() const {
- return (getFlags() & FlagRValueReference) != 0;
- }
- bool isValid() const { return DbgNode && isType(); }
-};
-
-/// \brief A basic type, like 'int' or 'float'.
-class DIBasicType : public DIType {
- MDBasicType *getRaw() const { return dyn_cast_or_null<MDBasicType>(get()); }
-
-public:
- explicit DIBasicType(const MDNode *N = nullptr) : DIType(N) {}
- DIBasicType(const MDBasicType *N) : DIType(N) {}
-
- unsigned getEncoding() const { RETURN_FROM_RAW(N->getEncoding(), 0); }
-
- bool Verify() const;
-};
-
-/// \brief A simple derived type
-///
-/// Like a const qualified type, a typedef, a pointer or reference, et cetera.
-/// Or, a data member of a class/struct/union.
-class DIDerivedType : public DIType {
- MDDerivedTypeBase *getRaw() const {
- return dyn_cast_or_null<MDDerivedTypeBase>(get());
- }
-
-public:
- explicit DIDerivedType(const MDNode *N = nullptr) : DIType(N) {}
- DIDerivedType(const MDDerivedTypeBase *N) : DIType(N) {}
-
- DITypeRef getTypeDerivedFrom() const {
- RETURN_REF_FROM_RAW(DITypeRef, N->getBaseType());
- }
-
- /// \brief Return property node, if this ivar is associated with one.
- MDNode *getObjCProperty() const {
- if (auto *N = dyn_cast_or_null<MDDerivedType>(get()))
- return dyn_cast_or_null<MDNode>(N->getExtraData());
- return nullptr;
- }
-
- DITypeRef getClassType() const {
- assert(getTag() == dwarf::DW_TAG_ptr_to_member_type);
- if (auto *N = dyn_cast_or_null<MDDerivedType>(get()))
- return DITypeRef::get(N->getExtraData());
- return DITypeRef::get(nullptr);
- }
-
- Constant *getConstant() const {
- assert((getTag() == dwarf::DW_TAG_member) && isStaticMember());
- if (auto *N = dyn_cast_or_null<MDDerivedType>(get()))
- if (auto *C = dyn_cast_or_null<ConstantAsMetadata>(N->getExtraData()))
- return C->getValue();
-
- return nullptr;
- }
-
- bool Verify() const;
-};
-
-/// \brief Types that refer to multiple other types.
-///
-/// This descriptor holds a type that can refer to multiple other types, like a
-/// function or struct.
-///
-/// DICompositeType is derived from DIDerivedType because some
-/// composite types (such as enums) can be derived from basic types
-// FIXME: Make this derive from DIType directly & just store the
-// base type in a single DIType field.
-class DICompositeType : public DIDerivedType {
- friend class DIBuilder;
-
- /// \brief Set the array of member DITypes.
- void setArraysHelper(MDNode *Elements, MDNode *TParams);
-
- MDCompositeTypeBase *getRaw() const {
- return dyn_cast_or_null<MDCompositeTypeBase>(get());
- }
-
-public:
- explicit DICompositeType(const MDNode *N = nullptr) : DIDerivedType(N) {}
- DICompositeType(const MDCompositeTypeBase *N) : DIDerivedType(N) {}
-
- DIArray getElements() const {
- assert(!isSubroutineType() && "no elements for DISubroutineType");
- RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getElements());
- }
-
-private:
- template <typename T>
- void setArrays(DITypedArray<T> Elements, DIArray TParams = DIArray()) {
- assert(
- (!TParams || DbgNode->getNumOperands() == 8) &&
- "If you're setting the template parameters this should include a slot "
- "for that!");
- setArraysHelper(Elements, TParams);
- }
-
-public:
- unsigned getRunTimeLang() const { RETURN_FROM_RAW(N->getRuntimeLang(), 0); }
- DITypeRef getContainingType() const {
- RETURN_REF_FROM_RAW(DITypeRef, N->getVTableHolder());
- }
-
-private:
- /// \brief Set the containing type.
- void setContainingType(DICompositeType ContainingType);