LLVM: lib/DWARFLinker/Parallel/DWARFLinkerTypeUnit.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
12
13using namespace llvm;
16
21 AcceleratorRecords(&GlobalData.getAllocator()) {
22
23 UnitName = "__artificial_type_unit";
24
26
27
29 LineTable.Prologue.MinInstLength = 1;
30 LineTable.Prologue.MaxOpsPerInst = 1;
31 LineTable.Prologue.DefaultIsStmt = 1;
32 LineTable.Prologue.LineBase = -5;
33 LineTable.Prologue.LineRange = 14;
34 LineTable.Prologue.OpcodeBase = 13;
35 LineTable.Prologue.StandardOpcodeLengths = {0, 1, 1, 1, 1, 0,
36 0, 0, 1, 0, 0, 1};
37
39}
40
42 prepareDataForTreeCreation();
43
44
45
52
53 DIEGenerator DIETreeGenerator(Allocator, *this);
55
56
57 DIE *UnitDIE = DIETreeGenerator.createDIE(dwarf::DW_TAG_compile_unit, 0);
60
62 ProducerString += "llvm DWARFLinkerParallel library version ";
65 {OutOffset},
66 GlobalData.getStringPool().insert(ProducerString.str()).first},
67 PatchesOffsets);
68 OutOffset += DIETreeGenerator
70 dwarf::DW_FORM_strp)
71 .second;
72
73 if (Language) {
74 OutOffset += DIETreeGenerator
76 dwarf::DW_FORM_data2, *Language)
77 .second;
78 }
79
83 PatchesOffsets);
84 OutOffset += DIETreeGenerator
86 dwarf::DW_FORM_strp)
87 .second;
88
89 if (!LineTable.Prologue.FileNames.empty()) {
91 DebugOffsetPatch{OutOffset, &DebugLineSection}, PatchesOffsets);
92
93 OutOffset += DIETreeGenerator
95 dwarf::DW_FORM_sec_offset, 0xbaddef)
96 .second;
97 }
98
101 PatchesOffsets);
102 OutOffset += DIETreeGenerator
104 dwarf::DW_FORM_strp)
105 .second;
106
108
109
110
111 OutOffset += DIETreeGenerator
113 dwarf::DW_FORM_sec_offset,
115 .second;
116 }
117
119 OutOffset =
120 finalizeTypeEntryRec(UnitDIE->getOffset(), UnitDIE, Types.getRoot());
121
122
123 for (uint64_t *OffsetPtr : PatchesOffsets)
125
127 });
128}
129
130void TypeUnit::prepareDataForTreeCreation() {
133
134
135
136
138
141
142 Types.sortTypes();
143 });
144 }
145
148
153 return LHS.Directory->first() < RHS.Directory->first() ||
154 (!(RHS.Directory->first() < LHS.Directory->first()) &&
155 LHS.FilePath->first() < RHS.FilePath->first());
156 };
157
158 DebugInfoSection.ListDebugTypeDeclFilePatch.sort(PatchesComparator);
159 }
160
161
163 getScalarFormForValue(
164 DebugInfoSection.ListDebugTypeDeclFilePatch.size())
165 .first;
166
167 DebugInfoSection.ListDebugTypeDeclFilePatch.forEach(
168 [&](DebugTypeDeclFilePatch &Patch) {
172 .str()
173 .c_str());
175 return;
176
177 uint32_t FileIdx =
179
180 unsigned DIESize = Patch.Die->getSize();
181 DIEGenerator DIEGen(Patch.Die, Types.getThreadLocalAllocator(),
182 *this);
183
184 DIESize += DIEGen
185 .addScalarAttribute(dwarf::DW_AT_decl_file,
186 DeclFileForm, FileIdx)
187 .second;
189 });
190 });
191
192 if (.getOptions().AllowNonDeterministicOutput) {
193
195 forEach([&](SectionDescriptor &OutSection) {
196 std::function<bool(const DebugStrPatch &LHS, const DebugStrPatch &RHS)>
197 StrPatchesComparator =
198 [&](const DebugStrPatch &LHS, const DebugStrPatch &RHS) {
199 return LHS.String->getKey() < RHS.String->getKey();
200 };
201 OutSection.ListDebugStrPatch.sort(StrPatchesComparator);
202
203 std::function<bool(const DebugTypeStrPatch &LHS,
204 const DebugTypeStrPatch &RHS)>
205 TypeStrPatchesComparator = [&](const DebugTypeStrPatch &LHS,
206 const DebugTypeStrPatch &RHS) {
207 return LHS.String->getKey() < RHS.String->getKey();
208 };
209 OutSection.ListDebugTypeStrPatch.sort(TypeStrPatchesComparator);
210 });
211 });
212 }
213
214 if (.getOptions().AllowNonDeterministicOutput) {
215
217 forEach([&](SectionDescriptor &OutSection) {
218 std::function<bool(const DebugLineStrPatch &LHS,
219 const DebugLineStrPatch &RHS)>
220 LineStrPatchesComparator = [&](const DebugLineStrPatch &LHS,
221 const DebugLineStrPatch &RHS) {
222 return LHS.String->getKey() < RHS.String->getKey();
223 };
224 OutSection.ListDebugLineStrPatch.sort(LineStrPatchesComparator);
225
226 std::function<bool(const DebugTypeLineStrPatch &LHS,
227 const DebugTypeLineStrPatch &RHS)>
228 TypeLineStrPatchesComparator =
229 [&](const DebugTypeLineStrPatch &LHS,
230 const DebugTypeLineStrPatch &RHS) {
231 return LHS.String->getKey() < RHS.String->getKey();
232 };
233 OutSection.ListDebugTypeLineStrPatch.sort(TypeLineStrPatchesComparator);
234 });
235 });
236 }
237}
238
239uint64_t TypeUnit::finalizeTypeEntryRec(uint64_t OutOffset, DIE *OutDIE,
241 bool HasChildren = ->getValue().load()->Children.empty();
242 DIEGenerator DIEGen(OutDIE, Types.getThreadLocalAllocator(), *this);
243 OutOffset += DIEGen.finalizeAbbreviations(HasChildren, nullptr);
244 OutOffset += OutDIE->getSize() - 1;
245
246 if (HasChildren) {
247 Entry->getValue().load()->Children.forEach([&](TypeEntry *ChildEntry) {
248 DIE *ChildDIE = &ChildEntry->getValue().load()->getFinalDie();
249 DIEGen.addChild(ChildDIE);
250
252
253 OutOffset = finalizeTypeEntryRec(OutOffset, ChildDIE, ChildEntry);
254 });
255
256
257 OutOffset += sizeof(int8_t);
258 }
259
261 return OutOffset;
262}
263
264uint32_t TypeUnit::addFileNameIntoLinetable(StringEntry *Dir,
266 uint32_t DirIdx = 0;
267
268 if (Dir->first() == "") {
269 DirIdx = 0;
270 } else {
271 DirectoriesMapTy::iterator DirEntry = DirectoriesMap.find(Dir);
272 if (DirEntry == DirectoriesMap.end()) {
273
274 assert(LineTable.Prologue.IncludeDirectories.size() < UINT32_MAX);
275 DirIdx = LineTable.Prologue.IncludeDirectories.size();
276 DirectoriesMap.insert({Dir, DirIdx});
277 LineTable.Prologue.IncludeDirectories.push_back(
280 } else {
281 DirIdx = DirEntry->second;
282 }
283
285 DirIdx++;
286 }
287
288 auto [FileEntry, Inserted] = FileNamesMap.try_emplace(
289 {FileName, DirIdx}, LineTable.Prologue.FileNames.size());
290 if (Inserted) {
291
292 assert(LineTable.Prologue.FileNames.size() < UINT32_MAX);
293 LineTable.Prologue.FileNames.push_back(DWARFDebugLine::FileNameEntry());
295 dwarf::DW_FORM_string, FileName->getKeyData());
296 LineTable.Prologue.FileNames.back().DirIdx = DirIdx;
297 }
298
299 uint32_t FileIdx = FileEntry->second;
300 return getVersion() < 5 ? FileIdx + 1 : FileIdx;
301}
302
303std::pair<dwarf::Form, uint8_t>
304TypeUnit::getScalarFormForValue(uint64_t Value) const {
305 if (Value > 0xFFFFFFFF)
306 return std::make_pair(dwarf::DW_FORM_data8, 8);
307
308 if (Value > 0xFFFF)
309 return std::make_pair(dwarf::DW_FORM_data4, 4);
310
311 if (Value > 0xFF)
312 return std::make_pair(dwarf::DW_FORM_data2, 2);
313
314 return std::make_pair(dwarf::DW_FORM_data1, 1);
315}
316
317uint8_t TypeUnit::getSizeByAttrForm(dwarf::Form Form) const {
318 if (Form == dwarf::DW_FORM_data1)
319 return 1;
320
321 if (Form == dwarf::DW_FORM_data2)
322 return 2;
323
324 if (Form == dwarf::DW_FORM_data4)
325 return 4;
326
327 if (Form == dwarf::DW_FORM_data8)
328 return 8;
329
330 if (Form == dwarf::DW_FORM_data16)
331 return 16;
332
334}
335
339
342
343
344
353 }
354
356
357
358 if (!LineTable.Prologue.FileNames.empty()) {
359 Tasks.push_back(
361 }
362
363
365
366
369 Tasks.push_back([&]() -> Error {
372 });
373 }
374
375
377
378
380
382 Tasks, [&](std::function<Error(void)> F) { return F(); }))
383 return Err;
384
386}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
A structured debug information entry.
unsigned getAbbrevNumber() const
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
void setOffset(unsigned O)
static LLVM_ABI DWARFFormValue createFromPValue(dwarf::Form F, const char *V)
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
StringRef str() const
Explicit conversion to StringRef.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
const ValueTy & getValue() const
const char * getKeyData() const
getKeyData - Return the start of the string data that is the key for this value.
Triple - Helper class for working with autoconf configuration names.
@ Pub
.debug_pubnames, .debug_pubtypes
This class is a helper to create output DIE tree.
std::pair< DIEValue &, size_t > addStringPlaceholderAttribute(dwarf::Attribute Attr, dwarf::Form AttrForm)
Adds string attribute with dummy offset to the current DIE.
DIE * createDIE(dwarf::Tag DieTag, uint32_t OutOffset)
Creates a DIE of specified tag DieTag and OutOffset.
std::pair< DIEValue &, size_t > addScalarAttribute(dwarf::Attribute Attr, dwarf::Form AttrForm, uint64_t Value)
Adds specified scalar attribute to the current DIE.
std::string UnitName
The name of this unit.
IndexedValuesMap< const StringEntry * > DebugStringIndexMap
Maps a string into the index inside .debug_str_offsets section.
unsigned ID
Unique ID for the unit.
StringRef getUnitName() const
Returns this unit name.
void setOutUnitDIE(DIE *UnitDie)
Set output unit DIE.
DwarfUnit(LinkingGlobalData &GlobalData, unsigned ID, StringRef ClangModuleName)
DIE * getOutUnitDIE()
Returns output unit DIE.
This class keeps data and services common for the whole linking process.
const DWARFLinkerOptions & getOptions() const
Returns linking options.
uint16_t getDebugStrOffsetsHeaderSize() const
Return size of header of debug_str_offsets table.
LinkingGlobalData & GlobalData
dwarf::FormParams Format
Format for sections.
const dwarf::FormParams & getFormParams() const
Return size of address.
void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianness)
Sets output format for all keeping sections.
uint16_t getVersion() const
Return DWARF version.
uint16_t getDebugInfoHeaderSize() const
Return size of header of debug_info table.
void forEach(function_ref< void(SectionDescriptor &)> Handler)
Enumerate all sections and call Handler for each.
SectionDescriptor & getOrCreateSectionDescriptor(DebugSectionKind SectionKind)
Returns descriptor for the specified section of SectionKind.
Error finishCloningAndEmit(const Triple &TargetTriple)
Emits resulting dwarf based on information from DIE tree.
Definition DWARFLinkerTypeUnit.cpp:336
void createDIETree(BumpPtrAllocator &Allocator)
Generates DIE tree based on information from TypesMap.
Definition DWARFLinkerTypeUnit.cpp:41
TypeUnit(LinkingGlobalData &GlobalData, unsigned ID, std::optional< uint16_t > Language, dwarf::FormParams Format, llvm::endianness Endianess)
Definition DWARFLinkerTypeUnit.cpp:17
LLVM_ABI void spawn(std::function< void()> f)
Error emitDebugInfo(const Triple &TargetTriple)
Emit .debug_info section for unit DIEs.
Error emitDebugStringOffsetSection()
Emit the .debug_str_offsets section for current unit.
void emitPubAccelerators()
Emit .debug_pubnames and .debug_pubtypes for Unit.
Error emitAbbreviations()
Error emitDebugLine(const Triple &TargetTriple, const DWARFDebugLine::LineTable &OutLineTable)
Emit .debug_line section.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
SmallVector< uint64_t * > OffsetsPtrVector
Type for list of pointers to patches offsets.
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
StringMapEntry< EmptyStringSetTag > StringEntry
StringEntry keeps data of the string: the length, external offset and a string body which is placed r...
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Error parallelForEachError(RangeTy &&R, FuncTy Fn)
A helper struct providing information about the byte size of DW_FORM values that vary in size dependi...
bool AllowNonDeterministicOutput
Allow to generate valid, but non deterministic output.
This structure is used to update strings offsets into .debug_str.
This structure is used to keep data of the concrete section.
void notePatchWithOffsetUpdate(const T &Patch, OffsetsPtrVector &PatchesOffsetsList)
While creating patches, offsets to attributes may be partially unknown(because size of abbreviation n...