129 lines
3.9 KiB
C++
129 lines
3.9 KiB
C++
|
//===- llvm-jitlink-executor.cpp - Out-of-proc executor for llvm-jitlink -===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
//
|
||
|
// Simple out-of-process executor for llvm-jitlink.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#include "llvm/ADT/StringRef.h"
|
||
|
#include "llvm/ExecutionEngine/Orc/Shared/FDRawByteChannel.h"
|
||
|
#include "llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h"
|
||
|
#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
|
||
|
#include "llvm/Support/DynamicLibrary.h"
|
||
|
#include "llvm/Support/Error.h"
|
||
|
#include "llvm/Support/raw_ostream.h"
|
||
|
#include <sstream>
|
||
|
|
||
|
#ifdef LLVM_ON_UNIX
|
||
|
|
||
|
#include <netinet/in.h>
|
||
|
#include <sys/socket.h>
|
||
|
|
||
|
#endif
|
||
|
|
||
|
using namespace llvm;
|
||
|
using namespace llvm::orc;
|
||
|
|
||
|
ExitOnError ExitOnErr;
|
||
|
|
||
|
LLVM_ATTRIBUTE_USED void linkComponents() {
|
||
|
errs() << (void *)&llvm_orc_registerEHFrameSectionWrapper
|
||
|
<< (void *)&llvm_orc_deregisterEHFrameSectionWrapper;
|
||
|
}
|
||
|
|
||
|
void printErrorAndExit(Twine ErrMsg) {
|
||
|
errs() << "error: " << ErrMsg.str() << "\n\n"
|
||
|
<< "Usage:\n"
|
||
|
<< " llvm-jitlink-executor filedescs=<infd>,<outfd> [args...]\n"
|
||
|
<< " llvm-jitlink-executor listen=<host>:<port> [args...]\n";
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
int openListener(std::string Host, int Port) {
|
||
|
#ifndef LLVM_ON_UNIX
|
||
|
// FIXME: Add TCP support for Windows.
|
||
|
printErrorAndExit("listen option not supported");
|
||
|
return 0;
|
||
|
#else
|
||
|
int SockFD = socket(PF_INET, SOCK_STREAM, 0);
|
||
|
struct sockaddr_in ServerAddr, ClientAddr;
|
||
|
socklen_t ClientAddrLen = sizeof(ClientAddr);
|
||
|
memset(&ServerAddr, 0, sizeof(ServerAddr));
|
||
|
ServerAddr.sin_family = PF_INET;
|
||
|
ServerAddr.sin_family = INADDR_ANY;
|
||
|
ServerAddr.sin_port = htons(Port);
|
||
|
|
||
|
{
|
||
|
// lose the "Address already in use" error message
|
||
|
int Yes = 1;
|
||
|
if (setsockopt(SockFD, SOL_SOCKET, SO_REUSEADDR, &Yes, sizeof(int)) == -1) {
|
||
|
errs() << "Error calling setsockopt.\n";
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (bind(SockFD, (struct sockaddr *)&ServerAddr, sizeof(ServerAddr)) < 0) {
|
||
|
errs() << "Error on binding.\n";
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
listen(SockFD, 1);
|
||
|
return accept(SockFD, (struct sockaddr *)&ClientAddr, &ClientAddrLen);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int main(int argc, char *argv[]) {
|
||
|
|
||
|
ExitOnErr.setBanner(std::string(argv[0]) + ": ");
|
||
|
|
||
|
int InFD = 0;
|
||
|
int OutFD = 0;
|
||
|
|
||
|
if (argc < 2)
|
||
|
printErrorAndExit("insufficient arguments");
|
||
|
else {
|
||
|
StringRef Arg1 = argv[1];
|
||
|
StringRef SpecifierType, Specifier;
|
||
|
std::tie(SpecifierType, Specifier) = Arg1.split('=');
|
||
|
if (SpecifierType == "filedescs") {
|
||
|
StringRef FD1Str, FD2Str;
|
||
|
std::tie(FD1Str, FD2Str) = Specifier.split(',');
|
||
|
if (FD1Str.getAsInteger(10, InFD))
|
||
|
printErrorAndExit(FD1Str + " is not a valid file descriptor");
|
||
|
if (FD2Str.getAsInteger(10, OutFD))
|
||
|
printErrorAndExit(FD2Str + " is not a valid file descriptor");
|
||
|
} else if (SpecifierType == "listen") {
|
||
|
StringRef Host, PortStr;
|
||
|
std::tie(Host, PortStr) = Specifier.split(':');
|
||
|
|
||
|
int Port = 0;
|
||
|
if (PortStr.getAsInteger(10, Port))
|
||
|
printErrorAndExit("port" + PortStr + " is not a valid integer");
|
||
|
|
||
|
InFD = OutFD = openListener(Host.str(), Port);
|
||
|
} else
|
||
|
printErrorAndExit("invalid specifier type \"" + SpecifierType + "\"");
|
||
|
}
|
||
|
|
||
|
ExitOnErr.setBanner(std::string(argv[0]) + ":");
|
||
|
|
||
|
using JITLinkExecutorEndpoint =
|
||
|
shared::MultiThreadedRPCEndpoint<shared::FDRawByteChannel>;
|
||
|
|
||
|
shared::registerStringError<shared::FDRawByteChannel>();
|
||
|
|
||
|
shared::FDRawByteChannel C(InFD, OutFD);
|
||
|
JITLinkExecutorEndpoint EP(C, true);
|
||
|
OrcRPCTPCServer<JITLinkExecutorEndpoint> Server(EP);
|
||
|
Server.setProgramName(std::string("llvm-jitlink-executor"));
|
||
|
|
||
|
ExitOnErr(Server.run());
|
||
|
|
||
|
return 0;
|
||
|
}
|