diff options
Diffstat (limited to 'llvm/lib/IR/DebugInfo.cpp')
-rw-r--r-- | llvm/lib/IR/DebugInfo.cpp | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 9684bd73f4e..d3207cae350 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -425,6 +425,17 @@ static bool fieldIsMDString(const MDNode *DbgNode, unsigned Elt) { return !Fld || isa<MDString>(Fld); } +/// Check if a value can be a TypeRef. +static bool isTypeRef(const Value *Val) { + return !Val || isa<MDString>(Val) || isa<MDNode>(Val); +} + +/// Check if a field at position Elt of a MDNode can be a TypeRef. +static bool fieldIsTypeRef(const MDNode *DbgNode, unsigned Elt) { + Value *Fld = getField(DbgNode, Elt); + return isTypeRef(Fld); +} + /// Verify - Verify that a type descriptor is well formed. bool DIType::Verify() const { if (!isType()) @@ -470,8 +481,8 @@ bool DIDerivedType::Verify() const { if (!fieldIsMDNode(DbgNode, 9)) return false; if (getTag() == dwarf::DW_TAG_ptr_to_member_type) - // Make sure ClassType @ field 10 is MDNode. - if (!fieldIsMDNode(DbgNode, 10)) + // Make sure ClassType @ field 10 is a TypeRef. + if (!fieldIsTypeRef(DbgNode, 10)) return false; return isDerivedType() && DbgNode->getNumOperands() >= 10 && @@ -923,6 +934,32 @@ bool llvm::isSubprogramContext(const MDNode *Context) { return false; } +/// Update DITypeIdentifierMap by going through retained types of each CU. +DITypeIdentifierMap llvm::generateDITypeIdentifierMap( + const NamedMDNode *CU_Nodes) { + DITypeIdentifierMap Map; + for (unsigned CUi = 0, CUe = CU_Nodes->getNumOperands(); CUi != CUe; ++CUi) { + DICompileUnit CU(CU_Nodes->getOperand(CUi)); + DIArray Retain = CU.getRetainedTypes(); + for (unsigned Ti = 0, Te = Retain.getNumElements(); Ti != Te; ++Ti) { + if (!Retain.getElement(Ti).isCompositeType()) + continue; + DICompositeType Ty(Retain.getElement(Ti)); + if (MDString *TypeId = Ty.getIdentifier()) { + // Definition has priority over declaration. + // Try to insert (TypeId, Ty) to Map. + std::pair<DITypeIdentifierMap::iterator, bool> P = + Map.insert(std::make_pair(TypeId, Ty)); + // If TypeId already exists in Map and this is a definition, replace + // whatever we had (declaration or definition) with the definition. + if (!P.second && !Ty.isForwardDecl()) + P.first->second = Ty; + } + } + } + return Map; +} + //===----------------------------------------------------------------------===// // DebugInfoFinder implementations. //===----------------------------------------------------------------------===// @@ -1378,3 +1415,34 @@ void DIVariable::printExtendedName(raw_ostream &OS) const { } } } + +DITypeRef::DITypeRef(const Value *V) : TypeVal(V) { + assert(isTypeRef(V) && "DITypeRef should be a MDString or MDNode"); +} + +/// Given a DITypeIdentifierMap, tries to find the corresponding +/// DIType for a DITypeRef. +DIType DITypeRef::resolve(const DITypeIdentifierMap &Map) const { + if (!TypeVal) + return NULL; + + if (const MDNode *MD = dyn_cast<MDNode>(TypeVal)) { + assert(DIType(MD).isType() && + "MDNode in DITypeRef should be a DIType."); + return MD; + } + + const MDString *MS = cast<MDString>(TypeVal); + // 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 Iter->second; +} + +/// Specialize getFieldAs to handle fields that are references to DITypes. +template <> +DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const { + return DITypeRef(getField(DbgNode, Elt)); +} |