[llvm] r191843 - Adding out-of-process execution support to lli.

Andrew Kaylor andrew.kaylor at intel.com
Wed Oct 2 10:12:36 PDT 2013


Author: akaylor
Date: Wed Oct  2 12:12:36 2013
New Revision: 191843

URL: http://llvm.org/viewvc/llvm-project?rev=191843&view=rev
Log:
Adding out-of-process execution support to lli.

At this time only Unix-based systems are supported.  Windows has stubs and should re-route to the simulated mode.

Thanks to Sriram Murali for contributions to this patch.



Added:
    llvm/trunk/tools/lli/ChildTarget/
    llvm/trunk/tools/lli/ChildTarget/CMakeLists.txt
    llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp
    llvm/trunk/tools/lli/ChildTarget/Makefile
    llvm/trunk/tools/lli/ChildTarget/Unix/
    llvm/trunk/tools/lli/ChildTarget/Unix/ChildTarget.inc
    llvm/trunk/tools/lli/ChildTarget/Windows/
    llvm/trunk/tools/lli/ChildTarget/Windows/ChildTarget.inc
    llvm/trunk/tools/lli/RemoteTargetExternal.cpp
    llvm/trunk/tools/lli/RemoteTargetExternal.h
    llvm/trunk/tools/lli/RemoteTargetMessage.h
    llvm/trunk/tools/lli/Unix/
    llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc
    llvm/trunk/tools/lli/Windows/
    llvm/trunk/tools/lli/Windows/RemoteTargetExternal.inc
Modified:
    llvm/trunk/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll
    llvm/trunk/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll
    llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-common-symbols-remote.ll
    llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-data-align-remote.ll
    llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll
    llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-remote.ll
    llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-remote.ll
    llvm/trunk/tools/lli/CMakeLists.txt
    llvm/trunk/tools/lli/Makefile
    llvm/trunk/tools/lli/RemoteTarget.cpp
    llvm/trunk/tools/lli/RemoteTarget.h
    llvm/trunk/tools/lli/lli.cpp

