aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp
blob: fd7e30ffea87cb1fb795e9948a9012f7fdf5f144 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//===- 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;
}