lli: Factor portable messaging into a new RPCChannel facility
authorAlp Toker <alp@nuanti.com>
Thu, 23 Jan 2014 22:19:45 +0000 (22:19 +0000)
committerAlp Toker <alp@nuanti.com>
Thu, 23 Jan 2014 22:19:45 +0000 (22:19 +0000)
The client and server now use a single unified low-level RPC core built around
LLVM's existing cross-platform abstractions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199947 91177308-0d34-0410-b5e6-96231b3b80d8

tools/lli/ChildTarget/ChildTarget.cpp
tools/lli/ChildTarget/Unix/ChildTarget.inc [deleted file]
tools/lli/ChildTarget/Windows/ChildTarget.inc [deleted file]
tools/lli/RPCChannel.h [new file with mode: 0644]
tools/lli/RemoteTargetExternal.cpp
tools/lli/RemoteTargetExternal.h
tools/lli/Unix/RPCChannel.inc [new file with mode: 0644]
tools/lli/Unix/RemoteTargetExternal.inc [deleted file]
tools/lli/Windows/RPCChannel.inc [new file with mode: 0644]
tools/lli/Windows/RemoteTargetExternal.inc [deleted file]

index de264af2cdd1fe7c884ffee7b984aa2ddbcc37c5..1e3000da46adf5f2b1b3bf1ee65681605f498d8f 100644 (file)
@@ -1,5 +1,6 @@
 #include "llvm/Config/config.h"
 #include "llvm/Support/Memory.h"
+#include "../RPCChannel.h"
 #include "../RemoteTarget.h"
 #include "../RemoteTargetMessage.h"
 #include <assert.h>
