X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=unittests%2FExecutionEngine%2FMCJIT%2FMCJITTest.cpp;h=7b9cb6cd57e57a8581ab74dcc3ae2b10f9b4df21;hp=9786befd720f1698ceab4df16bc540812a875570;hb=b9b04eeb85b2bc4f54003a9436f792e13f4d37ad;hpb=354362524a72b3fa43a6c09380b7ae3b2380cbba diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp index 9786befd720..7b9cb6cd57e 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp @@ -18,19 +18,13 @@ using namespace llvm; +namespace { + class MCJITTest : public testing::Test, public MCJITTestBase { protected: - - virtual void SetUp(); + void SetUp() override { M.reset(createEmptyModule("
")); } }; -// Provide out-of-line definition to prevent weak vtable. -void MCJITTest::SetUp() { - M.reset(createEmptyModule("
")); -} - -namespace { - // FIXME: Ensure creating an execution engine does not crash when constructed // with a null module. /* @@ -55,9 +49,9 @@ TEST_F(MCJITTest, global_variable) { int initialValue = 5; GlobalValue *Global = insertGlobalInt32(M.get(), "test_global", initialValue); - createJIT(M.take()); + createJIT(std::move(M)); void *globalPtr = TheJIT->getPointerToGlobal(Global); - EXPECT_TRUE(0 != globalPtr) + EXPECT_TRUE(nullptr != globalPtr) << "Unable to get pointer to global value from JIT"; EXPECT_EQ(initialValue, *(int32_t*)globalPtr) @@ -68,7 +62,7 @@ TEST_F(MCJITTest, add_function) { SKIP_UNSUPPORTED_PLATFORM; Function *F = insertAddFunction(M.get()); - createJIT(M.take()); + createJIT(std::move(M)); uint64_t addPtr = TheJIT->getFunctionAddress(F->getName().str()); EXPECT_TRUE(0 != addPtr) << "Unable to get pointer to function from JIT"; @@ -89,7 +83,7 @@ TEST_F(MCJITTest, run_main) { int rc = 6; Function *Main = insertMainFunction(M.get(), 6); - createJIT(M.take()); + createJIT(std::move(M)); uint64_t ptr = TheJIT->getFunctionAddress(Main->getName().str()); EXPECT_TRUE(0 != ptr) << "Unable to get pointer to main() from JIT"; @@ -110,7 +104,7 @@ TEST_F(MCJITTest, return_global) { Value *ReadGlobal = Builder.CreateLoad(GV); endFunctionWithRet(ReturnGlobal, ReadGlobal); - createJIT(M.take()); + createJIT(std::move(M)); uint64_t rgvPtr = TheJIT->getFunctionAddress(ReturnGlobal->getName().str()); EXPECT_TRUE(0 != rgvPtr); @@ -175,13 +169,13 @@ TEST_F(MCJITTest, multiple_functions) { std::stringstream funcName; funcName << "level_" << i; Outer = startFunction(M.get(), funcName.str()); - Value *innerResult = Builder.CreateCall(Inner); + Value *innerResult = Builder.CreateCall(Inner, {}); endFunctionWithRet(Outer, innerResult); Inner = Outer; } - createJIT(M.take()); + createJIT(std::move(M)); uint64_t ptr = TheJIT->getFunctionAddress(Outer->getName().str()); EXPECT_TRUE(0 != ptr) << "Unable to get pointer to outer function from JIT"; @@ -193,4 +187,81 @@ TEST_F(MCJITTest, multiple_functions) { #endif /*!defined(__arm__)*/ +TEST_F(MCJITTest, multiple_decl_lookups) { + SKIP_UNSUPPORTED_PLATFORM; + + Function *Foo = insertExternalReferenceToFunction(M.get(), "_exit"); + createJIT(std::move(M)); + void *A = TheJIT->getPointerToFunction(Foo); + void *B = TheJIT->getPointerToFunction(Foo); + + EXPECT_TRUE(A != 0) << "Failed lookup - test not correctly configured."; + EXPECT_EQ(A, B) << "Repeat calls to getPointerToFunction fail."; +} + +typedef void * (*FunctionHandlerPtr)(const std::string &str); + +TEST_F(MCJITTest, lazy_function_creator_pointer) { + SKIP_UNSUPPORTED_PLATFORM; + + Function *Foo = insertExternalReferenceToFunction(M.get(), + "\1Foo"); + Function *Parent = startFunction(M.get(), "Parent"); + CallInst *Call = Builder.CreateCall(Foo, {}); + Builder.CreateRet(Call); + + createJIT(std::move(M)); + + // Set up the lazy function creator that records the name of the last + // unresolved external function found in the module. Using a function pointer + // prevents us from capturing local variables, which is why this is static. + static std::string UnresolvedExternal; + FunctionHandlerPtr UnresolvedHandler = [] (const std::string &str) { + UnresolvedExternal = str; + return (void *)(uintptr_t)-1; + }; + TheJIT->InstallLazyFunctionCreator(UnresolvedHandler); + + // JIT the module. + TheJIT->finalizeObject(); + + // Verify that our handler was called. + EXPECT_EQ(UnresolvedExternal, "Foo"); +} + +TEST_F(MCJITTest, lazy_function_creator_lambda) { + SKIP_UNSUPPORTED_PLATFORM; + + Function *Foo1 = insertExternalReferenceToFunction(M.get(), + "\1Foo1"); + Function *Foo2 = insertExternalReferenceToFunction(M.get(), + "\1Foo2"); + Function *Parent = startFunction(M.get(), "Parent"); + CallInst *Call1 = Builder.CreateCall(Foo1, {}); + CallInst *Call2 = Builder.CreateCall(Foo2, {}); + Value *Result = Builder.CreateAdd(Call1, Call2); + Builder.CreateRet(Result); + + createJIT(std::move(M)); + + // Set up the lazy function creator that records the name of unresolved + // external functions in the module. + std::vector UnresolvedExternals; + auto UnresolvedHandler = [&UnresolvedExternals] (const std::string &str) { + llvm:dbgs() << "str is '" << str << "'\n"; + UnresolvedExternals.push_back(str); + return (void *)(uintptr_t)-1; + }; + TheJIT->InstallLazyFunctionCreator(UnresolvedHandler); + + // JIT the module. + TheJIT->finalizeObject(); + + // Verify that our handler was called for each unresolved function. + auto I = UnresolvedExternals.begin(), E = UnresolvedExternals.end(); + EXPECT_EQ(UnresolvedExternals.size(), 2); + EXPECT_FALSE(std::find(I, E, "Foo1") == E); + EXPECT_FALSE(std::find(I, E, "Foo2") == E); +} + }