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 class MCJITMultipleModuleTest : public testing::Test, public MCJITTestBase { 22 public: 23 virtual ~MCJITMultipleModuleTest(); 24 }; 25 26 // Provide out-of-line definition to prevent weak vtable. 27 MCJITMultipleModuleTest::~MCJITMultipleModuleTest() {} 28 29 namespace { 30 31 // FIXME: ExecutionEngine has no support empty modules 32 /* 33 TEST_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 51 void 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 63 void 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 /* 76 TEST_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 96 TEST_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 116 TEST_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 137 TEST_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 158 TEST_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 178 TEST_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 205 TEST_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 243 TEST_F(MCJITMultipleModuleTest, three_module_case) { 244 SKIP_UNSUPPORTED_PLATFORM; 245 246 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 268 TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) { 269 SKIP_UNSUPPORTED_PLATFORM; 270 271 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 293 TEST_F(MCJITMultipleModuleTest, three_module_chain_case) { 294 SKIP_UNSUPPORTED_PLATFORM; 295 296 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 318 TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) { 319 SKIP_UNSUPPORTED_PLATFORM; 320 321 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 343 TEST_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 364 TEST_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 385 TEST_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 } 402