Skip to content

Commit c5da065

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 ad488d7 commit c5da065

File tree

4 files changed

+131
-43
lines changed

4 files changed

+131
-43
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 = DIEs(GV).getVariableDIE(GV))
182182
return Die;
183183

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

795795
DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, bool Abstract) {
796796
auto *VariableDie = DIE::get(DIEValueAllocator, DV.getTag());
797-
insertDIE(DV.getVariable(), VariableDie);
797+
DIEs(DV.getVariable()).LVs().insertDIE(DV, VariableDie, Abstract);
798798
DV.setDIE(*VariableDie);
799799
// Abstract variables don't get common attributes later, so apply them now.
800800
if (Abstract) {
@@ -1009,7 +1009,7 @@ DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV,
10091009
DIE *DwarfCompileUnit::constructLabelDIE(DbgLabel &DL,
10101010
const LexicalScope &Scope) {
10111011
auto LabelDie = DIE::get(DIEValueAllocator, DL.getTag());
1012-
insertDIE(DL.getLabel(), LabelDie);
1012+
DIEs(DL.getLabel()).Labels().insertDIE(DL, LabelDie, Scope.isAbstractScope());
10131013
DL.setDIE(*LabelDie);
10141014

10151015
if (Scope.isAbstractScope())

llvm/lib/CodeGen/AsmPrinter/DwarfFile.h

Lines changed: 100 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "llvm/ADT/SmallVector.h"
1515
#include "llvm/ADT/StringRef.h"
1616
#include "llvm/CodeGen/DIE.h"
17+
#include "llvm/IR/DebugInfoMetadata.h"
1718
#include "llvm/Support/Allocator.h"
1819
#include <map>
1920
#include <memory>
@@ -25,9 +26,6 @@ class AsmPrinter;
2526
class DbgEntity;
2627
class DbgVariable;
2728
class DbgLabel;
28-
class DINode;
29-
class DILocalScope;
30-
class DwarfCompileUnit;
3129
class DwarfUnit;
3230
class LexicalScope;
3331
class MCSection;
@@ -51,6 +49,102 @@ struct RangeSpanList {
5149
SmallVector<RangeSpan, 2> Ranges;
5250
};
5351

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

94188
// Collection of abstract subprogram DIEs.
189+
// TODO: move it to InfoHolder?
95190
DenseMap<const DILocalScope *, DIE *> AbstractLocalScopeDIEs;
96191
DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities;
97192

98-
/// Maps MDNodes for type system with the corresponding DIEs. These DIEs can
99-
/// be shared across CUs, that is why we keep the map here instead
100-
/// of in DwarfCompileUnit.
101-
DenseMap<const MDNode *, DIE *> DITypeNodeToDieMap;
193+
DwarfInfoHolder InfoHolder;
102194

103195
public:
104196
DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA);
@@ -174,13 +266,7 @@ class DwarfFile {
174266
return AbstractEntities;
175267
}
176268

177-
void insertDIE(const MDNode *TypeMD, DIE *Die) {
178-
DITypeNodeToDieMap.insert(std::make_pair(TypeMD, Die));
179-
}
180-
181-
DIE *getDIE(const MDNode *TypeMD) {
182-
return DITypeNodeToDieMap.lookup(TypeMD);
183-
}
269+
DwarfInfoHolder &DIEs() { return InfoHolder; }
184270
};
185271

186272
} // end namespace llvm

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -193,23 +193,13 @@ 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-
}
196+
DIE *DwarfUnit::getDIE(const DINode *D) const { return DIEs(D).getDIE(D); }
201197

202198
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));
199+
DIEs(Desc).insertDIE(Desc, D);
208200
}
209201

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