@@ -12,11 +13,11 @@ using namespace llvm;
 
 class LLIChildTarget {
 public:
-  ~LLIChildTarget(); // OS-specific destructor
   void initialize();
   LLIMessageType waitForIncomingMessage();
   void handleMessage(LLIMessageType messageType);
   RemoteTarget *RT;
+  RPCChannel RPC;
 
 private:
   // Incoming message handlers
@@ -32,8 +33,10 @@ private:
 
   // OS-specific functions
   void initializeConnection();
-  int WriteBytes(const void *Data, size_t Size);
-  int ReadBytes(void *Data, size_t Size);
+  int WriteBytes(const void *Data, size_t Size) {
+    return RPC.WriteBytes(Data, Size);
+  }
+  int ReadBytes(void *Data, size_t Size) { return RPC.ReadBytes(Data, Size); }
 
   // Communication handles (OS-specific)
   void *ConnectionData;
@@ -55,7 +58,7 @@ int main() {
 
 // Public methods
 void LLIChildTarget::initialize() {
-  initializeConnection();
+  RPC.createClient();
   sendChildActive();
 }
 
@@ -231,9 +234,9 @@ void LLIChildTarget::sendExecutionComplete(int Result) {
 }
 
 #ifdef LLVM_ON_UNIX
-#include "Unix/ChildTarget.inc"
+#include "../Unix/RPCChannel.inc"
 #endif
 
 #ifdef LLVM_ON_WIN32
-#include "Windows/ChildTarget.inc"
+#include "../Windows/RPCChannel.inc"
 #endif
diff --git a/tools/lli/ChildTarget/Unix/ChildTarget.inc b/tools/lli/ChildTarget/Unix/ChildTarget.inc
deleted file mode 100644 (file)
index 67a24ec..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-//===- ChildTarget.inc - Child process for external JIT execution for Unix -==//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implementation of the Unix-specific parts of the ChildTarget class
-// which executes JITed code in a separate process from where it was built.
-//
-//===----------------------------------------------------------------------===//
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-namespace {
-
-struct ConnectionData_t {
-  int InputPipe;
-  int OutputPipe;
-
-  ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {}
-};
-
-} // namespace
-
-LLIChildTarget::~LLIChildTarget() {
-  delete static_cast<ConnectionData_t *>(ConnectionData);
-}
-
-// OS-specific methods
-void LLIChildTarget::initializeConnection() {
-  // Store the parent ends of the pipes
-  ConnectionData = (void*)new ConnectionData_t(STDIN_FILENO, STDOUT_FILENO);
-}
-
-int LLIChildTarget::WriteBytes(const void *Data, size_t Size) {
-  return write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size);
-}
-
-int LLIChildTarget::ReadBytes(void *Data, size_t Size) {
-  return read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size);
-}
diff --git a/tools/lli/ChildTarget/Windows/ChildTarget.inc b/tools/lli/ChildTarget/Windows/ChildTarget.inc
deleted file mode 100644 (file)
index 289f27a..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-//=- ChildTarget.inc - Child process for external JIT execution for Windows -=//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Non-implementation of the Windows-specific parts of the ChildTarget class
-// which executes JITed code in a separate process from where it was built.
-//
-//===----------------------------------------------------------------------===//
-
-LLIChildTarget::~LLIChildTarget() {
-}
-
-// The RemoteTargetExternal implementation should prevent us from ever getting
-// here on Windows, but nothing prevents a user from running this directly.
-void LLIChildTarget::initializeConnection() {
-  assert(0 && "lli-child-target is not implemented for Windows");
-}
-
-int LLIChildTarget::WriteBytes(const void *Data, size_t Size) {
-  return 0;
-}
-
-int LLIChildTarget::ReadBytes(void *Data, size_t Size) {
-  return 0;
-}
diff --git a/tools/lli/RPCChannel.h b/tools/lli/RPCChannel.h
new file mode 100644 (file)
index 0000000..d04c8c2
--- /dev/null
@@ -0,0 +1,51 @@
+//===---------- RPCChannel.h - LLVM out-of-process JIT execution ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Definition of the RemoteTargetExternal class which executes JITed code in a
+// separate process from where it was built.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLI_RPCCHANNEL_H
+#define LLI_RPCCHANNEL_H
+
+#include <stdlib.h>
+#include <string>
+
+namespace llvm {
+
+class RPCChannel {
+public:
+  std::string ChildName;
+
+  RPCChannel() {}
+  ~RPCChannel();
+
+  static void ReportError(int rc, size_t Size, std::string &ErrorMsg);
+
+  /// Start the remote process.
+  ///
+  /// @returns True on success. On failure, ErrorMsg is updated with
+  ///          descriptive text of the encountered error.
+  bool createServer();
+
+  bool createClient();
+
+  // This will get filled in as a point to an OS-specific structure.
+  void *ConnectionData;
+
+  int WriteBytes(const void *Data, size_t Size);
+  int ReadBytes(void *Data, size_t Size);
+
+  void Wait();
+};
+
+} // end namespace llvm
+
+#endif // LLI_RPCCHANNEL_H
index 3bf7bf4e3b89d873553089a7de08757c149802e0..c1bc8dfe99ca991144abbebd99b7bf2365445aac 100644 (file)
@@ -111,7 +111,7 @@ bool RemoteTargetExternal::executeCode(uint64_t Address, int32_t &RetVal) {
 
 void RemoteTargetExternal::stop() {
   SendTerminate();
-  Wait();
+  RPC.Wait();
 }
 
 bool RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
@@ -317,9 +317,9 @@ void RemoteTargetExternal::AppendRead(void *Data, uint32_t Size) {
 }
 
 #ifdef LLVM_ON_UNIX
-#include "Unix/RemoteTargetExternal.inc"
+#include "Unix/RPCChannel.inc"
 #endif
 
 #ifdef LLVM_ON_WIN32
-#include "Windows/RemoteTargetExternal.inc"
+#include "Windows/RPCChannel.inc"
 #endif
index 5ef67100e360f4f7cddab69d5a991385d79540a1..b332b19c0b56345a4005950cc1ca7b9164346243 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef LLI_REMOTETARGETEXTERNAL_H
 #define LLI_REMOTETARGETEXTERNAL_H
 
+#include "RPCChannel.h"
 #include "RemoteTarget.h"
 #include "RemoteTargetMessage.h"
 #include "llvm/ADT/SmallVector.h"
 namespace llvm {
 
 class RemoteTargetExternal : public RemoteTarget {
+  RPCChannel RPC;
+
+  bool WriteBytes(const void *Data, size_t Size) {
+    int rc = RPC.WriteBytes(Data, Size);
+    if (rc != -1 && (size_t)rc == Size)
+      return true;
+
+    ErrorMsg = "WriteBytes: ";
+    RPC.ReportError(rc, Size, ErrorMsg);
+    return false;
+  }
+
+  bool ReadBytes(void *Data, size_t Size) {
+    int rc = RPC.ReadBytes(Data, Size);
+    if (rc != -1 && (size_t)rc == Size)
+      return true;
+
+    ErrorMsg = "ReadBytes: ";
+    RPC.ReportError(rc, Size, ErrorMsg);
+    return false;
+  }
+
 public:
   /// Allocate space in the remote target address space.
   ///
@@ -79,17 +102,26 @@ public:
   /// @returns Page alignment return value. Default of 4k.
   virtual unsigned getPageAlignment() { return 4096; }
 
-  /// Start the remote process.
-  ///
-  /// @returns True on success. On failure, ErrorMsg is updated with
-  ///          descriptive text of the encountered error.
-  virtual bool create();
+  virtual bool create() {
+    RPC.ChildName = ChildName;
+    if (!RPC.createServer())
+      return true;
+
+    // We must get Ack from the client (blocking read)
+    if (!Receive(LLI_ChildActive)) {
+      ErrorMsg += ", (RPCChannel::create) - Stopping process!";
+      stop();
+      return false;
+    }
+
+    return true;
+  }
 
   /// Terminate the remote process.
   virtual void stop();
 
   RemoteTargetExternal(std::string &Name) : RemoteTarget(), ChildName(Name) {}
-  virtual ~RemoteTargetExternal();
+  virtual ~RemoteTargetExternal() {}
 
 private:
   std::string ChildName;
@@ -119,13 +151,6 @@ private:
   SmallVector<int, 2> Sizes;
   void AppendWrite(const void *Data, uint32_t Size);
   void AppendRead(void *Data, uint32_t Size);
-
-  // This will get filled in as a point to an OS-specific structure.
-  void *ConnectionData;
-
-  bool WriteBytes(const void *Data, size_t Size);
-  bool ReadBytes(void *Data, size_t Size);
-  void Wait();
 };
 
 } // end namespace llvm
diff --git a/tools/lli/Unix/RPCChannel.inc b/tools/lli/Unix/RPCChannel.inc
new file mode 100644 (file)
index 0000000..b7dec37
--- /dev/null
@@ -0,0 +1,118 @@
+//=- RPCChannel.inc - LLVM out-of-process JIT execution for Unix --=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of the Unix-specific parts of the RPCChannel class
+// which executes JITed code in a separate process from where it was built.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+namespace {
+
+struct ConnectionData_t {
+  int InputPipe;
+  int OutputPipe;
+
+  ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {}
+};
+
+} // namespace
+
+namespace llvm {
+
+bool RPCChannel::createServer() {
+  int PipeFD[2][2];
+  pid_t ChildPID;
+
+  // Create two pipes.
+  if (pipe(PipeFD[0]) != 0 || pipe(PipeFD[1]) != 0)
+    perror("Error creating pipe: ");
+
+  ChildPID = fork();
+
+  if (ChildPID == 0) {
+    // In the child...
+
+    // Close the parent ends of the pipes
+    close(PipeFD[0][1]);
+    close(PipeFD[1][0]);
+
+    // Use our pipes as stdin and stdout
+    if (PipeFD[0][0] != STDIN_FILENO) {
+      dup2(PipeFD[0][0], STDIN_FILENO);
+      close(PipeFD[0][0]);
+    }
+    if (PipeFD[1][1] != STDOUT_FILENO) {
+      dup2(PipeFD[1][1], STDOUT_FILENO);
+      close(PipeFD[1][1]);
+    }
+
+    // Execute the child process.
+    char *args[1] = { NULL };
+    int rc = execv(ChildName.c_str(), args);
+    if (rc != 0)
+      perror("Error executing child process: ");
+  } else {
+    // In the parent...
+
+    // Close the child ends of the pipes
+    close(PipeFD[0][0]);
+    close(PipeFD[1][1]);
+
+    // Store the parent ends of the pipes
+    ConnectionData = (void *)new ConnectionData_t(PipeFD[1][0], PipeFD[0][1]);
+    return true;
+  }
+  return false;
+}
+
+bool RPCChannel::createClient() {
+  // Store the parent ends of the pipes
+  ConnectionData = (void *)new ConnectionData_t(STDIN_FILENO, STDOUT_FILENO);
+  return true;
+}
+
+void RPCChannel::ReportError(int rc, size_t Size, std::string &ErrorMsg) {
+  if (rc == -1) {
+    if (errno == EPIPE)
+      ErrorMsg += "pipe closed";
+    else if (errno == EINTR)
+      ErrorMsg += "interrupted";
+    else
+      ErrorMsg += "file descriptor error";
+  } else {
+    char Number[10] = { 0 };
+    ErrorMsg += "Expecting ";
+    sprintf(Number, "%d", (uint32_t)Size);
+    ErrorMsg += Number;
+    ErrorMsg += " bytes, Got ";
+    sprintf(Number, "%d", rc);
+    ErrorMsg += Number;
+  }
+}
+
+int RPCChannel::WriteBytes(const void *Data, size_t Size) {
+  return write(((ConnectionData_t *)ConnectionData)->OutputPipe, Data, Size);
+}
+
+int RPCChannel::ReadBytes(void *Data, size_t Size) {
+  return read(((ConnectionData_t *)ConnectionData)->InputPipe, Data, Size);
+}
+
+void RPCChannel::Wait() { wait(NULL); }
+
+RPCChannel::~RPCChannel() {
+  delete static_cast<ConnectionData_t *>(ConnectionData);
+}
+
+} // namespace llvm
diff --git a/tools/lli/Unix/RemoteTargetExternal.inc b/tools/lli/Unix/RemoteTargetExternal.inc
deleted file mode 100644 (file)
index ea8e459..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-//=- RemoteTargetExternal.inc - LLVM out-of-process JIT execution for Unix --=//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implementation of the Unix-specific parts of the RemoteTargetExternal class
-// which executes JITed code in a separate process from where it was built.
-//
-//===----------------------------------------------------------------------===//
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-namespace {
-
-struct ConnectionData_t {
-  int InputPipe;
-  int OutputPipe;
-
-  ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {}
-};
-
-} // namespace
-
-namespace llvm {
-
-bool RemoteTargetExternal::create() {
-  int PipeFD[2][2];
-  pid_t ChildPID;
-
-  // Create two pipes.
-  if (pipe(PipeFD[0]) != 0 || pipe(PipeFD[1]) != 0)
-    perror("Error creating pipe: ");
-
-  ChildPID = fork();
-
-  if (ChildPID == 0) {
-    // In the child...
-
-    // Close the parent ends of the pipes
-    close(PipeFD[0][1]);
-    close(PipeFD[1][0]);
-
-    // Use our pipes as stdin and stdout
-    if (PipeFD[0][0] != STDIN_FILENO) {
-      dup2(PipeFD[0][0], STDIN_FILENO);
-      close(PipeFD[0][0]);
-    }
-    if (PipeFD[1][1] != STDOUT_FILENO) {
-      dup2(PipeFD[1][1], STDOUT_FILENO);
-      close(PipeFD[1][1]);
-    }
-
-    // Execute the child process.
-    char *args[1] = { NULL };
-    int rc = execv(ChildName.c_str(), args);
-    if (rc != 0)
-      perror("Error executing child process: ");
-  }
-  else {
-    // In the parent...
-
-    // Close the child ends of the pipes
-    close(PipeFD[0][0]);
-    close(PipeFD[1][1]);
-
-    // Store the parent ends of the pipes
-    ConnectionData = (void*)new ConnectionData_t(PipeFD[1][0], PipeFD[0][1]);
-
-    // We must get Ack from the client (blocking read)
-    if (!Receive(LLI_ChildActive)) {
-      ErrorMsg += ", (RemoteTargetExternal::create) - Stopping process!";
-      stop();
-      return false;
-    }
-  }
-  return true;
-}
-
-static void ReportError(int rc, size_t Size, std::string &ErrorMsg) {
-  if (rc == -1) {
-    if (errno == EPIPE)
-      ErrorMsg += "pipe closed";
-    else if (errno == EINTR)
-      ErrorMsg += "interrupted";
-    else
-      ErrorMsg += "file descriptor error";
-  } else {
-    char Number[10] = { 0 };
-    ErrorMsg += "Expecting ";
-    sprintf(Number, "%d", (uint32_t)Size);
-    ErrorMsg += Number;
-    ErrorMsg += " bytes, Got ";
-    sprintf(Number, "%d", rc);
-    ErrorMsg += Number;
-  }
-}
-
-bool RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) {
-  int rc = write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size);
-  if (rc != -1 && (size_t)rc == Size)
-    return true;
-
-  ErrorMsg = "WriteBytes: ";
-  ReportError(rc, Size, ErrorMsg);
-  return false;
-}
-
-bool RemoteTargetExternal::ReadBytes(void *Data, size_t Size) {
-  int rc = read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size);
-  if (rc != -1 && (size_t)rc == Size)
-    return true;
-
-  ErrorMsg = "ReadBytes: ";
-  ReportError(rc, Size, ErrorMsg);
-  return false;
-}
-
-void RemoteTargetExternal::Wait() {
-  wait(NULL);
-}
-
-RemoteTargetExternal::~RemoteTargetExternal() {
-  delete static_cast<ConnectionData_t *>(ConnectionData);
-}
-
-} // namespace llvm
diff --git a/tools/lli/Windows/RPCChannel.inc b/tools/lli/Windows/RPCChannel.inc
new file mode 100644 (file)
index 0000000..3ad57ae
--- /dev/null
@@ -0,0 +1,31 @@
+//=- RPCChannel.inc - LLVM out-of-process JIT execution for Windows --=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of the Windows-specific parts of the RPCChannel class
+// which executes JITed code in a separate process from where it was built.
+//
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+
+bool RPCChannel::createServer() { return false; }
+
+bool RPCChannel::createClient() { return false; }
+
+void RPCChannel::ReportError(int rc, size_t Size, std::string &ErrorMsg) {}
+
+int RPCChannel::WriteBytes(const void *Data, size_t Size) { return -1; }
+
+int RPCChannel::ReadBytes(void *Data, size_t Size) { return -1; }
+
+void RPCChannel::Wait() {}
+
+RPCChannel::~RPCChannel() {}
+
+} // namespace llvm
diff --git a/tools/lli/Windows/RemoteTargetExternal.inc b/tools/lli/Windows/RemoteTargetExternal.inc
deleted file mode 100644 (file)
index 0a4dba6..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-//= RemoteTargetExternal.inc - LLVM out-of-process JIT execution for Windows =//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Definition of the Windows-specific parts of the RemoteTargetExternal class
-// which is meant to execute JITed code in a separate process from where it was
-// built.  To support this functionality on Windows, implement these functions.
-//
-//===----------------------------------------------------------------------===//
-
-namespace llvm {
-
-bool RemoteTargetExternal::create() {
-  return false;
-}
-
-bool RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) {
-  return false;
-}
-
-bool RemoteTargetExternal::ReadBytes(void *Data, size_t Size) {
-  return false;
-}
-
-void RemoteTargetExternal::Wait() {
-}
-
-RemoteTargetExternal::~RemoteTargetExternal() {
-}
-
-} // namespace llvm