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/Core.h"
13 #include "llvm-c/OrcBindings.h"
14 #include "llvm-c/Target.h"
15 #include "llvm-c/TargetMachine.h"
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 namespace llvm {
22
23 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
24
25 class OrcCAPIExecutionTest : public testing::Test, public OrcExecutionTest {
26 protected:
createTestModule(const Triple & TT)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)();
41
myTestFuncImpl()42 static int myTestFuncImpl() {
43 return 42;
44 }
45
46 static char *testFuncName;
47
myResolver(const char * Name,void * Ctx)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 {
CompileContextllvm::OrcCAPIExecutionTest::CompileContext55 CompileContext() : Compiled(false) { }
56
57 OrcCAPIExecutionTest* APIExecTest;
58 std::unique_ptr<Module> M;
59 LLVMOrcModuleHandle H;
60 bool Compiled;
61 };
62
myCompileCallback(LLVMOrcJITStackRef JITStack,void * Ctx)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, nullptr);
70 CCtx->Compiled = true;
71 LLVMOrcTargetAddress MainAddr = LLVMOrcGetSymbolAddress(JITStack, "main");
72 LLVMOrcSetIndirectStubPointer(JITStack, "foo", MainAddr);
73 return MainAddr;
74 }
75 };
76
77 char *OrcCAPIExecutionTest::testFuncName = nullptr;
78
TEST_F(OrcCAPIExecutionTest,TestEagerIRCompilation)79 TEST_F(OrcCAPIExecutionTest, TestEagerIRCompilation) {
80 if (!TM)
81 return;
82
83 LLVMOrcJITStackRef JIT =
84 LLVMOrcCreateInstance(wrap(TM.get()));
85
86 std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
87
88 LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
89
90 LLVMOrcModuleHandle H =
91 LLVMOrcAddEagerlyCompiledIR(JIT, wrap(M.get()), myResolver, nullptr);
92 MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main");
93 int Result = MainFn();
94 EXPECT_EQ(Result, 42)
95 << "Eagerly JIT'd code did not return expected result";
96
97 LLVMOrcRemoveModule(JIT, H);
98
99 LLVMOrcDisposeMangledSymbol(testFuncName);
100 LLVMOrcDisposeInstance(JIT);
101 }
102
TEST_F(OrcCAPIExecutionTest,TestLazyIRCompilation)103 TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) {
104 if (!TM)
105 return;
106
107 LLVMOrcJITStackRef JIT =
108 LLVMOrcCreateInstance(wrap(TM.get()));
109
110 std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
111
112 LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
113
114 LLVMOrcModuleHandle H =
115 LLVMOrcAddLazilyCompiledIR(JIT, wrap(M.get()), myResolver, nullptr);
116 MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main");
117 int Result = MainFn();
118 EXPECT_EQ(Result, 42)
119 << "Lazily JIT'd code did not return expected result";
120
121 LLVMOrcRemoveModule(JIT, H);
122
123 LLVMOrcDisposeMangledSymbol(testFuncName);
124 LLVMOrcDisposeInstance(JIT);
125 }
126
TEST_F(OrcCAPIExecutionTest,TestDirectCallbacksAPI)127 TEST_F(OrcCAPIExecutionTest, TestDirectCallbacksAPI) {
128 if (!TM)
129 return;
130
131 LLVMOrcJITStackRef JIT =
132 LLVMOrcCreateInstance(wrap(TM.get()));
133
134 LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
135
136 CompileContext C;
137 C.APIExecTest = this;
138 LLVMOrcCreateIndirectStub(JIT, "foo",
139 LLVMOrcCreateLazyCompileCallback(JIT,
140 myCompileCallback,
141 &C));
142 MainFnTy FooFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "foo");
143 int Result = FooFn();
144 EXPECT_TRUE(C.Compiled)
145 << "Function wasn't lazily compiled";
146 EXPECT_EQ(Result, 42)
147 << "Direct-callback JIT'd code did not return expected result";
148
149 C.Compiled = false;
150 FooFn();
151 EXPECT_FALSE(C.Compiled)
152 << "Direct-callback JIT'd code was JIT'd twice";
153
154 LLVMOrcRemoveModule(JIT, C.H);
155
156 LLVMOrcDisposeMangledSymbol(testFuncName);
157 LLVMOrcDisposeInstance(JIT);
158 }
159
160 } // namespace llvm
161