mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-16 14:31:59 +00:00
83ece7a499
MCJIT remote execution (ChildTarget+RemoteTargetExternal) protocol was in dire need of refactoring. It was fail-prone, had no error reporting and implemented the same message logic on every single function. This patch rectifies it, and makes it work on ARM, where it was randomly failing. Other architectures shall profit from this change as well, making their buildbots and releases more reliable. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199261 91177308-0d34-0410-b5e6-96231b3b80d8
134 lines
3.3 KiB
C++
134 lines
3.3 KiB
C++
//=- 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
namespace {
|
|
|
|
struct ConnectionData_t {
|
|
int InputPipe;
|
|
int OutputPipe;
|
|
|
|
ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
namespace llvm {
|
|
|
|
bool 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]);
|
|
|
|
// We must get Ack from the client (blocking read)
|
|
if (!Receive(LLI_ChildActive)) {
|
|
ErrorMsg += ", (RemoteTargetExternal::create) - Stopping process!";
|
|
stop();
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static void ReportError(int rc, size_t Size, std::string &ErrorMsg) {
|
|
if (rc == -1) {
|
|
if (errno == EPIPE)
|
|
ErrorMsg += "pipe closed";
|
|
else if (errno == EINTR)
|
|
ErrorMsg += "interrupted";
|
|
else
|
|
ErrorMsg += "file descriptor error";
|
|
} else {
|
|
char Number[10] = { 0 };
|
|
ErrorMsg += "Expecting ";
|
|
sprintf(Number, "%d", (uint32_t)Size);
|
|
ErrorMsg += Number;
|
|
ErrorMsg += " bytes, Got ";
|
|
sprintf(Number, "%d", rc);
|
|
ErrorMsg += Number;
|
|
}
|
|
}
|
|
|
|
bool RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) {
|
|
int rc = write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size);
|
|
if (rc != -1 && (size_t)rc == Size)
|
|
return true;
|
|
|
|
ErrorMsg = "WriteBytes: ";
|
|
ReportError(rc, Size, ErrorMsg);
|
|
return false;
|
|
}
|
|
|
|
bool RemoteTargetExternal::ReadBytes(void *Data, size_t Size) {
|
|
int rc = read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size);
|
|
if (rc != -1 && (size_t)rc == Size)
|
|
return true;
|
|
|
|
ErrorMsg = "ReadBytes: ";
|
|
ReportError(rc, Size, ErrorMsg);
|
|
return false;
|
|
}
|
|
|
|
void RemoteTargetExternal::Wait() {
|
|
wait(NULL);
|
|
}
|
|
|
|
RemoteTargetExternal::~RemoteTargetExternal() {
|
|
delete static_cast<ConnectionData_t *>(ConnectionData);
|
|
}
|
|
|
|
} // namespace llvm
|