Modified: llvm/trunk/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll?rev=191843&r1=191842&r2=191843&view=diff
==============================================================================
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll (original)
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll Wed Oct  2 12:12:36 2013
@@ -1,4 +1,4 @@
-; RUN: %lli_mcjit -remote-mcjit %s > /dev/null
+; RUN: %lli_mcjit -remote-mcjit -mcjit-remote-process=lli-child-target %s > /dev/null
 ; XFAIL:  mips
 
 define i32 @bar() {

Modified: llvm/trunk/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll?rev=191843&r1=191842&r2=191843&view=diff
==============================================================================
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll (original)
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll Wed Oct  2 12:12:36 2013
@@ -1,4 +1,4 @@
-; RUN: %lli_mcjit -remote-mcjit -disable-lazy-compilation=false %s
+; RUN: %lli_mcjit -remote-mcjit -disable-lazy-compilation=false -mcjit-remote-process=lli-child-target %s
 ; XFAIL:  mips
 
 define i32 @main() nounwind {

Modified: llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-common-symbols-remote.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-common-symbols-remote.ll?rev=191843&r1=191842&r2=191843&view=diff
==============================================================================
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-common-symbols-remote.ll (original)
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-common-symbols-remote.ll Wed Oct  2 12:12:36 2013
@@ -1,4 +1,4 @@
-; RUN: %lli_mcjit -remote-mcjit -O0 -disable-lazy-compilation=false %s
+; RUN: %lli_mcjit -remote-mcjit -O0 -disable-lazy-compilation=false -mcjit-remote-process=lli-child-target %s
 ; XFAIL: mips
 
 ; The intention of this test is to verify that symbols mapped to COMMON in ELF

Modified: llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-data-align-remote.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-data-align-remote.ll?rev=191843&r1=191842&r2=191843&view=diff
==============================================================================
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-data-align-remote.ll (original)
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-data-align-remote.ll Wed Oct  2 12:12:36 2013
@@ -1,4 +1,4 @@
-; RUN:  %lli_mcjit -remote-mcjit -O0 %s
+; RUN:  %lli_mcjit -remote-mcjit -O0 -mcjit-remote-process=lli-child-target %s
 ; XFAIL: mips
 
 ; Check that a variable is always aligned as specified.

Modified: llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll?rev=191843&r1=191842&r2=191843&view=diff
==============================================================================
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll (original)
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll Wed Oct  2 12:12:36 2013
@@ -1,4 +1,4 @@
-; RUN: %lli_mcjit -remote-mcjit %s > /dev/null
+; RUN: %lli_mcjit -remote-mcjit -mcjit-remote-process=lli-child-target %s > /dev/null
 ; XFAIL:  mips
 
 define double @test(double* %DP, double %Arg) {

Modified: llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-remote.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-remote.ll?rev=191843&r1=191842&r2=191843&view=diff
==============================================================================
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-remote.ll (original)
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-remote.ll Wed Oct  2 12:12:36 2013
@@ -1,4 +1,4 @@
-; RUN: %lli_mcjit -remote-mcjit %s > /dev/null
+; RUN: %lli_mcjit -remote-mcjit -mcjit-remote-process=lli-child-target %s > /dev/null
 ; XFAIL: mips
 
 @count = global i32 1, align 4

Modified: llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-remote.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-remote.ll?rev=191843&r1=191842&r2=191843&view=diff
==============================================================================
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-remote.ll (original)
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-remote.ll Wed Oct  2 12:12:36 2013
@@ -1,4 +1,4 @@
-; RUN: %lli_mcjit -remote-mcjit -O0 %s
+; RUN: %lli_mcjit -remote-mcjit -O0 -mcjit-remote-process=lli-child-target %s
 
 @.str = private unnamed_addr constant [6 x i8] c"data1\00", align 1
 @ptr = global i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0), align 4

Modified: llvm/trunk/tools/lli/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/CMakeLists.txt?rev=191843&r1=191842&r2=191843&view=diff
==============================================================================
--- llvm/trunk/tools/lli/CMakeLists.txt (original)
+++ llvm/trunk/tools/lli/CMakeLists.txt Wed Oct  2 12:12:36 2013
@@ -1,6 +1,8 @@
 
 set(LLVM_LINK_COMPONENTS mcjit jit interpreter nativecodegen bitreader asmparser irreader selectiondag native instrumentation)
 
+add_subdirectory(ChildTarget)
+
 if( LLVM_USE_OPROFILE )
   set(LLVM_LINK_COMPONENTS
     ${LLVM_LINK_COMPONENTS}
@@ -21,4 +23,5 @@ add_llvm_tool(lli
   lli.cpp
   RecordingMemoryManager.cpp
   RemoteTarget.cpp
+  RemoteTargetExternal.cpp
   )

Added: llvm/trunk/tools/lli/ChildTarget/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/CMakeLists.txt?rev=191843&view=auto
==============================================================================
--- llvm/trunk/tools/lli/ChildTarget/CMakeLists.txt (added)
+++ llvm/trunk/tools/lli/ChildTarget/CMakeLists.txt Wed Oct  2 12:12:36 2013
@@ -0,0 +1,3 @@
+add_llvm_tool(lli-child-target
+  ChildTarget.cpp
+  )

Added: llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp?rev=191843&view=auto
==============================================================================
--- llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp (added)
+++ llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp Wed Oct  2 12:12:36 2013
@@ -0,0 +1,241 @@
+#include "llvm/Config/config.h"
+
+#include "../RemoteTargetMessage.h"
+#include <assert.h>
+#include <map>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+using namespace llvm;
+
+class LLIChildTarget {
+public:
+  void initialize();
+  LLIMessageType waitForIncomingMessage();
+  void handleMessage(LLIMessageType messageType);
+
+private:
+  // Incoming message handlers
+  void handleAllocateSpace();
+  void handleLoadSection(bool IsCode);
+  void handleExecute();
+  void handleTerminate();
+
+  // Outgoing message handlers
+  void sendChildActive();
+  void sendAllocationResult(uint64_t Addr);
+  void sendLoadComplete();
+  void sendExecutionComplete(uint64_t Result);
+
+  // OS-specific functions
+  void initializeConnection();
+  int WriteBytes(const void *Data, size_t Size);
+  int ReadBytes(void *Data, size_t Size);
+  uint64_t allocate(uint32_t Alignment, uint32_t Size);
+  void makeSectionExecutable(uint64_t Addr, uint32_t Size);
+  void InvalidateInstructionCache(const void *Addr, size_t Len);
+  void releaseMemory(uint64_t Addr, uint32_t Size);
+
+  // Store a map of allocated buffers to sizes.
+  typedef std::map<uint64_t, uint32_t> AllocMapType;
+  AllocMapType m_AllocatedBufferMap;
+
+  // Communication handles (OS-specific)
+  void *ConnectionData;
+};
+
+int main() {
+  LLIChildTarget  ThisChild;
+  ThisChild.initialize();
+  LLIMessageType MsgType;
+  do {
+    MsgType = ThisChild.waitForIncomingMessage();
+    ThisChild.handleMessage(MsgType);
+  } while (MsgType != LLI_Terminate &&
+           MsgType != LLI_Error);
+  return 0;
+}
+
+// Public methods
+void LLIChildTarget::initialize() {
+  initializeConnection();
+  sendChildActive();
+}
+
+LLIMessageType LLIChildTarget::waitForIncomingMessage() {
+  int32_t MsgType = -1;
+  if (ReadBytes(&MsgType, 4) > 0)
+    return (LLIMessageType)MsgType;
+  return LLI_Error;
+}
+
+void LLIChildTarget::handleMessage(LLIMessageType messageType) {
+  switch (messageType) {
+    case LLI_AllocateSpace:
+      handleAllocateSpace();
+      break;
+    case LLI_LoadCodeSection:
+      handleLoadSection(true);
+      break;
+    case LLI_LoadDataSection:
+      handleLoadSection(false);
+      break;
+    case LLI_Execute:
+      handleExecute();
+      break;
+    case LLI_Terminate:
+      handleTerminate();
+      break;
+    default:
+      // FIXME: Handle error!
+      break;
+  }
+}
+
+// Incoming message handlers
+void LLIChildTarget::handleAllocateSpace() {
+  // Read and verify the message data size.
+  uint32_t DataSize;
+  int rc = ReadBytes(&DataSize, 4);
+  assert(rc == 4);
+  assert(DataSize == 8);
+
+  // Read the message arguments.
+  uint32_t Alignment;
+  uint32_t AllocSize;
+  rc = ReadBytes(&Alignment, 4);
+  assert(rc == 4);
+  rc = ReadBytes(&AllocSize, 4);
+  assert(rc == 4);
+
+  // Allocate the memory.
+  uint64_t Addr = allocate(Alignment, AllocSize);
+
+  // Send AllocationResult message.
+  sendAllocationResult(Addr);
+}
+
+void LLIChildTarget::handleLoadSection(bool IsCode) {
+  // Read the message data size.
+  uint32_t DataSize;
+  int rc = ReadBytes(&DataSize, 4);
+  assert(rc == 4);
+
+  // Read the target load address.
+  uint64_t Addr;
+  rc = ReadBytes(&Addr, 8);
+  assert(rc == 8);
+
+  size_t BufferSize = DataSize - 8;
+
+  // FIXME: Verify that this is in allocated space
+
+  // Read section data into previously allocated buffer
+  rc = ReadBytes((void*)Addr, DataSize - 8);
+  assert(rc == (int)(BufferSize));
+
+  // If IsCode, mark memory executable
+  if (IsCode)
+    makeSectionExecutable(Addr, BufferSize);
+
+  // Send MarkLoadComplete message.
+  sendLoadComplete();
+}
+
+void LLIChildTarget::handleExecute() {
+  // Read the message data size.
+  uint32_t DataSize;
+  int rc = ReadBytes(&DataSize, 4);
+  assert(rc == 4);
+  assert(DataSize == 8);
+
+  // Read the target address.
+  uint64_t Addr;
+  rc = ReadBytes(&Addr, 8);
+  assert(rc == 8);
+
+  // Call function
+  int Result;
+  int (*fn)(void) = (int(*)(void))Addr;
+  Result = fn();
+
+  // Send ExecutionResult message.
+  sendExecutionComplete((int64_t)Result);
+}
+
+void LLIChildTarget::handleTerminate() {
+  // Release all allocated memory
+  AllocMapType::iterator Begin = m_AllocatedBufferMap.begin();
+  AllocMapType::iterator End = m_AllocatedBufferMap.end();
+  for (AllocMapType::iterator It = Begin; It != End; ++It) {
+    releaseMemory(It->first, It->second);
+  }
+  m_AllocatedBufferMap.clear();
+}
+
+// Outgoing message handlers
+void LLIChildTarget::sendChildActive() {
+  // Write the message type.
+  uint32_t MsgType = (uint32_t)LLI_ChildActive;
+  int rc = WriteBytes(&MsgType, 4);
+  assert(rc == 4);
+
+  // Write the data size.
+  uint32_t DataSize = 0;
+  rc = WriteBytes(&DataSize, 4);
+  assert(rc == 4);
+}
+
+void LLIChildTarget::sendAllocationResult(uint64_t Addr) {
+  // Write the message type.
+  uint32_t MsgType = (uint32_t)LLI_AllocationResult;
+  int rc = WriteBytes(&MsgType, 4);
+  assert(rc == 4);
+
+  // Write the data size.
+  uint32_t DataSize = 8;
+  rc = WriteBytes(&DataSize, 4);
+  assert(rc == 4);
+
+  // Write the allocated address.
+  rc = WriteBytes(&Addr, 8);
+  assert(rc == 8);
+}
+
+void LLIChildTarget::sendLoadComplete() {
+  // Write the message type.
+  uint32_t MsgType = (uint32_t)LLI_LoadComplete;
+  int rc = WriteBytes(&MsgType, 4);
+  assert(rc == 4);
+
+  // Write the data size.
+  uint32_t DataSize = 0;
+  rc = WriteBytes(&DataSize, 4);
+  assert(rc == 4);
+}
+
+void LLIChildTarget::sendExecutionComplete(uint64_t Result) {
+  // Write the message type.
+  uint32_t MsgType = (uint32_t)LLI_ExecutionResult;
+  int rc = WriteBytes(&MsgType, 4);
+  assert(rc == 4);
+
+
+  // Write the data size.
+  uint32_t DataSize = 8;
+  rc = WriteBytes(&DataSize, 4);
+  assert(rc == 4);
+
+  // Write the result.
+  rc = WriteBytes(&Result, 8);
+  assert(rc == 8);
+}
+
+#ifdef LLVM_ON_UNIX
+#include "Unix/ChildTarget.inc"
+#endif
+
+#ifdef LLVM_ON_WIN32
+#include "Windows/ChildTarget.inc"
+#endif

Added: llvm/trunk/tools/lli/ChildTarget/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/Makefile?rev=191843&view=auto
==============================================================================
--- llvm/trunk/tools/lli/ChildTarget/Makefile (added)
+++ llvm/trunk/tools/lli/ChildTarget/Makefile Wed Oct  2 12:12:36 2013
@@ -0,0 +1,17 @@
+##===- tools/lli/Makefile ------------------------------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL := ../../..
+TOOLNAME := lli-child-target
+
+include $(LEVEL)/Makefile.config
+
+LINK_COMPONENTS :=
+
+include $(LLVM_SRC_ROOT)/Makefile.rules

Added: llvm/trunk/tools/lli/ChildTarget/Unix/ChildTarget.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/Unix/ChildTarget.inc?rev=191843&view=auto
==============================================================================
--- llvm/trunk/tools/lli/ChildTarget/Unix/ChildTarget.inc (added)
+++ llvm/trunk/tools/lli/ChildTarget/Unix/ChildTarget.inc Wed Oct  2 12:12:36 2013
@@ -0,0 +1,141 @@
+//===- 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 <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+namespace {
+
+struct ConnectionData_t {
+  int InputPipe;
+  int OutputPipe;
+
+  ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {}
+};
+
+} // namespace
+
+// 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);
+}
+
+// The functions below duplicate functionality that is implemented in
+// Support/Memory.cpp with the goal of avoiding a dependency on any
+// llvm libraries.
+
+uint64_t LLIChildTarget::allocate(uint32_t Alignment, uint32_t Size) {
+  if (!Alignment)
+    Alignment = 16;
+
+  static const size_t PageSize = getpagesize();
+  const size_t NumPages = (Size+PageSize-1)/PageSize;
+  Size = NumPages*PageSize;
+
+  int fd = -1;
+#ifdef NEED_DEV_ZERO_FOR_MMAP
+  static int zero_fd = open("/dev/zero", O_RDWR);
+  if (zero_fd == -1)
+    return 0;
+  fd = zero_fd;
+#endif
+
+  int MMFlags = MAP_PRIVATE |
+#ifdef HAVE_MMAP_ANONYMOUS
+  MAP_ANONYMOUS
+#else
+  MAP_ANON
+#endif
+  ; // Ends statement above
+
+  uint64_t Addr = (uint64_t)::mmap(0, Size, PROT_READ | PROT_WRITE, MMFlags, fd, 0);
+  if (Addr == (uint64_t)MAP_FAILED)
+    return 0;
+
+  // Align the address.
+  Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
+
+  m_AllocatedBufferMap[Addr] = Size;
+
+  // Return aligned address
+  return Addr;
+}
+
+void LLIChildTarget::makeSectionExecutable(uint64_t Addr, uint32_t Size) {
+  // FIXME: We have to mark the memory as RWX because multiple code chunks may
+  // be on the same page.  The RemoteTarget interface should be changed to
+  // work around that.
+  int Result = ::mprotect((void*)Addr, Size, PROT_READ | PROT_WRITE | PROT_EXEC);
+  if (Result != 0)
+    InvalidateInstructionCache((const void *)Addr, Size);
+}
+
+/// InvalidateInstructionCache - Before the JIT can run a block of code
+/// that has been emitted it must invalidate the instruction cache on some
+/// platforms.
+void LLIChildTarget::InvalidateInstructionCache(const void *Addr,
+                                        size_t Len) {
+
+// icache invalidation for PPC and ARM.
+#if defined(__APPLE__)
+
+#  if (defined(__POWERPC__) || defined (__ppc__) || \
+     defined(_POWER) || defined(_ARCH_PPC)) || defined(__arm__)
+  sys_icache_invalidate(const_cast<void *>(Addr), Len);
+#  endif
+
+#else
+
+#  if (defined(__POWERPC__) || defined (__ppc__) || \
+       defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__)
+  const size_t LineSize = 32;
+
+  const intptr_t Mask = ~(LineSize - 1);
+  const intptr_t StartLine = ((intptr_t) Addr) & Mask;
+  const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask;
+
+  for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
+    asm volatile("dcbf 0, %0" : : "r"(Line));
+  asm volatile("sync");
+
+  for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
+    asm volatile("icbi 0, %0" : : "r"(Line));
+  asm volatile("isync");
+#  elif defined(__arm__) && defined(__GNUC__)
+  // FIXME: Can we safely always call this for __GNUC__ everywhere?
+  const char *Start = static_cast<const char *>(Addr);
+  const char *End = Start + Len;
+  __clear_cache(const_cast<char *>(Start), const_cast<char *>(End));
+#  elif defined(__mips__)
+  const char *Start = static_cast<const char *>(Addr);
+  cacheflush(const_cast<char *>(Start), Len, BCACHE);
+#  endif
+
+#endif  // end apple
+}
+
+void LLIChildTarget::releaseMemory(uint64_t Addr, uint32_t Size) {
+  ::munmap((void*)Addr, Size);
+}

