1 //===- 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
19 using namespace llvm;
20
21 namespace {
22
23 class MCJITMultipleModuleTest : public testing::Test, public MCJITTestBase {};
24
25 // FIXME: ExecutionEngine has no support empty modules
26 /*
27 TEST_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
checkAdd(uint64_t ptr)45 void 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
checkAccumulate(uint64_t ptr)57 void 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 /*
70 TEST_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
TEST_F(MCJITMultipleModuleTest,two_module_case)90 TEST_F(MCJITMultipleModuleTest, two_module_case) {
91 SKIP_UNSUPPORTED_PLATFORM;
92
93 std::unique_ptr<Module> A, B;
94 Function *FA, *FB;
95 createTwoModuleCase(A, FA, B, FB);
96
97 createJIT(std::move(A));
98 TheJIT->addModule(std::move(B));
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
TEST_F(MCJITMultipleModuleTest,two_module_reverse_case)110 TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) {
111 SKIP_UNSUPPORTED_PLATFORM;
112
113 std::unique_ptr<Module> A, B;
114 Function *FA, *FB;
115 createTwoModuleCase(A, FA, B, FB);
116
117 createJIT(std::move(A));
118 TheJIT->addModule(std::move(B));
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
TEST_F(MCJITMultipleModuleTest,two_module_extern_reverse_case)131 TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) {
132 SKIP_UNSUPPORTED_PLATFORM;
133
134 std::unique_ptr<Module> A, B;
135 Function *FA, *FB;
136 createTwoModuleExternCase(A, FA, B, FB);
137
138 createJIT(std::move(A));
139 TheJIT->addModule(std::move(B));
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
TEST_F(MCJITMultipleModuleTest,two_module_extern_case)152 TEST_F(MCJITMultipleModuleTest, two_module_extern_case) {
153 SKIP_UNSUPPORTED_PLATFORM;
154
155 std::unique_ptr<Module> A, B;
156 Function *FA, *FB;
157 createTwoModuleExternCase(A, FA, B, FB);
158
159 createJIT(std::move(A));
160 TheJIT->addModule(std::move(B));
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
TEST_F(MCJITMultipleModuleTest,two_module_consecutive_call_case)172 TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) {
173 SKIP_UNSUPPORTED_PLATFORM;
174
175 std::unique_ptr<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(std::move(A));
181 TheJIT->addModule(std::move(B));
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
TEST_F(MCJITMultipleModuleTest,two_module_global_variables_case)199 TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) {
200 SKIP_UNSUPPORTED_PLATFORM;
201
202 std::unique_ptr<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(std::move(A));
217 TheJIT->addModule(std::move(B));
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
TEST_F(MCJITMultipleModuleTest,three_module_case)237 TEST_F(MCJITMultipleModuleTest, three_module_case) {
238 SKIP_UNSUPPORTED_PLATFORM;
239
240 std::unique_ptr<Module> A, B, C;
241 Function *FA, *FB, *FC;
242 createThreeModuleCase(A, FA, B, FB, C, FC);
243
244 createJIT(std::move(A));
245 TheJIT->addModule(std::move(B));
246 TheJIT->addModule(std::move(C));
247
248 uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());
249 checkAdd(ptr);
250
251 ptr = TheJIT->getFunctionAddress(FB->getName().str());
252 checkAdd(ptr);
253
254 ptr = TheJIT->getFunctionAddress(FA->getName().str());
255 checkAdd(ptr);
256 }
257
258 // Module A { Function FA },
259 // Module B { Extern FA, Function FB which calls FA },
260 // Module C { Extern FA, Function FC which calls FA },
261 // execute FA, FB, FC
TEST_F(MCJITMultipleModuleTest,three_module_case_reverse_order)262 TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) {
263 SKIP_UNSUPPORTED_PLATFORM;
264
265 std::unique_ptr<Module> A, B, C;
266 Function *FA, *FB, *FC;
267 createThreeModuleCase(A, FA, B, FB, C, FC);
268
269 createJIT(std::move(A));
270 TheJIT->addModule(std::move(B));
271 TheJIT->addModule(std::move(C));
272
273 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
274 checkAdd(ptr);
275
276 ptr = TheJIT->getFunctionAddress(FB->getName().str());
277 checkAdd(ptr);
278
279 ptr = TheJIT->getFunctionAddress(FC->getName().str());
280 checkAdd(ptr);
281 }
282
283 // Module A { Function FA },
284 // Module B { Extern FA, Function FB which calls FA },
285 // Module C { Extern FB, Function FC which calls FB },
286 // execute FC, FB, FA
TEST_F(MCJITMultipleModuleTest,three_module_chain_case)287 TEST_F(MCJITMultipleModuleTest, three_module_chain_case) {
288 SKIP_UNSUPPORTED_PLATFORM;
289
290 std::unique_ptr<Module> A, B, C;
291 Function *FA, *FB, *FC;
292 createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC);
293
294 createJIT(std::move(A));
295 TheJIT->addModule(std::move(B));
296 TheJIT->addModule(std::move(C));
297
298 uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());
299 checkAdd(ptr);
300
301 ptr = TheJIT->getFunctionAddress(FB->getName().str());
302 checkAdd(ptr);
303
304 ptr = TheJIT->getFunctionAddress(FA->getName().str());
305 checkAdd(ptr);
306 }
307
308 // Module A { Function FA },
309 // Module B { Extern FA, Function FB which calls FA },
310 // Module C { Extern FB, Function FC which calls FB },
311 // execute FA, FB, FC
TEST_F(MCJITMultipleModuleTest,three_modules_chain_case_reverse_order)312 TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) {
313 SKIP_UNSUPPORTED_PLATFORM;
314
315 std::unique_ptr<Module> A, B, C;
316 Function *FA, *FB, *FC;
317 createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC);
318
319 createJIT(std::move(A));
320 TheJIT->addModule(std::move(B));
321 TheJIT->addModule(std::move(C));
322
323 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
324 checkAdd(ptr);
325
326 ptr = TheJIT->getFunctionAddress(FB->getName().str());
327 checkAdd(ptr);
328
329 ptr = TheJIT->getFunctionAddress(FC->getName().str());
330 checkAdd(ptr);
331 }
332
333 // Module A { Extern FB, Function FA which calls FB1 },
334 // Module B { Extern FA, Function FB1, Function FB2 which calls FA },
335 // execute FA, then FB1
336 // FIXME: this test case is not supported by MCJIT
TEST_F(MCJITMultipleModuleTest,cross_module_dependency_case)337 TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) {
338 SKIP_UNSUPPORTED_PLATFORM;
339
340 std::unique_ptr<Module> A, B;
341 Function *FA, *FB1, *FB2;
342 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
343
344 createJIT(std::move(A));
345 TheJIT->addModule(std::move(B));
346
347 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
348 checkAccumulate(ptr);
349
350 ptr = TheJIT->getFunctionAddress(FB1->getName().str());
351 checkAccumulate(ptr);
352 }
353
354 // Module A { Extern FB, Function FA which calls FB1 },
355 // Module B { Extern FA, Function FB1, Function FB2 which calls FA },
356 // execute FB1 then FA
357 // FIXME: this test case is not supported by MCJIT
TEST_F(MCJITMultipleModuleTest,cross_module_dependency_case_reverse_order)358 TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) {
359 SKIP_UNSUPPORTED_PLATFORM;
360
361 std::unique_ptr<Module> A, B;
362 Function *FA, *FB1, *FB2;
363 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
364
365 createJIT(std::move(A));
366 TheJIT->addModule(std::move(B));
367
368 uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());
369 checkAccumulate(ptr);
370
371 ptr = TheJIT->getFunctionAddress(FA->getName().str());
372 checkAccumulate(ptr);
373 }
374
375 // Module A { Extern FB1, Function FA which calls FB1 },
376 // Module B { Extern FA, Function FB1, Function FB2 which calls FA },
377 // execute FB1 then FB2
378 // FIXME: this test case is not supported by MCJIT
TEST_F(MCJITMultipleModuleTest,cross_module_dependency_case3)379 TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) {
380 SKIP_UNSUPPORTED_PLATFORM;
381
382 std::unique_ptr<Module> A, B;
383 Function *FA, *FB1, *FB2;
384 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
385
386 createJIT(std::move(A));
387 TheJIT->addModule(std::move(B));
388
389 uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());
390 checkAccumulate(ptr);
391
392 ptr = TheJIT->getFunctionAddress(FB2->getName().str());
393 checkAccumulate(ptr);
394 }
395 }
396