File: | unittests/ExecutionEngine/MCJIT/MCJITTest.cpp |
Location: | line 93, column 20 |
Description: | Called function pointer is null (null dereference) |
1 | //===- MCJITTest.cpp - Unit tests for the MCJIT -----------------*- C++ -*-===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | // | |||
10 | // This test suite verifies basic MCJIT functionality such as making function | |||
11 | // calls, using global variables, and compiling multpile modules. | |||
12 | // | |||
13 | //===----------------------------------------------------------------------===// | |||
14 | ||||
15 | #include "llvm/ExecutionEngine/MCJIT.h" | |||
16 | #include "llvm/Support/DynamicLibrary.h" | |||
17 | #include "MCJITTestBase.h" | |||
18 | #include "gtest/gtest.h" | |||
19 | ||||
20 | using namespace llvm; | |||
21 | ||||
22 | namespace { | |||
23 | ||||
24 | class MCJITTest : public testing::Test, public MCJITTestBase { | |||
25 | protected: | |||
26 | void SetUp() override { M.reset(createEmptyModule("<main>")); } | |||
27 | }; | |||
28 | ||||
29 | // FIXME: Ensure creating an execution engine does not crash when constructed | |||
30 | // with a null module. | |||
31 | /* | |||
32 | TEST_F(MCJITTest, null_module) { | |||
33 | createJIT(0); | |||
34 | } | |||
35 | */ | |||
36 | ||||
37 | // FIXME: In order to JIT an empty module, there needs to be | |||
38 | // an interface to ExecutionEngine that forces compilation but | |||
39 | // does not require retrieval of a pointer to a function/global. | |||
40 | /* | |||
41 | TEST_F(MCJITTest, empty_module) { | |||
42 | createJIT(M.take()); | |||
43 | //EXPECT_NE(0, TheJIT->getObjectImage()) | |||
44 | // << "Unable to generate executable loaded object image"; | |||
45 | } | |||
46 | */ | |||
47 | ||||
48 | TEST_F(MCJITTest, global_variable)class MCJITTest_global_variable_Test : public MCJITTest { public : MCJITTest_global_variable_Test() {} private: virtual void TestBody (); static ::testing::TestInfo* const test_info_ __attribute__ ((unused)); MCJITTest_global_variable_Test(MCJITTest_global_variable_Test const &); void operator=(MCJITTest_global_variable_Test const &);};::testing::TestInfo* const MCJITTest_global_variable_Test ::test_info_ = ::testing::internal::MakeAndRegisterTestInfo( "MCJITTest", "global_variable", __null, __null, (::testing:: internal::GetTypeId<MCJITTest>()), MCJITTest::SetUpTestCase , MCJITTest::TearDownTestCase, new ::testing::internal::TestFactoryImpl < MCJITTest_global_variable_Test>);void MCJITTest_global_variable_Test ::TestBody() { | |||
49 | SKIP_UNSUPPORTED_PLATFORMdo if (!ArchSupportsMCJIT() || !OSSupportsMCJIT()) return; while (0); | |||
50 | ||||
51 | int initialValue = 5; | |||
52 | GlobalValue *Global = insertGlobalInt32(M.get(), "test_global", initialValue); | |||
53 | createJIT(std::move(M)); | |||
54 | void *globalPtr = TheJIT->getPointerToGlobal(Global); | |||
55 | EXPECT_TRUE(nullptr != globalPtr)switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar_ = ::testing::AssertionResult(nullptr != globalPtr) ) ; else ::testing::internal::AssertHelper(::testing::TestPartResult ::kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 55, ::testing::internal::GetBoolAssertionFailureMessage( gtest_ar_ , "nullptr != globalPtr", "false", "true").c_str()) = ::testing ::Message() | |||
56 | << "Unable to get pointer to global value from JIT"; | |||
57 | ||||
58 | EXPECT_EQ(initialValue, *(int32_t*)globalPtr)switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing ::internal::IsNullLiteralHelper(initialValue)) == 1)>::Compare ("initialValue", "*(int32_t*)globalPtr", initialValue, *(int32_t *)globalPtr))) ; else ::testing::internal::AssertHelper(::testing ::TestPartResult::kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 58, gtest_ar.failure_message()) = ::testing::Message() | |||
59 | << "Unexpected initial value of global"; | |||
60 | } | |||
61 | ||||
62 | TEST_F(MCJITTest, add_function)class MCJITTest_add_function_Test : public MCJITTest { public : MCJITTest_add_function_Test() {} private: virtual void TestBody (); static ::testing::TestInfo* const test_info_ __attribute__ ((unused)); MCJITTest_add_function_Test(MCJITTest_add_function_Test const &); void operator=(MCJITTest_add_function_Test const &);};::testing::TestInfo* const MCJITTest_add_function_Test ::test_info_ = ::testing::internal::MakeAndRegisterTestInfo( "MCJITTest", "add_function", __null, __null, (::testing::internal ::GetTypeId<MCJITTest>()), MCJITTest::SetUpTestCase, MCJITTest ::TearDownTestCase, new ::testing::internal::TestFactoryImpl< MCJITTest_add_function_Test>);void MCJITTest_add_function_Test ::TestBody() { | |||
63 | SKIP_UNSUPPORTED_PLATFORMdo if (!ArchSupportsMCJIT() || !OSSupportsMCJIT()) return; while (0); | |||
64 | ||||
65 | Function *F = insertAddFunction(M.get()); | |||
66 | createJIT(std::move(M)); | |||
67 | uint64_t addPtr = TheJIT->getFunctionAddress(F->getName().str()); | |||
68 | EXPECT_TRUE(0 != addPtr)switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar_ = ::testing::AssertionResult(0 != addPtr)) ; else :: testing::internal::AssertHelper(::testing::TestPartResult::kNonFatalFailure , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 68, ::testing::internal::GetBoolAssertionFailureMessage( gtest_ar_ , "0 != addPtr", "false", "true").c_str()) = ::testing::Message () | |||
69 | << "Unable to get pointer to function from JIT"; | |||
70 | ||||
71 | ASSERT_TRUE(addPtr != 0)switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar_ = ::testing::AssertionResult(addPtr != 0)) ; else return ::testing::internal::AssertHelper(::testing::TestPartResult:: kFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 71, ::testing::internal::GetBoolAssertionFailureMessage( gtest_ar_ , "addPtr != 0", "false", "true").c_str()) = ::testing::Message () << "Unable to get pointer to function ."; | |||
72 | int (*AddPtr)(int, int) = (int(*)(int, int))addPtr ; | |||
73 | EXPECT_EQ(0, AddPtr(0, 0))switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing ::internal::IsNullLiteralHelper(0)) == 1)>::Compare("0", "AddPtr(0, 0)" , 0, AddPtr(0, 0)))) ; else ::testing::internal::AssertHelper (::testing::TestPartResult::kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 73, gtest_ar.failure_message()) = ::testing::Message(); | |||
74 | EXPECT_EQ(1, AddPtr(1, 0))switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing ::internal::IsNullLiteralHelper(1)) == 1)>::Compare("1", "AddPtr(1, 0)" , 1, AddPtr(1, 0)))) ; else ::testing::internal::AssertHelper (::testing::TestPartResult::kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 74, gtest_ar.failure_message()) = ::testing::Message(); | |||
75 | EXPECT_EQ(3, AddPtr(1, 2))switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing ::internal::IsNullLiteralHelper(3)) == 1)>::Compare("3", "AddPtr(1, 2)" , 3, AddPtr(1, 2)))) ; else ::testing::internal::AssertHelper (::testing::TestPartResult::kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 75, gtest_ar.failure_message()) = ::testing::Message(); | |||
76 | EXPECT_EQ(-5, AddPtr(-2, -3))switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing ::internal::IsNullLiteralHelper(-5)) == 1)>::Compare("-5", "AddPtr(-2, -3)", -5, AddPtr(-2, -3)))) ; else ::testing::internal ::AssertHelper(::testing::TestPartResult::kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 76, gtest_ar.failure_message()) = ::testing::Message(); | |||
77 | EXPECT_EQ(30, AddPtr(10, 20))switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing ::internal::IsNullLiteralHelper(30)) == 1)>::Compare("30", "AddPtr(10, 20)", 30, AddPtr(10, 20)))) ; else ::testing::internal ::AssertHelper(::testing::TestPartResult::kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 77, gtest_ar.failure_message()) = ::testing::Message(); | |||
78 | EXPECT_EQ(-30, AddPtr(-10, -20))switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing ::internal::IsNullLiteralHelper(-30)) == 1)>::Compare("-30" , "AddPtr(-10, -20)", -30, AddPtr(-10, -20)))) ; else ::testing ::internal::AssertHelper(::testing::TestPartResult::kNonFatalFailure , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 78, gtest_ar.failure_message()) = ::testing::Message(); | |||
79 | EXPECT_EQ(-40, AddPtr(-10, -30))switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing ::internal::IsNullLiteralHelper(-40)) == 1)>::Compare("-40" , "AddPtr(-10, -30)", -40, AddPtr(-10, -30)))) ; else ::testing ::internal::AssertHelper(::testing::TestPartResult::kNonFatalFailure , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 79, gtest_ar.failure_message()) = ::testing::Message(); | |||
80 | } | |||
81 | ||||
82 | TEST_F(MCJITTest, run_main)class MCJITTest_run_main_Test : public MCJITTest { public: MCJITTest_run_main_Test () {} private: virtual void TestBody(); static ::testing::TestInfo * const test_info_ __attribute__ ((unused)); MCJITTest_run_main_Test (MCJITTest_run_main_Test const &); void operator=(MCJITTest_run_main_Test const &);};::testing::TestInfo* const MCJITTest_run_main_Test ::test_info_ = ::testing::internal::MakeAndRegisterTestInfo( "MCJITTest", "run_main", __null, __null, (::testing::internal ::GetTypeId<MCJITTest>()), MCJITTest::SetUpTestCase, MCJITTest ::TearDownTestCase, new ::testing::internal::TestFactoryImpl< MCJITTest_run_main_Test>);void MCJITTest_run_main_Test::TestBody () { | |||
83 | SKIP_UNSUPPORTED_PLATFORMdo if (!ArchSupportsMCJIT() || !OSSupportsMCJIT()) return; while (0); | |||
84 | ||||
85 | int rc = 6; | |||
86 | Function *Main = insertMainFunction(M.get(), 6); | |||
87 | createJIT(std::move(M)); | |||
88 | uint64_t ptr = TheJIT->getFunctionAddress(Main->getName().str()); | |||
| ||||
89 | EXPECT_TRUE(0 != ptr)switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar_ = ::testing::AssertionResult(0 != ptr)) ; else ::testing ::internal::AssertHelper(::testing::TestPartResult::kNonFatalFailure , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 89, ::testing::internal::GetBoolAssertionFailureMessage( gtest_ar_ , "0 != ptr", "false", "true").c_str()) = ::testing::Message( ) | |||
90 | << "Unable to get pointer to main() from JIT"; | |||
91 | ||||
92 | int (*FuncPtr)() = (int(*)())ptr; | |||
93 | int returnCode = FuncPtr(); | |||
| ||||
94 | EXPECT_EQ(returnCode, rc)switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing ::internal::IsNullLiteralHelper(returnCode)) == 1)>::Compare ("returnCode", "rc", returnCode, rc))) ; else ::testing::internal ::AssertHelper(::testing::TestPartResult::kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 94, gtest_ar.failure_message()) = ::testing::Message(); | |||
95 | } | |||
96 | ||||
97 | TEST_F(MCJITTest, return_global)class MCJITTest_return_global_Test : public MCJITTest { public : MCJITTest_return_global_Test() {} private: virtual void TestBody (); static ::testing::TestInfo* const test_info_ __attribute__ ((unused)); MCJITTest_return_global_Test(MCJITTest_return_global_Test const &); void operator=(MCJITTest_return_global_Test const &);};::testing::TestInfo* const MCJITTest_return_global_Test ::test_info_ = ::testing::internal::MakeAndRegisterTestInfo( "MCJITTest", "return_global", __null, __null, (::testing::internal ::GetTypeId<MCJITTest>()), MCJITTest::SetUpTestCase, MCJITTest ::TearDownTestCase, new ::testing::internal::TestFactoryImpl< MCJITTest_return_global_Test>);void MCJITTest_return_global_Test ::TestBody() { | |||
98 | SKIP_UNSUPPORTED_PLATFORMdo if (!ArchSupportsMCJIT() || !OSSupportsMCJIT()) return; while (0); | |||
99 | ||||
100 | int32_t initialNum = 7; | |||
101 | GlobalVariable *GV = insertGlobalInt32(M.get(), "myglob", initialNum); | |||
102 | ||||
103 | Function *ReturnGlobal = startFunction<int32_t(void)>(M.get(), | |||
104 | "ReturnGlobal"); | |||
105 | Value *ReadGlobal = Builder.CreateLoad(GV); | |||
106 | endFunctionWithRet(ReturnGlobal, ReadGlobal); | |||
107 | ||||
108 | createJIT(std::move(M)); | |||
109 | uint64_t rgvPtr = TheJIT->getFunctionAddress(ReturnGlobal->getName().str()); | |||
110 | EXPECT_TRUE(0 != rgvPtr)switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar_ = ::testing::AssertionResult(0 != rgvPtr)) ; else :: testing::internal::AssertHelper(::testing::TestPartResult::kNonFatalFailure , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 110, ::testing::internal::GetBoolAssertionFailureMessage( gtest_ar_ , "0 != rgvPtr", "false", "true").c_str()) = ::testing::Message (); | |||
111 | ||||
112 | int32_t(*FuncPtr)() = (int32_t(*)())rgvPtr; | |||
113 | EXPECT_EQ(initialNum, FuncPtr())switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing ::internal::IsNullLiteralHelper(initialNum)) == 1)>::Compare ("initialNum", "FuncPtr()", initialNum, FuncPtr()))) ; else :: testing::internal::AssertHelper(::testing::TestPartResult::kNonFatalFailure , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 113, gtest_ar.failure_message()) = ::testing::Message() | |||
114 | << "Invalid value for global returned from JITted function"; | |||
115 | } | |||
116 | ||||
117 | // FIXME: This case fails due to a bug with getPointerToGlobal(). | |||
118 | // The bug is due to MCJIT not having an implementation of getPointerToGlobal() | |||
119 | // which results in falling back on the ExecutionEngine implementation that | |||
120 | // allocates a new memory block for the global instead of using the same | |||
121 | // global variable that is emitted by MCJIT. Hence, the pointer (gvPtr below) | |||
122 | // has the correct initial value, but updates to the real global (accessed by | |||
123 | // JITted code) are not propagated. Instead, getPointerToGlobal() should return | |||
124 | // a pointer into the loaded ObjectImage to reference the emitted global. | |||
125 | /* | |||
126 | TEST_F(MCJITTest, increment_global) { | |||
127 | SKIP_UNSUPPORTED_PLATFORM; | |||
128 | ||||
129 | int32_t initialNum = 5; | |||
130 | Function *IncrementGlobal = startFunction<int32_t(void)>(M.get(), "IncrementGlobal"); | |||
131 | GlobalVariable *GV = insertGlobalInt32(M.get(), "my_global", initialNum); | |||
132 | Value *DerefGV = Builder.CreateLoad(GV); | |||
133 | Value *AddResult = Builder.CreateAdd(DerefGV, | |||
134 | ConstantInt::get(Context, APInt(32, 1))); | |||
135 | Builder.CreateStore(AddResult, GV); | |||
136 | endFunctionWithRet(IncrementGlobal, AddResult); | |||
137 | ||||
138 | createJIT(M.take()); | |||
139 | void *gvPtr = TheJIT->getPointerToGlobal(GV); | |||
140 | EXPECT_EQ(initialNum, *(int32_t*)gvPtr); | |||
141 | ||||
142 | void *vPtr = TheJIT->getFunctionAddress(IncrementGlobal->getName().str()); | |||
143 | EXPECT_TRUE(0 != vPtr) | |||
144 | << "Unable to get pointer to main() from JIT"; | |||
145 | ||||
146 | int32_t(*FuncPtr)(void) = (int32_t(*)(void))(intptr_t)vPtr; | |||
147 | ||||
148 | for(int i = 1; i < 3; ++i) { | |||
149 | int32_t result = FuncPtr(); | |||
150 | EXPECT_EQ(initialNum + i, result); // OK | |||
151 | EXPECT_EQ(initialNum + i, *(int32_t*)gvPtr); // FAILS | |||
152 | } | |||
153 | } | |||
154 | */ | |||
155 | ||||
156 | // PR16013: XFAIL this test on ARM, which currently can't handle multiple relocations. | |||
157 | #if !defined(__arm__) | |||
158 | ||||
159 | TEST_F(MCJITTest, multiple_functions)class MCJITTest_multiple_functions_Test : public MCJITTest { public : MCJITTest_multiple_functions_Test() {} private: virtual void TestBody(); static ::testing::TestInfo* const test_info_ __attribute__ ((unused)); MCJITTest_multiple_functions_Test(MCJITTest_multiple_functions_Test const &); void operator=(MCJITTest_multiple_functions_Test const &);};::testing::TestInfo* const MCJITTest_multiple_functions_Test ::test_info_ = ::testing::internal::MakeAndRegisterTestInfo( "MCJITTest", "multiple_functions", __null, __null, (::testing ::internal::GetTypeId<MCJITTest>()), MCJITTest::SetUpTestCase , MCJITTest::TearDownTestCase, new ::testing::internal::TestFactoryImpl < MCJITTest_multiple_functions_Test>);void MCJITTest_multiple_functions_Test ::TestBody() { | |||
160 | SKIP_UNSUPPORTED_PLATFORMdo if (!ArchSupportsMCJIT() || !OSSupportsMCJIT()) return; while (0); | |||
161 | ||||
162 | unsigned int numLevels = 23; | |||
163 | int32_t innerRetVal= 5; | |||
164 | ||||
165 | Function *Inner = startFunction<int32_t(void)>(M.get(), "Inner"); | |||
166 | endFunctionWithRet(Inner, ConstantInt::get(Context, APInt(32, innerRetVal))); | |||
167 | ||||
168 | Function *Outer; | |||
169 | for (unsigned int i = 0; i < numLevels; ++i) { | |||
170 | std::stringstream funcName; | |||
171 | funcName << "level_" << i; | |||
172 | Outer = startFunction<int32_t(void)>(M.get(), funcName.str()); | |||
173 | Value *innerResult = Builder.CreateCall(Inner, {}); | |||
174 | endFunctionWithRet(Outer, innerResult); | |||
175 | ||||
176 | Inner = Outer; | |||
177 | } | |||
178 | ||||
179 | createJIT(std::move(M)); | |||
180 | uint64_t ptr = TheJIT->getFunctionAddress(Outer->getName().str()); | |||
181 | EXPECT_TRUE(0 != ptr)switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar_ = ::testing::AssertionResult(0 != ptr)) ; else ::testing ::internal::AssertHelper(::testing::TestPartResult::kNonFatalFailure , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 181, ::testing::internal::GetBoolAssertionFailureMessage( gtest_ar_ , "0 != ptr", "false", "true").c_str()) = ::testing::Message( ) | |||
182 | << "Unable to get pointer to outer function from JIT"; | |||
183 | ||||
184 | int32_t(*FuncPtr)() = (int32_t(*)())ptr; | |||
185 | EXPECT_EQ(innerRetVal, FuncPtr())switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing ::internal::IsNullLiteralHelper(innerRetVal)) == 1)>::Compare ("innerRetVal", "FuncPtr()", innerRetVal, FuncPtr()))) ; else ::testing::internal::AssertHelper(::testing::TestPartResult:: kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 185, gtest_ar.failure_message()) = ::testing::Message() | |||
186 | << "Incorrect result returned from function"; | |||
187 | } | |||
188 | ||||
189 | #endif /*!defined(__arm__)*/ | |||
190 | ||||
191 | TEST_F(MCJITTest, multiple_decl_lookups)class MCJITTest_multiple_decl_lookups_Test : public MCJITTest { public: MCJITTest_multiple_decl_lookups_Test() {} private: virtual void TestBody(); static ::testing::TestInfo* const test_info_ __attribute__ ((unused)); MCJITTest_multiple_decl_lookups_Test (MCJITTest_multiple_decl_lookups_Test const &); void operator =(MCJITTest_multiple_decl_lookups_Test const &);};::testing ::TestInfo* const MCJITTest_multiple_decl_lookups_Test ::test_info_ = ::testing::internal::MakeAndRegisterTestInfo( "MCJITTest", "multiple_decl_lookups", __null, __null, (::testing::internal ::GetTypeId<MCJITTest>()), MCJITTest::SetUpTestCase, MCJITTest ::TearDownTestCase, new ::testing::internal::TestFactoryImpl< MCJITTest_multiple_decl_lookups_Test>);void MCJITTest_multiple_decl_lookups_Test ::TestBody() { | |||
192 | SKIP_UNSUPPORTED_PLATFORMdo if (!ArchSupportsMCJIT() || !OSSupportsMCJIT()) return; while (0); | |||
193 | ||||
194 | Function *Foo = insertExternalReferenceToFunction<void(void)>(M.get(), "_exit"); | |||
195 | createJIT(std::move(M)); | |||
196 | void *A = TheJIT->getPointerToFunction(Foo); | |||
197 | void *B = TheJIT->getPointerToFunction(Foo); | |||
198 | ||||
199 | EXPECT_TRUE(A != nullptr)switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar_ = ::testing::AssertionResult(A != nullptr)) ; else ::testing::internal::AssertHelper(::testing::TestPartResult:: kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 199, ::testing::internal::GetBoolAssertionFailureMessage( gtest_ar_ , "A != nullptr", "false", "true").c_str()) = ::testing::Message () << "Failed lookup - test not correctly configured."; | |||
200 | EXPECT_EQ(A, B)switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing ::internal::IsNullLiteralHelper(A)) == 1)>::Compare("A", "B" , A, B))) ; else ::testing::internal::AssertHelper(::testing:: TestPartResult::kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 200, gtest_ar.failure_message()) = ::testing::Message() << "Repeat calls to getPointerToFunction fail."; | |||
201 | } | |||
202 | ||||
203 | typedef void * (*FunctionHandlerPtr)(const std::string &str); | |||
204 | ||||
205 | TEST_F(MCJITTest, lazy_function_creator_pointer)class MCJITTest_lazy_function_creator_pointer_Test : public MCJITTest { public: MCJITTest_lazy_function_creator_pointer_Test() {} private : virtual void TestBody(); static ::testing::TestInfo* const test_info_ __attribute__ ((unused)); MCJITTest_lazy_function_creator_pointer_Test (MCJITTest_lazy_function_creator_pointer_Test const &); void operator=(MCJITTest_lazy_function_creator_pointer_Test const &);};::testing::TestInfo* const MCJITTest_lazy_function_creator_pointer_Test ::test_info_ = ::testing::internal::MakeAndRegisterTestInfo( "MCJITTest", "lazy_function_creator_pointer", __null, __null , (::testing::internal::GetTypeId<MCJITTest>()), MCJITTest ::SetUpTestCase, MCJITTest::TearDownTestCase, new ::testing:: internal::TestFactoryImpl< MCJITTest_lazy_function_creator_pointer_Test >);void MCJITTest_lazy_function_creator_pointer_Test::TestBody () { | |||
206 | SKIP_UNSUPPORTED_PLATFORMdo if (!ArchSupportsMCJIT() || !OSSupportsMCJIT()) return; while (0); | |||
207 | ||||
208 | Function *Foo = insertExternalReferenceToFunction<int32_t(void)>(M.get(), | |||
209 | "\1Foo"); | |||
210 | startFunction<int32_t(void)>(M.get(), "Parent"); | |||
211 | CallInst *Call = Builder.CreateCall(Foo, {}); | |||
212 | Builder.CreateRet(Call); | |||
213 | ||||
214 | createJIT(std::move(M)); | |||
215 | ||||
216 | // Set up the lazy function creator that records the name of the last | |||
217 | // unresolved external function found in the module. Using a function pointer | |||
218 | // prevents us from capturing local variables, which is why this is static. | |||
219 | static std::string UnresolvedExternal; | |||
220 | FunctionHandlerPtr UnresolvedHandler = [] (const std::string &str) { | |||
221 | // Try to resolve the function in the current process before marking it as | |||
222 | // unresolved. This solves an issue on ARM where '__aeabi_*' function names | |||
223 | // are passed to this handler. | |||
224 | void *symbol = | |||
225 | llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(str.c_str()); | |||
226 | if (symbol) { | |||
227 | return symbol; | |||
228 | } | |||
229 | ||||
230 | UnresolvedExternal = str; | |||
231 | return (void *)(uintptr_t)-1; | |||
232 | }; | |||
233 | TheJIT->InstallLazyFunctionCreator(UnresolvedHandler); | |||
234 | ||||
235 | // JIT the module. | |||
236 | TheJIT->finalizeObject(); | |||
237 | ||||
238 | // Verify that our handler was called. | |||
239 | EXPECT_EQ(UnresolvedExternal, "Foo")switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing ::internal::IsNullLiteralHelper(UnresolvedExternal)) == 1)> ::Compare("UnresolvedExternal", "\"Foo\"", UnresolvedExternal , "Foo"))) ; else ::testing::internal::AssertHelper(::testing ::TestPartResult::kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 239, gtest_ar.failure_message()) = ::testing::Message(); | |||
240 | } | |||
241 | ||||
242 | TEST_F(MCJITTest, lazy_function_creator_lambda)class MCJITTest_lazy_function_creator_lambda_Test : public MCJITTest { public: MCJITTest_lazy_function_creator_lambda_Test() {} private : virtual void TestBody(); static ::testing::TestInfo* const test_info_ __attribute__ ((unused)); MCJITTest_lazy_function_creator_lambda_Test (MCJITTest_lazy_function_creator_lambda_Test const &); void operator=(MCJITTest_lazy_function_creator_lambda_Test const & );};::testing::TestInfo* const MCJITTest_lazy_function_creator_lambda_Test ::test_info_ = ::testing::internal::MakeAndRegisterTestInfo( "MCJITTest", "lazy_function_creator_lambda", __null, __null, (::testing::internal::GetTypeId<MCJITTest>()), MCJITTest ::SetUpTestCase, MCJITTest::TearDownTestCase, new ::testing:: internal::TestFactoryImpl< MCJITTest_lazy_function_creator_lambda_Test >);void MCJITTest_lazy_function_creator_lambda_Test::TestBody () { | |||
243 | SKIP_UNSUPPORTED_PLATFORMdo if (!ArchSupportsMCJIT() || !OSSupportsMCJIT()) return; while (0); | |||
244 | ||||
245 | Function *Foo1 = insertExternalReferenceToFunction<int32_t(void)>(M.get(), | |||
246 | "\1Foo1"); | |||
247 | Function *Foo2 = insertExternalReferenceToFunction<int32_t(void)>(M.get(), | |||
248 | "\1Foo2"); | |||
249 | startFunction<int32_t(void)>(M.get(), "Parent"); | |||
250 | CallInst *Call1 = Builder.CreateCall(Foo1, {}); | |||
251 | CallInst *Call2 = Builder.CreateCall(Foo2, {}); | |||
252 | Value *Result = Builder.CreateAdd(Call1, Call2); | |||
253 | Builder.CreateRet(Result); | |||
254 | ||||
255 | createJIT(std::move(M)); | |||
256 | ||||
257 | // Set up the lazy function creator that records the name of unresolved | |||
258 | // external functions in the module. | |||
259 | std::vector<std::string> UnresolvedExternals; | |||
260 | auto UnresolvedHandler = [&UnresolvedExternals] (const std::string &str) { | |||
261 | // Try to resolve the function in the current process before marking it as | |||
262 | // unresolved. This solves an issue on ARM where '__aeabi_*' function names | |||
263 | // are passed to this handler. | |||
264 | void *symbol = | |||
265 | llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(str.c_str()); | |||
266 | if (symbol) { | |||
267 | return symbol; | |||
268 | } | |||
269 | UnresolvedExternals.push_back(str); | |||
270 | return (void *)(uintptr_t)-1; | |||
271 | }; | |||
272 | TheJIT->InstallLazyFunctionCreator(UnresolvedHandler); | |||
273 | ||||
274 | // JIT the module. | |||
275 | TheJIT->finalizeObject(); | |||
276 | ||||
277 | // Verify that our handler was called for each unresolved function. | |||
278 | auto I = UnresolvedExternals.begin(), E = UnresolvedExternals.end(); | |||
279 | EXPECT_EQ(UnresolvedExternals.size(), 2u)switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing ::internal::IsNullLiteralHelper(UnresolvedExternals.size())) == 1)>::Compare("UnresolvedExternals.size()", "2u", UnresolvedExternals .size(), 2u))) ; else ::testing::internal::AssertHelper(::testing ::TestPartResult::kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 279, gtest_ar.failure_message()) = ::testing::Message(); | |||
280 | EXPECT_FALSE(std::find(I, E, "Foo1") == E)switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar_ = ::testing::AssertionResult(!(std::find(I, E, "Foo1" ) == E))) ; else ::testing::internal::AssertHelper(::testing:: TestPartResult::kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 280, ::testing::internal::GetBoolAssertionFailureMessage( gtest_ar_ , "std::find(I, E, \"Foo1\") == E", "true", "false").c_str()) = ::testing::Message(); | |||
281 | EXPECT_FALSE(std::find(I, E, "Foo2") == E)switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar_ = ::testing::AssertionResult(!(std::find(I, E, "Foo2" ) == E))) ; else ::testing::internal::AssertHelper(::testing:: TestPartResult::kNonFatalFailure, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp" , 281, ::testing::internal::GetBoolAssertionFailureMessage( gtest_ar_ , "std::find(I, E, \"Foo2\") == E", "true", "false").c_str()) = ::testing::Message(); | |||
282 | } | |||
283 | ||||
284 | } // end anonymous namespace |