Skip to content

Commit e8a6b27

Browse files
committed
Overload resolution for __clang_Interpreter_SetValueNoAlloc symbols to be defined with LLVM <19
1 parent 9c6be69 commit e8a6b27

File tree

1 file changed

+75
-3
lines changed

1 file changed

+75
-3
lines changed

lib/CppInterOp/CppInterOp.cpp

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,31 @@
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
9497
extern "C" void* __clang_Interpreter_SetValueWithAlloc(void* This, void* OutVal,
9598
void* OpaqueType)
9699
#else
97100
void* __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

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

Comments
 (0)