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