brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.6 KiB · 710ce6d Raw
426 lines · cpp
1//===- MCJITMultipeModuleTest.cpp - Unit tests for the MCJIT ----*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This test suite verifies MCJIT for handling multiple modules in a single10// ExecutionEngine by building multiple modules, making function calls across11// modules, accessing global variables, etc.12//===----------------------------------------------------------------------===//13 14#include "MCJITTestBase.h"15#include "llvm/ExecutionEngine/MCJIT.h"16#include "gtest/gtest.h"17 18using namespace llvm;19 20namespace {21 22class MCJITMultipleModuleTest : public testing::Test, public MCJITTestBase {};23 24// FIXME: ExecutionEngine has no support empty modules25/*26TEST_F(MCJITMultipleModuleTest, multiple_empty_modules) {27  SKIP_UNSUPPORTED_PLATFORM;28 29  createJIT(M.take());30  // JIT-compile31  EXPECT_NE(0, TheJIT->getObjectImage())32    << "Unable to generate executable loaded object image";33 34  TheJIT->addModule(createEmptyModule("<other module>"));35  TheJIT->addModule(createEmptyModule("<other other module>"));36 37  // JIT again38  EXPECT_NE(0, TheJIT->getObjectImage())39    << "Unable to generate executable loaded object image";40}41*/42 43// Helper Function to test add operation44void checkAdd(uint64_t ptr) {45  ASSERT_TRUE(ptr != 0) << "Unable to get pointer to function.";46  int (*AddPtr)(int, int) = (int (*)(int, int))ptr;47  EXPECT_EQ(0, AddPtr(0, 0));48  EXPECT_EQ(1, AddPtr(1, 0));49  EXPECT_EQ(3, AddPtr(1, 2));50  EXPECT_EQ(-5, AddPtr(-2, -3));51  EXPECT_EQ(30, AddPtr(10, 20));52  EXPECT_EQ(-30, AddPtr(-10, -20));53  EXPECT_EQ(-40, AddPtr(-10, -30));54}55 56void checkAccumulate(uint64_t ptr) {57  ASSERT_TRUE(ptr != 0) << "Unable to get pointer to function.";58  int32_t (*FPtr)(int32_t) = (int32_t (*)(int32_t))(intptr_t)ptr;59  EXPECT_EQ(0, FPtr(0));60  EXPECT_EQ(1, FPtr(1));61  EXPECT_EQ(3, FPtr(2));62  EXPECT_EQ(6, FPtr(3));63  EXPECT_EQ(10, FPtr(4));64  EXPECT_EQ(15, FPtr(5));65}66 67// FIXME: ExecutionEngine has no support empty modules68/*69TEST_F(MCJITMultipleModuleTest, multiple_empty_modules) {70  SKIP_UNSUPPORTED_PLATFORM;71 72  createJIT(M.take());73  // JIT-compile74  EXPECT_NE(0, TheJIT->getObjectImage())75    << "Unable to generate executable loaded object image";76 77  TheJIT->addModule(createEmptyModule("<other module>"));78  TheJIT->addModule(createEmptyModule("<other other module>"));79 80  // JIT again81  EXPECT_NE(0, TheJIT->getObjectImage())82    << "Unable to generate executable loaded object image";83}84*/85 86// Module A { Function FA },87// Module B { Function FB },88// execute FA then FB89TEST_F(MCJITMultipleModuleTest, two_module_case) {90  SKIP_UNSUPPORTED_PLATFORM;91 92  std::unique_ptr<Module> A, B;93  Function *FA, *FB;94  createTwoModuleCase(A, FA, B, FB);95 96  createJIT(std::move(A));97  TheJIT->addModule(std::move(B));98 99  uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());100  checkAdd(ptr);101 102  ptr = TheJIT->getFunctionAddress(FB->getName().str());103  checkAdd(ptr);104}105 106// Module A { Function FA },107// Module B { Function FB },108// execute FB then FA109TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) {110  SKIP_UNSUPPORTED_PLATFORM;111 112  std::unique_ptr<Module> A, B;113  Function *FA, *FB;114  createTwoModuleCase(A, FA, B, FB);115 116  createJIT(std::move(A));117  TheJIT->addModule(std::move(B));118 119  uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());120  TheJIT->finalizeObject();121  checkAdd(ptr);122 123  ptr = TheJIT->getFunctionAddress(FA->getName().str());124  checkAdd(ptr);125}126 127// Module A { Function FA },128// Module B { Extern FA, Function FB which calls FA },129// execute FB then FA130TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) {131  SKIP_UNSUPPORTED_PLATFORM;132 133  std::unique_ptr<Module> A, B;134  Function *FA, *FB;135  createTwoModuleExternCase(A, FA, B, FB);136 137  createJIT(std::move(A));138  TheJIT->addModule(std::move(B));139 140  uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());141  TheJIT->finalizeObject();142  checkAdd(ptr);143 144  ptr = TheJIT->getFunctionAddress(FA->getName().str());145  checkAdd(ptr);146}147 148// Module A { Function FA },149// Module B { Extern FA, Function FB which calls FA },150// execute FA then FB151TEST_F(MCJITMultipleModuleTest, two_module_extern_case) {152  SKIP_UNSUPPORTED_PLATFORM;153 154  std::unique_ptr<Module> A, B;155  Function *FA, *FB;156  createTwoModuleExternCase(A, FA, B, FB);157 158  createJIT(std::move(A));159  TheJIT->addModule(std::move(B));160 161  uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());162  checkAdd(ptr);163 164  ptr = TheJIT->getFunctionAddress(FB->getName().str());165  checkAdd(ptr);166}167 168// Module A { Function FA1, Function FA2 which calls FA1 },169// Module B { Extern FA1, Function FB which calls FA1 },170// execute FB then FA2171TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) {172  SKIP_UNSUPPORTED_PLATFORM;173 174  std::unique_ptr<Module> A, B;175  Function *FA1, *FA2, *FB;176  createTwoModuleExternCase(A, FA1, B, FB);177  FA2 = insertSimpleCallFunction(A.get(), FA1);178 179  createJIT(std::move(A));180  TheJIT->addModule(std::move(B));181 182  uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());183  TheJIT->finalizeObject();184  checkAdd(ptr);185 186  ptr = TheJIT->getFunctionAddress(FA2->getName().str());187  checkAdd(ptr);188}189 190// TODO:191// Module A { Extern Global GVB, Global Variable GVA, Function FA loads GVB },192// Module B { Extern Global GVA, Global Variable GVB, Function FB loads GVA },193 194 195// Module A { Global Variable GVA, Function FA loads GVA },196// Module B { Global Variable GVB, Internal Global GVC, Function FB loads GVB },197// execute FB then FA, also check that the global variables are properly accesible198// through the ExecutionEngine APIs199TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) {200  SKIP_UNSUPPORTED_PLATFORM;201 202  std::unique_ptr<Module> A, B;203  Function *FA, *FB;204  GlobalVariable *GVA, *GVB, *GVC;205 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(A.get(),213                     FunctionType::get(Builder.getInt32Ty(), {}, false), "FA");214  endFunctionWithRet(FA, Builder.CreateLoad(Builder.getInt32Ty(), GVA));215  FB = startFunction(B.get(),216                     FunctionType::get(Builder.getInt32Ty(), {}, false), "FB");217  endFunctionWithRet(FB, Builder.CreateLoad(Builder.getInt32Ty(), GVB));218 219  GVC = insertGlobalInt32(B.get(), "GVC", initialNum);220  GVC->setLinkage(GlobalValue::InternalLinkage);221 222  createJIT(std::move(A));223  TheJIT->addModule(std::move(B));224 225  EXPECT_EQ(GVA, TheJIT->FindGlobalVariableNamed("GVA"));226  EXPECT_EQ(GVB, TheJIT->FindGlobalVariableNamed("GVB"));227  EXPECT_EQ(GVC, TheJIT->FindGlobalVariableNamed("GVC",true));228  EXPECT_EQ(nullptr, TheJIT->FindGlobalVariableNamed("GVC"));229 230  uint64_t FBPtr = TheJIT->getFunctionAddress(FB->getName().str());231  TheJIT->finalizeObject();232  EXPECT_TRUE(0 != FBPtr);233  int32_t(*FuncPtr)() = (int32_t(*)())FBPtr;234  EXPECT_EQ(initialNum, FuncPtr())235    << "Invalid value for global returned from JITted function in module B";236 237  uint64_t FAPtr = TheJIT->getFunctionAddress(FA->getName().str());238  EXPECT_TRUE(0 != FAPtr);239  FuncPtr = (int32_t(*)())FAPtr;240  EXPECT_EQ(initialNum, FuncPtr())241    << "Invalid value for global returned from JITted function in module A";242}243 244// Module A { Function FA },245// Module B { Extern FA, Function FB which calls FA },246// Module C { Extern FA, Function FC which calls FA },247// execute FC, FB, FA248TEST_F(MCJITMultipleModuleTest, three_module_case) {249  SKIP_UNSUPPORTED_PLATFORM;250 251  std::unique_ptr<Module> A, B, C;252  Function *FA, *FB, *FC;253  createThreeModuleCase(A, FA, B, FB, C, FC);254 255  createJIT(std::move(A));256  TheJIT->addModule(std::move(B));257  TheJIT->addModule(std::move(C));258 259  uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());260  checkAdd(ptr);261 262  ptr = TheJIT->getFunctionAddress(FB->getName().str());263  checkAdd(ptr);264 265  ptr = TheJIT->getFunctionAddress(FA->getName().str());266  checkAdd(ptr);267}268 269// Module A { Function FA },270// Module B { Extern FA, Function FB which calls FA },271// Module C { Extern FA, Function FC which calls FA },272// execute FA, FB, FC273TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) {274  SKIP_UNSUPPORTED_PLATFORM;275 276  std::unique_ptr<Module> A, B, C;277  Function *FA, *FB, *FC;278  createThreeModuleCase(A, FA, B, FB, C, FC);279 280  createJIT(std::move(A));281  TheJIT->addModule(std::move(B));282  TheJIT->addModule(std::move(C));283 284  uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());285  checkAdd(ptr);286 287  ptr = TheJIT->getFunctionAddress(FB->getName().str());288  checkAdd(ptr);289 290  ptr = TheJIT->getFunctionAddress(FC->getName().str());291  checkAdd(ptr);292}293 294// Module A { Function FA },295// Module B { Extern FA, Function FB which calls FA },296// Module C { Extern FB, Function FC which calls FB },297// execute FC, FB, FA298TEST_F(MCJITMultipleModuleTest, three_module_chain_case) {299  SKIP_UNSUPPORTED_PLATFORM;300 301  std::unique_ptr<Module> A, B, C;302  Function *FA, *FB, *FC;303  createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC);304 305  createJIT(std::move(A));306  TheJIT->addModule(std::move(B));307  TheJIT->addModule(std::move(C));308 309  uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());310  checkAdd(ptr);311 312  ptr = TheJIT->getFunctionAddress(FB->getName().str());313  checkAdd(ptr);314 315  ptr = TheJIT->getFunctionAddress(FA->getName().str());316  checkAdd(ptr);317}318 319// Module A { Function FA },320// Module B { Extern FA, Function FB which calls FA },321// Module C { Extern FB, Function FC which calls FB },322// execute FA, FB, FC323TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) {324  SKIP_UNSUPPORTED_PLATFORM;325 326  std::unique_ptr<Module> A, B, C;327  Function *FA, *FB, *FC;328  createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC);329 330  createJIT(std::move(A));331  TheJIT->addModule(std::move(B));332  TheJIT->addModule(std::move(C));333 334  uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());335  checkAdd(ptr);336 337  ptr = TheJIT->getFunctionAddress(FB->getName().str());338  checkAdd(ptr);339 340  ptr = TheJIT->getFunctionAddress(FC->getName().str());341  checkAdd(ptr);342}343 344// Module A { Extern FB, Function FA which calls FB1 },345// Module B { Extern FA, Function FB1, Function FB2 which calls FA },346// execute FA, then FB1347// FIXME: this test case is not supported by MCJIT348TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) {349  SKIP_UNSUPPORTED_PLATFORM;350 351  std::unique_ptr<Module> A, B;352  Function *FA, *FB1, *FB2;353  createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);354 355  createJIT(std::move(A));356  TheJIT->addModule(std::move(B));357 358  uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());359  checkAccumulate(ptr);360 361  ptr = TheJIT->getFunctionAddress(FB1->getName().str());362  checkAccumulate(ptr);363}364 365// Module A { Extern FB, Function FA which calls FB1 },366// Module B { Extern FA, Function FB1, Function FB2 which calls FA },367// execute FB1 then FA368// FIXME: this test case is not supported by MCJIT369TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) {370  SKIP_UNSUPPORTED_PLATFORM;371 372  std::unique_ptr<Module> A, B;373  Function *FA, *FB1, *FB2;374  createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);375 376  createJIT(std::move(A));377  TheJIT->addModule(std::move(B));378 379  uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());380  checkAccumulate(ptr);381 382  ptr = TheJIT->getFunctionAddress(FA->getName().str());383  checkAccumulate(ptr);384}385 386// Module A { Extern FB1, Function FA which calls FB1 },387// Module B { Extern FA, Function FB1, Function FB2 which calls FA },388// execute FB1 then FB2389// FIXME: this test case is not supported by MCJIT390TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) {391  SKIP_UNSUPPORTED_PLATFORM;392 393  std::unique_ptr<Module> A, B;394  Function *FA, *FB1, *FB2;395  createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);396 397  createJIT(std::move(A));398  TheJIT->addModule(std::move(B));399 400  uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());401  checkAccumulate(ptr);402 403  ptr = TheJIT->getFunctionAddress(FB2->getName().str());404  checkAccumulate(ptr);405}406 407// Test that FindFunctionNamed finds the definition of408// a function in the correct module. We check two functions409// in two different modules, to make sure that for at least410// one of them MCJIT had to ignore the extern declaration.411TEST_F(MCJITMultipleModuleTest, FindFunctionNamed_test) {412  SKIP_UNSUPPORTED_PLATFORM;413 414  std::unique_ptr<Module> A, B;415  Function *FA, *FB1, *FB2;416  createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);417 418  createJIT(std::move(A));419  TheJIT->addModule(std::move(B));420 421  EXPECT_EQ(FA, TheJIT->FindFunctionNamed(FA->getName().data()));422  EXPECT_EQ(FB1, TheJIT->FindFunctionNamed(FB1->getName().data()));423}424 425} // end anonymous namespace426