Skip to content

Commit c7ef2b3

Browse files
Store DynFixupInfos as ManagedStatic to achieve lazy init
1 parent a6512e2 commit c7ef2b3

File tree

4 files changed

+98
-71
lines changed

4 files changed

+98
-71
lines changed

llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,9 @@ struct HalfWords {
164164
const uint16_t Lo; // Second halfword
165165
};
166166

167-
/// Initialize the lookup table for dynamic FixupInfo checks, e.g. checkOpcode()
168-
void populateFixupInfos();
169-
170167
/// FixupInfo base class is required for dynamic lookups.
171168
struct FixupInfoBase {
169+
static const FixupInfoBase *getDynFixupInfo(Edge::Kind K);
172170
virtual ~FixupInfoBase() {}
173171
};
174172

llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,6 @@ createLinkGraphFromELFObject_aarch32(MemoryBufferRef ObjectBuffer) {
232232
<< ObjectBuffer.getBufferIdentifier() << "...\n";
233233
});
234234

235-
aarch32::populateFixupInfos();
236-
237235
auto ELFObj = ObjectFile::createELFObjectFile(ObjectBuffer);
238236
if (!ELFObj)
239237
return ELFObj.takeError();

llvm/lib/ExecutionEngine/JITLink/aarch32.cpp

Lines changed: 74 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
1818
#include "llvm/Object/ELFObjectFile.h"
1919
#include "llvm/Support/Endian.h"
20+
#include "llvm/Support/ManagedStatic.h"
2021
#include "llvm/Support/MathExtras.h"
2122

2223
#define DEBUG_TYPE "jitlink"
@@ -249,12 +250,6 @@ Error makeUnexpectedOpcodeError(const LinkGraph &G, const ArmRelocation &R,
249250
static_cast<uint32_t>(R.Wd), G.getEdgeKindName(Kind)));
250251
}
251252

252-
static auto &getFixupInfoTable() {
253-
static constexpr size_t Items = LastRelocation + 1;
254-
static std::array<std::unique_ptr<FixupInfoBase>, Items> FixupInfoTable;
255-
return FixupInfoTable;
256-
}
257-
258253
template <EdgeKind_aarch32 K> constexpr bool isArm() {
259254
return FirstArmRelocation <= K && K <= LastArmRelocation;
260255
}
@@ -278,68 +273,81 @@ static bool checkOpcodeThumb(uint16_t Hi, uint16_t Lo) {
278273
(Lo & FixupInfo<K>::OpcodeMask.Lo) == FixupInfo<K>::Opcode.Lo;
279274
}
280275

