[llvm] 209c242 - [ORC] Add writePointers to ExecutorProcessControl's MemoryAccess
Sunho Kim via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 19 11:49:22 PDT 2023
Author: Sunho Kim
Date: 2023-09-20T03:49:08+09:00
New Revision: 209c242845e56eb8dbbde5e380b165d261769266
URL: https://github.com/llvm/llvm-project/commit/209c242845e56eb8dbbde5e380b165d261769266
DIFF: https://github.com/llvm/llvm-project/commit/209c242845e56eb8dbbde5e380b165d261769266.diff
LOG: [ORC] Add writePointers to ExecutorProcessControl's MemoryAccess
Add pointer write functionality to MemoryAccess that is needed for implementing redirection manager. It also refactors the code a bit by introducing InProcessMemoryAccess class.
Reviewed By: lhames
Differential Revision: https://reviews.llvm.org/D157378
Added:
Modified:
llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h
llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h
index 8c1d457d06ab36c..bc1f5f0eb70cb9a 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h
@@ -32,6 +32,7 @@ class EPCGenericMemoryAccess : public ExecutorProcessControl::MemoryAccess {
ExecutorAddr WriteUInt32s;
ExecutorAddr WriteUInt64s;
ExecutorAddr WriteBuffers;
+ ExecutorAddr WritePointers;
};
/// Create an EPCGenericMemoryAccess instance from a given set of
@@ -74,6 +75,13 @@ class EPCGenericMemoryAccess : public ExecutorProcessControl::MemoryAccess {
FAs.WriteBuffers, std::move(OnWriteComplete), Ws);
}
+ void writePointersAsync(ArrayRef<tpctypes::PointerWrite> Ws,
+ WriteResultFn OnWriteComplete) override {
+ using namespace shared;
+ EPC.callSPSWrapperAsync<void(SPSSequence<SPSMemoryAccessPointerWrite>)>(
+ FAs.WritePointers, std::move(OnWriteComplete), Ws);
+ }
+
private:
ExecutorProcessControl &EPC;
FuncAddrs FAs;
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
index a26886fefdc340b..9e42d6dd615dfd1 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
@@ -120,6 +120,9 @@ class ExecutorProcessControl {
virtual void writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws,
WriteResultFn OnWriteComplete) = 0;
+ virtual void writePointersAsync(ArrayRef<tpctypes::PointerWrite> Ws,
+ WriteResultFn OnWriteComplete) = 0;
+
Error writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws) {
std::promise<MSVCPError> ResultP;
auto ResultF = ResultP.get_future();
@@ -159,6 +162,14 @@ class ExecutorProcessControl {
[&](Error Err) { ResultP.set_value(std::move(Err)); });
return ResultF.get();
}
+
+ Error writePointers(ArrayRef<tpctypes::PointerWrite> Ws) {
+ std::promise<MSVCPError> ResultP;
+ auto ResultF = ResultP.get_future();
+ writePointersAsync(Ws,
+ [&](Error Err) { ResultP.set_value(std::move(Err)); });
+ return ResultF.get();
+ }
};
/// A pair of a dylib and a set of symbols to be looked up.
@@ -403,21 +414,48 @@ class ExecutorProcessControl {
StringMap<ExecutorAddr> BootstrapSymbols;
};
+class InProcessMemoryAccess : public ExecutorProcessControl::MemoryAccess {
+public:
+ InProcessMemoryAccess(bool IsArch64Bit) : IsArch64Bit(IsArch64Bit) {}
+ void writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,
+ WriteResultFn OnWriteComplete) override;
+
+ void writeUInt16sAsync(ArrayRef<tpctypes::UInt16Write> Ws,
+ WriteResultFn OnWriteComplete) override;
+
+ void writeUInt32sAsync(ArrayRef<tpctypes::UInt32Write> Ws,
+ WriteResultFn OnWriteComplete) override;
+
+ void writeUInt64sAsync(ArrayRef<tpctypes::UInt64Write> Ws,
+ WriteResultFn OnWriteComplete) override;
+
+ void writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws,
+ WriteResultFn OnWriteComplete) override;
+
+ void writePointersAsync(ArrayRef<tpctypes::PointerWrite> Ws,
+ WriteResultFn OnWriteComplete) override;
+
+private:
+ bool IsArch64Bit;
+};
+
/// A ExecutorProcessControl instance that asserts if any of its methods are
/// used. Suitable for use is unit tests, and by ORC clients who haven't moved
/// to ExecutorProcessControl-based APIs yet.
-class UnsupportedExecutorProcessControl : public ExecutorProcessControl {
+class UnsupportedExecutorProcessControl : public ExecutorProcessControl,
+ private InProcessMemoryAccess {
public:
UnsupportedExecutorProcessControl(
std::shared_ptr<SymbolStringPool> SSP = nullptr,
- std::unique_ptr<TaskDispatcher> D = nullptr,
- const std::string &TT = "", unsigned PageSize = 0)
- : ExecutorProcessControl(SSP ? std::move(SSP)
- : std::make_shared<SymbolStringPool>(),
- D ? std::move(D)
- : std::make_unique<InPlaceTaskDispatcher>()) {
+ std::unique_ptr<TaskDispatcher> D = nullptr, const std::string &TT = "",
+ unsigned PageSize = 0)
+ : ExecutorProcessControl(
+ SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>(),
+ D ? std::move(D) : std::make_unique<InPlaceTaskDispatcher>()),
+ InProcessMemoryAccess(Triple(TT).isArch64Bit()) {
this->TargetTriple = Triple(TT);
this->PageSize = PageSize;
+ this->MemAccess = this;
}
Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override {
@@ -452,9 +490,8 @@ class UnsupportedExecutorProcessControl : public ExecutorProcessControl {
};
/// A ExecutorProcessControl implementation targeting the current process.
-class SelfExecutorProcessControl
- : public ExecutorProcessControl,
- private ExecutorProcessControl::MemoryAccess {
+class SelfExecutorProcessControl : public ExecutorProcessControl,
+ private InProcessMemoryAccess {
public:
SelfExecutorProcessControl(
std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,
@@ -490,21 +527,6 @@ class SelfExecutorProcessControl
Error disconnect() override;
private:
- void writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,
- WriteResultFn OnWriteComplete) override;
-
- void writeUInt16sAsync(ArrayRef<tpctypes::UInt16Write> Ws,
- WriteResultFn OnWriteComplete) override;
-
- void writeUInt32sAsync(ArrayRef<tpctypes::UInt32Write> Ws,
- WriteResultFn OnWriteComplete) override;
-
- void writeUInt64sAsync(ArrayRef<tpctypes::UInt64Write> Ws,
- WriteResultFn OnWriteComplete) override;
-
- void writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws,
- WriteResultFn OnWriteComplete) override;
-
static shared::CWrapperFunctionResult
jitDispatchViaWrapperFunctionManager(void *Ctx, const void *FnTag,
const char *Data, size_t Size);
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
index 09c73db44a947b3..985baa769a67aad 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
@@ -100,6 +100,17 @@ struct BufferWrite {
StringRef Buffer;
};
+/// Describes a write to a pointer.
+/// For use with TargetProcessControl::MemoryAccess objects.
+struct PointerWrite {
+ PointerWrite() = default;
+ PointerWrite(ExecutorAddr Addr, ExecutorAddr Value)
+ : Addr(Addr), Value(Value) {}
+
+ ExecutorAddr Addr;
+ ExecutorAddr Value;
+};
+
/// A handle used to represent a loaded dylib in the target process.
using DylibHandle = ExecutorAddr;
@@ -133,6 +144,7 @@ using SPSMemoryAccessUInt32Write = SPSMemoryAccessUIntWrite<uint32_t>;
using SPSMemoryAccessUInt64Write = SPSMemoryAccessUIntWrite<uint64_t>;
using SPSMemoryAccessBufferWrite = SPSTuple<SPSExecutorAddr, SPSSequence<char>>;
+using SPSMemoryAccessPointerWrite = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>;
template <>
class SPSSerializationTraits<SPSRemoteAllocGroup, tpctypes::RemoteAllocGroup> {
@@ -302,6 +314,26 @@ class SPSSerializationTraits<SPSMemoryAccessBufferWrite,
}
};
+template <>
+class SPSSerializationTraits<SPSMemoryAccessPointerWrite,
+ tpctypes::PointerWrite> {
+public:
+ static size_t size(const tpctypes::PointerWrite &W) {
+ return SPSTuple<SPSExecutorAddr, SPSExecutorAddr>::AsArgList::size(W.Addr,
+ W.Value);
+ }
+
+ static bool serialize(SPSOutputBuffer &OB, const tpctypes::PointerWrite &W) {
+ return SPSTuple<SPSExecutorAddr, SPSExecutorAddr>::AsArgList::serialize(
+ OB, W.Addr, W.Value);
+ }
+
+ static bool deserialize(SPSInputBuffer &IB, tpctypes::PointerWrite &W) {
+ return SPSTuple<SPSExecutorAddr, SPSExecutorAddr>::AsArgList::deserialize(
+ IB, W.Addr, W.Value);
+ }
+};
+
} // end namespace shared
} // end namespace orc
} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
index fc928f2e6146bf5..ad27deff38d9eee 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
@@ -29,7 +29,8 @@ SelfExecutorProcessControl::SelfExecutorProcessControl(
std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,
Triple TargetTriple, unsigned PageSize,
std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)
- : ExecutorProcessControl(std::move(SSP), std::move(D)) {
+ : ExecutorProcessControl(std::move(SSP), std::move(D)),
+ InProcessMemoryAccess(TargetTriple.isArch64Bit()) {
OwnedMemMgr = std::move(MemMgr);
if (!OwnedMemMgr)
@@ -146,41 +147,54 @@ Error SelfExecutorProcessControl::disconnect() {
return Error::success();
}
-void SelfExecutorProcessControl::writeUInt8sAsync(
- ArrayRef<tpctypes::UInt8Write> Ws, WriteResultFn OnWriteComplete) {
+void InProcessMemoryAccess::writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,
+ WriteResultFn OnWriteComplete) {
for (auto &W : Ws)
*W.Addr.toPtr<uint8_t *>() = W.Value;
OnWriteComplete(Error::success());
}
-void SelfExecutorProcessControl::writeUInt16sAsync(
+void InProcessMemoryAccess::writeUInt16sAsync(
ArrayRef<tpctypes::UInt16Write> Ws, WriteResultFn OnWriteComplete) {
for (auto &W : Ws)
*W.Addr.toPtr<uint16_t *>() = W.Value;
OnWriteComplete(Error::success());
}
-void SelfExecutorProcessControl::writeUInt32sAsync(
+void InProcessMemoryAccess::writeUInt32sAsync(
ArrayRef<tpctypes::UInt32Write> Ws, WriteResultFn OnWriteComplete) {
for (auto &W : Ws)
*W.Addr.toPtr<uint32_t *>() = W.Value;
OnWriteComplete(Error::success());
}
-void SelfExecutorProcessControl::writeUInt64sAsync(
+void InProcessMemoryAccess::writeUInt64sAsync(
ArrayRef<tpctypes::UInt64Write> Ws, WriteResultFn OnWriteComplete) {
for (auto &W : Ws)
*W.Addr.toPtr<uint64_t *>() = W.Value;
OnWriteComplete(Error::success());
}
-void SelfExecutorProcessControl::writeBuffersAsync(
+void InProcessMemoryAccess::writeBuffersAsync(
ArrayRef<tpctypes::BufferWrite> Ws, WriteResultFn OnWriteComplete) {
for (auto &W : Ws)
memcpy(W.Addr.toPtr<char *>(), W.Buffer.data(), W.Buffer.size());
OnWriteComplete(Error::success());
}
+void InProcessMemoryAccess::writePointersAsync(
+ ArrayRef<tpctypes::PointerWrite> Ws, WriteResultFn OnWriteComplete) {
+ if (IsArch64Bit) {
+ for (auto &W : Ws)
+ *W.Addr.toPtr<uint64_t *>() = W.Value.getValue();
+ } else {
+ for (auto &W : Ws)
+ *W.Addr.toPtr<uint32_t *>() = static_cast<uint32_t>(W.Value.getValue());
+ }
+
+ OnWriteComplete(Error::success());
+}
+
shared::CWrapperFunctionResult
SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager(
void *Ctx, const void *FnTag, const char *Data, size_t Size) {
diff --git a/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp b/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp
index 83f50ecb10651b6..1aab70babc81ad1 100644
--- a/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp
@@ -41,6 +41,17 @@ llvm::orc::shared::CWrapperFunctionResult testWriteBuffers(const char *ArgData,
.release();
}
+llvm::orc::shared::CWrapperFunctionResult testWritePointers(const char *ArgData,
+ size_t ArgSize) {
+ return WrapperFunction<void(SPSSequence<SPSMemoryAccessPointerWrite>)>::
+ handle(ArgData, ArgSize,
+ [](std::vector<tpctypes::PointerWrite> Ws) {
+ for (auto &W : Ws)
+ *W.Addr.template toPtr<uint64_t *>() = W.Value.getValue();
+ })
+ .release();
+}
+
TEST(EPCGenericMemoryAccessTest, MemWrites) {
auto SelfEPC = cantFail(SelfExecutorProcessControl::Create());
@@ -54,6 +65,7 @@ TEST(EPCGenericMemoryAccessTest, MemWrites) {
FAs.WriteUInt64s = ExecutorAddr::fromPtr(
&testWriteUInts<tpctypes::UInt64Write, SPSMemoryAccessUInt64Write>);
FAs.WriteBuffers = ExecutorAddr::fromPtr(&testWriteBuffers);
+ FAs.WritePointers = ExecutorAddr::fromPtr(&testWritePointers);
auto MemAccess = std::make_unique<EPCGenericMemoryAccess>(*SelfEPC, FAs);
@@ -62,6 +74,7 @@ TEST(EPCGenericMemoryAccessTest, MemWrites) {
uint16_t Test_UInt16 = 0;
uint32_t Test_UInt32 = 0;
uint64_t Test_UInt64 = 0;
+ uint64_t Test_Pointer = 0;
char Test_Buffer[21];
auto Err1 =
@@ -93,6 +106,11 @@ TEST(EPCGenericMemoryAccessTest, MemWrites) {
EXPECT_THAT_ERROR(std::move(Err5), Succeeded());
EXPECT_EQ(StringRef(Test_Buffer, TestMsg.size()), TestMsg);
+ auto Err6 = MemAccess->writePointers(
+ {{ExecutorAddr::fromPtr(&Test_Pointer), ExecutorAddr(1U)}});
+ EXPECT_THAT_ERROR(std::move(Err6), Succeeded());
+ EXPECT_EQ(Test_Pointer, 1U);
+
cantFail(SelfEPC->disconnect());
}
More information about the llvm-commits
mailing list