-
Notifications
You must be signed in to change notification settings - Fork 39
[interp] Register runtime symbols for clang-repl #726
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,6 +48,11 @@ | |
| #include "llvm/ADT/SmallVector.h" | ||
| #include "llvm/ADT/StringRef.h" | ||
| #include "llvm/Demangle/Demangle.h" | ||
| #if CLANG_VERSION_MAJOR >= 20 | ||
| #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h" | ||
| #include "llvm/ExecutionEngine/Orc/CoreContainers.h" | ||
| #endif | ||
| #include "llvm/ExecutionEngine/Orc/Core.h" | ||
| #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" | ||
| #include "llvm/IR/GlobalValue.h" | ||
| #include "llvm/Support/Casting.h" | ||
|
|
@@ -61,6 +66,7 @@ | |
| #include <algorithm> | ||
| #include <cassert> | ||
| #include <cstddef> | ||
| #include <cstdint> | ||
| #include <cstdio> | ||
| #include <deque> | ||
| #include <iterator> | ||
|
|
@@ -91,6 +97,34 @@ | |
| #include <unistd.h> | ||
| #endif // WIN32 | ||
|
|
||
| // Runtime symbols required if the library using JIT (Cpp::Evaluate) does not | ||
| // link to llvm | ||
| #if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN) | ||
| struct __clang_Interpreter_NewTag { | ||
| } __ci_newtag; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: variable '__ci_newtag' can be made static or moved into an anonymous namespace to enforce internal linkage [misc-use-internal-linkage] lib/CppInterOp/CppInterOp.cpp:96: - struct __clang_Interpreter_NewTag {
+ static struct __clang_Interpreter_NewTag {
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: variable '__ci_newtag' can be made static or moved into an anonymous namespace to enforce internal linkage [misc-use-internal-linkage] lib/CppInterOp/CppInterOp.cpp:100: - struct __clang_Interpreter_NewTag {
+ static struct __clang_Interpreter_NewTag {
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: variable '__ci_newtag' can be made static or moved into an anonymous namespace to enforce internal linkage [misc-use-internal-linkage] lib/CppInterOp/CppInterOp.cpp:102: - struct __clang_Interpreter_NewTag {
+ static struct __clang_Interpreter_NewTag { |
||
| #if CLANG_VERSION_MAJOR > 21 | ||
| extern "C" void* __clang_Interpreter_SetValueWithAlloc(void* This, void* OutVal, | ||
| void* OpaqueType) | ||
| #else | ||
| void* __clang_Interpreter_SetValueWithAlloc(void* This, void* OutVal, | ||
| void* OpaqueType); | ||
| #endif | ||
|
|
||
| #if CLANG_VERSION_MAJOR > 18 | ||
| extern "C" void __clang_Interpreter_SetValueNoAlloc(void* This, | ||
| void* OutVal, | ||
| void* OpaqueType, ...); | ||
| #else | ||
| void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*); | ||
| void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*); | ||
| void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float); | ||
| void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double); | ||
| void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double); | ||
| void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, | ||
| unsigned long long); | ||
| #endif | ||
| #endif // CPPINTEROP_USE_CLING | ||
|
|
||
| namespace Cpp { | ||
|
|
||
| using namespace clang; | ||
|
|
@@ -3175,6 +3209,29 @@ | |
| } | ||
|
|
||
| namespace { | ||
| #if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN) | ||
| bool DefineAbsoluteSymbol(compat::Interpreter& I, | ||
| const char* linker_mangled_name, uint64_t address) { | ||
aaronj0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| using namespace llvm; | ||
| using namespace llvm::orc; | ||
|
|
||
| llvm::orc::LLJIT& Jit = *compat::getExecutionEngine(I); | ||
| llvm::orc::ExecutionSession& ES = Jit.getExecutionSession(); | ||
aaronj0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| JITDylib& DyLib = *Jit.getProcessSymbolsJITDylib().get(); | ||
aaronj0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| llvm::orc::SymbolMap InjectedSymbols{ | ||
aaronj0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| {ES.intern(linker_mangled_name), | ||
| ExecutorSymbolDef(ExecutorAddr(address), JITSymbolFlags::Exported)}}; | ||
|
|
||
| if (Error Err = DyLib.define(absoluteSymbols(InjectedSymbols))) { | ||
aaronj0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| logAllUnhandledErrors(std::move(Err), errs(), | ||
aaronj0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "DefineAbsoluteSymbol error: "); | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
| #endif | ||
|
|
||
| static std::string MakeResourcesPath() { | ||
| StringRef Dir; | ||
| #ifdef LLVM_BINARY_DIR | ||
|
|
@@ -3280,6 +3337,88 @@ | |
|
|
||
| sInterpreters->emplace_back(I, /*Owned=*/true); | ||
|
|
||
| // Define runtime symbols in the JIT dylib for clang-repl | ||
| #if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN) | ||
| DefineAbsoluteSymbol(*I, "__ci_newtag", | ||
| reinterpret_cast<uint64_t>(&__ci_newtag)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: do not use reinterpret_cast [cppcoreguidelines-pro-type-reinterpret-cast] reinterpret_cast<uint64_t>(&__ci_newtag));
^ |
||
| // llvm >= 21 has this defined as a C symbol that does not require mangling | ||
| #if CLANG_VERSION_MAJOR >= 21 | ||
| DefineAbsoluteSymbol( | ||
| *I, "__clang_Interpreter_SetValueWithAlloc", | ||
| reinterpret_cast<uint64_t>(&__clang_Interpreter_SetValueWithAlloc)); | ||
| #else | ||
| // obtain mangled name | ||
| auto* D = static_cast<clang::Decl*>( | ||
| Cpp::GetNamed("__clang_Interpreter_SetValueWithAlloc")); | ||
| if (auto* FD = llvm::dyn_cast<FunctionDecl>(D)) { | ||
| auto GD = GlobalDecl(FD); | ||
| std::string mangledName; | ||
| compat::maybeMangleDeclName(GD, mangledName); | ||
| DefineAbsoluteSymbol( | ||
| *I, mangledName.c_str(), | ||
| reinterpret_cast<uint64_t>(&__clang_Interpreter_SetValueWithAlloc)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: do not use reinterpret_cast [cppcoreguidelines-pro-type-reinterpret-cast] reinterpret_cast<uint64_t>(&__clang_Interpreter_SetValueWithAlloc));
^ |
||
| } | ||
| #endif | ||
| // llvm < 19 has multiple overloads of __clang_Interpreter_SetValueNoAlloc | ||
| #if CLANG_VERSION_MAJOR < 19 | ||
| // 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. | ||
| const std::vector<TCppFunction_t> Methods = Cpp::GetFunctionsUsingName( | ||
| Cpp::GetGlobalScope(), "__clang_Interpreter_SetValueNoAlloc"); | ||
| std::string mangledName; | ||
| ASTContext& Ctxt = I->getSema().getASTContext(); | ||
| auto* TAI = Ctxt.VoidPtrTy.getAsOpaquePtr(); | ||
|
|
||
| // possible parameter lists for __clang_Interpreter_SetValueNoAlloc overloads | ||
| // in LLVM 18 | ||
| const std::vector<std::vector<Cpp::TemplateArgInfo>> a_params = { | ||
| {TAI, TAI, TAI}, | ||
| {TAI, TAI, TAI, TAI}, | ||
| {TAI, TAI, TAI, Ctxt.FloatTy.getAsOpaquePtr()}, | ||
| {TAI, TAI, TAI, Ctxt.DoubleTy.getAsOpaquePtr()}, | ||
| {TAI, TAI, TAI, Ctxt.LongDoubleTy.getAsOpaquePtr()}, | ||
| {TAI, TAI, TAI, Ctxt.UnsignedLongLongTy.getAsOpaquePtr()}}; | ||
|
|
||
| using FP0 = void (*)(void*, void*, void*); | ||
| using FP1 = void (*)(void*, void*, void*, void*); | ||
| using FP2 = void (*)(void*, void*, void*, float); | ||
| using FP3 = void (*)(void*, void*, void*, double); | ||
| using FP4 = void (*)(void*, void*, void*, long double); | ||
| using FP5 = void (*)(void*, void*, void*, unsigned long long); | ||
|
|
||
| const std::vector<void*> func_pointers = { | ||
| reinterpret_cast<void*>( | ||
| static_cast<FP0>(&__clang_Interpreter_SetValueNoAlloc)), | ||
| reinterpret_cast<void*>( | ||
| static_cast<FP1>(&__clang_Interpreter_SetValueNoAlloc)), | ||
| reinterpret_cast<void*>( | ||
| static_cast<FP2>(&__clang_Interpreter_SetValueNoAlloc)), | ||
| reinterpret_cast<void*>( | ||
| static_cast<FP3>(&__clang_Interpreter_SetValueNoAlloc)), | ||
| reinterpret_cast<void*>( | ||
| static_cast<FP4>(&__clang_Interpreter_SetValueNoAlloc)), | ||
| reinterpret_cast<void*>( | ||
| static_cast<FP5>(&__clang_Interpreter_SetValueNoAlloc))}; | ||
|
|
||
| // these symbols are not externed, so we need to mangle their names | ||
| for (size_t i = 0; i < a_params.size(); ++i) { | ||
| auto* decl = static_cast<clang::Decl*>( | ||
| Cpp::BestOverloadFunctionMatch(Methods, {}, a_params[i])); | ||
| if (auto* fd = llvm::dyn_cast<clang::FunctionDecl>(decl)) { | ||
| auto gd = clang::GlobalDecl(fd); | ||
| compat::maybeMangleDeclName(gd, mangledName); | ||
| DefineAbsoluteSymbol(*I, mangledName.c_str(), | ||
| reinterpret_cast<uint64_t>(func_pointers[i])); | ||
| } | ||
| } | ||
| #else | ||
| DefineAbsoluteSymbol( | ||
| *I, "__clang_Interpreter_SetValueNoAlloc", | ||
| reinterpret_cast<uint64_t>(&__clang_Interpreter_SetValueNoAlloc)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: do not use reinterpret_cast [cppcoreguidelines-pro-type-reinterpret-cast] reinterpret_cast<uint64_t>(&__clang_Interpreter_SetValueNoAlloc));
^ |
||
| #endif | ||
| #endif | ||
| return I; | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: variable '__ci_newtag' can be made static or moved into an anonymous namespace to enforce internal linkage [misc-use-internal-linkage]
lib/CppInterOp/CppInterOp.cpp:91: