Home | History | Annotate | Download | only in MCJIT
      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