blob: d9448d47667f5d782940a3c6946ca863b3ed284a [file] [log] [blame]
Lang Hames130a7c42015-10-28 02:40:04 +00001//===--------------- 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"
Lang Hamesec300632017-09-17 03:25:03 +000011#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
Eric Christophera6b96002015-12-18 01:46:52 +000012#include "llvm-c/Core.h"
Lang Hames130a7c42015-10-28 02:40:04 +000013#include "llvm-c/OrcBindings.h"
14#include "llvm-c/Target.h"
15#include "llvm-c/TargetMachine.h"
Chandler Carruth9a67b072017-06-06 11:06:56 +000016#include "gtest/gtest.h"
Lang Hames130a7c42015-10-28 02:40:04 +000017
Duncan P. N. Exon Smith91d3cfe2016-04-05 20:45:04 +000018#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
Lang Hames130a7c42015-10-28 02:40:04 +000021
22namespace llvm {
23
Aaron Ballman5db085d2015-11-04 14:40:54 +000024DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
Lang Hames130a7c42015-10-28 02:40:04 +000025
26class OrcCAPIExecutionTest : public testing::Test, public OrcExecutionTest {
27protected:
Lang Hames130a7c42015-10-28 02:40:04 +000028 std::unique_ptr<Module> createTestModule(const Triple &TT) {
Mehdi Amini03b42e42016-04-14 21:59:01 +000029 ModuleBuilder MB(Context, TT.str(), "");
Lang Hames130a7c42015-10-28 02:40:04 +000030 Function *TestFunc = MB.createFunctionDecl<int()>("testFunc");
31 Function *Main = MB.createFunctionDecl<int(int, char*[])>("main");
32
Mehdi Amini03b42e42016-04-14 21:59:01 +000033 Main->getBasicBlockList().push_back(BasicBlock::Create(Context));
Lang Hames130a7c42015-10-28 02:40:04 +000034 IRBuilder<> B(&Main->back());
35 Value* Result = B.CreateCall(TestFunc);
36 B.CreateRet(Result);
37
38 return MB.takeModule();
39 }
40
Lang Hamesec300632017-09-17 03:25:03 +000041 std::shared_ptr<object::OwningBinary<object::ObjectFile>>
42 createTestObject() {
43 orc::SimpleCompiler IRCompiler(*TM);
44 auto M = createTestModule(TM->getTargetTriple());
45 M->setDataLayout(TM->createDataLayout());
46 return std::make_shared<object::OwningBinary<object::ObjectFile>>(
47 IRCompiler(*M));
48 }
49
Eugene Zelenkoffec81c2015-11-04 22:32:32 +000050 typedef int (*MainFnTy)();
Lang Hames130a7c42015-10-28 02:40:04 +000051
Eugene Zelenkoffec81c2015-11-04 22:32:32 +000052 static int myTestFuncImpl() {
Lang Hames130a7c42015-10-28 02:40:04 +000053 return 42;
54 }
55
56 static char *testFuncName;
57
58 static uint64_t myResolver(const char *Name, void *Ctx) {
59 if (!strncmp(Name, testFuncName, 8))
60 return (uint64_t)&myTestFuncImpl;
61 return 0;
62 }
63
Lang Hamesfd6e8dc2015-10-30 03:20:21 +000064 struct CompileContext {
65 CompileContext() : Compiled(false) { }
66
67 OrcCAPIExecutionTest* APIExecTest;
68 std::unique_ptr<Module> M;
69 LLVMOrcModuleHandle H;
70 bool Compiled;
71 };
72
73 static LLVMOrcTargetAddress myCompileCallback(LLVMOrcJITStackRef JITStack,
74 void *Ctx) {
75 CompileContext *CCtx = static_cast<CompileContext*>(Ctx);
76 auto *ET = CCtx->APIExecTest;
77 CCtx->M = ET->createTestModule(ET->TM->getTargetTriple());
Lang Hamescd9d49b2017-06-23 23:25:28 +000078 LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(CCtx->M.release()));
Lang Hames4ce98662017-07-07 02:59:13 +000079 LLVMOrcAddEagerlyCompiledIR(JITStack, &CCtx->H, SM, myResolver, nullptr);
Lang Hamescd9d49b2017-06-23 23:25:28 +000080 LLVMOrcDisposeSharedModuleRef(SM);
Lang Hamesfd6e8dc2015-10-30 03:20:21 +000081 CCtx->Compiled = true;
Lang Hames4ce98662017-07-07 02:59:13 +000082 LLVMOrcTargetAddress MainAddr;
83 LLVMOrcGetSymbolAddress(JITStack, &MainAddr, "main");
Lang Hamesfd6e8dc2015-10-30 03:20:21 +000084 LLVMOrcSetIndirectStubPointer(JITStack, "foo", MainAddr);
85 return MainAddr;
86 }
Lang Hames130a7c42015-10-28 02:40:04 +000087};
88
Eugene Zelenkoffec81c2015-11-04 22:32:32 +000089char *OrcCAPIExecutionTest::testFuncName = nullptr;
Lang Hames130a7c42015-10-28 02:40:04 +000090
91TEST_F(OrcCAPIExecutionTest, TestEagerIRCompilation) {
Lang Hames130a7c42015-10-28 02:40:04 +000092 if (!TM)
93 return;
94
Lang Hames130a7c42015-10-28 02:40:04 +000095 LLVMOrcJITStackRef JIT =
Rafael Espindolae63e0182015-11-03 16:40:37 +000096 LLVMOrcCreateInstance(wrap(TM.get()));
Lang Hames130a7c42015-10-28 02:40:04 +000097
Lang Hamesfd6e8dc2015-10-30 03:20:21 +000098 std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
99
Lang Hames130a7c42015-10-28 02:40:04 +0000100 LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
101
Lang Hamescd9d49b2017-06-23 23:25:28 +0000102 LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(M.release()));
Lang Hames4ce98662017-07-07 02:59:13 +0000103 LLVMOrcModuleHandle H;
104 LLVMOrcAddEagerlyCompiledIR(JIT, &H, SM, myResolver, nullptr);
Lang Hamescd9d49b2017-06-23 23:25:28 +0000105 LLVMOrcDisposeSharedModuleRef(SM);
Lang Hames4ce98662017-07-07 02:59:13 +0000106 LLVMOrcTargetAddress MainAddr;
107 LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
108 MainFnTy MainFn = (MainFnTy)MainAddr;
Lang Hames130a7c42015-10-28 02:40:04 +0000109 int Result = MainFn();
110 EXPECT_EQ(Result, 42)
111 << "Eagerly JIT'd code did not return expected result";
112
113 LLVMOrcRemoveModule(JIT, H);
114
115 LLVMOrcDisposeMangledSymbol(testFuncName);
116 LLVMOrcDisposeInstance(JIT);
117}
118
119TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) {
Lang Hames130a7c42015-10-28 02:40:04 +0000120 if (!TM)
121 return;
122
Lang Hames130a7c42015-10-28 02:40:04 +0000123 LLVMOrcJITStackRef JIT =
Rafael Espindolae63e0182015-11-03 16:40:37 +0000124 LLVMOrcCreateInstance(wrap(TM.get()));
Lang Hames130a7c42015-10-28 02:40:04 +0000125
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000126 std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
127
Lang Hames130a7c42015-10-28 02:40:04 +0000128 LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000129
Lang Hamescd9d49b2017-06-23 23:25:28 +0000130 LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(M.release()));
Lang Hames4ce98662017-07-07 02:59:13 +0000131 LLVMOrcModuleHandle H;
132 LLVMOrcAddLazilyCompiledIR(JIT, &H, SM, myResolver, nullptr);
Lang Hamescd9d49b2017-06-23 23:25:28 +0000133 LLVMOrcDisposeSharedModuleRef(SM);
Lang Hames4ce98662017-07-07 02:59:13 +0000134 LLVMOrcTargetAddress MainAddr;
135 LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
136 MainFnTy MainFn = (MainFnTy)MainAddr;
Lang Hames130a7c42015-10-28 02:40:04 +0000137 int Result = MainFn();
138 EXPECT_EQ(Result, 42)
139 << "Lazily JIT'd code did not return expected result";
140
141 LLVMOrcRemoveModule(JIT, H);
142
143 LLVMOrcDisposeMangledSymbol(testFuncName);
144 LLVMOrcDisposeInstance(JIT);
145}
146
Lang Hamesec300632017-09-17 03:25:03 +0000147TEST_F(OrcCAPIExecutionTest, TestAddObjectFile) {
148 if (!TM)
149 return;
150
151 std::unique_ptr<MemoryBuffer> ObjBuffer;
152 {
153 auto OwningObj = createTestObject();
154 auto ObjAndBuffer = OwningObj->takeBinary();
155 ObjBuffer = std::move(ObjAndBuffer.second);
156 }
157
158 LLVMOrcJITStackRef JIT =
159 LLVMOrcCreateInstance(wrap(TM.get()));
160 LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
161
162 LLVMOrcModuleHandle H;
163 LLVMOrcAddObjectFile(JIT, &H, wrap(ObjBuffer.release()), myResolver, nullptr);
164 LLVMOrcTargetAddress MainAddr;
165 LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
166 MainFnTy MainFn = (MainFnTy)MainAddr;
167 int Result = MainFn();
168 EXPECT_EQ(Result, 42)
169 << "Lazily JIT'd code did not return expected result";
170
171 LLVMOrcRemoveModule(JIT, H);
172
173 LLVMOrcDisposeMangledSymbol(testFuncName);
174 LLVMOrcDisposeInstance(JIT);
175}
176
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000177TEST_F(OrcCAPIExecutionTest, TestDirectCallbacksAPI) {
178 if (!TM)
179 return;
180
181 LLVMOrcJITStackRef JIT =
Rafael Espindolae63e0182015-11-03 16:40:37 +0000182 LLVMOrcCreateInstance(wrap(TM.get()));
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000183
184 LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
185
186 CompileContext C;
187 C.APIExecTest = this;
Lang Hames4ce98662017-07-07 02:59:13 +0000188 LLVMOrcTargetAddress CCAddr;
189 LLVMOrcCreateLazyCompileCallback(JIT, &CCAddr, myCompileCallback, &C);
190 LLVMOrcCreateIndirectStub(JIT, "foo", CCAddr);
191 LLVMOrcTargetAddress MainAddr;
192 LLVMOrcGetSymbolAddress(JIT, &MainAddr, "foo");
193 MainFnTy FooFn = (MainFnTy)MainAddr;
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000194 int Result = FooFn();
195 EXPECT_TRUE(C.Compiled)
196 << "Function wasn't lazily compiled";
197 EXPECT_EQ(Result, 42)
198 << "Direct-callback JIT'd code did not return expected result";
199
200 C.Compiled = false;
201 FooFn();
202 EXPECT_FALSE(C.Compiled)
203 << "Direct-callback JIT'd code was JIT'd twice";
204
205 LLVMOrcRemoveModule(JIT, C.H);
206
207 LLVMOrcDisposeMangledSymbol(testFuncName);
208 LLVMOrcDisposeInstance(JIT);
209}
210
Duncan P. N. Exon Smith91d3cfe2016-04-05 20:45:04 +0000211} // namespace llvm