12d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor//===- MCJITTest.cpp - Unit tests for the MCJIT ---------------------------===// 22d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// 32d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// The LLVM Compiler Infrastructure 42d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// 52d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// This file is distributed under the University of Illinois Open Source 62d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// License. See LICENSE.TXT for details. 72d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// 82d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor//===----------------------------------------------------------------------===// 92d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// 102d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// This test suite verifies basic MCJIT functionality such as making function 112d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// calls, using global variables, and compiling multpile modules. 122d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// 132d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor//===----------------------------------------------------------------------===// 142d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 152d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor#include "llvm/ExecutionEngine/MCJIT.h" 162d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor#include "MCJITTestBase.h" 175a88dda4be791426ab4d20a6a6c9c65d66614a27Chandler Carruth#include "gtest/gtest.h" 182d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 192d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylorusing namespace llvm; 202d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 219d7c776d32c8a4d64b37a91c2d627629cf1498efBill Wendlingnamespace { 229d7c776d32c8a4d64b37a91c2d627629cf1498efBill Wendling 232d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylorclass MCJITTest : public testing::Test, public MCJITTestBase { 242d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylorprotected: 252c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar void SetUp() override { M.reset(createEmptyModule("<main>")); } 262d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor}; 272d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 2870c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor// FIXME: Ensure creating an execution engine does not crash when constructed 2970c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor// with a null module. 3070c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor/* 3170c1ea493e6156eccde5270c139ef423b19ab580Andrew KaylorTEST_F(MCJITTest, null_module) { 3270c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor createJIT(0); 3370c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor} 3470c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor*/ 3570c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor 362d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// FIXME: In order to JIT an empty module, there needs to be 372d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// an interface to ExecutionEngine that forces compilation but 3870c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor// does not require retrieval of a pointer to a function/global. 392d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor/* 402d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew KaylorTEST_F(MCJITTest, empty_module) { 412d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor createJIT(M.take()); 422d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor //EXPECT_NE(0, TheJIT->getObjectImage()) 432d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor // << "Unable to generate executable loaded object image"; 442d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor} 452d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor*/ 462d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 472d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew KaylorTEST_F(MCJITTest, global_variable) { 482d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor SKIP_UNSUPPORTED_PLATFORM; 492d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 502d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor int initialValue = 5; 512d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor GlobalValue *Global = insertGlobalInt32(M.get(), "test_global", initialValue); 5237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines createJIT(std::move(M)); 532d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor void *globalPtr = TheJIT->getPointerToGlobal(Global); 54c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines EXPECT_TRUE(nullptr != globalPtr) 552d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor << "Unable to get pointer to global value from JIT"; 562d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 572d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor EXPECT_EQ(initialValue, *(int32_t*)globalPtr) 582d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor << "Unexpected initial value of global"; 592d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor} 602d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 612d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew KaylorTEST_F(MCJITTest, add_function) { 622d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor SKIP_UNSUPPORTED_PLATFORM; 632d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 642d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor Function *F = insertAddFunction(M.get()); 6537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines createJIT(std::move(M)); 6670c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor uint64_t addPtr = TheJIT->getFunctionAddress(F->getName().str()); 672d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor EXPECT_TRUE(0 != addPtr) 682d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor << "Unable to get pointer to function from JIT"; 692d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 7070c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor ASSERT_TRUE(addPtr != 0) << "Unable to get pointer to function ."; 7170c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor int (*AddPtr)(int, int) = (int(*)(int, int))addPtr ; 7270c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor EXPECT_EQ(0, AddPtr(0, 0)); 7370c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor EXPECT_EQ(1, AddPtr(1, 0)); 7470c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor EXPECT_EQ(3, AddPtr(1, 2)); 7570c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor EXPECT_EQ(-5, AddPtr(-2, -3)); 7670c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor EXPECT_EQ(30, AddPtr(10, 20)); 7770c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor EXPECT_EQ(-30, AddPtr(-10, -20)); 7870c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor EXPECT_EQ(-40, AddPtr(-10, -30)); 792d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor} 802d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 812d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew KaylorTEST_F(MCJITTest, run_main) { 822d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor SKIP_UNSUPPORTED_PLATFORM; 832d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 842d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor int rc = 6; 852d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor Function *Main = insertMainFunction(M.get(), 6); 8637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines createJIT(std::move(M)); 8770c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor uint64_t ptr = TheJIT->getFunctionAddress(Main->getName().str()); 8870c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor EXPECT_TRUE(0 != ptr) 892d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor << "Unable to get pointer to main() from JIT"; 902d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 9170c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor int (*FuncPtr)(void) = (int(*)(void))ptr; 922d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor int returnCode = FuncPtr(); 932d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor EXPECT_EQ(returnCode, rc); 942d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor} 952d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 962d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew KaylorTEST_F(MCJITTest, return_global) { 972d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor SKIP_UNSUPPORTED_PLATFORM; 982d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 992d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor int32_t initialNum = 7; 1002d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor GlobalVariable *GV = insertGlobalInt32(M.get(), "myglob", initialNum); 1012d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 1022d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor Function *ReturnGlobal = startFunction<int32_t(void)>(M.get(), 1032d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor "ReturnGlobal"); 1042d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor Value *ReadGlobal = Builder.CreateLoad(GV); 1052d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor endFunctionWithRet(ReturnGlobal, ReadGlobal); 1062d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 10737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines createJIT(std::move(M)); 10870c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor uint64_t rgvPtr = TheJIT->getFunctionAddress(ReturnGlobal->getName().str()); 1092d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor EXPECT_TRUE(0 != rgvPtr); 1102d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 11170c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor int32_t(*FuncPtr)(void) = (int32_t(*)(void))rgvPtr; 1122d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor EXPECT_EQ(initialNum, FuncPtr()) 1132d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor << "Invalid value for global returned from JITted function"; 1142d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor} 1152d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 1162d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// FIXME: This case fails due to a bug with getPointerToGlobal(). 1172d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// The bug is due to MCJIT not having an implementation of getPointerToGlobal() 1182d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// which results in falling back on the ExecutionEngine implementation that 1192d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// allocates a new memory block for the global instead of using the same 1202d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// global variable that is emitted by MCJIT. Hence, the pointer (gvPtr below) 1212d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// has the correct initial value, but updates to the real global (accessed by 1222d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// JITted code) are not propagated. Instead, getPointerToGlobal() should return 1232d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// a pointer into the loaded ObjectImage to reference the emitted global. 1242d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor/* 1252d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew KaylorTEST_F(MCJITTest, increment_global) { 1262d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor SKIP_UNSUPPORTED_PLATFORM; 1272d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 1282d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor int32_t initialNum = 5; 1292d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor Function *IncrementGlobal = startFunction<int32_t(void)>(M.get(), "IncrementGlobal"); 1302d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor GlobalVariable *GV = insertGlobalInt32(M.get(), "my_global", initialNum); 1312d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor Value *DerefGV = Builder.CreateLoad(GV); 1322d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor Value *AddResult = Builder.CreateAdd(DerefGV, 1332d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor ConstantInt::get(Context, APInt(32, 1))); 1342d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor Builder.CreateStore(AddResult, GV); 1352d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor endFunctionWithRet(IncrementGlobal, AddResult); 1362d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 1372d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor createJIT(M.take()); 1382d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor void *gvPtr = TheJIT->getPointerToGlobal(GV); 1392d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor EXPECT_EQ(initialNum, *(int32_t*)gvPtr); 1402d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 14170c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor void *vPtr = TheJIT->getFunctionAddress(IncrementGlobal->getName().str()); 1422d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor EXPECT_TRUE(0 != vPtr) 1432d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor << "Unable to get pointer to main() from JIT"; 1442d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 1452d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor int32_t(*FuncPtr)(void) = (int32_t(*)(void))(intptr_t)vPtr; 1462d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 1472d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor for(int i = 1; i < 3; ++i) { 1482d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor int32_t result = FuncPtr(); 1492d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor EXPECT_EQ(initialNum + i, result); // OK 1502d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor EXPECT_EQ(initialNum + i, *(int32_t*)gvPtr); // FAILS 1512d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor } 1522d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor} 1532d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor*/ 1542d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 155abb38fe8dec11b1ea7535f84fac8ad0f0af70addDavid Tweed// PR16013: XFAIL this test on ARM, which currently can't handle multiple relocations. 156abb38fe8dec11b1ea7535f84fac8ad0f0af70addDavid Tweed#if !defined(__arm__) 157abb38fe8dec11b1ea7535f84fac8ad0f0af70addDavid Tweed 1582d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew KaylorTEST_F(MCJITTest, multiple_functions) { 1592d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor SKIP_UNSUPPORTED_PLATFORM; 1602d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 1612d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor unsigned int numLevels = 23; 1622d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor int32_t innerRetVal= 5; 1632d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 1642d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor Function *Inner = startFunction<int32_t(void)>(M.get(), "Inner"); 1652d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor endFunctionWithRet(Inner, ConstantInt::get(Context, APInt(32, innerRetVal))); 1662d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 1672d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor Function *Outer; 1682d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor for (unsigned int i = 0; i < numLevels; ++i) { 1692d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor std::stringstream funcName; 1702d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor funcName << "level_" << i; 1712d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor Outer = startFunction<int32_t(void)>(M.get(), funcName.str()); 1722d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor Value *innerResult = Builder.CreateCall(Inner); 1732d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor endFunctionWithRet(Outer, innerResult); 1742d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 1752d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor Inner = Outer; 1762d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor } 1772d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 17837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines createJIT(std::move(M)); 17970c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor uint64_t ptr = TheJIT->getFunctionAddress(Outer->getName().str()); 18070c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor EXPECT_TRUE(0 != ptr) 1812d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor << "Unable to get pointer to outer function from JIT"; 1822d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 18370c1ea493e6156eccde5270c139ef423b19ab580Andrew Kaylor int32_t(*FuncPtr)(void) = (int32_t(*)(void))ptr; 1842d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor EXPECT_EQ(innerRetVal, FuncPtr()) 1852d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor << "Incorrect result returned from function"; 1862d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor} 1872d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor 188abb38fe8dec11b1ea7535f84fac8ad0f0af70addDavid Tweed#endif /*!defined(__arm__)*/ 189abb38fe8dec11b1ea7535f84fac8ad0f0af70addDavid Tweed 19037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesTEST_F(MCJITTest, multiple_decl_lookups) { 19137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines SKIP_UNSUPPORTED_PLATFORM; 19237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 19337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Function *Foo = insertExternalReferenceToFunction<void(void)>(M.get(), "_exit"); 19437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines createJIT(std::move(M)); 19537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines void *A = TheJIT->getPointerToFunction(Foo); 19637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines void *B = TheJIT->getPointerToFunction(Foo); 19737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 19837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines EXPECT_TRUE(A != 0) << "Failed lookup - test not correctly configured."; 19937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines EXPECT_EQ(A, B) << "Repeat calls to getPointerToFunction fail."; 20037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 20137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 2022d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor} 203