13
13
#include "llvm/Support/EndianStream.h"
14
14
#include "llvm/Support/LEB128.h"
15
15
#include <cstdint>
16
+ #include <optional>
16
17
17
18
namespace llvm {
18
19
namespace bolt {
@@ -163,10 +164,16 @@ static uint64_t getNameOffset(BinaryContext &BC, DWARFUnit &Unit,
163
164
Index * DwarfOffsetByteSize);
164
165
}
165
166
166
- void DWARF5AcceleratorTable::addAccelTableEntry(
167
- DWARFUnit &Unit, const DIE &Die, const std::optional<uint64_t> &DWOID) {
167
+ static uint64_t getEntryID(const BOLTDWARF5AccelTableData &Entry) {
168
+ return reinterpret_cast<uint64_t>(&Entry);
169
+ }
170
+
171
+ std::optional<BOLTDWARF5AccelTableData *>
172
+ DWARF5AcceleratorTable::addAccelTableEntry(
173
+ DWARFUnit &Unit, const DIE &Die, const std::optional<uint64_t> &DWOID,
174
+ std::optional<BOLTDWARF5AccelTableData *> &Parent) {
168
175
if (Unit.getVersion() < 5 || !NeedToCreate)
169
- return;
176
+ return std::nullopt ;
170
177
std::string NameToUse = "";
171
178
auto canProcess = [&](const DIE &Die) -> bool {
172
179
switch (Die.getTag()) {
@@ -217,7 +224,7 @@ void DWARF5AcceleratorTable::addAccelTableEntry(
217
224
};
218
225
219
226
if (!canProcess(Die))
220
- return;
227
+ return std::nullopt ;
221
228
222
229
// Addes a Unit to either CU, LocalTU or ForeignTU list the first time we
223
230
// encounter it.
@@ -227,10 +234,11 @@ void DWARF5AcceleratorTable::addAccelTableEntry(
227
234
addUnit(Unit, DWOID);
228
235
}
229
236
230
- auto addEntry = [&](DIEValue ValName) -> void {
237
+ auto addEntry =
238
+ [&](DIEValue ValName) -> std::optional<BOLTDWARF5AccelTableData *> {
231
239
if ((!ValName || ValName.getForm() == dwarf::DW_FORM_string) &&
232
240
NameToUse.empty())
233
- return;
241
+ return std::nullopt ;
234
242
std::string Name = "";
235
243
uint64_t NameIndexOffset = 0;
236
244
if (NameToUse.empty()) {
@@ -275,13 +283,23 @@ void DWARF5AcceleratorTable::addAccelTableEntry(
275
283
<< ".\n";
276
284
SecondIndex = Iter->second;
277
285
}
286
+ std::optional<uint64_t> ParentOffset =
287
+ (Parent ? std::optional<uint64_t>(getEntryID(**Parent)) : std::nullopt);
288
+ // This will be populated later in writeEntry.
289
+ // This way only parent entries get tracked.
290
+ // Keeping memory footprint down.
291
+ if (ParentOffset)
292
+ EntryRelativeOffsets.insert({*ParentOffset, 0});
278
293
It.Values.push_back(new (Allocator) BOLTDWARF5AccelTableData(
279
- Die.getOffset(), std::nullopt, DieTag, UnitID, IsTU, SecondIndex));
294
+ Die.getOffset(), ParentOffset, DieTag, UnitID, IsTU, SecondIndex));
295
+ return It.Values.back();
280
296
};
281
297
282
- addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_name));
283
- addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_linkage_name));
284
- return;
298
+ std::optional<BOLTDWARF5AccelTableData *> NameEntry =
299
+ addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_name));
300
+ std::optional<BOLTDWARF5AccelTableData *> LinkageNameEntry =
301
+ addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_linkage_name));
302
+ return NameEntry ? NameEntry : LinkageNameEntry;
285
303
}
286
304
287
305
/// Algorithm from llvm implementation.
@@ -382,6 +400,11 @@ void DWARF5AcceleratorTable::populateAbbrevsMap() {
382
400
if (SecondEntryRet)
383
401
Abbrev.addAttribute(SecondEntryRet->Encoding);
384
402
Abbrev.addAttribute({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
403
+ if (std::optional<uint64_t> Offset = Value->getParentDieOffset())
404
+ Abbrev.addAttribute({dwarf::DW_IDX_parent, dwarf::DW_FORM_ref4});
405
+ else
406
+ Abbrev.addAttribute(
407
+ {dwarf::DW_IDX_parent, dwarf::DW_FORM_flag_present});
385
408
FoldingSetNodeID ID;
386
409
Abbrev.Profile(ID);
387
410
void *InsertPos;
@@ -401,7 +424,11 @@ void DWARF5AcceleratorTable::populateAbbrevsMap() {
401
424
}
402
425
}
403
426
404
- void DWARF5AcceleratorTable::writeEntry(const BOLTDWARF5AccelTableData &Entry) {
427
+ void DWARF5AcceleratorTable::writeEntry(BOLTDWARF5AccelTableData &Entry) {
428
+ const uint64_t EntryID = getEntryID(Entry);
429
+ if (EntryRelativeOffsets.find(EntryID) != EntryRelativeOffsets.end())
430
+ EntryRelativeOffsets[EntryID] = EntriesBuffer->size();
431
+
405
432
const std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
406
433
getIndexForEntry(Entry);
407
434
// For forgeign type (FTU) units that need to refer to the FTU and to the CU.
@@ -456,6 +483,17 @@ void DWARF5AcceleratorTable::writeEntry(const BOLTDWARF5AccelTableData &Entry) {
456
483
llvm::endianness::little);
457
484
break;
458
485
}
486
+ case dwarf::DW_IDX_parent: {
487
+ assert(
488
+ (AttrEnc.Form == dwarf::DW_FORM_ref4 && Entry.getParentDieOffset()) ||
489
+ AttrEnc.Form == dwarf::DW_FORM_flag_present);
490
+ if (std::optional<uint64_t> ParentOffset = Entry.getParentDieOffset()) {
491
+ Entry.setPatchOffset(EntriesBuffer->size());
492
+ support::endian::write(*Entriestream, static_cast<uint32_t>(UINT32_MAX),
493
+ llvm::endianness::little);
494
+ }
495
+ break;
496
+ }
459
497
}
460
498
}
461
499
}
@@ -464,13 +502,34 @@ void DWARF5AcceleratorTable::writeEntries() {
464
502
for (auto &Bucket : getBuckets()) {
465
503
for (DWARF5AcceleratorTable::HashData *Hash : Bucket) {
466
504
Hash->EntryOffset = EntriesBuffer->size();
467
- for (const BOLTDWARF5AccelTableData *Value : Hash->Values) {
505
+ for (BOLTDWARF5AccelTableData *Value : Hash->Values) {
468
506
writeEntry(*Value);
469
507
}
470
508
support::endian::write(*Entriestream, static_cast<uint8_t>(0),
471
509
llvm::endianness::little);
472
510
}
473
511
}
512
+ // Patching parent offsets.
513
+ for (auto &Bucket : getBuckets()) {
514
+ for (DWARF5AcceleratorTable::HashData *Hash : Bucket) {
515
+ for (BOLTDWARF5AccelTableData *Entry : Hash->Values) {
516
+ std::optional<uint64_t> ParentOffset = Entry->getParentDieOffset();
517
+ if (!ParentOffset)
518
+ continue;
519
+ if (const auto Iter = EntryRelativeOffsets.find(*ParentOffset);
520
+ Iter != EntryRelativeOffsets.end()) {
521
+ const uint64_t PatchOffset = Entry->getPatchOffset();
522
+ uint32_t *Ptr = reinterpret_cast<uint32_t *>(
523
+ &EntriesBuffer.get()->data()[PatchOffset]);
524
+ *Ptr = Iter->second;
525
+ } else {
526
+ BC.errs() << "BOLT-WARNING: [internal-dwarf-warning]: Could not find "
527
+ "entry with offset "
528
+ << *ParentOffset << "\n";
529
+ }
530
+ }
531
+ }
532
+ }
474
533
}
475
534
476
535
void DWARF5AcceleratorTable::writeAugmentationString() {
0 commit comments