clang 24.0.0git
IncrementalExecutor.cpp
Go to the documentation of this file.
1//===--- IncrementalExecutor.cpp - Incremental Execution --------*- 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//===----------------------------------------------------------------------===//
8//
9// This has the implementation of the base facilities for incremental execution.
10//
11//===----------------------------------------------------------------------===//
12
15#ifdef __EMSCRIPTEN__
16#include "Wasm.h"
17#endif // __EMSCRIPTEN__
18
20#include "clang/Config/config.h"
22#include "clang/Driver/Driver.h"
24
25#include "llvm/ADT/SmallString.h"
26#include "llvm/ADT/SmallVector.h"
27#include "llvm/ADT/StringRef.h"
28#include "llvm/ADT/Twine.h"
29
30#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
31#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
32#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h"
33#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
34#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
35#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
36#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
37#include "llvm/ExecutionEngine/Orc/LLJIT.h"
38#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
39#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
40#include "llvm/ExecutionEngine/Orc/SharedMemoryMapSPS.h"
41#include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h"
42
43#include "llvm/Support/Error.h"
44#include "llvm/Support/FileSystem.h"
45#include "llvm/Support/FormatVariadic.h"
46#include "llvm/Support/Path.h"
47#include "llvm/Support/raw_ostream.h"
48
49#include "llvm/TargetParser/Host.h"
50
51#include <array>
52#include <functional>
53#include <memory>
54#include <optional>
55#include <string>
56#include <utility>
57
58#ifdef LLVM_ON_UNIX
59#include <netdb.h>
60#include <netinet/in.h>
61#include <sys/socket.h>
62#include <unistd.h>
63#endif
64
65// Address of the host's emulated-TLS runtime entry point, or null if the host
66// cannot provide one. clang-repl's JIT always lowers thread_local to emulated
67// TLS (JITTargetMachineBuilder forces EmulatedTLS on), so JIT'd code references
68// __emutls_get_address on every target. That symbol lives in the compiler
69// runtime -- libgcc_s.so on a glibc toolchain, or the compiler-rt builtins
70// static archive on Darwin and on compiler-rt-rtlib toolchains. When it is only
71// in a static archive and nothing else references it, it is never linked in and
72// ORC's process-symbol lookup cannot resolve it. Referencing it here
73// force-links the archive member so it is present regardless of how the host
74// provides it. Defined if available at configure time
75// (CLANG_HAVE_EMUTLS_GET_ADDRESS). When unavailable, thread_locals instead rely
76// on process-symbol lookup.
77#if CLANG_HAVE_EMUTLS_GET_ADDRESS
78extern "C" void *__emutls_get_address(void *);
79static void *getEmuTLSGetAddressPtr() {
80 return reinterpret_cast<void *>(&__emutls_get_address);
81}
82#else
83static void *getEmuTLSGetAddressPtr() { return nullptr; }
84#endif
85
86namespace clang {
88
90createJITTargetMachineBuilder(const llvm::Triple &TT) {
91 if (TT.getTriple() == llvm::sys::getProcessTriple())
92 // This fails immediately if the target backend is not registered
93 return llvm::orc::JITTargetMachineBuilder::detectHost();
94
95 // If the target backend is not registered, LLJITBuilder::create() will fail
96 return llvm::orc::JITTargetMachineBuilder(TT);
97}
98
100createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB) {
101 auto JITBuilder = std::make_unique<llvm::orc::LLJITBuilder>();
102 JITBuilder->setJITTargetMachineBuilder(std::move(JTMB));
103 JITBuilder->setPrePlatformSetup([](llvm::orc::LLJIT &J) {
104 // Try to enable debugging of JIT'd code (only works with JITLink for
105 // ELF and MachO).
106 consumeError(llvm::orc::enableDebuggerSupport(J));
107 return llvm::Error::success();
108 });
109 return std::move(JITBuilder);
110}
111
113createSharedMemoryManager(llvm::orc::ExecutorProcessControl &EPC,
114 unsigned SlabAllocateSize) {
115 auto &ES = EPC.getExecutionSession();
116 auto B = llvm::orc::sps::createSharedMemoryMapBindings(ES);
117 if (!B)
118 return B.takeError();
119
120 size_t SlabSize;
121 if (llvm::Triple(llvm::sys::getProcessTriple()).isOSWindows())
122 SlabSize = 1024 * 1024;
123 else
124 SlabSize = 1024 * 1024 * 1024;
125
126 if (SlabAllocateSize > 0)
127 SlabSize = SlabAllocateSize;
128
129 return llvm::orc::MapperJITLinkMemoryManager::CreateWithMapper<
130 llvm::orc::SharedMemoryMapper>(SlabSize, ES, std::move(*B));
131}
132
133static llvm::Expected<
134 std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, uint32_t>>
135launchExecutor(llvm::StringRef ExecutablePath,
136 std::function<void()> CustomizeFork) {
137#ifndef LLVM_ON_UNIX
138 // FIXME: Add support for Windows.
139 return llvm::make_error<llvm::StringError>(
140 "-" + ExecutablePath + " not supported on non-unix platforms",
141 llvm::inconvertibleErrorCode());
142#elif !LLVM_ENABLE_THREADS
143 // Out of process mode using SimpleRemoteEPC depends on threads.
144 return llvm::make_error<llvm::StringError>(
145 "-" + ExecutablePath +
146 " requires threads, but LLVM was built with "
147 "LLVM_ENABLE_THREADS=Off",
148 llvm::inconvertibleErrorCode());
149#else
150
151 if (!llvm::sys::fs::can_execute(ExecutablePath))
152 return llvm::make_error<llvm::StringError>(
153 llvm::formatv("Specified executor invalid: {0}", ExecutablePath),
154 llvm::inconvertibleErrorCode());
155
156 constexpr int ReadEnd = 0;
157 constexpr int WriteEnd = 1;
158
159 // Pipe FDs.
160 int ToExecutor[2];
161 int FromExecutor[2];
162
163 uint32_t ChildPID;
164
165 // Create pipes to/from the executor..
166 if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0)
167 return llvm::make_error<llvm::StringError>(
168 "Unable to create pipe for executor", llvm::inconvertibleErrorCode());
169
170 ChildPID = fork();
171
172 if (ChildPID == 0) {
173 // In the child...
174
175 // Close the parent ends of the pipes
176 close(ToExecutor[WriteEnd]);
177 close(FromExecutor[ReadEnd]);
178
179 if (CustomizeFork)
180 CustomizeFork();
181
182 // Execute the child process.
183 std::unique_ptr<char[]> ExecutorPath, FDSpecifier;
184 {
185 ExecutorPath = std::make_unique<char[]>(ExecutablePath.size() + 1);
186 strcpy(ExecutorPath.get(), ExecutablePath.data());
187
188 std::string FDSpecifierStr("filedescs=");
189 FDSpecifierStr += llvm::utostr(ToExecutor[ReadEnd]);
190 FDSpecifierStr += ',';
191 FDSpecifierStr += llvm::utostr(FromExecutor[WriteEnd]);
192 FDSpecifier = std::make_unique<char[]>(FDSpecifierStr.size() + 1);
193 strcpy(FDSpecifier.get(), FDSpecifierStr.c_str());
194 }
195
196 char *const Args[] = {ExecutorPath.get(), FDSpecifier.get(), nullptr};
197 int RC = execvp(ExecutorPath.get(), Args);
198 if (RC != 0) {
199 llvm::errs() << "unable to launch out-of-process executor \""
200 << ExecutorPath.get() << "\"\n";
201 exit(1);
202 }
203 }
204 // else we're the parent...
205
206 // Close the child ends of the pipes
207 close(ToExecutor[ReadEnd]);
208 close(FromExecutor[WriteEnd]);
209
210 auto EPCOrErr =
211 llvm::orc::SimpleRemoteEPC::Create<llvm::orc::FDSimpleRemoteEPCTransport>(
212 std::make_unique<llvm::orc::DynamicThreadPoolTaskDispatcher>(
213 std::nullopt),
214 FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
215 if (!EPCOrErr)
216 return EPCOrErr.takeError();
217 return std::make_pair(std::move(*EPCOrErr), ChildPID);
218#endif
219}
220
221#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
222
223static Expected<int> connectTCPSocketImpl(std::string Host,
224 std::string PortStr) {
225 addrinfo *AI;
226 addrinfo Hints{};
227 Hints.ai_family = AF_INET;
228 Hints.ai_socktype = SOCK_STREAM;
229 Hints.ai_flags = AI_NUMERICSERV;
230
231 if (int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI))
232 return llvm::make_error<llvm::StringError>(
233 llvm::formatv("address resolution failed ({0})", strerror(EC)),
234 llvm::inconvertibleErrorCode());
235 // Cycle through the returned addrinfo structures and connect to the first
236 // reachable endpoint.
237 int SockFD;
238 addrinfo *Server;
239 for (Server = AI; Server != nullptr; Server = Server->ai_next) {
240 // socket might fail, e.g. if the address family is not supported. Skip to
241 // the next addrinfo structure in such a case.
242 if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0)
243 continue;
244
245 // If connect returns null, we exit the loop with a working socket.
246 if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0)
247 break;
248
249 close(SockFD);
250 }
251 freeaddrinfo(AI);
252
253 // If we reached the end of the loop without connecting to a valid endpoint,
254 // dump the last error that was logged in socket() or connect().
255 if (Server == nullptr)
256 return llvm::make_error<llvm::StringError>("invalid hostname",
257 llvm::inconvertibleErrorCode());
258
259 return SockFD;
260}
261
263connectTCPSocket(llvm::StringRef NetworkAddress) {
264#ifndef LLVM_ON_UNIX
265 // FIXME: Add TCP support for Windows.
266 return llvm::make_error<llvm::StringError>(
267 "-" + NetworkAddress + " not supported on non-unix platforms",
268 llvm::inconvertibleErrorCode());
269#elif !LLVM_ENABLE_THREADS
270 // Out of process mode using SimpleRemoteEPC depends on threads.
271 return llvm::make_error<llvm::StringError>(
272 "-" + NetworkAddress +
273 " requires threads, but LLVM was built with "
274 "LLVM_ENABLE_THREADS=Off",
275 llvm::inconvertibleErrorCode());
276#else
277
278 auto CreateErr = [NetworkAddress](Twine Details) {
279 return llvm::make_error<llvm::StringError>(
280 formatv("Failed to connect TCP socket '{0}': {1}", NetworkAddress,
281 Details),
282 llvm::inconvertibleErrorCode());
283 };
284
285 StringRef Host, PortStr;
286 std::tie(Host, PortStr) = NetworkAddress.split(':');
287 if (Host.empty())
288 return CreateErr("Host name for -" + NetworkAddress + " can not be empty");
289 if (PortStr.empty())
290 return CreateErr("Port number in -" + NetworkAddress + " can not be empty");
291 int Port = 0;
292 if (PortStr.getAsInteger(10, Port))
293 return CreateErr("Port number '" + PortStr + "' is not a valid integer");
294
295 Expected<int> SockFD = connectTCPSocketImpl(Host.str(), PortStr.str());
296 if (!SockFD)
297 return SockFD.takeError();
298
299 return llvm::orc::SimpleRemoteEPC::Create<
300 llvm::orc::FDSimpleRemoteEPCTransport>(
301 std::make_unique<llvm::orc::DynamicThreadPoolTaskDispatcher>(
302 std::nullopt),
303 *SockFD, *SockFD);
304#endif
305}
306#endif // _WIN32
307
309createLLJITBuilder(std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC,
310 llvm::StringRef OrcRuntimePath) {
311 auto JTMB = createJITTargetMachineBuilder(EPC->getTargetTriple());
312 if (!JTMB)
313 return JTMB.takeError();
314 auto JB = createDefaultJITBuilder(std::move(*JTMB));
315 if (!JB)
316 return JB.takeError();
317
318 (*JB)->setExecutorProcessControl(std::move(EPC));
319 (*JB)->setPlatformSetUp(
320 llvm::orc::ExecutorNativePlatform(OrcRuntimePath.str()));
321
322 return std::move(*JB);
323}
324
325static llvm::Expected<
326 std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, uint32_t>>
328 std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
329 uint32_t childPid = -1;
330 if (!IncrExecutorBuilder.OOPExecutor.empty()) {
331 // Launch an out-of-process executor locally in a child process.
332 auto ResultOrErr = launchExecutor(IncrExecutorBuilder.OOPExecutor,
333 IncrExecutorBuilder.CustomizeFork);
334 if (!ResultOrErr)
335 return ResultOrErr.takeError();
336 childPid = ResultOrErr->second;
337 auto EPCOrErr = std::move(ResultOrErr->first);
338 EPC = std::move(EPCOrErr);
339 } else if (IncrExecutorBuilder.OOPExecutorConnect != "") {
340#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
341 auto EPCOrErr = connectTCPSocket(IncrExecutorBuilder.OOPExecutorConnect);
342 if (!EPCOrErr)
343 return EPCOrErr.takeError();
344 EPC = std::move(*EPCOrErr);
345#else
346 return llvm::make_error<llvm::StringError>(
347 "Out-of-process JIT over TCP is not supported on this platform",
348 std::error_code());
349#endif
350 }
351
352 std::unique_ptr<llvm::orc::LLJITBuilder> JB;
353 if (EPC) {
354 auto JBOrErr =
355 createLLJITBuilder(std::move(EPC), IncrExecutorBuilder.OrcRuntimePath);
356 if (!JBOrErr)
357 return JBOrErr.takeError();
358 JB = std::move(*JBOrErr);
359
360 if (IncrExecutorBuilder.UseSharedMemory)
361 JB->setMemoryManagerCreator(
362 [SlabAllocateSize = IncrExecutorBuilder.SlabAllocateSize](
363 llvm::orc::ExecutionSession &ES) {
364 return createSharedMemoryManager(ES.getExecutorProcessControl(),
365 SlabAllocateSize);
366 });
367 }
368
369 return std::make_pair(std::move(JB), childPid);
370}
371
373IncrementalExecutorBuilder::create(llvm::orc::ThreadSafeContext &TSC,
374 const clang::TargetInfo &TI) {
375 if (IE)
376 return std::move(IE);
377 llvm::Triple TT = TI.getTriple();
378 if (!TT.isOSWindows() && IsOutOfProcess) {
379 if (!JITBuilder) {
380 auto ResOrErr = outOfProcessJITBuilder(*this);
381 if (!ResOrErr)
382 return ResOrErr.takeError();
383 JITBuilder = std::move(ResOrErr->first);
384 ExecutorPID = ResOrErr->second;
385 }
386 if (!JITBuilder)
387 return llvm::make_error<llvm::StringError>(
388 "Operation failed. No LLJITBuilder for out-of-process JIT",
389 std::error_code());
390 }
391
392 if (!JITBuilder) {
393 auto JTMB = createJITTargetMachineBuilder(TT);
394 if (!JTMB)
395 return JTMB.takeError();
396 if (CM)
397 JTMB->setCodeModel(CM);
398 auto JB = createDefaultJITBuilder(std::move(*JTMB));
399 if (!JB)
400 return JB.takeError();
401 JITBuilder = std::move(*JB);
402 // TODO: Switch to native TLS once clang-repl can adopt the ORC runtime
403 // (which provides __emutls_get_address and supports the full TLS
404 // lifecycle). That will also remove the in-process-only constraint below.
405 //
406 // clang-repl lowers thread_local to emulated TLS on every target (see
407 // JITTargetMachineBuilder), so JIT'd code calls __emutls_get_address. When
408 // the host cannot resolve that symbol through process-symbol lookup
409 // (Darwin, and ELF toolchains that link compiler-rt builtins rather than
410 // libgcc_s), define the force-linked host symbol (see
411 // getEmuTLSGetAddressPtr) as an absolute symbol so it is visible to JIT'd
412 // code. This is harmless where process-symbol lookup would already resolve
413 // it: an already-defined symbol shadows the process-symbols generator.
414 // In-process execution only -- the host address is meaningless in an
415 // out-of-process executor.
416 if (void *EmuTLSGetAddress = getEmuTLSGetAddressPtr())
417 JITBuilder->setNotifyCreatedCallback(
418 [EmuTLSGetAddress](llvm::orc::LLJIT &J) {
419 auto &JD = J.getProcessSymbolsJITDylib()
420 ? *J.getProcessSymbolsJITDylib()
421 : J.getMainJITDylib();
422 return JD.define(llvm::orc::absoluteSymbols(
423 {{J.mangleAndIntern("__emutls_get_address"),
424 {llvm::orc::ExecutorAddr::fromPtr(EmuTLSGetAddress),
425 llvm::JITSymbolFlags::Exported}}}));
426 });
427 }
428
429 llvm::Error Err = llvm::Error::success();
430 std::unique_ptr<IncrementalExecutor> Executor;
431#ifdef __EMSCRIPTEN__
432 Executor = std::make_unique<WasmIncrementalExecutor>(Err);
433#else
434 Executor = std::make_unique<OrcIncrementalExecutor>(TSC, *JITBuilder, Err);
435#endif
436
437 if (Err)
438 return std::move(Err);
439
440 return std::move(Executor);
441}
442
443llvm::Error IncrementalExecutorBuilder::UpdateOrcRuntimePath(
445 if (!IsOutOfProcess)
446 return llvm::Error::success();
447
448 const clang::driver::Driver &D = C.getDriver();
449 const clang::driver::ToolChain &TC = C.getDefaultToolChain();
450
452
453 // Get canonical compiler-rt path
454 std::string CompilerRTPath = TC.getCompilerRT(C.getArgs(), "orc_rt");
455 llvm::StringRef CanonicalFilename = llvm::sys::path::filename(CompilerRTPath);
456
457 if (CanonicalFilename.empty()) {
458 return llvm::make_error<llvm::StringError>(
459 "Could not determine OrcRuntime filename from ToolChain",
460 llvm::inconvertibleErrorCode());
461 }
462
463 OrcRTLibNames.push_back(CanonicalFilename.str());
464
465 // Derive legacy spelling (libclang_rt.orc_rt -> orc_rt)
466 llvm::StringRef LegacySuffix = CanonicalFilename;
467 if (LegacySuffix.consume_front("libclang_rt.")) {
468 OrcRTLibNames.push_back(("lib" + LegacySuffix).str());
469 }
470
471 // Extract directory
472 llvm::SmallString<256> OrcRTDir(CompilerRTPath);
473 llvm::sys::path::remove_filename(OrcRTDir);
474
475 llvm::SmallVector<std::string, 8> triedPaths;
476
477 auto findInDir = [&](llvm::StringRef Dir) -> std::optional<std::string> {
478 for (const auto &LibName : OrcRTLibNames) {
479 llvm::SmallString<256> FullPath = Dir;
480 llvm::sys::path::append(FullPath, LibName);
481 if (llvm::sys::fs::exists(FullPath))
482 return std::string(FullPath.str());
483 triedPaths.push_back(std::string(FullPath.str()));
484 }
485 return std::nullopt;
486 };
487
488 // Try the primary directory first
489 if (auto Found = findInDir(OrcRTDir)) {
491 return llvm::Error::success();
492 }
493
494 // We want to find the relative path from the Driver to the OrcRTDir
495 // to replicate that structure elsewhere if needed.
496 llvm::StringRef Rel = OrcRTDir.str();
497 if (!Rel.consume_front(llvm::sys::path::parent_path(D.Dir))) {
498 return llvm::make_error<llvm::StringError>(
499 llvm::formatv("OrcRuntime library path ({0}) is not located within the "
500 "Clang resource directory ({1}). Check your installation "
501 "or provide an explicit path via -resource-dir.",
502 OrcRTDir, D.Dir)
503 .str(),
504 llvm::inconvertibleErrorCode());
505 }
506
507 // Generic Backward Search (Climbing the tree)
508 // This is useful for unit tests or relocated toolchains
509 llvm::SmallString<256> Cursor(D.Dir); // Start from the driver directory
510 while (llvm::sys::path::has_parent_path(Cursor)) {
511 Cursor = llvm::sys::path::parent_path(Cursor).str();
512 llvm::SmallString<256> Candidate = Cursor;
513 llvm::sys::path::append(Candidate, Rel);
514
515 if (auto Found = findInDir(Candidate)) {
517 return llvm::Error::success();
518 }
519
520 // Safety check
521 if (triedPaths.size() > 32)
522 break;
523 }
524
525 // Build a helpful error string
526 std::string Joined;
527 for (size_t i = 0; i < triedPaths.size(); ++i) {
528 if (i > 0)
529 Joined += "\n ";
530 Joined += triedPaths[i];
531 }
532
533 return llvm::make_error<llvm::StringError>(
534 llvm::formatv("OrcRuntime library not found. Checked: {0}",
535 Joined.empty() ? "<none>" : Joined)
536 .str(),
537 std::make_error_code(std::errc::no_such_file_or_directory));
538}
539
540} // end namespace clang
static void * getEmuTLSGetAddressPtr()
std::optional< llvm::CodeModel::Model > CM
An optional code model to provide to the JITTargetMachineBuilder.
bool IsOutOfProcess
Indicates whether out-of-process JIT execution is enabled.
std::unique_ptr< IncrementalExecutor > IE
An optional external IncrementalExecutor.
std::function< void()> CustomizeFork
Custom lambda to be executed inside child process/executor.
std::string OOPExecutor
Path to the out-of-process JIT executor.
uint32_t ExecutorPID
PID of the out-of-process JIT executor.
bool UseSharedMemory
Indicates whether to use shared memory for communication.
llvm::Expected< std::unique_ptr< IncrementalExecutor > > create(llvm::orc::ThreadSafeContext &TSC, const clang::TargetInfo &TI)
std::string OrcRuntimePath
Path to the ORC runtime library.
std::unique_ptr< llvm::orc::LLJITBuilder > JITBuilder
An optional external orc jit builder.
unsigned SlabAllocateSize
Representing the slab allocation size for memory management in kb.
Exposes information about the current target.
Definition TargetInfo.h:226
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Compilation - A set of tasks to perform for a single driver invocation.
Definition Compilation.h:46
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition Driver.h:93
std::string Dir
The path the driver executable was in, as invoked from the command line.
Definition Driver.h:168
ToolChain - Access to tools for a single platform.
Definition ToolChain.h:92
virtual std::string getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component, FileType Type=ToolChain::FT_Static, bool IsFortran=false) const
Defines the clang::TargetInfo interface.
Top level wrappers for InstallAPI frontend operations.
static llvm::Expected< std::unique_ptr< llvm::orc::LLJITBuilder > > createLLJITBuilder(std::unique_ptr< llvm::orc::ExecutorProcessControl > EPC, llvm::StringRef OrcRuntimePath)
static llvm::Expected< std::unique_ptr< llvm::orc::LLJITBuilder > > createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB)
static llvm::Expected< std::pair< std::unique_ptr< llvm::orc::LLJITBuilder >, uint32_t > > outOfProcessJITBuilder(const IncrementalExecutorBuilder &IncrExecutorBuilder)
static llvm::Expected< std::pair< std::unique_ptr< llvm::orc::SimpleRemoteEPC >, uint32_t > > launchExecutor(llvm::StringRef ExecutablePath, std::function< void()> CustomizeFork)
static llvm::Expected< llvm::orc::JITTargetMachineBuilder > createJITTargetMachineBuilder(const llvm::Triple &TT)
Expected< std::unique_ptr< llvm::jitlink::JITLinkMemoryManager > > createSharedMemoryManager(llvm::orc::ExecutorProcessControl &EPC, unsigned SlabAllocateSize)
int const char * function
Definition c++config.h:31
__builtin_elementwise_add_sat __builtin_elementwise_sub_sat uint32_t __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t