JITLinkTestCommon.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. //===------- JITLinkTestCommon.cpp - Common code for JITLink tests --------===//
  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. #include "JITLinkTestCommon.h"
  9. #include "llvm/MC/MCCodeEmitter.h"
  10. #include "llvm/MC/MCObjectWriter.h"
  11. #include "llvm/MC/MCParser/MCTargetAsmParser.h"
  12. #include "llvm/Support/TargetSelect.h"
  13. using namespace llvm::jitlink;
  14. namespace llvm {
  15. Expected<std::unique_ptr<JITLinkTestCommon::TestResources>>
  16. JITLinkTestCommon::TestResources::Create(StringRef AsmSrc, StringRef TripleStr,
  17. bool PIC, bool LargeCodeModel,
  18. MCTargetOptions Options) {
  19. Error Err = Error::success();
  20. auto R = std::unique_ptr<TestResources>(new TestResources(
  21. AsmSrc, TripleStr, PIC, LargeCodeModel, std::move(Options), Err));
  22. if (Err)
  23. return std::move(Err);
  24. return std::move(R);
  25. }
  26. MemoryBufferRef
  27. JITLinkTestCommon::TestResources::getTestObjectBufferRef() const {
  28. return MemoryBufferRef(StringRef(ObjBuffer.data(), ObjBuffer.size()),
  29. "Test object");
  30. }
  31. JITLinkTestCommon::TestResources::TestResources(StringRef AsmSrc,
  32. StringRef TripleStr, bool PIC,
  33. bool LargeCodeModel,
  34. MCTargetOptions Options,
  35. Error &Err)
  36. : ObjStream(ObjBuffer), Options(std::move(Options)) {
  37. ErrorAsOutParameter _(&Err);
  38. Triple TT(Triple::normalize(TripleStr));
  39. if (auto Err2 = initializeTripleSpecifics(TT)) {
  40. Err = std::move(Err2);
  41. return;
  42. }
  43. initializeTestSpecifics(AsmSrc, TT, PIC, LargeCodeModel);
  44. }
  45. Error JITLinkTestCommon::TestResources::initializeTripleSpecifics(Triple &TT) {
  46. std::string ErrorMsg;
  47. TheTarget = TargetRegistry::lookupTarget("", TT, ErrorMsg);
  48. if (!TheTarget)
  49. return make_error<StringError>(ErrorMsg, inconvertibleErrorCode());
  50. MRI.reset(TheTarget->createMCRegInfo(TT.getTriple()));
  51. if (!MRI)
  52. report_fatal_error("Could not build MCRegisterInfo for triple");
  53. MAI.reset(TheTarget->createMCAsmInfo(*MRI, TT.getTriple()));
  54. if (!MAI)
  55. report_fatal_error("Could not build MCAsmInfo for triple");
  56. MCII.reset(TheTarget->createMCInstrInfo());
  57. if (!MCII)
  58. report_fatal_error("Could not build MCInstrInfo for triple");
  59. STI.reset(TheTarget->createMCSubtargetInfo(TT.getTriple(), "", ""));
  60. if (!STI)
  61. report_fatal_error("Could not build MCSubtargetInfo for triple");
  62. DisCtx = std::make_unique<MCContext>(MAI.get(), MRI.get(), nullptr);
  63. Dis.reset(TheTarget->createMCDisassembler(*STI, *DisCtx));
  64. if (!Dis)
  65. report_fatal_error("Could not build MCDisassembler");
  66. return Error::success();
  67. }
  68. void JITLinkTestCommon::TestResources::initializeTestSpecifics(
  69. StringRef AsmSrc, const Triple &TT, bool PIC, bool LargeCodeModel) {
  70. SrcMgr.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(AsmSrc), SMLoc());
  71. AsCtx = std::make_unique<MCContext>(MAI.get(), MRI.get(), &MOFI, &SrcMgr);
  72. MOFI.InitMCObjectFileInfo(TT, PIC, *AsCtx, LargeCodeModel);
  73. std::unique_ptr<MCCodeEmitter> CE(
  74. TheTarget->createMCCodeEmitter(*MCII, *MRI, *AsCtx));
  75. if (!CE)
  76. report_fatal_error("Could not build MCCodeEmitter");
  77. std::unique_ptr<MCAsmBackend> MAB(
  78. TheTarget->createMCAsmBackend(*STI, *MRI, Options));
  79. if (!MAB)
  80. report_fatal_error("Could not build MCAsmBackend for test");
  81. std::unique_ptr<MCObjectWriter> MOW(MAB->createObjectWriter(ObjStream));
  82. MOS.reset(TheTarget->createMCObjectStreamer(
  83. TT, *AsCtx, std::move(MAB), std::move(MOW), std::move(CE), *STI,
  84. Options.MCRelaxAll, Options.MCIncrementalLinkerCompatible, false));
  85. std::unique_ptr<MCAsmParser> MAP(
  86. createMCAsmParser(SrcMgr, *AsCtx, *MOS, *MAI));
  87. std::unique_ptr<MCTargetAsmParser> TAP(
  88. TheTarget->createMCAsmParser(*STI, *MAP, *MCII, Options));
  89. if (!TAP)
  90. report_fatal_error("Could not build MCTargetAsmParser for test");
  91. MAP->setTargetParser(*TAP);
  92. if (MAP->Run(false))
  93. report_fatal_error("Failed to parse test case");
  94. }
  95. JITLinkTestCommon::TestJITLinkContext::TestJITLinkContext(
  96. TestResources &TR, TestCaseFunction TestCase)
  97. : TR(TR), TestCase(std::move(TestCase)) {}
  98. JITLinkTestCommon::TestJITLinkContext &
  99. JITLinkTestCommon::TestJITLinkContext::setMemoryManager(
  100. std::unique_ptr<JITLinkMemoryManager> MM) {
  101. assert(!MemMgr && "Memory manager already set");
  102. MemMgr = std::move(MM);
  103. return *this;
  104. }
  105. JITLinkMemoryManager &
  106. JITLinkTestCommon::TestJITLinkContext::getMemoryManager() {
  107. if (!MemMgr)
  108. MemMgr = std::make_unique<InProcessMemoryManager>();
  109. return *MemMgr;
  110. }
  111. MemoryBufferRef JITLinkTestCommon::TestJITLinkContext::getObjectBuffer() const {
  112. return TR.getTestObjectBufferRef();
  113. }
  114. void JITLinkTestCommon::TestJITLinkContext::notifyFailed(Error Err) {
  115. ADD_FAILURE() << "Unexpected failure: " << toString(std::move(Err));
  116. }
  117. void JITLinkTestCommon::TestJITLinkContext::lookup(
  118. const DenseSet<StringRef> &Symbols,
  119. std::unique_ptr<JITLinkAsyncLookupContinuation> LC) {
  120. jitlink::AsyncLookupResult LookupResult;
  121. DenseSet<StringRef> MissingSymbols;
  122. for (const auto &Symbol : Symbols) {
  123. auto I = Externals.find(Symbol);
  124. if (I != Externals.end())
  125. LookupResult[Symbol] = I->second;
  126. else
  127. MissingSymbols.insert(Symbol);
  128. }
  129. if (MissingSymbols.empty())
  130. LC->run(std::move(LookupResult));
  131. else {
  132. std::string ErrMsg;
  133. {
  134. raw_string_ostream ErrMsgStream(ErrMsg);
  135. ErrMsgStream << "Failed to resolve external symbols: [";
  136. for (auto &Sym : MissingSymbols)
  137. ErrMsgStream << " " << Sym;
  138. ErrMsgStream << " ]\n";
  139. }
  140. LC->run(
  141. make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()));
  142. }
  143. }
  144. void JITLinkTestCommon::TestJITLinkContext::notifyResolved(LinkGraph &G) {
  145. if (NotifyResolved)
  146. NotifyResolved(G);
  147. }
  148. void JITLinkTestCommon::TestJITLinkContext::notifyFinalized(
  149. std::unique_ptr<JITLinkMemoryManager::Allocation> A) {
  150. if (NotifyFinalized)
  151. NotifyFinalized(std::move(A));
  152. }
  153. Error JITLinkTestCommon::TestJITLinkContext::modifyPassConfig(
  154. const Triple &TT, PassConfiguration &Config) {
  155. if (TestCase)
  156. Config.PostFixupPasses.push_back([&](LinkGraph &G) -> Error {
  157. TestCase(G);
  158. return Error::success();
  159. });
  160. return Error::success();
  161. }
  162. JITLinkTestCommon::JITLinkTestCommon() { initializeLLVMTargets(); }
  163. Expected<std::pair<MCInst, size_t>>
  164. JITLinkTestCommon::disassemble(const MCDisassembler &Dis, jitlink::Block &B,
  165. size_t Offset) {
  166. ArrayRef<uint8_t> InstBuffer(
  167. reinterpret_cast<const uint8_t *>(B.getContent().data()) + Offset,
  168. B.getContent().size() - Offset);
  169. MCInst Inst;
  170. uint64_t InstSize;
  171. auto Status =
  172. Dis.getInstruction(Inst, InstSize, InstBuffer, 0, nulls(), nulls());
  173. if (Status != MCDisassembler::Success)
  174. return make_error<StringError>("Could not disassemble instruction",
  175. inconvertibleErrorCode());
  176. return std::make_pair(Inst, InstSize);
  177. }
  178. Expected<int64_t> JITLinkTestCommon::decodeImmediateOperand(
  179. const MCDisassembler &Dis, jitlink::Block &B, size_t OpIdx, size_t Offset) {
  180. auto InstAndSize = disassemble(Dis, B, Offset);
  181. if (!InstAndSize)
  182. return InstAndSize.takeError();
  183. if (OpIdx >= InstAndSize->first.getNumOperands())
  184. return make_error<StringError>("Invalid operand index",
  185. inconvertibleErrorCode());
  186. auto &Op = InstAndSize->first.getOperand(OpIdx);
  187. if (!Op.isImm())
  188. return make_error<StringError>("Operand at index is not immediate",
  189. inconvertibleErrorCode());
  190. return Op.getImm();
  191. }
  192. bool JITLinkTestCommon::AreTargetsInitialized = false;
  193. void JITLinkTestCommon::initializeLLVMTargets() {
  194. if (!AreTargetsInitialized) {
  195. InitializeAllTargets();
  196. InitializeAllTargetMCs();
  197. InitializeAllAsmParsers();
  198. InitializeAllAsmPrinters();
  199. InitializeAllDisassemblers();
  200. AreTargetsInitialized = true;
  201. }
  202. }
  203. } // end namespace llvm