Skip to content

Commit 5f2a7fa

Browse files
committed
[Reland][Reland][DWARFLinkerParallel] Add limited functionality to DWARFLinkerParallel.
This patch is extracted from D96035, it adds support for the existing DWARFLinker functionality. What is not supported yet: 1. Types deduplication(--odr mode). 2. Modules deduplication. 3. Generation of index tables. Reland2: temporarily disabled call to "--linker llvm" for tls-variable.test and location-expression.test as it does not work properly on bigendian architecture. Differential Revision: https://reviews.llvm.org/D153268
1 parent 9108897 commit 5f2a7fa

File tree

133 files changed

+8485
-1007
lines changed

Some content is hidden

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

133 files changed

+8485
-1007
lines changed

llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,29 +27,34 @@ struct DwarfStringPoolEntry {
2727
bool isIndexed() const { return Index != NotIndexed; }
2828
};
2929

30+
/// DwarfStringPoolEntry with string keeping externally.
31+
struct DwarfStringPoolEntryWithExtString : public DwarfStringPoolEntry {
32+
StringRef String;
33+
};
34+
3035
/// DwarfStringPoolEntryRef: Dwarf string pool entry reference.
3136
///
3237
/// Dwarf string pool entry keeps string value and its data.
3338
/// There are two variants how data are represented:
3439
///
35-
/// 1. By value - StringMapEntry<DwarfStringPoolEntry>.
36-
/// 2. By pointer - StringMapEntry<DwarfStringPoolEntry *>.
40+
/// 1. String data in pool - StringMapEntry<DwarfStringPoolEntry>.
41+
/// 2. External string data - DwarfStringPoolEntryWithExtString.
3742
///
38-
/// The "By pointer" variant allows for reducing memory usage for the case
39-
/// when string pool entry does not have data: it keeps the null pointer
40-
/// and so no need to waste space for the full DwarfStringPoolEntry.
41-
/// It is recommended to use "By pointer" variant if not all entries
42-
/// of dwarf string pool have corresponding DwarfStringPoolEntry.
43+
/// The external data variant allows reducing memory usage for the case
44+
/// when string pool entry does not have data: string entry does not
45+
/// keep any data and so no need to waste space for the full
46+
/// DwarfStringPoolEntry. It is recommended to use external variant if not all
47+
/// entries of dwarf string pool have corresponding DwarfStringPoolEntry.
4348

