[llvm] r191792 - Debug Info: remove duplication of DIEs when a DIE is part of the type system

Manman Ren manman.ren at gmail.com
Tue Oct 1 12:52:23 PDT 2013


Author: mren
Date: Tue Oct  1 14:52:23 2013
New Revision: 191792

URL: http://llvm.org/viewvc/llvm-project?rev=191792&view=rev
Log:
Debug Info: remove duplication of DIEs when a DIE is part of the type system
and it is shared across CUs.

We add a few maps in DwarfDebug to map MDNodes for the type system to the
corresponding DIEs: MDTypeNodeToDieMap, MDSPNodeToDieMap, and
MDStaticMemberNodeToDieMap. These DIEs can be shared across CUs, that is why we
keep the maps in DwarfDebug instead of CompileUnit.

Sometimes, when we try to add an attribute to a DIE, the DIE is not yet added
to its owner yet, so we don't know whether we should use ref_addr or ref4.
We create a worklist that will be processed during finalization to add
attributes with the correct form (ref_addr or ref4).

We add addDIEEntry to DwarfDebug to be a wrapper around DIE->addValue. It checks
whether we know the correct form, if not, we update the worklist
(DIEEntryWorklist).

A testing case is added to show that we only create a single DIE for a type
MDNode and we use ref_addr to refer to the type DIE.