214204
void DwarfUnit::addFlag(DIE &Die, dwarf::Attribute Attribute) {
215205
if (DD->getDwarfVersion() >= 4)
@@ -798,7 +788,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIStringType *STy) {
798788
addString(Buffer, dwarf::DW_AT_name, Name);
799789

800790
if (DIVariable *Var = STy->getStringLength()) {
801-
if (auto *VarDIE = getDIE(Var))
791+
if (auto *VarDIE = DIEs(Var).getVariableDIE(Var))
802792
addDIEEntry(Buffer, dwarf::DW_AT_string_length, *VarDIE);
803793
} else if (DIExpression *Expr = STy->getStringLengthExp()) {
804794
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1117,8 +1107,8 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
11171107
constructTypeDIE(VariantPart, Composite);
11181108
}
11191109
} else if (Tag == dwarf::DW_TAG_namelist) {
1120-
auto *Var = dyn_cast<DINode>(Element);
1121-
auto *VarDIE = getDIE(Var);
1110+
auto *Var = dyn_cast<DIVariable>(Element);
1111+
auto *VarDIE = DIEs(Var).getVariableDIE(Var);
11221112
if (VarDIE) {
11231113
DIE &ItemDie = createAndAddDIE(dwarf::DW_TAG_namelist_item, Buffer);
11241114
addDIEEntry(ItemDie, dwarf::DW_AT_namelist_item, *VarDIE);
@@ -1180,7 +1170,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
11801170
Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type ||
11811171
Tag == dwarf::DW_TAG_union_type) {
11821172
if (auto *Var = dyn_cast_or_null<DIVariable>(CTy->getRawSizeInBits())) {
1183-
if (auto *VarDIE = getDIE(Var))
1173+
if (auto *VarDIE = DIEs(Var).getVariableDIE(Var))
11841174
addDIEEntry(Buffer, dwarf::DW_AT_bit_size, *VarDIE);
11851175
} else if (auto *Exp =
11861176
dyn_cast_or_null<DIExpression>(CTy->getRawSizeInBits())) {
@@ -1582,7 +1572,7 @@ void DwarfUnit::constructSubrangeDIE(DIE &DW_Subrange, const DISubrangeType *SR,
15821572
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
15831573
DISubrangeType::BoundType Bound) -> void {
15841574
if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) {
1585-
if (auto *VarDIE = getDIE(BV))
1575+
if (auto *VarDIE = DIEs(BV).getVariableDIE(BV))
15861576
addDIEEntry(DW_Subrange, Attr, *VarDIE);
15871577
} else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) {
15881578
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1624,7 +1614,7 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR) {
16241614
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
16251615
DISubrange::BoundType Bound) -> void {
16261616
if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) {
1627-
if (auto *VarDIE = getDIE(BV))
1617+
if (auto *VarDIE = DIEs(BV).getVariableDIE(BV))
16281618
addDIEEntry(DW_Subrange, Attr, *VarDIE);
16291619
} else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) {
16301620
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1666,7 +1656,7 @@ void DwarfUnit::constructGenericSubrangeDIE(DIE &Buffer,
16661656
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
16671657
DIGenericSubrange::BoundType Bound) -> void {
16681658
if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) {
1669-
if (auto *VarDIE = getDIE(BV))
1659+
if (auto *VarDIE = DIEs(BV).getVariableDIE(BV))
16701660
addDIEEntry(DwGenericSubrange, Attr, *VarDIE);
16711661
} else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) {
16721662
if (BE->isConstant() &&
@@ -1746,7 +1736,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
17461736
}
17471737

17481738
if (DIVariable *Var = CTy->getDataLocation()) {
1749-
if (auto *VarDIE = getDIE(Var))
1739+
if (auto *VarDIE = DIEs(Var).getVariableDIE(Var))
17501740
addDIEEntry(Buffer, dwarf::DW_AT_data_location, *VarDIE);
17511741
} else if (DIExpression *Expr = CTy->getDataLocationExp()) {
17521742
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1757,7 +1747,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
17571747
}
17581748

17591749
if (DIVariable *Var = CTy->getAssociated()) {
1760-
if (auto *VarDIE = getDIE(Var))
1750+
if (auto *VarDIE = DIEs(Var).getVariableDIE(Var))
17611751
addDIEEntry(Buffer, dwarf::DW_AT_associated, *VarDIE);
17621752
} else if (DIExpression *Expr = CTy->getAssociatedExp()) {
17631753
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1768,7 +1758,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
17681758
}
17691759

17701760
if (DIVariable *Var = CTy->getAllocated()) {
1771-
if (auto *VarDIE = getDIE(Var))
1761+
if (auto *VarDIE = DIEs(Var).getVariableDIE(Var))
17721762
addDIEEntry(Buffer, dwarf::DW_AT_allocated, *VarDIE);
17731763
} else if (DIExpression *Expr = CTy->getAllocatedExp()) {
17741764
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1891,7 +1881,7 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
18911881

18921882
// Handle the size.
18931883
if (auto *Var = dyn_cast_or_null<DIVariable>(DT->getRawSizeInBits())) {
1894-
if (auto *VarDIE = getDIE(Var))
1884+
if (auto *VarDIE = DIEs(Var).getVariableDIE(Var))
18951885
addDIEEntry(MemberDie, dwarf::DW_AT_bit_size, *VarDIE);
18961886
} else if (auto *Exp =
18971887
dyn_cast_or_null<DIExpression>(DT->getRawSizeInBits())) {
@@ -1917,7 +1907,7 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
19171907
// See https://dwarfstd.org/issues/250501.1.html
19181908
if (auto *Var = dyn_cast_or_null<DIVariable>(DT->getRawOffsetInBits())) {
19191909
if (!Asm->TM.Options.DebugStrictDwarf || DD->getDwarfVersion() >= 6) {
1920-
if (auto *VarDIE = getDIE(Var))
1910+
if (auto *VarDIE = DIEs(Var).getVariableDIE(Var))
19211911
addDIEEntry(MemberDie, dwarf::DW_AT_data_bit_offset, *VarDIE);
19221912
}
19231913
} else if (auto *Expr =

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h

Lines changed: 13 additions & 1 deletion
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;
@@ -152,6 +152,18 @@ class DwarfUnit : public DIEUnit {
152152

153153
void insertDIE(DIE *D);
154154

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

0 commit comments

Comments
 (0)