• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--------------- OrcCAPITest.cpp - Unit tests Orc C API ---------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "OrcTestCommon.h"
11 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
12 #include "llvm-c/Core.h"
13 #include "llvm-c/OrcBindings.h"
14 #include "llvm-c/Target.h"
15 #include "llvm-c/TargetMachine.h"
16 #include "gtest/gtest.h"
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 namespace llvm {
23 
24 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
25 
26 class OrcCAPIExecutionTest : public testing::Test, public OrcExecutionTest {
27 protected:
createTestModule(const Triple & TT)28   std::unique_ptr<Module> createTestModule(const Triple &TT) {
29     ModuleBuilder MB(Context, TT.str(), "");
30     Function *TestFunc = MB.createFunctionDecl<int()>("testFunc");
31     Function *Main = MB.createFunctionDecl<int(int, char*[])>("main");
32 
33     Main->getBasicBlockList().push_back(BasicBlock::Create(Context));
34     IRBuilder<> B(&Main->back());
35     Value* Result = B.CreateCall(TestFunc);
36     B.CreateRet(Result);
37 
38     return MB.takeModule();
39   }
40 
createTestObject()41   std::unique_ptr<MemoryBuffer> createTestObject() {
42     orc::SimpleCompiler IRCompiler(*TM);
43     auto M = createTestModule(TM->getTargetTriple());
44     M->setDataLayout(TM->createDataLayout());
45     return IRCompiler(*M);
46   }
47 
48   typedef int (*MainFnTy)();
49 
myTestFuncImpl()50   static int myTestFuncImpl() {
51     return 42;
52   }
53 
54   static char *testFuncName;
55 
myResolver(const char * Name,void * Ctx)56   static uint64_t myResolver(const char *Name, void *Ctx) {
57     if (!strncmp(Name, testFuncName, 8))
58       return (uint64_t)&myTestFuncImpl;
59     return 0;
60   }
61 
62   struct CompileContext {
CompileContextllvm::OrcCAPIExecutionTest::CompileContext63     CompileContext() : Compiled(false) { }
64 
65     OrcCAPIExecutionTest* APIExecTest;
66     std::unique_ptr<Module> M;
67     LLVMOrcModuleHandle H;
68     bool Compiled;
69   };
70 
myCompileCallback(LLVMOrcJITStackRef JITStack,void * Ctx)71   static LLVMOrcTargetAddress myCompileCallback(LLVMOrcJITStackRef JITStack,
72                                                 void *Ctx) {
73     CompileContext *CCtx = static_cast<CompileContext*>(Ctx);
74     auto *ET = CCtx->APIExecTest;
75     CCtx->M = ET->createTestModule(ET->TM->getTargetTriple());
76     LLVMOrcAddEagerlyCompiledIR(JITStack, &CCtx->H, wrap(CCtx->M.release()),
77                                 myResolver, nullptr);
78     CCtx->Compiled = true;
79     LLVMOrcTargetAddress MainAddr;
80     LLVMOrcGetSymbolAddress(JITStack, &MainAddr, "main");
81     LLVMOrcSetIndirectStubPointer(JITStack, "foo", MainAddr);
82     return MainAddr;
83   }
84 };
85 
86 char *OrcCAPIExecutionTest::testFuncName = nullptr;
87 
TEST_F(OrcCAPIExecutionTest,TestEagerIRCompilation)88 TEST_F(OrcCAPIExecutionTest, TestEagerIRCompilation) {
89   if (!SupportsJIT)
90     return;
91 
92   LLVMOrcJITStackRef JIT =
93     LLVMOrcCreateInstance(wrap(TM.get()));
94 
95   std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
96 
97   LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
98 
99   LLVMOrcModuleHandle H;
100   LLVMOrcAddEagerlyCompiledIR(JIT, &H, wrap(M.release()), myResolver, nullptr);
101 
102   // get symbol address searching the entire stack
103   {
104     LLVMOrcTargetAddress MainAddr;
105     LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
106     MainFnTy MainFn = (MainFnTy)MainAddr;
107     int Result = MainFn();
108     EXPECT_EQ(Result, 42)
109       << "Eagerly JIT'd code did not return expected result";
110   }
111 
112   // and then just searching a single handle
113   {
114     LLVMOrcTargetAddress MainAddr;
115     LLVMOrcGetSymbolAddressIn(JIT, &MainAddr, H, "main");
116     MainFnTy MainFn = (MainFnTy)MainAddr;
117     int Result = MainFn();
118     EXPECT_EQ(Result, 42)
119       << "Eagerly JIT'd code did not return expected result";
120   }
121 
122   LLVMOrcRemoveModule(JIT, H);
123 
124   LLVMOrcDisposeMangledSymbol(testFuncName);
125   LLVMOrcDisposeInstance(JIT);
126 }
127 
TEST_F(OrcCAPIExecutionTest,TestLazyIRCompilation)128 TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) {
129   if (!SupportsIndirection)
130     return;
131 
132   LLVMOrcJITStackRef JIT =
133     LLVMOrcCreateInstance(wrap(TM.get()));
134 
135   std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
136 
137   LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
138 
139   LLVMOrcModuleHandle H;
140   LLVMOrcAddLazilyCompiledIR(JIT, &H, wrap(M.release()), myResolver, nullptr);
141   LLVMOrcTargetAddress MainAddr;
142   LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
143   MainFnTy MainFn = (MainFnTy)MainAddr;
144   int Result = MainFn();
145   EXPECT_EQ(Result, 42)
146     << "Lazily JIT'd code did not return expected result";
147 
148   LLVMOrcRemoveModule(JIT, H);
149 
150   LLVMOrcDisposeMangledSymbol(testFuncName);
151   LLVMOrcDisposeInstance(JIT);
152 }
153 
TEST_F(OrcCAPIExecutionTest,TestAddObjectFile)154 TEST_F(OrcCAPIExecutionTest, TestAddObjectFile) {
155   if (!SupportsJIT)
156     return;
157 
158   auto ObjBuffer = createTestObject();
159 
160   LLVMOrcJITStackRef JIT =
161     LLVMOrcCreateInstance(wrap(TM.get()));
162   LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
163 
164   LLVMOrcModuleHandle H;
165   LLVMOrcAddObjectFile(JIT, &H, wrap(ObjBuffer.release()), myResolver, nullptr);
166   LLVMOrcTargetAddress MainAddr;
167   LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
168   MainFnTy MainFn = (MainFnTy)MainAddr;
169   int Result = MainFn();
170   EXPECT_EQ(Result, 42)
171     << "Lazily JIT'd code did not return expected result";
172 
173   LLVMOrcRemoveModule(JIT, H);
174 
175   LLVMOrcDisposeMangledSymbol(testFuncName);
176   LLVMOrcDisposeInstance(JIT);
177 }
178 
TEST_F(OrcCAPIExecutionTest,TestDirectCallbacksAPI)179 TEST_F(OrcCAPIExecutionTest, TestDirectCallbacksAPI) {
180   if (!SupportsIndirection)
181     return;
182 
183   LLVMOrcJITStackRef JIT =
184     LLVMOrcCreateInstance(wrap(TM.get()));
185 
186   LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
187 
188   CompileContext C;
189   C.APIExecTest = this;
190   LLVMOrcTargetAddress CCAddr;
191   LLVMOrcCreateLazyCompileCallback(JIT, &CCAddr, myCompileCallback, &C);
192   LLVMOrcCreateIndirectStub(JIT, "foo", CCAddr);
193   LLVMOrcTargetAddress MainAddr;
194   LLVMOrcGetSymbolAddress(JIT, &MainAddr, "foo");
195   MainFnTy FooFn = (MainFnTy)MainAddr;
196   int Result = FooFn();
197   EXPECT_TRUE(C.Compiled)
198     << "Function wasn't lazily compiled";
199   EXPECT_EQ(Result, 42)
200     << "Direct-callback JIT'd code did not return expected result";
201 
202   C.Compiled = false;
203   FooFn();
204   EXPECT_FALSE(C.Compiled)
205     << "Direct-callback JIT'd code was JIT'd twice";
206 
207   LLVMOrcRemoveModule(JIT, C.H);
208 
209   LLVMOrcDisposeMangledSymbol(testFuncName);
210   LLVMOrcDisposeInstance(JIT);
211 }
212 
213 } // namespace llvm
214