[llvm] 68f31aa - [ORC][Runtime] Add `dlupdate` for MachO (#97441)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 10 17:50:04 PDT 2024
Author: SahilPatidar
Date: 2024-09-11T10:50:01+10:00
New Revision: 68f31aaae95f9824e58001c7f9115034df51039e
URL: https://github.com/llvm/llvm-project/commit/68f31aaae95f9824e58001c7f9115034df51039e
DIFF: https://github.com/llvm/llvm-project/commit/68f31aaae95f9824e58001c7f9115034df51039e.diff
LOG: [ORC][Runtime] Add `dlupdate` for MachO (#97441)
With the help of @lhames, This pull request introduces the `dlupdate`
function in the ORC runtime. `dlupdate` enables incremental execution of
new initializers introduced in the REPL environment. Unlike traditional
`dlopen`, which manages initializers, code mapping, and library
reference counts, `dlupdate` focuses exclusively on running new
initializers.
Added:
Modified:
compiler-rt/lib/orc/dlfcn_wrapper.cpp
compiler-rt/lib/orc/macho_platform.cpp
compiler-rt/lib/orc/macho_platform.h
llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/orc/dlfcn_wrapper.cpp b/compiler-rt/lib/orc/dlfcn_wrapper.cpp
index fd9dce40d6738c..bbbc79f607f270 100644
--- a/compiler-rt/lib/orc/dlfcn_wrapper.cpp
+++ b/compiler-rt/lib/orc/dlfcn_wrapper.cpp
@@ -20,6 +20,7 @@ using namespace orc_rt;
extern "C" const char *__orc_rt_jit_dlerror();
extern "C" void *__orc_rt_jit_dlopen(const char *path, int mode);
+extern "C" int __orc_rt_jit_dlupdate(void *dso_handle, int mode);
extern "C" int __orc_rt_jit_dlclose(void *dso_handle);
ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
@@ -41,6 +42,18 @@ __orc_rt_jit_dlopen_wrapper(const char *ArgData, size_t ArgSize) {
.release();
}
+#ifdef __APPLE__
+ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
+__orc_rt_jit_dlupdate_wrapper(const char *ArgData, size_t ArgSize) {
+ return WrapperFunction<int32_t(SPSExecutorAddr, int32_t)>::handle(
+ ArgData, ArgSize,
+ [](ExecutorAddr &DSOHandle, int32_t mode) {
+ return __orc_rt_jit_dlupdate(DSOHandle.toPtr<void *>(), mode);
+ })
+ .release();
+}
+#endif
+
ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
__orc_rt_jit_dlclose_wrapper(const char *ArgData, size_t ArgSize) {
return WrapperFunction<int32_t(SPSExecutorAddr)>::handle(
diff --git a/compiler-rt/lib/orc/macho_platform.cpp b/compiler-rt/lib/orc/macho_platform.cpp
index c092545b2a3677..8cc3594b5d0cf7 100644
--- a/compiler-rt/lib/orc/macho_platform.cpp
+++ b/compiler-rt/lib/orc/macho_platform.cpp
@@ -331,6 +331,7 @@ class MachOPlatformRuntimeState {
const char *dlerror();
void *dlopen(std::string_view Name, int Mode);
+ int dlupdate(void *DSOHandle, int Mode);
int dlclose(void *DSOHandle);
void *dlsym(void *DSOHandle, const char *Symbol);
@@ -380,6 +381,12 @@ class MachOPlatformRuntimeState {
Error dlopenInitialize(std::unique_lock<std::mutex> &JDStatesLock,
JITDylibState &JDS, MachOJITDylibDepInfoMap &DepInfo);
+ Error dlupdateImpl(void *DSOHandle, int Mode);
+ Error dlupdateFull(std::unique_lock<std::mutex> &JDStatesLock,
+ JITDylibState &JDS);
+ Error dlupdateInitialize(std::unique_lock<std::mutex> &JDStatesLock,
+ JITDylibState &JDS);
+
Error dlcloseImpl(void *DSOHandle);
Error dlcloseDeinitialize(std::unique_lock<std::mutex> &JDStatesLock,
JITDylibState &JDS);
@@ -789,6 +796,20 @@ void *MachOPlatformRuntimeState::dlopen(std::string_view Path, int Mode) {
}
}
+int MachOPlatformRuntimeState::dlupdate(void *DSOHandle, int Mode) {
+ ORC_RT_DEBUG({
+ std::string S;
+ printdbg("MachOPlatform::dlupdate(%p) (%s)\n", DSOHandle, S.c_str());
+ });
+ std::lock_guard<std::recursive_mutex> Lock(DyldAPIMutex);
+ if (auto Err = dlupdateImpl(DSOHandle, Mode)) {
+ // FIXME: Make dlerror thread safe.
+ DLFcnError = toString(std::move(Err));
+ return -1;
+ }
+ return 0;
+}
+
int MachOPlatformRuntimeState::dlclose(void *DSOHandle) {
ORC_RT_DEBUG({
auto *JDS = getJITDylibStateByHeader(DSOHandle);
@@ -1244,6 +1265,67 @@ Error MachOPlatformRuntimeState::dlopenInitialize(
return Error::success();
}
+Error MachOPlatformRuntimeState::dlupdateImpl(void *DSOHandle, int Mode) {
+ std::unique_lock<std::mutex> Lock(JDStatesMutex);
+
+ // Try to find JITDylib state by DSOHandle.
+ auto *JDS = getJITDylibStateByHeader(DSOHandle);
+
+ if (!JDS) {
+ std::ostringstream ErrStream;
+ ErrStream << "No registered JITDylib for " << DSOHandle;
+ return make_error<StringError>(ErrStream.str());
+ }
+
+ if (!JDS->referenced())
+ return make_error<StringError>("dlupdate failed, JITDylib must be open.");
+
+ if (!JDS->Sealed) {
+ if (auto Err = dlupdateFull(Lock, *JDS))
+ return Err;
+ }
+
+ return Error::success();
+}
+
+Error MachOPlatformRuntimeState::dlupdateFull(
+ std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) {
+ // Call back to the JIT to push the initializers.
+ Expected<MachOJITDylibDepInfoMap> DepInfo((MachOJITDylibDepInfoMap()));
+ // Unlock so that we can accept the initializer update.
+ JDStatesLock.unlock();
+ if (auto Err = WrapperFunction<SPSExpected<SPSMachOJITDylibDepInfoMap>(
+ SPSExecutorAddr)>::
+ call(JITDispatch(&__orc_rt_macho_push_initializers_tag), DepInfo,
+ ExecutorAddr::fromPtr(JDS.Header)))
+ return Err;
+ JDStatesLock.lock();
+
+ if (!DepInfo)
+ return DepInfo.takeError();
+
+ if (auto Err = dlupdateInitialize(JDStatesLock, JDS))
+ return Err;
+
+ return Error::success();
+}
+
+Error MachOPlatformRuntimeState::dlupdateInitialize(
+ std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) {
+ ORC_RT_DEBUG({
+ printdbg("MachOPlatformRuntimeState::dlupdateInitialize(\"%s\")\n",
+ JDS.Name.c_str());
+ });
+
+ // Initialize this JITDylib.
+ if (auto Err = registerObjCRegistrationObjects(JDStatesLock, JDS))
+ return Err;
+ if (auto Err = runModInits(JDStatesLock, JDS))
+ return Err;
+
+ return Error::success();
+}
+
Error MachOPlatformRuntimeState::dlcloseImpl(void *DSOHandle) {
std::unique_lock<std::mutex> Lock(JDStatesMutex);
@@ -1517,6 +1599,10 @@ void *__orc_rt_macho_jit_dlopen(const char *path, int mode) {
return MachOPlatformRuntimeState::get().dlopen(path, mode);
}
+int __orc_rt_macho_jit_dlupdate(void *dso_handle, int mode) {
+ return MachOPlatformRuntimeState::get().dlupdate(dso_handle, mode);
+}
+
int __orc_rt_macho_jit_dlclose(void *dso_handle) {
return MachOPlatformRuntimeState::get().dlclose(dso_handle);
}
diff --git a/compiler-rt/lib/orc/macho_platform.h b/compiler-rt/lib/orc/macho_platform.h
index 62234039437c09..ad70c97809d2f6 100644
--- a/compiler-rt/lib/orc/macho_platform.h
+++ b/compiler-rt/lib/orc/macho_platform.h
@@ -24,6 +24,7 @@ ORC_RT_INTERFACE void __orc_rt_macho_cxa_finalize(void *dso_handle);
// dlfcn functions.
ORC_RT_INTERFACE const char *__orc_rt_macho_jit_dlerror();
ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlopen(const char *path, int mode);
+ORC_RT_INTERFACE int __orc_rt_macho_jit_dlupdate(void *dso_handle, int mode);
ORC_RT_INTERFACE int __orc_rt_macho_jit_dlclose(void *dso_handle);
ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlsym(void *dso_handle,
const char *symbol);
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
index 3a71ddc88ce956..2660b9f74f405a 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
@@ -13,6 +13,7 @@
#ifndef LLVM_EXECUTIONENGINE_ORC_LLJIT_H
#define LLVM_EXECUTIONENGINE_ORC_LLJIT_H
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
@@ -620,6 +621,7 @@ class ORCPlatformSupport : public LLJIT::PlatformSupport {
private:
orc::LLJIT &J;
DenseMap<orc::JITDylib *, orc::ExecutorAddr> DSOHandles;
+ SmallPtrSet<JITDylib const *, 8> InitializedDylib;
};
} // End namespace orc
diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index 2f9f4d33df0173..19b3f3d6ea0380 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -602,6 +602,7 @@ Error ORCPlatformSupport::initialize(orc::JITDylib &JD) {
using llvm::orc::shared::SPSExecutorAddr;
using llvm::orc::shared::SPSString;
using SPSDLOpenSig = SPSExecutorAddr(SPSString, int32_t);
+ using SPSDLUpdateSig = int32_t(SPSExecutorAddr, int32_t);
enum dlopen_mode : int32_t {
ORC_RT_RTLD_LAZY = 0x1,
ORC_RT_RTLD_NOW = 0x2,
@@ -612,9 +613,30 @@ Error ORCPlatformSupport::initialize(orc::JITDylib &JD) {
auto &ES = J.getExecutionSession();
auto MainSearchOrder = J.getMainJITDylib().withLinkOrderDo(
[](const JITDylibSearchOrder &SO) { return SO; });
+ StringRef WrapperToCall = "__orc_rt_jit_dlopen_wrapper";
+ bool dlupdate = false;
+ if (ES.getTargetTriple().isOSBinFormatMachO()) {
+ if (InitializedDylib.contains(&JD)) {
+ WrapperToCall = "__orc_rt_jit_dlupdate_wrapper";
+ dlupdate = true;
+ } else
+ InitializedDylib.insert(&JD);
+ }
- if (auto WrapperAddr = ES.lookup(
- MainSearchOrder, J.mangleAndIntern("__orc_rt_jit_dlopen_wrapper"))) {
+ if (auto WrapperAddr =
+ ES.lookup(MainSearchOrder, J.mangleAndIntern(WrapperToCall))) {
+ if (dlupdate) {
+ int32_t result;
+ auto E = ES.callSPSWrapper<SPSDLUpdateSig>(WrapperAddr->getAddress(),
+ result, DSOHandles[&JD],
+ int32_t(ORC_RT_RTLD_LAZY));
+ if (E)
+ return E;
+ else if (result)
+ return make_error<StringError>("dlupdate failed",
+ inconvertibleErrorCode());
+ return Error::success();
+ }
return ES.callSPSWrapper<SPSDLOpenSig>(WrapperAddr->getAddress(),
DSOHandles[&JD], JD.getName(),
int32_t(ORC_RT_RTLD_LAZY));
@@ -641,6 +663,7 @@ Error ORCPlatformSupport::deinitialize(orc::JITDylib &JD) {
return make_error<StringError>("dlclose failed",
inconvertibleErrorCode());
DSOHandles.erase(&JD);
+ InitializedDylib.erase(&JD);
} else
return WrapperAddr.takeError();
return Error::success();
diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index a71afe1a3162f0..e56d6b47799c0b 100644
--- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -428,6 +428,7 @@ MachOPlatform::standardRuntimeUtilityAliases() {
{"___orc_rt_run_program", "___orc_rt_macho_run_program"},
{"___orc_rt_jit_dlerror", "___orc_rt_macho_jit_dlerror"},
{"___orc_rt_jit_dlopen", "___orc_rt_macho_jit_dlopen"},
+ {"___orc_rt_jit_dlupdate", "___orc_rt_macho_jit_dlupdate"},
{"___orc_rt_jit_dlclose", "___orc_rt_macho_jit_dlclose"},
{"___orc_rt_jit_dlsym", "___orc_rt_macho_jit_dlsym"},
{"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}};
More information about the llvm-commits
mailing list