1 | //===- bolt/Core/DebugNames.h - Debug names support ---*- C++ |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file contains declaration of classes required for generation of |
10 | // .debug_names section. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef BOLT_CORE_DEBUG_NAMES_H |
15 | #define BOLT_CORE_DEBUG_NAMES_H |
16 | |
17 | #include "bolt/Core/DebugData.h" |
18 | #include "llvm/CodeGen/AccelTable.h" |
19 | |
20 | namespace llvm { |
21 | namespace bolt { |
22 | class BOLTDWARF5AccelTableData : public DWARF5AccelTableData { |
23 | public: |
24 | BOLTDWARF5AccelTableData(const uint64_t DieOffset, |
25 | const std::optional<uint64_t> DefiningParentOffset, |
26 | const unsigned DieTag, const unsigned UnitID, |
27 | const bool IsTU, |
28 | const std::optional<unsigned> SecondUnitID) |
29 | : DWARF5AccelTableData(DieOffset, DefiningParentOffset, DieTag, UnitID, |
30 | IsTU), |
31 | SecondUnitID(SecondUnitID) {} |
32 | |
33 | uint64_t getDieOffset() const { return DWARF5AccelTableData::getDieOffset(); } |
34 | unsigned getDieTag() const { return DWARF5AccelTableData::getDieTag(); } |
35 | unsigned getUnitID() const { return DWARF5AccelTableData::getUnitID(); } |
36 | bool isTU() const { return DWARF5AccelTableData::isTU(); } |
37 | std::optional<unsigned> getSecondUnitID() const { return SecondUnitID; } |
38 | |
39 | void setPatchOffset(uint64_t PatchOffset) { OffsetVal = PatchOffset; } |
40 | uint64_t getPatchOffset() const { return std::get<uint64_t>(v: OffsetVal); } |
41 | |
42 | private: |
43 | std::optional<unsigned> SecondUnitID; |
44 | }; |
45 | |
46 | class DWARF5AcceleratorTable { |
47 | public: |
48 | DWARF5AcceleratorTable(const bool CreateDebugNames, BinaryContext &BC, |
49 | DebugStrWriter &MainBinaryStrWriter); |
50 | ~DWARF5AcceleratorTable() { |
51 | for (DebugNamesAbbrev *Abbrev : AbbreviationsVector) |
52 | Abbrev->~DebugNamesAbbrev(); |
53 | } |
54 | /// Add DWARF5 Accelerator table entry. |
55 | /// Input is DWARFUnit being processed, DIE that belongs to it, potential |
56 | /// DWOID if the Unit comes from a DWO section, and potential parent entry. |
57 | std::optional<BOLTDWARF5AccelTableData *> |
58 | addAccelTableEntry(DWARFUnit &Unit, const DIE &Die, |
59 | const std::optional<uint64_t> &DWOID, |
60 | std::optional<BOLTDWARF5AccelTableData *> &Parent); |
61 | /// Set current unit being processed. |
62 | void setCurrentUnit(DWARFUnit &Unit, const uint64_t UnitStartOffset); |
63 | /// Emit Accelerator table. |
64 | void emitAccelTable(); |
65 | /// Returns true if the table was crated. |
66 | bool isCreated() const { return NeedToCreate; } |
67 | /// Returns buffer containing the accelerator table. |
68 | std::unique_ptr<DebugBufferVector> releaseBuffer() { |
69 | return std::move(FullTableBuffer); |
70 | } |
71 | /// Adds a DIE that is referenced across CUs. |
72 | void addCrossCUDie(const DIE *Die) { |
73 | CrossCUDies.insert(KV: {Die->getOffset(), Die}); |
74 | } |
75 | /// Returns true if the DIE can generate an entry for a cross cu reference. |
76 | /// This only checks TAGs of a DIE because when this is invoked DIE might not |
77 | /// be fully constructed. |
78 | bool canGenerateEntryWithCrossCUReference( |
79 | const DWARFUnit &Unit, const DIE &Die, |
80 | const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec); |
81 | |
82 | private: |
83 | BinaryContext &BC; |
84 | bool NeedToCreate = false; |
85 | BumpPtrAllocator Allocator; |
86 | DebugStrWriter &MainBinaryStrWriter; |
87 | StringRef StrSection; |
88 | uint64_t CurrentUnitOffset = 0; |
89 | const DWARFUnit *CurrentUnit = nullptr; |
90 | std::unordered_map<uint32_t, uint32_t> AbbrevTagToIndexMap; |
91 | |
92 | /// Represents a group of entries with identical name (and hence, hash value). |
93 | struct HashData { |
94 | uint64_t StrOffset; |
95 | uint32_t HashValue; |
96 | uint32_t EntryOffset; |
97 | std::vector<BOLTDWARF5AccelTableData *> Values; |
98 | }; |
99 | using HashList = std::vector<HashData *>; |
100 | using BucketList = std::vector<HashList>; |
101 | /// Contains all the offsets of CUs. |
102 | SmallVector<uint32_t, 1> CUList; |
103 | /// Contains all the offsets of local TUs. |
104 | SmallVector<uint32_t, 1> LocalTUList; |
105 | /// Contains all the type hashes for split dwarf TUs. |
106 | SmallVector<uint64_t, 1> ForeignTUList; |
107 | using StringEntries = |
108 | MapVector<std::string, HashData, llvm::StringMap<unsigned>>; |
109 | StringEntries Entries; |
110 | /// FoldingSet that uniques the abbreviations. |
111 | FoldingSet<DebugNamesAbbrev> AbbreviationsSet; |
112 | /// Vector containing DebugNames abbreviations for iteration in order. |
113 | SmallVector<DebugNamesAbbrev *, 5> AbbreviationsVector; |
114 | /// The bump allocator to use when creating DIEAbbrev objects in the uniqued |
115 | /// storage container. |
116 | BumpPtrAllocator Alloc; |
117 | uint32_t BucketCount = 0; |
118 | uint32_t UniqueHashCount = 0; |
119 | uint32_t AbbrevTableSize = 0; |
120 | uint32_t CUIndexEncodingSize = 4; |
121 | uint32_t TUIndexEncodingSize = 4; |
122 | uint32_t AugmentationStringSize = 0; |
123 | dwarf::Form CUIndexForm = dwarf::DW_FORM_data4; |
124 | dwarf::Form TUIndexForm = dwarf::DW_FORM_data4; |
125 | |
126 | BucketList Buckets; |
127 | |
128 | std::unique_ptr<DebugBufferVector> FullTableBuffer; |
129 | std::unique_ptr<raw_svector_ostream> FullTableStream; |
130 | std::unique_ptr<DebugBufferVector> StrBuffer; |
131 | std::unique_ptr<raw_svector_ostream> StrStream; |
132 | std::unique_ptr<DebugBufferVector> EntriesBuffer; |
133 | std::unique_ptr<raw_svector_ostream> Entriestream; |
134 | std::unique_ptr<DebugBufferVector> AugStringBuffer; |
135 | std::unique_ptr<raw_svector_ostream> AugStringtream; |
136 | llvm::DenseMap<llvm::hash_code, uint64_t> StrCacheToOffsetMap; |
137 | // Contains DWO ID to CUList Index. |
138 | llvm::DenseMap<uint64_t, uint32_t> CUOffsetsToPatch; |
139 | // Contains a map of Entry ID to Entry relative offset. |
140 | llvm::DenseMap<uint64_t, uint32_t> EntryRelativeOffsets; |
141 | llvm::DenseMap<uint64_t, const DIE *> CrossCUDies; |
142 | /// Adds Unit to either CUList, LocalTUList or ForeignTUList. |
143 | /// Input Unit being processed, and DWO ID if Unit is being processed comes |
144 | /// from a DWO section. |
145 | void addUnit(DWARFUnit &Unit, const std::optional<uint64_t> &DWOID); |
146 | /// Returns number of buckets in .debug_name table. |
147 | ArrayRef<HashList> getBuckets() const { return Buckets; } |
148 | /// Get encoding for a given attribute. |
149 | std::optional<DWARF5AccelTable::UnitIndexAndEncoding> |
150 | getIndexForEntry(const BOLTDWARF5AccelTableData &Value) const; |
151 | /// Get encoding for a given attribute for second index. |
152 | /// Returns nullopt if there is no second index. |
153 | std::optional<DWARF5AccelTable::UnitIndexAndEncoding> |
154 | getSecondIndexForEntry(const BOLTDWARF5AccelTableData &Value) const; |
155 | /// Uniquify Entries. |
156 | void finalize(); |
157 | /// Computes bucket count. |
158 | void computeBucketCount(); |
159 | /// Populate Abbreviations Map. |
160 | void populateAbbrevsMap(); |
161 | /// Write Entries. |
162 | void writeEntries(); |
163 | /// Write an Entry. |
164 | void writeEntry(BOLTDWARF5AccelTableData &Entry); |
165 | /// Write augmentation_string for BOLT. |
166 | void writeAugmentationString(); |
167 | /// Emit out Header for DWARF5 Accelerator table. |
168 | void () const; |
169 | /// Emit out CU list. |
170 | void emitCUList() const; |
171 | /// Emit out TU List. Combination of LocalTUList and ForeignTUList. |
172 | void emitTUList() const; |
173 | /// Emit buckets. |
174 | void emitBuckets() const; |
175 | /// Emit hashes for hash table. |
176 | void emitHashes() const; |
177 | /// Emit string offsets for hash table. |
178 | void emitStringOffsets() const; |
179 | /// Emit Entry Offsets for hash table. |
180 | void emitOffsets() const; |
181 | /// Emit abbreviation table. |
182 | void emitAbbrevs(); |
183 | /// Emit entries. |
184 | void emitData(); |
185 | /// Emit augmentation string. |
186 | void emitAugmentationString() const; |
187 | }; |
188 | } // namespace bolt |
189 | } // namespace llvm |
190 | #endif |
191 | |