Added: llvm/trunk/tools/lli/ChildTarget/Windows/ChildTarget.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/Windows/ChildTarget.inc?rev=191843&view=auto
==============================================================================
--- llvm/trunk/tools/lli/ChildTarget/Windows/ChildTarget.inc (added)
+++ llvm/trunk/tools/lli/ChildTarget/Windows/ChildTarget.inc Wed Oct  2 12:12:36 2013
@@ -0,0 +1,41 @@
+//=- 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.
+//
+//===----------------------------------------------------------------------===//
+
+// 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;
+}
+
+uint64_t LLIChildTarget::allocate(uint32_t Alignment, uint32_t Size) {
+  return 0;
+}
+
+void LLIChildTarget::makeSectionExecutable(uint64_t Addr, uint32_t Size) {
+}
+
+void LLIChildTarget::InvalidateInstructionCache(const void *Addr,
+                                        size_t Len) {
+}
+
+void LLIChildTarget::releaseMemory(uint64_t Addr, uint32_t Size) {
+}

Modified: llvm/trunk/tools/lli/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/Makefile?rev=191843&r1=191842&r2=191843&view=diff
==============================================================================
--- llvm/trunk/tools/lli/Makefile (original)
+++ llvm/trunk/tools/lli/Makefile Wed Oct  2 12:12:36 2013
@@ -10,6 +10,8 @@
 LEVEL := ../..
 TOOLNAME := lli
 
