90
90
#include < unistd.h>
91
91
#endif // WIN32
92
92
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
94
96
extern " C" void * __clang_Interpreter_SetValueWithAlloc (void * This, void * OutVal,
95
97
void * OpaqueType)
96
98
#else
97
99
void * __clang_Interpreter_SetValueWithAlloc (void * This, void * OutVal,
98
100
void * OpaqueType);
99
101
#endif
100
102
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
104
116
105
117
namespace Cpp {
106
118
@@ -3488,10 +3500,12 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
3488
3500
3489
3501
// Define runtime symbols in the JIT dylib for clang-repl
3490
3502
#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
3492
3505
DefineAbsoluteSymbol (*I, " __clang_Interpreter_SetValueWithAlloc" ,
3493
- (uint64_t )&__clang_Interpreter_SetValueNoAlloc );
3506
+ (uint64_t )&__clang_Interpreter_SetValueWithAlloc );
3494
3507
#else
3508
+ // obtain mangled name
3495
3509
auto * D = static_cast <clang::Decl*>(
3496
3510
Cpp::GetNamed (" __clang_Interpreter_SetValueWithAlloc" ));
3497
3511
if (auto * FD = llvm::dyn_cast<FunctionDecl>(D)) {
@@ -3502,8 +3516,54 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
3502
3516
(uint64_t )&__clang_Interpreter_SetValueWithAlloc);
3503
3517
}
3504
3518
#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
3507
3567
#endif
3508
3568
return I;
3509
3569
}
0 commit comments