JITLinkTestCommon.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. //===---- JITLinkTestCommon.h - Utilities for Orc Unit Tests ----*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Common utilities for JITLink unit tests.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef LLVM_UNITTESTS_EXECUTIONENGINE_JITLINK_JITLINKTESTCOMMON_H
  13. #define LLVM_UNITTESTS_EXECUTIONENGINE_JITLINK_JITLINKTESTCOMMON_H
  14. #include "llvm/ADT/Triple.h"
  15. #include "llvm/ExecutionEngine/JITLink/JITLink.h"
  16. #include "llvm/MC/MCAsmBackend.h"
  17. #include "llvm/MC/MCAsmInfo.h"
  18. #include "llvm/MC/MCContext.h"
  19. #include "llvm/MC/MCDisassembler/MCDisassembler.h"
  20. #include "llvm/MC/MCInstrInfo.h"
  21. #include "llvm/MC/MCObjectFileInfo.h"
  22. #include "llvm/MC/MCObjectStreamer.h"
  23. #include "llvm/MC/MCParser/MCAsmParser.h"
  24. #include "llvm/MC/MCRegisterInfo.h"
  25. #include "llvm/MC/MCSubtargetInfo.h"
  26. #include "llvm/MC/MCTargetOptions.h"
  27. #include "llvm/Support/Endian.h"
  28. #include "llvm/Support/SourceMgr.h"
  29. #include "llvm/Support/TargetRegistry.h"
  30. #include "gtest/gtest.h"
  31. namespace llvm {
  32. class JITLinkTestCommon {
  33. public:
  34. class TestResources {
  35. public:
  36. static Expected<std::unique_ptr<TestResources>>
  37. Create(StringRef AsmSrc, StringRef TripleStr, bool PIC, bool LargeCodeModel,
  38. MCTargetOptions Options);
  39. MemoryBufferRef getTestObjectBufferRef() const;
  40. const MCDisassembler &getDisassembler() const { return *Dis; }
  41. private:
  42. TestResources(StringRef AsmSrc, StringRef TripleStr, bool PIC,
  43. bool LargeCodeModel, MCTargetOptions Options, Error &Err);
  44. Error initializeTripleSpecifics(Triple &TT);
  45. void initializeTestSpecifics(StringRef AsmSource, const Triple &TT,
  46. bool PIC, bool LargeCodeModel);
  47. const Target *TheTarget = nullptr;
  48. SourceMgr SrcMgr;
  49. SmallVector<char, 0> ObjBuffer;
  50. raw_svector_ostream ObjStream;
  51. MCTargetOptions Options;
  52. std::unique_ptr<MCRegisterInfo> MRI;
  53. std::unique_ptr<MCAsmInfo> MAI;
  54. std::unique_ptr<MCInstrInfo> MCII;
  55. std::unique_ptr<MCSubtargetInfo> STI;
  56. MCObjectFileInfo MOFI;
  57. std::unique_ptr<MCContext> AsCtx;
  58. std::unique_ptr<MCStreamer> MOS;
  59. std::unique_ptr<MCContext> DisCtx;
  60. std::unique_ptr<const MCDisassembler> Dis;
  61. };
  62. class TestJITLinkContext : public jitlink::JITLinkContext {
  63. public:
  64. using TestCaseFunction = std::function<void(jitlink::LinkGraph &)>;
  65. using NotifyResolvedFunction = std::function<void(jitlink::LinkGraph &G)>;
  66. using NotifyFinalizedFunction = std::function<void(
  67. std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation>)>;
  68. TestJITLinkContext(TestResources &TR, TestCaseFunction TestCase);
  69. StringMap<JITEvaluatedSymbol> &externals() { return Externals; }
  70. TestJITLinkContext &
  71. setNotifyResolved(NotifyResolvedFunction NotifyResolved);
  72. TestJITLinkContext &
  73. setNotifyFinalized(NotifyFinalizedFunction NotifyFinalized);
  74. TestJITLinkContext &
  75. setMemoryManager(std::unique_ptr<jitlink::JITLinkMemoryManager> MM);
  76. jitlink::JITLinkMemoryManager &getMemoryManager() override;
  77. MemoryBufferRef getObjectBuffer() const override;
  78. void notifyFailed(Error Err) override;
  79. void lookup(
  80. const DenseSet<StringRef> &Symbols,
  81. std::unique_ptr<jitlink::JITLinkAsyncLookupContinuation> LC) override;
  82. void notifyResolved(jitlink::LinkGraph &G) override;
  83. void notifyFinalized(
  84. std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation> A) override;
  85. Error modifyPassConfig(const Triple &TT,
  86. jitlink::PassConfiguration &Config) override;
  87. private:
  88. TestResources &TR;
  89. TestCaseFunction TestCase;
  90. NotifyResolvedFunction NotifyResolved;
  91. NotifyFinalizedFunction NotifyFinalized;
  92. std::unique_ptr<MemoryBuffer> ObjBuffer;
  93. std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr;
  94. StringMap<JITEvaluatedSymbol> Externals;
  95. };
  96. JITLinkTestCommon();
  97. /// Get TestResources for this target/test.
  98. ///
  99. /// If this method fails it is likely because the target is not supported in
  100. /// this build. The test should bail out without failing (possibly logging a
  101. /// diagnostic).
  102. Expected<std::unique_ptr<TestResources>>
  103. getTestResources(StringRef AsmSrc, StringRef Triple, bool PIC,
  104. bool LargeCodeModel, MCTargetOptions Options) const {
  105. return TestResources::Create(AsmSrc, Triple, PIC, LargeCodeModel,
  106. std::move(Options));
  107. }
  108. template <typename T>
  109. static Expected<T> readInt(jitlink::LinkGraph &G, jitlink::Block &B,
  110. size_t Offset = 0) {
  111. if (Offset + sizeof(T) > B.getSize())
  112. return make_error<StringError>("Reading past end of block content",
  113. inconvertibleErrorCode());
  114. return support::endian::read<T, 1>(B.getContent().data() + Offset,
  115. G.getEndianness());
  116. }
  117. template <typename T>
  118. static Expected<T> readInt(jitlink::LinkGraph &G, StringRef SymbolName,
  119. size_t Offset = 0) {
  120. for (auto *Sym : G.defined_symbols()) {
  121. if (Sym->getName() == SymbolName)
  122. return readInt<T>(G, Sym->getBlock(), Sym->getOffset() + Offset);
  123. }
  124. return make_error<StringError>("Symbol \"" + SymbolName + "\" not found",
  125. inconvertibleErrorCode());
  126. }
  127. static Expected<std::pair<MCInst, size_t>>
  128. disassemble(const MCDisassembler &Dis, jitlink::Block &B, size_t Offset = 0);
  129. static Expected<int64_t> decodeImmediateOperand(const MCDisassembler &Dis,
  130. jitlink::Block &B,
  131. size_t OpIdx,
  132. size_t Offset = 0);
  133. static jitlink::Symbol &symbol(jitlink::LinkGraph &G, StringRef Name) {
  134. for (auto *Sym : G.defined_symbols())
  135. if (Sym->getName() == Name)
  136. return *Sym;
  137. for (auto *Sym : G.external_symbols())
  138. if (Sym->getName() == Name)
  139. return *Sym;
  140. for (auto *Sym : G.absolute_symbols())
  141. if (Sym->getName() == Name)
  142. return *Sym;
  143. llvm_unreachable("Name must reference a symbol");
  144. }
  145. static JITTargetAddress symbolAddr(jitlink::LinkGraph &G, StringRef Name) {
  146. return symbol(G, Name).getAddress();
  147. }
  148. template <typename PredT>
  149. static size_t countEdgesMatching(jitlink::Block &B, const PredT &Pred) {
  150. return std::count_if(B.edges().begin(), B.edges().end(), Pred);
  151. }
  152. template <typename PredT>
  153. static size_t countEdgesMatching(jitlink::LinkGraph &G, StringRef Name,
  154. const PredT &Pred) {
  155. return countEdgesMatching(symbol(G, Name), Pred);
  156. }
  157. private:
  158. static bool AreTargetsInitialized;
  159. void initializeLLVMTargets();
  160. DenseMap<StringRef, JITEvaluatedSymbol> Externals;
  161. };
  162. } // end namespace llvm
  163. #endif