1 //===- MCJITMultipeModuleTest.cpp - Unit tests for the MCJIT ----*- C++ -*-===// 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(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 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 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 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 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, 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; 202 203 std::unique_ptr<Module> A, B; 204 Function *FA, *FB; 205 GlobalVariable *GVA, *GVB, *GVC; 206 A.reset(createEmptyModule("A")); 207 B.reset(createEmptyModule("B")); 208 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)); 216 217 GVC = insertGlobalInt32(B.get(), "GVC", initialNum); 218 GVC->setLinkage(GlobalValue::InternalLinkage); 219 220 createJIT(std::move(A)); 221 TheJIT->addModule(std::move(B)); 222 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(nullptr, TheJIT->FindGlobalVariableNamed("GVC")); 227 228 uint64_t FBPtr = TheJIT->getFunctionAddress(FB->getName().str()); 229 TheJIT->finalizeObject(); 230 EXPECT_TRUE(0 != FBPtr); 231 int32_t(*FuncPtr)() = (int32_t(*)())FBPtr; 232 EXPECT_EQ(initialNum, FuncPtr()) 233 << "Invalid value for global returned from JITted function in module B"; 234 235 uint64_t FAPtr = TheJIT->getFunctionAddress(FA->getName().str()); 236 EXPECT_TRUE(0 != FAPtr); 237 FuncPtr = (int32_t(*)())FAPtr; 238 EXPECT_EQ(initialNum, FuncPtr()) 239 << "Invalid value for global returned from JITted function in module A"; 240 } 241 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; 248 249 std::unique_ptr<Module> A, B, C; 250 Function *FA, *FB, *FC; 251 createThreeModuleCase(A, FA, B, FB, C, FC); 252 253 createJIT(std::move(A)); 254 TheJIT->addModule(std::move(B)); 255 TheJIT->addModule(std::move(C)); 256 257 uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str()); 258 checkAdd(ptr); 259 260 ptr = TheJIT->getFunctionAddress(FB->getName().str()); 261 checkAdd(ptr); 262 263 ptr = TheJIT->getFunctionAddress(FA->getName().str()); 264 checkAdd(ptr); 265 } 266 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; 273 274 std::unique_ptr<Module> A, B, C; 275 Function *FA, *FB, *FC; 276 createThreeModuleCase(A, FA, B, FB, C, FC); 277 278 createJIT(std::move(A)); 279 TheJIT->addModule(std::move(B)); 280 TheJIT->addModule(std::move(C)); 281 282 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); 283 checkAdd(ptr); 284 285 ptr = TheJIT->getFunctionAddress(FB->getName().str()); 286 checkAdd(ptr); 287 288 ptr = TheJIT->getFunctionAddress(FC->getName().str()); 289 checkAdd(ptr); 290 } 291 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; 298 299 std::unique_ptr<Module> A, B, C; 300 Function *FA, *FB, *FC; 301 createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); 302 303 createJIT(std::move(A)); 304 TheJIT->addModule(std::move(B)); 305 TheJIT->addModule(std::move(C)); 306 307 uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str()); 308 checkAdd(ptr); 309 310 ptr = TheJIT->getFunctionAddress(FB->getName().str()); 311 checkAdd(ptr); 312 313 ptr = TheJIT->getFunctionAddress(FA->getName().str()); 314 checkAdd(ptr); 315 } 316 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; 323 324 std::unique_ptr<Module> A, B, C; 325 Function *FA, *FB, *FC; 326 createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); 327 328 createJIT(std::move(A)); 329 TheJIT->addModule(std::move(B)); 330 TheJIT->addModule(std::move(C)); 331 332 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); 333 checkAdd(ptr); 334 335 ptr = TheJIT->getFunctionAddress(FB->getName().str()); 336 checkAdd(ptr); 337 338 ptr = TheJIT->getFunctionAddress(FC->getName().str()); 339 checkAdd(ptr); 340 } 341 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; 348 349 std::unique_ptr<Module> A, B; 350 Function *FA, *FB1, *FB2; 351 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); 352 353 createJIT(std::move(A)); 354 TheJIT->addModule(std::move(B)); 355 356 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); 357 checkAccumulate(ptr); 358 359 ptr = TheJIT->getFunctionAddress(FB1->getName().str()); 360 checkAccumulate(ptr); 361 } 362 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; 369 370 std::unique_ptr<Module> A, B; 371 Function *FA, *FB1, *FB2; 372 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); 373 374 createJIT(std::move(A)); 375 TheJIT->addModule(std::move(B)); 376 377 uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str()); 378 checkAccumulate(ptr); 379 380 ptr = TheJIT->getFunctionAddress(FA->getName().str()); 381 checkAccumulate(ptr); 382 } 383 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; 390 391 std::unique_ptr<Module> A, B; 392 Function *FA, *FB1, *FB2; 393 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); 394 395 createJIT(std::move(A)); 396 TheJIT->addModule(std::move(B)); 397 398 uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str()); 399 checkAccumulate(ptr); 400 401 ptr = TheJIT->getFunctionAddress(FB2->getName().str()); 402 checkAccumulate(ptr); 403 } 404 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; 411 412 std::unique_ptr<Module> A, B; 413 Function *FA, *FB1, *FB2; 414 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); 415 416 createJIT(std::move(A)); 417 TheJIT->addModule(std::move(B)); 418 419 EXPECT_EQ(FA, TheJIT->FindFunctionNamed(FA->getName().data())); 420 EXPECT_EQ(FB1, TheJIT->FindFunctionNamed(FB1->getName().data())); 421 } 422 423 } // end anonymous namespace 424