|
66 | 66 | #include <algorithm> |
67 | 67 | #include <cassert> |
68 | 68 | #include <cstddef> |
| 69 | +#include <cstdint> |
69 | 70 | #include <cstdio> |
70 | 71 | #include <deque> |
71 | 72 | #include <iterator> |
|
96 | 97 | #include <unistd.h> |
97 | 98 | #endif // WIN32 |
98 | 99 |
|
| 100 | +// Runtime symbols required if the library using JIT (Cpp::Evaluate) does not |
| 101 | +// link to llvm |
| 102 | +#if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN) |
| 103 | +struct __clang_Interpreter_NewTag { |
| 104 | +} __ci_newtag; |
| 105 | +#if CLANG_VERSION_MAJOR > 21 |
| 106 | +extern "C" void* __clang_Interpreter_SetValueWithAlloc(void* This, void* OutVal, |
| 107 | + void* OpaqueType) |
| 108 | +#else |
| 109 | +void* __clang_Interpreter_SetValueWithAlloc(void* This, void* OutVal, |
| 110 | + void* OpaqueType); |
| 111 | +#endif |
| 112 | + |
| 113 | +#if CLANG_VERSION_MAJOR > 18 |
| 114 | + extern "C" void __clang_Interpreter_SetValueNoAlloc(void* This, |
| 115 | + void* OutVal, |
| 116 | + void* OpaqueType, ...); |
| 117 | +#else |
| 118 | +void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*); |
| 119 | +void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*); |
| 120 | +void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float); |
| 121 | +void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double); |
| 122 | +void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double); |
| 123 | +void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, |
| 124 | + unsigned long long); |
| 125 | +#endif |
| 126 | +#endif // CPPINTEROP_USE_CLING |
| 127 | + |
99 | 128 | namespace Cpp { |
100 | 129 |
|
101 | 130 | using namespace clang; |
@@ -3308,6 +3337,88 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/, |
3308 | 3337 |
|
3309 | 3338 | sInterpreters->emplace_back(I, /*Owned=*/true); |
3310 | 3339 |
|
| 3340 | +// Define runtime symbols in the JIT dylib for clang-repl |
| 3341 | +#if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN) |
| 3342 | + DefineAbsoluteSymbol(*I, "__ci_newtag", |
| 3343 | + reinterpret_cast<uint64_t>(&__ci_newtag)); |
| 3344 | +// llvm > 22 has this defined as a C symbol that does not require mangling |
| 3345 | +#if CLANG_VERSION_MAJOR >= 22 |
| 3346 | + DefineAbsoluteSymbol( |
| 3347 | + *I, "__clang_Interpreter_SetValueWithAlloc", |
| 3348 | + reinterpret_cast<uint64_t>(&__clang_Interpreter_SetValueWithAlloc)); |
| 3349 | +#else |
| 3350 | + // obtain mangled name |
| 3351 | + auto* D = static_cast<clang::Decl*>( |
| 3352 | + Cpp::GetNamed("__clang_Interpreter_SetValueWithAlloc")); |
| 3353 | + if (auto* FD = llvm::dyn_cast<FunctionDecl>(D)) { |
| 3354 | + auto GD = GlobalDecl(FD); |
| 3355 | + std::string mangledName; |
| 3356 | + compat::maybeMangleDeclName(GD, mangledName); |
| 3357 | + DefineAbsoluteSymbol( |
| 3358 | + *I, mangledName.c_str(), |
| 3359 | + reinterpret_cast<uint64_t>(&__clang_Interpreter_SetValueWithAlloc)); |
| 3360 | + } |
| 3361 | +#endif |
| 3362 | +// llvm < 19 has multiple overloads of __clang_Interpreter_SetValueNoAlloc |
| 3363 | +#if CLANG_VERSION_MAJOR < 19 |
| 3364 | + // obtain all 6 candidates, and obtain the correct Decl for each overload |
| 3365 | + // using BestOverloadFunctionMatch. We then map the decl to the correct |
| 3366 | + // function pointer (force the compiler to find the right declarion by casting |
| 3367 | + // to the corresponding function pointer signature) and then register it. |
| 3368 | + const std::vector<TCppFunction_t> Methods = Cpp::GetFunctionsUsingName( |
| 3369 | + Cpp::GetGlobalScope(), "__clang_Interpreter_SetValueNoAlloc"); |
| 3370 | + std::string mangledName; |
| 3371 | + ASTContext& Ctxt = I->getSema().getASTContext(); |
| 3372 | + auto* TAI = Ctxt.VoidPtrTy.getAsOpaquePtr(); |
| 3373 | + |
| 3374 | + // possible parameter lists for __clang_Interpreter_SetValueNoAlloc overloads |
| 3375 | + // in LLVM 18 |
| 3376 | + const std::vector<std::vector<Cpp::TemplateArgInfo>> a_params = { |
| 3377 | + {TAI, TAI, TAI}, |
| 3378 | + {TAI, TAI, TAI, TAI}, |
| 3379 | + {TAI, TAI, TAI, Ctxt.FloatTy.getAsOpaquePtr()}, |
| 3380 | + {TAI, TAI, TAI, Ctxt.DoubleTy.getAsOpaquePtr()}, |
| 3381 | + {TAI, TAI, TAI, Ctxt.LongDoubleTy.getAsOpaquePtr()}, |
| 3382 | + {TAI, TAI, TAI, Ctxt.UnsignedLongLongTy.getAsOpaquePtr()}}; |
| 3383 | + |
| 3384 | + using FP0 = void (*)(void*, void*, void*); |
| 3385 | + using FP1 = void (*)(void*, void*, void*, void*); |
| 3386 | + using FP2 = void (*)(void*, void*, void*, float); |
| 3387 | + using FP3 = void (*)(void*, void*, void*, double); |
| 3388 | + using FP4 = void (*)(void*, void*, void*, long double); |
| 3389 | + using FP5 = void (*)(void*, void*, void*, unsigned long long); |
| 3390 | + |
| 3391 | + const std::vector<void*> func_pointers = { |
| 3392 | + reinterpret_cast<void*>( |
| 3393 | + static_cast<FP0>(&__clang_Interpreter_SetValueNoAlloc)), |
| 3394 | + reinterpret_cast<void*>( |
| 3395 | + static_cast<FP1>(&__clang_Interpreter_SetValueNoAlloc)), |
| 3396 | + reinterpret_cast<void*>( |
| 3397 | + static_cast<FP2>(&__clang_Interpreter_SetValueNoAlloc)), |
| 3398 | + reinterpret_cast<void*>( |
| 3399 | + static_cast<FP3>(&__clang_Interpreter_SetValueNoAlloc)), |
| 3400 | + reinterpret_cast<void*>( |
| 3401 | + static_cast<FP4>(&__clang_Interpreter_SetValueNoAlloc)), |
| 3402 | + reinterpret_cast<void*>( |
| 3403 | + static_cast<FP5>(&__clang_Interpreter_SetValueNoAlloc))}; |
| 3404 | + |
| 3405 | + // these symbols are not externed, so we need to mangle their names |
| 3406 | + for (size_t i = 0; i < a_params.size(); ++i) { |
| 3407 | + auto* decl = static_cast<clang::Decl*>( |
| 3408 | + Cpp::BestOverloadFunctionMatch(Methods, {}, a_params[i])); |
| 3409 | + if (auto* fd = llvm::dyn_cast<clang::FunctionDecl>(decl)) { |
| 3410 | + auto gd = clang::GlobalDecl(fd); |
| 3411 | + compat::maybeMangleDeclName(gd, mangledName); |
| 3412 | + DefineAbsoluteSymbol(*I, mangledName.c_str(), |
| 3413 | + reinterpret_cast<uint64_t>(func_pointers[i])); |
| 3414 | + } |
| 3415 | + } |
| 3416 | +#else |
| 3417 | + DefineAbsoluteSymbol( |
| 3418 | + *I, "__clang_Interpreter_SetValueNoAlloc", |
| 3419 | + reinterpret_cast<uint64_t>(&__clang_Interpreter_SetValueNoAlloc)); |
| 3420 | +#endif |
| 3421 | +#endif |
3311 | 3422 | return I; |
3312 | 3423 | } |
3313 | 3424 |
|
|
0 commit comments