diff options
author | Manman Ren <manman.ren@gmail.com> | 2013-09-05 18:48:31 +0000 |
---|---|---|
committer | Manman Ren <manman.ren@gmail.com> | 2013-09-05 18:48:31 +0000 |
commit | bc66071baa3153ba95d673b8084383835221eef6 (patch) | |
tree | ea089a4002af6dfa75f7df34d5da3c0a36b04247 | |
parent | 79916948e1fd176a3898b596b679cc9dba3d40a8 (diff) | |
download | llvm-bc66071baa3153ba95d673b8084383835221eef6.tar.gz llvm-bc66071baa3153ba95d673b8084383835221eef6.tar.bz2 llvm-bc66071baa3153ba95d673b8084383835221eef6.tar.xz |
Debug Info: Use identifier to reference DIType in base type field of
ptr_to_member.
We introduce a new class DITypeRef that represents a reference to a DIType.
It wraps around a Value*, which can be either an identifier in MDString
or an actual MDNode. The class has a helper function "resolve" that
finds the actual MDNode for a given DITypeRef.
We specialize getFieldAs to return a field that is a reference to a
DIType. To correctly access the base type field of ptr_to_member,
getClassType now calls getFieldAs<DITypeRef> to return a DITypeRef.
Also add a typedef for DITypeIdentifierMap and a helper
generateDITypeIdentifierMap in DebugInfo.h. In DwarfDebug.cpp, we keep
a DITypeIdentifierMap and call generateDITypeIdentifierMap to actually
populate the map.
Verifier is updated accordingly.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190081 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/DebugInfo.h | 32 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.h | 7 | ||||
-rw-r--r-- | lib/IR/DIBuilder.cpp | 14 | ||||
-rw-r--r-- | lib/IR/DebugInfo.cpp | 72 | ||||
-rw-r--r-- | test/DebugInfo/tu-member-pointer.ll | 29 |
7 files changed, 156 insertions, 6 deletions
diff --git a/include/llvm/DebugInfo.h b/include/llvm/DebugInfo.h index 87ccac10dd..997d01e994 100644 --- a/include/llvm/DebugInfo.h +++ b/include/llvm/DebugInfo.h @@ -17,6 +17,7 @@ #ifndef LLVM_DEBUGINFO_H #define LLVM_DEBUGINFO_H +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -45,12 +46,19 @@ namespace llvm { class DILexicalBlockFile; class DIVariable; class DIType; + class DITypeRef; class DIObjCProperty; + /// Maps from type identifier to the actual MDNode. + typedef DenseMap<const MDString *, MDNode*> DITypeIdentifierMap; + /// DIDescriptor - A thin wraper around MDNode to access encoded debug info. /// This should not be stored in a container, because the underlying MDNode /// may change in certain situations. class DIDescriptor { + // Befriends DITypeRef so DITypeRef can befriend the protected member + // function: getFieldAs<DITypeRef>. + friend class DITypeRef; public: enum { FlagPrivate = 1 << 0, @@ -143,6 +151,23 @@ namespace llvm { void dump() const; }; + /// Specialize getFieldAs to handle fields that are references to DITypes. + template <> + DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const; + + /// Represents reference to a DIType, abstracts over direct and + /// identifier-based metadata type references. + class DITypeRef { + friend DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const; + + /// TypeVal can be either a MDNode or a MDString, in the latter, + /// MDString specifies the type identifier. + const Value *TypeVal; + explicit DITypeRef(const Value *V); + public: + DIType resolve(const DITypeIdentifierMap &Map) const; + }; + /// DISubrange - This is used to represent ranges, for array bounds. class DISubrange : public DIDescriptor { friend class DIDescriptor; @@ -296,9 +321,9 @@ namespace llvm { /// associated with one. MDNode *getObjCProperty() const; - DIType getClassType() const { + DITypeRef getClassType() const { assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - return getFieldAs<DIType>(10); + return getFieldAs<DITypeRef>(10); } Constant *getConstant() const { @@ -720,6 +745,9 @@ namespace llvm { /// cleanseInlinedVariable - Remove inlined scope from the variable. DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); + /// Construct DITypeIdentifierMap by going through retained types of each CU. + DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); + /// DebugInfoFinder tries to list all debug info MDNodes used in a module. To /// list debug info MDNodes used by an instruction, DebugInfoFinder uses /// processDeclare, processValue and processLocation to handle DbgDeclareInst, diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 4c95e14096..6db54d2faf 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -905,7 +905,7 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { if (Tag == dwarf::DW_TAG_ptr_to_member_type) addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, - getOrCreateTypeDIE(DTy.getClassType())); + getOrCreateTypeDIE(DD->resolve(DTy.getClassType()))); // Add source line info if available and TyDesc is not a forward declaration. if (!DTy.isForwardDecl()) addSourceLine(&Buffer, DTy); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index f97ddcb5a8..57ad489970 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -823,6 +823,7 @@ void DwarfDebug::beginModule() { NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); if (!CU_Nodes) return; + TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes); // Emit initial sections so we can reference labels later. emitSectionLabels(); @@ -2631,3 +2632,8 @@ void DwarfDebug::emitDebugStrDWO() { InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(), OffSec, StrSym); } + +/// Find the MDNode for the given type reference. +MDNode *DwarfDebug::resolve(DITypeRef TRef) const { + return TRef.resolve(TypeIdentifierMap); +} diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 97a454ac9d..0258fdc3db 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -450,6 +450,9 @@ class DwarfDebug { // Holder for the skeleton information. DwarfUnits SkeletonHolder; + // Maps from a type identifier to the actual MDNode. + DITypeIdentifierMap TypeIdentifierMap; + private: void addScopeVariable(LexicalScope *LS, DbgVariable *Var); @@ -679,6 +682,10 @@ public: /// Returns the Dwarf Version. unsigned getDwarfVersion() const { return DwarfVersion; } + + /// Find the MDNode for the given type reference. + MDNode *resolve(DITypeRef TRef) const; + }; } // End of namespace llvm diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp index 51e296383e..2ff10b593e 100644 --- a/lib/IR/DIBuilder.cpp +++ b/lib/IR/DIBuilder.cpp @@ -75,6 +75,18 @@ void DIBuilder::finalize() { DIType(TempImportedModules).replaceAllUsesWith(IMs); } +/// Use the type identifier instead of the actual MDNode if possible, +/// to help type uniquing. This function returns the identifier if it +/// exists for the given type, otherwise returns the MDNode. +static Value *getTypeIdentifier(DIType T) { + if (!T.isCompositeType()) + return T; + DICompositeType DTy(T); + if (!DTy.getIdentifier()) + return T; + return DTy.getIdentifier(); +} + /// getNonCompileUnitScope - If N is compile unit return NULL otherwise return /// N. static MDNode *getNonCompileUnitScope(MDNode *N) { @@ -322,7 +334,7 @@ DIDerivedType DIBuilder::createMemberPointerType(DIType PointeeTy, ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags PointeeTy, - Base + getTypeIdentifier(Base) }; return DIDerivedType(MDNode::get(VMContext, Elts)); } diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 9684bd73f4..d3207cae35 100644 --- a/lib/IR/DebugInfo.cpp +++ b/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)); +} diff --git a/test/DebugInfo/tu-member-pointer.ll b/test/DebugInfo/tu-member-pointer.ll new file mode 100644 index 0000000000..b8f6719bc3 --- /dev/null +++ b/test/DebugInfo/tu-member-pointer.ll @@ -0,0 +1,29 @@ +; REQUIRES: object-emission + +; RUN: llc -filetype=obj -O0 < %s > %t +; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s +; CHECK: [[TYPE:.*]]: DW_TAG_base_type +; CHECK: DW_TAG_ptr_to_member_type +; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + {{.*}} => {[[TYPE]]}) +; IR generated from clang -g with the following source: +; struct Foo { +; int e; +; }; +; int Foo:*x = 0; + +@x = global i64 -1, align 8 + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!10} + +!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.4", i1 false, metadata !"", i32 0, metadata !2, metadata !3, metadata !2, metadata !5, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [foo.cpp] [DW_LANG_C_plus_plus] +!1 = metadata !{metadata !"foo.cpp", metadata !"."} +!2 = metadata !{i32 0} +!3 = metadata !{metadata !4} +!4 = metadata !{i32 786451, metadata !1, null, metadata !"Foo", i32 1, i64 0, i64 0, i32 0, i32 4, null, null, i32 0, null, null, metadata !"_ZTS3Foo"} ; [ DW_TAG_structure_type ] [Foo] [line 1, size 0, align 0, offset 0] [decl] [from ] +!5 = metadata !{metadata !6} +!6 = metadata !{i32 786484, i32 0, null, metadata !"x", metadata !"x", metadata !"", metadata !7, i32 4, metadata !8, i32 0, i32 1, i64* @x, null} ; [ DW_TAG_variable ] [x] [line 4] [def] +!7 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [foo.cpp] +!8 = metadata !{i32 786463, null, null, null, i32 0, i64 0, i64 0, i64 0, i32 0, metadata !9, metadata !"_ZTS3Foo"} ; [ DW_TAG_ptr_to_member_type ] [line 0, size 0, align 0, offset 0] [from int] +!9 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!10 = metadata !{i32 2, metadata !"Dwarf Version", i32 2} |