16
16
#define BOLT_CORE_DIE_BUILDER_H
17
17
18
18
#include " llvm/CodeGen/DIE.h"
19
- #include " llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
20
19
#include " llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
21
20
#include " llvm/DebugInfo/DWARF/DWARFDie.h"
22
21
#include " llvm/DebugInfo/DWARF/DWARFExpression.h"
23
22
#include " llvm/DebugInfo/DWARF/DWARFUnit.h"
24
- #include " llvm/IR/Type.h"
25
23
#include " llvm/Support/Allocator.h"
26
24
#include " llvm/Support/ErrorHandling.h"
27
25
28
- #include < cstdint>
29
- #include < forward_list>
30
26
#include < list>
31
27
#include < memory>
32
- #include < mutex>
33
28
#include < optional>
34
- #include < set>
35
- #include < shared_mutex>
36
- #include < sys/types.h>
37
29
#include < unordered_map>
38
- #include < utility>
39
30
#include < vector>
40
31
41
32
namespace llvm {
42
33
43
34
namespace bolt {
35
+ class DIEStreamer ;
44
36
45
37
class DIEBuilder {
38
+ friend DIEStreamer;
39
+
40
+ public:
41
+ // / Wrapper around DIE so we can access DIEs easily.
46
42
struct DIEInfo {
47
43
DIE *Die;
48
44
uint32_t DieId;
49
45
uint32_t UnitId;
50
- uint32_t CanonicalDIEOffset;
51
46
};
52
47
53
- struct UnitInfo {
54
- std::list<DIEInfo> DieInfoList;
55
- uint32_t UnitId;
56
- uint32_t UnitOffset;
57
- bool Isconstructed = false ;
58
- uint32_t NewDieId = 0 ;
48
+ // / Contains information for the CU level of DWARF.
49
+ struct DWARFUnitInfo {
50
+ // Contains all the DIEs for the current unit.
51
+ // Accessed by DIE ID.
52
+ std::vector<std::unique_ptr<DIEInfo>> DieInfoVector;
53
+ DIE *UnitDie = nullptr ;
54
+ uint32_t UnitId = 0 ;
55
+ uint32_t UnitOffset = 0 ;
56
+ uint32_t UnitLength = 0 ;
57
+ bool IsConstructed = false ;
58
+ // A map of DIE offsets in original DWARF section to DIE ID.
59
+ // Whih is used to access DieInfoVector.
59
60
std::unordered_map<uint64_t , uint32_t > DIEIDMap;
60
- std::unordered_map<uint32_t , DIEInfo *> DIEId2InfoMap;
61
61
};
62
62
63
- struct ForwardReferenceInfo {
64
- ForwardReferenceInfo (DIEInfo *Die,
65
- DWARFAbbreviationDeclaration::AttributeSpec spec)
66
- : Dst(Die), AttrSpec(spec) {}
63
+ private:
64
+ // / Contains information so that we we can update references in locexpr after
65
+ // / we calculated all the final DIE offsets.
66
+ struct LocWithReference {
67
+ LocWithReference (std::vector<uint8_t > &&BlockData, DWARFUnit &U, DIE &Die,
68
+ dwarf::Form Form, dwarf::Attribute Attr)
69
+ : BlockData(BlockData), U(U), Die(Die), Form(Form), Attr(Attr) {}
70
+ std::vector<uint8_t > BlockData;
71
+ DWARFUnit &U;
72
+ DIE &Die;
73
+ dwarf::Form Form;
74
+ dwarf::Attribute Attr;
75
+ };
76
+ // / Contains information so that we can update cross CU references, after we
77
+ // / calculated all the final DIE offsets.
78
+ struct AddrReferenceInfo {
79
+ AddrReferenceInfo (DIEInfo *Die,
80
+ DWARFAbbreviationDeclaration::AttributeSpec Spec)
81
+ : Dst(Die), AttrSpec(Spec) {}
67
82
DIEInfo *Dst;
68
83
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec;
69
84
};
70
85
71
- bool IsBuilt = false ;
72
- std::unordered_map<DWARFUnit *, std::vector<DIE *>> UnitDIEs ;
73
- std::unordered_map<DWARFUnit *, uint32_t > UnitIDMap;
86
+ // / A map of Units to Unit Index.
87
+ std::unordered_map<uint64_t , uint32_t > UnitIDMap ;
88
+ // / A map of Type Units to Type DIEs.
74
89
std::unordered_map<DWARFUnit *, DIE *> TypeDIEMap;
75
90
std::vector<DWARFUnit *> DUList;
76
- std::vector<UnitInfo > CloneUnitCtxMap;
77
- std::vector<std::pair<DIEInfo *, ForwardReferenceInfo >> ForwardReferences ;
91
+ std::vector<DWARFUnitInfo > CloneUnitCtxMap;
92
+ std::vector<std::pair<DIEInfo *, AddrReferenceInfo >> AddrReferences ;
78
93
FoldingSet<DIEAbbrev> AbbreviationsSet;
79
94
std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
80
95
std::vector<DWARFUnit *> DWARF4TUVector;
81
- std::vector<DWARFUnit *> DWARF4CUVector ;
96
+ std::vector<LocWithReference> LocWithReferencesToProcess ;
82
97
BumpPtrAllocator DIEAlloc;
83
98
84
99
// / Resolve the reference in DIE, if target is not loaded into IR,
85
100
// / pre-allocate it. \p RefCU will be updated to the Unit specific by \p
86
101
// / RefValue.
87
- DWARFDie
88
- resolveDIEReference (const DWARFFormValue &RefValue,
89
- DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
90
- DWARFUnit *&RefCU,
91
- DWARFDebugInfoEntry &DwarfDebugInfoEntry,
92
- const std::vector<DWARFUnit *> &DUOffsetList);
93
-
94
- // / Clone one attribute according the format. \return the size of this
102
+ DWARFDie resolveDIEReference (const DWARFFormValue &RefValue,
103
+ DWARFUnit *&RefCU,
104
+ DWARFDebugInfoEntry &DwarfDebugInfoEntry,
105
+ const std::vector<DWARFUnit *> &DUOffsetList);
106
+
107
+ // / Resolve the reference in DIE, if target is not loaded into IR,
108
+ // / pre-allocate it. \p RefCU will be updated to the Unit specific by \p
109
+ // / RefValue.
110
+ DWARFDie resolveDIEReference (const uint64_t ReffOffset, DWARFUnit *&RefCU,
111
+ DWARFDebugInfoEntry &DwarfDebugInfoEntry,
112
+ const std::vector<DWARFUnit *> &DUOffsetList);
113
+
114
+ // / Clone one attribute according to the format. \return the size of this
95
115
// / attribute.
96
- uint32_t
116
+ void
97
117
cloneAttribute (DIE &Die, const DWARFDie &InputDIE, DWARFUnit &U,
98
118
const DWARFFormValue &Val,
99
119
const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
100
- unsigned AttrSize, bool IsLittleEndian,
101
- std::vector<DWARFUnit *> &DUOffsetList);
120
+ const std::vector<DWARFUnit *> &DUOffsetList);
102
121
103
122
// / Clone an attribute in string format.
104
- uint32_t cloneStringAttribute (
105
- DIE &Die, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
106
- unsigned AttrSize, const DWARFFormValue &Val, const DWARFUnit &U);
123
+ void cloneStringAttribute (
124
+ DIE &Die, const DWARFUnit &U,
125
+ const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
126
+ const DWARFFormValue &Val);
107
127
108
128
// / Clone an attribute in reference format.
109
- uint32_t cloneDieReferenceAttribute (
110
- DIE &Die, const DWARFDie &InputDIE,
111
- DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, unsigned AttrSize,
112
- const DWARFFormValue &Val, DWARFUnit &U,
113
- std::vector<DWARFUnit *> &DUOffsetList);
129
+ void cloneDieReferenceAttribute (
130
+ DIE &Die, const DWARFUnit &U, const DWARFDie &InputDIE,
131
+ const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
132
+ const DWARFFormValue &Val, const std::vector<DWARFUnit *> &DUOffsetList);
114
133
115
134
// / Clone an attribute in block format.
116
- uint32_t
117
- cloneBlockAttribute (DIE &Die, DWARFUnit &U,
118
- DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
119
- const DWARFFormValue &Val, unsigned AttrSize,
120
- bool IsLittleEndian);
135
+ void cloneBlockAttribute (
136
+ DIE &Die, DWARFUnit &U,
137
+ const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
138
+ const DWARFFormValue &Val);
121
139
140
+ enum class CloneExpressionStage { INIT, PATCH };
122
141
// / Clone an attribute in expression format. \p OutputBuffer will hold the
123
142
// / output content.
124
- void cloneExpression (DataExtractor &Data, DWARFExpression &Expression,
125
- DWARFUnit &U, SmallVectorImpl<uint8_t > &OutputBuffer);
143
+ // / Returns true if Expression contains a reference.
144
+ bool cloneExpression (const DataExtractor &Data,
145
+ const DWARFExpression &Expression, DWARFUnit &U,
146
+ SmallVectorImpl<uint8_t > &OutputBuffer,
147
+ const CloneExpressionStage &Stage);
126
148
127
149
// / Clone an attribute in address format.
128
- uint32_t
129
- cloneAddressAttribute ( DIE &Die,
130
- DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
131
- const DWARFFormValue &Val, const DWARFUnit &U );
150
+ void cloneAddressAttribute (
151
+ DIE &Die, const DWARFUnit &U ,
152
+ const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
153
+ const DWARFFormValue &Val);
132
154
133
- // / Clone an attribute in Refsig format.
134
- uint32_t
135
- cloneRefsigAttribute (DIE &Die,
136
- DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
137
- unsigned AttrSize, const DWARFFormValue &Val);
155
+ // / Clone an attribute in refsig format.
156
+ void cloneRefsigAttribute (
157
+ DIE &Die, const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
158
+ const DWARFFormValue &Val);
138
159
139
160
// / Clone an attribute in scalar format.
140
- uint32_t
141
- cloneScalarAttribute ( DIE &Die, const DWARFDie &InputDIE,
142
- DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
143
- const DWARFFormValue &Val, unsigned AttrSize );
161
+ void cloneScalarAttribute (
162
+ DIE &Die, const DWARFDie &InputDIE,
163
+ const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
164
+ const DWARFFormValue &Val);
144
165
145
166
// / Clone an attribute in loclist format.
146
- uint32_t
147
- cloneLoclistAttrubute ( DIE &Die, const DWARFDie &InputDIE,
148
- DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
149
- const DWARFFormValue &Val, unsigned AttrSize );
167
+ void cloneLoclistAttrubute (
168
+ DIE &Die, const DWARFDie &InputDIE,
169
+ const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
170
+ const DWARFFormValue &Val);
150
171
151
- // / Update the Cross-CU reference offset .
152
- void computeReference ();
172
+ // / Update references once the layout is finalized .
173
+ void updateReferences ();
153
174
154
175
// / Update the Offset and Size of DIE.
155
- uint32_t computeDIEOffset (DWARFUnit &CU, DIE &Die, uint32_t &CurOffset);
176
+ uint32_t computeDIEOffset (const DWARFUnit &CU, DIE &Die, uint32_t &CurOffset);
156
177
157
- void registerUnit (DWARFUnit &Unit) {
158
- UnitIDMap[&Unit] = DUList.size ();
159
- DUList.push_back (&Unit);
160
- }
178
+ void registerUnit (DWARFUnit &DU);
161
179
162
180
// / \return the unique ID of \p U if it exists.
163
- std::optional<uint32_t > getUnitId (DWARFUnit &DU) {
164
- if (UnitIDMap.count (&DU))
165
- return UnitIDMap[&DU];
166
- return std::nullopt;
167
- }
181
+ std::optional<uint32_t > getUnitId (const DWARFUnit &DU);
168
182
169
- UnitInfo &getUnitInfo (uint32_t UnitId) { return CloneUnitCtxMap[UnitId]; }
183
+ DWARFUnitInfo &getUnitInfo (uint32_t UnitId) {
184
+ return CloneUnitCtxMap[UnitId];
185
+ }
170
186
171
187
DIEInfo &getDIEInfo (uint32_t UnitId, uint32_t DIEId) {
172
- if (CloneUnitCtxMap[UnitId].DIEId2InfoMap . count (DIEId) )
173
- return *CloneUnitCtxMap[UnitId].DIEId2InfoMap [DIEId];
188
+ if (CloneUnitCtxMap[UnitId].DieInfoVector . size () > DIEId )
189
+ return *CloneUnitCtxMap[UnitId].DieInfoVector [DIEId]. get () ;
174
190
175
- errs () << " BOLT-ERROR: The DIE is not allocated before looking up, some"
191
+ errs () << " BOLT-WARNING: [internal-dwarf-error]: The DIE is not allocated "
192
+ " before looking up, some"
176
193
<< " unexpected corner cases happened.\n " ;
177
- return CloneUnitCtxMap[UnitId].DieInfoList .front ();
194
+ return * CloneUnitCtxMap[UnitId].DieInfoVector .front (). get ();
178
195
}
179
196
180
- UnitInfo &getUnitInfoByDwarfUnit (DWARFUnit &DwarfUnit) {
181
- std::optional<uint32_t > UnitId = getUnitId (DwarfUnit);
182
- return getUnitInfo (*UnitId);
183
- }
184
-
185
- std::optional<uint32_t > getAllocDIEId (DWARFUnit &DU, DWARFDie &DDie) {
186
- UnitInfo &UnitInfo = getUnitInfoByDwarfUnit (DU);
187
- uint64_t Offset = DDie.getOffset ();
188
-
189
- if (!UnitInfo.DIEIDMap .count (Offset))
190
- return std::nullopt;
191
- return UnitInfo.DIEIDMap [Offset];
197
+ std::optional<uint32_t > getAllocDIEId (const DWARFUnit &DU,
198
+ const uint64_t Offset) {
199
+ const DWARFUnitInfo &DWARFUnitInfo = getUnitInfoByDwarfUnit (DU);
200
+ auto Iter = DWARFUnitInfo.DIEIDMap .find (Offset);
201
+ return (Iter == DWARFUnitInfo.DIEIDMap .end ())
202
+ ? std::nullopt
203
+ : std::optional<uint32_t >(Iter->second );
192
204
}
193
-
194
- std::optional<uint32_t > getAllocDIEId (DWARFUnit &DU, uint64_t Offset) {
195
- UnitInfo &UnitInfo = getUnitInfoByDwarfUnit (DU);
196
-
197
- if (!UnitInfo.DIEIDMap .count (Offset))
198
- return std::nullopt;
199
- return UnitInfo.DIEIDMap [Offset];
205
+ std::optional<uint32_t > getAllocDIEId (const DWARFUnit &DU,
206
+ const DWARFDie &DDie) {
207
+ return getAllocDIEId (DU, DDie.getOffset ());
200
208
}
201
209
202
- // To avoid overhead, do not use this unless we do get the UnitInfo first.
203
- // We can use getDIEInfo with UnitId and DieId
204
- DIEInfo &getDIEInfoByDwarfDie (DWARFDie * DwarfDie) {
205
- DWARFUnit * DwarfUnit = DwarfDie-> getDwarfUnit ();
206
- std::optional<uint32_t > UnitId = getUnitId (* DwarfUnit);
207
- std::optional<uint32_t > hasDIEId = getAllocDIEId (* DwarfUnit, * DwarfDie);
208
- assert (hasDIEId. has_value () );
210
+ // To avoid overhead, do not use this unless we do get the DWARFUnitInfo
211
+ // first. We can use getDIEInfo with UnitId and DieId
212
+ DIEInfo &getDIEInfoByDwarfDie (DWARFDie & DwarfDie) {
213
+ DWARFUnit & DwarfUnit = * DwarfDie. getDwarfUnit ();
214
+ std::optional<uint32_t > UnitId = getUnitId (DwarfUnit);
215
+ std::optional<uint32_t > HasDieId = getAllocDIEId (DwarfUnit, DwarfDie);
216
+ assert (HasDieId );
209
217
210
- return getDIEInfo (*UnitId, *hasDIEId );
218
+ return getDIEInfo (*UnitId, *HasDieId );
211
219
}
212
220
213
- std::optional<uint32_t > allocDIE (DWARFUnit &DU, DWARFDie &DDie,
214
- BumpPtrAllocator &Alloc, uint32_t UId,
215
- uint32_t offset = 0 );
216
-
217
- uint32_t AllocDIEId (DWARFUnit &DU) {
218
- UnitInfo &UnitInfo = getUnitInfoByDwarfUnit (DU);
219
- return UnitInfo.NewDieId ++;
220
- }
221
+ uint32_t allocDIE (const DWARFUnit &DU, const DWARFDie &DDie,
222
+ BumpPtrAllocator &Alloc, const uint32_t UId);
221
223
222
224
// / Construct IR for \p DU. \p DUOffsetList specific the Unit in current
223
225
// / Section.
224
226
void constructFromUnit (DWARFUnit &DU, std::vector<DWARFUnit *> &DUOffsetList);
225
227
226
228
// / Construct a DIE for \p DDie in \p U. \p DUOffsetList specific the Unit in
227
229
// / current Section.
228
- DIE *constructDIEFast (DWARFDie &DDie, DWARFUnit &U, bool IsLittleEndian,
229
- uint32_t UnitId,
230
+ DIE *constructDIEFast (DWARFDie &DDie, DWARFUnit &U, uint32_t UnitId,
230
231
std::vector<DWARFUnit *> &DUOffsetList);
231
232
232
233
public:
233
234
DIEBuilder (DWARFContext *DwarfContext, bool IsDWO = false );
234
235
235
- std::vector<DIE *> getDIEsByUnit (DWARFUnit &DU) { return UnitDIEs[&DU]; }
236
+ // / Returns DWARFUnitInfo for DWARFUnit
237
+ DWARFUnitInfo &getUnitInfoByDwarfUnit (const DWARFUnit &DwarfUnit) {
238
+ std::optional<uint32_t > UnitId = getUnitId (DwarfUnit);
239
+ return getUnitInfo (*UnitId);
240
+ }
241
+
242
+ const std::vector<std::unique_ptr<DIEInfo>> &getDIEsByUnit (DWARFUnit &DU) {
243
+ DWARFUnitInfo &U = getUnitInfoByDwarfUnit (DU);
244
+ return U.DieInfoVector ;
245
+ }
236
246
std::vector<std::unique_ptr<DIEAbbrev>> &getAbbrevs () {
237
247
return Abbreviations;
238
248
}
@@ -246,17 +256,16 @@ class DIEBuilder {
246
256
}
247
257
248
258
std::vector<DWARFUnit *> getDWARF4TUVector () { return DWARF4TUVector; }
249
- bool isEmpty () { return !IsBuilt ; }
259
+ bool isEmpty () { return CloneUnitCtxMap. empty () ; }
250
260
251
- DIE *getUnitDIEbyUnit (DWARFUnit &DU) {
252
- assert (UnitDIEs.count (&DU) && UnitDIEs[&DU].size () &&
253
- " DU is not constructed in IR" );
254
- return UnitDIEs[&DU].front ();
261
+ DIE *getUnitDIEbyUnit (const DWARFUnit &DU) {
262
+ const DWARFUnitInfo &U = getUnitInfoByDwarfUnit (DU);
263
+ return U.UnitDie ;
255
264
}
256
265
257
266
// / Generate and populate all Abbrevs.
258
267
void generateAbbrevs ();
259
- void generateUnitAbbrevs (DIE *die );
268
+ void generateUnitAbbrevs (DIE *Die );
260
269
void assignAbbrev (DIEAbbrev &Abbrev);
261
270
262
271
// / Finish current DIE construction.
0 commit comments