summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.cpp10
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.h3
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp20
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp44
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h51
-rw-r--r--test/Linker/type-unique-simple-a.ll19
6 files changed, 129 insertions, 18 deletions
diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp
index 7fb3c90dcb..7a14be65e2 100644
--- a/lib/CodeGen/AsmPrinter/DIE.cpp
+++ b/lib/CodeGen/AsmPrinter/DIE.cpp
@@ -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) {
diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h
index 6eaa6ee66e..35b76b52c1 100644
--- a/lib/CodeGen/AsmPrinter/DIE.h
+++ b/lib/CodeGen/AsmPrinter/DIE.h
@@ -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; }
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index d3d8251bb2..e5761ea475 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -242,7 +242,7 @@ void CompileUnit::addDelta(DIE *Die, uint16_t Attribute, uint16_t Form,
///
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(const MDNode *TyNode) {
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, DIType Ty, uint16_t Attribute) {
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, DIType Ty, uint16_t Attribute) {
// 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(DINameSpace NS) {
/// 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::createGlobalVariableDIE(const MDNode *N) {
// 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::constructContainingTypeDIEs() {
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(const DIDerivedType DT) {
if (const ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(DT.getConstant()))
addConstantFPValue(StaticMemberDIE, CFP);
- insertDIE(DT, StaticMemberDIE);
+ DD->insertStaticMemberDIE(DT, StaticMemberDIE);
return StaticMemberDIE;
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 3826255697..3f2de40fa8 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -357,7 +357,7 @@ bool DwarfDebug::isSubprogramContext(const MDNode *Context) {
// 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::constructInlinedScopeDIE(CompileUnit *TheCU,
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(CompileUnit *TheCU, LexicalScope *Scope) {
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::vector<DIEAbbrev *> *Abbrevs) {
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);
+}
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 144635ef6a..7e0ae22f51 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -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);
diff --git a/test/Linker/type-unique-simple-a.ll b/test/Linker/type-unique-simple-a.ll
index 7c2e7bfa90..251e5b3424 100644
--- a/test/Linker/type-unique-simple-a.ll
+++ b/test/Linker/type-unique-simple-a.ll
@@ -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;