Modified:
    llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
    llvm/trunk/test/Linker/type-unique-simple-a.ll

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp?rev=191792&r1=191791&r2=191792&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp Tue Oct  1 14:52:23 2013
@@ -113,13 +113,21 @@ DIE::~DIE() {
 /// Climb up the parent chain to get the compile unit DIE to which this DIE
 /// belongs.
 DIE *DIE::getCompileUnit() {
+  DIE *Cu = checkCompileUnit();
+  assert(Cu && "We should not have orphaned DIEs.");
+  return Cu;
+}
+
+/// Climb up the parent chain to get the compile unit DIE this DIE belongs
+/// to. Return NULL if DIE is not added to an owner yet.
+DIE *DIE::checkCompileUnit() {
   DIE *p = this;
   while (p) {
     if (p->getTag() == dwarf::DW_TAG_compile_unit)
       return p;
     p = p->getParent();
   }
-  llvm_unreachable("We should not have orphaned DIEs.");
+  return NULL;
 }
 
 DIEValue *DIE::findAttribute(uint16_t Attribute) {

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h?rev=191792&r1=191791&r2=191792&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h Tue Oct  1 14:52:23 2013
@@ -152,6 +152,9 @@ namespace llvm {
     /// Climb up the parent chain to get the compile unit DIE this DIE belongs
     /// to.
     DIE *getCompileUnit();
+    /// Similar to getCompileUnit, returns null when DIE is not added to an
+    /// owner yet.
+    DIE *checkCompileUnit();
     void setTag(uint16_t Tag) { Abbrev.setTag(Tag); }
     void setOffset(unsigned O) { Offset = O; }
     void setSize(unsigned S) { Size = S; }

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp?rev=191792&r1=191791&r2=191792&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp Tue Oct  1 14:52:23 2013
@@ -242,7 +242,7 @@ void CompileUnit::addDelta(DIE *Die, uin
 ///
 void CompileUnit::addDIEEntry(DIE *Die, uint16_t Attribute, uint16_t Form,
                               DIE *Entry) {
-  Die->addValue(Attribute, Form, createDIEEntry(Entry));
+  DD->addDIEEntry(Die, Attribute, Form, createDIEEntry(Entry));
 }
 
 /// addBlock - Add block data.
@@ -784,13 +784,13 @@ DIE *CompileUnit::getOrCreateTypeDIE(con
   DIType Ty(TyNode);
   if (!Ty.isType())
     return NULL;
-  DIE *TyDIE = getDIE(Ty);
+  DIE *TyDIE = DD->getTypeDIE(Ty);
   if (TyDIE)
     return TyDIE;
 
   // Create new type.
   TyDIE = new DIE(dwarf::DW_TAG_base_type);
-  insertDIE(Ty, TyDIE);
+  DD->insertTypeDIE(Ty, TyDIE);
   if (Ty.isBasicType())
     constructTypeDIE(*TyDIE, DIBasicType(Ty));
   else if (Ty.isCompositeType())
@@ -826,7 +826,7 @@ void CompileUnit::addType(DIE *Entity, D
   DIEEntry *Entry = getDIEEntry(Ty);
   // If it exists then use the existing value.
   if (Entry) {
-    Entity->addValue(Attribute, dwarf::DW_FORM_ref4, Entry);
+    DD->addDIEEntry(Entity, Attribute, dwarf::DW_FORM_ref4, Entry);
     return;
   }
 
@@ -836,7 +836,7 @@ void CompileUnit::addType(DIE *Entity, D
   // Set up proxy.
   Entry = createDIEEntry(Buffer);
   insertDIEEntry(Ty, Entry);
-  Entity->addValue(Attribute, dwarf::DW_FORM_ref4, Entry);
+  DD->addDIEEntry(Entity, Attribute, dwarf::DW_FORM_ref4, Entry);
 
   // If this is a complete composite type then include it in the
   // list of global types.
@@ -1268,14 +1268,14 @@ DIE *CompileUnit::getOrCreateNameSpace(D
 
 /// getOrCreateSubprogramDIE - Create new DIE using SP.
 DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
-  DIE *SPDie = getDIE(SP);
+  DIE *SPDie = DD->getSPDIE(SP);
   if (SPDie)
     return SPDie;
 
   SPDie = new DIE(dwarf::DW_TAG_subprogram);
 
   // DW_TAG_inlined_subroutine may refer to this DIE.
-  insertDIE(SP, SPDie);
+  DD->insertSPDIE(SP, SPDie);
 
   DISubprogram SPDecl = SP.getFunctionDeclaration();
   DIE *DeclDie = NULL;
@@ -1422,7 +1422,7 @@ void CompileUnit::createGlobalVariableDI
     // But that class might not exist in the DWARF yet.
     // Creating the class will create the static member decl DIE.
     getOrCreateContextDIE(DD->resolve(SDMDecl.getContext()));
-    VariableDIE = getDIE(SDMDecl);
+    VariableDIE = DD->getStaticMemberDIE(SDMDecl);
     assert(VariableDIE && "Static member decl has no context?");
     IsStaticMember = true;
   }
@@ -1616,7 +1616,7 @@ void CompileUnit::constructContainingTyp
     DIE *SPDie = CI->first;
     const MDNode *N = CI->second;
     if (!N) continue;
-    DIE *NDie = getDIE(N);
+    DIE *NDie = DD->getTypeDIE(N);
     if (!NDie) continue;
     addDIEEntry(SPDie, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, NDie);
   }
@@ -1819,6 +1819,6 @@ DIE *CompileUnit::createStaticMemberDIE(
   if (const ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(DT.getConstant()))
     addConstantFPValue(StaticMemberDIE, CFP);
 
-  insertDIE(DT, StaticMemberDIE);
+  DD->insertStaticMemberDIE(DT, StaticMemberDIE);
   return StaticMemberDIE;
 }

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=191792&r1=191791&r2=191792&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Tue Oct  1 14:52:23 2013
@@ -357,7 +357,7 @@ bool DwarfDebug::isSubprogramContext(con
 // scope then create and insert DIEs for these variables.
 DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU,
                                           const MDNode *SPNode) {
-  DIE *SPDie = SPCU->getDIE(SPNode);
+  DIE *SPDie = getSPDIE(SPNode);
 
   assert(SPDie && "Unable to find subprogram DIE!");
   DISubprogram SP(SPNode);
@@ -511,7 +511,7 @@ DIE *DwarfDebug::constructInlinedScopeDI
     return NULL;
   DIScope DS(Scope->getScopeNode());
   DISubprogram InlinedSP = getDISubprogram(DS);
-  DIE *OriginDIE = TheCU->getDIE(InlinedSP);
+  DIE *OriginDIE = getSPDIE(InlinedSP);
   if (!OriginDIE) {
     DEBUG(dbgs() << "Unable to find original DIE for an inlined subprogram.");
     return NULL;
@@ -616,7 +616,7 @@ DIE *DwarfDebug::constructScopeDIE(Compi
   else if (DS.isSubprogram()) {
     ProcessedSPNodes.insert(DS);
     if (Scope->isAbstractScope()) {
-      ScopeDIE = TheCU->getDIE(DS);
+      ScopeDIE = getSPDIE(DS);
       // Note down abstract DIE.
       if (ScopeDIE)
         AbstractSPDies.insert(std::make_pair(DS, ScopeDIE));
@@ -992,7 +992,7 @@ void DwarfDebug::collectDeadVariables()
         CompileUnit *SPCU = CUMap.lookup(TheCU);
         assert(SPCU && "Unable to find Compile Unit!");
         constructSubprogramDIE(SPCU, SP);
-        DIE *ScopeDIE = SPCU->getDIE(SP);
+        DIE *ScopeDIE = getSPDIE(SP);
         for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) {
           DIVariable DV(Variables.getElement(vi));
           if (!DV.isVariable()) continue;
@@ -1065,6 +1065,15 @@ void DwarfDebug::finalizeModuleInfo() {
                                      Hash.computeDIEODRSignature(Die));
   }
 
+  // Process the worklist to add attributes with the correct form (ref_addr or
+  // ref4).
+  for (unsigned I = 0, E = DIEEntryWorklist.size(); I < E; I++) {
+    addDIEEntry(DIEEntryWorklist[I].Die, DIEEntryWorklist[I].Attribute,
+                dwarf::DW_FORM_ref4, DIEEntryWorklist[I].Entry);
+    assert(E == DIEEntryWorklist.size() &&
+           "We should not add to the worklist during finalization.");
+  }
+
   // Handle anything that needs to be done on a per-cu basis.
   for (DenseMap<const MDNode *, CompileUnit *>::iterator CUI = CUMap.begin(),
                                                          CUE = CUMap.end();
@@ -2042,7 +2051,11 @@ void DwarfDebug::emitDIE(DIE *Die, std::
       Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr));
 
     switch (Attr) {
-    case dwarf::DW_AT_abstract_origin: {
+    case dwarf::DW_AT_abstract_origin:
+    case dwarf::DW_AT_type:
+    case dwarf::DW_AT_friend:
+    case dwarf::DW_AT_specification:
+    case dwarf::DW_AT_containing_type: {
       DIEEntry *E = cast<DIEEntry>(Values[i]);
       DIE *Origin = E->getEntry();
       unsigned Addr = Origin->getOffset();
@@ -3031,3 +3044,24 @@ void DwarfDebug::emitDebugStrDWO() {
   InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
                          OffSec, StrSym);
 }
+
+/// When we don't know whether the correct form is ref4 or ref_addr, we create
+/// a worklist item and insert it to DIEEntryWorklist.
+void DwarfDebug::addDIEEntry(DIE *Die, uint16_t Attribute, uint16_t Form,
+                             DIEEntry *Entry) {
+  /// Early exit when we only have a single CU.
+  if (GlobalCUIndexCount == 1 || Form != dwarf::DW_FORM_ref4) {
+    Die->addValue(Attribute, Form, Entry);
+    return;
+  }
+  DIE *DieCU = Die->checkCompileUnit();
+  DIE *EntryCU = Entry->getEntry()->checkCompileUnit();
+  if (!DieCU || !EntryCU) {
+    // Die or Entry is not added to an owner yet.
+    insertDIEEntryWorklist(Die, Attribute, Entry);
+    return;
+  }
+  Die->addValue(Attribute,
+         EntryCU == DieCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr,
+         Entry);
+}

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=191792&r1=191791&r2=191792&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Tue Oct  1 14:52:23 2013
@@ -326,6 +326,30 @@ class DwarfDebug {
   // Maps subprogram MDNode with its corresponding CompileUnit.
   DenseMap <const MDNode *, CompileUnit *> SPMap;
 
+  /// Maps type MDNode with its corresponding DIE. These DIEs can be
+  /// shared across CUs, that is why we keep the map here instead
+  /// of in CompileUnit.
+  DenseMap<const MDNode *, DIE *> MDTypeNodeToDieMap;
+  /// Maps subprogram MDNode with its corresponding DIE.
+  DenseMap<const MDNode *, DIE *> MDSPNodeToDieMap;
+  /// Maps static member MDNode with its corresponding DIE.
+  DenseMap<const MDNode *, DIE *> MDStaticMemberNodeToDieMap;
+
+  /// Specifies a worklist item. Sometimes, when we try to add an attribute to
+  /// a DIE, the DIE is not yet added to its owner yet, so we don't know whether
+  /// we should use ref_addr or ref4. We create a worklist that will be
+  /// processed during finalization to add attributes with the correct form
+  /// (ref_addr or ref4).
+  struct DIEEntryWorkItem {
+    DIE *Die;
+    uint16_t Attribute;
+    DIEEntry *Entry;
+    DIEEntryWorkItem(DIE *D, uint16_t A, DIEEntry *E) :
+      Die(D), Attribute(A), Entry(E) {
+    }
+  };
+  SmallVector<DIEEntryWorkItem, 64> DIEEntryWorklist;
+
   // Used to uniquely define abbreviations.
   FoldingSet<DIEAbbrev> AbbreviationsSet;
 
@@ -660,6 +684,28 @@ public:
   DwarfDebug(AsmPrinter *A, Module *M);
   ~DwarfDebug();
 
+  void insertTypeDIE(const MDNode *TypeMD, DIE *Die) {
+    MDTypeNodeToDieMap.insert(std::make_pair(TypeMD, Die));
+  }
+  DIE *getTypeDIE(const MDNode *TypeMD) {
+    return MDTypeNodeToDieMap.lookup(TypeMD);
+  }
+  void insertSPDIE(const MDNode *SPMD, DIE *Die) {
+    MDSPNodeToDieMap.insert(std::make_pair(SPMD, Die));
+  }
+  DIE *getSPDIE(const MDNode *SPMD) {
+    return MDSPNodeToDieMap.lookup(SPMD);
+  }
+  void insertStaticMemberDIE(const MDNode *StaticMD, DIE *Die) {
+    MDStaticMemberNodeToDieMap.insert(std::make_pair(StaticMD, Die));
+  }
+  DIE *getStaticMemberDIE(const MDNode *StaticMD) {
+    return MDStaticMemberNodeToDieMap.lookup(StaticMD);
+  }
+  void insertDIEEntryWorklist(DIE *Die, uint16_t Attribute, DIEEntry *Entry) {
+    DIEEntryWorklist.push_back(DIEEntryWorkItem(Die, Attribute, Entry));
+  }
+
   /// \brief Emit all Dwarf sections that should come prior to the
   /// content.
   void beginModule();
@@ -722,6 +768,11 @@ public:
     return Ref.resolve(TypeIdentifierMap);
   }
 
+  /// When we don't know whether the correct form is ref4 or ref_addr, we create
+  /// a worklist item and insert it to DIEEntryWorklist.
+  void addDIEEntry(DIE *Die, uint16_t Attribute, uint16_t Form,
+                   DIEEntry *Entry);
+
   /// isSubprogramContext - Return true if Context is either a subprogram
   /// or another context nested inside a subprogram.
   bool isSubprogramContext(const MDNode *Context);

Modified: llvm/trunk/test/Linker/type-unique-simple-a.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/type-unique-simple-a.ll?rev=191792&r1=191791&r2=191792&view=diff
==============================================================================
--- llvm/trunk/test/Linker/type-unique-simple-a.ll (original)
+++ llvm/trunk/test/Linker/type-unique-simple-a.ll Tue Oct  1 14:52:23 2013
@@ -1,7 +1,22 @@
-; RUN: llvm-link %s %p/type-unique-simple-b.ll -S -o - | FileCheck %s
+; REQUIRES: object-emission
 
-; CHECK: DW_TAG_structure_type
+; RUN: llvm-link %s %p/type-unique-simple-b.ll -S -o %t
+; RUN: cat %t | FileCheck %s -check-prefix=LINK
+; RUN: llc -filetype=obj -O0 < %t > %t2
+; RUN: llvm-dwarfdump -debug-dump=info %t2 | FileCheck %s
+; CHECK: 0x[[INT:.*]]: DW_TAG_base_type
+; CHECK-NEXT: DW_AT_name {{.*}} = "int"
+; CHECK-NOT: DW_TAG_base_type
+; CHECK: 0x[[BASE:.*]]: DW_TAG_structure_type
+; CHECK-NEXT: DW_AT_name {{.*}} = "Base"
 ; CHECK-NOT: DW_TAG_structure_type
+; CHECK: DW_TAG_formal_parameter
+; CHECK: DW_AT_type [DW_FORM_ref_addr] {{.*}}[[INT]])
+; CHECK: DW_TAG_variable
+; CHECK: DW_AT_type [DW_FORM_ref_addr] {{.*}}[[BASE]])
+
+; LINK: DW_TAG_structure_type
+; LINK-NOT: DW_TAG_structure_type
 ; Content of header files:
 ; struct Base {
 ;   int a;





More information about the llvm-commits mailing list