+PARALLEL_DIRS := ChildTarget
+
 include $(LEVEL)/Makefile.config
 
 LINK_COMPONENTS := mcjit jit instrumentation interpreter nativecodegen bitreader asmparser irreader selectiondag native

Modified: llvm/trunk/tools/lli/RemoteTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTarget.cpp?rev=191843&r1=191842&r2=191843&view=diff
==============================================================================
--- llvm/trunk/tools/lli/RemoteTarget.cpp (original)
+++ llvm/trunk/tools/lli/RemoteTarget.cpp Wed Oct  2 12:12:36 2013
@@ -13,13 +13,44 @@
 //===----------------------------------------------------------------------===//
 
 #include "RemoteTarget.h"
+#include "RemoteTargetExternal.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/DataTypes.h"
 #include "llvm/Support/Memory.h"
 #include <stdlib.h>
 #include <string>
+
 using namespace llvm;
 
+// Static methods
+RemoteTarget *RemoteTarget::createRemoteTarget() {
+  return new RemoteTarget;
+}
+
+RemoteTarget *RemoteTarget::createExternalRemoteTarget(std::string &ChildName) {
+#ifdef LLVM_ON_UNIX
+  return new RemoteTargetExternal(ChildName);
+#else
+  return 0;
+#endif
+}
+
+bool RemoteTarget::hostSupportsExternalRemoteTarget() {
+#ifdef LLVM_ON_UNIX
+  return true;
+#else
+  return false;
+#endif
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Simulated remote execution
+//
+// This implementation will simply move generated code and data to a new memory
+// location in the current executable and let it run from there.
+////////////////////////////////////////////////////////////////////////////////
+
 bool RemoteTarget::allocateSpace(size_t Size, unsigned Alignment,
                                  uint64_t &Address) {
   sys::MemoryBlock *Prev = Allocations.size() ? &Allocations.back() : NULL;

Modified: llvm/trunk/tools/lli/RemoteTarget.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTarget.h?rev=191843&r1=191842&r2=191843&view=diff
==============================================================================
--- llvm/trunk/tools/lli/RemoteTarget.h (original)
+++ llvm/trunk/tools/lli/RemoteTarget.h Wed Oct  2 12:12:36 2013
@@ -41,7 +41,9 @@ public:
   ///
   /// @returns False on success. On failure, ErrorMsg is updated with
   ///          descriptive text of the encountered error.
-  bool allocateSpace(size_t Size, unsigned Alignment, uint64_t &Address);
+  virtual bool allocateSpace(size_t Size,
+                             unsigned Alignment,
+                             uint64_t &Address);
 
   /// Load data into the target address space.
   ///
@@ -51,7 +53,9 @@ public:
   ///
   /// @returns False on success. On failure, ErrorMsg is updated with
   ///          descriptive text of the encountered error.
-  bool loadData(uint64_t Address, const void *Data, size_t Size);
+  virtual bool loadData(uint64_t Address,
+                        const void *Data,
+                        size_t Size);
 
   /// Load code into the target address space and prepare it for execution.
   ///
@@ -61,7 +65,9 @@ public:
   ///
   /// @returns False on success. On failure, ErrorMsg is updated with
   ///          descriptive text of the encountered error.
-  bool loadCode(uint64_t Address, const void *Data, size_t Size);
+  virtual bool loadCode(uint64_t Address,
+                        const void *Data,
+                        size_t Size);
 
   /// Execute code in the target process. The called function is required
   /// to be of signature int "(*)(void)".
@@ -72,24 +78,29 @@ public:
   ///
   /// @returns False on success. On failure, ErrorMsg is updated with
   ///          descriptive text of the encountered error.
-  bool executeCode(uint64_t Address, int &RetVal);
+  virtual bool executeCode(uint64_t Address,
+                           int &RetVal);
 
   /// Minimum alignment for memory permissions. Used to seperate code and
   /// data regions to make sure data doesn't get marked as code or vice
   /// versa.
   ///
   /// @returns Page alignment return value. Default of 4k.
-  unsigned getPageAlignment() { return 4096; }
+  virtual unsigned getPageAlignment() { return 4096; }
 
   /// Start the remote process.
-  void create();
+  virtual void create();
 
   /// Terminate the remote process.
-  void stop();
+  virtual void stop();
 
   RemoteTarget() : ErrorMsg(""), IsRunning(false) {}
-  ~RemoteTarget() { if (IsRunning) stop(); }
+  virtual ~RemoteTarget() { if (IsRunning) stop(); }
 
+  // Create an instance of the system-specific remote target class.
+  static RemoteTarget *createRemoteTarget();
+  static RemoteTarget *createExternalRemoteTarget(std::string &ChildName);
+  static bool hostSupportsExternalRemoteTarget(); 
 private:
   // Main processing function for the remote target process. Command messages
   // are received on file descriptor CmdFD and responses come back on OutFD.

Added: llvm/trunk/tools/lli/RemoteTargetExternal.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTargetExternal.cpp?rev=191843&view=auto
==============================================================================
--- llvm/trunk/tools/lli/RemoteTargetExternal.cpp (added)
+++ llvm/trunk/tools/lli/RemoteTargetExternal.cpp Wed Oct  2 12:12:36 2013
@@ -0,0 +1,162 @@
+//===---- RemoteTargetExternal.cpp - 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of the RemoteTargetExternal class which executes JITed code
+// in a separate process from where it was built.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Config/config.h"
+
+#include "RemoteTarget.h"
+#include "RemoteTargetExternal.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Memory.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+using namespace llvm;
+
+bool RemoteTargetExternal::allocateSpace(size_t Size, unsigned Alignment,
+                                 uint64_t &Address) {
+  SendAllocateSpace(Alignment, Size);
+  Receive(LLI_AllocationResult, Address);
+  return false;
+}
+
+bool RemoteTargetExternal::loadData(uint64_t Address, const void *Data, size_t Size) {
+  SendLoadSection(Address, Data, (uint32_t)Size, false);
+  Receive(LLI_LoadComplete);
+  return false;
+}
+
+bool RemoteTargetExternal::loadCode(uint64_t Address, const void *Data, size_t Size) {
+  SendLoadSection(Address, Data, (uint32_t)Size, true);
+  Receive(LLI_LoadComplete);
+  return false;
+}
+
+bool RemoteTargetExternal::executeCode(uint64_t Address, int &RetVal) {
+  SendExecute(Address);
+
+  Receive(LLI_ExecutionResult, RetVal);
+  return false;
+}
+
+void RemoteTargetExternal::stop() {
+  SendTerminate();
+  Wait();
+}
+
+void RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
+  int rc;
+  uint32_t MsgType = (uint32_t)LLI_AllocateSpace;
+  rc = WriteBytes(&MsgType, 4);
+  assert(rc == 4 && "Error writing message type.");
+
+  uint32_t DataSize = 8;
+  rc = WriteBytes(&DataSize, 4);
+  assert(rc == 4 && "Error writing data size.");
+
+  rc = WriteBytes(&Alignment, 4);
+  assert(rc == 4 && "Error writing alignment data.");
+
+  rc = WriteBytes(&Size, 4);
+  assert(rc == 4 && "Error writing size data.");
+}
+
+void RemoteTargetExternal::SendLoadSection(uint64_t Addr,
+                                       const void *Data,
+                                       uint32_t Size,
+                                       bool IsCode) {
+  int rc;
+  uint32_t MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;
+  rc = WriteBytes(&MsgType, 4);
+  assert(rc == 4 && "Error writing message type.");
+
+  uint32_t DataSize = Size + 8;
+  rc = WriteBytes(&DataSize, 4);
+  assert(rc == 4 && "Error writing data size.");
+
+  rc = WriteBytes(&Addr, 8);
+  assert(rc == 8 && "Error writing data.");
+
+  rc = WriteBytes(Data, Size);
+  assert(rc == (int)Size && "Error writing data.");
+}
+
+void RemoteTargetExternal::SendExecute(uint64_t Addr) {
+  int rc;
+  uint32_t MsgType = (uint32_t)LLI_Execute;
+  rc = WriteBytes(&MsgType, 4);
+  assert(rc == 4 && "Error writing message type.");
+
+  uint32_t DataSize = 8;
+  rc = WriteBytes(&DataSize, 4);
+  assert(rc == 4 && "Error writing data size.");
+
+  rc = WriteBytes(&Addr, 8);
+  assert(rc == 8 && "Error writing data.");
+}
+
+void RemoteTargetExternal::SendTerminate() {
+  int rc;
+  uint32_t MsgType = (uint32_t)LLI_Terminate;
+  rc = WriteBytes(&MsgType, 4);
+  assert(rc == 4 && "Error writing message type.");
+
+  // No data or data size is sent with Terminate
+}
+
+
+void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType) {
+  int rc;
+  uint32_t MsgType;
+  rc = ReadBytes(&MsgType, 4);
+  assert(rc == 4 && "Error reading message type.");
+  assert(MsgType == ExpectedMsgType && "Error: received unexpected message type.");
+
+  uint32_t DataSize;
+  rc = ReadBytes(&DataSize, 4);
+  assert(rc == 4 && "Error reading data size.");
+  assert(DataSize == 0 && "Error: unexpected data size.");
+}
+
+void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, int &Data) {
+  uint64_t Temp;
+  Receive(ExpectedMsgType, Temp);
+  Data = (int)(int64_t)Temp;
+}
+
+void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, uint64_t &Data) {
+  int rc;
+  uint32_t MsgType;
+  rc = ReadBytes(&MsgType, 4);
+  assert(rc == 4 && "Error reading message type.");
+  assert(MsgType == ExpectedMsgType && "Error: received unexpected message type.");
+
+  uint32_t DataSize;
+  rc = ReadBytes(&DataSize, 4);
+  assert(rc == 4 && "Error reading data size.");
+  assert(DataSize == 8 && "Error: unexpected data size.");
+
+  rc = ReadBytes(&Data, 8);
+  assert(DataSize == 8 && "Error: unexpected data.");
+}
+
+#ifdef LLVM_ON_UNIX
+#include "Unix/RemoteTargetExternal.inc"
+#endif
+
+#ifdef LLVM_ON_WIN32
+#include "Windows/RemoteTargetExternal.inc"
+#endif

