<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Oct 1, 2013 at 12:52 PM, Manman Ren <span dir="ltr"><<a href="mailto:manman.ren@gmail.com" target="_blank">manman.ren@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: mren<br>
Date: Tue Oct  1 14:52:23 2013<br>
New Revision: 191792<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=191792&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=191792&view=rev</a><br>
Log:<br>
Debug Info: remove duplication of DIEs when a DIE is part of the type system<br>
and it is shared across CUs.<br></blockquote><div><br></div><div>This may require some discussion/consideration.</div><div><br></div><div>The first thing that comes to my mind is that this is changing the DIE structure from trees to DAGs and, perhaps importantly, is going to make parent/child relationships incomplete (ie: A child of B no longer implies that B is the parent of A) which is a bit concerning.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
We add a few maps in DwarfDebug to map MDNodes for the type system to the<br>
corresponding DIEs: MDTypeNodeToDieMap, MDSPNodeToDieMap, and<br>
MDStaticMemberNodeToDieMap. These DIEs can be shared across CUs, that is why we<br>
keep the maps in DwarfDebug instead of CompileUnit.<br></blockquote><div><br></div><div>Why nod simply map MDNode* to DIE the same as we do in the CompileUnit? We should be able to do this for all DIEs, no? (essentially just move the map up from CompileUnit to DwarfDebug)<br>
<br>But I'm not sure how effective this would be - like I said, might need some thought/discussion to understand your solution & consider alternatives.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
Sometimes, when we try to add an attribute to a DIE, the DIE is not yet added<br>
to its owner yet, so we don't know whether we should use ref_addr or ref4.<br>
We create a worklist that will be processed during finalization to add<br>
attributes with the correct form (ref_addr or ref4).<br></blockquote><div><br></div><div>Do you have an example of this as a test case? (I really wish we had an easy way to see test coverage - so I could just tell at a glance whether the worklist code is being exercised by your test cases... oh well)</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
We add addDIEEntry to DwarfDebug to be a wrapper around DIE->addValue. It checks<br>
whether we know the correct form, if not, we update the worklist<br>
(DIEEntryWorklist).<br>
<br>
A testing case is added to show that we only create a single DIE for a type<br>
MDNode and we use ref_addr to refer to the type DIE.<br>
<br>
Modified:<br>
    llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp<br>
    llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h<br>
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp<br>
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp<br>
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h<br>
    llvm/trunk/test/Linker/type-unique-simple-a.ll<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp?rev=191792&r1=191791&r2=191792&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp?rev=191792&r1=191791&r2=191792&view=diff</a><br>

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

==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h Tue Oct  1 14:52:23 2013<br>
@@ -152,6 +152,9 @@ namespace llvm {<br>
     /// Climb up the parent chain to get the compile unit DIE this DIE belongs<br>
     /// to.<br>
     DIE *getCompileUnit();<br>
+    /// Similar to getCompileUnit, returns null when DIE is not added to an<br>
+    /// owner yet.<br>
+    DIE *checkCompileUnit();<br></blockquote><div><br></div><div>Why is this not just "getParent() == NULL"? Why do you need a walk for the DIE?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

     void setTag(uint16_t Tag) { Abbrev.setTag(Tag); }<br>
     void setOffset(unsigned O) { Offset = O; }<br>
     void setSize(unsigned S) { Size = S; }<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp?rev=191792&r1=191791&r2=191792&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp?rev=191792&r1=191791&r2=191792&view=diff</a><br>

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

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

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

==============================================================================<br>
--- llvm/trunk/test/Linker/type-unique-simple-a.ll (original)<br>
+++ llvm/trunk/test/Linker/type-unique-simple-a.ll Tue Oct  1 14:52:23 2013<br>
@@ -1,7 +1,22 @@<br>
-; RUN: llvm-link %s %p/type-unique-simple-b.ll -S -o - | FileCheck %s<br>
+; REQUIRES: object-emission<br>
<br>
-; CHECK: DW_TAG_structure_type<br>
+; RUN: llvm-link %s %p/type-unique-simple-b.ll -S -o %t<br>
+; RUN: cat %t | FileCheck %s -check-prefix=LINK<br>
+; RUN: llc -filetype=obj -O0 < %t > %t2<br>
+; RUN: llvm-dwarfdump -debug-dump=info %t2 | FileCheck %s<br>
+; CHECK: 0x[[INT:.*]]: DW_TAG_base_type<br>
+; CHECK-NEXT: DW_AT_name {{.*}} = "int"<br>
+; CHECK-NOT: DW_TAG_base_type<br>
+; CHECK: 0x[[BASE:.*]]: DW_TAG_structure_type<br>
+; CHECK-NEXT: DW_AT_name {{.*}} = "Base"<br>
 ; CHECK-NOT: DW_TAG_structure_type<br>
+; CHECK: DW_TAG_formal_parameter<br>
+; CHECK: DW_AT_type [DW_FORM_ref_addr] {{.*}}[[INT]])<br>
+; CHECK: DW_TAG_variable<br>
+; CHECK: DW_AT_type [DW_FORM_ref_addr] {{.*}}[[BASE]])<br>
+<br>
+; LINK: DW_TAG_structure_type<br>
+; LINK-NOT: DW_TAG_structure_type<br>
 ; Content of header files:<br>
 ; struct Base {<br>
 ;   int a;<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>