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 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 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 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(A.release()); 98 TheJIT->addModule(B.release()); 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 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(A.release()); 118 TheJIT->addModule(B.release()); 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 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(A.release()); 139 TheJIT->addModule(B.release()); 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 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(A.release()); 160 TheJIT->addModule(B.release()); 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 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(A.release()); 181 TheJIT->addModule(B.release()); 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 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(A.release()); 217 TheJIT->addModule(B.release()); 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 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(A.release()); 245 TheJIT->addModule(B.release()); 246 TheJIT->addModule(C.release()); 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 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(A.release()); 270 TheJIT->addModule(B.release()); 271 TheJIT->addModule(C.release()); 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 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(A.release()); 295 TheJIT->addModule(B.release()); 296 TheJIT->addModule(C.release()); 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 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(A.release()); 320 TheJIT->addModule(B.release()); 321 TheJIT->addModule(C.release()); 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 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(A.release()); 345 TheJIT->addModule(B.release()); 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 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(A.release()); 366 TheJIT->addModule(B.release()); 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 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(A.release()); 387 TheJIT->addModule(B.release()); 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