Skip to content

Commit adfd4a4

Browse files
committed
Overload resolution for __clang_Interpreter_SetValueNoAlloc symbols to be defined with LLVM <19
1 parent 376cc2b commit adfd4a4

File tree

1 file changed

+75
-4
lines changed

1 file changed

+75
-4
lines changed

lib/CppInterOp/CppInterOp.cpp

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,31 @@
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
9093
extern "C" void* __clang_Interpreter_SetValueWithAlloc(void* This, void* OutVal,
9194
void* OpaqueType)
9295
#else
9396
void* __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

101115
namespace 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

Comments
 (0)