Skip to content

Commit ee69197

Browse files
committed
[DwarfDebug] Support emitting function-local declaration for a lexical block
This is another attempt to make function-local declarations (like static variables, structs/classes and other) be correctly emitted within a lexical (bracketed) block. Fixes https://bugs.llvm.org/show_bug.cgi?id=19238. Differential Revision: https://reviews.llvm.org/D113741
1 parent 5d49511 commit ee69197

14 files changed

+1050
-107
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

Lines changed: 96 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -551,8 +551,18 @@ void DwarfCompileUnit::constructScopeDIE(LexicalScope *Scope,
551551
// Emit lexical blocks.
552552
DIE *ScopeDIE = constructLexicalScopeDIE(Scope);
553553
assert(ScopeDIE && "Scope DIE should not be null.");
554-
555554
ParentScopeDIE.addChild(ScopeDIE);
555+
556+
// Track abstract and concrete lexical block scopes.
557+
if (Scope->isAbstractScope()) {
558+
assert(!getAbstractScopeDIEs().count(DS) &&
559+
"Abstract DIE for this scope exists!");
560+
getAbstractScopeDIEs()[DS] = ScopeDIE;
561+
} else if (!Scope->getInlinedAt()) {
562+
assert(!LocalScopeDIEs.count(DS) && "Concrete DIE for this scope exists!");
563+
LocalScopeDIEs[DS] = ScopeDIE;
564+
}
565+
556566
createAndAddScopeChildren(Scope, *ScopeDIE);
557567
}
558568

