Skip to content

Commit e0c44d6

Browse files
committed
[DwarfDebug] Move abstract entities tracking from DwarfCompileUnit to DwarfUnit
DwarfCompileUnit::constructVariableDIE() and constructLabelDIE() are meant for constructing both abstract and concrete DIEs of a DbgEntity. They use DwarfUnit::insertDIE() to store a freshly-created DIE. However, insertDIE()/DwarfUnit::DITypeNodeToDieMap stores only single DIE per DINode. If insertDIE() is called several times for the same instance of DINode, only first DIE is saved in DwarfUnit::DITypeNodeToDieMap, as follows from DenseMap::insert() specification. It means, depending on what is called first, DwarfCompileUnit::constructVariableDIE(LV, /* Abstract */ true) or DwarfCompileUnit::constructVariableDIE(LV, /* Abstract */ false), DwarfUnit::DITypeNodeToDieMap stores either abstract or concrete DIE of a node. This behavior suggests an obscure API of DwarfCompileUnit, as it silently discards one of the DIEs and makes it unclear what DwarfUnit::DITypeNodeToDieMap is made for. Also, DwarfFile and DwarfUnit have a tiny duplicate code piece. To address that, DwarfInfoHolder class is introduced, which stores DIEs for DILocalVariables and DILabels separately from DIEs for other DINodes (as DILocalVariables and DILabels may have concrete and abstract DIEs), and allows explicit access to abstract/concrete DIEs of a debug info entity. DwarfInfoHolder may later be used for tracking DIEs of abstract/concrete lexical scopes. Currently, concrete lexical block/subprogram DIEs are distinguished by their DISubprogram/DILocalScope/DILocalScope+inlinedAt in DwarfCompileUnit. As a result, the same DISubprogram can't be attached to two llvm::Functions (https://lists.llvm.org/pipermail/llvm-dev/2020-September/145342.html). Matching DISubprogram/DILocalScope DIEs with their LexicalScopes and letting DwarfUnit members to access abstract scopes may enable linking DISubprogram to several llvm::Functions, and allow the transition from distinct to uniqued DISubprograms proposed here llvm#142166 (comment).
1 parent a05e004 commit e0c44d6

File tree

4 files changed

+134
-45
lines changed

4 files changed

