summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/lli
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lli')
-rw-r--r--contrib/llvm/tools/lli/ChildTarget/ChildTarget.cpp242
-rw-r--r--contrib/llvm/tools/lli/ChildTarget/Unix/ChildTarget.inc166
-rw-r--r--contrib/llvm/tools/lli/ChildTarget/Windows/ChildTarget.inc44
-rw-r--r--contrib/llvm/tools/lli/RecordingMemoryManager.cpp128
-rw-r--r--contrib/llvm/tools/lli/RecordingMemoryManager.h87
-rw-r--r--contrib/llvm/tools/lli/RemoteMemoryManager.cpp206
-rw-r--r--contrib/llvm/tools/lli/RemoteMemoryManager.h114
-rw-r--r--contrib/llvm/tools/lli/RemoteTarget.cpp31
-rw-r--r--contrib/llvm/tools/lli/RemoteTarget.h27
-rw-r--r--contrib/llvm/tools/lli/RemoteTargetExternal.cpp162
-rw-r--r--contrib/llvm/tools/lli/RemoteTargetExternal.h118
-rw-r--r--contrib/llvm/tools/lli/RemoteTargetMessage.h45
-rw-r--r--contrib/llvm/tools/lli/Unix/RemoteTargetExternal.inc96
-rw-r--r--contrib/llvm/tools/lli/Windows/RemoteTargetExternal.inc35
-rw-r--r--contrib/llvm/tools/lli/lli.cpp322
15 files changed, 1455 insertions, 368 deletions
diff --git a/contrib/llvm/tools/lli/ChildTarget/ChildTarget.cpp b/contrib/llvm/tools/lli/ChildTarget/ChildTarget.cpp
new file mode 100644
index 0000000..55fcae9
--- /dev/null
+++ b/contrib/llvm/tools/lli/ChildTarget/ChildTarget.cpp
@@ -0,0 +1,242 @@
+#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:
+ ~LLIChildTarget(); // OS-specific destructor
+ 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
diff --git a/contrib/llvm/tools/lli/ChildTarget/Unix/ChildTarget.inc b/contrib/llvm/tools/lli/ChildTarget/Unix/ChildTarget.inc
new file mode 100644
index 0000000..cc95810
--- /dev/null
+++ b/contrib/llvm/tools/lli/ChildTarget/Unix/ChildTarget.inc
@@ -0,0 +1,166 @@
+//===- 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>
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#ifdef __APPLE__
+#include <mach/mach.h>
+#endif
+
+#if defined(__mips__)
+# if defined(__OpenBSD__)
+# include <mips64/sysarch.h>
+# else
+# include <sys/cachectl.h>
+# endif
+#endif
+
+#ifdef __APPLE__
+extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
+#else
+extern "C" void __clear_cache(void *, void*);
+#endif
+
+namespace {
+
+struct ConnectionData_t {
+ int InputPipe;
+ int OutputPipe;
+
+ ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {}
+};
+
+} // namespace
+
+LLIChildTarget::~LLIChildTarget() {
+ delete static_cast<ConnectionData_t *>(ConnectionData);
+}
+
+// OS-specific methods
+void LLIChildTarget::initializeConnection() {
+ // Store the parent ends of the pipes
+ ConnectionData = (void*)new ConnectionData_t(STDIN_FILENO, STDOUT_FILENO);
+}
+
+int LLIChildTarget::WriteBytes(const void *Data, size_t Size) {
+ return write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size);
+}
+
+int LLIChildTarget::ReadBytes(void *Data, size_t Size) {
+ return read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size);
+}
+
+// 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);
+}
diff --git a/contrib/llvm/tools/lli/ChildTarget/Windows/ChildTarget.inc b/contrib/llvm/tools/lli/ChildTarget/Windows/ChildTarget.inc
new file mode 100644
index 0000000..45db2b0
--- /dev/null
+++ b/contrib/llvm/tools/lli/ChildTarget/Windows/ChildTarget.inc
@@ -0,0 +1,44 @@
+//=- ChildTarget.inc - Child process for external JIT execution for Windows -=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Non-implementation of the Windows-specific parts of the ChildTarget class
+// which executes JITed code in a separate process from where it was built.
+//
+//===----------------------------------------------------------------------===//
+
+LLIChildTarget::~LLIChildTarget() {
+}
+
+// The RemoteTargetExternal implementation should prevent us from ever getting
+// here on Windows, but nothing prevents a user from running this directly.
+void LLIChildTarget::initializeConnection() {
+ assert(0 && "lli-child-target is not implemented for Windows");
+}
+
+int LLIChildTarget::WriteBytes(const void *Data, size_t Size) {
+ return 0;
+}
+
+int LLIChildTarget::ReadBytes(void *Data, size_t Size) {
+ return 0;
+}
+
+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) {
+}
diff --git a/contrib/llvm/tools/lli/RecordingMemoryManager.cpp b/contrib/llvm/tools/lli/RecordingMemoryManager.cpp
deleted file mode 100644
index e4d992d..0000000
--- a/contrib/llvm/tools/lli/RecordingMemoryManager.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-//===- RecordingMemoryManager.cpp - Recording memory manager --------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This memory manager allocates local storage and keeps a record of each
-// allocation. Iterators are provided for all data and code allocations.
-//
-//===----------------------------------------------------------------------===//
-
-#include "RecordingMemoryManager.h"
-using namespace llvm;
-
-RecordingMemoryManager::~RecordingMemoryManager() {
- for (SmallVectorImpl<Allocation>::iterator
- I = AllocatedCodeMem.begin(), E = AllocatedCodeMem.end();
- I != E; ++I)
- sys::Memory::releaseMappedMemory(I->first);
- for (SmallVectorImpl<Allocation>::iterator
- I = AllocatedDataMem.begin(), E = AllocatedDataMem.end();
- I != E; ++I)
- sys::Memory::releaseMappedMemory(I->first);
-}
-
-uint8_t *RecordingMemoryManager::
-allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) {
- // The recording memory manager is just a local copy of the remote target.
- // The alignment requirement is just stored here for later use. Regular
- // heap storage is sufficient here, but we're using mapped memory to work
- // around a bug in MCJIT.
- sys::MemoryBlock Block = allocateSection(Size);
- AllocatedCodeMem.push_back(Allocation(Block, Alignment));
- return (uint8_t*)Block.base();
-}
-
-uint8_t *RecordingMemoryManager::
-allocateDataSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID, bool IsReadOnly) {
- // The recording memory manager is just a local copy of the remote target.
- // The alignment requirement is just stored here for later use. Regular
- // heap storage is sufficient here, but we're using mapped memory to work
- // around a bug in MCJIT.
- sys::MemoryBlock Block = allocateSection(Size);
- AllocatedDataMem.push_back(Allocation(Block, Alignment));
- return (uint8_t*)Block.base();
-}
-
-sys::MemoryBlock RecordingMemoryManager::allocateSection(uintptr_t Size) {
- error_code ec;
- sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(Size,
- &Near,
- sys::Memory::MF_READ |
- sys::Memory::MF_WRITE,
- ec);
- assert(!ec && MB.base());
-
- // FIXME: This is part of a work around to keep sections near one another
- // when MCJIT performs relocations after code emission but before
- // the generated code is moved to the remote target.
- // Save this address as the basis for our next request
- Near = MB;
- return MB;
-}
-
-void RecordingMemoryManager::setMemoryWritable() { llvm_unreachable("Unexpected!"); }
-void RecordingMemoryManager::setMemoryExecutable() { llvm_unreachable("Unexpected!"); }
-void RecordingMemoryManager::setPoisonMemory(bool poison) { llvm_unreachable("Unexpected!"); }
-void RecordingMemoryManager::AllocateGOT() { llvm_unreachable("Unexpected!"); }
-uint8_t *RecordingMemoryManager::getGOTBase() const {
- llvm_unreachable("Unexpected!");
- return 0;
-}
-uint8_t *RecordingMemoryManager::startFunctionBody(const Function *F, uintptr_t &ActualSize){
- llvm_unreachable("Unexpected!");
- return 0;
-}
-uint8_t *RecordingMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
- unsigned Alignment) {
- llvm_unreachable("Unexpected!");
- return 0;
-}
-void RecordingMemoryManager::endFunctionBody(const Function *F, uint8_t *FunctionStart,
- uint8_t *FunctionEnd) {
- llvm_unreachable("Unexpected!");
-}
-uint8_t *RecordingMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) {
- llvm_unreachable("Unexpected!");
- return 0;
-}
-uint8_t *RecordingMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) {
- llvm_unreachable("Unexpected!");
- return 0;
-}
-void RecordingMemoryManager::deallocateFunctionBody(void *Body) {
- llvm_unreachable("Unexpected!");
-}
-uint8_t* RecordingMemoryManager::startExceptionTable(const Function* F, uintptr_t &ActualSize) {
- llvm_unreachable("Unexpected!");
- return 0;
-}
-void RecordingMemoryManager::endExceptionTable(const Function *F, uint8_t *TableStart,
- uint8_t *TableEnd, uint8_t* FrameRegister) {
- llvm_unreachable("Unexpected!");
-}
-void RecordingMemoryManager::deallocateExceptionTable(void *ET) {
- llvm_unreachable("Unexpected!");
-}
-
-static int jit_noop() {
- return 0;
-}
-
-void *RecordingMemoryManager::getPointerToNamedFunction(const std::string &Name,
- bool AbortOnFailure) {
- // We should not invoke parent's ctors/dtors from generated main()!
- // On Mingw and Cygwin, the symbol __main is resolved to
- // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors
- // (and register wrong callee's dtors with atexit(3)).
- // We expect ExecutionEngine::runStaticConstructorsDestructors()
- // is called before ExecutionEngine::runFunctionAsMain() is called.
- if (Name == "__main") return (void*)(intptr_t)&jit_noop;
-
- return NULL;
-}
diff --git a/contrib/llvm/tools/lli/RecordingMemoryManager.h b/contrib/llvm/tools/lli/RecordingMemoryManager.h
deleted file mode 100644
index 991f535..0000000
--- a/contrib/llvm/tools/lli/RecordingMemoryManager.h
+++ /dev/null
@@ -1,87 +0,0 @@
-//===- RecordingMemoryManager.h - LLI MCJIT recording memory manager ------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This memory manager allocates local storage and keeps a record of each
-// allocation. Iterators are provided for all data and code allocations.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef RECORDINGMEMORYMANAGER_H
-#define RECORDINGMEMORYMANAGER_H
-
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ExecutionEngine/JITMemoryManager.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Memory.h"
-#include <utility>
-
-namespace llvm {
-
-class RecordingMemoryManager : public JITMemoryManager {
-public:
- typedef std::pair<sys::MemoryBlock, unsigned> Allocation;
-
-private:
- SmallVector<Allocation, 16> AllocatedDataMem;
- SmallVector<Allocation, 16> AllocatedCodeMem;
-
- // FIXME: This is part of a work around to keep sections near one another
- // when MCJIT performs relocations after code emission but before
- // the generated code is moved to the remote target.
- sys::MemoryBlock Near;
- sys::MemoryBlock allocateSection(uintptr_t Size);
-
-public:
- RecordingMemoryManager() {}
- virtual ~RecordingMemoryManager();
-
- typedef SmallVectorImpl<Allocation>::const_iterator const_data_iterator;
- typedef SmallVectorImpl<Allocation>::const_iterator const_code_iterator;
-
- const_data_iterator data_begin() const { return AllocatedDataMem.begin(); }
- const_data_iterator data_end() const { return AllocatedDataMem.end(); }
- const_code_iterator code_begin() const { return AllocatedCodeMem.begin(); }
- const_code_iterator code_end() const { return AllocatedCodeMem.end(); }
-
- uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID);
-
- uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID, bool IsReadOnly);
-
- void *getPointerToNamedFunction(const std::string &Name,
- bool AbortOnFailure = true);
-
- bool applyPermissions(std::string *ErrMsg) { return false; }
-
- // The following obsolete JITMemoryManager calls are stubbed out for
- // this model.
- void setMemoryWritable();
- void setMemoryExecutable();
- void setPoisonMemory(bool poison);
- void AllocateGOT();
- uint8_t *getGOTBase() const;
- uint8_t *startFunctionBody(const Function *F, uintptr_t &ActualSize);
- uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize,
- unsigned Alignment);
- void endFunctionBody(const Function *F, uint8_t *FunctionStart,
- uint8_t *FunctionEnd);
- uint8_t *allocateSpace(intptr_t Size, unsigned Alignment);
- uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
- void deallocateFunctionBody(void *Body);
- uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize);
- void endExceptionTable(const Function *F, uint8_t *TableStart,
- uint8_t *TableEnd, uint8_t* FrameRegister);
- void deallocateExceptionTable(void *ET);
-
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/contrib/llvm/tools/lli/RemoteMemoryManager.cpp b/contrib/llvm/tools/lli/RemoteMemoryManager.cpp
new file mode 100644
index 0000000..04fc40e
--- /dev/null
+++ b/contrib/llvm/tools/lli/RemoteMemoryManager.cpp
@@ -0,0 +1,206 @@
+//===---- RemoteMemoryManager.cpp - Recording memory manager --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This memory manager allocates local storage and keeps a record of each
+// allocation. Iterators are provided for all data and code allocations.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "lli"
+#include "RemoteMemoryManager.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/ObjectImage.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+
+RemoteMemoryManager::~RemoteMemoryManager() {
+ for (SmallVector<Allocation, 2>::iterator
+ I = AllocatedSections.begin(), E = AllocatedSections.end();
+ I != E; ++I)
+ sys::Memory::releaseMappedMemory(I->MB);
+}
+
+uint8_t *RemoteMemoryManager::
+allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
+ StringRef SectionName) {
+ // The recording memory manager is just a local copy of the remote target.
+ // The alignment requirement is just stored here for later use. Regular
+ // heap storage is sufficient here, but we're using mapped memory to work
+ // around a bug in MCJIT.
+ sys::MemoryBlock Block = allocateSection(Size);
+ // AllocatedSections will own this memory.
+ AllocatedSections.push_back( Allocation(Block, Alignment, true) );
+ // UnmappedSections has the same information but does not own the memory.
+ UnmappedSections.push_back( Allocation(Block, Alignment, true) );
+ return (uint8_t*)Block.base();
+}
+
+uint8_t *RemoteMemoryManager::
+allocateDataSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID, StringRef SectionName,
+ bool IsReadOnly) {
+ // The recording memory manager is just a local copy of the remote target.
+ // The alignment requirement is just stored here for later use. Regular
+ // heap storage is sufficient here, but we're using mapped memory to work
+ // around a bug in MCJIT.
+ sys::MemoryBlock Block = allocateSection(Size);
+ // AllocatedSections will own this memory.
+ AllocatedSections.push_back( Allocation(Block, Alignment, false) );
+ // UnmappedSections has the same information but does not own the memory.
+ UnmappedSections.push_back( Allocation(Block, Alignment, false) );
+ return (uint8_t*)Block.base();
+}
+
+sys::MemoryBlock RemoteMemoryManager::allocateSection(uintptr_t Size) {
+ error_code ec;
+ sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(Size,
+ &Near,
+ sys::Memory::MF_READ |
+ sys::Memory::MF_WRITE,
+ ec);
+ assert(!ec && MB.base());
+
+ // FIXME: This is part of a work around to keep sections near one another
+ // when MCJIT performs relocations after code emission but before
+ // the generated code is moved to the remote target.
+ // Save this address as the basis for our next request
+ Near = MB;
+ return MB;
+}
+
+void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE,
+ const ObjectImage *Obj) {
+ // The client should have called setRemoteTarget() before triggering any
+ // code generation.
+ assert(Target);
+ if (!Target)
+ return;
+
+ // FIXME: Make this function thread safe.
+
+ // Lay out our sections in order, with all the code sections first, then
+ // all the data sections.
+ uint64_t CurOffset = 0;
+ unsigned MaxAlign = Target->getPageAlignment();
+ SmallVector<std::pair<Allocation, uint64_t>, 16> Offsets;
+ unsigned NumSections = UnmappedSections.size();
+ // We're going to go through the list twice to separate code and data, but
+ // it's a very small list, so that's OK.
+ for (size_t i = 0, e = NumSections; i != e; ++i) {
+ Allocation &Section = UnmappedSections[i];
+ if (Section.IsCode) {
+ unsigned Size = Section.MB.size();
+ unsigned Align = Section.Alignment;
+ DEBUG(dbgs() << "code region: size " << Size
+ << ", alignment " << Align << "\n");
+ // Align the current offset up to whatever is needed for the next
+ // section.
+ CurOffset = (CurOffset + Align - 1) / Align * Align;
+ // Save off the address of the new section and allocate its space.
+ Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
+ CurOffset += Size;
+ }
+ }
+ // Adjust to keep code and data aligned on seperate pages.
+ CurOffset = (CurOffset + MaxAlign - 1) / MaxAlign * MaxAlign;
+ for (size_t i = 0, e = NumSections; i != e; ++i) {
+ Allocation &Section = UnmappedSections[i];
+ if (!Section.IsCode) {
+ unsigned Size = Section.MB.size();
+ unsigned Align = Section.Alignment;
+ DEBUG(dbgs() << "data region: size " << Size
+ << ", alignment " << Align << "\n");
+ // Align the current offset up to whatever is needed for the next
+ // section.
+ CurOffset = (CurOffset + Align - 1) / Align * Align;
+ // Save off the address of the new section and allocate its space.
+ Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
+ CurOffset += Size;
+ }
+ }
+
+ // Allocate space in the remote target.
+ uint64_t RemoteAddr;
+ if (Target->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
+ report_fatal_error(Target->getErrorMsg());
+
+ // Map the section addresses so relocations will get updated in the local
+ // copies of the sections.
+ for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
+ uint64_t Addr = RemoteAddr + Offsets[i].second;
+ EE->mapSectionAddress(const_cast<void*>(Offsets[i].first.MB.base()), Addr);
+
+ DEBUG(dbgs() << " Mapping local: " << Offsets[i].first.MB.base()
+ << " to remote: 0x" << format("%llx", Addr) << "\n");
+
+ MappedSections[Addr] = Offsets[i].first;
+ }
+
+ UnmappedSections.clear();
+}
+
+bool RemoteMemoryManager::finalizeMemory(std::string *ErrMsg) {
+ // FIXME: Make this function thread safe.
+ for (DenseMap<uint64_t, Allocation>::iterator
+ I = MappedSections.begin(), E = MappedSections.end();
+ I != E; ++I) {
+ uint64_t RemoteAddr = I->first;
+ const Allocation &Section = I->second;
+ if (Section.IsCode) {
+ Target->loadCode(RemoteAddr, Section.MB.base(), Section.MB.size());
+
+ DEBUG(dbgs() << " loading code: " << Section.MB.base()
+ << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
+ } else {
+ Target->loadData(RemoteAddr, Section.MB.base(), Section.MB.size());
+
+ DEBUG(dbgs() << " loading data: " << Section.MB.base()
+ << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
+ }
+ }
+
+ MappedSections.clear();
+
+ return false;
+}
+
+void RemoteMemoryManager::setMemoryWritable() { llvm_unreachable("Unexpected!"); }
+void RemoteMemoryManager::setMemoryExecutable() { llvm_unreachable("Unexpected!"); }
+void RemoteMemoryManager::setPoisonMemory(bool poison) { llvm_unreachable("Unexpected!"); }
+void RemoteMemoryManager::AllocateGOT() { llvm_unreachable("Unexpected!"); }
+uint8_t *RemoteMemoryManager::getGOTBase() const {
+ llvm_unreachable("Unexpected!");
+ return 0;
+}
+uint8_t *RemoteMemoryManager::startFunctionBody(const Function *F, uintptr_t &ActualSize){
+ llvm_unreachable("Unexpected!");
+ return 0;
+}
+uint8_t *RemoteMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
+ unsigned Alignment) {
+ llvm_unreachable("Unexpected!");
+ return 0;
+}
+void RemoteMemoryManager::endFunctionBody(const Function *F, uint8_t *FunctionStart,
+ uint8_t *FunctionEnd) {
+ llvm_unreachable("Unexpected!");
+}
+uint8_t *RemoteMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) {
+ llvm_unreachable("Unexpected!");
+ return 0;
+}
+uint8_t *RemoteMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) {
+ llvm_unreachable("Unexpected!");
+ return 0;
+}
+void RemoteMemoryManager::deallocateFunctionBody(void *Body) {
+ llvm_unreachable("Unexpected!");
+}
diff --git a/contrib/llvm/tools/lli/RemoteMemoryManager.h b/contrib/llvm/tools/lli/RemoteMemoryManager.h
new file mode 100644
index 0000000..5d0456f
--- /dev/null
+++ b/contrib/llvm/tools/lli/RemoteMemoryManager.h
@@ -0,0 +1,114 @@
+//===- RemoteMemoryManager.h - LLI MCJIT recording memory manager ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This memory manager allocates local storage and keeps a record of each
+// allocation. Iterators are provided for all data and code allocations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef REMOTEMEMORYMANAGER_H
+#define REMOTEMEMORYMANAGER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ExecutionEngine/JITMemoryManager.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Memory.h"
+#include <utility>
+
+#include "RemoteTarget.h"
+
+namespace llvm {
+
+class RemoteMemoryManager : public JITMemoryManager {
+public:
+ // Notice that this structure takes ownership of the memory allocated.
+ struct Allocation {
+ Allocation() {}
+ Allocation(sys::MemoryBlock mb, unsigned a, bool code)
+ : MB(mb), Alignment(a), IsCode(code) {}
+
+ sys::MemoryBlock MB;
+ unsigned Alignment;
+ bool IsCode;
+ };
+
+private:
+ // This vector contains Allocation objects for all sections which we have
+ // allocated. This vector effectively owns the memory associated with the
+ // allocations.
+ SmallVector<Allocation, 2> AllocatedSections;
+
+ // This vector contains pointers to Allocation objects for any sections we
+ // have allocated locally but have not yet remapped for the remote target.
+ // When we receive notification of a completed module load, we will map
+ // these sections into the remote target.
+ SmallVector<Allocation, 2> UnmappedSections;
+
+ // This map tracks the sections we have remapped for the remote target
+ // but have not yet copied to the target.
+ DenseMap<uint64_t, Allocation> MappedSections;
+
+ // FIXME: This is part of a work around to keep sections near one another
+ // when MCJIT performs relocations after code emission but before
+ // the generated code is moved to the remote target.
+ sys::MemoryBlock Near;
+ sys::MemoryBlock allocateSection(uintptr_t Size);
+
+ RemoteTarget *Target;
+
+public:
+ RemoteMemoryManager() : Target(NULL) {}
+ virtual ~RemoteMemoryManager();
+
+ uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID, StringRef SectionName);
+
+ uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID, StringRef SectionName,
+ bool IsReadOnly);
+
+ // For now, remote symbol resolution is not support in lli. The MCJIT
+ // interface does support this, but clients must provide their own
+ // mechanism for finding remote symbol addresses. MCJIT will resolve
+ // symbols from Modules it contains.
+ uint64_t getSymbolAddress(const std::string &Name) { return 0; }
+
+ void notifyObjectLoaded(ExecutionEngine *EE, const ObjectImage *Obj);
+
+ bool finalizeMemory(std::string *ErrMsg);
+
+ // For now, remote EH frame registration isn't supported. Remote symbol
+ // resolution is a prerequisite to supporting remote EH frame registration.
+ void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {}
+ void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {}
+
+ // This is a non-interface function used by lli
+ void setRemoteTarget(RemoteTarget *T) { Target = T; }
+
+ // The following obsolete JITMemoryManager calls are stubbed out for
+ // this model.
+ void setMemoryWritable();
+ void setMemoryExecutable();
+ void setPoisonMemory(bool poison);
+ void AllocateGOT();
+ uint8_t *getGOTBase() const;
+ uint8_t *startFunctionBody(const Function *F, uintptr_t &ActualSize);
+ uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize,
+ unsigned Alignment);
+ void endFunctionBody(const Function *F, uint8_t *FunctionStart,
+ uint8_t *FunctionEnd);
+ uint8_t *allocateSpace(intptr_t Size, unsigned Alignment);
+ uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
+ void deallocateFunctionBody(void *Body);
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/lli/RemoteTarget.cpp b/contrib/llvm/tools/lli/RemoteTarget.cpp
index 212bdfd..5c74e6e 100644
--- a/contrib/llvm/tools/lli/RemoteTarget.cpp
+++ b/contrib/llvm/tools/lli/RemoteTarget.cpp
@@ -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;
diff --git a/contrib/llvm/tools/lli/RemoteTarget.h b/contrib/llvm/tools/lli/RemoteTarget.h
index b2a6d0e..c95fbd1 100644
--- a/contrib/llvm/tools/lli/RemoteTarget.h
+++ b/contrib/llvm/tools/lli/RemoteTarget.h
@@ -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.
diff --git a/contrib/llvm/tools/lli/RemoteTargetExternal.cpp b/contrib/llvm/tools/lli/RemoteTargetExternal.cpp
new file mode 100644
index 0000000..742a948
--- /dev/null
+++ b/contrib/llvm/tools/lli/RemoteTargetExternal.cpp
@@ -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 == (uint32_t)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 == (uint32_t)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
diff --git a/contrib/llvm/tools/lli/RemoteTargetExternal.h b/contrib/llvm/tools/lli/RemoteTargetExternal.h
new file mode 100644
index 0000000..a4bfad2
--- /dev/null
+++ b/contrib/llvm/tools/lli/RemoteTargetExternal.h
@@ -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
diff --git a/contrib/llvm/tools/lli/RemoteTargetMessage.h b/contrib/llvm/tools/lli/RemoteTargetMessage.h
new file mode 100644
index 0000000..12cfa9a
--- /dev/null
+++ b/contrib/llvm/tools/lli/RemoteTargetMessage.h
@@ -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
diff --git a/contrib/llvm/tools/lli/Unix/RemoteTargetExternal.inc b/contrib/llvm/tools/lli/Unix/RemoteTargetExternal.inc
new file mode 100644
index 0000000..9c1a4cc
--- /dev/null
+++ b/contrib/llvm/tools/lli/Unix/RemoteTargetExternal.inc
@@ -0,0 +1,96 @@
+//=- 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;
+
+ // Create two pipes.
+ if (pipe(PipeFD[0]) != 0 || pipe(PipeFD[1]) != 0)
+ perror("Error creating pipe: ");
+
+ ChildPID = fork();
+
+ if (ChildPID == 0) {
+ // In the child...
+
+ // Close the parent ends of the pipes
+ close(PipeFD[0][1]);
+ close(PipeFD[1][0]);
+
+ // Use our pipes as stdin and stdout
+ if (PipeFD[0][0] != STDIN_FILENO) {
+ dup2(PipeFD[0][0], STDIN_FILENO);
+ close(PipeFD[0][0]);
+ }
+ if (PipeFD[1][1] != STDOUT_FILENO) {
+ dup2(PipeFD[1][1], STDOUT_FILENO);
+ close(PipeFD[1][1]);
+ }
+
+ // Execute the child process.
+ char *args[1] = { NULL };
+ int rc = execv(ChildName.c_str(), args);
+ if (rc != 0)
+ perror("Error executing child process: ");
+ }
+ else {
+ // In the parent...
+
+ // Close the child ends of the pipes
+ close(PipeFD[0][0]);
+ close(PipeFD[1][1]);
+
+ // Store the parent ends of the pipes
+ ConnectionData = (void*)new ConnectionData_t(PipeFD[1][0], PipeFD[0][1]);
+
+ 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);
+}
+
+RemoteTargetExternal::~RemoteTargetExternal() {
+ delete static_cast<ConnectionData_t *>(ConnectionData);
+}
+
+} // namespace llvm
diff --git a/contrib/llvm/tools/lli/Windows/RemoteTargetExternal.inc b/contrib/llvm/tools/lli/Windows/RemoteTargetExternal.inc
new file mode 100644
index 0000000..aef4627
--- /dev/null
+++ b/contrib/llvm/tools/lli/Windows/RemoteTargetExternal.inc
@@ -0,0 +1,35 @@
+//= 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() {
+}
+
+RemoteTargetExternal::~RemoteTargetExternal() {
+}
+
+} // namespace llvm
diff --git a/contrib/llvm/tools/lli/lli.cpp b/contrib/llvm/tools/lli/lli.cpp
index 297763f..f317566 100644
--- a/contrib/llvm/tools/lli/lli.cpp
+++ b/contrib/llvm/tools/lli/lli.cpp
@@ -15,7 +15,7 @@
#define DEBUG_TYPE "lli"
#include "llvm/IR/LLVMContext.h"
-#include "RecordingMemoryManager.h"
+#include "RemoteMemoryManager.h"
#include "RemoteTarget.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Bitcode/ReaderWriter.h"
@@ -27,8 +27,10 @@
#include "llvm/ExecutionEngine/JITMemoryManager.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
+#include "llvm/IR/TypeBuilder.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -41,10 +43,12 @@
#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"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/Instrumentation.h"
#include <cerrno>
#ifdef __CYGWIN__
@@ -71,6 +75,10 @@ namespace {
"use-mcjit", cl::desc("Enable use of the MC-based JIT (if available)"),
cl::init(false));
+ cl::opt<bool> DebugIR(
+ "debug-ir", cl::desc("Generate debug information to allow debugging IR."),
+ cl::init(false));
+
// The MCJIT supports building for a target address space separate from
// the JIT compilation process. Use a forked process and a copying
// memory manager with IPC to execute using this functionality.
@@ -78,6 +86,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 will be executed and will communicate 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",
@@ -113,6 +133,11 @@ namespace {
cl::value_desc("function"),
cl::init("main"));
+ cl::list<std::string>
+ ExtraModules("extra-module",
+ cl::desc("Extra modules to be loaded"),
+ cl::value_desc("input bitcode"));
+
cl::opt<std::string>
FakeArgv0("fake-argv0",
cl::desc("Override the 'argv[0]' value passed into the executing"
@@ -159,11 +184,6 @@ namespace {
clEnumValEnd));
cl::opt<bool>
- EnableJITExceptionHandling("jit-enable-eh",
- cl::desc("Emit exception handling information"),
- cl::init(false));
-
- cl::opt<bool>
GenerateSoftFloatCalls("soft-float",
cl::desc("Generate software floating point library calls"),
cl::init(false));
@@ -209,82 +229,46 @@ static void do_shutdown() {
#endif
}
-void layoutRemoteTargetMemory(RemoteTarget *T, RecordingMemoryManager *JMM) {
- // Lay out our sections in order, with all the code sections first, then
- // all the data sections.
- uint64_t CurOffset = 0;
- unsigned MaxAlign = T->getPageAlignment();
- SmallVector<std::pair<const void*, uint64_t>, 16> Offsets;
- SmallVector<unsigned, 16> Sizes;
- for (RecordingMemoryManager::const_code_iterator I = JMM->code_begin(),
- E = JMM->code_end();
- I != E; ++I) {
- DEBUG(dbgs() << "code region: size " << I->first.size()
- << ", alignment " << I->second << "\n");
- // Align the current offset up to whatever is needed for the next
- // section.
- unsigned Align = I->second;
- CurOffset = (CurOffset + Align - 1) / Align * Align;
- // Save off the address of the new section and allocate its space.
- Offsets.push_back(std::pair<const void*,uint64_t>(I->first.base(), CurOffset));
- Sizes.push_back(I->first.size());
- CurOffset += I->first.size();
- }
- // Adjust to keep code and data aligned on seperate pages.
- CurOffset = (CurOffset + MaxAlign - 1) / MaxAlign * MaxAlign;
- unsigned FirstDataIndex = Offsets.size();
- for (RecordingMemoryManager::const_data_iterator I = JMM->data_begin(),
- E = JMM->data_end();
- I != E; ++I) {
- DEBUG(dbgs() << "data region: size " << I->first.size()
- << ", alignment " << I->second << "\n");
- // Align the current offset up to whatever is needed for the next
- // section.
- unsigned Align = I->second;
- CurOffset = (CurOffset + Align - 1) / Align * Align;
- // Save off the address of the new section and allocate its space.
- Offsets.push_back(std::pair<const void*,uint64_t>(I->first.base(), CurOffset));
- Sizes.push_back(I->first.size());
- CurOffset += I->first.size();
- }
-
- // Allocate space in the remote target.
- uint64_t RemoteAddr;
- if (T->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
- report_fatal_error(T->getErrorMsg());
- // Map the section addresses so relocations will get updated in the local
- // copies of the sections.
- for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
- uint64_t Addr = RemoteAddr + Offsets[i].second;
- EE->mapSectionAddress(const_cast<void*>(Offsets[i].first), Addr);
-
- DEBUG(dbgs() << " Mapping local: " << Offsets[i].first
- << " to remote: " << format("%p", Addr) << "\n");
-
- }
-
- // Trigger application of relocations
- EE->finalizeObject();
-
- // Now load it all to the target.
- for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
- uint64_t Addr = RemoteAddr + Offsets[i].second;
-
- if (i < FirstDataIndex) {
- T->loadCode(Addr, Offsets[i].first, Sizes[i]);
-
- DEBUG(dbgs() << " loading code: " << Offsets[i].first
- << " to remote: " << format("%p", Addr) << "\n");
- } else {
- T->loadData(Addr, Offsets[i].first, Sizes[i]);
-
- DEBUG(dbgs() << " loading data: " << Offsets[i].first
- << " to remote: " << format("%p", Addr) << "\n");
- }
-
+// On Mingw and Cygwin, an external symbol named '__main' is called from the
+// generated 'main' function to allow static intialization. To avoid linking
+// problems with remote targets (because lli's remote target support does not
+// currently handle external linking) we add a secondary module which defines
+// an empty '__main' function.
+static void addCygMingExtraModule(ExecutionEngine *EE,
+ LLVMContext &Context,
+ StringRef TargetTripleStr) {
+ IRBuilder<> Builder(Context);
+ Triple TargetTriple(TargetTripleStr);
+
+ // Create a new module.
+ Module *M = new Module("CygMingHelper", Context);
+ M->setTargetTriple(TargetTripleStr);
+
+ // Create an empty function named "__main".
+ Function *Result;
+ if (TargetTriple.isArch64Bit()) {
+ Result = Function::Create(
+ TypeBuilder<int64_t(void), false>::get(Context),
+ GlobalValue::ExternalLinkage, "__main", M);
+ } else {
+ Result = Function::Create(
+ TypeBuilder<int32_t(void), false>::get(Context),
+ GlobalValue::ExternalLinkage, "__main", M);
}
+ BasicBlock *BB = BasicBlock::Create(Context, "__main", Result);
+ Builder.SetInsertPoint(BB);
+ Value *ReturnVal;
+ if (TargetTriple.isArch64Bit())
+ ReturnVal = ConstantInt::get(Context, APInt(64, 0));
+ else
+ ReturnVal = ConstantInt::get(Context, APInt(32, 0));
+ Builder.CreateRet(ReturnVal);
+
+ // Add this new module to the ExecutionEngine.
+ EE->addModule(M);
}
+
//===----------------------------------------------------------------------===//
// main Driver function
//
@@ -326,6 +310,17 @@ int main(int argc, char **argv, char * const *envp) {
}
}
+ if (DebugIR) {
+ if (!UseMCJIT) {
+ errs() << "warning: -debug-ir used without -use-mcjit. Only partial debug"
+ << " information will be emitted by the non-MC JIT engine. To see full"
+ << " source debug information, enable the flag '-use-mcjit'.\n";
+
+ }
+ ModulePass *DebugIRPass = createDebugIRPass();
+ DebugIRPass->runOnModule(*Mod);
+ }
+
EngineBuilder builder(Mod);
builder.setMArch(MArch);
builder.setMCPU(MCPU);
@@ -342,14 +337,14 @@ int main(int argc, char **argv, char * const *envp) {
Mod->setTargetTriple(Triple::normalize(TargetTriple));
// Enable MCJIT if desired.
- JITMemoryManager *JMM = 0;
+ RTDyldMemoryManager *RTDyldMM = 0;
if (UseMCJIT && !ForceInterpreter) {
builder.setUseMCJIT(true);
if (RemoteMCJIT)
- JMM = new RecordingMemoryManager();
+ RTDyldMM = new RemoteMemoryManager();
else
- JMM = new SectionMemoryManager();
- builder.setJITMemoryManager(JMM);
+ RTDyldMM = new SectionMemoryManager();
+ builder.setMCJITMemoryManager(RTDyldMM);
} else {
if (RemoteMCJIT) {
errs() << "error: Remote process execution requires -use-mcjit\n";
@@ -381,7 +376,6 @@ int main(int argc, char **argv, char * const *envp) {
// Remote target execution doesn't handle EH or debug registration.
if (!RemoteMCJIT) {
- Options.JITExceptionHandling = EnableJITExceptionHandling;
Options.JITEmitDebugInfo = EmitJitDebugInfo;
Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk;
}
@@ -397,6 +391,22 @@ int main(int argc, char **argv, char * const *envp) {
exit(1);
}
+ // Load any additional modules specified on the command line.
+ for (unsigned i = 0, e = ExtraModules.size(); i != e; ++i) {
+ Module *XMod = ParseIRFile(ExtraModules[i], Err, Context);
+ if (!XMod) {
+ Err.print(argv[0], errs());
+ return 1;
+ }
+ EE->addModule(XMod);
+ }
+
+ // If the target is Cygwin/MingW and we are generating remote code, we
+ // need an extra module to help out with linking.
+ if (RemoteMCJIT && Triple(Mod->getTargetTriple()).isOSCygMing()) {
+ addCygMingExtraModule(EE, Context, Mod->getTargetTriple());
+ }
+
// The following functions have no effect if their respective profiling
// support wasn't enabled in the build configuration.
EE->RegisterJITEventListener(
@@ -435,82 +445,43 @@ int main(int argc, char **argv, char * const *envp) {
return -1;
}
- // If the program doesn't explicitly call exit, we will need the Exit
- // function later on to make an explicit call, so get the function now.
- Constant *Exit = Mod->getOrInsertFunction("exit", Type::getVoidTy(Context),
- Type::getInt32Ty(Context),
- NULL);
-
// Reset errno to zero on entry to main.
errno = 0;
- // Remote target MCJIT doesn't (yet) support static constructors. No reason
- // it couldn't. This is a limitation of the LLI implemantation, not the
- // MCJIT itself. FIXME.
- //
- // Run static constructors.
- if (!RemoteMCJIT) {
- if (UseMCJIT && !ForceInterpreter) {
- // Give MCJIT a chance to apply relocations and set page permissions.
- EE->finalizeObject();
- }
- EE->runStaticConstructorsDestructors(false);
- }
-
- if (NoLazyCompilation) {
- for (Module::iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) {
- Function *Fn = &*I;
- if (Fn != EntryFn && !Fn->isDeclaration())
- EE->getPointerToFunction(Fn);
- }
- }
-
int Result;
- if (RemoteMCJIT) {
- RecordingMemoryManager *MM = static_cast<RecordingMemoryManager*>(JMM);
- // 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();
-
- // Ask for a pointer to the entry function. This triggers the actual
- // compilation.
- (void)EE->getPointerToFunction(EntryFn);
- // Enough has been compiled to execute the entry function now, so
- // layout the target memory.
- layoutRemoteTargetMemory(&Target, 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);
-
- DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at "
- << format("%p", Entry) << "\n");
+ if (!RemoteMCJIT) {
+ // If the program doesn't explicitly call exit, we will need the Exit
+ // function later on to make an explicit call, so get the function now.
+ Constant *Exit = Mod->getOrInsertFunction("exit", Type::getVoidTy(Context),
+ Type::getInt32Ty(Context),
+ NULL);
+
+ // Run static constructors.
+ if (UseMCJIT && !ForceInterpreter) {
+ // Give MCJIT a chance to apply relocations and set page permissions.
+ EE->finalizeObject();
+ }
+ EE->runStaticConstructorsDestructors(false);
- if (Target.executeCode(Entry, Result))
- errs() << "ERROR: " << Target.getErrorMsg() << "\n";
+ if (!UseMCJIT && NoLazyCompilation) {
+ for (Module::iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) {
+ Function *Fn = &*I;
+ if (Fn != EntryFn && !Fn->isDeclaration())
+ EE->getPointerToFunction(Fn);
+ }
+ }
- Target.stop();
- } else {
// Trigger compilation separately so code regions that need to be
// invalidated will be known.
(void)EE->getPointerToFunction(EntryFn);
// Clear instruction cache before code will be executed.
- if (JMM)
- static_cast<SectionMemoryManager*>(JMM)->invalidateInstructionCache();
+ if (RTDyldMM)
+ static_cast<SectionMemoryManager*>(RTDyldMM)->invalidateInstructionCache();
// Run main.
Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp);
- }
- // Like static constructors, the remote target MCJIT support doesn't handle
- // this yet. It could. FIXME.
- if (!RemoteMCJIT) {
// Run static destructors.
EE->runStaticConstructorsDestructors(true);
@@ -528,6 +499,67 @@ int main(int argc, char **argv, char * const *envp) {
errs() << "ERROR: exit defined with wrong prototype!\n";
abort();
}
+ } else {
+ // else == "if (RemoteMCJIT)"
+
+ // Remote target MCJIT doesn't (yet) support static constructors. No reason
+ // it couldn't. This is a limitation of the LLI implemantation, not the
+ // MCJIT itself. FIXME.
+ //
+ RemoteMemoryManager *MM = static_cast<RemoteMemoryManager*>(RTDyldMM);
+ // 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.
+
+ 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(ChildEXE));
+ }
+ } else {
+ // No child process name provided, use simulated remote execution.
+ Target.reset(RemoteTarget::createRemoteTarget());
+ }
+
+ // Give the memory manager a pointer to our remote target interface object.
+ MM->setRemoteTarget(Target.get());
+
+ // Create the remote target.
+ Target->create();
+
+ // 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.
+ //
+ // Our memory manager will map generated code into the remote address
+ // space as it is loaded and copy the bits over during the finalizeMemory
+ // operation.
+ //
+ // FIXME: argv and envp handling.
+ 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";
+
+ // Like static constructors, the remote target MCJIT support doesn't handle
+ // this yet. It could. FIXME.
+
+ // Stop the remote target
+ Target->stop();
}
+
return Result;
}
OpenPOWER on IntegriCloud