Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / examples / OrcV2Examples / LLJITWithRemoteDebugging / RemoteJITUtils.cpp
blob49f5fcdbef8dfe5257b08f007782a1c68f723980
1 //===-- RemoteJITUtils.cpp - Utilities for remote-JITing --------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "RemoteJITUtils.h"
11 #include "llvm/ADT/StringExtras.h"
12 #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
13 #include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
14 #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
15 #include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
16 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
17 #include "llvm/Support/FileSystem.h"
18 #include "llvm/Support/Path.h"
20 #ifdef LLVM_ON_UNIX
21 #include <netdb.h>
22 #include <netinet/in.h>
23 #include <sys/socket.h>
24 #include <unistd.h>
25 #endif // LLVM_ON_UNIX
27 using namespace llvm;
28 using namespace llvm::orc;
30 Error addDebugSupport(ObjectLayer &ObjLayer) {
31 ExecutionSession &ES = ObjLayer.getExecutionSession();
32 auto Registrar = createJITLoaderGDBRegistrar(ES);
33 if (!Registrar)
34 return Registrar.takeError();
36 auto *ObjLinkingLayer = cast<ObjectLinkingLayer>(&ObjLayer);
37 if (!ObjLinkingLayer)
38 return createStringError(inconvertibleErrorCode(),
39 "No debug support for given object layer type");
41 ObjLinkingLayer->addPlugin(std::make_unique<DebugObjectManagerPlugin>(
42 ES, std::move(*Registrar), true, true));
43 return Error::success();
46 Expected<std::unique_ptr<DefinitionGenerator>>
47 loadDylib(ExecutionSession &ES, StringRef RemotePath) {
48 if (auto Handle = ES.getExecutorProcessControl().loadDylib(RemotePath.data()))
49 return std::make_unique<EPCDynamicLibrarySearchGenerator>(ES, *Handle);
50 else
51 return Handle.takeError();
54 static void findLocalExecutorHelper() {}
55 std::string findLocalExecutor(const char *HostArgv0) {
56 // This just needs to be some static symbol in the binary; C++ doesn't
57 // allow taking the address of ::main however.
58 uintptr_t UIntPtr = reinterpret_cast<uintptr_t>(&findLocalExecutorHelper);
59 void *VoidPtr = reinterpret_cast<void *>(UIntPtr);
60 SmallString<256> FullName(sys::fs::getMainExecutable(HostArgv0, VoidPtr));
61 sys::path::remove_filename(FullName);
62 sys::path::append(FullName, "llvm-jitlink-executor");
63 return FullName.str().str();
66 #ifndef LLVM_ON_UNIX
68 // FIXME: Add support for Windows.
69 Expected<std::pair<std::unique_ptr<SimpleRemoteEPC>, uint64_t>>
70 launchLocalExecutor(StringRef ExecutablePath) {
71 return make_error<StringError>(
72 "Remote JITing not yet supported on non-unix platforms",
73 inconvertibleErrorCode());
76 // FIXME: Add support for Windows.
77 Expected<std::unique_ptr<SimpleRemoteEPC>>
78 connectTCPSocket(StringRef NetworkAddress) {
79 return make_error<StringError>(
80 "Remote JITing not yet supported on non-unix platforms",
81 inconvertibleErrorCode());
84 #else
86 Expected<std::pair<std::unique_ptr<SimpleRemoteEPC>, uint64_t>>
87 launchLocalExecutor(StringRef ExecutablePath) {
88 constexpr int ReadEnd = 0;
89 constexpr int WriteEnd = 1;
91 if (!sys::fs::can_execute(ExecutablePath))
92 return make_error<StringError>(
93 formatv("Specified executor invalid: {0}", ExecutablePath),
94 inconvertibleErrorCode());
96 // Pipe FDs.
97 int ToExecutor[2];
98 int FromExecutor[2];
100 // Create pipes to/from the executor..
101 if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0)
102 return make_error<StringError>("Unable to create pipe for executor",
103 inconvertibleErrorCode());
105 pid_t ProcessID = fork();
106 if (ProcessID == 0) {
107 // In the child...
109 // Close the parent ends of the pipes
110 close(ToExecutor[WriteEnd]);
111 close(FromExecutor[ReadEnd]);
113 // Execute the child process.
114 std::unique_ptr<char[]> ExecPath, FDSpecifier;
116 ExecPath = std::make_unique<char[]>(ExecutablePath.size() + 1);
117 strcpy(ExecPath.get(), ExecutablePath.data());
119 std::string FDSpecifierStr("filedescs=");
120 FDSpecifierStr += utostr(ToExecutor[ReadEnd]);
121 FDSpecifierStr += ',';
122 FDSpecifierStr += utostr(FromExecutor[WriteEnd]);
123 FDSpecifier = std::make_unique<char[]>(FDSpecifierStr.size() + 1);
124 strcpy(FDSpecifier.get(), FDSpecifierStr.c_str());
127 char *const Args[] = {ExecPath.get(), FDSpecifier.get(), nullptr};
128 int RC = execvp(ExecPath.get(), Args);
129 if (RC != 0)
130 return make_error<StringError>(
131 "Unable to launch out-of-process executor '" + ExecutablePath + "'\n",
132 inconvertibleErrorCode());
134 llvm_unreachable("Fork won't return in success case");
136 // else we're the parent...
138 // Close the child ends of the pipes
139 close(ToExecutor[ReadEnd]);
140 close(FromExecutor[WriteEnd]);
142 auto EPC = SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
143 std::make_unique<DynamicThreadPoolTaskDispatcher>(),
144 SimpleRemoteEPC::Setup(),
145 FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
146 if (!EPC)
147 return EPC.takeError();
149 return std::make_pair(std::move(*EPC), static_cast<uint64_t>(ProcessID));
152 static Expected<int> connectTCPSocketImpl(std::string Host,
153 std::string PortStr) {
154 addrinfo *AI;
155 addrinfo Hints{};
156 Hints.ai_family = AF_INET;
157 Hints.ai_socktype = SOCK_STREAM;
158 Hints.ai_flags = AI_NUMERICSERV;
160 if (int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI))
161 return make_error<StringError>(
162 formatv("address resolution failed ({0})", gai_strerror(EC)),
163 inconvertibleErrorCode());
165 // Cycle through the returned addrinfo structures and connect to the first
166 // reachable endpoint.
167 int SockFD;
168 addrinfo *Server;
169 for (Server = AI; Server != nullptr; Server = Server->ai_next) {
170 // If socket fails, maybe it's because the address family is not supported.
171 // Skip to the next addrinfo structure.
172 if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0)
173 continue;
175 // If connect works, we exit the loop with a working socket.
176 if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0)
177 break;
179 close(SockFD);
181 freeaddrinfo(AI);
183 // Did we reach the end of the loop without connecting to a valid endpoint?
184 if (Server == nullptr)
185 return make_error<StringError>("invalid hostname",
186 inconvertibleErrorCode());
188 return SockFD;
191 Expected<std::unique_ptr<SimpleRemoteEPC>>
192 connectTCPSocket(StringRef NetworkAddress) {
193 auto CreateErr = [NetworkAddress](StringRef Details) {
194 return make_error<StringError>(
195 formatv("Failed to connect TCP socket '{0}': {1}", NetworkAddress,
196 Details),
197 inconvertibleErrorCode());
200 StringRef Host, PortStr;
201 std::tie(Host, PortStr) = NetworkAddress.split(':');
202 if (Host.empty())
203 return CreateErr("host name cannot be empty");
204 if (PortStr.empty())
205 return CreateErr("port cannot be empty");
206 int Port = 0;
207 if (PortStr.getAsInteger(10, Port))
208 return CreateErr("port number is not a valid integer");
210 Expected<int> SockFD = connectTCPSocketImpl(Host.str(), PortStr.str());
211 if (!SockFD)
212 return CreateErr(toString(SockFD.takeError()));
214 return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
215 std::make_unique<DynamicThreadPoolTaskDispatcher>(),
216 SimpleRemoteEPC::Setup(), *SockFD);
219 #endif