+134
-45
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ unsigned DwarfCompileUnit::getOrCreateSourceID(const DIFile *File) {
178178
DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
179179
const DIGlobalVariable *GV, ArrayRef<GlobalExpr> GlobalExprs) {
180180
// Check for pre-existence.
181-
if (DIE *Die = getDIE(GV))
181+
if (DIE *Die = getDIEs(GV).getVariableDIE(GV))
182182
return Die;
183183

184184
assert(GV);
@@ -795,7 +795,7 @@ DIE *DwarfCompileUnit::constructLexicalScopeDIE(LexicalScope *Scope) {
795795

796796
DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, bool Abstract) {
797797
auto *VariableDie = DIE::get(DIEValueAllocator, DV.getTag());
798-
insertDIE(DV.getVariable(), VariableDie);
798+
getDIEs(DV.getVariable()).getLVs().insertDIE(DV, VariableDie, Abstract);
799799
DV.setDIE(*VariableDie);
800800
// Abstract variables don't get common attributes later, so apply them now.
801801
if (Abstract) {
@@ -1010,7 +1010,7 @@ DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV,
10101010
DIE *DwarfCompileUnit::constructLabelDIE(DbgLabel &DL,
10111011
const LexicalScope &Scope) {
10121012
auto LabelDie = DIE::get(DIEValueAllocator, DL.getTag());
1013-
insertDIE(DL.getLabel(), LabelDie);
1013+
getDIEs(DL.getLabel()).getLabels().insertDIE(DL, LabelDie, Scope.isAbstractScope());
10141014
DL.setDIE(*LabelDie);
10151015

10161016
if (Scope.isAbstractScope())

llvm/lib/CodeGen/AsmPrinter/DwarfFile.h

Lines changed: 101 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "llvm/ADT/SmallVector.h"
1616
#include "llvm/ADT/StringRef.h"
1717
#include "llvm/CodeGen/DIE.h"
18+
#include "llvm/IR/DebugInfoMetadata.h"
1819
#include "llvm/Support/Allocator.h"
1920
#include <map>
2021
#include <memory>
@@ -26,9 +27,6 @@ class AsmPrinter;
2627
class DbgEntity;
2728
class DbgVariable;
2829
class DbgLabel;
29-
class DINode;
30-
class DILocalScope;
31-
class DISubprogram;
3230
class DwarfCompileUnit;
3331
class DwarfUnit;
3432
class LexicalScope;
@@ -53,6 +51,103 @@ struct RangeSpanList {
5351
SmallVector<RangeSpan, 2> Ranges;
5452
};
5553

54+
/// Tracks abstract and concrete DIEs for debug info entities of a certain type.
55+
template <typename DINodeT, typename DbgEntityT> class DINodeInfoHolder {
56+
DenseMap<const DINodeT *, DIE *> AbstractMap;
57+
DenseMap<const DINodeT *, SmallDenseMap<const DbgEntityT *, DIE *, 2>>
58+
ConcreteMap;
59+
60+
static const DINodeT *getNode(const DbgEntityT &N) {
61+
return cast<DINodeT>(N.getEntity());
62+
}
63+
64+
public:
65+
void insertAbstractDIE(const DINodeT *N, DIE *D) {
66+
auto [_, Inserted] = AbstractMap.try_emplace(N, D);
67+
assert(Inserted && "Duplicate abstract DIE for debug info node");
68+
}
69+
70+
void insertConcreteDIE(const DbgEntityT &N, DIE *D) {
71+
auto [_, Inserted] = ConcreteMap[getNode(N)].try_emplace(&N, D);
72+
assert(Inserted && "Duplicate concrete DIE for debug info node");
73+
}
74+
75+
void insertDIE(const DbgEntityT &N, DIE *D, bool Abstract) {
76+
if (Abstract)
77+
insertAbstractDIE(getNode(N), D);
78+
else
79+
insertConcreteDIE(N, D);
80+
}
81+
82+
DIE *getAbstractDIE(const DINodeT *N) const { return AbstractMap.lookup(N); }
83+
84+
DIE *getConcreteDIE(const DbgEntityT &N) const {
85+
if (auto I = ConcreteMap.find(getNode(N)); I != ConcreteMap.end())
86+
return I->second.lookup(&N);
87+
return nullptr;
88+
}
89+
90+
/// Returns abstract DIE for the entity.
91+
/// If no abstract DIE was created, returns any concrete DIE for the entity.
92+
DIE *getDIE(const DINodeT *N) const {
93+
if (DIE *D = getAbstractDIE(N))
94+
return D;
95+
96+
if (auto I = ConcreteMap.find(N); I != ConcreteMap.end())
97+
return I->second.empty() ? nullptr : I->second.begin()->second;
98+
99+
return nullptr;
100+
}
101+
};
102+
103+
/// Tracks DIEs for debug info entites.
104+
/// These DIEs can be shared across CUs, that is why we keep the map here
105+
/// instead of in DwarfCompileUnit.
106+
class DwarfInfoHolder {
107+
// DIEs of local DbgVariables.
108+
DINodeInfoHolder<DILocalVariable, DbgVariable> LVHolder;
109+
DINodeInfoHolder<DILabel, DbgLabel> LabelHolder;
110+
111+
/// Other DINodes with the corresponding DIEs.
112+
DenseMap<const DINode *, DIE *> MDNodeToDieMap;
113+
114+
public:
115+
void insertDIE(const DINode *N, DIE *Die) {
116+
assert((!isa<DILabel>(N) && !isa<DILocalVariable>(N)) &&
117+
"Use getLabels().insertDIE() for labels or getLVs().insertDIE() for "
118+
"local variables");
119+
auto [_, Inserted] = MDNodeToDieMap.try_emplace(N, Die);
120+
assert((Inserted || isa<DISubprogram>(N) || isa<DIType>(N)) &&
121+
"DIE for this DINode has already been added");
122+
}
123+
124+
void insertDIE(DIE *D) { MDNodeToDieMap.try_emplace(nullptr, D); }
125+
126+
DIE *getDIE(const DINode *N) const {
127+
DIE *D = MDNodeToDieMap.lookup(N);
128+
assert((!D || (!isa<DILabel>(N) && !isa<DILocalVariable>(N))) &&
129+
"Use getLabels().getDIE() for labels or getLVs().getDIE() for "
130+
"local variables");
131+
return D;
132+
}
133+
134+
auto &getLVs() { return LVHolder; }
135+
auto &getLVs() const { return LVHolder; }
136+
auto &getLabels() { return LabelHolder; }
137+
auto &getLabels() const { return LabelHolder; }
138+
139+
/// For a global variable, returns DIE of the variable.
140+
///
141+
/// For a local variable, returns abstract DIE of the variable.
142+
/// If no abstract DIE was created, returns any concrete DIE of the variable.
143+
DIE *getVariableDIE(const DIVariable *V) const {
144+
if (auto *LV = dyn_cast<DILocalVariable>(V))
145+
if (DIE *D = getLVs().getDIE(LV))
146+
return D;
147+
return getDIE(V);
148+
}
149+
};
150+
56151
class DwarfFile {
57152
// Target of Dwarf emission, used for sizing of abbreviations.
58153
AsmPrinter *Asm;
@@ -94,16 +189,14 @@ class DwarfFile {
94189
DenseMap<LexicalScope *, LabelList> ScopeLabels;
95190

96191
// Collection of abstract subprogram DIEs.
192+
// TODO: move it to InfoHolder?
97193
DenseMap<const DILocalScope *, DIE *> AbstractLocalScopeDIEs;
98194
DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities;
99195
/// Keeps track of abstract subprograms to populate them only once.
100196
// FIXME: merge creation and population of abstract scopes.
101197
SmallPtrSet<const DISubprogram *, 8> FinalizedAbstractSubprograms;
102198

103-
/// Maps MDNodes for type system with the corresponding DIEs. These DIEs can
104-
/// be shared across CUs, that is why we keep the map here instead
105-
/// of in DwarfCompileUnit.
106-
DenseMap<const MDNode *, DIE *> DITypeNodeToDieMap;
199+
DwarfInfoHolder InfoHolder;
107200

108201
public:
109202
DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA);
@@ -183,13 +276,7 @@ class DwarfFile {
183276
return FinalizedAbstractSubprograms;
184277
}
185278

186-
void insertDIE(const MDNode *TypeMD, DIE *Die) {
187-
DITypeNodeToDieMap.insert(std::make_pair(TypeMD, Die));
188-
}
189-
190-
DIE *getDIE(const MDNode *TypeMD) {
191-
return DITypeNodeToDieMap.lookup(TypeMD);
192-
}
279+
DwarfInfoHolder &getDIEs() { return InfoHolder; }
193280
};
194281

195282
} // end namespace llvm

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -193,23 +193,11 @@ bool DwarfUnit::isShareableAcrossCUs(const DINode *D) const {
193193
!DD->generateTypeUnits();
194194
}
195195

196-
DIE *DwarfUnit::getDIE(const DINode *D) const {
197-
if (isShareableAcrossCUs(D))
198-
return DU->getDIE(D);
199-
return MDNodeToDieMap.lookup(D);
200-
}
201-
202196
void DwarfUnit::insertDIE(const DINode *Desc, DIE *D) {
203-
if (isShareableAcrossCUs(Desc)) {
204-
DU->insertDIE(Desc, D);
205-
return;
206-
}
207-
MDNodeToDieMap.insert(std::make_pair(Desc, D));
197+
getDIEs(Desc).insertDIE(Desc, D);
208198
}
209199

210-
void DwarfUnit::insertDIE(DIE *D) {
211-
MDNodeToDieMap.insert(std::make_pair(nullptr, D));
212-
}
200+
void DwarfUnit::insertDIE(DIE *D) { InfoHolder.insertDIE(D); }
213201

214202
void DwarfUnit::addFlag(DIE &Die, dwarf::Attribute Attribute) {
215203
if (DD->getDwarfVersion() >= 4)
@@ -798,7 +786,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIStringType *STy) {
798786
addString(Buffer, dwarf::DW_AT_name, Name);
799787

800788
if (DIVariable *Var = STy->getStringLength()) {
801-
if (auto *VarDIE = getDIE(Var))
789+
if (auto *VarDIE = getDIEs(Var).getVariableDIE(Var))
802790
addDIEEntry(Buffer, dwarf::DW_AT_string_length, *VarDIE);
803791
} else if (DIExpression *Expr = STy->getStringLengthExp()) {
804792
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1117,8 +1105,8 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
11171105
constructTypeDIE(VariantPart, Composite);
11181106
}
11191107
} else if (Tag == dwarf::DW_TAG_namelist) {
1120-
auto *Var = dyn_cast<DINode>(Element);
1121-
auto *VarDIE = getDIE(Var);
1108+
auto *Var = dyn_cast<DIVariable>(Element);
1109+
auto *VarDIE = getDIEs(Var).getVariableDIE(Var);
11221110
if (VarDIE) {
11231111
DIE &ItemDie = createAndAddDIE(dwarf::DW_TAG_namelist_item, Buffer);
11241112
addDIEEntry(ItemDie, dwarf::DW_AT_namelist_item, *VarDIE);
@@ -1180,7 +1168,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
11801168
Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type ||
11811169
Tag == dwarf::DW_TAG_union_type) {
11821170
if (auto *Var = dyn_cast_or_null<DIVariable>(CTy->getRawSizeInBits())) {
1183-
if (auto *VarDIE = getDIE(Var))
1171+
if (auto *VarDIE = getDIEs(Var).getVariableDIE(Var))
11841172
addDIEEntry(Buffer, dwarf::DW_AT_bit_size, *VarDIE);
11851173
} else if (auto *Exp =
11861174
dyn_cast_or_null<DIExpression>(CTy->getRawSizeInBits())) {
@@ -1581,7 +1569,7 @@ void DwarfUnit::constructSubrangeDIE(DIE &DW_Subrange, const DISubrangeType *SR,
15811569
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
15821570
DISubrangeType::BoundType Bound) -> void {
15831571
if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) {
1584-
if (auto *VarDIE = getDIE(BV))
1572+
if (auto *VarDIE = getDIEs(BV).getVariableDIE(BV))
15851573
addDIEEntry(DW_Subrange, Attr, *VarDIE);
15861574
} else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) {
15871575
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1623,7 +1611,7 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR) {
16231611
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
16241612
DISubrange::BoundType Bound) -> void {
16251613
if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) {
1626-
if (auto *VarDIE = getDIE(BV))
1614+
if (auto *VarDIE = getDIEs(BV).getVariableDIE(BV))
16271615
addDIEEntry(DW_Subrange, Attr, *VarDIE);
16281616
} else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) {
16291617
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1665,7 +1653,7 @@ void DwarfUnit::constructGenericSubrangeDIE(DIE &Buffer,
16651653
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
16661654
DIGenericSubrange::BoundType Bound) -> void {
16671655
if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) {
1668-
if (auto *VarDIE = getDIE(BV))
1656+
if (auto *VarDIE = getDIEs(BV).getVariableDIE(BV))
16691657
addDIEEntry(DwGenericSubrange, Attr, *VarDIE);
16701658
} else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) {
16711659
if (BE->isConstant() &&
@@ -1745,7 +1733,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
17451733
}
17461734

17471735
if (DIVariable *Var = CTy->getDataLocation()) {
1748-
if (auto *VarDIE = getDIE(Var))
1736+
if (auto *VarDIE = getDIEs(Var).getVariableDIE(Var))
17491737
addDIEEntry(Buffer, dwarf::DW_AT_data_location, *VarDIE);
17501738
} else if (DIExpression *Expr = CTy->getDataLocationExp()) {
17511739
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1756,7 +1744,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
17561744
}
17571745

17581746
if (DIVariable *Var = CTy->getAssociated()) {
1759-
if (auto *VarDIE = getDIE(Var))
1747+
if (auto *VarDIE = getDIEs(Var).getVariableDIE(Var))
17601748
addDIEEntry(Buffer, dwarf::DW_AT_associated, *VarDIE);
17611749
} else if (DIExpression *Expr = CTy->getAssociatedExp()) {
17621750
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1767,7 +1755,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
17671755
}
17681756

17691757
if (DIVariable *Var = CTy->getAllocated()) {
1770-
if (auto *VarDIE = getDIE(Var))
1758+
if (auto *VarDIE = getDIEs(Var).getVariableDIE(Var))
17711759
addDIEEntry(Buffer, dwarf::DW_AT_allocated, *VarDIE);
17721760
} else if (DIExpression *Expr = CTy->getAllocatedExp()) {
17731761
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1890,7 +1878,7 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
18901878

18911879
// Handle the size.
18921880
if (auto *Var = dyn_cast_or_null<DIVariable>(DT->getRawSizeInBits())) {
1893-
if (auto *VarDIE = getDIE(Var))
1881+
if (auto *VarDIE = getDIEs(Var).getVariableDIE(Var))
18941882
addDIEEntry(MemberDie, dwarf::DW_AT_bit_size, *VarDIE);
18951883
} else if (auto *Exp =
18961884
dyn_cast_or_null<DIExpression>(DT->getRawSizeInBits())) {
@@ -1916,7 +1904,7 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
19161904
// See https://dwarfstd.org/issues/250501.1.html
19171905
if (auto *Var = dyn_cast_or_null<DIVariable>(DT->getRawOffsetInBits())) {
19181906
if (!Asm->TM.Options.DebugStrictDwarf || DD->getDwarfVersion() >= 6) {
1919-
if (auto *VarDIE = getDIE(Var))
1907+
if (auto *VarDIE = getDIEs(Var).getVariableDIE(Var))
19201908
addDIEEntry(MemberDie, dwarf::DW_AT_data_bit_offset, *VarDIE);
19211909
}
19221910
} else if (auto *Expr =

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class DwarfUnit : public DIEUnit {
6060

6161
/// Tracks the mapping of unit level debug information variables to debug
6262
/// information entries.
63-
DenseMap<const MDNode *, DIE *> MDNodeToDieMap;
63+
DwarfInfoHolder InfoHolder;
6464

6565
/// A list of all the DIEBlocks in use.
6666
std::vector<DIEBlock *> DIEBlocks;
@@ -138,7 +138,9 @@ class DwarfUnit : public DIEUnit {
138138
/// We delegate the request to DwarfDebug when the MDNode can be part of the
139139
/// type system, since DIEs for the type system can be shared across CUs and
140140
/// the mappings are kept in DwarfDebug.
141-
DIE *getDIE(const DINode *D) const;
141+
DIE *getDIE(const DINode *D) const {
142+
return getDIEs(D).getDIE(D);
143+
}
142144

143145
/// Returns a fresh newly allocated DIELoc.
144146
DIELoc *getDIELoc() { return new (DIEValueAllocator) DIELoc; }
@@ -152,6 +154,18 @@ class DwarfUnit : public DIEUnit {
152154

153155
void insertDIE(DIE *D);
154156

157+
const DwarfInfoHolder &getDIEs(const DINode *N) const {
158+
if (isShareableAcrossCUs(N))
159+
return DU->getDIEs();
160+
161+
return InfoHolder;
162+
}
163+
164+
DwarfInfoHolder &getDIEs(const DINode *N) {
165+
return const_cast<DwarfInfoHolder &>(
166+
const_cast<const DwarfUnit *>(this)->getDIEs(N));
167+
}
168+
155169
/// Add a flag that is true to the DIE.
156170
void addFlag(DIE &Die, dwarf::Attribute Attribute);
157171

0 commit comments

Comments
 (0)