Skip to content

Commit

Permalink
Supporting all entities declared in lexical scope in LLVM debug info.
Browse files Browse the repository at this point in the history
Differential Revision: http://reviews.llvm.org/D15976

llvm-svn: 261633
  • Loading branch information
Amjad Aboud committed Feb 23, 2016
1 parent d1abcf7 commit fc8f296
Showing 20 changed files with 815 additions and 91 deletions.
140 changes: 108 additions & 32 deletions llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
Original file line number Diff line number Diff line change
@@ -114,10 +114,16 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(

// Construct the context before querying for the existence of the DIE in
// case such construction creates the DIE.
DIE *ContextDIE = getOrCreateContextDIE(GVContext);
// For Local Scope, do not construct context DIE.
bool IsLocalScope = GVContext && isa<DILocalScope>(GVContext);
DIE *ContextDIE = IsLocalScope ? nullptr : getOrCreateContextDIE(GVContext);
assert(ContextDIE || IsLocalScope);

// Create new global variable and add to map.
DIE *VariableDIE = IsLocalScope
? createDIE(GV->getTag(), GV)
: &createAndAddDIE(GV->getTag(), *ContextDIE, GV);

// Add to map.
DIE *VariableDIE = &createAndAddDIE(GV->getTag(), *ContextDIE, GV);
DIScope *DeclContext;
if (auto *SDMDecl = GV->getStaticDataMemberDeclaration()) {
DeclContext = resolve(SDMDecl->getScope());
@@ -335,23 +341,15 @@ void DwarfCompileUnit::constructScopeDIE(
if (DD->isLexicalScopeDIENull(Scope))
return;

unsigned ChildScopeCount;
bool HasNonScopeChildren;

// We create children here when we know the scope DIE is not going to be
// null and the children will be added to the scope DIE.
createScopeChildrenDIE(Scope, Children, &ChildScopeCount);

// Skip imported directives in gmlt-like data.
if (!includeMinimalInlineScopes()) {
// There is no need to emit empty lexical block DIE.
for (const auto *IE : ImportedEntities[DS])
Children.push_back(
constructImportedEntityDIE(cast<DIImportedEntity>(IE)));
}
createScopeChildrenDIE(Scope, Children, &HasNonScopeChildren);

// If there are only other scopes as children, put them directly in the
// parent instead, as this scope would serve no purpose.
if (Children.size() == ChildScopeCount) {
if (!HasNonScopeChildren) {
FinalChildren.insert(FinalChildren.end(),
std::make_move_iterator(Children.begin()),
std::make_move_iterator(Children.end()));
@@ -366,6 +364,7 @@ void DwarfCompileUnit::constructScopeDIE(
ScopeDIE->addChild(std::move(I));

FinalChildren.push_back(std::move(ScopeDIE));
addLocalScopeDieToLexicalScope(Scope, ScopeDIE);
}

DIE::value_iterator
@@ -558,20 +557,37 @@ DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV,

DIE *DwarfCompileUnit::createScopeChildrenDIE(LexicalScope *Scope,
SmallVectorImpl<DIE *> &Children,
unsigned *ChildScopeCount) {
bool *HasNonScopeChildren) {
DIE *ObjectPointer = nullptr;
bool HasLocalDclDie = false;
auto *DS = Scope->getScopeNode();

for (DbgVariable *DV : DU->getScopeVariables().lookup(Scope))
Children.push_back(constructVariableDIE(*DV, *Scope, ObjectPointer));

unsigned ChildCountWithoutScopes = Children.size();
// Skip local declarations in gmlt-like data.
if (!includeMinimalInlineScopes()) {
for (const auto *DI : LocalDeclNodes[DS]) {
DIE *D = nullptr;
if (auto *IE = dyn_cast<DIImportedEntity>(DI))
D = getOrCreateImportedEntityDIE(IE);
else if (auto *GV = dyn_cast<DIGlobalVariable>(DI))
D = getOrCreateGlobalVariableDIE(GV);
else if (auto *RT = dyn_cast<DIType>(DI))
D = getOrCreateTypeDIE(RT);
else
llvm_unreachable("Unexpected DI node!");
addLocalDclDieToLexicalScope(Scope, D);
HasLocalDclDie = true;
}
}

if (HasNonScopeChildren)
*HasNonScopeChildren = !Children.empty() || HasLocalDclDie;

for (LexicalScope *LS : Scope->getChildren())
constructScopeDIE(LS, Children);

if (ChildScopeCount)
*ChildScopeCount = Children.size() - ChildCountWithoutScopes;

return ObjectPointer;
}

@@ -613,6 +629,8 @@ DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope,
for (auto &I : Children)
ScopeDIE.addChild(std::move(I));

addLocalScopeDieToLexicalScope(Scope, &ScopeDIE);

return ObjectPointer;
}

@@ -649,10 +667,20 @@ void DwarfCompileUnit::constructAbstractSubprogramScopeDIE(
addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
}

DIE *DwarfCompileUnit::getOrCreateImportedEntityDIE(
const DIImportedEntity *Module) {
if (DIE *Die = getDIE(Module))
return Die;

return constructImportedEntityDIE(Module);
}

DIE *DwarfCompileUnit::constructImportedEntityDIE(
const DIImportedEntity *Module) {
DIE *IMDie = DIE::get(DIEValueAllocator, (dwarf::Tag)Module->getTag());
insertDIE(Module, IMDie);

assert(!getDIE(Module));

DIE *IMDie = createDIE(Module->getTag(), Module);
DIE *EntityDie;
auto *Entity = resolve(Module->getEntity());
if (auto *NS = dyn_cast<DINamespace>(Entity))
@@ -679,22 +707,46 @@ DIE *DwarfCompileUnit::constructImportedEntityDIE(
}

void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) {
DIE *D = getDIE(SP);
if (DIE *AbsSPDIE = DU->getAbstractSPDies().lookup(SP)) {
if (D)
if (DIE *D = getDIE(SP)) {
if (DIE *AbsSPDIE = DU->getAbstractSPDies().lookup(SP))
// If this subprogram has an abstract definition, reference that
addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE);
} else {
if (!D && !includeMinimalInlineScopes())
// Lazily construct the subprogram if we didn't see either concrete or
// inlined versions during codegen. (except in -gmlt ^ where we want
// to omit these entirely)
D = getOrCreateSubprogramDIE(SP);
if (D)
else
// And attach the attributes
applySubprogramAttributesToDefinition(SP, *D);
}
}

void DwarfCompileUnit::finishLocalScopeDefinitions() {
for (const auto &I : getLSDieInfoMap()) {
auto LSInfo = I.second;
// Attach all local dcl DIEs to abstract local scope if available,
// otherwise attach it to concrete local scope.
DIE *LBDie =
LSInfo.AbstractLSDie ? LSInfo.AbstractLSDie : LSInfo.ConcreteLSDie;
assert(LBDie || LSInfo.LocalDclDies.empty());
for (auto &D : LSInfo.LocalDclDies)
LBDie->addChild(std::move(D));

if (isa<DISubprogram>(I.first))
// For function scope there is nothing else to do.
// "abstract_origin" dwarf attribute was added somewhere else.
continue;

if (LSInfo.AbstractLSDie) {
// Add "abstract_origin" dwarf attribute to concrete local scope pointing
// to the corresponding abstract local scope.
if (LSInfo.ConcreteLSDie)
addDIEEntry(*LSInfo.ConcreteLSDie, dwarf::DW_AT_abstract_origin,
*LSInfo.AbstractLSDie);
// Add "abstract_origin" dwarf attribute to inline local scope pointing
// to the corresponding abstract local scope.
for (auto &L : LSInfo.InlineLSDies)
addDIEEntry(*L, dwarf::DW_AT_abstract_origin, *LSInfo.AbstractLSDie);
}
}
}

void DwarfCompileUnit::collectDeadVariables(const DISubprogram *SP) {
assert(SP && "CU's subprogram list contains a non-subprogram");
assert(SP->isDefinition() &&
@@ -705,7 +757,7 @@ void DwarfCompileUnit::collectDeadVariables(const DISubprogram *SP) {

DIE *SPDIE = DU->getAbstractSPDies().lookup(SP);
if (!SPDIE)
SPDIE = getDIE(SP);
return;
assert(SPDIE);
for (const DILocalVariable *DV : Variables) {
DbgVariable NewVar(DV, /* IA */ nullptr, DD);
@@ -830,6 +882,30 @@ void DwarfCompileUnit::applySubprogramAttributesToDefinition(
addGlobalName(SP->getName(), SPDie, Context);
}

void DwarfCompileUnit::addLocalScopeDieToLexicalScope(LexicalScope *LS,
DIE *D) {
auto &LSInfo = getLSDieInfoMap()[LS->getScopeNode()];
if (LS->isAbstractScope()) {
assert(!LSInfo.AbstractLSDie && "Adding abstract LS DIE twice.");
LSInfo.AbstractLSDie = D;
return;
}
if (LS->getInlinedAt()) {
assert(!LSInfo.InlineLSDies.count(D) && "Adding inline LS DIE twice.");
LSInfo.InlineLSDies.insert(D);
return;
}
assert(!LSInfo.ConcreteLSDie && "Adding cocncrete LS DIE twice.");
LSInfo.ConcreteLSDie = D;
return;
}

void DwarfCompileUnit::addLocalDclDieToLexicalScope(LexicalScope *LS, DIE *D) {
auto &LSInfo = getLSDieInfoMap()[LS->getScopeNode()];
LSInfo.LocalDclDies.insert(D);
return;
}

bool DwarfCompileUnit::isDwoUnit() const {
return DD->useSplitDwarf() && Skeleton;
}
36 changes: 29 additions & 7 deletions llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H

#include "DwarfUnit.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/Support/Dwarf.h"
@@ -48,11 +49,10 @@ class DwarfCompileUnit : public DwarfUnit {
/// The start of the unit macro info within macro section.
MCSymbol *MacroLabelBegin;

typedef llvm::SmallVector<const MDNode *, 8> ImportedEntityList;
typedef llvm::DenseMap<const MDNode *, ImportedEntityList>
ImportedEntityMap;
typedef llvm::SmallVector<const MDNode *, 8> LocalDeclNodeList;
typedef llvm::DenseMap<const MDNode *, LocalDeclNodeList> LocalScopesMap;

ImportedEntityMap ImportedEntities;
LocalScopesMap LocalDeclNodes;

/// GlobalNames - A map of globally visible named entities for this unit.
StringMap<const DIE *> GlobalNames;
@@ -71,6 +71,15 @@ class DwarfCompileUnit : public DwarfUnit {
// ranges/locs.
const MCSymbol *BaseAddress;

struct LocalScopeDieInfo {
DIE *ConcreteLSDie = nullptr;
DIE *AbstractLSDie = nullptr;
SetVector<DIE *> InlineLSDies;
SetVector<DIE *> LocalDclDies;
};
// Collection of local scope DIE info.
DenseMap<const MDNode *, LocalScopeDieInfo> LocalScopeDieInfoMap;

/// \brief Construct a DIE for the given DbgVariable without initializing the
/// DbgVariable's DIE reference.
DIE *constructVariableDIEImpl(const DbgVariable &DV, bool Abstract);
@@ -117,8 +126,8 @@ class DwarfCompileUnit : public DwarfUnit {

unsigned getOrCreateSourceID(StringRef FileName, StringRef DirName) override;

void addImportedEntity(const DIImportedEntity* IE) {
ImportedEntities[IE->getScope()].push_back(IE);
void addLocalDeclNode(const DINode *DI, DILocalScope *Scope) {
LocalDeclNodes[Scope].push_back(DI);
}

/// addRange - Add an address range to the list of ranges for this unit.
@@ -166,7 +175,7 @@ class DwarfCompileUnit : public DwarfUnit {
/// A helper function to create children of a Scope DIE.
DIE *createScopeChildrenDIE(LexicalScope *Scope,
SmallVectorImpl<DIE *> &Children,
unsigned *ChildScopeCount = nullptr);
bool *HasNonScopeChildren = nullptr);

/// \brief Construct a DIE for this subprogram scope.
void constructSubprogramScopeDIE(LexicalScope *Scope);
@@ -175,11 +184,15 @@ class DwarfCompileUnit : public DwarfUnit {

void constructAbstractSubprogramScopeDIE(LexicalScope *Scope);

/// \brief Get or create import_module DIE.
DIE *getOrCreateImportedEntityDIE(const DIImportedEntity *Module);
/// \brief Construct import_module DIE.
DIE *constructImportedEntityDIE(const DIImportedEntity *Module);

void finishSubprogramDefinition(const DISubprogram *SP);

void finishLocalScopeDefinitions();

void collectDeadVariables(const DISubprogram *SP);

/// Set the skeleton unit associated with this unit.
@@ -253,6 +266,15 @@ class DwarfCompileUnit : public DwarfUnit {

void setBaseAddress(const MCSymbol *Base) { BaseAddress = Base; }
const MCSymbol *getBaseAddress() const { return BaseAddress; }

DenseMap<const MDNode *, LocalScopeDieInfo> &getLSDieInfoMap() {
return LocalScopeDieInfoMap;
}

/// Add local scope DIE entry to lexical scope info.
void addLocalScopeDieToLexicalScope(LexicalScope *LS, DIE *D);
/// Add local declaration DIE entry to lexical scope info.
void addLocalDclDieToLexicalScope(LexicalScope *LS, DIE *D);
};

} // end llvm namespace
32 changes: 27 additions & 5 deletions llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
@@ -455,6 +455,16 @@ void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU,
D->addChild(TheCU.constructImportedEntityDIE(N));
}

bool DwarfDebug::collectLocalScopedNode(DIScope *S, const DINode *N,
DwarfCompileUnit &CU) {
if (auto LS = dyn_cast_or_null<DILocalScope>(S)) {
getLocalScopes(LS->getSubprogram()).insert(LS);
CU.addLocalDeclNode(N, LS);
return true;
}
return false;
}

// Emit all Dwarf sections that should come prior to the content. Create
// global DIEs and emit initial debug info sections. This is invoked by
// the target AsmPrinter.
@@ -474,10 +484,9 @@ void DwarfDebug::beginModule() {
for (MDNode *N : CU_Nodes->operands()) {
auto *CUNode = cast<DICompileUnit>(N);
DwarfCompileUnit &CU = constructDwarfCompileUnit(CUNode);
for (auto *IE : CUNode->getImportedEntities())
CU.addImportedEntity(IE);
for (auto *GV : CUNode->getGlobalVariables())
CU.getOrCreateGlobalVariableDIE(GV);
if (!collectLocalScopedNode(GV->getScope(), GV, CU))
CU.getOrCreateGlobalVariableDIE(GV);
for (auto *SP : CUNode->getSubprograms())
SPMap.insert(std::make_pair(SP, &CU));
for (auto *Ty : CUNode->getEnumTypes()) {
@@ -489,14 +498,17 @@ void DwarfDebug::beginModule() {
// The retained types array by design contains pointers to
// MDNodes rather than DIRefs. Unique them here.
DIType *RT = cast<DIType>(resolve(Ty->getRef()));
if (!RT->isExternalTypeRef())
if (RT->isExternalTypeRef())
// There is no point in force-emitting a forward declaration.
continue;
if (!collectLocalScopedNode(resolve(Ty->getScope()), RT, CU))
CU.getOrCreateTypeDIE(RT);
}
// Emit imported_modules last so that the relevant context is already
// available.
for (auto *IE : CUNode->getImportedEntities())
constructAndAddImportedEntityDIE(CU, IE);
if (!collectLocalScopedNode(IE->getScope(), IE, CU))
constructAndAddImportedEntityDIE(CU, IE);
}

// Tell MMI that we have debug info.
@@ -529,6 +541,11 @@ void DwarfDebug::finishSubprogramDefinitions() {
});
}

void DwarfDebug::finishLocalScopeDefinitions() {
for (const auto &I : CUMap)
I.second->finishLocalScopeDefinitions();
}

// Collect info for variables that were optimized out.
void DwarfDebug::collectDeadVariables() {
const Module *M = MMI->getModule();
@@ -554,6 +571,8 @@ void DwarfDebug::finalizeModuleInfo() {

finishSubprogramDefinitions();

finishLocalScopeDefinitions();

finishVariableDefinitions();

// Collect info for variables that were optimized out.
@@ -1149,6 +1168,9 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes
&& "ensureAbstractVariableIsCreated inserted abstract scopes");
}
// Assure abstract local scope created for each one contains local DIEs.
for (const DILocalScope *LS : getLocalScopes(SP))
LScopes.getOrCreateAbstractScope(LS);
constructAbstractSubprogramScopeDIE(AScope);
}

Loading

0 comments on commit fc8f296

Please sign in to comment.