Added: llvm/trunk/tools/lli/RemoteTargetExternal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTargetExternal.h?rev=191843&view=auto
==============================================================================
--- llvm/trunk/tools/lli/RemoteTargetExternal.h (added)
+++ llvm/trunk/tools/lli/RemoteTargetExternal.h Wed Oct  2 12:12:36 2013
@@ -0,0 +1,118 @@
+//===----- RemoteTargetExternal.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_REMOTETARGETEXTERNAL_H
+#define LLI_REMOTETARGETEXTERNAL_H
+
+#include "llvm/Config/config.h"
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Memory.h"
+#include <stdlib.h>
+#include <string>
+
+#include "RemoteTarget.h"
+#include "RemoteTargetMessage.h"
+
+namespace llvm {
+
+class RemoteTargetExternal : public RemoteTarget {
+public:
+  /// Allocate space in the remote target address space.
+  ///
+  /// @param      Size      Amount of space, in bytes, to allocate.
+  /// @param      Alignment Required minimum alignment for allocated space.
+  /// @param[out] Address   Remote address of the allocated memory.
+  ///
+  /// @returns False on success. On failure, ErrorMsg is updated with
+  ///          descriptive text of the encountered error.
+  virtual bool allocateSpace(size_t Size,
+                             unsigned Alignment,
+                             uint64_t &Address);
+
+  /// Load data into the target address space.
+  ///
+  /// @param      Address   Destination address in the target process.
+  /// @param      Data      Source address in the host process.
+  /// @param      Size      Number of bytes to copy.
+  ///
+  /// @returns False on success. On failure, ErrorMsg is updated with
+  ///          descriptive text of the encountered error.
+  virtual bool loadData(uint64_t Address, const void *Data, size_t Size);
+
+  /// Load code into the target address space and prepare it for execution.
+  ///
+  /// @param      Address   Destination address in the target process.
+  /// @param      Data      Source address in the host process.
+  /// @param      Size      Number of bytes to copy.
+  ///
+  /// @returns False on success. On failure, ErrorMsg is updated with
+  ///          descriptive text of the encountered error.
+  virtual bool loadCode(uint64_t Address, const void *Data, size_t Size);
+
+  /// Execute code in the target process. The called function is required
+  /// to be of signature int "(*)(void)".
+  ///
+  /// @param      Address   Address of the loaded function in the target
+  ///                       process.
+  /// @param[out] RetVal    The integer return value of the called function.
+  ///
+  /// @returns False on success. On failure, ErrorMsg is updated with
+  ///          descriptive text of the encountered error.
+  virtual bool executeCode(uint64_t Address, int &RetVal);
+
+  /// Minimum alignment for memory permissions. Used to seperate code and
+  /// data regions to make sure data doesn't get marked as code or vice
+  /// versa.
+  ///
+  /// @returns Page alignment return value. Default of 4k.
+  virtual unsigned getPageAlignment() { return 4096; }
+
+  /// Start the remote process.
+  virtual void create();
+
+  /// Terminate the remote process.
+  virtual void stop();
+
+  RemoteTargetExternal(std::string &Name) : RemoteTarget(), ChildName(Name) {}
+  virtual ~RemoteTargetExternal() {}
+
+private:
+  std::string ChildName;
+
+  // This will get filled in as a point to an OS-specific structure.
+  void *ConnectionData;
+
+  void SendAllocateSpace(uint32_t Alignment, uint32_t Size);
+  void SendLoadSection(uint64_t Addr,
+                       const void *Data,
+                       uint32_t Size,
+                       bool IsCode);
+  void SendExecute(uint64_t Addr);
+  void SendTerminate();
+
+  void Receive(LLIMessageType Msg);
+  void Receive(LLIMessageType Msg, int &Data);
+  void Receive(LLIMessageType Msg, uint64_t &Data);
+
+  int WriteBytes(const void *Data, size_t Size);
+  int ReadBytes(void *Data, size_t Size);
+  void Wait();
+};
+
+} // end namespace llvm
+
+#endif // LLI_REMOTETARGETEXTERNAL_H

