X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=unittests%2FExecutionEngine%2FMCJIT%2FMCJITTest.cpp;h=744bfdb4a01bc175923ec9ada297f19d524db842;hb=4e036ff575c54e01aea7f8028d282974480b071e;hp=f65ec96d944b91663886b9c9405a04845c391bb9;hpb=22af148912c8503e305d1cc8741293686d66b864;p=oota-llvm.git diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp index f65ec96d944..744bfdb4a01 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp @@ -1,4 +1,4 @@ -//===- MCJITTest.cpp - Unit tests for the MCJIT ---------------------------===// +//===- MCJITTest.cpp - Unit tests for the MCJIT -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/Support/DynamicLibrary.h" #include "MCJITTestBase.h" #include "gtest/gtest.h" @@ -88,7 +89,7 @@ TEST_F(MCJITTest, run_main) { EXPECT_TRUE(0 != ptr) << "Unable to get pointer to main() from JIT"; - int (*FuncPtr)(void) = (int(*)(void))ptr; + int (*FuncPtr)() = (int(*)())ptr; int returnCode = FuncPtr(); EXPECT_EQ(returnCode, rc); } @@ -108,7 +109,7 @@ TEST_F(MCJITTest, return_global) { uint64_t rgvPtr = TheJIT->getFunctionAddress(ReturnGlobal->getName().str()); EXPECT_TRUE(0 != rgvPtr); - int32_t(*FuncPtr)(void) = (int32_t(*)(void))rgvPtr; + int32_t(*FuncPtr)() = (int32_t(*)())rgvPtr; EXPECT_EQ(initialNum, FuncPtr()) << "Invalid value for global returned from JITted function"; } @@ -180,7 +181,7 @@ TEST_F(MCJITTest, multiple_functions) { EXPECT_TRUE(0 != ptr) << "Unable to get pointer to outer function from JIT"; - int32_t(*FuncPtr)(void) = (int32_t(*)(void))ptr; + int32_t(*FuncPtr)() = (int32_t(*)())ptr; EXPECT_EQ(innerRetVal, FuncPtr()) << "Incorrect result returned from function"; } @@ -195,8 +196,89 @@ TEST_F(MCJITTest, multiple_decl_lookups) { void *A = TheJIT->getPointerToFunction(Foo); void *B = TheJIT->getPointerToFunction(Foo); - EXPECT_TRUE(A != 0) << "Failed lookup - test not correctly configured."; + EXPECT_TRUE(A != nullptr) << "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"); + 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) { + // Try to resolve the function in the current process before marking it as + // unresolved. This solves an issue on ARM where '__aeabi_*' function names + // are passed to this handler. + void *symbol = + llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(str.c_str()); + if (symbol) { + return symbol; + } + + 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"); + 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) { + // Try to resolve the function in the current process before marking it as + // unresolved. This solves an issue on ARM where '__aeabi_*' function names + // are passed to this handler. + void *symbol = + llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(str.c_str()); + if (symbol) { + return symbol; + } + 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(), 2u); + EXPECT_FALSE(std::find(I, E, "Foo1") == E); + EXPECT_FALSE(std::find(I, E, "Foo2") == E); } + +} // end anonymous namespace