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
This commit is contained in:
Manman Ren
2013-10-01 19:52:23 +00:00
parent dfef7cbfc6
commit 620f436b20
6 changed files with 129 additions and 18 deletions

View File

@ -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);
}