Added: llvm/trunk/tools/lli/RemoteTargetMessage.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTargetMessage.h?rev=191843&view=auto
==============================================================================
--- llvm/trunk/tools/lli/RemoteTargetMessage.h (added)
+++ llvm/trunk/tools/lli/RemoteTargetMessage.h Wed Oct  2 12:12:36 2013
@@ -0,0 +1,45 @@
+//===---- RemoteTargetMessage.h - LLI out-of-process message protocol -----===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Definition of the LLIMessageType enum which is used for communication with a
+// child process for remote execution.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLI_REMOTETARGETMESSAGE_H
+#define LLI_REMOTETARGETMESSAGE_H
+
+namespace llvm {
+
+// LLI messages from parent-to-child or vice versa follow an exceedingly simple
+// protocol where the first four bytes represent the message type, the next
+// four bytes represent the size of data for the command and following bytes
+// represent the actual data.
+//
+// The protocol is not intended to be robust, secure or fault-tolerant.  It is
+// only here for testing purposes and is therefore intended to be the simplest
+// implementation that will work.  It is assumed that the parent and child
+// share characteristics like endianness.
+
+enum LLIMessageType {
+  LLI_Error = -1,
+  LLI_ChildActive = 0,        // Data = not used
+  LLI_AllocateSpace,          // Data = struct { uint_32t Align, uint_32t Size }
+  LLI_AllocationResult,       // Data = uint64_t AllocAddress (in Child memory space)
+  LLI_LoadCodeSection,        // Data = uint32_t Addr, followed by section contests
+  LLI_LoadDataSection,        // Data = uint32_t Addr, followed by section contents
+  LLI_LoadComplete,           // Data = not used
+  LLI_Execute,                // Data = Address of function to execute
+  LLI_ExecutionResult,        // Data = uint64_t Result
+  LLI_Terminate               // Data = not used
+};
+
+} // end namespace llvm
+
+#endif