4449
class DwarfStringPoolEntryRef {
4550
/// Pointer type for "By value" string entry.
4651
using ByValStringEntryPtr = const StringMapEntry<DwarfStringPoolEntry> *;
4752

48-
/// Pointer type for "By pointer" string entry.
49-
using ByPtrStringEntryPtr = const StringMapEntry<DwarfStringPoolEntry *> *;
53+
/// Pointer type for external string entry.
54+
using ExtStringEntryPtr = const DwarfStringPoolEntryWithExtString *;
5055

5156
/// Pointer to the dwarf string pool Entry.
52-
PointerUnion<ByValStringEntryPtr, ByPtrStringEntryPtr> MapEntry = nullptr;
57+
PointerUnion<ByValStringEntryPtr, ExtStringEntryPtr> MapEntry = nullptr;
5358

5459
public:
5560
DwarfStringPoolEntryRef() = default;
@@ -61,10 +66,8 @@ class DwarfStringPoolEntryRef {
6166

6267
/// ASSUMPTION: DwarfStringPoolEntryRef keeps pointer to \p Entry,
6368
/// thus specified entry mustn`t be reallocated.
64-
DwarfStringPoolEntryRef(const StringMapEntry<DwarfStringPoolEntry *> &Entry)
65-
: MapEntry(&Entry) {
66-
assert(cast<ByPtrStringEntryPtr>(MapEntry)->second != nullptr);
67-
}
69+
DwarfStringPoolEntryRef(const DwarfStringPoolEntryWithExtString &Entry)
70+
: MapEntry(&Entry) {}
6871

6972
explicit operator bool() const { return !MapEntry.isNull(); }
7073

@@ -88,15 +91,15 @@ class DwarfStringPoolEntryRef {
8891
if (isa<ByValStringEntryPtr>(MapEntry))
8992
return cast<ByValStringEntryPtr>(MapEntry)->first();
9093

91-
return cast<ByPtrStringEntryPtr>(MapEntry)->first();
94+
return cast<ExtStringEntryPtr>(MapEntry)->String;
9295
}
9396

9497
/// \returns the entire string pool entry for convenience.
9598
const DwarfStringPoolEntry &getEntry() const {
9699
if (isa<ByValStringEntryPtr>(MapEntry))
97100
return cast<ByValStringEntryPtr>(MapEntry)->second;
98101

99-
return *cast<ByPtrStringEntryPtr>(MapEntry)->second;
102+
return *cast<ExtStringEntryPtr>(MapEntry);
100103
}
101104

102105
bool operator==(const DwarfStringPoolEntryRef &X) const {

llvm/include/llvm/DWARFLinker/DWARFLinker.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,11 @@ using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
270270
/// and its address map.
271271
class DWARFFile {
272272
public:
273+
using UnloadCallbackTy = std::function<void(StringRef FileName)>;
273274
DWARFFile(StringRef Name, std::unique_ptr<DWARFContext> Dwarf,
274275
std::unique_ptr<AddressesMap> Addresses,
275-
const std::vector<std::string> &Warnings)
276+
const std::vector<std::string> &Warnings,
277+
UnloadCallbackTy = nullptr)
276278
: FileName(Name), Dwarf(std::move(Dwarf)),
277279
Addresses(std::move(Addresses)), Warnings(Warnings) {}
278280

llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
#define LLVM_DWARFLINKERPARALLEL_ADDRESSESMAP_H
1111

1212
#include "llvm/ADT/AddressRanges.h"
13+
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
1314
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
1415
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
16+
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
1517
#include <cstdint>
1618

1719
namespace llvm {
@@ -62,6 +64,108 @@ class AddressesMap {
6264

6365
/// Erases all data.
6466
virtual void clear() = 0;
67+
68+
/// This function checks whether variable has DWARF expression containing
69+
/// operation referencing live address(f.e. DW_OP_addr, DW_OP_addrx...).
70+
/// \returns first is true if the expression has an operation referencing an
71+
/// address.
72+
/// second is the relocation adjustment value if the live address is
73+
/// referenced.
74+
std::pair<bool, std::optional<int64_t>>
75+
getVariableRelocAdjustment(const DWARFDie &DIE) {
76+
assert((DIE.getTag() == dwarf::DW_TAG_variable ||
77+
DIE.getTag() == dwarf::DW_TAG_constant) &&
78+
"Wrong type of input die");
79+
80+
const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
81+
82+
// Check if DIE has DW_AT_location attribute.
83+
DWARFUnit *U = DIE.getDwarfUnit();
84+
std::optional<uint32_t> LocationIdx =
85+
Abbrev->findAttributeIndex(dwarf::DW_AT_location);
86+
if (!LocationIdx)
87+
return std::make_pair(false, std::nullopt);
88+
89+
// Get offset to the DW_AT_location attribute.
90+
uint64_t AttrOffset =
91+
Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U);
92+
93+
// Get value of the DW_AT_location attribute.
94+
std::optional<DWARFFormValue> LocationValue =
95+
Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U);
96+
if (!LocationValue)
97+
return std::make_pair(false, std::nullopt);
98+
99+
// Check that DW_AT_location attribute is of 'exprloc' class.
100+
// Handling value of location expressions for attributes of 'loclist'
101+
// class is not implemented yet.
102+
std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock();
103+
if (!Expr)
104+
return std::make_pair(false, std::nullopt);
105+
106+
// Parse 'exprloc' expression.
107+
DataExtractor Data(toStringRef(*Expr), U->getContext().isLittleEndian(),
108+
U->getAddressByteSize());
109+
DWARFExpression Expression(Data, U->getAddressByteSize(),
110+
U->getFormParams().Format);
111+
112+
bool HasLocationAddress = false;
113+
uint64_t CurExprOffset = 0;
114+
for (DWARFExpression::iterator It = Expression.begin();
115+
It != Expression.end(); ++It) {
116+
DWARFExpression::iterator NextIt = It;
117+
++NextIt;
118+
119+
const DWARFExpression::Operation &Op = *It;
120+
switch (Op.getCode()) {
121+
case dwarf::DW_OP_const2u:
122+
case dwarf::DW_OP_const4u:
123+
case dwarf::DW_OP_const8u:
124+
case dwarf::DW_OP_const2s:
125+
case dwarf::DW_OP_const4s:
126+
case dwarf::DW_OP_const8s:
127+
if (NextIt == Expression.end() || !isTlsAddressCode(NextIt->getCode()))
128+
break;
129+
[[fallthrough]];
130+
case dwarf::DW_OP_addr: {
131+
HasLocationAddress = true;
132+
// Check relocation for the address.
133+
if (std::optional<int64_t> RelocAdjustment =
134+
getExprOpAddressRelocAdjustment(*U, Op,
135+
AttrOffset + CurExprOffset,
136+
AttrOffset + Op.getEndOffset()))
137+
return std::make_pair(HasLocationAddress, *RelocAdjustment);
138+
} break;
139+
case dwarf::DW_OP_constx:
140+
case dwarf::DW_OP_addrx: {
141+
HasLocationAddress = true;
142+
if (std::optional<uint64_t> AddressOffset =
143+
DIE.getDwarfUnit()->getIndexedAddressOffset(
144+
Op.getRawOperand(0))) {
145+
// Check relocation for the address.
146+
if (std::optional<int64_t> RelocAdjustment =
147+
getExprOpAddressRelocAdjustment(
148+
*U, Op, *AddressOffset,
149+
*AddressOffset +
150+
DIE.getDwarfUnit()->getAddressByteSize()))
151+
return std::make_pair(HasLocationAddress, *RelocAdjustment);
152+
}
153+
} break;
154+
default: {
155+
// Nothing to do.
156+
} break;
157+
}
158+
CurExprOffset = Op.getEndOffset();
159+
}
160+
161+
return std::make_pair(HasLocationAddress, std::nullopt);
162+
}
163+
164+
protected:
165+
inline bool isTlsAddressCode(uint8_t DW_OP_Code) {
166+
return DW_OP_Code == dwarf::DW_OP_form_tls_address ||
167+
DW_OP_Code == dwarf::DW_OP_GNU_push_tls_address;
168+
}
65169
};
66170

67171
} // end of namespace dwarflinker_parallel

llvm/include/llvm/DWARFLinkerParallel/DWARFFile.h

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,7 @@ class DWARFFile {
3030
DWARFFile(StringRef Name, std::unique_ptr<DWARFContext> Dwarf,
3131
std::unique_ptr<AddressesMap> Addresses,
3232
const std::vector<std::string> &Warnings,
33-
UnloadCallbackTy UnloadFunc = nullptr)
34-
: FileName(Name), Dwarf(std::move(Dwarf)),
35-
Addresses(std::move(Addresses)), Warnings(Warnings),
36-
UnloadFunc(UnloadFunc) {
37-
if (this->Dwarf)
38-
Endianess = this->Dwarf->isLittleEndian() ? support::endianness::little
39-
: support::endianness::big;
40-
}
33+
UnloadCallbackTy UnloadFunc = nullptr);
4134

4235
/// Object file name.
4336
StringRef FileName;
@@ -51,9 +44,6 @@ class DWARFFile {
5144
/// Warnings for object file.
5245
const std::vector<std::string> &Warnings;
5346

54-
/// Endiannes of source DWARF information.
55-
support::endianness Endianess = support::endianness::little;
56-
5747
/// Callback to the module keeping object file to unload.
5848
UnloadCallbackTy UnloadFunc;
5949

llvm/include/llvm/DWARFLinkerParallel/StringPool.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace dwarflinker_parallel {
2121

2222
/// StringEntry keeps data of the string: the length, external offset
2323
/// and a string body which is placed right after StringEntry.
24-
using StringEntry = StringMapEntry<DwarfStringPoolEntry *>;
24+
using StringEntry = StringMapEntry<std::nullopt_t>;
2525

2626
class StringPoolEntryInfo {
2727
public:
@@ -64,6 +64,8 @@ class StringPool
6464

6565
parallel::PerThreadBumpPtrAllocator &getAllocatorRef() { return Allocator; }
6666

67+
void clear() { Allocator.Reset(); }
68+
6769
private:
6870
parallel::PerThreadBumpPtrAllocator Allocator;
6971
};

llvm/include/llvm/DWARFLinkerParallel/StringTable.h

Lines changed: 0 additions & 88 deletions
This file was deleted.

llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class DwarfStreamer;
2222

2323
class DWARFDebugMacro {
2424
friend DwarfStreamer;
25+
friend dwarflinker_parallel::CompileUnit;
2526

2627
/// DWARFv5 section 6.3.1 Macro Information Header.
2728
enum HeaderFlagMask {

llvm/lib/DWARFLinker/DWARFLinker.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,10 @@ DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr,
444444

445445
const DWARFExpression::Operation &Op = *It;
446446
switch (Op.getCode()) {
447+
case dwarf::DW_OP_const2u:
447448
case dwarf::DW_OP_const4u:
448449
case dwarf::DW_OP_const8u:
450+
case dwarf::DW_OP_const2s:
449451
case dwarf::DW_OP_const4s:
450452
case dwarf::DW_OP_const8s:
451453
if (NextIt == Expression.end() || !isTlsAddressCode(NextIt->getCode()))

llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,10 @@ void CompileUnit::markEverythingAsKept() {
9797
++NextIt;
9898

9999
switch (It->getCode()) {
100+
case dwarf::DW_OP_const2u:
100101
case dwarf::DW_OP_const4u:
101102
case dwarf::DW_OP_const8u:
103+
case dwarf::DW_OP_const2s:
102104
case dwarf::DW_OP_const4s:
103105
case dwarf::DW_OP_const8s:
104106
if (NextIt == Expression.end() ||

0 commit comments

Comments
 (0)