blob: cea6274656b85b966db0fdbf293831ec4bce67e2 [file] [log] [blame]
Andrew Kaylor6bbb2c92013-10-01 01:48:36 +00001//===- MCJITMultipeModuleTest.cpp - Unit tests for the MCJIT---------------===//
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// This test suite verifies MCJIT for handling multiple modules in a single
11// ExecutionEngine by building multiple modules, making function calls across
12// modules, accessing global variables, etc.
13//===----------------------------------------------------------------------===//
14
15#include "llvm/ExecutionEngine/MCJIT.h"
16#include "MCJITTestBase.h"
17#include "gtest/gtest.h"
18
19using namespace llvm;
20
Juergen Ributzkad12ccbd2013-11-19 00:57:56 +000021class MCJITMultipleModuleTest : public testing::Test, public MCJITTestBase {
22public:
23 virtual ~MCJITMultipleModuleTest();
24};
25
26// Provide out-of-line definition to prevent weak vtable.
27MCJITMultipleModuleTest::~MCJITMultipleModuleTest() {}
Andrew Kaylor6bbb2c92013-10-01 01:48:36 +000028
29namespace {
30
31// FIXME: ExecutionEngine has no support empty modules
32/*
33TEST_F(MCJITMultipleModuleTest, multiple_empty_modules) {
34 SKIP_UNSUPPORTED_PLATFORM;
35
36 createJIT(M.take());
37 // JIT-compile
38 EXPECT_NE(0, TheJIT->getObjectImage())
39 << "Unable to generate executable loaded object image";
40
41 TheJIT->addModule(createEmptyModule("<other module>"));
42 TheJIT->addModule(createEmptyModule("<other other module>"));
43
44 // JIT again
45 EXPECT_NE(0, TheJIT->getObjectImage())
46 << "Unable to generate executable loaded object image";
47}
48*/
49
50// Helper Function to test add operation
51void checkAdd(uint64_t ptr) {
52 ASSERT_TRUE(ptr != 0) << "Unable to get pointer to function.";
53 int (*AddPtr)(int, int) = (int (*)(int, int))ptr;
54 EXPECT_EQ(0, AddPtr(0, 0));
55 EXPECT_EQ(1, AddPtr(1, 0));
56 EXPECT_EQ(3, AddPtr(1, 2));
57 EXPECT_EQ(-5, AddPtr(-2, -3));
58 EXPECT_EQ(30, AddPtr(10, 20));
59 EXPECT_EQ(-30, AddPtr(-10, -20));
60 EXPECT_EQ(-40, AddPtr(-10, -30));
61}
62
63void checkAccumulate(uint64_t ptr) {
64 ASSERT_TRUE(ptr != 0) << "Unable to get pointer to function.";
65 int32_t (*FPtr)(int32_t) = (int32_t (*)(int32_t))(intptr_t)ptr;
66 EXPECT_EQ(0, FPtr(0));
67 EXPECT_EQ(1, FPtr(1));
68 EXPECT_EQ(3, FPtr(2));
69 EXPECT_EQ(6, FPtr(3));
70 EXPECT_EQ(10, FPtr(4));
71 EXPECT_EQ(15, FPtr(5));
72}
73
74// FIXME: ExecutionEngine has no support empty modules
75/*
76TEST_F(MCJITMultipleModuleTest, multiple_empty_modules) {
77 SKIP_UNSUPPORTED_PLATFORM;
78
79 createJIT(M.take());
80 // JIT-compile
81 EXPECT_NE(0, TheJIT->getObjectImage())
82 << "Unable to generate executable loaded object image";
83
84 TheJIT->addModule(createEmptyModule("<other module>"));
85 TheJIT->addModule(createEmptyModule("<other other module>"));
86
87 // JIT again
88 EXPECT_NE(0, TheJIT->getObjectImage())
89 << "Unable to generate executable loaded object image";
90}
91*/
92
93// Module A { Function FA },
94// Module B { Function FB },
95// execute FA then FB
96TEST_F(MCJITMultipleModuleTest, two_module_case) {
97 SKIP_UNSUPPORTED_PLATFORM;
98
99 OwningPtr<Module> A, B;
100 Function *FA, *FB;
101 createTwoModuleCase(A, FA, B, FB);
102
103 createJIT(A.take());
104 TheJIT->addModule(B.take());
105
106 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
107 checkAdd(ptr);
108
109 ptr = TheJIT->getFunctionAddress(FB->getName().str());
110 checkAdd(ptr);
111}
112
113// Module A { Function FA },
114// Module B { Function FB },
115// execute FB then FA
116TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) {
117 SKIP_UNSUPPORTED_PLATFORM;
118
119 OwningPtr<Module> A, B;
120 Function *FA, *FB;
121 createTwoModuleCase(A, FA, B, FB);
122
123 createJIT(A.take());
124 TheJIT->addModule(B.take());
125
126 uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
127 TheJIT->finalizeObject();
128 checkAdd(ptr);
129
130 ptr = TheJIT->getFunctionAddress(FA->getName().str());
131 checkAdd(ptr);
132}
133
134// Module A { Function FA },
135// Module B { Extern FA, Function FB which calls FA },
136// execute FB then FA
137TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) {
138 SKIP_UNSUPPORTED_PLATFORM;
139
140 OwningPtr<Module> A, B;
141 Function *FA, *FB;
142 createTwoModuleExternCase(A, FA, B, FB);
143
144 createJIT(A.take());
145 TheJIT->addModule(B.take());
146
147 uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
148 TheJIT->finalizeObject();
149 checkAdd(ptr);
150
151 ptr = TheJIT->getFunctionAddress(FA->getName().str());
152 checkAdd(ptr);
153}
154
155// Module A { Function FA },
156// Module B { Extern FA, Function FB which calls FA },
157// execute FA then FB
158TEST_F(MCJITMultipleModuleTest, two_module_extern_case) {
159 SKIP_UNSUPPORTED_PLATFORM;
160
161 OwningPtr<Module> A, B;
162 Function *FA, *FB;
163 createTwoModuleExternCase(A, FA, B, FB);
164
165 createJIT(A.take());
166 TheJIT->addModule(B.take());
167
168 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
169 checkAdd(ptr);
170
171 ptr = TheJIT->getFunctionAddress(FB->getName().str());
172 checkAdd(ptr);
173}
174
175// Module A { Function FA1, Function FA2 which calls FA1 },
176// Module B { Extern FA1, Function FB which calls FA1 },
177// execute FB then FA2
178TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) {
179 SKIP_UNSUPPORTED_PLATFORM;
180
181 OwningPtr<Module> A, B;
182 Function *FA1, *FA2, *FB;
183 createTwoModuleExternCase(A, FA1, B, FB);
184 FA2 = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(A.get(), FA1);
185
186 createJIT(A.take());
187 TheJIT->addModule(B.take());
188
189 uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
190 TheJIT->finalizeObject();
191 checkAdd(ptr);
192
193 ptr = TheJIT->getFunctionAddress(FA2->getName().str());
194 checkAdd(ptr);
195}
196
197// TODO:
198// Module A { Extern Global GVB, Global Variable GVA, Function FA loads GVB },
199// Module B { Extern Global GVA, Global Variable GVB, Function FB loads GVA },
200
201
202// Module A { Global Variable GVA, Function FA loads GVA },
203// Module B { Global Variable GVB, Function FB loads GVB },
204// execute FB then FA
205TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) {
206 SKIP_UNSUPPORTED_PLATFORM;
207
208 OwningPtr<Module> A, B;
209 Function *FA, *FB;
210 GlobalVariable *GVA, *GVB;
211 A.reset(createEmptyModule("A"));
212 B.reset(createEmptyModule("B"));
213
214 int32_t initialNum = 7;
215 GVA = insertGlobalInt32(A.get(), "GVA", initialNum);
216 GVB = insertGlobalInt32(B.get(), "GVB", initialNum);
217 FA = startFunction<int32_t(void)>(A.get(), "FA");
218 endFunctionWithRet(FA, Builder.CreateLoad(GVA));
219 FB = startFunction<int32_t(void)>(B.get(), "FB");
220 endFunctionWithRet(FB, Builder.CreateLoad(GVB));
221
222 createJIT(A.take());
223 TheJIT->addModule(B.take());
224
225 uint64_t FBPtr = TheJIT->getFunctionAddress(FB->getName().str());
226 TheJIT->finalizeObject();
227 EXPECT_TRUE(0 != FBPtr);
228 int32_t(*FuncPtr)(void) = (int32_t(*)(void))FBPtr;
229 EXPECT_EQ(initialNum, FuncPtr())
230 << "Invalid value for global returned from JITted function in module B";
231
232 uint64_t FAPtr = TheJIT->getFunctionAddress(FA->getName().str());
233 EXPECT_TRUE(0 != FAPtr);
234 FuncPtr = (int32_t(*)(void))FAPtr;
235 EXPECT_EQ(initialNum, FuncPtr())
236 << "Invalid value for global returned from JITted function in module A";
237}
238
239// Module A { Function FA },
240// Module B { Extern FA, Function FB which calls FA },
241// Module C { Extern FA, Function FC which calls FA },
242// execute FC, FB, FA
243TEST_F(MCJITMultipleModuleTest, three_module_case) {
Tim Northover39ddb3f2013-10-02 16:11:07 +0000244 SKIP_UNSUPPORTED_PLATFORM;
245
Andrew Kaylor6bbb2c92013-10-01 01:48:36 +0000246 OwningPtr<Module> A, B, C;
247 Function *FA, *FB, *FC;
248 createThreeModuleCase(A, FA, B, FB, C, FC);
249
250 createJIT(A.take());
251 TheJIT->addModule(B.take());
252 TheJIT->addModule(C.take());
253
254 uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());
255 checkAdd(ptr);
256
257 ptr = TheJIT->getFunctionAddress(FB->getName().str());
258 checkAdd(ptr);
259
260 ptr = TheJIT->getFunctionAddress(FA->getName().str());
261 checkAdd(ptr);
262}
263
264// Module A { Function FA },
265// Module B { Extern FA, Function FB which calls FA },
266// Module C { Extern FA, Function FC which calls FA },
267// execute FA, FB, FC
268TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) {
Tim Northover39ddb3f2013-10-02 16:11:07 +0000269 SKIP_UNSUPPORTED_PLATFORM;
270
Andrew Kaylor6bbb2c92013-10-01 01:48:36 +0000271 OwningPtr<Module> A, B, C;
272 Function *FA, *FB, *FC;
273 createThreeModuleCase(A, FA, B, FB, C, FC);
274
275 createJIT(A.take());
276 TheJIT->addModule(B.take());
277 TheJIT->addModule(C.take());
278
279 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
280 checkAdd(ptr);
281
282 ptr = TheJIT->getFunctionAddress(FB->getName().str());
283 checkAdd(ptr);
284
285 ptr = TheJIT->getFunctionAddress(FC->getName().str());
286 checkAdd(ptr);
287}
288
289// Module A { Function FA },
290// Module B { Extern FA, Function FB which calls FA },
291// Module C { Extern FB, Function FC which calls FB },
292// execute FC, FB, FA
293TEST_F(MCJITMultipleModuleTest, three_module_chain_case) {
Tim Northover39ddb3f2013-10-02 16:11:07 +0000294 SKIP_UNSUPPORTED_PLATFORM;
295
Andrew Kaylor6bbb2c92013-10-01 01:48:36 +0000296 OwningPtr<Module> A, B, C;
297 Function *FA, *FB, *FC;
298 createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC);
299
300 createJIT(A.take());
301 TheJIT->addModule(B.take());
302 TheJIT->addModule(C.take());
303
304 uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());
305 checkAdd(ptr);
306
307 ptr = TheJIT->getFunctionAddress(FB->getName().str());
308 checkAdd(ptr);
309
310 ptr = TheJIT->getFunctionAddress(FA->getName().str());
311 checkAdd(ptr);
312}
313
314// Module A { Function FA },
315// Module B { Extern FA, Function FB which calls FA },
316// Module C { Extern FB, Function FC which calls FB },
317// execute FA, FB, FC
318TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) {
Tim Northover39ddb3f2013-10-02 16:11:07 +0000319 SKIP_UNSUPPORTED_PLATFORM;
320
Andrew Kaylor6bbb2c92013-10-01 01:48:36 +0000321 OwningPtr<Module> A, B, C;
322 Function *FA, *FB, *FC;
323 createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC);
324
325 createJIT(A.take());
326 TheJIT->addModule(B.take());
327 TheJIT->addModule(C.take());
328
329 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
330 checkAdd(ptr);
331
332 ptr = TheJIT->getFunctionAddress(FB->getName().str());
333 checkAdd(ptr);
334
335 ptr = TheJIT->getFunctionAddress(FC->getName().str());
336 checkAdd(ptr);
337}
338
339// Module A { Extern FB, Function FA which calls FB1 },
340// Module B { Extern FA, Function FB1, Function FB2 which calls FA },
341// execute FA, then FB1
342// FIXME: this test case is not supported by MCJIT
343TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) {
344 SKIP_UNSUPPORTED_PLATFORM;
345
346 OwningPtr<Module> A, B;
347 Function *FA, *FB1, *FB2;
348 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
349
350 createJIT(A.take());
351 TheJIT->addModule(B.take());
352
353 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
354 checkAccumulate(ptr);
355
356 ptr = TheJIT->getFunctionAddress(FB1->getName().str());
357 checkAccumulate(ptr);
358}
359
360// Module A { Extern FB, Function FA which calls FB1 },
361// Module B { Extern FA, Function FB1, Function FB2 which calls FA },
362// execute FB1 then FA
363// FIXME: this test case is not supported by MCJIT
364TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) {
365 SKIP_UNSUPPORTED_PLATFORM;
366
367 OwningPtr<Module> A, B;
368 Function *FA, *FB1, *FB2;
369 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
370
371 createJIT(A.take());
372 TheJIT->addModule(B.take());
373
374 uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());
375 checkAccumulate(ptr);
376
377 ptr = TheJIT->getFunctionAddress(FA->getName().str());
378 checkAccumulate(ptr);
379}
380
381// Module A { Extern FB1, Function FA which calls FB1 },
382// Module B { Extern FA, Function FB1, Function FB2 which calls FA },
383// execute FB1 then FB2
384// FIXME: this test case is not supported by MCJIT
385TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) {
386 SKIP_UNSUPPORTED_PLATFORM;
387
388 OwningPtr<Module> A, B;
389 Function *FA, *FB1, *FB2;
390 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
391
392 createJIT(A.take());
393 TheJIT->addModule(B.take());
394
395 uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());
396 checkAccumulate(ptr);
397
398 ptr = TheJIT->getFunctionAddress(FB2->getName().str());
399 checkAccumulate(ptr);
400}
401}