Index: unittests/ExecutionEngine/MCJIT/CMakeLists.txt =================================================================== --- unittests/ExecutionEngine/MCJIT/CMakeLists.txt +++ unittests/ExecutionEngine/MCJIT/CMakeLists.txt @@ -11,6 +11,7 @@ MCJITTest.cpp MCJITCAPITest.cpp MCJITMemoryManagerTest.cpp + MCJITMultipleModuleTest.cpp MCJITObjectCacheTest.cpp ) Index: unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp =================================================================== --- /dev/null +++ unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp @@ -0,0 +1,162 @@ +//===- MCJITMultipeModuleTest.cpp - Unit tests for the MCJIT ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This test suite verifies basic MCJIT functionality such as making function +// calls, using global variables, and compiling multpile modules. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/MCJIT.h" +#include "MCJITTestBase.h" +#include "gtest/gtest.h" + +using namespace llvm; + +class MCJITMultipleModuleTest : public testing::Test, public MCJITTestBase { +protected: + + virtual void SetUp() { + M.reset(createEmptyModule("
")); + } +}; + +namespace { + +// FIXME: ExecutionEngine has no support empty modules +/* +TEST_F(MCJITMultipleModuleTest, multiple_empty_modules) { + SKIP_UNSUPPORTED_PLATFORM; + + createJIT(M.take()); + // JIT-compile + EXPECT_NE(0, TheJIT->getObjectImage()) + << "Unable to generate executable loaded object image"; + + TheJIT->addModule(createEmptyModule("")); + TheJIT->addModule(createEmptyModule("")); + + // JIT again + EXPECT_NE(0, TheJIT->getObjectImage()) + << "Unable to generate executable loaded object image"; +} +*/ + +void testAdd(void *vPtr) { + ASSERT_TRUE(0!=vPtr); + int32_t(*FuncPtr)(int32_t, int32_t) = (int32_t(*)(int32_t, int32_t))(intptr_t)vPtr; + EXPECT_EQ(0, FuncPtr(0, 0)); + EXPECT_EQ(1, FuncPtr(1, 0)); + EXPECT_EQ(2, FuncPtr(1, 1)); + EXPECT_EQ(-40, FuncPtr(-10, -30)); +} + +// Module A { Function FA }, +// Module B { Function FB }, +// execute FA then FB +TEST_F(MCJITMultipleModuleTest, two_module_case) { + SKIP_UNSUPPORTED_PLATFORM; + OwningPtr A, B; + Function *FA, *FB; + createTwoModuleCase(A, FA, B, FB); + + createJIT(A.take()); + Module *SaveB = B.get(); + TheJIT->addModule(B.take()); + + void *vPtr = TheJIT->getPointerToFunction(FA); + TheJIT->finalizeModule(SaveB); + testAdd(vPtr); + + vPtr = TheJIT->getPointerToFunction(FB); + testAdd(vPtr); + +} + +// Module A { Function FA }, +// Module B { Function FB }, +// execute FB then FA +TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) { + SKIP_UNSUPPORTED_PLATFORM; + OwningPtr A, B; + Function *FA, *FB; + createTwoModuleCase(A, FA, B, FB); + + createJIT(A.take()); + TheJIT->addModule(B.take()); + + void *vPtr = TheJIT->getPointerToFunction(FB); + TheJIT->finalizeObject(); + testAdd(vPtr); + + vPtr = TheJIT->getPointerToFunction(FA); + testAdd(vPtr); +} + +// Module A { Function FA }, +// Module B { Extern FA, Function FB which calls FA }, +// execute FB then FA +TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) { + OwningPtr A, B; + Function *FA, *FB; + createTwoModuleExternCase(A, FA, B, FB); + + createJIT(A.take()); + TheJIT->addModule(B.take()); + + void *vPtr = TheJIT->getPointerToFunction(FB); + TheJIT->finalizeObject(); + testAdd(vPtr); + + vPtr = TheJIT->getPointerToFunction(FA); + testAdd(vPtr); +} + +// Module A { Function FA }, +// Module B { Extern FA, Function FB which calls FA }, +// execute FA then FB +TEST_F(MCJITMultipleModuleTest, two_module_extern_case) { + SKIP_UNSUPPORTED_PLATFORM; + + OwningPtr A, B; + Function *FA, *FB; + createTwoModuleExternCase(A, FA, B, FB); + + createJIT(A.take()); + Module *SaveB = B.get(); + TheJIT->addModule(B.take()); + + void *vPtr = TheJIT->getPointerToFunction(FA); + TheJIT->finalizeModule(SaveB); + testAdd(vPtr); + + vPtr = TheJIT->getPointerToFunction(FB); + testAdd(vPtr); +} + +// Module A { Function FA1, Function FA2 which calls FA1 }, +// Module B { Extern FA1, Function FB which calls FA1 }, +// execute FB then FA2 +TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) { + OwningPtr A, B; + Function *FA1, *FA2, *FB; + createTwoModuleExternCase(A, FA1, B, FB); + FA2 = insertSimpleCallFunction(A.get(), FA1); + + createJIT(A.take()); + TheJIT->addModule(B.take()); + + void *vPtr = TheJIT->getPointerToFunction(FB); + TheJIT->finalizeObject(); + testAdd(vPtr); + + vPtr = TheJIT->getPointerToFunction(FA2); + testAdd(vPtr); +} + +} Index: unittests/ExecutionEngine/MCJIT/MCJITTestBase.h =================================================================== --- unittests/ExecutionEngine/MCJIT/MCJITTestBase.h +++ unittests/ExecutionEngine/MCJIT/MCJITTestBase.h @@ -138,6 +138,36 @@ name); return Global; } + + // Populates Modules A and B: + // Module A { Function FA }, + // Module B { Function FB } + void createTwoModuleCase(OwningPtr &A, + Function *&FA, + OwningPtr &B, + Function *&FB) { + A.reset(createEmptyModule("A")); + FA = insertAddFunction(A.get()); + + B.reset(createEmptyModule("B")); + FB = insertAddFunction(B.get()); + } + + // Populates Modules A and B: + // Module A { Function FA }, + // Module B { Extern FA, Function FB which calls FA } + void createTwoModuleExternCase(OwningPtr &A, + Function *&FA, + OwningPtr &B, + Function *&FB) { + A.reset(createEmptyModule("A")); + FA = insertAddFunction(A.get()); + + B.reset(createEmptyModule("B")); + Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA); + FB = insertSimpleCallFunction(B.get(), FAExtern_in_B); + } + }; class MCJITTestBase : public MCJITTestAPICommon, public TrivialModuleBuilder {