9090#include < unistd.h>
9191#endif // WIN32
9292
93- #if CLANG_VERSION_MAJOR > 22
93+ // Runtime symbols required if the library using JIT (Cpp::Evaluate) does not link to llvm
94+ #ifndef CPPINTEROP_USE_CLING
95+ #if CLANG_VERSION_MAJOR >= 22
9496extern " C" void * __clang_Interpreter_SetValueWithAlloc (void * This, void * OutVal,
9597 void * OpaqueType)
9698#else
9799void * __clang_Interpreter_SetValueWithAlloc (void * This, void * OutVal,
98100 void * OpaqueType);
99101#endif
100102
101- extern " C" void __clang_Interpreter_SetValueNoAlloc (void * This,
102- void * OutVal,
103- void * OpaqueType, ...);
103+ #if CLANG_VERSION_MAJOR >= 19
104+ extern " C" void __clang_Interpreter_SetValueNoAlloc (void * This,
105+ void * OutVal,
106+ void * OpaqueType, ...);
107+ #elif CLANG_VERSION_MAJOR == 18
108+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *);
109+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *, void *);
110+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *, float );
111+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *, double );
112+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *, long double );
113+ void __clang_Interpreter_SetValueNoAlloc (void *,void *,void *,unsigned long long );
114+ #endif
115+ #endif // CPPINTEROP_USE_CLING
104116
105117namespace Cpp {
106118
@@ -3488,10 +3500,12 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
34883500
34893501// Define runtime symbols in the JIT dylib for clang-repl
34903502#ifndef CPPINTEROP_USE_CLING
3491- #if CLANG_VERSION_MAJOR > 22
3503+ // llvm > 22 has this defined as a C symbol that does not require mangling
3504+ #if CLANG_VERSION_MAJOR >= 22
34923505 DefineAbsoluteSymbol (*I, " __clang_Interpreter_SetValueWithAlloc" ,
3493- (uint64_t )&__clang_Interpreter_SetValueNoAlloc );
3506+ (uint64_t )&__clang_Interpreter_SetValueWithAlloc );
34943507#else
3508+ // obtain mangled name
34953509 auto * D = static_cast <clang::Decl*>(
34963510 Cpp::GetNamed (" __clang_Interpreter_SetValueWithAlloc" ));
34973511 if (auto * FD = llvm::dyn_cast<FunctionDecl>(D)) {
@@ -3502,8 +3516,54 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
35023516 (uint64_t )&__clang_Interpreter_SetValueWithAlloc);
35033517 }
35043518#endif
3505- DefineAbsoluteSymbol (*I, " __clang_Interpreter_SetValueNoAlloc" ,
3506- (uint64_t )&__clang_Interpreter_SetValueNoAlloc);
3519+ // llvm < 19 has multiple overloads of __clang_Interpreter_SetValueNoAlloc
3520+ #if CLANG_VERSION_MAJOR < 19
3521+ // obtain all 6 candidates, and obtain the correct Decl for each overload using BestOverloadFunctionMatch. We then map the decl to the correct function pointer (force the compiler to find the right declarion by casting to the corresponding function pointer signature) and then register it.
3522+ const std::vector<TCppFunction_t> Methods = Cpp::GetFunctionsUsingName (Cpp::GetGlobalScope (), " __clang_Interpreter_SetValueNoAlloc" );
3523+ std::string mangledName;
3524+ ASTContext& Ctxt = I->getSema ().getASTContext ();
3525+ auto * TAI = Ctxt.VoidPtrTy .getAsOpaquePtr ();
3526+
3527+ // possible parameter lists for __clang_Interpreter_SetValueNoAlloc overloads in LLVM 18
3528+ const std::vector<std::vector<Cpp::TemplateArgInfo>> a_params = {
3529+ {TAI, TAI, TAI},
3530+ {TAI, TAI, TAI, TAI},
3531+ {TAI, TAI, TAI, Ctxt.FloatTy .getAsOpaquePtr ()},
3532+ {TAI, TAI, TAI, Ctxt.DoubleTy .getAsOpaquePtr ()},
3533+ {TAI, TAI, TAI, Ctxt.LongDoubleTy .getAsOpaquePtr ()},
3534+ {TAI, TAI, TAI, Ctxt.UnsignedLongLongTy .getAsOpaquePtr ()}
3535+ };
3536+
3537+ using FP0 = void (*)(void *, void *, void *);
3538+ using FP1 = void (*)(void *, void *, void *, void *);
3539+ using FP2 = void (*)(void *, void *, void *, float );
3540+ using FP3 = void (*)(void *, void *, void *, double );
3541+ using FP4 = void (*)(void *, void *, void *, long double );
3542+ using FP5 = void (*)(void *, void *, void *, unsigned long long );
3543+
3544+ const std::vector<void *> func_pointers = {
3545+ reinterpret_cast <void *>(static_cast <FP0>(&__clang_Interpreter_SetValueNoAlloc)),
3546+ reinterpret_cast <void *>(static_cast <FP1>(&__clang_Interpreter_SetValueNoAlloc)),
3547+ reinterpret_cast <void *>(static_cast <FP2>(&__clang_Interpreter_SetValueNoAlloc)),
3548+ reinterpret_cast <void *>(static_cast <FP3>(&__clang_Interpreter_SetValueNoAlloc)),
3549+ reinterpret_cast <void *>(static_cast <FP4>(&__clang_Interpreter_SetValueNoAlloc)),
3550+ reinterpret_cast <void *>(static_cast <FP5>(&__clang_Interpreter_SetValueNoAlloc))
3551+ };
3552+
3553+ // these symbols are not externed, so we need to mangle their names
3554+ for (size_t i = 0 ; i < a_params.size (); ++i) {
3555+ auto * decl = static_cast <clang::Decl*>(Cpp::BestOverloadFunctionMatch (Methods, {}, a_params[i]));
3556+ if (auto * fd = llvm::dyn_cast<clang::FunctionDecl>(decl)) {
3557+ auto gd = clang::GlobalDecl (fd);
3558+ compat::maybeMangleDeclName (gd, mangledName);
3559+ DefineAbsoluteSymbol (*I, mangledName.c_str (),
3560+ reinterpret_cast <uint64_t >(func_pointers[i]));
3561+ }
3562+ }
3563+ #else
3564+ DefineAbsoluteSymbol (*I, " __clang_Interpreter_SetValueNoAlloc" ,
3565+ (uint64_t )&__clang_Interpreter_SetValueNoAlloc);
3566+ #endif
35073567#endif
35083568 return I;
35093569}
0 commit comments