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 "MCJITTestBase.h" 16 #include "llvm/ExecutionEngine/MCJIT.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(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 207 A.reset(createEmptyModule("A")); 208 B.reset(createEmptyModule("B")); 209 210 int32_t initialNum = 7; 211 GVA = insertGlobalInt32(A.get(), "GVA", initialNum); 212 GVB = insertGlobalInt32(B.get(), "GVB", initialNum); 213 FA = startFunction(A.get(), 214 FunctionType::get(Builder.getInt32Ty(), {}, false), "FA"); 215 endFunctionWithRet(FA, Builder.CreateLoad(GVA)); 216 FB = startFunction(B.get(), 217 FunctionType::get(Builder.getInt32Ty(), {}, false), "FB"); 218 endFunctionWithRet(FB, Builder.CreateLoad(GVB)); 219 220 GVC = insertGlobalInt32(B.get(), "GVC", initialNum); 221 GVC->setLinkage(GlobalValue::InternalLinkage); 222 223 createJIT(std::move(A)); 224 TheJIT->addModule(std::move(B)); 225 226 EXPECT_EQ(GVA, TheJIT->FindGlobalVariableNamed("GVA")); 227 EXPECT_EQ(GVB, TheJIT->FindGlobalVariableNamed("GVB")); 228 EXPECT_EQ(GVC, TheJIT->FindGlobalVariableNamed("GVC",true)); 229 EXPECT_EQ(nullptr, TheJIT->FindGlobalVariableNamed("GVC")); 230 231 uint64_t FBPtr = TheJIT->getFunctionAddress(FB->getName().str()); 232 TheJIT->finalizeObject(); 233 EXPECT_TRUE(0 != FBPtr); 234 int32_t(*FuncPtr)() = (int32_t(*)())FBPtr; 235 EXPECT_EQ(initialNum, FuncPtr()) 236 << "Invalid value for global returned from JITted function in module B"; 237 238 uint64_t FAPtr = TheJIT->getFunctionAddress(FA->getName().str()); 239 EXPECT_TRUE(0 != FAPtr); 240 FuncPtr = (int32_t(*)())FAPtr; 241 EXPECT_EQ(initialNum, FuncPtr()) 242 << "Invalid value for global returned from JITted function in module A"; 243 } 244 245 // Module A { Function FA }, 246 // Module B { Extern FA, Function FB which calls FA }, 247 // Module C { Extern FA, Function FC which calls FA }, 248 // execute FC, FB, FA 249 TEST_F(MCJITMultipleModuleTest, three_module_case) { 250 SKIP_UNSUPPORTED_PLATFORM; 251 252 std::unique_ptr<Module> A, B, C; 253 Function *FA, *FB, *FC; 254 createThreeModuleCase(A, FA, B, FB, C, FC); 255 256 createJIT(std::move(A)); 257 TheJIT->addModule(std::move(B)); 258 TheJIT->addModule(std::move(C)); 259 260 uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str()); 261 checkAdd(ptr); 262 263 ptr = TheJIT->getFunctionAddress(FB->getName().str()); 264 checkAdd(ptr); 265 266 ptr = TheJIT->getFunctionAddress(FA->getName().str()); 267 checkAdd(ptr); 268 } 269 270 // Module A { Function FA }, 271 // Module B { Extern FA, Function FB which calls FA }, 272 // Module C { Extern FA, Function FC which calls FA }, 273 // execute FA, FB, FC 274 TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) { 275 SKIP_UNSUPPORTED_PLATFORM; 276 277 std::unique_ptr<Module> A, B, C; 278 Function *FA, *FB, *FC; 279 createThreeModuleCase(A, FA, B, FB, C, FC); 280 281 createJIT(std::move(A)); 282 TheJIT->addModule(std::move(B)); 283 TheJIT->addModule(std::move(C)); 284 285 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); 286 checkAdd(ptr); 287 288 ptr = TheJIT->getFunctionAddress(FB->getName().str()); 289 checkAdd(ptr); 290 291 ptr = TheJIT->getFunctionAddress(FC->getName().str()); 292 checkAdd(ptr); 293 } 294 295 // Module A { Function FA }, 296 // Module B { Extern FA, Function FB which calls FA }, 297 // Module C { Extern FB, Function FC which calls FB }, 298 // execute FC, FB, FA 299 TEST_F(MCJITMultipleModuleTest, three_module_chain_case) { 300 SKIP_UNSUPPORTED_PLATFORM; 301 302 std::unique_ptr<Module> A, B, C; 303 Function *FA, *FB, *FC; 304 createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); 305 306 createJIT(std::move(A)); 307 TheJIT->addModule(std::move(B)); 308 TheJIT->addModule(std::move(C)); 309 310 uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str()); 311 checkAdd(ptr); 312 313 ptr = TheJIT->getFunctionAddress(FB->getName().str()); 314 checkAdd(ptr); 315 316 ptr = TheJIT->getFunctionAddress(FA->getName().str()); 317 checkAdd(ptr); 318 } 319 320 // Module A { Function FA }, 321 // Module B { Extern FA, Function FB which calls FA }, 322 // Module C { Extern FB, Function FC which calls FB }, 323 // execute FA, FB, FC 324 TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) { 325 SKIP_UNSUPPORTED_PLATFORM; 326 327 std::unique_ptr<Module> A, B, C; 328 Function *FA, *FB, *FC; 329 createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); 330 331 createJIT(std::move(A)); 332 TheJIT->addModule(std::move(B)); 333 TheJIT->addModule(std::move(C)); 334 335 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); 336 checkAdd(ptr); 337 338 ptr = TheJIT->getFunctionAddress(FB->getName().str()); 339 checkAdd(ptr); 340 341 ptr = TheJIT->getFunctionAddress(FC->getName().str()); 342 checkAdd(ptr); 343 } 344 345 // Module A { Extern FB, Function FA which calls FB1 }, 346 // Module B { Extern FA, Function FB1, Function FB2 which calls FA }, 347 // execute FA, then FB1 348 // FIXME: this test case is not supported by MCJIT 349 TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) { 350 SKIP_UNSUPPORTED_PLATFORM; 351 352 std::unique_ptr<Module> A, B; 353 Function *FA, *FB1, *FB2; 354 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); 355 356 createJIT(std::move(A)); 357 TheJIT->addModule(std::move(B)); 358 359 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); 360 checkAccumulate(ptr); 361 362 ptr = TheJIT->getFunctionAddress(FB1->getName().str()); 363 checkAccumulate(ptr); 364 } 365 366 // Module A { Extern FB, Function FA which calls FB1 }, 367 // Module B { Extern FA, Function FB1, Function FB2 which calls FA }, 368 // execute FB1 then FA 369 // FIXME: this test case is not supported by MCJIT 370 TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) { 371 SKIP_UNSUPPORTED_PLATFORM; 372 373 std::unique_ptr<Module> A, B; 374 Function *FA, *FB1, *FB2; 375 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); 376 377 createJIT(std::move(A)); 378 TheJIT->addModule(std::move(B)); 379 380 uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str()); 381 checkAccumulate(ptr); 382 383 ptr = TheJIT->getFunctionAddress(FA->getName().str()); 384 checkAccumulate(ptr); 385 } 386 387 // Module A { Extern FB1, Function FA which calls FB1 }, 388 // Module B { Extern FA, Function FB1, Function FB2 which calls FA }, 389 // execute FB1 then FB2 390 // FIXME: this test case is not supported by MCJIT 391 TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) { 392 SKIP_UNSUPPORTED_PLATFORM; 393 394 std::unique_ptr<Module> A, B; 395 Function *FA, *FB1, *FB2; 396 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); 397 398 createJIT(std::move(A)); 399 TheJIT->addModule(std::move(B)); 400 401 uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str()); 402 checkAccumulate(ptr); 403 404 ptr = TheJIT->getFunctionAddress(FB2->getName().str()); 405 checkAccumulate(ptr); 406 } 407 408 // Test that FindFunctionNamed finds the definition of 409 // a function in the correct module. We check two functions 410 // in two different modules, to make sure that for at least 411 // one of them MCJIT had to ignore the extern declaration. 412 TEST_F(MCJITMultipleModuleTest, FindFunctionNamed_test) { 413 SKIP_UNSUPPORTED_PLATFORM; 414 415 std::unique_ptr<Module> A, B; 416 Function *FA, *FB1, *FB2; 417 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); 418 419 createJIT(std::move(A)); 420 TheJIT->addModule(std::move(B)); 421 422 EXPECT_EQ(FA, TheJIT->FindFunctionNamed(FA->getName().data())); 423 EXPECT_EQ(FB1, TheJIT->FindFunctionNamed(FB1->getName().data())); 424 } 425 426 } // end anonymous namespace 427