24#include "llvm/ADT/SmallString.h"
25#include "llvm/ADT/SmallVector.h"
26#include "llvm/ADT/StringRef.h"
27#include "llvm/ADT/Twine.h"
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"
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"
48#include "llvm/TargetParser/Host.h"
59#include <netinet/in.h>
60#include <sys/socket.h>
78#if defined(LLVM_ON_UNIX) && !defined(__EMSCRIPTEN__) && !defined(_AIX) && \
79 !defined(__MVS__) && !defined(__FreeBSD__)
80extern "C" void *__emutls_get_address(
void *);
82 return reinterpret_cast<void *
>(&__emutls_get_address);
93 if (TT.getTriple() == llvm::sys::getProcessTriple())
95 return llvm::orc::JITTargetMachineBuilder::detectHost();
98 return llvm::orc::JITTargetMachineBuilder(TT);
103 auto JITBuilder = std::make_unique<llvm::orc::LLJITBuilder>();
104 JITBuilder->setJITTargetMachineBuilder(std::move(JTMB));
105 JITBuilder->setPrePlatformSetup([](llvm::orc::LLJIT &J) {
108 consumeError(llvm::orc::enableDebuggerSupport(J));
109 return llvm::Error::success();
111 return std::move(JITBuilder);
116 unsigned SlabAllocateSize) {
117 llvm::orc::SharedMemoryMapper::SymbolAddrs SAs;
118 if (
auto Err = EPC.getBootstrapSymbols(
120 llvm::orc::rt::ExecutorSharedMemoryMapperServiceInstanceName},
122 llvm::orc::rt::ExecutorSharedMemoryMapperServiceReserveWrapperName},
125 ExecutorSharedMemoryMapperServiceInitializeWrapperName},
128 ExecutorSharedMemoryMapperServiceDeinitializeWrapperName},
131 ExecutorSharedMemoryMapperServiceReleaseWrapperName}}))
132 return std::move(Err);
135 if (llvm::Triple(llvm::sys::getProcessTriple()).isOSWindows())
136 SlabSize = 1024 * 1024;
138 SlabSize = 1024 * 1024 * 1024;
140 if (SlabAllocateSize > 0)
141 SlabSize = SlabAllocateSize;
143 return llvm::orc::MapperJITLinkMemoryManager::CreateWithMapper<
144 llvm::orc::SharedMemoryMapper>(SlabSize, EPC, SAs);
148 std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>,
uint32_t>>
153 return llvm::make_error<llvm::StringError>(
154 "-" + ExecutablePath +
" not supported on non-unix platforms",
155 llvm::inconvertibleErrorCode());
156#elif !LLVM_ENABLE_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());
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());
170 constexpr int ReadEnd = 0;
171 constexpr int WriteEnd = 1;
180 if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0)
181 return llvm::make_error<llvm::StringError>(
182 "Unable to create pipe for executor", llvm::inconvertibleErrorCode());
190 close(ToExecutor[WriteEnd]);
191 close(FromExecutor[ReadEnd]);
197 std::unique_ptr<char[]> ExecutorPath, FDSpecifier;
199 ExecutorPath = std::make_unique<char[]>(ExecutablePath.size() + 1);
200 strcpy(ExecutorPath.get(), ExecutablePath.data());
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());
210 char *
const Args[] = {ExecutorPath.get(), FDSpecifier.get(),
nullptr};
211 int RC = execvp(ExecutorPath.get(), Args);
213 llvm::errs() <<
"unable to launch out-of-process executor \""
214 << ExecutorPath.get() <<
"\"\n";
221 close(ToExecutor[ReadEnd]);
222 close(FromExecutor[WriteEnd]);
225 llvm::orc::SimpleRemoteEPC::Create<llvm::orc::FDSimpleRemoteEPCTransport>(
226 std::make_unique<llvm::orc::DynamicThreadPoolTaskDispatcher>(
228 FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
230 return EPCOrErr.takeError();
231 return std::make_pair(std::move(*EPCOrErr), ChildPID);
235#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
238 std::string PortStr) {
241 Hints.ai_family = AF_INET;
242 Hints.ai_socktype = SOCK_STREAM;
243 Hints.ai_flags = AI_NUMERICSERV;
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());
253 for (Server = AI; Server !=
nullptr; Server = Server->ai_next) {
256 if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0)
260 if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0)
269 if (Server ==
nullptr)
270 return llvm::make_error<llvm::StringError>(
"invalid hostname",
271 llvm::inconvertibleErrorCode());
277connectTCPSocket(llvm::StringRef NetworkAddress) {
280 return llvm::make_error<llvm::StringError>(
281 "-" + NetworkAddress +
" not supported on non-unix platforms",
282 llvm::inconvertibleErrorCode());
283#elif !LLVM_ENABLE_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());
292 auto CreateErr = [NetworkAddress](Twine Details) {
293 return llvm::make_error<llvm::StringError>(
294 formatv(
"Failed to connect TCP socket '{0}': {1}", NetworkAddress,
296 llvm::inconvertibleErrorCode());
299 StringRef
Host, PortStr;
300 std::tie(Host, PortStr) = NetworkAddress.split(
':');
302 return CreateErr(
"Host name for -" + NetworkAddress +
" can not be empty");
304 return CreateErr(
"Port number in -" + NetworkAddress +
" can not be empty");
306 if (PortStr.getAsInteger(10, Port))
307 return CreateErr(
"Port number '" + PortStr +
"' is not a valid integer");
311 return SockFD.takeError();
313 return llvm::orc::SimpleRemoteEPC::Create<
314 llvm::orc::FDSimpleRemoteEPCTransport>(
315 std::make_unique<llvm::orc::DynamicThreadPoolTaskDispatcher>(
324 llvm::StringRef OrcRuntimePath) {
327 return JTMB.takeError();
330 return JB.takeError();
332 (*JB)->setExecutorProcessControl(std::move(EPC));
333 (*JB)->setPlatformSetUp(
334 llvm::orc::ExecutorNativePlatform(OrcRuntimePath.str()));
336 return std::move(*JB);
340 std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>,
uint32_t>>
342 std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
349 return ResultOrErr.takeError();
350 childPid = ResultOrErr->second;
351 auto EPCOrErr = std::move(ResultOrErr->first);
352 EPC = std::move(EPCOrErr);
354#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
357 return EPCOrErr.takeError();
358 EPC = std::move(*EPCOrErr);
360 return llvm::make_error<llvm::StringError>(
361 "Out-of-process JIT over TCP is not supported on this platform",
366 std::unique_ptr<llvm::orc::LLJITBuilder> JB;
371 return JBOrErr.takeError();
372 JB = std::move(*JBOrErr);
375 JB->setMemoryManagerCreator(
377 llvm::orc::ExecutionSession &ES) {
378 return createSharedMemoryManager(ES.getExecutorProcessControl(),
383 return std::make_pair(std::move(JB), childPid);
390 return std::move(
IE);
396 return ResOrErr.takeError();
401 return llvm::make_error<llvm::StringError>(
402 "Operation failed. No LLJITBuilder for out-of-process JIT",
409 return JTMB.takeError();
411 JTMB->setCodeModel(
CM);
414 return JB.takeError();
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}}}));
443 llvm::Error Err = llvm::Error::success();
444 std::unique_ptr<IncrementalExecutor> Executor;
446 Executor = std::make_unique<WasmIncrementalExecutor>(Err);
448 Executor = std::make_unique<OrcIncrementalExecutor>(TSC, *
JITBuilder, Err);
452 return std::move(Err);
454 return std::move(Executor);
457llvm::Error IncrementalExecutorBuilder::UpdateOrcRuntimePath(
460 return llvm::Error::success();
468 std::string CompilerRTPath = TC.
getCompilerRT(
C.getArgs(),
"orc_rt");
469 llvm::StringRef CanonicalFilename = llvm::sys::path::filename(CompilerRTPath);
471 if (CanonicalFilename.empty()) {
472 return llvm::make_error<llvm::StringError>(
473 "Could not determine OrcRuntime filename from ToolChain",
474 llvm::inconvertibleErrorCode());
477 OrcRTLibNames.push_back(CanonicalFilename.str());
480 llvm::StringRef LegacySuffix = CanonicalFilename;
481 if (LegacySuffix.consume_front(
"libclang_rt.")) {
482 OrcRTLibNames.push_back((
"lib" + LegacySuffix).str());
487 llvm::sys::path::remove_filename(OrcRTDir);
491 auto findInDir = [&](llvm::StringRef Dir) -> std::optional<std::string> {
492 for (
const auto &LibName : OrcRTLibNames) {
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()));
503 if (
auto Found = findInDir(OrcRTDir)) {
504 OrcRuntimePath = *
Found;
505 return llvm::Error::success();
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.",
518 llvm::inconvertibleErrorCode());
524 while (llvm::sys::path::has_parent_path(Cursor)) {
525 Cursor = llvm::sys::path::parent_path(Cursor).str();
527 llvm::sys::path::append(Candidate, Rel);
529 if (
auto Found = findInDir(Candidate)) {
530 OrcRuntimePath = *
Found;
531 return llvm::Error::success();
535 if (triedPaths.size() > 32)
541 for (
size_t i = 0; i < triedPaths.size(); ++i) {
544 Joined += triedPaths[i];
547 return llvm::make_error<llvm::StringError>(
548 llvm::formatv(
"OrcRuntime library not found. Checked: {0}",
549 Joined.empty() ?
"<none>" : Joined)
551 std::make_error_code(std::errc::no_such_file_or_directory));
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.
~IncrementalExecutorBuilder()
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.
std::string OOPExecutorConnect
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.
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.
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
std::string Dir
The path the driver executable was in, as invoked from the command line.
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
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t