Skip to content

Commit 9e9d591

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 06cffb7 commit 9e9d591

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)
@@ -803,7 +791,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIStringType *STy) {
803791
addString(Buffer, dwarf::DW_AT_name, Name);
804792

805793
if (DIVariable *Var = STy->getStringLength()) {
806-
if (auto *VarDIE = getDIE(Var))
794+
if (auto *VarDIE = getDIEs(Var).getVariableDIE(Var))
807795
addDIEEntry(Buffer, dwarf::DW_AT_string_length, *VarDIE);
808796
} else if (DIExpression *Expr = STy->getStringLengthExp()) {
809797
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1122,8 +1110,8 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
11221110
constructTypeDIE(VariantPart, Composite);
11231111
}
11241112
} else if (Tag == dwarf::DW_TAG_namelist) {
1125-
auto *Var = dyn_cast<DINode>(Element);
1126-
auto *VarDIE = getDIE(Var);
1113+
auto *Var = dyn_cast<DIVariable>(Element);
1114+
auto *VarDIE = getDIEs(Var).getVariableDIE(Var);
11271115
if (VarDIE) {
11281116
DIE &ItemDie = createAndAddDIE(dwarf::DW_TAG_namelist_item, Buffer);
11291117
addDIEEntry(ItemDie, dwarf::DW_AT_namelist_item, *VarDIE);
@@ -1185,7 +1173,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
11851173
Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type ||
11861174
Tag == dwarf::DW_TAG_union_type) {
11871175
if (auto *Var = dyn_cast_or_null<DIVariable>(CTy->getRawSizeInBits())) {
1188-
if (auto *VarDIE = getDIE(Var))
1176+
if (auto *VarDIE = getDIEs(Var).getVariableDIE(Var))
11891177
addDIEEntry(Buffer, dwarf::DW_AT_bit_size, *VarDIE);
11901178
} else if (auto *Exp =
11911179
dyn_cast_or_null<DIExpression>(CTy->getRawSizeInBits())) {
@@ -1586,7 +1574,7 @@ void DwarfUnit::constructSubrangeDIE(DIE &DW_Subrange, const DISubrangeType *SR,
15861574
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
15871575
DISubrangeType::BoundType Bound) -> void {
15881576
if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) {
1589-
if (auto *VarDIE = getDIE(BV))
1577+
if (auto *VarDIE = getDIEs(BV).getVariableDIE(BV))
15901578
addDIEEntry(DW_Subrange, Attr, *VarDIE);
15911579
} else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) {
15921580
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1628,7 +1616,7 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR) {
16281616
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
16291617
DISubrange::BoundType Bound) -> void {
16301618
if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) {
1631-
if (auto *VarDIE = getDIE(BV))
1619+
if (auto *VarDIE = getDIEs(BV).getVariableDIE(BV))
16321620
addDIEEntry(DW_Subrange, Attr, *VarDIE);
16331621
} else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) {
16341622
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1670,7 +1658,7 @@ void DwarfUnit::constructGenericSubrangeDIE(DIE &Buffer,
16701658
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
16711659
DIGenericSubrange::BoundType Bound) -> void {
16721660
if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) {
1673-
if (auto *VarDIE = getDIE(BV))
1661+
if (auto *VarDIE = getDIEs(BV).getVariableDIE(BV))
16741662
addDIEEntry(DwGenericSubrange, Attr, *VarDIE);
16751663
} else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) {
16761664
if (BE->isConstant() &&
@@ -1749,7 +1737,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
17491737
}
17501738

17511739
if (DIVariable *Var = CTy->getDataLocation()) {
1752-
if (auto *VarDIE = getDIE(Var))
1740+
if (auto *VarDIE = getDIEs(Var).getVariableDIE(Var))
17531741
addDIEEntry(Buffer, dwarf::DW_AT_data_location, *VarDIE);
17541742
} else if (DIExpression *Expr = CTy->getDataLocationExp()) {
17551743
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1760,7 +1748,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
17601748
}
17611749

17621750
if (DIVariable *Var = CTy->getAssociated()) {
1763-
if (auto *VarDIE = getDIE(Var))
1751+
if (auto *VarDIE = getDIEs(Var).getVariableDIE(Var))
17641752
addDIEEntry(Buffer, dwarf::DW_AT_associated, *VarDIE);
17651753
} else if (DIExpression *Expr = CTy->getAssociatedExp()) {
17661754
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1771,7 +1759,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
17711759
}
17721760

17731761
if (DIVariable *Var = CTy->getAllocated()) {
1774-
if (auto *VarDIE = getDIE(Var))
1762+
if (auto *VarDIE = getDIEs(Var).getVariableDIE(Var))
17751763
addDIEEntry(Buffer, dwarf::DW_AT_allocated, *VarDIE);
17761764
} else if (DIExpression *Expr = CTy->getAllocatedExp()) {
17771765
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1896,7 +1884,7 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
18961884
if (DT->getRawSizeInBits() == nullptr) {
18971885
// No size, just ignore.
18981886
} else if (auto *Var = dyn_cast<DIVariable>(DT->getRawSizeInBits())) {
1899-
if (auto *VarDIE = getDIE(Var))
1887+
if (auto *VarDIE = getDIEs(Var).getVariableDIE(Var))
19001888
addDIEEntry(MemberDie, dwarf::DW_AT_bit_size, *VarDIE);
19011889
} else if (auto *Exp = dyn_cast<DIExpression>(DT->getRawSizeInBits())) {
19021890
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
@@ -1921,7 +1909,7 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
19211909
// See https://dwarfstd.org/issues/250501.1.html
19221910
if (auto *Var = dyn_cast_or_null<DIVariable>(DT->getRawOffsetInBits())) {
19231911
if (!Asm->TM.Options.DebugStrictDwarf || DD->getDwarfVersion() >= 6) {
1924-
if (auto *VarDIE = getDIE(Var))
1912+
if (auto *VarDIE = getDIEs(Var).getVariableDIE(Var))
19251913
addDIEEntry(MemberDie, dwarf::DW_AT_data_bit_offset, *VarDIE);
19261914
}
19271915
} else if (auto *Expr =

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h

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

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

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

144146
/// Returns a fresh newly allocated DIELoc.
145147
DIELoc *getDIELoc() { return new (DIEValueAllocator) DIELoc; }
@@ -153,6 +155,18 @@ class DwarfUnit : public DIEUnit {
153155

154156
void insertDIE(DIE *D);
155157

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

0 commit comments

Comments
 (0)