Added: llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc?rev=191843&view=auto
==============================================================================
--- llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc (added)
+++ llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc Wed Oct  2 12:12:36 2013
@@ -0,0 +1,91 @@
+//=- 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 <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+
+namespace {
+
+struct ConnectionData_t {
+  int InputPipe;
+  int OutputPipe;
+
+  ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {}
+};
+
+} // namespace
+
+namespace llvm {
+
+void RemoteTargetExternal::create() {
+  int PipeFD[2][2];
+  pid_t ChildPID;
+
+  pipe(PipeFD[0]);
+  pipe(PipeFD[1]);
+
+  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]);
+
+    Receive(LLI_ChildActive);
+  }
+}
+
+int RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) {
+  return write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size);
+}
+
+int RemoteTargetExternal::ReadBytes(void *Data, size_t Size) {
+  return read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size);
+}
+
+void RemoteTargetExternal::Wait() {
+  wait(NULL);
+}
+
+} // namespace llvm
\ No newline at end of file

Added: llvm/trunk/tools/lli/Windows/RemoteTargetExternal.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/Windows/RemoteTargetExternal.inc?rev=191843&view=auto
==============================================================================
--- llvm/trunk/tools/lli/Windows/RemoteTargetExternal.inc (added)
+++ llvm/trunk/tools/lli/Windows/RemoteTargetExternal.inc Wed Oct  2 12:12:36 2013
@@ -0,0 +1,32 @@
+//= 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 {
+
+void RemoteTargetExternal::create() {
+}
+
+int RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) {
+  return 0;
+}
+
+int RemoteTargetExternal::ReadBytes(void *Data, size_t Size) {
+  return 0;
+}
+
+void RemoteTargetExternal::Wait() {
+}
+
+} // namespace llvm

