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