[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