281-
template <EdgeKind_aarch32 K>
282-
static std::unique_ptr<FixupInfoBase> initFixupInfo() {
283-
auto Entry = std::make_unique<FixupInfo<K>>();
284-
if constexpr (hasOpcode<K>(0)) {
285-
static_assert(isArm<K>() != isThumb<K>(), "Classes are mutually exclusive");
286-
if constexpr (isArm<K>())
287-
Entry->checkOpcode = checkOpcodeArm<K>;
288-
if constexpr (isThumb<K>())
289-
Entry->checkOpcode = checkOpcodeThumb<K>;
276+
class FixupInfoTable {
277+
static constexpr size_t Items = LastRelocation + 1;
278+
279+
public:
280+
FixupInfoTable() {
281+
populateEntries<FirstArmRelocation, LastArmRelocation>();
282+
populateEntries<FirstThumbRelocation, LastThumbRelocation>();
290283
}
291-
return Entry;
292-
}
293284

294-
template <EdgeKind_aarch32 K, EdgeKind_aarch32 LastK, typename TableT>
295-
void populateFixupInfos(TableT &Table) {
296-
assert(K < Table.size() && "Index out of range");
297-
assert(Table.at(K) == nullptr && "Initialized entries are immutable");
298-
Table[K] = initFixupInfo<K>();
299-
if constexpr (K < LastK) {
300-
constexpr auto Next = static_cast<EdgeKind_aarch32>(K + 1);
301-
populateFixupInfos<Next, LastK>(Table);
285+
const FixupInfoBase *getEntry(Edge::Kind K) {
286+
assert(K < Data.size() && "Index out of bounds");
287+
return Data.at(K).get();
302288
}
303-
}
304-
} // namespace
305289

306-
void populateFixupInfos() {
307-
static std::once_flag Flag;
308-
std::call_once(Flag, []() {
309-
auto &Table = getFixupInfoTable();
310-
populateFixupInfos<FirstArmRelocation, LastArmRelocation>(Table);
311-
populateFixupInfos<FirstThumbRelocation, LastThumbRelocation>(Table);
312-
});
313-
}
290+
private:
291+
template <EdgeKind_aarch32 K, EdgeKind_aarch32 LastK>
292+
void populateEntries() {
293+
assert(K < Data.size() && "Index out of range");
294+
assert(Data.at(K) == nullptr && "Initialized entries are immutable");
295+
Data[K] = initEntry<K>();
296+
if constexpr (K < LastK) {
297+
constexpr auto Next = static_cast<EdgeKind_aarch32>(K + 1);
298+
populateEntries<Next, LastK>();
299+
}
300+
}
314301

315-
template <typename TargetModeSubclass>
316-
static const TargetModeSubclass *const getDynFixupInfo(Edge::Kind K) {
317-
assert(K >= Edge::FirstRelocation && "Invalid value for edge kind");
318-
assert(K <= LastRelocation && "Invalid value for edge kind");
319-
assert(getFixupInfoTable().at(K) && "Please call populateFixupInfos() first");
320-
return static_cast<TargetModeSubclass *>(getFixupInfoTable().at(K).get());
321-
}
302+
template <EdgeKind_aarch32 K>
303+
static std::unique_ptr<FixupInfoBase> initEntry() {
304+
auto Entry = std::make_unique<FixupInfo<K>>();
305+
if constexpr (hasOpcode<K>(0)) {
306+
static_assert(isArm<K>() != isThumb<K>(), "Classes are mutually exclusive");
307+
if constexpr (isArm<K>())
308+
Entry->checkOpcode = checkOpcodeArm<K>;
309+
if constexpr (isThumb<K>())
310+
Entry->checkOpcode = checkOpcodeThumb<K>;
311+
}
312+
return Entry;
313+
}
322314

323-
static bool checkOpcode(const ArmRelocation &R, Edge::Kind Kind) {
315+
private:
316+
std::array<std::unique_ptr<FixupInfoBase>, Items> Data;
317+
};
318+
319+
} // namespace
320+
321+
ManagedStatic<FixupInfoTable> DynFixupInfos;
322+
323+
static Error
324+
checkOpcode(LinkGraph &G, const ArmRelocation &R, Edge::Kind Kind) {
324325
assert(Kind >= FirstArmRelocation && Kind <= LastArmRelocation &&
325-
"Edge kind is no Arm relocation");
326-
const FixupInfoArm *const Info = getDynFixupInfo<FixupInfoArm>(Kind);
327-
if (LLVM_LIKELY(Info) && LLVM_LIKELY(Info->checkOpcode))
328-
return Info->checkOpcode(R.Wd);
329-
LLVM_DEBUG(dbgs() << "Can not perform Opcode check for aarch32 edge kind "
330-
<< getEdgeKindName(Kind));
331-
return true;
326+
"Edge kind must be Arm relocation");
327+
const FixupInfoBase *Entry = DynFixupInfos->getEntry(Kind);
328+
const FixupInfoArm &Info = *static_cast<const FixupInfoArm *>(Entry);
329+
assert(Info.checkOpcode && "Opcode check is mandatory for Arm edges");
330+
if (!Info.checkOpcode(R.Wd))
331+
return makeUnexpectedOpcodeError(G, R, Kind);
332+
333+
return Error::success();
332334
}
333335

334-
static bool checkOpcode(const ThumbRelocation &R, Edge::Kind Kind) {
336+
static Error
337+
checkOpcode(LinkGraph &G, const ThumbRelocation &R, Edge::Kind Kind) {
335338
assert(Kind >= FirstThumbRelocation && Kind <= LastThumbRelocation &&
336-
"Edge kind is no Thumb relocation");
337-
const FixupInfoThumb *const Info = getDynFixupInfo<FixupInfoThumb>(Kind);
338-
if (LLVM_LIKELY(Info) && LLVM_LIKELY(Info->checkOpcode))
339-
return Info->checkOpcode(R.Hi, R.Lo);
340-
LLVM_DEBUG(dbgs() << "Can not perform Opcode check for aarch32 edge kind "
341-
<< getEdgeKindName(Kind));
342-
return true;
339+
"Edge kind must be Thumb relocation");
340+
const FixupInfoBase *Entry = DynFixupInfos->getEntry(Kind);
341+
const FixupInfoThumb &Info = *static_cast<const FixupInfoThumb *>(Entry);
342+
assert(Info.checkOpcode && "Opcode check is mandatory for Thumb edges");
343+
if (!Info.checkOpcode(R.Hi, R.Lo))
344+
return makeUnexpectedOpcodeError(G, R, Kind);
345+
346+
return Error::success();
347+
}
348+
349+
const FixupInfoBase *FixupInfoBase::getDynFixupInfo(Edge::Kind K) {
350+
return DynFixupInfos->getEntry(K);
343351
}
344352

