|
13 | 13 | //===----------------------------------------------------------------------===//
|
14 | 14 |
|
15 | 15 | #include "llvm/ExecutionEngine/MCJIT.h"
|
| 16 | +#include "llvm/Support/DynamicLibrary.h" |
16 | 17 | #include "MCJITTestBase.h"
|
17 | 18 | #include "gtest/gtest.h"
|
18 | 19 |
|
@@ -199,4 +200,85 @@ TEST_F(MCJITTest, multiple_decl_lookups) {
|
199 | 200 | EXPECT_EQ(A, B) << "Repeat calls to getPointerToFunction fail.";
|
200 | 201 | }
|
201 | 202 |
|
| 203 | +typedef void * (*FunctionHandlerPtr)(const std::string &str); |
| 204 | + |
| 205 | +TEST_F(MCJITTest, lazy_function_creator_pointer) { |
| 206 | + SKIP_UNSUPPORTED_PLATFORM; |
| 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"); |
| 240 | +} |
| 241 | + |
| 242 | +TEST_F(MCJITTest, lazy_function_creator_lambda) { |
| 243 | + SKIP_UNSUPPORTED_PLATFORM; |
| 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); |
| 280 | + EXPECT_FALSE(std::find(I, E, "Foo1") == E); |
| 281 | + EXPECT_FALSE(std::find(I, E, "Foo2") == E); |
| 282 | +} |
| 283 | + |
202 | 284 | }
|
0 commit comments