Skip to content

Commit 08136d8

Browse files
committed
[DWARFLinkerParallel] Add support of accelerator tables to DWARFLinkerParallel.
This patch is extracted from D96035, it adds support for the accelerator tables to the DWARFLinkerParallel functionality. Differential Revision: https://reviews.llvm.org/D154793
1 parent 57b0194 commit 08136d8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1319
-1489
lines changed

llvm/include/llvm/CodeGen/AccelTable.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/Support/DJB.h"
2626
#include "llvm/Support/Debug.h"
2727
#include <cstdint>
28+
#include <variant>
2829
#include <vector>
2930

3031
/// \file
@@ -310,9 +311,13 @@ void emitDWARF5AccelTable(AsmPrinter *Asm,
310311
const DwarfDebug &DD,
311312
ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs);
312313

314+
/// Emit a DWARFv5 Accelerator Table consisting of entries in the specified
315+
/// AccelTable. The \p CUs contains either symbols keeping offsets to the
316+
/// start of compilation unit, either offsets to the start of compilation
317+
/// unit themselves.
313318
void emitDWARF5AccelTable(
314319
AsmPrinter *Asm, AccelTable<DWARF5AccelTableStaticData> &Contents,
315-
ArrayRef<MCSymbol *> CUs,
320+
ArrayRef<std::variant<MCSymbol *, uint64_t>> CUs,
316321
llvm::function_ref<unsigned(const DWARF5AccelTableStaticData &)>
317322
getCUIndexForEntry);
318323

