Debug Info: Fix LTO type uniquing for C++ member declarations
based on the ODR.
This adds an OdrMemberMap to DwarfDebug which is used to unique C++
member function declarations based on the unique identifier of their
containing class and their mangled name.
We can't use the usual DIRef mechanism here because DIScopes are indexed
using their entire MDNode, including decl_file and decl_line, which need
not be unique (see testcase).
Prior to this change multiple redundant member function declarations would
end up in the same uniqued DW_TAG_class_type.
llvm-svn: 203982
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 4b2b7b0..a03da3c 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -364,6 +364,7 @@
// scope then create and insert DIEs for these variables.
DIE *DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit *SPCU,
DISubprogram SP) {
+ SP = SPCU->getOdrUniqueSubprogram(resolve(SP.getContext()), SP);
DIE *SPDie = SPCU->getDIE(SP);
assert(SPDie && "Unable to find subprogram DIE!");
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index bd1d304..baf8732 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -353,6 +353,9 @@
/// of in DwarfCompileUnit.
DenseMap<const MDNode *, DIE *> MDTypeNodeToDieMap;
+ // Used to unique C++ member function declarations.
+ StringMap<const MDNode *> OdrMemberMap;
+
// Stores the current file ID for a given compile unit.
DenseMap<unsigned, unsigned> FileIDCUMap;
// Source id map, i.e. CUID, source filename and directory,
@@ -702,6 +705,11 @@
return MDTypeNodeToDieMap.lookup(TypeMD);
}
+ /// \brief Look up or create an entry in the OdrMemberMap.
+ const MDNode *&getOrCreateOdrMember(StringRef Key) {
+ return OdrMemberMap.GetOrCreateValue(Key).getValue();
+ }
+
/// \brief Emit all Dwarf sections that should come prior to the
/// content.
void beginModule();
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index dbdcf9d..836beb8 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1405,12 +1405,33 @@
return NDie;
}
+/// Unique C++ member function declarations based on their
+/// context and mangled name.
+DISubprogram
+DwarfUnit::getOdrUniqueSubprogram(DIScope Context, DISubprogram SP) const {
+ if (!hasODR() ||
+ !Context.isCompositeType() ||
+ SP.getLinkageName().empty() ||
+ SP.isDefinition())
+ return SP;
+ // Create a key with the UID of the parent class and this SP's name.
+ Twine Key = SP.getContext().getName() + SP.getLinkageName();
+ const MDNode *&Entry = DD->getOrCreateOdrMember(Key.str());
+ if (!Entry)
+ Entry = &*SP;
+
+ return DISubprogram(Entry);
+}
+
/// getOrCreateSubprogramDIE - Create new DIE using SP.
DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
// Construct the context before querying for the existence of the DIE in case
// such construction creates the DIE (as is the case for member function
// declarations).
- DIE *ContextDIE = getOrCreateContextDIE(resolve(SP.getContext()));
+ DIScope Context = resolve(SP.getContext());
+ DIE *ContextDIE = getOrCreateContextDIE(Context);
+ // Unique declarations based on the ODR, where applicable.
+ SP = getOdrUniqueSubprogram(Context, SP);
DIE *SPDie = getDIE(SP);
if (SPDie)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
index af465c0..d820873 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -485,6 +485,28 @@
virtual DwarfCompileUnit &getCU() = 0;
+ /// \brief Return whether this compilation unit has the
+ /// one-definition-rule (ODR). In C++ this allows the compiler to
+ /// perform type unique during LTO.
+ bool hasODR() const {
+ switch (getLanguage()) {
+ case dwarf::DW_LANG_C_plus_plus:
+ case dwarf::DW_LANG_C_plus_plus_03:
+ case dwarf::DW_LANG_C_plus_plus_11:
+ // For all we care, the C++ part of the language has the ODR and
+ // ObjC methods are not represented in a way that they could be
+ // confused with C++ member functions.
+ case dwarf::DW_LANG_ObjC_plus_plus:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /// \brief Unique C++ member function declarations based on their
+ /// context+mangled name.
+ DISubprogram getOdrUniqueSubprogram(DIScope Context, DISubprogram SP) const;
+
protected:
/// getOrCreateStaticMemberDIE - Create new static data member DIE.
DIE *getOrCreateStaticMemberDIE(DIDerivedType DT);