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 23 namespace { 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 OwningPtr<Module> A, B; 94 Function *FA, *FB; 95 createTwoModuleCase(A, FA, B, FB); 96 97 createJIT(A.take()); 98 TheJIT->addModule(B.take()); 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 OwningPtr<Module> A, B; 114 Function *FA, *FB; 115 createTwoModuleCase(A, FA, B, FB); 116 117 createJIT(A.take()); 118 TheJIT->addModule(B.take()); 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 OwningPtr<Module> A, B; 135 Function *FA, *FB; 136 createTwoModuleExternCase(A, FA, B, FB); 137 138 createJIT(A.take()); 139 TheJIT->addModule(B.take()); 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 OwningPtr<Module> A, B; 156 Function *FA, *FB; 157 createTwoModuleExternCase(A, FA, B, FB); 158 159 createJIT(A.take()); 160 TheJIT->addModule(B.take()); 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 OwningPtr<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.take()); 181 TheJIT->addModule(B.take()); 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 OwningPtr<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.take()); 217 TheJIT->addModule(B.take()); 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 OwningPtr<Module> A, B, C; 239 Function *FA, *FB, *FC; 240 createThreeModuleCase(A, FA, B, FB, C, FC); 241 242 createJIT(A.take()); 243 TheJIT->addModule(B.take()); 244 TheJIT->addModule(C.take()); 245 246 uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str()); 247 checkAdd(ptr); 248 249 ptr = TheJIT->getFunctionAddress(FB->getName().str()); 250 checkAdd(ptr); 251 252 ptr = TheJIT->getFunctionAddress(FA->getName().str()); 253 checkAdd(ptr); 254 } 255 256 // Module A { Function FA }, 257 // Module B { Extern FA, Function FB which calls FA }, 258 // Module C { Extern FA, Function FC which calls FA }, 259 // execute FA, FB, FC 260 TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) { 261 OwningPtr<Module> A, B, C; 262 Function *FA, *FB, *FC; 263 createThreeModuleCase(A, FA, B, FB, C, FC); 264 265 createJIT(A.take()); 266 TheJIT->addModule(B.take()); 267 TheJIT->addModule(C.take()); 268 269 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); 270 checkAdd(ptr); 271 272 ptr = TheJIT->getFunctionAddress(FB->getName().str()); 273 checkAdd(ptr); 274 275 ptr = TheJIT->getFunctionAddress(FC->getName().str()); 276 checkAdd(ptr); 277 } 278 279 // Module A { Function FA }, 280 // Module B { Extern FA, Function FB which calls FA }, 281 // Module C { Extern FB, Function FC which calls FB }, 282 // execute FC, FB, FA 283 TEST_F(MCJITMultipleModuleTest, three_module_chain_case) { 284 OwningPtr<Module> A, B, C; 285 Function *FA, *FB, *FC; 286 createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); 287 288 createJIT(A.take()); 289 TheJIT->addModule(B.take()); 290 TheJIT->addModule(C.take()); 291 292 uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str()); 293 checkAdd(ptr); 294 295 ptr = TheJIT->getFunctionAddress(FB->getName().str()); 296 checkAdd(ptr); 297 298 ptr = TheJIT->getFunctionAddress(FA->getName().str()); 299 checkAdd(ptr); 300 } 301 302 // Module A { Function FA }, 303 // Module B { Extern FA, Function FB which calls FA }, 304 // Module C { Extern FB, Function FC which calls FB }, 305 // execute FA, FB, FC 306 TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) { 307 OwningPtr<Module> A, B, C; 308 Function *FA, *FB, *FC; 309 createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); 310 311 createJIT(A.take()); 312 TheJIT->addModule(B.take()); 313 TheJIT->addModule(C.take()); 314 315 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); 316 checkAdd(ptr); 317 318 ptr = TheJIT->getFunctionAddress(FB->getName().str()); 319 checkAdd(ptr); 320 321 ptr = TheJIT->getFunctionAddress(FC->getName().str()); 322 checkAdd(ptr); 323 } 324 325 // Module A { Extern FB, Function FA which calls FB1 }, 326 // Module B { Extern FA, Function FB1, Function FB2 which calls FA }, 327 // execute FA, then FB1 328 // FIXME: this test case is not supported by MCJIT 329 TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) { 330 SKIP_UNSUPPORTED_PLATFORM; 331 332 OwningPtr<Module> A, B; 333 Function *FA, *FB1, *FB2; 334 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); 335 336 createJIT(A.take()); 337 TheJIT->addModule(B.take()); 338 339 uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); 340 checkAccumulate(ptr); 341 342 ptr = TheJIT->getFunctionAddress(FB1->getName().str()); 343 checkAccumulate(ptr); 344 } 345 346 // Module A { Extern FB, Function FA which calls FB1 }, 347 // Module B { Extern FA, Function FB1, Function FB2 which calls FA }, 348 // execute FB1 then FA 349 // FIXME: this test case is not supported by MCJIT 350 TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) { 351 SKIP_UNSUPPORTED_PLATFORM; 352 353 OwningPtr<Module> A, B; 354 Function *FA, *FB1, *FB2; 355 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); 356 357 createJIT(A.take()); 358 TheJIT->addModule(B.take()); 359 360 uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str()); 361 checkAccumulate(ptr); 362 363 ptr = TheJIT->getFunctionAddress(FA->getName().str()); 364 checkAccumulate(ptr); 365 } 366 367 // Module A { Extern FB1, Function FA which calls FB1 }, 368 // Module B { Extern FA, Function FB1, Function FB2 which calls FA }, 369 // execute FB1 then FB2 370 // FIXME: this test case is not supported by MCJIT 371 TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) { 372 SKIP_UNSUPPORTED_PLATFORM; 373 374 OwningPtr<Module> A, B; 375 Function *FA, *FB1, *FB2; 376 createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); 377 378 createJIT(A.take()); 379 TheJIT->addModule(B.take()); 380 381 uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str()); 382 checkAccumulate(ptr); 383 384 ptr = TheJIT->getFunctionAddress(FB2->getName().str()); 385 checkAccumulate(ptr); 386 } 387 } 388