llvm/include/llvm/DWARFLinkerParallel/DWARFLinker.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,6 @@ class ExtraDwarfEmitter {
100100
/// Emit section named SecName with data SecData.
101101
virtual void emitSectionContents(StringRef SecData, StringRef SecName) = 0;
102102

103-
/// Emit temporarily symbol named \p SymName inside section \p SecName.
104-
virtual MCSymbol *emitTempSym(StringRef SecName, StringRef SymName) = 0;
105-
106103
/// Emit the swift_ast section stored in \p Buffer.
107104
virtual void emitSwiftAST(StringRef Buffer) = 0;
108105

llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
213213

214214
Header Header;
215215
DenseMap<uint32_t, SmallVector<AttributeEncoding, 2>> Abbreviations;
216-
ArrayRef<MCSymbol *> CompUnits;
216+
ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits;
217217
llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry;
218218
MCSymbol *ContributionEnd = nullptr;
219219
MCSymbol *AbbrevStart = Asm->createTempSymbol("names_abbrev_start");
@@ -235,7 +235,7 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
235235
public:
236236
Dwarf5AccelTableWriter(
237237
AsmPrinter *Asm, const AccelTableBase &Contents,
238-
ArrayRef<MCSymbol *> CompUnits,
238+
ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits,
239239
llvm::function_ref<unsigned(const DataT &)> GetCUIndexForEntry);
240240

241241
void emit();
@@ -419,7 +419,10 @@ template <typename DataT>
419419
void Dwarf5AccelTableWriter<DataT>::emitCUList() const {
420420
for (const auto &CU : enumerate(CompUnits)) {
421421
Asm->OutStreamer->AddComment("Compilation unit " + Twine(CU.index()));
422-
Asm->emitDwarfSymbolReference(CU.value());
422+
if (std::holds_alternative<MCSymbol *>(CU.value()))
423+
Asm->emitDwarfSymbolReference(std::get<MCSymbol *>(CU.value()));
424+
else
425+
Asm->emitDwarfLengthOrOffset(std::get<uint64_t>(CU.value()));
423426
}
424427
}
425428

@@ -508,7 +511,7 @@ template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() const {
508511
template <typename DataT>
509512
Dwarf5AccelTableWriter<DataT>::Dwarf5AccelTableWriter(
510513
AsmPrinter *Asm, const AccelTableBase &Contents,
511-
ArrayRef<MCSymbol *> CompUnits,
514+
ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits,
512515
llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry)
513516
: AccelTableWriter(Asm, Contents, false),
514517
Header(CompUnits.size(), Contents.getBucketCount(),
@@ -545,7 +548,7 @@ void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents,
545548
void llvm::emitDWARF5AccelTable(
546549
AsmPrinter *Asm, AccelTable<DWARF5AccelTableData> &Contents,
547550
const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) {
548-
std::vector<MCSymbol *> CompUnits;
551+
std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits;
549552
SmallVector<unsigned, 1> CUIndex(CUs.size());
550553
int Count = 0;
551554
for (const auto &CU : enumerate(CUs)) {
@@ -581,7 +584,7 @@ void llvm::emitDWARF5AccelTable(
581584

582585
void llvm::emitDWARF5AccelTable(
583586
AsmPrinter *Asm, AccelTable<DWARF5AccelTableStaticData> &Contents,
584-
ArrayRef<MCSymbol *> CUs,
587+
ArrayRef<std::variant<MCSymbol *, uint64_t>> CUs,
585588
llvm::function_ref<unsigned(const DWARF5AccelTableStaticData &)>
586589
getCUIndexForEntry) {
587590
Contents.finalize(Asm, "names");

llvm/lib/DWARFLinker/DWARFStreamer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ void DwarfStreamer::emitDebugNames(
297297
return;
298298

299299
// Build up data structures needed to emit this section.
300-
std::vector<MCSymbol *> CompUnits;
300+
std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits;
301301
DenseMap<unsigned, size_t> UniqueIdToCuMap;
302302
unsigned Id = 0;
303303
for (auto &CU : EmittedUnits) {

llvm/lib/DWARFLinkerParallel/ArrayList.h

Lines changed: 85 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,60 +9,63 @@
99
#ifndef LLVM_LIB_DWARFLINKERPARALLEL_ARRAYLIST_H
1010
#define LLVM_LIB_DWARFLINKERPARALLEL_ARRAYLIST_H
1111

12-
#include "DWARFLinkerGlobalData.h"
1312
#include "llvm/Support/PerThreadBumpPtrAllocator.h"
13+
#include <atomic>
1414

1515
namespace llvm {
1616
namespace dwarflinker_parallel {
1717

1818
/// This class is a simple list of T structures. It keeps elements as
1919
/// pre-allocated groups to save memory for each element's next pointer.
2020
/// It allocates internal data using specified per-thread BumpPtrAllocator.
21+
/// Method add() can be called asynchronously.
2122
template <typename T, size_t ItemsGroupSize = 512> class ArrayList {
2223
public:
23-
/// Copy specified \p Item into the list.
24-
T &noteItem(const T &Item) {
25-
assert(Allocator != nullptr);
26-
27-
ItemsGroup *CurGroup = LastGroup;
28-
29-
if (CurGroup == nullptr) {
30-
// Allocate first ItemsGroup.
31-
LastGroup = Allocator->Allocate<ItemsGroup>();
32-
LastGroup->ItemsCount = 0;
33-
LastGroup->Next = nullptr;
34-
GroupsHead = LastGroup;
35-
CurGroup = LastGroup;
24+
/// Add specified \p Item to the list.
25+
T &add(const T &Item) {
26+
assert(Allocator);
27+
28+
// Allocate head group if it is not allocated yet.
29+
while (!LastGroup) {
30+
if (allocateNewGroup(GroupsHead))
31+
LastGroup = GroupsHead.load();
3632
}
3733

38-
if (CurGroup->ItemsCount == ItemsGroupSize) {
39-
// Allocate next ItemsGroup if current one is full.
40-
LastGroup = Allocator->Allocate<ItemsGroup>();
41-
LastGroup->ItemsCount = 0;
42-
LastGroup->Next = nullptr;
43-
CurGroup->Next = LastGroup;
34+
ItemsGroup *CurGroup;
35+
size_t CurItemsCount;
36+
do {
4437
CurGroup = LastGroup;
45-
}
38+
CurItemsCount = CurGroup->ItemsCount.fetch_add(1);
39+
40+
// Check whether current group is full.
41+
if (CurItemsCount < ItemsGroupSize)
42+
break;
43+
44+
// Allocate next group if necessary.
45+
if (!CurGroup->Next)
46+
allocateNewGroup(CurGroup->Next);
47+
48+
LastGroup.compare_exchange_weak(CurGroup, CurGroup->Next);
49+
} while (true);
4650

47-
// Copy item into the next position inside current ItemsGroup.
48-
CurGroup->Items[CurGroup->ItemsCount] = Item;
49-
return CurGroup->Items[CurGroup->ItemsCount++];
51+
// Store item into the current group.
52+
CurGroup->Items[CurItemsCount] = Item;
53+
return CurGroup->Items[CurItemsCount];
5054
}
5155

5256
using ItemHandlerTy = function_ref<void(T &)>;
5357

5458
/// Enumerate all items and apply specified \p Handler to each.
5559
void forEach(ItemHandlerTy Handler) {
56-
for (ItemsGroup *CurGroup = GroupsHead; CurGroup != nullptr;
60+
for (ItemsGroup *CurGroup = GroupsHead; CurGroup;
5761
CurGroup = CurGroup->Next) {
58-
for (size_t Idx = 0; Idx < CurGroup->ItemsCount; Idx++) {
59-
Handler(CurGroup->Items[Idx]);
60-
}
62+
for (T &Item : *CurGroup)
63+
Handler(Item);
6164
}
6265
}
6366

6467
/// Check whether list is empty.
65-
bool empty() { return GroupsHead == nullptr; }
68+
bool empty() { return !GroupsHead; }
6669

6770
/// Erase list.
6871
void erase() {
@@ -76,13 +79,61 @@ template <typename T, size_t ItemsGroupSize = 512> class ArrayList {
7679

7780
protected:
7881
struct ItemsGroup {
79-
std::array<T, ItemsGroupSize> Items;
80-
ItemsGroup *Next = nullptr;
81-
size_t ItemsCount = 0;
82+
using ArrayTy = std::array<T, ItemsGroupSize>;
83+
84+
// Array of items kept by this group.
85+
ArrayTy Items;
86+
87+
// Pointer to the next items group.
88+
std::atomic<ItemsGroup *> Next = nullptr;
89+
90+
// Number of items in this group.
91+
// NOTE: ItemsCount could be inaccurate as it might be incremented by
92+
// several threads. Use getItemsCount() method to get real number of items
93+
// inside ItemsGroup.
94+
std::atomic<size_t> ItemsCount = 0;
95+
96+
size_t getItemsCount() const {
97+
return std::min(ItemsCount.load(), ItemsGroupSize);
98+
}
99+
100+
typename ArrayTy::iterator begin() { return Items.begin(); }
101+
typename ArrayTy::iterator end() { return Items.begin() + getItemsCount(); }
82102
};
83103

84-
ItemsGroup *GroupsHead = nullptr;
85-
ItemsGroup *LastGroup = nullptr;
104+
// Allocate new group. Put allocated group into the \p AtomicGroup if
105+
// it is empty. If \p AtomicGroup is filled by another thread then
106+
// put allocated group into the end of groups list.
107+
// \returns true if allocated group is put into the \p AtomicGroup.
108+
bool allocateNewGroup(std::atomic<ItemsGroup *> &AtomicGroup) {
109+
ItemsGroup *CurGroup = nullptr;
110+
111+
// Allocate new group.
112+
ItemsGroup *NewGroup = Allocator->Allocate<ItemsGroup>();
113+
NewGroup->ItemsCount = 0;
114+
NewGroup->Next = nullptr;
115+
116+
// Try to replace current group with allocated one.
117+
if (AtomicGroup.compare_exchange_weak(CurGroup, NewGroup))
118+
return true;
119+
120+
// Put allocated group as last group.
121+
while (CurGroup) {
122+
ItemsGroup *NextGroup = CurGroup->Next;
123+
124+
if (!NextGroup) {
125+
if (CurGroup->Next.compare_exchange_weak(NextGroup, NewGroup))
126+
break;
127+
}
128+
129+
CurGroup = NextGroup;
130+
}
131+
132+
return false;
133+
}
134+
135+
std::atomic<ItemsGroup *> GroupsHead = nullptr;
136+
std::atomic<ItemsGroup *> LastGroup = nullptr;
86137
parallel::PerThreadBumpPtrAllocator *Allocator = nullptr;
87138
};
88139

llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ size_t DIEAttributeCloner::cloneDieRefAttr(
226226
return 0;
227227

228228
std::optional<std::pair<CompileUnit *, uint32_t>> RefDiePair =
229-
CU.resolveDIEReference(Val);
229+
CU.resolveDIEReference(Val, ResolveInterCUReferencesMode::Resolve);
230230
if (!RefDiePair) {
231231
// If the referenced DIE is not found, drop the attribute.
232232
CU.warn("cann't find referenced DIE.", InputDieEntry);
@@ -314,6 +314,11 @@ size_t DIEAttributeCloner::cloneScalarAttr(
314314
}
315315

316316
uint64_t Value;
317+
if (AttrSpec.Attr == dwarf::DW_AT_const_value &&
318+
(InputDieEntry->getTag() == dwarf::DW_TAG_variable ||
319+
InputDieEntry->getTag() == dwarf::DW_TAG_constant))
320+
AttrInfo.HasLiveAddress = true;
321+
317322
if (CU.getGlobalData().getOptions().UpdateIndexTablesOnly) {
318323
if (auto OptionalValue = Val.getAsUnsignedConstant())
319324
Value = *OptionalValue;
@@ -483,14 +488,19 @@ size_t DIEAttributeCloner::cloneBlockAttr(
483488
(AttrOutOffset + (FinalAttributeSize - Bytes.size()));
484489
}
485490

491+
if (HasLocationExpressionAddress)
492+
AttrInfo.HasLiveAddress =
493+
VarAddressAdjustment.has_value() ||
494+
CU.getGlobalData().getOptions().UpdateIndexTablesOnly;
495+
486496
return FinalAttributeSize;
487497
}
488498

489499
size_t DIEAttributeCloner::cloneAddressAttr(
490500
const DWARFFormValue &Val,
491501
const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {
492502
if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
493-
AttrInfo.HasLowPc = true;
503+
AttrInfo.HasLiveAddress = true;
494504

495505
if (CU.getGlobalData().getOptions().UpdateIndexTablesOnly)
496506
return Generator

llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.h

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,28 @@
1717
namespace llvm {
1818
namespace dwarflinker_parallel {
1919

20+
/// Information gathered and exchanged between the various
21+
/// clone*Attr helpers about the attributes of a particular DIE.
22+
struct AttributesInfo {
23+
/// Short Name.
24+
StringEntry *Name = nullptr;
25+
26+
/// Mangled Name.
27+
StringEntry *MangledName = nullptr;
28+
29+
/// Does the DIE have an address pointing to live code section?
30+
bool HasLiveAddress = false;
31+
32+
/// Is this DIE only a declaration?
33+
bool IsDeclaration = false;
34+
35+
/// Does the DIE have a ranges attribute?
36+
bool HasRanges = false;
37+
38+
/// Does the DIE have a string offset attribute?
39+
bool HasStringOffsetBaseAttr = false;
40+
};
41+
2042
/// This class creates clones of input DIE attributes.
2143
/// It enumerates attributes of input DIE, creates clone for each
2244
/// attribute, adds cloned attribute to the output DIE.
@@ -44,29 +66,7 @@ class DIEAttributeCloner {
4466
/// Create abbreviations for the output DIE after all attributes are cloned.
4567
unsigned finalizeAbbreviations(bool HasChildrenToClone);
4668

47-
/// Information gathered and exchanged between the various
48-
/// clone*Attr helpers about the attributes of a particular DIE.
49-
///
5069
/// Cannot be used concurrently.
51-
struct AttributesInfo {
52-
/// Names.
53-
StringEntry *Name = nullptr;
54-
StringEntry *MangledName = nullptr;
55-
StringEntry *NameWithoutTemplate = nullptr;
56-
57-
/// Does the DIE have a low_pc attribute?
58-
bool HasLowPc = false;
59-
60-
/// Is this DIE only a declaration?
61-
bool IsDeclaration = false;
62-
63-
/// Does the DIE have a ranges attribute?
64-
bool HasRanges = false;
65-
66-
/// Does the DIE have a string offset attribute?
67-
bool HasStringOffsetBaseAttr = false;
68-
};
69-
7070
AttributesInfo AttrInfo;
7171

7272
protected:

0 commit comments

Comments
 (0)