<div dir="ltr">I don't think lli should be rolling it's own process creation and pipe code. Have you looked at Support/Program.h? It will use the preferred posix_spawn() call on Mac, and other things that you would otherwise forget.<div>
<br></div><div>If the "redirects" interface isn't good enough, feel free to augment it.</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Oct 2, 2013 at 1:12 PM, Andrew Kaylor <span dir="ltr"><<a href="mailto:andrew.kaylor@intel.com" target="_blank">andrew.kaylor@intel.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: akaylor<br>
Date: Wed Oct 2 12:12:36 2013<br>
New Revision: 191843<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=191843&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=191843&view=rev</a><br>
Log:<br>
Adding out-of-process execution support to lli.<br>
<br>
At this time only Unix-based systems are supported. Windows has stubs and should re-route to the simulated mode.<br>
<br>
Thanks to Sriram Murali for contributions to this patch.<br>
<br>
<br>
<br>
Added:<br>
llvm/trunk/tools/lli/ChildTarget/<br>
llvm/trunk/tools/lli/ChildTarget/CMakeLists.txt<br>
llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp<br>
llvm/trunk/tools/lli/ChildTarget/Makefile<br>
llvm/trunk/tools/lli/ChildTarget/Unix/<br>
llvm/trunk/tools/lli/ChildTarget/Unix/ChildTarget.inc<br>
llvm/trunk/tools/lli/ChildTarget/Windows/<br>
llvm/trunk/tools/lli/ChildTarget/Windows/ChildTarget.inc<br>
llvm/trunk/tools/lli/RemoteTargetExternal.cpp<br>
llvm/trunk/tools/lli/RemoteTargetExternal.h<br>
llvm/trunk/tools/lli/RemoteTargetMessage.h<br>
llvm/trunk/tools/lli/Unix/<br>
llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc<br>
llvm/trunk/tools/lli/Windows/<br>
llvm/trunk/tools/lli/Windows/RemoteTargetExternal.inc<br>
Modified:<br>
llvm/trunk/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll<br>
llvm/trunk/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll<br>
llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-common-symbols-remote.ll<br>
llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-data-align-remote.ll<br>
llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll<br>
llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-remote.ll<br>
llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-remote.ll<br>
llvm/trunk/tools/lli/CMakeLists.txt<br>
llvm/trunk/tools/lli/Makefile<br>
llvm/trunk/tools/lli/RemoteTarget.cpp<br>
llvm/trunk/tools/lli/RemoteTarget.h<br>
llvm/trunk/tools/lli/lli.cpp<br>
<br>
Modified: llvm/trunk/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll?rev=191843&r1=191842&r2=191843&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll?rev=191843&r1=191842&r2=191843&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll (original)<br>
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll Wed Oct 2 12:12:36 2013<br>
@@ -1,4 +1,4 @@<br>
-; RUN: %lli_mcjit -remote-mcjit %s > /dev/null<br>
+; RUN: %lli_mcjit -remote-mcjit -mcjit-remote-process=lli-child-target %s > /dev/null<br>
; XFAIL: mips<br>
<br>
define i32 @bar() {<br>
<br>
Modified: llvm/trunk/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll?rev=191843&r1=191842&r2=191843&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll?rev=191843&r1=191842&r2=191843&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll (original)<br>
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll Wed Oct 2 12:12:36 2013<br>
@@ -1,4 +1,4 @@<br>
-; RUN: %lli_mcjit -remote-mcjit -disable-lazy-compilation=false %s<br>
+; RUN: %lli_mcjit -remote-mcjit -disable-lazy-compilation=false -mcjit-remote-process=lli-child-target %s<br>
; XFAIL: mips<br>
<br>
define i32 @main() nounwind {<br>
<br>
Modified: llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-common-symbols-remote.ll<br>
URL: <a href="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" target="_blank">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</a><br>
==============================================================================<br>
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-common-symbols-remote.ll (original)<br>
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-common-symbols-remote.ll Wed Oct 2 12:12:36 2013<br>
@@ -1,4 +1,4 @@<br>
-; RUN: %lli_mcjit -remote-mcjit -O0 -disable-lazy-compilation=false %s<br>
+; RUN: %lli_mcjit -remote-mcjit -O0 -disable-lazy-compilation=false -mcjit-remote-process=lli-child-target %s<br>
; XFAIL: mips<br>
<br>
; The intention of this test is to verify that symbols mapped to COMMON in ELF<br>
<br>
Modified: llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-data-align-remote.ll<br>
URL: <a href="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" target="_blank">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</a><br>
==============================================================================<br>
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-data-align-remote.ll (original)<br>
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-data-align-remote.ll Wed Oct 2 12:12:36 2013<br>
@@ -1,4 +1,4 @@<br>
-; RUN: %lli_mcjit -remote-mcjit -O0 %s<br>
+; RUN: %lli_mcjit -remote-mcjit -O0 -mcjit-remote-process=lli-child-target %s<br>
; XFAIL: mips<br>
<br>
; Check that a variable is always aligned as specified.<br>
<br>
Modified: llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll<br>
URL: <a href="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" target="_blank">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</a><br>
==============================================================================<br>
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll (original)<br>
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll Wed Oct 2 12:12:36 2013<br>
@@ -1,4 +1,4 @@<br>
-; RUN: %lli_mcjit -remote-mcjit %s > /dev/null<br>
+; RUN: %lli_mcjit -remote-mcjit -mcjit-remote-process=lli-child-target %s > /dev/null<br>
; XFAIL: mips<br>
<br>
define double @test(double* %DP, double %Arg) {<br>
<br>
Modified: llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-remote.ll<br>
URL: <a href="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" target="_blank">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</a><br>
==============================================================================<br>
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-remote.ll (original)<br>
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-remote.ll Wed Oct 2 12:12:36 2013<br>
@@ -1,4 +1,4 @@<br>
-; RUN: %lli_mcjit -remote-mcjit %s > /dev/null<br>
+; RUN: %lli_mcjit -remote-mcjit -mcjit-remote-process=lli-child-target %s > /dev/null<br>
; XFAIL: mips<br>
<br>
@count = global i32 1, align 4<br>
<br>
Modified: llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-remote.ll<br>
URL: <a href="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" target="_blank">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</a><br>
==============================================================================<br>
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-remote.ll (original)<br>
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-remote.ll Wed Oct 2 12:12:36 2013<br>
@@ -1,4 +1,4 @@<br>
-; RUN: %lli_mcjit -remote-mcjit -O0 %s<br>
+; RUN: %lli_mcjit -remote-mcjit -O0 -mcjit-remote-process=lli-child-target %s<br>
<br>
@.str = private unnamed_addr constant [6 x i8] c"data1\00", align 1<br>
@ptr = global i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0), align 4<br>
<br>
Modified: llvm/trunk/tools/lli/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/CMakeLists.txt?rev=191843&r1=191842&r2=191843&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/CMakeLists.txt?rev=191843&r1=191842&r2=191843&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/CMakeLists.txt (original)<br>
+++ llvm/trunk/tools/lli/CMakeLists.txt Wed Oct 2 12:12:36 2013<br>
@@ -1,6 +1,8 @@<br>
<br>
set(LLVM_LINK_COMPONENTS mcjit jit interpreter nativecodegen bitreader asmparser irreader selectiondag native instrumentation)<br>
<br>
+add_subdirectory(ChildTarget)<br>
+<br>
if( LLVM_USE_OPROFILE )<br>
set(LLVM_LINK_COMPONENTS<br>
${LLVM_LINK_COMPONENTS}<br>
@@ -21,4 +23,5 @@ add_llvm_tool(lli<br>
lli.cpp<br>
RecordingMemoryManager.cpp<br>
RemoteTarget.cpp<br>
+ RemoteTargetExternal.cpp<br>
)<br>
<br>
Added: llvm/trunk/tools/lli/ChildTarget/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/CMakeLists.txt?rev=191843&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/CMakeLists.txt?rev=191843&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/ChildTarget/CMakeLists.txt (added)<br>
+++ llvm/trunk/tools/lli/ChildTarget/CMakeLists.txt Wed Oct 2 12:12:36 2013<br>
@@ -0,0 +1,3 @@<br>
+add_llvm_tool(lli-child-target<br>
+ ChildTarget.cpp<br>
+ )<br>
<br>
Added: llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp?rev=191843&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp?rev=191843&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp (added)<br>
+++ llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp Wed Oct 2 12:12:36 2013<br>
@@ -0,0 +1,241 @@<br>
+#include "llvm/Config/config.h"<br>
+<br>
+#include "../RemoteTargetMessage.h"<br>
+#include <assert.h><br>
+#include <map><br>
+#include <stdint.h><br>
+#include <string><br>
+#include <vector><br>
+<br>
+using namespace llvm;<br>
+<br>
+class LLIChildTarget {<br>
+public:<br>
+ void initialize();<br>
+ LLIMessageType waitForIncomingMessage();<br>
+ void handleMessage(LLIMessageType messageType);<br>
+<br>
+private:<br>
+ // Incoming message handlers<br>
+ void handleAllocateSpace();<br>
+ void handleLoadSection(bool IsCode);<br>
+ void handleExecute();<br>
+ void handleTerminate();<br>
+<br>
+ // Outgoing message handlers<br>
+ void sendChildActive();<br>
+ void sendAllocationResult(uint64_t Addr);<br>
+ void sendLoadComplete();<br>
+ void sendExecutionComplete(uint64_t Result);<br>
+<br>
+ // OS-specific functions<br>
+ void initializeConnection();<br>
+ int WriteBytes(const void *Data, size_t Size);<br>
+ int ReadBytes(void *Data, size_t Size);<br>
+ uint64_t allocate(uint32_t Alignment, uint32_t Size);<br>
+ void makeSectionExecutable(uint64_t Addr, uint32_t Size);<br>
+ void InvalidateInstructionCache(const void *Addr, size_t Len);<br>
+ void releaseMemory(uint64_t Addr, uint32_t Size);<br>
+<br>
+ // Store a map of allocated buffers to sizes.<br>
+ typedef std::map<uint64_t, uint32_t> AllocMapType;<br>
+ AllocMapType m_AllocatedBufferMap;<br>
+<br>
+ // Communication handles (OS-specific)<br>
+ void *ConnectionData;<br>
+};<br>
+<br>
+int main() {<br>
+ LLIChildTarget ThisChild;<br>
+ ThisChild.initialize();<br>
+ LLIMessageType MsgType;<br>
+ do {<br>
+ MsgType = ThisChild.waitForIncomingMessage();<br>
+ ThisChild.handleMessage(MsgType);<br>
+ } while (MsgType != LLI_Terminate &&<br>
+ MsgType != LLI_Error);<br>
+ return 0;<br>
+}<br>
+<br>
+// Public methods<br>
+void LLIChildTarget::initialize() {<br>
+ initializeConnection();<br>
+ sendChildActive();<br>
+}<br>
+<br>
+LLIMessageType LLIChildTarget::waitForIncomingMessage() {<br>
+ int32_t MsgType = -1;<br>
+ if (ReadBytes(&MsgType, 4) > 0)<br>
+ return (LLIMessageType)MsgType;<br>
+ return LLI_Error;<br>
+}<br>
+<br>
+void LLIChildTarget::handleMessage(LLIMessageType messageType) {<br>
+ switch (messageType) {<br>
+ case LLI_AllocateSpace:<br>
+ handleAllocateSpace();<br>
+ break;<br>
+ case LLI_LoadCodeSection:<br>
+ handleLoadSection(true);<br>
+ break;<br>
+ case LLI_LoadDataSection:<br>
+ handleLoadSection(false);<br>
+ break;<br>
+ case LLI_Execute:<br>
+ handleExecute();<br>
+ break;<br>
+ case LLI_Terminate:<br>
+ handleTerminate();<br>
+ break;<br>
+ default:<br>
+ // FIXME: Handle error!<br>
+ break;<br>
+ }<br>
+}<br>
+<br>
+// Incoming message handlers<br>
+void LLIChildTarget::handleAllocateSpace() {<br>
+ // Read and verify the message data size.<br>
+ uint32_t DataSize;<br>
+ int rc = ReadBytes(&DataSize, 4);<br>
+ assert(rc == 4);<br>
+ assert(DataSize == 8);<br>
+<br>
+ // Read the message arguments.<br>
+ uint32_t Alignment;<br>
+ uint32_t AllocSize;<br>
+ rc = ReadBytes(&Alignment, 4);<br>
+ assert(rc == 4);<br>
+ rc = ReadBytes(&AllocSize, 4);<br>
+ assert(rc == 4);<br>
+<br>
+ // Allocate the memory.<br>
+ uint64_t Addr = allocate(Alignment, AllocSize);<br>
+<br>
+ // Send AllocationResult message.<br>
+ sendAllocationResult(Addr);<br>
+}<br>
+<br>
+void LLIChildTarget::handleLoadSection(bool IsCode) {<br>
+ // Read the message data size.<br>
+ uint32_t DataSize;<br>
+ int rc = ReadBytes(&DataSize, 4);<br>
+ assert(rc == 4);<br>
+<br>
+ // Read the target load address.<br>
+ uint64_t Addr;<br>
+ rc = ReadBytes(&Addr, 8);<br>
+ assert(rc == 8);<br>
+<br>
+ size_t BufferSize = DataSize - 8;<br>
+<br>
+ // FIXME: Verify that this is in allocated space<br>
+<br>
+ // Read section data into previously allocated buffer<br>
+ rc = ReadBytes((void*)Addr, DataSize - 8);<br>
+ assert(rc == (int)(BufferSize));<br>
+<br>
+ // If IsCode, mark memory executable<br>
+ if (IsCode)<br>
+ makeSectionExecutable(Addr, BufferSize);<br>
+<br>
+ // Send MarkLoadComplete message.<br>
+ sendLoadComplete();<br>
+}<br>
+<br>
+void LLIChildTarget::handleExecute() {<br>
+ // Read the message data size.<br>
+ uint32_t DataSize;<br>
+ int rc = ReadBytes(&DataSize, 4);<br>
+ assert(rc == 4);<br>
+ assert(DataSize == 8);<br>
+<br>
+ // Read the target address.<br>
+ uint64_t Addr;<br>
+ rc = ReadBytes(&Addr, 8);<br>
+ assert(rc == 8);<br>
+<br>
+ // Call function<br>
+ int Result;<br>
+ int (*fn)(void) = (int(*)(void))Addr;<br>
+ Result = fn();<br>
+<br>
+ // Send ExecutionResult message.<br>
+ sendExecutionComplete((int64_t)Result);<br>
+}<br>
+<br>
+void LLIChildTarget::handleTerminate() {<br>
+ // Release all allocated memory<br>
+ AllocMapType::iterator Begin = m_AllocatedBufferMap.begin();<br>
+ AllocMapType::iterator End = m_AllocatedBufferMap.end();<br>
+ for (AllocMapType::iterator It = Begin; It != End; ++It) {<br>
+ releaseMemory(It->first, It->second);<br>
+ }<br>
+ m_AllocatedBufferMap.clear();<br>
+}<br>
+<br>
+// Outgoing message handlers<br>
+void LLIChildTarget::sendChildActive() {<br>
+ // Write the message type.<br>
+ uint32_t MsgType = (uint32_t)LLI_ChildActive;<br>
+ int rc = WriteBytes(&MsgType, 4);<br>
+ assert(rc == 4);<br>
+<br>
+ // Write the data size.<br>
+ uint32_t DataSize = 0;<br>
+ rc = WriteBytes(&DataSize, 4);<br>
+ assert(rc == 4);<br>
+}<br>
+<br>
+void LLIChildTarget::sendAllocationResult(uint64_t Addr) {<br>
+ // Write the message type.<br>
+ uint32_t MsgType = (uint32_t)LLI_AllocationResult;<br>
+ int rc = WriteBytes(&MsgType, 4);<br>
+ assert(rc == 4);<br>
+<br>
+ // Write the data size.<br>
+ uint32_t DataSize = 8;<br>
+ rc = WriteBytes(&DataSize, 4);<br>
+ assert(rc == 4);<br>
+<br>
+ // Write the allocated address.<br>
+ rc = WriteBytes(&Addr, 8);<br>
+ assert(rc == 8);<br>
+}<br>
+<br>
+void LLIChildTarget::sendLoadComplete() {<br>
+ // Write the message type.<br>
+ uint32_t MsgType = (uint32_t)LLI_LoadComplete;<br>
+ int rc = WriteBytes(&MsgType, 4);<br>
+ assert(rc == 4);<br>
+<br>
+ // Write the data size.<br>
+ uint32_t DataSize = 0;<br>
+ rc = WriteBytes(&DataSize, 4);<br>
+ assert(rc == 4);<br>
+}<br>
+<br>
+void LLIChildTarget::sendExecutionComplete(uint64_t Result) {<br>
+ // Write the message type.<br>
+ uint32_t MsgType = (uint32_t)LLI_ExecutionResult;<br>
+ int rc = WriteBytes(&MsgType, 4);<br>
+ assert(rc == 4);<br>
+<br>
+<br>
+ // Write the data size.<br>
+ uint32_t DataSize = 8;<br>
+ rc = WriteBytes(&DataSize, 4);<br>
+ assert(rc == 4);<br>
+<br>
+ // Write the result.<br>
+ rc = WriteBytes(&Result, 8);<br>
+ assert(rc == 8);<br>
+}<br>
+<br>
+#ifdef LLVM_ON_UNIX<br>
+#include "Unix/ChildTarget.inc"<br>
+#endif<br>
+<br>
+#ifdef LLVM_ON_WIN32<br>
+#include "Windows/ChildTarget.inc"<br>
+#endif<br>
<br>
Added: llvm/trunk/tools/lli/ChildTarget/Makefile<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/Makefile?rev=191843&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/Makefile?rev=191843&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/ChildTarget/Makefile (added)<br>
+++ llvm/trunk/tools/lli/ChildTarget/Makefile Wed Oct 2 12:12:36 2013<br>
@@ -0,0 +1,17 @@<br>
+##===- tools/lli/Makefile ------------------------------*- Makefile -*-===##<br>
+#<br>
+# The LLVM Compiler Infrastructure<br>
+#<br>
+# This file is distributed under the University of Illinois Open Source<br>
+# License. See LICENSE.TXT for details.<br>
+#<br>
+##===----------------------------------------------------------------------===##<br>
+<br>
+LEVEL := ../../..<br>
+TOOLNAME := lli-child-target<br>
+<br>
+include $(LEVEL)/Makefile.config<br>
+<br>
+LINK_COMPONENTS :=<br>
+<br>
+include $(LLVM_SRC_ROOT)/Makefile.rules<br>
<br>
Added: llvm/trunk/tools/lli/ChildTarget/Unix/ChildTarget.inc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/Unix/ChildTarget.inc?rev=191843&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/Unix/ChildTarget.inc?rev=191843&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/ChildTarget/Unix/ChildTarget.inc (added)<br>
+++ llvm/trunk/tools/lli/ChildTarget/Unix/ChildTarget.inc Wed Oct 2 12:12:36 2013<br>
@@ -0,0 +1,141 @@<br>
+//===- ChildTarget.inc - Child process for external JIT execution for Unix -==//<br>
+//<br>
+// The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// Implementation of the Unix-specific parts of the ChildTarget class<br>
+// which executes JITed code in a separate process from where it was built.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include <unistd.h><br>
+#include <stdio.h><br>
+#include <stdlib.h><br>
+#include <sys/mman.h><br>
+<br>
+namespace {<br>
+<br>
+struct ConnectionData_t {<br>
+ int InputPipe;<br>
+ int OutputPipe;<br>
+<br>
+ ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {}<br>
+};<br>
+<br>
+} // namespace<br>
+<br>
+// OS-specific methods<br>
+void LLIChildTarget::initializeConnection() {<br>
+ // Store the parent ends of the pipes<br>
+ ConnectionData = (void*)new ConnectionData_t(STDIN_FILENO, STDOUT_FILENO);<br>
+}<br>
+<br>
+int LLIChildTarget::WriteBytes(const void *Data, size_t Size) {<br>
+ return write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size);<br>
+}<br>
+<br>
+int LLIChildTarget::ReadBytes(void *Data, size_t Size) {<br>
+ return read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size);<br>
+}<br>
+<br>
+// The functions below duplicate functionality that is implemented in<br>
+// Support/Memory.cpp with the goal of avoiding a dependency on any<br>
+// llvm libraries.<br>
+<br>
+uint64_t LLIChildTarget::allocate(uint32_t Alignment, uint32_t Size) {<br>
+ if (!Alignment)<br>
+ Alignment = 16;<br>
+<br>
+ static const size_t PageSize = getpagesize();<br>
+ const size_t NumPages = (Size+PageSize-1)/PageSize;<br>
+ Size = NumPages*PageSize;<br>
+<br>
+ int fd = -1;<br>
+#ifdef NEED_DEV_ZERO_FOR_MMAP<br>
+ static int zero_fd = open("/dev/zero", O_RDWR);<br>
+ if (zero_fd == -1)<br>
+ return 0;<br>
+ fd = zero_fd;<br>
+#endif<br>
+<br>
+ int MMFlags = MAP_PRIVATE |<br>
+#ifdef HAVE_MMAP_ANONYMOUS<br>
+ MAP_ANONYMOUS<br>
+#else<br>
+ MAP_ANON<br>
+#endif<br>
+ ; // Ends statement above<br>
+<br>
+ uint64_t Addr = (uint64_t)::mmap(0, Size, PROT_READ | PROT_WRITE, MMFlags, fd, 0);<br>
+ if (Addr == (uint64_t)MAP_FAILED)<br>
+ return 0;<br>
+<br>
+ // Align the address.<br>
+ Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);<br>
+<br>
+ m_AllocatedBufferMap[Addr] = Size;<br>
+<br>
+ // Return aligned address<br>
+ return Addr;<br>
+}<br>
+<br>
+void LLIChildTarget::makeSectionExecutable(uint64_t Addr, uint32_t Size) {<br>
+ // FIXME: We have to mark the memory as RWX because multiple code chunks may<br>
+ // be on the same page. The RemoteTarget interface should be changed to<br>
+ // work around that.<br>
+ int Result = ::mprotect((void*)Addr, Size, PROT_READ | PROT_WRITE | PROT_EXEC);<br>
+ if (Result != 0)<br>
+ InvalidateInstructionCache((const void *)Addr, Size);<br>
+}<br>
+<br>
+/// InvalidateInstructionCache - Before the JIT can run a block of code<br>
+/// that has been emitted it must invalidate the instruction cache on some<br>
+/// platforms.<br>
+void LLIChildTarget::InvalidateInstructionCache(const void *Addr,<br>
+ size_t Len) {<br>
+<br>
+// icache invalidation for PPC and ARM.<br>
+#if defined(__APPLE__)<br>
+<br>
+# if (defined(__POWERPC__) || defined (__ppc__) || \<br>
+ defined(_POWER) || defined(_ARCH_PPC)) || defined(__arm__)<br>
+ sys_icache_invalidate(const_cast<void *>(Addr), Len);<br>
+# endif<br>
+<br>
+#else<br>
+<br>
+# if (defined(__POWERPC__) || defined (__ppc__) || \<br>
+ defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__)<br>
+ const size_t LineSize = 32;<br>
+<br>
+ const intptr_t Mask = ~(LineSize - 1);<br>
+ const intptr_t StartLine = ((intptr_t) Addr) & Mask;<br>
+ const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask;<br>
+<br>
+ for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)<br>
+ asm volatile("dcbf 0, %0" : : "r"(Line));<br>
+ asm volatile("sync");<br>
+<br>
+ for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)<br>
+ asm volatile("icbi 0, %0" : : "r"(Line));<br>
+ asm volatile("isync");<br>
+# elif defined(__arm__) && defined(__GNUC__)<br>
+ // FIXME: Can we safely always call this for __GNUC__ everywhere?<br>
+ const char *Start = static_cast<const char *>(Addr);<br>
+ const char *End = Start + Len;<br>
+ __clear_cache(const_cast<char *>(Start), const_cast<char *>(End));<br>
+# elif defined(__mips__)<br>
+ const char *Start = static_cast<const char *>(Addr);<br>
+ cacheflush(const_cast<char *>(Start), Len, BCACHE);<br>
+# endif<br>
+<br>
+#endif // end apple<br>
+}<br>
+<br>
+void LLIChildTarget::releaseMemory(uint64_t Addr, uint32_t Size) {<br>
+ ::munmap((void*)Addr, Size);<br>
+}<br>
<br>
Added: llvm/trunk/tools/lli/ChildTarget/Windows/ChildTarget.inc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/Windows/ChildTarget.inc?rev=191843&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/Windows/ChildTarget.inc?rev=191843&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/ChildTarget/Windows/ChildTarget.inc (added)<br>
+++ llvm/trunk/tools/lli/ChildTarget/Windows/ChildTarget.inc Wed Oct 2 12:12:36 2013<br>
@@ -0,0 +1,41 @@<br>
+//=- ChildTarget.inc - Child process for external JIT execution for Windows -=//<br>
+//<br>
+// The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// Non-implementation of the Windows-specific parts of the ChildTarget class<br>
+// which executes JITed code in a separate process from where it was built.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+// The RemoteTargetExternal implementation should prevent us from ever getting<br>
+// here on Windows, but nothing prevents a user from running this directly.<br>
+void LLIChildTarget::initializeConnection() {<br>
+ assert(0 && "lli-child-target is not implemented for Windows");<br>
+}<br>
+<br>
+int LLIChildTarget::WriteBytes(const void *Data, size_t Size) {<br>
+ return 0;<br>
+}<br>
+<br>
+int LLIChildTarget::ReadBytes(void *Data, size_t Size) {<br>
+ return 0;<br>
+}<br>
+<br>
+uint64_t LLIChildTarget::allocate(uint32_t Alignment, uint32_t Size) {<br>
+ return 0;<br>
+}<br>
+<br>
+void LLIChildTarget::makeSectionExecutable(uint64_t Addr, uint32_t Size) {<br>
+}<br>
+<br>
+void LLIChildTarget::InvalidateInstructionCache(const void *Addr,<br>
+ size_t Len) {<br>
+}<br>
+<br>
+void LLIChildTarget::releaseMemory(uint64_t Addr, uint32_t Size) {<br>
+}<br>
<br>
Modified: llvm/trunk/tools/lli/Makefile<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/Makefile?rev=191843&r1=191842&r2=191843&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/Makefile?rev=191843&r1=191842&r2=191843&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/Makefile (original)<br>
+++ llvm/trunk/tools/lli/Makefile Wed Oct 2 12:12:36 2013<br>
@@ -10,6 +10,8 @@<br>
LEVEL := ../..<br>
TOOLNAME := lli<br>
<br>
+PARALLEL_DIRS := ChildTarget<br>
+<br>
include $(LEVEL)/Makefile.config<br>
<br>
LINK_COMPONENTS := mcjit jit instrumentation interpreter nativecodegen bitreader asmparser irreader selectiondag native<br>
<br>
Modified: llvm/trunk/tools/lli/RemoteTarget.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTarget.cpp?rev=191843&r1=191842&r2=191843&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTarget.cpp?rev=191843&r1=191842&r2=191843&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/RemoteTarget.cpp (original)<br>
+++ llvm/trunk/tools/lli/RemoteTarget.cpp Wed Oct 2 12:12:36 2013<br>
@@ -13,13 +13,44 @@<br>
//===----------------------------------------------------------------------===//<br>
<br>
#include "RemoteTarget.h"<br>
+#include "RemoteTargetExternal.h"<br>
#include "llvm/ADT/StringRef.h"<br>
#include "llvm/Support/DataTypes.h"<br>
#include "llvm/Support/Memory.h"<br>
#include <stdlib.h><br>
#include <string><br>
+<br>
using namespace llvm;<br>
<br>
+// Static methods<br>
+RemoteTarget *RemoteTarget::createRemoteTarget() {<br>
+ return new RemoteTarget;<br>
+}<br>
+<br>
+RemoteTarget *RemoteTarget::createExternalRemoteTarget(std::string &ChildName) {<br>
+#ifdef LLVM_ON_UNIX<br>
+ return new RemoteTargetExternal(ChildName);<br>
+#else<br>
+ return 0;<br>
+#endif<br>
+}<br>
+<br>
+bool RemoteTarget::hostSupportsExternalRemoteTarget() {<br>
+#ifdef LLVM_ON_UNIX<br>
+ return true;<br>
+#else<br>
+ return false;<br>
+#endif<br>
+}<br>
+<br>
+<br>
+////////////////////////////////////////////////////////////////////////////////<br>
+// Simulated remote execution<br>
+//<br>
+// This implementation will simply move generated code and data to a new memory<br>
+// location in the current executable and let it run from there.<br>
+////////////////////////////////////////////////////////////////////////////////<br>
+<br>
bool RemoteTarget::allocateSpace(size_t Size, unsigned Alignment,<br>
uint64_t &Address) {<br>
sys::MemoryBlock *Prev = Allocations.size() ? &Allocations.back() : NULL;<br>
<br>
Modified: llvm/trunk/tools/lli/RemoteTarget.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTarget.h?rev=191843&r1=191842&r2=191843&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTarget.h?rev=191843&r1=191842&r2=191843&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/RemoteTarget.h (original)<br>
+++ llvm/trunk/tools/lli/RemoteTarget.h Wed Oct 2 12:12:36 2013<br>
@@ -41,7 +41,9 @@ public:<br>
///<br>
/// @returns False on success. On failure, ErrorMsg is updated with<br>
/// descriptive text of the encountered error.<br>
- bool allocateSpace(size_t Size, unsigned Alignment, uint64_t &Address);<br>
+ virtual bool allocateSpace(size_t Size,<br>
+ unsigned Alignment,<br>
+ uint64_t &Address);<br>
<br>
/// Load data into the target address space.<br>
///<br>
@@ -51,7 +53,9 @@ public:<br>
///<br>
/// @returns False on success. On failure, ErrorMsg is updated with<br>
/// descriptive text of the encountered error.<br>
- bool loadData(uint64_t Address, const void *Data, size_t Size);<br>
+ virtual bool loadData(uint64_t Address,<br>
+ const void *Data,<br>
+ size_t Size);<br>
<br>
/// Load code into the target address space and prepare it for execution.<br>
///<br>
@@ -61,7 +65,9 @@ public:<br>
///<br>
/// @returns False on success. On failure, ErrorMsg is updated with<br>
/// descriptive text of the encountered error.<br>
- bool loadCode(uint64_t Address, const void *Data, size_t Size);<br>
+ virtual bool loadCode(uint64_t Address,<br>
+ const void *Data,<br>
+ size_t Size);<br>
<br>
/// Execute code in the target process. The called function is required<br>
/// to be of signature int "(*)(void)".<br>
@@ -72,24 +78,29 @@ public:<br>
///<br>
/// @returns False on success. On failure, ErrorMsg is updated with<br>
/// descriptive text of the encountered error.<br>
- bool executeCode(uint64_t Address, int &RetVal);<br>
+ virtual bool executeCode(uint64_t Address,<br>
+ int &RetVal);<br>
<br>
/// Minimum alignment for memory permissions. Used to seperate code and<br>
/// data regions to make sure data doesn't get marked as code or vice<br>
/// versa.<br>
///<br>
/// @returns Page alignment return value. Default of 4k.<br>
- unsigned getPageAlignment() { return 4096; }<br>
+ virtual unsigned getPageAlignment() { return 4096; }<br>
<br>
/// Start the remote process.<br>
- void create();<br>
+ virtual void create();<br>
<br>
/// Terminate the remote process.<br>
- void stop();<br>
+ virtual void stop();<br>
<br>
RemoteTarget() : ErrorMsg(""), IsRunning(false) {}<br>
- ~RemoteTarget() { if (IsRunning) stop(); }<br>
+ virtual ~RemoteTarget() { if (IsRunning) stop(); }<br>
<br>
+ // Create an instance of the system-specific remote target class.<br>
+ static RemoteTarget *createRemoteTarget();<br>
+ static RemoteTarget *createExternalRemoteTarget(std::string &ChildName);<br>
+ static bool hostSupportsExternalRemoteTarget();<br>
private:<br>
// Main processing function for the remote target process. Command messages<br>
// are received on file descriptor CmdFD and responses come back on OutFD.<br>
<br>
Added: llvm/trunk/tools/lli/RemoteTargetExternal.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTargetExternal.cpp?rev=191843&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTargetExternal.cpp?rev=191843&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/RemoteTargetExternal.cpp (added)<br>
+++ llvm/trunk/tools/lli/RemoteTargetExternal.cpp Wed Oct 2 12:12:36 2013<br>
@@ -0,0 +1,162 @@<br>
+//===---- RemoteTargetExternal.cpp - LLVM out-of-process JIT execution ----===//<br>
+//<br>
+// The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// Implementation of the RemoteTargetExternal class which executes JITed code<br>
+// in a separate process from where it was built.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "llvm/Config/config.h"<br>
+<br>
+#include "RemoteTarget.h"<br>
+#include "RemoteTargetExternal.h"<br>
+<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/Support/DataTypes.h"<br>
+#include "llvm/Support/Memory.h"<br>
+#include "llvm/Support/Program.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+#include <string><br>
+<br>
+using namespace llvm;<br>
+<br>
+bool RemoteTargetExternal::allocateSpace(size_t Size, unsigned Alignment,<br>
+ uint64_t &Address) {<br>
+ SendAllocateSpace(Alignment, Size);<br>
+ Receive(LLI_AllocationResult, Address);<br>
+ return false;<br>
+}<br>
+<br>
+bool RemoteTargetExternal::loadData(uint64_t Address, const void *Data, size_t Size) {<br>
+ SendLoadSection(Address, Data, (uint32_t)Size, false);<br>
+ Receive(LLI_LoadComplete);<br>
+ return false;<br>
+}<br>
+<br>
+bool RemoteTargetExternal::loadCode(uint64_t Address, const void *Data, size_t Size) {<br>
+ SendLoadSection(Address, Data, (uint32_t)Size, true);<br>
+ Receive(LLI_LoadComplete);<br>
+ return false;<br>
+}<br>
+<br>
+bool RemoteTargetExternal::executeCode(uint64_t Address, int &RetVal) {<br>
+ SendExecute(Address);<br>
+<br>
+ Receive(LLI_ExecutionResult, RetVal);<br>
+ return false;<br>
+}<br>
+<br>
+void RemoteTargetExternal::stop() {<br>
+ SendTerminate();<br>
+ Wait();<br>
+}<br>
+<br>
+void RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {<br>
+ int rc;<br>
+ uint32_t MsgType = (uint32_t)LLI_AllocateSpace;<br>
+ rc = WriteBytes(&MsgType, 4);<br>
+ assert(rc == 4 && "Error writing message type.");<br>
+<br>
+ uint32_t DataSize = 8;<br>
+ rc = WriteBytes(&DataSize, 4);<br>
+ assert(rc == 4 && "Error writing data size.");<br>
+<br>
+ rc = WriteBytes(&Alignment, 4);<br>
+ assert(rc == 4 && "Error writing alignment data.");<br>
+<br>
+ rc = WriteBytes(&Size, 4);<br>
+ assert(rc == 4 && "Error writing size data.");<br>
+}<br>
+<br>
+void RemoteTargetExternal::SendLoadSection(uint64_t Addr,<br>
+ const void *Data,<br>
+ uint32_t Size,<br>
+ bool IsCode) {<br>
+ int rc;<br>
+ uint32_t MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;<br>
+ rc = WriteBytes(&MsgType, 4);<br>
+ assert(rc == 4 && "Error writing message type.");<br>
+<br>
+ uint32_t DataSize = Size + 8;<br>
+ rc = WriteBytes(&DataSize, 4);<br>
+ assert(rc == 4 && "Error writing data size.");<br>
+<br>
+ rc = WriteBytes(&Addr, 8);<br>
+ assert(rc == 8 && "Error writing data.");<br>
+<br>
+ rc = WriteBytes(Data, Size);<br>
+ assert(rc == (int)Size && "Error writing data.");<br>
+}<br>
+<br>
+void RemoteTargetExternal::SendExecute(uint64_t Addr) {<br>
+ int rc;<br>
+ uint32_t MsgType = (uint32_t)LLI_Execute;<br>
+ rc = WriteBytes(&MsgType, 4);<br>
+ assert(rc == 4 && "Error writing message type.");<br>
+<br>
+ uint32_t DataSize = 8;<br>
+ rc = WriteBytes(&DataSize, 4);<br>
+ assert(rc == 4 && "Error writing data size.");<br>
+<br>
+ rc = WriteBytes(&Addr, 8);<br>
+ assert(rc == 8 && "Error writing data.");<br>
+}<br>
+<br>
+void RemoteTargetExternal::SendTerminate() {<br>
+ int rc;<br>
+ uint32_t MsgType = (uint32_t)LLI_Terminate;<br>
+ rc = WriteBytes(&MsgType, 4);<br>
+ assert(rc == 4 && "Error writing message type.");<br>
+<br>
+ // No data or data size is sent with Terminate<br>
+}<br>
+<br>
+<br>
+void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType) {<br>
+ int rc;<br>
+ uint32_t MsgType;<br>
+ rc = ReadBytes(&MsgType, 4);<br>
+ assert(rc == 4 && "Error reading message type.");<br>
+ assert(MsgType == ExpectedMsgType && "Error: received unexpected message type.");<br>
+<br>
+ uint32_t DataSize;<br>
+ rc = ReadBytes(&DataSize, 4);<br>
+ assert(rc == 4 && "Error reading data size.");<br>
+ assert(DataSize == 0 && "Error: unexpected data size.");<br>
+}<br>
+<br>
+void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, int &Data) {<br>
+ uint64_t Temp;<br>
+ Receive(ExpectedMsgType, Temp);<br>
+ Data = (int)(int64_t)Temp;<br>
+}<br>
+<br>
+void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, uint64_t &Data) {<br>
+ int rc;<br>
+ uint32_t MsgType;<br>
+ rc = ReadBytes(&MsgType, 4);<br>
+ assert(rc == 4 && "Error reading message type.");<br>
+ assert(MsgType == ExpectedMsgType && "Error: received unexpected message type.");<br>
+<br>
+ uint32_t DataSize;<br>
+ rc = ReadBytes(&DataSize, 4);<br>
+ assert(rc == 4 && "Error reading data size.");<br>
+ assert(DataSize == 8 && "Error: unexpected data size.");<br>
+<br>
+ rc = ReadBytes(&Data, 8);<br>
+ assert(DataSize == 8 && "Error: unexpected data.");<br>
+}<br>
+<br>
+#ifdef LLVM_ON_UNIX<br>
+#include "Unix/RemoteTargetExternal.inc"<br>
+#endif<br>
+<br>
+#ifdef LLVM_ON_WIN32<br>
+#include "Windows/RemoteTargetExternal.inc"<br>
+#endif<br>
<br>
Added: llvm/trunk/tools/lli/RemoteTargetExternal.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTargetExternal.h?rev=191843&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTargetExternal.h?rev=191843&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/RemoteTargetExternal.h (added)<br>
+++ llvm/trunk/tools/lli/RemoteTargetExternal.h Wed Oct 2 12:12:36 2013<br>
@@ -0,0 +1,118 @@<br>
+//===----- RemoteTargetExternal.h - LLVM out-of-process JIT execution -----===//<br>
+//<br>
+// The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// Definition of the RemoteTargetExternal class which executes JITed code in a<br>
+// separate process from where it was built.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLI_REMOTETARGETEXTERNAL_H<br>
+#define LLI_REMOTETARGETEXTERNAL_H<br>
+<br>
+#include "llvm/Config/config.h"<br>
+<br>
+#include "llvm/ADT/SmallVector.h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/Support/DataTypes.h"<br>
+#include "llvm/Support/Memory.h"<br>
+#include <stdlib.h><br>
+#include <string><br>
+<br>
+#include "RemoteTarget.h"<br>
+#include "RemoteTargetMessage.h"<br>
+<br>
+namespace llvm {<br>
+<br>
+class RemoteTargetExternal : public RemoteTarget {<br>
+public:<br>
+ /// Allocate space in the remote target address space.<br>
+ ///<br>
+ /// @param Size Amount of space, in bytes, to allocate.<br>
+ /// @param Alignment Required minimum alignment for allocated space.<br>
+ /// @param[out] Address Remote address of the allocated memory.<br>
+ ///<br>
+ /// @returns False on success. On failure, ErrorMsg is updated with<br>
+ /// descriptive text of the encountered error.<br>
+ virtual bool allocateSpace(size_t Size,<br>
+ unsigned Alignment,<br>
+ uint64_t &Address);<br>
+<br>
+ /// Load data into the target address space.<br>
+ ///<br>
+ /// @param Address Destination address in the target process.<br>
+ /// @param Data Source address in the host process.<br>
+ /// @param Size Number of bytes to copy.<br>
+ ///<br>
+ /// @returns False on success. On failure, ErrorMsg is updated with<br>
+ /// descriptive text of the encountered error.<br>
+ virtual bool loadData(uint64_t Address, const void *Data, size_t Size);<br>
+<br>
+ /// Load code into the target address space and prepare it for execution.<br>
+ ///<br>
+ /// @param Address Destination address in the target process.<br>
+ /// @param Data Source address in the host process.<br>
+ /// @param Size Number of bytes to copy.<br>
+ ///<br>
+ /// @returns False on success. On failure, ErrorMsg is updated with<br>
+ /// descriptive text of the encountered error.<br>
+ virtual bool loadCode(uint64_t Address, const void *Data, size_t Size);<br>
+<br>
+ /// Execute code in the target process. The called function is required<br>
+ /// to be of signature int "(*)(void)".<br>
+ ///<br>
+ /// @param Address Address of the loaded function in the target<br>
+ /// process.<br>
+ /// @param[out] RetVal The integer return value of the called function.<br>
+ ///<br>
+ /// @returns False on success. On failure, ErrorMsg is updated with<br>
+ /// descriptive text of the encountered error.<br>
+ virtual bool executeCode(uint64_t Address, int &RetVal);<br>
+<br>
+ /// Minimum alignment for memory permissions. Used to seperate code and<br>
+ /// data regions to make sure data doesn't get marked as code or vice<br>
+ /// versa.<br>
+ ///<br>
+ /// @returns Page alignment return value. Default of 4k.<br>
+ virtual unsigned getPageAlignment() { return 4096; }<br>
+<br>
+ /// Start the remote process.<br>
+ virtual void create();<br>
+<br>
+ /// Terminate the remote process.<br>
+ virtual void stop();<br>
+<br>
+ RemoteTargetExternal(std::string &Name) : RemoteTarget(), ChildName(Name) {}<br>
+ virtual ~RemoteTargetExternal() {}<br>
+<br>
+private:<br>
+ std::string ChildName;<br>
+<br>
+ // This will get filled in as a point to an OS-specific structure.<br>
+ void *ConnectionData;<br>
+<br>
+ void SendAllocateSpace(uint32_t Alignment, uint32_t Size);<br>
+ void SendLoadSection(uint64_t Addr,<br>
+ const void *Data,<br>
+ uint32_t Size,<br>
+ bool IsCode);<br>
+ void SendExecute(uint64_t Addr);<br>
+ void SendTerminate();<br>
+<br>
+ void Receive(LLIMessageType Msg);<br>
+ void Receive(LLIMessageType Msg, int &Data);<br>
+ void Receive(LLIMessageType Msg, uint64_t &Data);<br>
+<br>
+ int WriteBytes(const void *Data, size_t Size);<br>
+ int ReadBytes(void *Data, size_t Size);<br>
+ void Wait();<br>
+};<br>
+<br>
+} // end namespace llvm<br>
+<br>
+#endif // LLI_REMOTETARGETEXTERNAL_H<br>
<br>
Added: llvm/trunk/tools/lli/RemoteTargetMessage.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTargetMessage.h?rev=191843&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/RemoteTargetMessage.h?rev=191843&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/RemoteTargetMessage.h (added)<br>
+++ llvm/trunk/tools/lli/RemoteTargetMessage.h Wed Oct 2 12:12:36 2013<br>
@@ -0,0 +1,45 @@<br>
+//===---- RemoteTargetMessage.h - LLI out-of-process message protocol -----===//<br>
+//<br>
+// The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// Definition of the LLIMessageType enum which is used for communication with a<br>
+// child process for remote execution.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLI_REMOTETARGETMESSAGE_H<br>
+#define LLI_REMOTETARGETMESSAGE_H<br>
+<br>
+namespace llvm {<br>
+<br>
+// LLI messages from parent-to-child or vice versa follow an exceedingly simple<br>
+// protocol where the first four bytes represent the message type, the next<br>
+// four bytes represent the size of data for the command and following bytes<br>
+// represent the actual data.<br>
+//<br>
+// The protocol is not intended to be robust, secure or fault-tolerant. It is<br>
+// only here for testing purposes and is therefore intended to be the simplest<br>
+// implementation that will work. It is assumed that the parent and child<br>
+// share characteristics like endianness.<br>
+<br>
+enum LLIMessageType {<br>
+ LLI_Error = -1,<br>
+ LLI_ChildActive = 0, // Data = not used<br>
+ LLI_AllocateSpace, // Data = struct { uint_32t Align, uint_32t Size }<br>
+ LLI_AllocationResult, // Data = uint64_t AllocAddress (in Child memory space)<br>
+ LLI_LoadCodeSection, // Data = uint32_t Addr, followed by section contests<br>
+ LLI_LoadDataSection, // Data = uint32_t Addr, followed by section contents<br>
+ LLI_LoadComplete, // Data = not used<br>
+ LLI_Execute, // Data = Address of function to execute<br>
+ LLI_ExecutionResult, // Data = uint64_t Result<br>
+ LLI_Terminate // Data = not used<br>
+};<br>
+<br>
+} // end namespace llvm<br>
+<br>
+#endif<br>
<br>
Added: llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc?rev=191843&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc?rev=191843&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc (added)<br>
+++ llvm/trunk/tools/lli/Unix/RemoteTargetExternal.inc Wed Oct 2 12:12:36 2013<br>
@@ -0,0 +1,91 @@<br>
+//=- RemoteTargetExternal.inc - LLVM out-of-process JIT execution for Unix --=//<br>
+//<br>
+// The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// Implementation of the Unix-specific parts of the RemoteTargetExternal class<br>
+// which executes JITed code in a separate process from where it was built.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include <unistd.h><br>
+#include <stdio.h><br>
+#include <stdlib.h><br>
+#include <sys/wait.h><br>
+<br>
+namespace {<br>
+<br>
+struct ConnectionData_t {<br>
+ int InputPipe;<br>
+ int OutputPipe;<br>
+<br>
+ ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {}<br>
+};<br>
+<br>
+} // namespace<br>
+<br>
+namespace llvm {<br>
+<br>
+void RemoteTargetExternal::create() {<br>
+ int PipeFD[2][2];<br>
+ pid_t ChildPID;<br>
+<br>
+ pipe(PipeFD[0]);<br>
+ pipe(PipeFD[1]);<br>
+<br>
+ ChildPID = fork();<br>
+<br>
+ if (ChildPID == 0) {<br>
+ // In the child...<br>
+<br>
+ // Close the parent ends of the pipes<br>
+ close(PipeFD[0][1]);<br>
+ close(PipeFD[1][0]);<br>
+<br>
+ // Use our pipes as stdin and stdout<br>
+ if (PipeFD[0][0] != STDIN_FILENO) {<br>
+ dup2(PipeFD[0][0], STDIN_FILENO);<br>
+ close(PipeFD[0][0]);<br>
+ }<br>
+ if (PipeFD[1][1] != STDOUT_FILENO) {<br>
+ dup2(PipeFD[1][1], STDOUT_FILENO);<br>
+ close(PipeFD[1][1]);<br>
+ }<br>
+<br>
+ // Execute the child process.<br>
+ char *args[1] = { NULL };<br>
+ int rc = execv(ChildName.c_str(), args);<br>
+ if (rc != 0)<br>
+ perror("Error executing child process: ");<br>
+ }<br>
+ else {<br>
+ // In the parent...<br>
+<br>
+ // Close the child ends of the pipes<br>
+ close(PipeFD[0][0]);<br>
+ close(PipeFD[1][1]);<br>
+<br>
+ // Store the parent ends of the pipes<br>
+ ConnectionData = (void*)new ConnectionData_t(PipeFD[1][0], PipeFD[0][1]);<br>
+<br>
+ Receive(LLI_ChildActive);<br>
+ }<br>
+}<br>
+<br>
+int RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) {<br>
+ return write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size);<br>
+}<br>
+<br>
+int RemoteTargetExternal::ReadBytes(void *Data, size_t Size) {<br>
+ return read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size);<br>
+}<br>
+<br>
+void RemoteTargetExternal::Wait() {<br>
+ wait(NULL);<br>
+}<br>
+<br>
+} // namespace llvm<br>
\ No newline at end of file<br>
<br>
Added: llvm/trunk/tools/lli/Windows/RemoteTargetExternal.inc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/Windows/RemoteTargetExternal.inc?rev=191843&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/Windows/RemoteTargetExternal.inc?rev=191843&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/Windows/RemoteTargetExternal.inc (added)<br>
+++ llvm/trunk/tools/lli/Windows/RemoteTargetExternal.inc Wed Oct 2 12:12:36 2013<br>
@@ -0,0 +1,32 @@<br>
+//= RemoteTargetExternal.inc - LLVM out-of-process JIT execution for Windows =//<br>
+//<br>
+// The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// Definition of the Windows-specific parts of the RemoteTargetExternal class<br>
+// which is meant to execute JITed code in a separate process from where it was<br>
+// built. To support this functionality on Windows, implement these functions.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+namespace llvm {<br>
+<br>
+void RemoteTargetExternal::create() {<br>
+}<br>
+<br>
+int RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) {<br>
+ return 0;<br>
+}<br>
+<br>
+int RemoteTargetExternal::ReadBytes(void *Data, size_t Size) {<br>
+ return 0;<br>
+}<br>
+<br>
+void RemoteTargetExternal::Wait() {<br>
+}<br>
+<br>
+} // namespace llvm<br>
<br>
Modified: llvm/trunk/tools/lli/lli.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/lli.cpp?rev=191843&r1=191842&r2=191843&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/lli.cpp?rev=191843&r1=191842&r2=191843&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/lli.cpp (original)<br>
+++ llvm/trunk/tools/lli/lli.cpp Wed Oct 2 12:12:36 2013<br>
@@ -41,6 +41,7 @@<br>
#include "llvm/Support/PluginLoader.h"<br>
#include "llvm/Support/PrettyStackTrace.h"<br>
#include "llvm/Support/Process.h"<br>
+#include "llvm/Support/Program.h"<br>
#include "llvm/Support/Signals.h"<br>
#include "llvm/Support/SourceMgr.h"<br>
#include "llvm/Support/TargetSelect.h"<br>
@@ -83,6 +84,18 @@ namespace {<br>
cl::desc("Execute MCJIT'ed code in a separate process."),<br>
cl::init(false));<br>
<br>
+ // Manually specify the child process for remote execution. This overrides<br>
+ // the simulated remote execution that allocates address space for child<br>
+ // execution. The child process resides in the disk and communicates with lli<br>
+ // via stdin/stdout pipes.<br>
+ cl::opt<std::string><br>
+ MCJITRemoteProcess("mcjit-remote-process",<br>
+ cl::desc("Specify the filename of the process to launch "<br>
+ "for remote MCJIT execution. If none is specified,"<br>
+ "\n\tremote execution will be simulated in-process."),<br>
+ cl::value_desc("filename"),<br>
+ cl::init(""));<br>
+<br>
// Determine optimization level.<br>
cl::opt<char><br>
OptLevel("O",<br>
@@ -481,30 +494,50 @@ int main(int argc, char **argv, char * c<br>
// Everything is prepared now, so lay out our program for the target<br>
// address space, assign the section addresses to resolve any relocations,<br>
// and send it to the target.<br>
- RemoteTarget Target;<br>
- Target.create();<br>
+<br>
+ OwningPtr<RemoteTarget> Target;<br>
+ if (!MCJITRemoteProcess.empty()) { // Remote execution on a child process<br>
+ if (!RemoteTarget::hostSupportsExternalRemoteTarget()) {<br>
+ errs() << "Warning: host does not support external remote targets.\n"<br>
+ << " Defaulting to simulated remote execution\n";<br>
+ Target.reset(RemoteTarget::createRemoteTarget());<br>
+ } else {<br>
+ std::string ChildEXE = sys::FindProgramByName(MCJITRemoteProcess);<br>
+ if (ChildEXE == "") {<br>
+ errs() << "Unable to find child target: '\''" << MCJITRemoteProcess << "\'\n";<br>
+ return -1;<br>
+ }<br>
+ Target.reset(RemoteTarget::createExternalRemoteTarget(MCJITRemoteProcess));<br>
+ }<br>
+ } else {<br>
+ // No child process name provided, use simulated remote execution.<br>
+ Target.reset(RemoteTarget::createRemoteTarget());<br>
+ }<br>
+<br>
+ // Create the remote target<br>
+ Target->create();<br>
<br>
// Trigger compilation.<br>
EE->generateCodeForModule(Mod);<br>
<br>
// Layout the target memory.<br>
- layoutRemoteTargetMemory(&Target, MM);<br>
+ layoutRemoteTargetMemory(Target.get(), MM);<br>
<br>
// Since we're executing in a (at least simulated) remote address space,<br>
// we can't use the ExecutionEngine::runFunctionAsMain(). We have to<br>
// grab the function address directly here and tell the remote target<br>
// to execute the function.<br>
// FIXME: argv and envp handling.<br>
- uint64_t Entry = (uint64_t)EE->getPointerToFunction(EntryFn);<br>
+ uint64_t Entry = EE->getFunctionAddress(EntryFn->getName().str());<br>
<br>
DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"<br>
<< format("%llx", Entry) << "\n");<br>
<br>
- if (Target.executeCode(Entry, Result))<br>
- errs() << "ERROR: " << Target.getErrorMsg() << "\n";<br>
+ if (Target->executeCode(Entry, Result))<br>
+ errs() << "ERROR: " << Target->getErrorMsg() << "\n";<br>
<br>
- Target.stop();<br>
- } else {<br>
+ Target->stop();<br>
+ } else { // !RemoteMCJIT<br>
// Trigger compilation separately so code regions that need to be<br>
// invalidated will be known.<br>
(void)EE->getPointerToFunction(EntryFn);<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>