17
17
#include " llvm/ExecutionEngine/JITLink/JITLink.h"
18
18
#include " llvm/Object/ELFObjectFile.h"
19
19
#include " llvm/Support/Endian.h"
20
+ #include " llvm/Support/ManagedStatic.h"
20
21
#include " llvm/Support/MathExtras.h"
21
22
22
23
#define DEBUG_TYPE " jitlink"
@@ -249,12 +250,6 @@ Error makeUnexpectedOpcodeError(const LinkGraph &G, const ArmRelocation &R,
249
250
static_cast <uint32_t >(R.Wd ), G.getEdgeKindName (Kind)));
250
251
}
251
252
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
-
258
253
template <EdgeKind_aarch32 K> constexpr bool isArm () {
259
254
return FirstArmRelocation <= K && K <= LastArmRelocation;
260
255
}
@@ -278,68 +273,81 @@ static bool checkOpcodeThumb(uint16_t Hi, uint16_t Lo) {
278
273
(Lo & FixupInfo<K>::OpcodeMask.Lo ) == FixupInfo<K>::Opcode.Lo ;
279
274
}
280
275
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>();
290
283
}
291
- return Entry;
292
- }
293
284
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 ();
302
288
}
303
- }
304
- } // namespace
305
289
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
+ }
314
301
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
+ }
322
314
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) {
324
325
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 ();
332
334
}
333
335
334
- static bool checkOpcode (const ThumbRelocation &R, Edge::Kind Kind) {
336
+ static Error
337
+ checkOpcode (LinkGraph &G, const ThumbRelocation &R, Edge::Kind Kind) {
335
338
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);
343
351
}
344
352
345
353
template <EdgeKind_aarch32 Kind>
@@ -408,8 +416,8 @@ Expected<int64_t> readAddendData(LinkGraph &G, Block &B, Edge::OffsetT Offset,
408
416
Expected<int64_t > readAddendArm (LinkGraph &G, Block &B, Edge::OffsetT Offset,
409
417
Edge::Kind Kind) {
410
418
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 );
413
421
414
422
switch (Kind) {
415
423
case Arm_Call:
@@ -431,8 +439,8 @@ Expected<int64_t> readAddendArm(LinkGraph &G, Block &B, Edge::OffsetT Offset,
431
439
Expected<int64_t > readAddendThumb (LinkGraph &G, Block &B, Edge::OffsetT Offset,
432
440
Edge::Kind Kind, const ArmConfig &ArmCfg) {
433
441
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 );
436
444
437
445
switch (Kind) {
438
446
case Thumb_Call:
@@ -509,8 +517,8 @@ Error applyFixupData(LinkGraph &G, Block &B, const Edge &E) {
509
517
Error applyFixupArm (LinkGraph &G, Block &B, const Edge &E) {
510
518
WritableArmRelocation R (B.getAlreadyMutableContent ().data () + E.getOffset ());
511
519
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 ;
514
522
515
523
uint64_t FixupAddress = (B.getAddress () + E.getOffset ()).getValue ();
516
524
int64_t Addend = E.getAddend ();
@@ -585,8 +593,8 @@ Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
585
593
WritableThumbRelocation R (B.getAlreadyMutableContent ().data () +
586
594
E.getOffset ());
587
595
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 ;
590
598
591
599
uint64_t FixupAddress = (B.getAddress () + E.getOffset ()).getValue ();
592
600
int64_t Addend = E.getAddend ();
0 commit comments