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