OrcCAPITest.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. //===--------------- OrcCAPITest.cpp - Unit tests Orc C API ---------------===//
  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 "OrcTestCommon.h"
  9. #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
  10. #include "llvm-c/Core.h"
  11. #include "llvm-c/OrcBindings.h"
  12. #include "llvm-c/Target.h"
  13. #include "llvm-c/TargetMachine.h"
  14. #include "gtest/gtest.h"
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. namespace llvm {
  19. DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
  20. class OrcCAPIExecutionTest : public testing::Test, public OrcExecutionTest {
  21. protected:
  22. std::unique_ptr<Module> createTestModule(const Triple &TT) {
  23. ModuleBuilder MB(Context, TT.str(), "");
  24. Type *IntTy = Type::getScalarTy<int>(Context);
  25. Function *TestFunc =
  26. MB.createFunctionDecl(FunctionType::get(IntTy, {}, false), "testFunc");
  27. Function *Main = MB.createFunctionDecl(
  28. FunctionType::get(
  29. IntTy,
  30. {IntTy, Type::getInt8PtrTy(Context)->getPointerTo()},
  31. false),
  32. "main");
  33. Main->getBasicBlockList().push_back(BasicBlock::Create(Context));
  34. IRBuilder<> B(&Main->back());
  35. Value* Result = B.CreateCall(TestFunc);
  36. B.CreateRet(Result);
  37. return MB.takeModule();
  38. }
  39. std::unique_ptr<MemoryBuffer> createTestObject() {
  40. orc::SimpleCompiler IRCompiler(*TM);
  41. auto M = createTestModule(TM->getTargetTriple());
  42. M->setDataLayout(TM->createDataLayout());
  43. return IRCompiler(*M);
  44. }
  45. typedef int (*MainFnTy)();
  46. static int myTestFuncImpl() {
  47. return 42;
  48. }
  49. static char *testFuncName;
  50. static uint64_t myResolver(const char *Name, void *Ctx) {
  51. if (!strncmp(Name, testFuncName, 8))
  52. return (uint64_t)&myTestFuncImpl;
  53. return 0;
  54. }
  55. struct CompileContext {
  56. CompileContext() : Compiled(false) { }
  57. OrcCAPIExecutionTest* APIExecTest;
  58. std::unique_ptr<Module> M;
  59. LLVMOrcModuleHandle H;
  60. bool Compiled;
  61. };
  62. static LLVMOrcTargetAddress myCompileCallback(LLVMOrcJITStackRef JITStack,
  63. void *Ctx) {
  64. CompileContext *CCtx = static_cast<CompileContext*>(Ctx);
  65. auto *ET = CCtx->APIExecTest;
  66. CCtx->M = ET->createTestModule(ET->TM->getTargetTriple());
  67. LLVMOrcAddEagerlyCompiledIR(JITStack, &CCtx->H, wrap(CCtx->M.release()),
  68. myResolver, nullptr);
  69. CCtx->Compiled = true;
  70. LLVMOrcTargetAddress MainAddr;
  71. LLVMOrcGetSymbolAddress(JITStack, &MainAddr, "main");
  72. LLVMOrcSetIndirectStubPointer(JITStack, "foo", MainAddr);
  73. return MainAddr;
  74. }
  75. };
  76. char *OrcCAPIExecutionTest::testFuncName = nullptr;
  77. TEST_F(OrcCAPIExecutionTest, TestEagerIRCompilation) {
  78. if (!SupportsJIT)
  79. return;
  80. LLVMOrcJITStackRef JIT =
  81. LLVMOrcCreateInstance(wrap(TM.get()));
  82. std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
  83. LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
  84. LLVMOrcModuleHandle H;
  85. LLVMOrcAddEagerlyCompiledIR(JIT, &H, wrap(M.release()), myResolver, nullptr);
  86. // get symbol address searching the entire stack
  87. {
  88. LLVMOrcTargetAddress MainAddr;
  89. LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
  90. MainFnTy MainFn = (MainFnTy)MainAddr;
  91. int Result = MainFn();
  92. EXPECT_EQ(Result, 42)
  93. << "Eagerly JIT'd code did not return expected result";
  94. }
  95. // and then just searching a single handle
  96. {
  97. LLVMOrcTargetAddress MainAddr;
  98. LLVMOrcGetSymbolAddressIn(JIT, &MainAddr, H, "main");
  99. MainFnTy MainFn = (MainFnTy)MainAddr;
  100. int Result = MainFn();
  101. EXPECT_EQ(Result, 42)
  102. << "Eagerly JIT'd code did not return expected result";
  103. }
  104. LLVMOrcRemoveModule(JIT, H);
  105. LLVMOrcDisposeMangledSymbol(testFuncName);
  106. LLVMOrcDisposeInstance(JIT);
  107. }
  108. TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) {
  109. if (!SupportsIndirection)
  110. return;
  111. LLVMOrcJITStackRef JIT =
  112. LLVMOrcCreateInstance(wrap(TM.get()));
  113. std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
  114. LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
  115. LLVMOrcModuleHandle H;
  116. LLVMOrcAddLazilyCompiledIR(JIT, &H, wrap(M.release()), myResolver, nullptr);
  117. LLVMOrcTargetAddress MainAddr;
  118. LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
  119. MainFnTy MainFn = (MainFnTy)MainAddr;
  120. int Result = MainFn();
  121. EXPECT_EQ(Result, 42)
  122. << "Lazily JIT'd code did not return expected result";
  123. LLVMOrcRemoveModule(JIT, H);
  124. LLVMOrcDisposeMangledSymbol(testFuncName);
  125. LLVMOrcDisposeInstance(JIT);
  126. }
  127. TEST_F(OrcCAPIExecutionTest, TestAddObjectFile) {
  128. if (!SupportsJIT)
  129. return;
  130. auto ObjBuffer = createTestObject();
  131. LLVMOrcJITStackRef JIT =
  132. LLVMOrcCreateInstance(wrap(TM.get()));
  133. LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
  134. LLVMOrcModuleHandle H;
  135. LLVMOrcAddObjectFile(JIT, &H, wrap(ObjBuffer.release()), myResolver, nullptr);
  136. LLVMOrcTargetAddress MainAddr;
  137. LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
  138. MainFnTy MainFn = (MainFnTy)MainAddr;
  139. int Result = MainFn();
  140. EXPECT_EQ(Result, 42)
  141. << "Lazily JIT'd code did not return expected result";
  142. LLVMOrcRemoveModule(JIT, H);
  143. LLVMOrcDisposeMangledSymbol(testFuncName);
  144. LLVMOrcDisposeInstance(JIT);
  145. }
  146. TEST_F(OrcCAPIExecutionTest, TestDirectCallbacksAPI) {
  147. if (!SupportsIndirection)
  148. return;
  149. LLVMOrcJITStackRef JIT =
  150. LLVMOrcCreateInstance(wrap(TM.get()));
  151. LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
  152. CompileContext C;
  153. C.APIExecTest = this;
  154. LLVMOrcTargetAddress CCAddr;
  155. LLVMOrcCreateLazyCompileCallback(JIT, &CCAddr, myCompileCallback, &C);
  156. LLVMOrcCreateIndirectStub(JIT, "foo", CCAddr);
  157. LLVMOrcTargetAddress MainAddr;
  158. LLVMOrcGetSymbolAddress(JIT, &MainAddr, "foo");
  159. MainFnTy FooFn = (MainFnTy)MainAddr;
  160. int Result = FooFn();
  161. EXPECT_TRUE(C.Compiled)
  162. << "Function wasn't lazily compiled";
  163. EXPECT_EQ(Result, 42)
  164. << "Direct-callback JIT'd code did not return expected result";
  165. C.Compiled = false;
  166. FooFn();
  167. EXPECT_FALSE(C.Compiled)
  168. << "Direct-callback JIT'd code was JIT'd twice";
  169. LLVMOrcRemoveModule(JIT, C.H);
  170. LLVMOrcDisposeMangledSymbol(testFuncName);
  171. LLVMOrcDisposeInstance(JIT);
  172. }
  173. } // namespace llvm