@@ -646,7 +656,7 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope) {
646656
auto *InlinedSP = getDISubprogram(DS);
647657
// Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram
648658
// was inlined from another compile unit.
649-
DIE *OriginDIE = getAbstractSPDies()[InlinedSP];
659+
DIE *OriginDIE = getAbstractScopeDIEs()[InlinedSP];
650660
assert(OriginDIE && "Unable to find original DIE for an inlined subprogram.");
651661

652662
auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_inlined_subroutine);
@@ -1001,6 +1011,12 @@ DIE &DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub,
10011011
if (Scope) {
10021012
assert(!Scope->getInlinedAt());
10031013
assert(!Scope->isAbstractScope());
1014+
1015+
// Remember the subrogram before creating child entities.
1016+
assert(!LocalScopeDIEs.count(Sub) &&
1017+
"Concrete DIE for the subprogram exists!");
1018+
LocalScopeDIEs[Sub] = &ScopeDIE;
1019+
10041020
// Collect lexical scope children first.
10051021
// ObjectPointer might be a local (non-argument) local variable if it's a
10061022
// block's synthetic this pointer.
@@ -1036,27 +1052,18 @@ DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope,
10361052
for (DbgVariable *DV : Locals)
10371053
ScopeDIE.addChild(constructVariableDIE(*DV, *Scope, ObjectPointer));
10381054

1039-
// Emit imported entities (skipped in gmlt-like data).
1040-
if (!includeMinimalInlineScopes()) {
1041-
for (const auto *IE : ImportedEntities[Scope->getScopeNode()])
1042-
ScopeDIE.addChild(constructImportedEntityDIE(cast<DIImportedEntity>(IE)));
1043-
}
1044-
10451055
// Emit labels.
10461056
for (DbgLabel *DL : DU->getScopeLabels().lookup(Scope))
10471057
ScopeDIE.addChild(constructLabelDIE(*DL, *Scope));
10481058

10491059
// Emit inner lexical scopes.
1050-
auto needToEmitLexicalScope = [this](LexicalScope *LS) {
1060+
auto needToEmitLexicalScope = [this](LexicalScope *LS) -> bool {
10511061
if (isa<DISubprogram>(LS->getScopeNode()))
10521062
return true;
10531063
auto Vars = DU->getScopeVariables().lookup(LS);
10541064
if (!Vars.Args.empty() || !Vars.Locals.empty())
10551065
return true;
1056-
if (!includeMinimalInlineScopes() &&
1057-
!ImportedEntities[LS->getScopeNode()].empty())
1058-
return true;
1059-
return false;
1066+
return LocalScopesWithLocalDecls.count(LS->getScopeNode());
10601067
};
10611068
for (LexicalScope *LS : Scope->getChildren()) {
10621069
// If the lexical block doesn't have non-scope children, skip
@@ -1072,11 +1079,10 @@ DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope,
10721079

10731080
void DwarfCompileUnit::constructAbstractSubprogramScopeDIE(
10741081
LexicalScope *Scope) {
1075-
DIE *&AbsDef = getAbstractSPDies()[Scope->getScopeNode()];
1076-
if (AbsDef)
1077-
return;
10781082

10791083
auto *SP = cast<DISubprogram>(Scope->getScopeNode());
1084+
if (auto *SPDie = getAbstractScopeDIEs().lookup(SP))
1085+
return;
10801086

10811087
DIE *ContextDIE;
10821088
DwarfCompileUnit *ContextCU = this;
@@ -1100,14 +1106,19 @@ void DwarfCompileUnit::constructAbstractSubprogramScopeDIE(
11001106

11011107
// Passing null as the associated node because the abstract definition
11021108
// shouldn't be found by lookup.
1103-
AbsDef = &ContextCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, nullptr);
1104-
ContextCU->applySubprogramAttributesToDefinition(SP, *AbsDef);
1105-
ContextCU->addSInt(*AbsDef, dwarf::DW_AT_inline,
1109+
DIE &AbsDef = ContextCU->createAndAddDIE(dwarf::DW_TAG_subprogram,
1110+
*ContextDIE, nullptr);
1111+
1112+
// Store the DIE before creating children.
1113+
getAbstractScopeDIEs()[SP] = &AbsDef;
1114+
1115+
ContextCU->applySubprogramAttributesToDefinition(SP, AbsDef);
1116+
ContextCU->addSInt(AbsDef, dwarf::DW_AT_inline,
11061117
DD->getDwarfVersion() <= 4 ? Optional<dwarf::Form>()
11071118
: dwarf::DW_FORM_implicit_const,
11081119
dwarf::DW_INL_inlined);
1109-
if (DIE *ObjectPointer = ContextCU->createAndAddScopeChildren(Scope, *AbsDef))
1110-
ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
1120+
if (DIE *ObjectPointer = ContextCU->createAndAddScopeChildren(Scope, AbsDef))
1121+
ContextCU->addDIEEntry(AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
11111122
}
11121123

11131124
bool DwarfCompileUnit::useGNUAnalogForDwarf5Feature() const {
@@ -1241,47 +1252,61 @@ void DwarfCompileUnit::constructCallSiteParmEntryDIEs(
12411252
}
12421253
}
12431254

1244-
DIE *DwarfCompileUnit::constructImportedEntityDIE(
1245-
const DIImportedEntity *Module) {
1246-
DIE *IMDie = DIE::get(DIEValueAllocator, (dwarf::Tag)Module->getTag());
1247-
insertDIE(Module, IMDie);
1255+
DIE *DwarfCompileUnit::createImportedEntityDIE(const DIImportedEntity *IE) {
1256+
DIE *IMDie = DIE::get(DIEValueAllocator, (dwarf::Tag)IE->getTag());
1257+
insertDIE(IE, IMDie);
1258+
12481259
DIE *EntityDie;
1249-
auto *Entity = Module->getEntity();
1260+
auto *Entity = IE->getEntity();
12501261
if (auto *NS = dyn_cast<DINamespace>(Entity))
12511262
EntityDie = getOrCreateNameSpace(NS);
12521263
else if (auto *M = dyn_cast<DIModule>(Entity))
12531264
EntityDie = getOrCreateModule(M);
1254-
else if (auto *SP = dyn_cast<DISubprogram>(Entity))
1255-
EntityDie = getOrCreateSubprogramDIE(SP);
1256-
else if (auto *T = dyn_cast<DIType>(Entity))
1265+
else if (auto *SP = dyn_cast<DISubprogram>(Entity)) {
1266+
// If we have abstract subprogram created, refer it.
1267+
if (auto *AbsSPDie = getAbstractScopeDIEs().lookup(SP))
1268+
EntityDie = AbsSPDie;
1269+
else
1270+
EntityDie = getOrCreateSubprogramDIE(SP);
1271+
} else if (auto *T = dyn_cast<DIType>(Entity))
12571272
EntityDie = getOrCreateTypeDIE(T);
12581273
else if (auto *GV = dyn_cast<DIGlobalVariable>(Entity))
12591274
EntityDie = getOrCreateGlobalVariableDIE(GV, {});
12601275
else
12611276
EntityDie = getDIE(Entity);
12621277
assert(EntityDie);
1263-
addSourceLine(*IMDie, Module->getLine(), Module->getFile());
1278+
1279+
addSourceLine(*IMDie, IE->getLine(), IE->getFile());
12641280
addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie);
1265-
StringRef Name = Module->getName();
1281+
StringRef Name = IE->getName();
12661282
if (!Name.empty())
12671283
addString(*IMDie, dwarf::DW_AT_name, Name);
12681284

12691285
// This is for imported module with renamed entities (such as variables and
12701286
// subprograms).
1271-
DINodeArray Elements = Module->getElements();
1287+
DINodeArray Elements = IE->getElements();
12721288
for (const auto *Element : Elements) {
12731289
if (!Element)
12741290
continue;
1275-
IMDie->addChild(
1276-
constructImportedEntityDIE(cast<DIImportedEntity>(Element)));
1291+
IMDie->addChild(createImportedEntityDIE(cast<DIImportedEntity>(Element)));
12771292
}
1278-
12791293
return IMDie;
12801294
}
12811295

1296+
void DwarfCompileUnit::createAndAddImportedEntityDIE(
1297+
const DIImportedEntity *IE) {
1298+
DIE *ContextDIE = getOrCreateContextDIE(IE->getScope());
1299+
assert(ContextDIE &&
1300+
"Could not get or create scope for the imported entity!");
1301+
if (!ContextDIE)
1302+
return;
1303+
1304+
ContextDIE->addChild(createImportedEntityDIE(IE));
1305+
}
1306+
12821307
void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) {
12831308
DIE *D = getDIE(SP);
1284-
if (DIE *AbsSPDIE = getAbstractSPDies().lookup(SP)) {
1309+
if (DIE *AbsSPDIE = getAbstractScopeDIEs().lookup(SP)) {
12851310
if (D)
12861311
// If this subprogram has an abstract definition, reference that
12871312
addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE);
@@ -1571,3 +1596,38 @@ void DwarfCompileUnit::createBaseTypeDIEs() {
15711596
Btr.Die = &Die;
15721597
}
15731598
}
1599+
1600+
static DIE *
1601+
findLocalScopeDIE(const DILocalScope *LS,
1602+
DenseMap<const DILocalScope *, DIE *> &ScopeDIEs) {
1603+
DIE *ScopeDIE = ScopeDIEs.lookup(LS);
1604+
if (isa<DISubprogram>(LS) && !ScopeDIE)
1605+
return nullptr;
1606+
if (!ScopeDIE)
1607+
return findLocalScopeDIE(cast<DILocalScope>(LS->getScope()), ScopeDIEs);
1608+
return ScopeDIE;
1609+
}
1610+
1611+
DIE *DwarfCompileUnit::findLocalScopeDIE(const DIScope *S) {
1612+
auto *LScope = dyn_cast_or_null<DILocalScope>(S);
1613+
if (!LScope)
1614+
return nullptr;
1615+
1616+
// Check if we have an abstract tree.
1617+
if (getAbstractScopeDIEs().count(LScope->getSubprogram()))
1618+
return ::findLocalScopeDIE(LScope, getAbstractScopeDIEs());
1619+
1620+
return ::findLocalScopeDIE(LScope, LocalScopeDIEs);
1621+
}
1622+
1623+
DIE *DwarfCompileUnit::getOrCreateContextDIE(const DIScope *Context) {
1624+
if (auto *LScope = dyn_cast_or_null<DILocalScope>(Context)) {
1625+
if (DIE *ScopeDIE = findLocalScopeDIE(LScope))
1626+
return ScopeDIE;
1627+
1628+
// If nothing was found, fall back to DISubprogram and let
1629+
// DwarfUnit::getOrCreateContextDIE() create a new DIE for it.
1630+
Context = LScope->getSubprogram();
1631+
}
1632+
return DwarfUnit::getOrCreateContextDIE(Context);
1633+
}

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,6 @@ class DwarfCompileUnit final : public DwarfUnit {
6262
/// The start of the unit macro info within macro section.
6363
MCSymbol *MacroLabelBegin;
6464

65-
using ImportedEntityList = SmallVector<const MDNode *, 8>;
66-
using ImportedEntityMap = DenseMap<const MDNode *, ImportedEntityList>;
67-
68-
ImportedEntityMap ImportedEntities;
69-
7065
/// GlobalNames - A map of globally visible named entities for this unit.
7166
StringMap<const DIE *> GlobalNames;
7267

@@ -80,9 +75,14 @@ class DwarfCompileUnit final : public DwarfUnit {
8075
// ranges/locs.
8176
const MCSymbol *BaseAddress = nullptr;
8277

83-
DenseMap<const MDNode *, DIE *> AbstractSPDies;
78+
DenseMap<const DILocalScope *, DIE *> LocalScopeDIEs;
79+
DenseMap<const DILocalScope *, DIE *> AbstractLocalScopeDIEs;
8480
DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities;
8581

82+
/// LocalScopesWithLocalDecls - A list of non-empty local scopes
83+
/// (with declaraions of static locals, function-local types, or imports).
84+
SmallPtrSet<const DILocalScope *, 8> LocalScopesWithLocalDecls;
85+
8686
/// DWO ID for correlating skeleton and split units.
8787
uint64_t DWOId = 0;
8888

@@ -92,10 +92,10 @@ class DwarfCompileUnit final : public DwarfUnit {
9292

9393
bool isDwoUnit() const override;
9494

95-
DenseMap<const MDNode *, DIE *> &getAbstractSPDies() {
95+
DenseMap<const DILocalScope *, DIE *> &getAbstractScopeDIEs() {
9696
if (isDwoUnit() && !DD->shareAcrossDWOCUs())
97-
return AbstractSPDies;
98-
return DU->getAbstractSPDies();
97+
return AbstractLocalScopeDIEs;
98+
return DU->getAbstractScopeDIEs();
9999
}
100100

101101
DenseMap<const DINode *, std::unique_ptr<DbgEntity>> &getAbstractEntities() {
@@ -169,17 +169,6 @@ class DwarfCompileUnit final : public DwarfUnit {
169169

170170
unsigned getOrCreateSourceID(const DIFile *File) override;
171171

172-
void addImportedEntity(const DIImportedEntity* IE) {
173-
DIScope *Scope = IE->getScope();
174-
assert(Scope && "Invalid Scope encoding!");
175-
if (!isa<DILocalScope>(Scope))
176-
// No need to add imported enities that are not local declaration.
177-
return;
178-
179-
auto *LocalScope = cast<DILocalScope>(Scope)->getNonLexicalBlockFileScope();
180-
ImportedEntities[LocalScope].push_back(IE);
181-
}
182-
183172
/// addRange - Add an address range to the list of ranges for this unit.
184173
void addRange(RangeSpan Range);
185174

@@ -221,6 +210,9 @@ class DwarfCompileUnit final : public DwarfUnit {
221210

222211
void createBaseTypeDIEs();
223212

213+
DIE *findLocalScopeDIE(const DIScope *S);
214+
DIE *getOrCreateContextDIE(const DIScope *Ty) override;
215+
224216
/// Construct a DIE for this subprogram scope.
225217
DIE &constructSubprogramScopeDIE(const DISubprogram *Sub,
226218
LexicalScope *Scope);
@@ -259,8 +251,9 @@ class DwarfCompileUnit final : public DwarfUnit {
259251
void constructCallSiteParmEntryDIEs(DIE &CallSiteDIE,
260252
SmallVector<DbgCallSiteParam, 4> &Params);
261253

262-
/// Construct import_module DIE.
263-
DIE *constructImportedEntityDIE(const DIImportedEntity *Module);
254+
/// Construct DIE for an imported entity.
255+
DIE *createImportedEntityDIE(const DIImportedEntity *IE);
256+
void createAndAddImportedEntityDIE(const DIImportedEntity *IE);
264257

265258
void finishSubprogramDefinition(const DISubprogram *SP);
266259
void finishEntityDefinition(const DbgEntity *Entity);
@@ -357,6 +350,10 @@ class DwarfCompileUnit final : public DwarfUnit {
357350
bool hasDwarfPubSections() const;
358351

359352
void addBaseTypeRef(DIEValueList &Die, int64_t Idx);
353+
354+
void recordLocalScopeWithDecls(const DILocalScope *S) {
355+
LocalScopesWithLocalDecls.insert(S);
356+
}
360357
};
361358

362359
} // end namespace llvm

0 commit comments

Comments
 (0)