1616#define BOLT_CORE_DIE_BUILDER_H
1717
1818#include " llvm/CodeGen/DIE.h"
19- #include " llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
2019#include " llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
2120#include " llvm/DebugInfo/DWARF/DWARFDie.h"
2221#include " llvm/DebugInfo/DWARF/DWARFExpression.h"
2322#include " llvm/DebugInfo/DWARF/DWARFUnit.h"
24- #include " llvm/IR/Type.h"
2523#include " llvm/Support/Allocator.h"
2624#include " llvm/Support/ErrorHandling.h"
2725
28- #include < cstdint>
29- #include < forward_list>
3026#include < list>
3127#include < memory>
32- #include < mutex>
3328#include < optional>
34- #include < set>
35- #include < shared_mutex>
36- #include < sys/types.h>
3729#include < unordered_map>
38- #include < utility>
3930#include < vector>
4031
4132namespace llvm {
4233
4334namespace bolt {
35+ class DIEStreamer ;
4436
4537class DIEBuilder {
38+ friend DIEStreamer;
39+
40+ public:
41+ // / Wrapper around DIE so we can access DIEs easily.
4642 struct DIEInfo {
4743 DIE *Die;
4844 uint32_t DieId;
4945 uint32_t UnitId;
50- uint32_t CanonicalDIEOffset;
5146 };
5247
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.
5960 std::unordered_map<uint64_t , uint32_t > DIEIDMap;
60- std::unordered_map<uint32_t , DIEInfo *> DIEId2InfoMap;
6161 };
6262
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) {}
6782 DIEInfo *Dst;
6883 DWARFAbbreviationDeclaration::AttributeSpec AttrSpec;
6984 };
7085
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.
7489 std::unordered_map<DWARFUnit *, DIE *> TypeDIEMap;
7590 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 ;
7893 FoldingSet<DIEAbbrev> AbbreviationsSet;
7994 std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
8095 std::vector<DWARFUnit *> DWARF4TUVector;
81- std::vector<DWARFUnit *> DWARF4CUVector ;
96+ std::vector<LocWithReference> LocWithReferencesToProcess ;
8297 BumpPtrAllocator DIEAlloc;
8398
8499 // / Resolve the reference in DIE, if target is not loaded into IR,
85100 // / pre-allocate it. \p RefCU will be updated to the Unit specific by \p
86101 // / 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
95115 // / attribute.
96- uint32_t
116+ void
97117 cloneAttribute (DIE &Die, const DWARFDie &InputDIE, DWARFUnit &U,
98118 const DWARFFormValue &Val,
99119 const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
100- unsigned AttrSize, bool IsLittleEndian,
101- std::vector<DWARFUnit *> &DUOffsetList);
120+ const std::vector<DWARFUnit *> &DUOffsetList);
102121
103122 // / 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);
107127
108128 // / 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);
114133
115134 // / 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);
121139
140+ enum class CloneExpressionStage { INIT, PATCH };
122141 // / Clone an attribute in expression format. \p OutputBuffer will hold the
123142 // / 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);
126148
127149 // / 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);
132154
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);
138159
139160 // / 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);
144165
145166 // / 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);
150171
151- // / Update the Cross-CU reference offset .
152- void computeReference ();
172+ // / Update references once the layout is finalized .
173+ void updateReferences ();
153174
154175 // / 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);
156177
157- void registerUnit (DWARFUnit &Unit) {
158- UnitIDMap[&Unit] = DUList.size ();
159- DUList.push_back (&Unit);
160- }
178+ void registerUnit (DWARFUnit &DU);
161179
162180 // / \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);
168182
169- UnitInfo &getUnitInfo (uint32_t UnitId) { return CloneUnitCtxMap[UnitId]; }
183+ DWARFUnitInfo &getUnitInfo (uint32_t UnitId) {
184+ return CloneUnitCtxMap[UnitId];
185+ }
170186
171187 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 () ;
174190
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"
176193 << " unexpected corner cases happened.\n " ;
177- return CloneUnitCtxMap[UnitId].DieInfoList .front ();
194+ return * CloneUnitCtxMap[UnitId].DieInfoVector .front (). get ();
178195 }
179196
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 );
192204 }
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 ());
200208 }
201209
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 );
209217
210- return getDIEInfo (*UnitId, *hasDIEId );
218+ return getDIEInfo (*UnitId, *HasDieId );
211219 }
212220
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);
221223
222224 // / Construct IR for \p DU. \p DUOffsetList specific the Unit in current
223225 // / Section.
224226 void constructFromUnit (DWARFUnit &DU, std::vector<DWARFUnit *> &DUOffsetList);
225227
226228 // / Construct a DIE for \p DDie in \p U. \p DUOffsetList specific the Unit in
227229 // / 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,
230231 std::vector<DWARFUnit *> &DUOffsetList);
231232
232233public:
233234 DIEBuilder (DWARFContext *DwarfContext, bool IsDWO = false );
234235
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+ }
236246 std::vector<std::unique_ptr<DIEAbbrev>> &getAbbrevs () {
237247 return Abbreviations;
238248 }
@@ -246,17 +256,16 @@ class DIEBuilder {
246256 }
247257
248258 std::vector<DWARFUnit *> getDWARF4TUVector () { return DWARF4TUVector; }
249- bool isEmpty () { return !IsBuilt ; }
259+ bool isEmpty () { return CloneUnitCtxMap. empty () ; }
250260
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 ;
255264 }
256265
257266 // / Generate and populate all Abbrevs.
258267 void generateAbbrevs ();
259- void generateUnitAbbrevs (DIE *die );
268+ void generateUnitAbbrevs (DIE *Die );
260269 void assignAbbrev (DIEAbbrev &Abbrev);
261270
262271 // / Finish current DIE construction.
0 commit comments