8686#include < unistd.h>
8787#endif // WIN32
8888
89- #if CLANG_VERSION_MAJOR > 22
89+ // Runtime symbols required if the library using JIT (Cpp::Evaluate) does not
90+ // link to llvm
91+ #ifndef CPPINTEROP_USE_CLING
92+ #if CLANG_VERSION_MAJOR >= 22
9093extern " C" void * __clang_Interpreter_SetValueWithAlloc (void * This, void * OutVal,
9194 void * OpaqueType)
9295#else
9396void * __clang_Interpreter_SetValueWithAlloc (void * This, void * OutVal,
9497 void * OpaqueType);
9598#endif
9699
100+ #if CLANG_VERSION_MAJOR >= 19
97101 extern " C" void __clang_Interpreter_SetValueNoAlloc (void * This,
98102 void * OutVal,
99103 void * OpaqueType, ...);
104+ #elif CLANG_VERSION_MAJOR == 18
105+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *);
106+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *, void *);
107+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *, float );
108+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *, double );
109+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *, long double );
110+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *,
111+ unsigned long long );
112+ #endif
113+ #endif // CPPINTEROP_USE_CLING
100114
101115namespace Cpp {
102116
@@ -3318,10 +3332,12 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
33183332
33193333// Define runtime symbols in the JIT dylib for clang-repl
33203334#ifndef CPPINTEROP_USE_CLING
3321- #if CLANG_VERSION_MAJOR > 22
3335+ // llvm > 22 has this defined as a C symbol that does not require mangling
3336+ #if CLANG_VERSION_MAJOR >= 22
33223337 DefineAbsoluteSymbol (*I, " __clang_Interpreter_SetValueWithAlloc" ,
3323- (uint64_t )&__clang_Interpreter_SetValueNoAlloc );
3338+ (uint64_t )&__clang_Interpreter_SetValueWithAlloc );
33243339#else
3340+ // obtain mangled name
33253341 auto * D = static_cast <clang::Decl*>(
33263342 Cpp::GetNamed (" __clang_Interpreter_SetValueWithAlloc" ));
33273343 if (auto * FD = llvm::dyn_cast<FunctionDecl>(D)) {
@@ -3332,10 +3348,65 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
33323348 (uint64_t )&__clang_Interpreter_SetValueWithAlloc);
33333349 }
33343350#endif
3351+ // llvm < 19 has multiple overloads of __clang_Interpreter_SetValueNoAlloc
3352+ #if CLANG_VERSION_MAJOR < 19
3353+ // obtain all 6 candidates, and obtain the correct Decl for each overload
3354+ // using BestOverloadFunctionMatch. We then map the decl to the correct
3355+ // function pointer (force the compiler to find the right declarion by casting
3356+ // to the corresponding function pointer signature) and then register it.
3357+ const std::vector<TCppFunction_t> Methods = Cpp::GetFunctionsUsingName (
3358+ Cpp::GetGlobalScope (), " __clang_Interpreter_SetValueNoAlloc" );
3359+ std::string mangledName;
3360+ ASTContext& Ctxt = I->getSema ().getASTContext ();
3361+ auto * TAI = Ctxt.VoidPtrTy .getAsOpaquePtr ();
3362+
3363+ // possible parameter lists for __clang_Interpreter_SetValueNoAlloc overloads
3364+ // in LLVM 18
3365+ const std::vector<std::vector<Cpp::TemplateArgInfo>> a_params = {
3366+ {TAI, TAI, TAI},
3367+ {TAI, TAI, TAI, TAI},
3368+ {TAI, TAI, TAI, Ctxt.FloatTy .getAsOpaquePtr ()},
3369+ {TAI, TAI, TAI, Ctxt.DoubleTy .getAsOpaquePtr ()},
3370+ {TAI, TAI, TAI, Ctxt.LongDoubleTy .getAsOpaquePtr ()},
3371+ {TAI, TAI, TAI, Ctxt.UnsignedLongLongTy .getAsOpaquePtr ()}};
3372+
3373+ using FP0 = void (*)(void *, void *, void *);
3374+ using FP1 = void (*)(void *, void *, void *, void *);
3375+ using FP2 = void (*)(void *, void *, void *, float );
3376+ using FP3 = void (*)(void *, void *, void *, double );
3377+ using FP4 = void (*)(void *, void *, void *, long double );
3378+ using FP5 = void (*)(void *, void *, void *, unsigned long long );
3379+
3380+ const std::vector<void *> func_pointers = {
3381+ reinterpret_cast <void *>(
3382+ static_cast <FP0>(&__clang_Interpreter_SetValueNoAlloc)),
3383+ reinterpret_cast <void *>(
3384+ static_cast <FP1>(&__clang_Interpreter_SetValueNoAlloc)),
3385+ reinterpret_cast <void *>(
3386+ static_cast <FP2>(&__clang_Interpreter_SetValueNoAlloc)),
3387+ reinterpret_cast <void *>(
3388+ static_cast <FP3>(&__clang_Interpreter_SetValueNoAlloc)),
3389+ reinterpret_cast <void *>(
3390+ static_cast <FP4>(&__clang_Interpreter_SetValueNoAlloc)),
3391+ reinterpret_cast <void *>(
3392+ static_cast <FP5>(&__clang_Interpreter_SetValueNoAlloc))};
3393+
3394+ // these symbols are not externed, so we need to mangle their names
3395+ for (size_t i = 0 ; i < a_params.size (); ++i) {
3396+ auto * decl = static_cast <clang::Decl*>(
3397+ Cpp::BestOverloadFunctionMatch (Methods, {}, a_params[i]));
3398+ if (auto * fd = llvm::dyn_cast<clang::FunctionDecl>(decl)) {
3399+ auto gd = clang::GlobalDecl (fd);
3400+ compat::maybeMangleDeclName (gd, mangledName);
3401+ DefineAbsoluteSymbol (*I, mangledName.c_str (),
3402+ reinterpret_cast <uint64_t >(func_pointers[i]));
3403+ }
3404+ }
3405+ #else
33353406 DefineAbsoluteSymbol (*I, " __clang_Interpreter_SetValueNoAlloc" ,
33363407 (uint64_t )&__clang_Interpreter_SetValueNoAlloc);
33373408#endif
3338-
3409+ # endif
33393410 return I;
33403411}
33413412
0 commit comments