345353
template <EdgeKind_aarch32 Kind>
@@ -408,8 +416,8 @@ Expected<int64_t> readAddendData(LinkGraph &G, Block &B, Edge::OffsetT Offset,
408416
Expected<int64_t> readAddendArm(LinkGraph &G, Block &B, Edge::OffsetT Offset,
409417
Edge::Kind Kind) {
410418
ArmRelocation R(B.getContent().data() + Offset);
411-
if (!checkOpcode(R, Kind))
412-
return makeUnexpectedOpcodeError(G, R, Kind);
419+
if (Error Err = checkOpcode(G, R, Kind))
420+
return std::move(Err);
413421

414422
switch (Kind) {
415423
case Arm_Call:
@@ -431,8 +439,8 @@ Expected<int64_t> readAddendArm(LinkGraph &G, Block &B, Edge::OffsetT Offset,
431439
Expected<int64_t> readAddendThumb(LinkGraph &G, Block &B, Edge::OffsetT Offset,
432440
Edge::Kind Kind, const ArmConfig &ArmCfg) {
433441
ThumbRelocation R(B.getContent().data() + Offset);
434-
if (!checkOpcode(R, Kind))
435-
return makeUnexpectedOpcodeError(G, R, Kind);
442+
if (Error Err = checkOpcode(G, R, Kind))
443+
return std::move(Err);
436444

437445
switch (Kind) {
438446
case Thumb_Call:
@@ -509,8 +517,8 @@ Error applyFixupData(LinkGraph &G, Block &B, const Edge &E) {
509517
Error applyFixupArm(LinkGraph &G, Block &B, const Edge &E) {
510518
WritableArmRelocation R(B.getAlreadyMutableContent().data() + E.getOffset());
511519
Edge::Kind Kind = E.getKind();
512-
if (!checkOpcode(R, Kind))
513-
return makeUnexpectedOpcodeError(G, R, Kind);
520+
if (Error Err = checkOpcode(G, R, Kind))
521+
return Err;
514522

515523
uint64_t FixupAddress = (B.getAddress() + E.getOffset()).getValue();
516524
int64_t Addend = E.getAddend();
@@ -585,8 +593,8 @@ Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
585593
WritableThumbRelocation R(B.getAlreadyMutableContent().data() +
586594
E.getOffset());
587595
Edge::Kind Kind = E.getKind();
588-
if (!checkOpcode(R, Kind))
589-
return makeUnexpectedOpcodeError(G, R, Kind);
596+
if (Error Err = checkOpcode(G, R, Kind))
597+
return Err;
590598

591599
uint64_t FixupAddress = (B.getAddress() + E.getOffset()).getValue();
592600
int64_t Addend = E.getAddend();

llvm/unittests/ExecutionEngine/JITLink/AArch32Tests.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,29 @@ TEST(AArch32_ELF, EdgeKinds) {
6767
}
6868
}
6969

70+
TEST(AArch32_ELF, DynFixupInfos) {
71+
// We can do an opcode check for all Arm edges
72+
for (Edge::Kind K = FirstArmRelocation; K < LastArmRelocation; K += 1) {
73+
const auto *Info = FixupInfoBase::getDynFixupInfo(K);
74+
EXPECT_NE(Info, nullptr);
75+
const auto *InfoArm = static_cast<const FixupInfoArm *>(Info);
76+
EXPECT_NE(InfoArm->checkOpcode, nullptr);
77+
EXPECT_FALSE(InfoArm->checkOpcode(0x00000000));
78+
}
79+
// We can do an opcode check for all Thumb edges
80+
for (Edge::Kind K = FirstThumbRelocation; K < LastThumbRelocation; K += 1) {
81+
const auto *Info = FixupInfoBase::getDynFixupInfo(K);
82+
EXPECT_NE(Info, nullptr);
83+
const auto *InfoThumb = static_cast<const FixupInfoThumb *>(Info);
84+
EXPECT_NE(InfoThumb->checkOpcode, nullptr);
85+
EXPECT_FALSE(InfoThumb->checkOpcode(0x0000, 0x0000));
86+
}
87+
// We cannot do it for Data and generic edges
88+
EXPECT_EQ(FixupInfoBase::getDynFixupInfo(FirstDataRelocation), nullptr);
89+
EXPECT_EQ(FixupInfoBase::getDynFixupInfo(Edge::GenericEdgeKind::Invalid),
90+
nullptr);
91+
}
92+
7093
namespace llvm {
7194
namespace jitlink {
7295
namespace aarch32 {

0 commit comments

Comments
 (0)