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
94+ // link to llvm
95+ #ifndef CPPINTEROP_USE_CLING
96+ #if CLANG_VERSION_MAJOR >= 22
9497extern " C" void * __clang_Interpreter_SetValueWithAlloc (void * This, void * OutVal,
9598 void * OpaqueType)
9699#else
97100void * __clang_Interpreter_SetValueWithAlloc (void * This, void * OutVal,
98101 void * OpaqueType);
99102#endif
100103
104+ #if CLANG_VERSION_MAJOR >= 19
101105 extern " C" void __clang_Interpreter_SetValueNoAlloc (void * This,
102106 void * OutVal,
103107 void * OpaqueType, ...);
108+ #elif CLANG_VERSION_MAJOR == 18
109+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *);
110+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *, void *);
111+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *, float );
112+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *, double );
113+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *, long double );
114+ void __clang_Interpreter_SetValueNoAlloc (void *, void *, void *,
115+ unsigned long long );
116+ #endif
117+ #endif // CPPINTEROP_USE_CLING
104118
105119namespace Cpp {
106120
@@ -3488,10 +3502,12 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
34883502
34893503// Define runtime symbols in the JIT dylib for clang-repl
34903504#ifndef CPPINTEROP_USE_CLING
3491- #if CLANG_VERSION_MAJOR > 22
3505+ // llvm > 22 has this defined as a C symbol that does not require mangling
3506+ #if CLANG_VERSION_MAJOR >= 22
34923507 DefineAbsoluteSymbol (*I, " __clang_Interpreter_SetValueWithAlloc" ,
3493- (uint64_t )&__clang_Interpreter_SetValueNoAlloc );
3508+ (uint64_t )&__clang_Interpreter_SetValueWithAlloc );
34943509#else
3510+ // obtain mangled name
34953511 auto * D = static_cast <clang::Decl*>(
34963512 Cpp::GetNamed (" __clang_Interpreter_SetValueWithAlloc" ));
34973513 if (auto * FD = llvm::dyn_cast<FunctionDecl>(D)) {
@@ -3502,8 +3518,64 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
35023518 (uint64_t )&__clang_Interpreter_SetValueWithAlloc);
35033519 }
35043520#endif
3521+ // llvm < 19 has multiple overloads of __clang_Interpreter_SetValueNoAlloc
3522+ #if CLANG_VERSION_MAJOR < 19
3523+ // obtain all 6 candidates, and obtain the correct Decl for each overload
3524+ // using BestOverloadFunctionMatch. We then map the decl to the correct
3525+ // function pointer (force the compiler to find the right declarion by casting
3526+ // to the corresponding function pointer signature) and then register it.
3527+ const std::vector<TCppFunction_t> Methods = Cpp::GetFunctionsUsingName (
3528+ Cpp::GetGlobalScope (), " __clang_Interpreter_SetValueNoAlloc" );
3529+ std::string mangledName;
3530+ ASTContext& Ctxt = I->getSema ().getASTContext ();
3531+ auto * TAI = Ctxt.VoidPtrTy .getAsOpaquePtr ();
3532+
3533+ // possible parameter lists for __clang_Interpreter_SetValueNoAlloc overloads
3534+ // in LLVM 18
3535+ const std::vector<std::vector<Cpp::TemplateArgInfo>> a_params = {
3536+ {TAI, TAI, TAI},
3537+ {TAI, TAI, TAI, TAI},
3538+ {TAI, TAI, TAI, Ctxt.FloatTy .getAsOpaquePtr ()},
3539+ {TAI, TAI, TAI, Ctxt.DoubleTy .getAsOpaquePtr ()},
3540+ {TAI, TAI, TAI, Ctxt.LongDoubleTy .getAsOpaquePtr ()},
3541+ {TAI, TAI, TAI, Ctxt.UnsignedLongLongTy .getAsOpaquePtr ()}};
3542+
3543+ using FP0 = void (*)(void *, void *, void *);
3544+ using FP1 = void (*)(void *, void *, void *, void *);
3545+ using FP2 = void (*)(void *, void *, void *, float );
3546+ using FP3 = void (*)(void *, void *, void *, double );
3547+ using FP4 = void (*)(void *, void *, void *, long double );
3548+ using FP5 = void (*)(void *, void *, void *, unsigned long long );
3549+
3550+ const std::vector<void *> func_pointers = {
3551+ reinterpret_cast <void *>(
3552+ static_cast <FP0>(&__clang_Interpreter_SetValueNoAlloc)),
3553+ reinterpret_cast <void *>(
3554+ static_cast <FP1>(&__clang_Interpreter_SetValueNoAlloc)),
3555+ reinterpret_cast <void *>(
3556+ static_cast <FP2>(&__clang_Interpreter_SetValueNoAlloc)),
3557+ reinterpret_cast <void *>(
3558+ static_cast <FP3>(&__clang_Interpreter_SetValueNoAlloc)),
3559+ reinterpret_cast <void *>(
3560+ static_cast <FP4>(&__clang_Interpreter_SetValueNoAlloc)),
3561+ reinterpret_cast <void *>(
3562+ static_cast <FP5>(&__clang_Interpreter_SetValueNoAlloc))};
3563+
3564+ // these symbols are not externed, so we need to mangle their names
3565+ for (size_t i = 0 ; i < a_params.size (); ++i) {
3566+ auto * decl = static_cast <clang::Decl*>(
3567+ Cpp::BestOverloadFunctionMatch (Methods, {}, a_params[i]));
3568+ if (auto * fd = llvm::dyn_cast<clang::FunctionDecl>(decl)) {
3569+ auto gd = clang::GlobalDecl (fd);
3570+ compat::maybeMangleDeclName (gd, mangledName);
3571+ DefineAbsoluteSymbol (*I, mangledName.c_str (),
3572+ reinterpret_cast <uint64_t >(func_pointers[i]));
3573+ }
3574+ }
3575+ #else
35053576 DefineAbsoluteSymbol (*I, " __clang_Interpreter_SetValueNoAlloc" ,
35063577 (uint64_t )&__clang_Interpreter_SetValueNoAlloc);
3578+ #endif
35073579#endif
35083580 return I;
35093581}
0 commit comments