1 //===- MCJITMultipeModuleTest.cpp - Unit tests for the MCJIT---------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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 //===----------------------------------------------------------------------===//
15 #include "llvm/ExecutionEngine/MCJIT.h"
16 #include "MCJITTestBase.h"
17 #include "gtest/gtest.h"
23 class MCJITMultipleModuleTest : public testing::Test, public MCJITTestBase {};
25 // FIXME: ExecutionEngine has no support empty modules
27 TEST_F(MCJITMultipleModuleTest, multiple_empty_modules) {
28 SKIP_UNSUPPORTED_PLATFORM;
32 EXPECT_NE(0, TheJIT->getObjectImage())
33 << "Unable to generate executable loaded object image";
35 TheJIT->addModule(createEmptyModule("<other module>"));
36 TheJIT->addModule(createEmptyModule("<other other module>"));
39 EXPECT_NE(0, TheJIT->getObjectImage())
40 << "Unable to generate executable loaded object image";
44 // Helper Function to test add operation
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));
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));
68 // FIXME: ExecutionEngine has no support empty modules
70 TEST_F(MCJITMultipleModuleTest, multiple_empty_modules) {
71 SKIP_UNSUPPORTED_PLATFORM;
75 EXPECT_NE(0, TheJIT->getObjectImage())
76 << "Unable to generate executable loaded object image";
78 TheJIT->addModule(createEmptyModule("<other module>"));
79 TheJIT->addModule(createEmptyModule("<other other module>"));
82 EXPECT_NE(0, TheJIT->getObjectImage())
83 << "Unable to generate executable loaded object image";
87 // Module A { Function FA },
88 // Module B { Function FB },
90 TEST_F(MCJITMultipleModuleTest, two_module_case) {
91 SKIP_UNSUPPORTED_PLATFORM;
93 std::unique_ptr<Module> A, B;
95 createTwoModuleCase(A, FA, B, FB);
97 createJIT(std::move(A));
98 TheJIT->addModule(std::move(B));
100 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
103 ptr = TheJIT->getFunctionAddress(FB->getName().str());
107 // Module A { Function FA },
108 // Module B { Function FB },
109 // execute FB then FA
110 TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) {
111 SKIP_UNSUPPORTED_PLATFORM;
113 std::unique_ptr<Module> A, B;
115 createTwoModuleCase(A, FA, B, FB);
117 createJIT(std::move(A));
118 TheJIT->addModule(std::move(B));
120 uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
121 TheJIT->finalizeObject();
124 ptr = TheJIT->getFunctionAddress(FA->getName().str());
128 // Module A { Function FA },
129 // Module B { Extern FA, Function FB which calls FA },
130 // execute FB then FA
131 TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) {
132 SKIP_UNSUPPORTED_PLATFORM;
134 std::unique_ptr<Module> A, B;
136 createTwoModuleExternCase(A, FA, B, FB);
138 createJIT(std::move(A));
139 TheJIT->addModule(std::move(B));
141 uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
142 TheJIT->finalizeObject();
145 ptr = TheJIT->getFunctionAddress(FA->getName().str());
149 // Module A { Function FA },
150 // Module B { Extern FA, Function FB which calls FA },
151 // execute FA then FB
152 TEST_F(MCJITMultipleModuleTest, two_module_extern_case) {
153 SKIP_UNSUPPORTED_PLATFORM;
155 std::unique_ptr<Module> A, B;
157 createTwoModuleExternCase(A, FA, B, FB);
159 createJIT(std::move(A));
160 TheJIT->addModule(std::move(B));
162 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
165 ptr = TheJIT->getFunctionAddress(FB->getName().str());
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
172 TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) {
173 SKIP_UNSUPPORTED_PLATFORM;
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);
180 createJIT(std::move(A));
181 TheJIT->addModule(std::move(B));
183 uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
184 TheJIT->finalizeObject();
187 ptr = TheJIT->getFunctionAddress(FA2->getName().str());
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 },
196 // Module A { Global Variable GVA, Function FA loads GVA },
197 // Module B { Global Variable GVB, Internal Global GVC, Function FB loads GVB },
198 // execute FB then FA, also check that the global variables are properly accesible
199 // through the ExecutionEngine APIs
200 TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) {
201 SKIP_UNSUPPORTED_PLATFORM;
203 std::unique_ptr<Module> A, B;
205 GlobalVariable *GVA, *GVB, *GVC;
206 A.reset(createEmptyModule("A"));
207 B.reset(createEmptyModule("B"));
209 int32_t initialNum = 7;
210 GVA = insertGlobalInt32(A.get(), "GVA", initialNum);
211 GVB = insertGlobalInt32(B.get(), "GVB", initialNum);
212 FA = startFunction<int32_t(void)>(A.get(), "FA");
213 endFunctionWithRet(FA, Builder.CreateLoad(GVA));
214 FB = startFunction<int32_t(void)>(B.get(), "FB");
215 endFunctionWithRet(FB, Builder.CreateLoad(GVB));
217 GVC = insertGlobalInt32(B.get(), "GVC", initialNum);
218 GVC->setLinkage(GlobalValue::InternalLinkage);
220 createJIT(std::move(A));
221 TheJIT->addModule(std::move(B));
223 EXPECT_EQ(GVA, TheJIT->FindGlobalVariableNamed("GVA"));
224 EXPECT_EQ(GVB, TheJIT->FindGlobalVariableNamed("GVB"));
225 EXPECT_EQ(GVC, TheJIT->FindGlobalVariableNamed("GVC",true));
226 EXPECT_EQ(NULL, TheJIT->FindGlobalVariableNamed("GVC"));
228 uint64_t FBPtr = TheJIT->getFunctionAddress(FB->getName().str());
229 TheJIT->finalizeObject();
230 EXPECT_TRUE(0 != FBPtr);
231 int32_t(*FuncPtr)(void) = (int32_t(*)(void))FBPtr;
232 EXPECT_EQ(initialNum, FuncPtr())
233 << "Invalid value for global returned from JITted function in module B";
235 uint64_t FAPtr = TheJIT->getFunctionAddress(FA->getName().str());
236 EXPECT_TRUE(0 != FAPtr);
237 FuncPtr = (int32_t(*)(void))FAPtr;
238 EXPECT_EQ(initialNum, FuncPtr())
239 << "Invalid value for global returned from JITted function in module A";
242 // Module A { Function FA },
243 // Module B { Extern FA, Function FB which calls FA },
244 // Module C { Extern FA, Function FC which calls FA },
245 // execute FC, FB, FA
246 TEST_F(MCJITMultipleModuleTest, three_module_case) {
247 SKIP_UNSUPPORTED_PLATFORM;
249 std::unique_ptr<Module> A, B, C;
250 Function *FA, *FB, *FC;
251 createThreeModuleCase(A, FA, B, FB, C, FC);
253 createJIT(std::move(A));
254 TheJIT->addModule(std::move(B));
255 TheJIT->addModule(std::move(C));
257 uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());
260 ptr = TheJIT->getFunctionAddress(FB->getName().str());
263 ptr = TheJIT->getFunctionAddress(FA->getName().str());
267 // Module A { Function FA },
268 // Module B { Extern FA, Function FB which calls FA },
269 // Module C { Extern FA, Function FC which calls FA },
270 // execute FA, FB, FC
271 TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) {
272 SKIP_UNSUPPORTED_PLATFORM;
274 std::unique_ptr<Module> A, B, C;
275 Function *FA, *FB, *FC;
276 createThreeModuleCase(A, FA, B, FB, C, FC);
278 createJIT(std::move(A));
279 TheJIT->addModule(std::move(B));
280 TheJIT->addModule(std::move(C));
282 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
285 ptr = TheJIT->getFunctionAddress(FB->getName().str());
288 ptr = TheJIT->getFunctionAddress(FC->getName().str());
292 // Module A { Function FA },
293 // Module B { Extern FA, Function FB which calls FA },
294 // Module C { Extern FB, Function FC which calls FB },
295 // execute FC, FB, FA
296 TEST_F(MCJITMultipleModuleTest, three_module_chain_case) {
297 SKIP_UNSUPPORTED_PLATFORM;
299 std::unique_ptr<Module> A, B, C;
300 Function *FA, *FB, *FC;
301 createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC);
303 createJIT(std::move(A));
304 TheJIT->addModule(std::move(B));
305 TheJIT->addModule(std::move(C));
307 uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());
310 ptr = TheJIT->getFunctionAddress(FB->getName().str());
313 ptr = TheJIT->getFunctionAddress(FA->getName().str());
317 // Module A { Function FA },
318 // Module B { Extern FA, Function FB which calls FA },
319 // Module C { Extern FB, Function FC which calls FB },
320 // execute FA, FB, FC
321 TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) {
322 SKIP_UNSUPPORTED_PLATFORM;
324 std::unique_ptr<Module> A, B, C;
325 Function *FA, *FB, *FC;
326 createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC);
328 createJIT(std::move(A));
329 TheJIT->addModule(std::move(B));
330 TheJIT->addModule(std::move(C));
332 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
335 ptr = TheJIT->getFunctionAddress(FB->getName().str());
338 ptr = TheJIT->getFunctionAddress(FC->getName().str());
342 // Module A { Extern FB, Function FA which calls FB1 },
343 // Module B { Extern FA, Function FB1, Function FB2 which calls FA },
344 // execute FA, then FB1
345 // FIXME: this test case is not supported by MCJIT
346 TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) {
347 SKIP_UNSUPPORTED_PLATFORM;
349 std::unique_ptr<Module> A, B;
350 Function *FA, *FB1, *FB2;
351 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
353 createJIT(std::move(A));
354 TheJIT->addModule(std::move(B));
356 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
357 checkAccumulate(ptr);
359 ptr = TheJIT->getFunctionAddress(FB1->getName().str());
360 checkAccumulate(ptr);
363 // Module A { Extern FB, Function FA which calls FB1 },
364 // Module B { Extern FA, Function FB1, Function FB2 which calls FA },
365 // execute FB1 then FA
366 // FIXME: this test case is not supported by MCJIT
367 TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) {
368 SKIP_UNSUPPORTED_PLATFORM;
370 std::unique_ptr<Module> A, B;
371 Function *FA, *FB1, *FB2;
372 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
374 createJIT(std::move(A));
375 TheJIT->addModule(std::move(B));
377 uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());
378 checkAccumulate(ptr);
380 ptr = TheJIT->getFunctionAddress(FA->getName().str());
381 checkAccumulate(ptr);
384 // Module A { Extern FB1, Function FA which calls FB1 },
385 // Module B { Extern FA, Function FB1, Function FB2 which calls FA },
386 // execute FB1 then FB2
387 // FIXME: this test case is not supported by MCJIT
388 TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) {
389 SKIP_UNSUPPORTED_PLATFORM;
391 std::unique_ptr<Module> A, B;
392 Function *FA, *FB1, *FB2;
393 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
395 createJIT(std::move(A));
396 TheJIT->addModule(std::move(B));
398 uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());
399 checkAccumulate(ptr);
401 ptr = TheJIT->getFunctionAddress(FB2->getName().str());
402 checkAccumulate(ptr);
405 // Test that FindFunctionNamed finds the definition of
406 // a function in the correct module. We check two functions
407 // in two different modules, to make sure that for at least
408 // one of them MCJIT had to ignore the extern declaration.
409 TEST_F(MCJITMultipleModuleTest, FindFunctionNamed_test) {
410 SKIP_UNSUPPORTED_PLATFORM;
412 std::unique_ptr<Module> A, B;
413 Function *FA, *FB1, *FB2;
414 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
416 createJIT(std::move(A));
417 TheJIT->addModule(std::move(B));
419 EXPECT_EQ(FA, TheJIT->FindFunctionNamed(FA->getName().data()));
420 EXPECT_EQ(FB1, TheJIT->FindFunctionNamed(FB1->getName().data()));