1 //===- ChildTarget.inc - Child process for external JIT execution for Unix -==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Implementation of the Unix-specific parts of the ChildTarget class
11 // which executes JITed code in a separate process from where it was built.
13 //===----------------------------------------------------------------------===//
19 #ifdef HAVE_SYS_MMAN_H
24 #include <mach/mach.h>
28 # if defined(__OpenBSD__)
29 # include <mips64/sysarch.h>
31 # include <sys/cachectl.h>
36 extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
38 extern "C" void __clear_cache(void *, void*);
43 struct ConnectionData_t {
47 ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {}
52 LLIChildTarget::~LLIChildTarget() {
53 delete static_cast<ConnectionData_t *>(ConnectionData);
56 // OS-specific methods
57 void LLIChildTarget::initializeConnection() {
58 // Store the parent ends of the pipes
59 ConnectionData = (void*)new ConnectionData_t(STDIN_FILENO, STDOUT_FILENO);
62 int LLIChildTarget::WriteBytes(const void *Data, size_t Size) {
63 return write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size);
66 int LLIChildTarget::ReadBytes(void *Data, size_t Size) {
67 return read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size);
70 // The functions below duplicate functionality that is implemented in
71 // Support/Memory.cpp with the goal of avoiding a dependency on any
74 uint64_t LLIChildTarget::allocate(uint32_t Alignment, uint32_t Size) {
78 static const size_t PageSize = getpagesize();
79 const size_t NumPages = (Size+PageSize-1)/PageSize;
80 Size = NumPages*PageSize;
83 #ifdef NEED_DEV_ZERO_FOR_MMAP
84 static int zero_fd = open("/dev/zero", O_RDWR);
90 int MMFlags = MAP_PRIVATE |
91 #ifdef HAVE_MMAP_ANONYMOUS
96 ; // Ends statement above
98 uint64_t Addr = (uint64_t)::mmap(0, Size, PROT_READ | PROT_WRITE, MMFlags, fd, 0);
99 if (Addr == (uint64_t)MAP_FAILED)
102 // Align the address.
103 Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
105 m_AllocatedBufferMap[Addr] = Size;
107 // Return aligned address
111 void LLIChildTarget::makeSectionExecutable(uint64_t Addr, uint32_t Size) {
112 // FIXME: We have to mark the memory as RWX because multiple code chunks may
113 // be on the same page. The RemoteTarget interface should be changed to
115 int Result = ::mprotect((void*)Addr, Size, PROT_READ | PROT_WRITE | PROT_EXEC);
117 InvalidateInstructionCache((const void *)Addr, Size);
120 /// InvalidateInstructionCache - Before the JIT can run a block of code
121 /// that has been emitted it must invalidate the instruction cache on some
123 void LLIChildTarget::InvalidateInstructionCache(const void *Addr,
126 // icache invalidation for PPC and ARM.
127 #if defined(__APPLE__)
129 # if (defined(__POWERPC__) || defined (__ppc__) || \
130 defined(_POWER) || defined(_ARCH_PPC)) || defined(__arm__)
131 sys_icache_invalidate(const_cast<void *>(Addr), Len);
136 # if (defined(__POWERPC__) || defined (__ppc__) || \
137 defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__)
138 const size_t LineSize = 32;
140 const intptr_t Mask = ~(LineSize - 1);
141 const intptr_t StartLine = ((intptr_t) Addr) & Mask;
142 const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask;
144 for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
145 asm volatile("dcbf 0, %0" : : "r"(Line));
146 asm volatile("sync");
148 for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
149 asm volatile("icbi 0, %0" : : "r"(Line));
150 asm volatile("isync");
151 # elif defined(__arm__) && defined(__GNUC__)
152 // FIXME: Can we safely always call this for __GNUC__ everywhere?
153 const char *Start = static_cast<const char *>(Addr);
154 const char *End = Start + Len;
155 __clear_cache(const_cast<char *>(Start), const_cast<char *>(End));
156 # elif defined(__mips__)
157 const char *Start = static_cast<const char *>(Addr);
158 cacheflush(const_cast<char *>(Start), Len, BCACHE);
164 void LLIChildTarget::releaseMemory(uint64_t Addr, uint32_t Size) {
165 ::munmap((void*)Addr, Size);