aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
diff options
context:
space:
mode:
authorManman Ren <manman.ren@gmail.com>2013-10-01 19:52:23 +0000
committerManman Ren <manman.ren@gmail.com>2013-10-01 19:52:23 +0000
commit620f436b205ab75e1dd48b9af8823bc30c53fd0e (patch)
tree14f7063a4c9f6a7de435b7b16894045baeb9ffb0 /lib/CodeGen/AsmPrinter/DwarfDebug.cpp
parentdfef7cbfc6a96d129b99750f554c7dbc000d3228 (diff)
downloadexternal_llvm-620f436b205ab75e1dd48b9af8823bc30c53fd0e.zip
external_llvm-620f436b205ab75e1dd48b9af8823bc30c53fd0e.tar.gz
external_llvm-620f436b205ab75e1dd48b9af8823bc30c53fd0e.tar.bz2
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191792 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp44
1 files changed, 39 insertions, 5 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 3826255..3f2de40 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);
+}