Modified: llvm/trunk/tools/lli/lli.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/lli.cpp?rev=191843&r1=191842&r2=191843&view=diff
==============================================================================
--- llvm/trunk/tools/lli/lli.cpp (original)
+++ llvm/trunk/tools/lli/lli.cpp Wed Oct  2 12:12:36 2013
@@ -41,6 +41,7 @@
 #include "llvm/Support/PluginLoader.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Process.h"
+#include "llvm/Support/Program.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/TargetSelect.h"
@@ -83,6 +84,18 @@ namespace {
     cl::desc("Execute MCJIT'ed code in a separate process."),
     cl::init(false));
 
+  // Manually specify the child process for remote execution. This overrides
+  // the simulated remote execution that allocates address space for child
+  // execution. The child process resides in the disk and communicates with lli
+  // via stdin/stdout pipes.
+  cl::opt<std::string>
+  MCJITRemoteProcess("mcjit-remote-process",
+            cl::desc("Specify the filename of the process to launch "
+                     "for remote MCJIT execution.  If none is specified,"
+                     "\n\tremote execution will be simulated in-process."),
+            cl::value_desc("filename"),
+            cl::init(""));
+
   // Determine optimization level.
   cl::opt<char>
   OptLevel("O",
@@ -481,30 +494,50 @@ int main(int argc, char **argv, char * c
     // Everything is prepared now, so lay out our program for the target
     // address space, assign the section addresses to resolve any relocations,
     // and send it to the target.
-    RemoteTarget Target;
-    Target.create();
+
+    OwningPtr<RemoteTarget> Target;
+    if (!MCJITRemoteProcess.empty()) { // Remote execution on a child process
+      if (!RemoteTarget::hostSupportsExternalRemoteTarget()) {
+        errs() << "Warning: host does not support external remote targets.\n"
+               << "  Defaulting to simulated remote execution\n";
+        Target.reset(RemoteTarget::createRemoteTarget());
+      } else {
+        std::string ChildEXE = sys::FindProgramByName(MCJITRemoteProcess);
+        if (ChildEXE == "") {
+          errs() << "Unable to find child target: '\''" << MCJITRemoteProcess << "\'\n";
+          return -1;
+        }
+        Target.reset(RemoteTarget::createExternalRemoteTarget(MCJITRemoteProcess));
+      }
+    } else {
+      // No child process name provided, use simulated remote execution.
+      Target.reset(RemoteTarget::createRemoteTarget());
+    }
+
+    // Create the remote target
+    Target->create();
 
     // Trigger compilation.
     EE->generateCodeForModule(Mod);
 
     // Layout the target memory.
-    layoutRemoteTargetMemory(&Target, MM);
+    layoutRemoteTargetMemory(Target.get(), MM);
 
     // Since we're executing in a (at least simulated) remote address space,
     // we can't use the ExecutionEngine::runFunctionAsMain(). We have to
     // grab the function address directly here and tell the remote target
     // to execute the function.
     // FIXME: argv and envp handling.
-    uint64_t Entry = (uint64_t)EE->getPointerToFunction(EntryFn);
+    uint64_t Entry = EE->getFunctionAddress(EntryFn->getName().str());
 
     DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
                  << format("%llx", Entry) << "\n");
 
-    if (Target.executeCode(Entry, Result))
-      errs() << "ERROR: " << Target.getErrorMsg() << "\n";
+    if (Target->executeCode(Entry, Result))
+      errs() << "ERROR: " << Target->getErrorMsg() << "\n";
 
-    Target.stop();
-  } else {
+    Target->stop();
+  } else { // !RemoteMCJIT
     // Trigger compilation separately so code regions that need to be 
     // invalidated will be known.
     (void)EE->getPointerToFunction(EntryFn);





More information about the llvm-commits mailing list