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