1259698Sdim//=- RemoteTargetExternal.inc - LLVM out-of-process JIT execution for Unix --=// 2259698Sdim// 3259698Sdim// The LLVM Compiler Infrastructure 4259698Sdim// 5259698Sdim// This file is distributed under the University of Illinois Open Source 6259698Sdim// License. See LICENSE.TXT for details. 7259698Sdim// 8259698Sdim//===----------------------------------------------------------------------===// 9259698Sdim// 10259698Sdim// Implementation of the Unix-specific parts of the RemoteTargetExternal class 11259698Sdim// which executes JITed code in a separate process from where it was built. 12259698Sdim// 13259698Sdim//===----------------------------------------------------------------------===// 14259698Sdim 15259698Sdim#include <unistd.h> 16259698Sdim#include <stdio.h> 17259698Sdim#include <stdlib.h> 18259698Sdim#include <sys/wait.h> 19259698Sdim 20259698Sdimnamespace { 21259698Sdim 22259698Sdimstruct ConnectionData_t { 23259698Sdim int InputPipe; 24259698Sdim int OutputPipe; 25259698Sdim 26259698Sdim ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {} 27259698Sdim}; 28259698Sdim 29259698Sdim} // namespace 30259698Sdim 31259698Sdimnamespace llvm { 32259698Sdim 33259698Sdimvoid RemoteTargetExternal::create() { 34259698Sdim int PipeFD[2][2]; 35259698Sdim pid_t ChildPID; 36259698Sdim 37259698Sdim // Create two pipes. 38259698Sdim if (pipe(PipeFD[0]) != 0 || pipe(PipeFD[1]) != 0) 39259698Sdim perror("Error creating pipe: "); 40259698Sdim 41259698Sdim ChildPID = fork(); 42259698Sdim 43259698Sdim if (ChildPID == 0) { 44259698Sdim // In the child... 45259698Sdim 46259698Sdim // Close the parent ends of the pipes 47259698Sdim close(PipeFD[0][1]); 48259698Sdim close(PipeFD[1][0]); 49259698Sdim 50259698Sdim // Use our pipes as stdin and stdout 51259698Sdim if (PipeFD[0][0] != STDIN_FILENO) { 52259698Sdim dup2(PipeFD[0][0], STDIN_FILENO); 53259698Sdim close(PipeFD[0][0]); 54259698Sdim } 55259698Sdim if (PipeFD[1][1] != STDOUT_FILENO) { 56259698Sdim dup2(PipeFD[1][1], STDOUT_FILENO); 57259698Sdim close(PipeFD[1][1]); 58259698Sdim } 59259698Sdim 60259698Sdim // Execute the child process. 61259698Sdim char *args[1] = { NULL }; 62259698Sdim int rc = execv(ChildName.c_str(), args); 63259698Sdim if (rc != 0) 64259698Sdim perror("Error executing child process: "); 65259698Sdim } 66259698Sdim else { 67259698Sdim // In the parent... 68259698Sdim 69259698Sdim // Close the child ends of the pipes 70259698Sdim close(PipeFD[0][0]); 71259698Sdim close(PipeFD[1][1]); 72259698Sdim 73259698Sdim // Store the parent ends of the pipes 74259698Sdim ConnectionData = (void*)new ConnectionData_t(PipeFD[1][0], PipeFD[0][1]); 75259698Sdim 76259698Sdim Receive(LLI_ChildActive); 77259698Sdim } 78259698Sdim} 79259698Sdim 80259698Sdimint RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) { 81259698Sdim return write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size); 82259698Sdim} 83259698Sdim 84259698Sdimint RemoteTargetExternal::ReadBytes(void *Data, size_t Size) { 85259698Sdim return read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size); 86259698Sdim} 87259698Sdim 88259698Sdimvoid RemoteTargetExternal::Wait() { 89259698Sdim wait(NULL); 90259698Sdim} 91259698Sdim 92259698SdimRemoteTargetExternal::~RemoteTargetExternal() { 93259698Sdim delete static_cast<ConnectionData_t *>(ConnectionData); 94259698Sdim} 95259698Sdim 96259698Sdim} // namespace llvm 97