18#include "llvm/ADT/StringExtras.h"
19#include "llvm/ExecutionEngine/ExecutionEngine.h"
20#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
21#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h"
22#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
23#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
24#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
25#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
26#include "llvm/ExecutionEngine/Orc/LLJIT.h"
27#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
28#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
29#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
30#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
31#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
32#include "llvm/ExecutionEngine/SectionMemoryManager.h"
33#include "llvm/IR/Module.h"
34#include "llvm/Support/FileSystem.h"
35#include "llvm/Support/ManagedStatic.h"
36#include "llvm/Support/Path.h"
37#include "llvm/Support/TargetSelect.h"
38#include "llvm/TargetParser/Host.h"
42#include <netinet/in.h>
43#include <sys/socket.h>
49 llvm::errs() << (
void *)&llvm_orc_registerJITLoaderGDBAllocAction;
58 llvm::orc::JITTargetMachineBuilder JTMB) {
59 auto JITBuilder = std::make_unique<llvm::orc::LLJITBuilder>();
60 JITBuilder->setJITTargetMachineBuilder(std::move(JTMB));
61 JITBuilder->setPrePlatformSetup([](llvm::orc::LLJIT &J) {
64 consumeError(llvm::orc::enableDebuggerSupport(J));
65 return llvm::Error::success();
67 return std::move(JITBuilder);
71 llvm::orc::LLJITBuilder &JITBuilder,
74 : TSCtx(TSC), OutOfProcessChildPid(Config.ExecutorPID) {
76 llvm::ErrorAsOutParameter EAO(&Err);
78 if (
auto JitOrErr = JITBuilder.create())
79 Jit = std::move(*JitOrErr);
81 Err = JitOrErr.takeError();
89 llvm::orc::ResourceTrackerSP RT =
90 Jit->getMainJITDylib().createResourceTracker();
91 ResourceTrackers[&PTU] = RT;
93 return Jit->addIRModule(RT, {std::move(PTU.
TheModule), TSCtx});
98 llvm::orc::ResourceTrackerSP RT = std::move(ResourceTrackers[&PTU]);
100 return llvm::Error::success();
102 ResourceTrackers.erase(&PTU);
103 if (llvm::Error Err = RT->remove())
105 return llvm::Error::success();
111 return Jit->deinitialize(Jit->getMainJITDylib());
115 return Jit->initialize(Jit->getMainJITDylib());
122 auto SO = makeJITDylibSearchOrder({&Jit->getMainJITDylib(),
123 Jit->getPlatformJITDylib().get(),
124 Jit->getProcessSymbolsJITDylib().get()});
126 ExecutionSession &ES = Jit->getExecutionSession();
129 ES.lookup(SO, (NameKind ==
LinkerName) ? ES.intern(Name)
130 : Jit->mangleAndIntern(Name));
131 if (
auto Err = SymOrErr.takeError())
132 return std::move(Err);
133 return SymOrErr->getAddress();
138 unsigned SlabAllocateSize) {
139 llvm::orc::SharedMemoryMapper::SymbolAddrs SAs;
140 if (
auto Err = SREPC.getBootstrapSymbols(
142 llvm::orc::rt::ExecutorSharedMemoryMapperServiceInstanceName},
144 llvm::orc::rt::ExecutorSharedMemoryMapperServiceReserveWrapperName},
147 ExecutorSharedMemoryMapperServiceInitializeWrapperName},
150 ExecutorSharedMemoryMapperServiceDeinitializeWrapperName},
153 ExecutorSharedMemoryMapperServiceReleaseWrapperName}}))
154 return std::move(Err);
157 if (llvm::Triple(llvm::sys::getProcessTriple()).isOSWindows())
158 SlabSize = 1024 * 1024;
160 SlabSize = 1024 * 1024 * 1024;
162 if (SlabAllocateSize > 0)
163 SlabSize = SlabAllocateSize;
165 return llvm::orc::MapperJITLinkMemoryManager::CreateWithMapper<
166 llvm::orc::SharedMemoryMapper>(SlabSize, SREPC, SAs);
171 bool UseSharedMemory,
172 unsigned SlabAllocateSize,
176 return llvm::make_error<llvm::StringError>(
177 "-" + ExecutablePath +
" not supported on non-unix platforms",
178 llvm::inconvertibleErrorCode());
179#elif !LLVM_ENABLE_THREADS
181 return llvm::make_error<llvm::StringError>(
182 "-" + ExecutablePath +
183 " requires threads, but LLVM was built with "
184 "LLVM_ENABLE_THREADS=Off",
185 llvm::inconvertibleErrorCode());
188 if (!llvm::sys::fs::can_execute(ExecutablePath))
189 return llvm::make_error<llvm::StringError>(
190 llvm::formatv(
"Specified executor invalid: {0}", ExecutablePath),
191 llvm::inconvertibleErrorCode());
193 constexpr int ReadEnd = 0;
194 constexpr int WriteEnd = 1;
203 if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0)
204 return llvm::make_error<llvm::StringError>(
205 "Unable to create pipe for executor", llvm::inconvertibleErrorCode());
213 close(ToExecutor[WriteEnd]);
214 close(FromExecutor[ReadEnd]);
220 std::unique_ptr<char[]> ExecutorPath, FDSpecifier;
222 ExecutorPath = std::make_unique<char[]>(ExecutablePath.size() + 1);
223 strcpy(ExecutorPath.get(), ExecutablePath.data());
225 std::string FDSpecifierStr(
"filedescs=");
226 FDSpecifierStr += llvm::utostr(ToExecutor[ReadEnd]);
227 FDSpecifierStr +=
',';
228 FDSpecifierStr += llvm::utostr(FromExecutor[WriteEnd]);
229 FDSpecifier = std::make_unique<char[]>(FDSpecifierStr.size() + 1);
230 strcpy(FDSpecifier.get(), FDSpecifierStr.c_str());
233 char *
const Args[] = {ExecutorPath.get(), FDSpecifier.get(),
nullptr};
234 int RC = execvp(ExecutorPath.get(), Args);
236 llvm::errs() <<
"unable to launch out-of-process executor \""
237 << ExecutorPath.get() <<
"\"\n";
244 close(ToExecutor[ReadEnd]);
245 close(FromExecutor[WriteEnd]);
247 llvm::orc::SimpleRemoteEPC::Setup S = llvm::orc::SimpleRemoteEPC::Setup();
249 S.CreateMemoryManager =
250 [SlabAllocateSize](llvm::orc::SimpleRemoteEPC &EPC) {
255 llvm::orc::SimpleRemoteEPC::Create<llvm::orc::FDSimpleRemoteEPCTransport>(
256 std::make_unique<llvm::orc::DynamicThreadPoolTaskDispatcher>(
258 std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
260 return EPCOrErr.takeError();
261 return std::make_pair(std::move(*EPCOrErr), ChildPID);
265#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
268 std::string PortStr) {
271 Hints.ai_family = AF_INET;
272 Hints.ai_socktype = SOCK_STREAM;
273 Hints.ai_flags = AI_NUMERICSERV;
275 if (
int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI))
276 return llvm::make_error<llvm::StringError>(
277 llvm::formatv(
"address resolution failed ({0})", strerror(EC)),
278 llvm::inconvertibleErrorCode());
283 for (Server = AI; Server !=
nullptr; Server = Server->ai_next) {
286 if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0)
290 if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0)
299 if (Server ==
nullptr)
300 return llvm::make_error<llvm::StringError>(
"invalid hostname",
301 llvm::inconvertibleErrorCode());
307IncrementalExecutor::connectTCPSocket(llvm::StringRef NetworkAddress,
308 bool UseSharedMemory,
309 unsigned SlabAllocateSize) {
312 return llvm::make_error<llvm::StringError>(
313 "-" + NetworkAddress +
" not supported on non-unix platforms",
314 llvm::inconvertibleErrorCode());
315#elif !LLVM_ENABLE_THREADS
317 return llvm::make_error<llvm::StringError>(
318 "-" + NetworkAddress +
319 " requires threads, but LLVM was built with "
320 "LLVM_ENABLE_THREADS=Off",
321 llvm::inconvertibleErrorCode());
324 auto CreateErr = [NetworkAddress](Twine Details) {
325 return llvm::make_error<llvm::StringError>(
326 formatv(
"Failed to connect TCP socket '{0}': {1}", NetworkAddress,
328 llvm::inconvertibleErrorCode());
331 StringRef
Host, PortStr;
332 std::tie(Host, PortStr) = NetworkAddress.split(
':');
334 return CreateErr(
"Host name for -" + NetworkAddress +
" can not be empty");
336 return CreateErr(
"Port number in -" + NetworkAddress +
" can not be empty");
338 if (PortStr.getAsInteger(10, Port))
339 return CreateErr(
"Port number '" + PortStr +
"' is not a valid integer");
343 return SockFD.takeError();
345 llvm::orc::SimpleRemoteEPC::Setup S = llvm::orc::SimpleRemoteEPC::Setup();
347 S.CreateMemoryManager =
348 [SlabAllocateSize](llvm::orc::SimpleRemoteEPC &EPC) {
352 return llvm::orc::SimpleRemoteEPC::Create<
353 llvm::orc::FDSimpleRemoteEPCTransport>(
354 std::make_unique<llvm::orc::DynamicThreadPoolTaskDispatcher>(
356 std::move(S), *SockFD, *SockFD);
LLVM_ATTRIBUTE_USED void linkComponents()
Defines the clang::TargetOptions class.
static llvm::Expected< std::pair< std::unique_ptr< llvm::orc::SimpleRemoteEPC >, uint32_t > > launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory, unsigned SlabAllocateSize, std::function< void()> CustomizeFork=nullptr)
virtual llvm::Error runCtors() const
virtual llvm::Error addModule(PartialTranslationUnit &PTU)
virtual ~IncrementalExecutor()
virtual llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddress(llvm::StringRef Name, SymbolNameKind NameKind) const
static llvm::Expected< std::unique_ptr< llvm::orc::LLJITBuilder > > createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB)
virtual llvm::Error removeModule(PartialTranslationUnit &PTU)
IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC)
virtual llvm::Error cleanUp()
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
Expected< std::unique_ptr< llvm::jitlink::JITLinkMemoryManager > > createSharedMemoryManager(llvm::orc::SimpleRemoteEPC &SREPC, unsigned SlabAllocateSize)
int const char * function
The class keeps track of various objects created as part of processing incremental inputs.
std::unique_ptr< llvm::Module > TheModule
The llvm IR produced for the input.