Debug Info: define a DIRef template.

Specialize the constructors for DIRef<DIScope> and DIRef<DIType> to make sure
the Value is indeed a scope ref and a type ref.

Use DIScopeRef for DIScope::getContext and DIType::getContext and use DITypeRef
for getContainingType and getClassType.

DIScope::generateRef now returns a DIScopeRef instead of a "Value *" for
readability and type safety.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190418 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Manman Ren 2013-09-10 18:30:07 +00:00
parent 1039e106d0
commit 2c46deb1d0
4 changed files with 88 additions and 60 deletions

View File

@ -17,6 +17,7 @@
#ifndef LLVM_DEBUGINFO_H #ifndef LLVM_DEBUGINFO_H
#define LLVM_DEBUGINFO_H #define LLVM_DEBUGINFO_H
#include "llvm/Support/Casting.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
@ -46,7 +47,7 @@ namespace llvm {
class DILexicalBlockFile; class DILexicalBlockFile;
class DIVariable; class DIVariable;
class DIType; class DIType;
class DIScopeRef; class DIScope;
class DIObjCProperty; class DIObjCProperty;
/// Maps from type identifier to the actual MDNode. /// Maps from type identifier to the actual MDNode.
@ -56,9 +57,10 @@ namespace llvm {
/// This should not be stored in a container, because the underlying MDNode /// This should not be stored in a container, because the underlying MDNode
/// may change in certain situations. /// may change in certain situations.
class DIDescriptor { class DIDescriptor {
// Befriends DIScopeRef so DIScopeRef can befriend the protected member // Befriends DIRef so DIRef can befriend the protected member
// function: getFieldAs<DIScopeRef>. // function: getFieldAs<DIRef>.
friend class DIScopeRef; template <typename T>
friend class DIRef;
public: public:
enum { enum {
FlagPrivate = 1 << 0, FlagPrivate = 1 << 0,
@ -151,10 +153,6 @@ namespace llvm {
void dump() const; void dump() const;
}; };
/// npecialize getFieldAs to handle fields that are references to DIScopes.
template <>
DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const;
/// DISubrange - This is used to represent ranges, for array bounds. /// DISubrange - This is used to represent ranges, for array bounds.
class DISubrange : public DIDescriptor { class DISubrange : public DIDescriptor {
friend class DIDescriptor; friend class DIDescriptor;
@ -192,6 +190,10 @@ namespace llvm {
bool Verify() const; bool Verify() const;
}; };
template <typename T>
class DIRef;
typedef DIRef<DIScope> DIScopeRef;
/// DIScope - A base class for various scopes. /// DIScope - A base class for various scopes.
class DIScope : public DIDescriptor { class DIScope : public DIDescriptor {
protected: protected:
@ -208,23 +210,7 @@ namespace llvm {
/// Generate a reference to this DIScope. Uses the type identifier instead /// Generate a reference to this DIScope. Uses the type identifier instead
/// of the actual MDNode if possible, to help type uniquing. /// of the actual MDNode if possible, to help type uniquing.
Value *generateRef(); DIScopeRef generateRef();
};
/// Represents reference to a DIScope, abstracts over direct and
/// identifier-based metadata scope references.
class DIScopeRef {
template <typename DescTy>
friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const;
friend DIScopeRef DIScope::getContext() const;
/// Val can be either a MDNode or a MDString, in the latter,
/// MDString specifies the type identifier.
const Value *Val;
explicit DIScopeRef(const Value *V);
public:
DIScope resolve(const DITypeIdentifierMap &Map) const;
operator Value *() const { return const_cast<Value*>(Val); }
}; };
/// DIType - This is a wrapper for a type. /// DIType - This is a wrapper for a type.
@ -241,7 +227,7 @@ namespace llvm {
/// Verify - Verify that a type descriptor is well formed. /// Verify - Verify that a type descriptor is well formed.
bool Verify() const; bool Verify() const;
DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } DIScopeRef getContext() const;
StringRef getName() const { return getStringField(3); } StringRef getName() const { return getStringField(3); }
unsigned getLineNumber() const { return getUnsignedField(4); } unsigned getLineNumber() const { return getUnsignedField(4); }
uint64_t getSizeInBits() const { return getUInt64Field(5); } uint64_t getSizeInBits() const { return getUInt64Field(5); }
@ -297,6 +283,53 @@ namespace llvm {
void replaceAllUsesWith(MDNode *D); void replaceAllUsesWith(MDNode *D);
}; };
/// 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::generateRef();
/// Val can be either a MDNode or a MDString, in the latter,
/// MDString specifies the type identifier.
const Value *Val;
explicit DIRef(const Value *V);
public:
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(DIType(Iter->second).isType() &&
"MDNode in DITypeIdentifierMap should be a DIType.");
return T(Iter->second);
}
operator Value *() const { return const_cast<Value*>(Val); }
};
/// Specialize getFieldAs to handle fields that are references to DIScopes.
template <>
DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const;
/// Specialize DIRef constructor for DIScopeRef.
template <>
DIRef<DIScope>::DIRef(const Value *V);
typedef DIRef<DIType> DITypeRef;
/// Specialize getFieldAs to handle fields that are references to DITypes.
template <>
DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const;
/// Specialize DIRef constructor for DITypeRef.
template <>
DIRef<DIType>::DIRef(const Value *V);
/// DIBasicType - A basic type, like 'int' or 'float'. /// DIBasicType - A basic type, like 'int' or 'float'.
class DIBasicType : public DIType { class DIBasicType : public DIType {
public: public:
@ -328,9 +361,9 @@ namespace llvm {
/// associated with one. /// associated with one.
MDNode *getObjCProperty() const; MDNode *getObjCProperty() const;
DIScopeRef getClassType() const { DITypeRef getClassType() const {
assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); assert(getTag() == dwarf::DW_TAG_ptr_to_member_type);
return getFieldAs<DIScopeRef>(10); return getFieldAs<DITypeRef>(10);
} }
Constant *getConstant() const { Constant *getConstant() const {
@ -358,8 +391,8 @@ namespace llvm {
void setTypeArray(DIArray Elements, DIArray TParams = DIArray()); void setTypeArray(DIArray Elements, DIArray TParams = DIArray());
void addMember(DIDescriptor D); void addMember(DIDescriptor D);
unsigned getRunTimeLang() const { return getUnsignedField(11); } unsigned getRunTimeLang() const { return getUnsignedField(11); }
DIScopeRef getContainingType() const { DITypeRef getContainingType() const {
return getFieldAs<DIScopeRef>(12); return getFieldAs<DITypeRef>(12);
} }
void setContainingType(DICompositeType ContainingType); void setContainingType(DICompositeType ContainingType);
DIArray getTemplateParams() const { return getFieldAs<DIArray>(13); } DIArray getTemplateParams() const { return getFieldAs<DIArray>(13); }
@ -426,8 +459,8 @@ namespace llvm {
unsigned getVirtuality() const { return getUnsignedField(10); } unsigned getVirtuality() const { return getUnsignedField(10); }
unsigned getVirtualIndex() const { return getUnsignedField(11); } unsigned getVirtualIndex() const { return getUnsignedField(11); }
DIScopeRef getContainingType() const { DITypeRef getContainingType() const {
return getFieldAs<DIScopeRef>(12); return getFieldAs<DITypeRef>(12);
} }
unsigned getFlags() const { unsigned getFlags() const {

View File

@ -2644,8 +2644,3 @@ void DwarfDebug::emitDebugStrDWO() {
InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(), InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
OffSec, StrSym); OffSec, StrSym);
} }
/// Find the MDNode for the given scope reference.
DIScope DwarfDebug::resolve(DIScopeRef SRef) const {
return SRef.resolve(TypeIdentifierMap);
}

View File

@ -684,7 +684,10 @@ public:
unsigned getDwarfVersion() const { return DwarfVersion; } unsigned getDwarfVersion() const { return DwarfVersion; }
/// Find the MDNode for the given scope reference. /// Find the MDNode for the given scope reference.
DIScope resolve(DIScopeRef SRef) const; template <typename T>
T resolve(DIRef<T> Ref) const {
return Ref.resolve(TypeIdentifierMap);
}
/// isSubprogramContext - Return true if Context is either a subprogram /// isSubprogramContext - Return true if Context is either a subprogram
/// or another context nested inside a subprogram. /// or another context nested inside a subprogram.

View File

@ -725,13 +725,13 @@ void DICompositeType::addMember(DIDescriptor D) {
/// Generate a reference to this DIType. Uses the type identifier instead /// Generate a reference to this DIType. Uses the type identifier instead
/// of the actual MDNode if possible, to help type uniquing. /// of the actual MDNode if possible, to help type uniquing.
Value *DIScope::generateRef() { DIScopeRef DIScope::generateRef() {
if (!isCompositeType()) if (!isCompositeType())
return *this; return DIScopeRef(*this);
DICompositeType DTy(DbgNode); DICompositeType DTy(DbgNode);
if (!DTy.getIdentifier()) if (!DTy.getIdentifier())
return *this; return DIScopeRef(*this);
return DTy.getIdentifier(); return DIScopeRef(DTy.getIdentifier());
} }
/// \brief Set the containing type. /// \brief Set the containing type.
@ -1432,26 +1432,14 @@ void DIVariable::printExtendedName(raw_ostream &OS) const {
} }
} }
DIScopeRef::DIScopeRef(const Value *V) : Val(V) { /// Specialize constructor to make sure it has the correct type.
template <>
DIRef<DIScope>::DIRef(const Value *V) : Val(V) {
assert(isScopeRef(V) && "DIScopeRef should be a MDString or MDNode"); assert(isScopeRef(V) && "DIScopeRef should be a MDString or MDNode");
} }
template <>
/// Given a DITypeIdentifierMap, tries to find the corresponding DIRef<DIType>::DIRef(const Value *V) : Val(V) {
/// DIScope for a DIScopeRef. assert(isTypeRef(V) && "DITypeRef should be a MDString or MDNode");
DIScope DIScopeRef::resolve(const DITypeIdentifierMap &Map) const {
if (!Val)
return DIScope();
if (const MDNode *MD = dyn_cast<MDNode>(Val))
return DIScope(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(DIType(Iter->second).isType() &&
"MDNode in DITypeIdentifierMap should be a DIType.");
return DIScope(Iter->second);
} }
/// Specialize getFieldAs to handle fields that are references to DIScopes. /// Specialize getFieldAs to handle fields that are references to DIScopes.
@ -1459,3 +1447,12 @@ template <>
DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const { DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const {
return DIScopeRef(getField(DbgNode, Elt)); return DIScopeRef(getField(DbgNode, Elt));
} }
/// Specialize getFieldAs to handle fields that are references to DITypes.
template <>
DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const {
return DITypeRef(getField(DbgNode, Elt));
}
DIScopeRef DIType::getContext() const {
return getFieldAs<DIScopeRef>(2);
}