Skip to content

Commit 886e131

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 da422da commit 886e131

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())) {
@@ -1578,7 +1568,7 @@ void DwarfUnit::constructSubrangeDIE(DIE &DW_Subrange, const DISubrangeType *SR,
15781568
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
15791569
DISubrangeType::BoundType Bound) -> void {
15801570
if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) {
1581-
if (auto *VarDIE = getDIE(BV))
1571+
if (auto *VarDIE = DIEs(BV).getVariableDIE(BV))
15821572
addDIEEntry(DW_Subrange, Attr, *VarDIE);
15831573
} else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) {
15841574
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1620,7 +1610,7 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR) {
16201610
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
16211611
DISubrange::BoundType Bound) -> void {
16221612
if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) {
1623-
if (auto *VarDIE = getDIE(BV))
1613+
if (auto *VarDIE = DIEs(BV).getVariableDIE(BV))
16241614
addDIEEntry(DW_Subrange, Attr, *VarDIE);
16251615
} else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) {
16261616
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1662,7 +1652,7 @@ void DwarfUnit::constructGenericSubrangeDIE(DIE &Buffer,
16621652
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
16631653
DIGenericSubrange::BoundType Bound) -> void {
16641654
if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) {
1665-
if (auto *VarDIE = getDIE(BV))
1655+
if (auto *VarDIE = DIEs(BV).getVariableDIE(BV))
16661656
addDIEEntry(DwGenericSubrange, Attr, *VarDIE);
16671657
} else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) {
16681658
if (BE->isConstant() &&
@@ -1742,7 +1732,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
17421732
}
17431733

17441734
if (DIVariable *Var = CTy->getDataLocation()) {
1745-
if (auto *VarDIE = getDIE(Var))
1735+
if (auto *VarDIE = DIEs(Var).getVariableDIE(Var))
17461736
addDIEEntry(Buffer, dwarf::DW_AT_data_location, *VarDIE);
17471737
} else if (DIExpression *Expr = CTy->getDataLocationExp()) {
17481738
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1753,7 +1743,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
17531743
}
17541744

17551745
if (DIVariable *Var = CTy->getAssociated()) {
1756-
if (auto *VarDIE = getDIE(Var))
1746+
if (auto *VarDIE = DIEs(Var).getVariableDIE(Var))
17571747
addDIEEntry(Buffer, dwarf::DW_AT_associated, *VarDIE);
17581748
} else if (DIExpression *Expr = CTy->getAssociatedExp()) {
17591749
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1764,7 +1754,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
17641754
}
17651755

17661756
if (DIVariable *Var = CTy->getAllocated()) {
1767-
if (auto *VarDIE = getDIE(Var))
1757+
if (auto *VarDIE = DIEs(Var).getVariableDIE(Var))
17681758
addDIEEntry(Buffer, dwarf::DW_AT_allocated, *VarDIE);
17691759
} else if (DIExpression *Expr = CTy->getAllocatedExp()) {
17701760
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1887,7 +1877,7 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
18871877

18881878
// Handle the size.
18891879
if (auto *Var = dyn_cast_or_null<DIVariable>(DT->getRawSizeInBits())) {
1890-
if (auto *VarDIE = getDIE(Var))
1880+
if (auto *VarDIE = DIEs(Var).getVariableDIE(Var))
18911881
addDIEEntry(MemberDie, dwarf::DW_AT_bit_size, *VarDIE);
18921882
} else if (auto *Exp =
18931883
dyn_cast_or_null<DIExpression>(DT->getRawSizeInBits())) {
@@ -1913,7 +1903,7 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
19131903
// See https://dwarfstd.org/issues/250501.1.html
19141904
if (auto *Var = dyn_cast_or_null<DIVariable>(DT->getRawOffsetInBits())) {
19151905
if (!Asm->TM.Options.DebugStrictDwarf || DD->getDwarfVersion() >= 6) {
1916-
if (auto *VarDIE = getDIE(Var))
1906+
if (auto *VarDIE = DIEs(Var).getVariableDIE(Var))
19171907
addDIEEntry(MemberDie, dwarf::DW_AT_data_bit_offset, *VarDIE);
19181908
}
19191909
} 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)