1312 lines · cpp
1//===- lli.cpp - LLVM Interpreter / Dynamic compiler ----------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This utility provides a simple wrapper around the LLVM Execution Engines,10// which allow the direct execution of LLVM programs through a Just-In-Time11// compiler, or through an interpreter if no JIT is available for this platform.12//13//===----------------------------------------------------------------------===//14 15#include "ForwardingMemoryManager.h"16#include "llvm/ADT/StringExtras.h"17#include "llvm/Bitcode/BitcodeReader.h"18#include "llvm/CodeGen/CommandFlags.h"19#include "llvm/CodeGen/LinkAllCodegenComponents.h"20#include "llvm/Config/llvm-config.h"21#include "llvm/ExecutionEngine/GenericValue.h"22#include "llvm/ExecutionEngine/Interpreter.h"23#include "llvm/ExecutionEngine/JITEventListener.h"24#include "llvm/ExecutionEngine/JITSymbol.h"25#include "llvm/ExecutionEngine/MCJIT.h"26#include "llvm/ExecutionEngine/ObjectCache.h"27#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"28#include "llvm/ExecutionEngine/Orc/DebugUtils.h"29#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h"30#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"31#include "llvm/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.h"32#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"33#include "llvm/ExecutionEngine/Orc/IRPartitionLayer.h"34#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"35#include "llvm/ExecutionEngine/Orc/LLJIT.h"36#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"37#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"38#include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h"39#include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h"40#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"41#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"42#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"43#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"44#include "llvm/ExecutionEngine/SectionMemoryManager.h"45#include "llvm/IR/IRBuilder.h"46#include "llvm/IR/LLVMContext.h"47#include "llvm/IR/Module.h"48#include "llvm/IR/Type.h"49#include "llvm/IR/Verifier.h"50#include "llvm/IRReader/IRReader.h"51#include "llvm/Object/Archive.h"52#include "llvm/Object/ObjectFile.h"53#include "llvm/Support/CommandLine.h"54#include "llvm/Support/Compiler.h"55#include "llvm/Support/Debug.h"56#include "llvm/Support/DynamicLibrary.h"57#include "llvm/Support/Format.h"58#include "llvm/Support/InitLLVM.h"59#include "llvm/Support/MathExtras.h"60#include "llvm/Support/Memory.h"61#include "llvm/Support/MemoryBuffer.h"62#include "llvm/Support/Path.h"63#include "llvm/Support/PluginLoader.h"64#include "llvm/Support/Process.h"65#include "llvm/Support/Program.h"66#include "llvm/Support/SourceMgr.h"67#include "llvm/Support/TargetSelect.h"68#include "llvm/Support/ToolOutputFile.h"69#include "llvm/Support/WithColor.h"70#include "llvm/Support/raw_ostream.h"71#include "llvm/TargetParser/Triple.h"72#include <cerrno>73#include <optional>74 75#if !defined(_MSC_VER) && !defined(__MINGW32__)76#include <unistd.h>77#else78#include <io.h>79#endif80 81#ifdef __CYGWIN__82#include <cygwin/version.h>83#if defined(CYGWIN_VERSION_DLL_MAJOR) && CYGWIN_VERSION_DLL_MAJOR<100784#define DO_NOTHING_ATEXIT 185#endif86#endif87 88using namespace llvm;89 90static codegen::RegisterCodeGenFlags CGF;91 92#define DEBUG_TYPE "lli"93 94namespace {95enum class JITKind { MCJIT, Orc, OrcLazy };96enum class JITLinkerKind { Default, RuntimeDyld, JITLink };97} // namespace98 99static cl::opt<std::string> InputFile(cl::desc("<input bitcode>"),100 cl::Positional, cl::init("-"));101 102static cl::list<std::string> InputArgv(cl::ConsumeAfter,103 cl::desc("<program arguments>..."));104 105static cl::opt<bool>106 ForceInterpreter("force-interpreter",107 cl::desc("Force interpretation: disable JIT"),108 cl::init(false));109 110static cl::opt<JITKind>111 UseJITKind("jit-kind", cl::desc("Choose underlying JIT kind."),112 cl::init(JITKind::Orc),113 cl::values(clEnumValN(JITKind::MCJIT, "mcjit", "MCJIT"),114 clEnumValN(JITKind::Orc, "orc", "Orc JIT"),115 clEnumValN(JITKind::OrcLazy, "orc-lazy",116 "Orc-based lazy JIT.")));117 118static cl::opt<JITLinkerKind> JITLinker(119 "jit-linker", cl::desc("Choose the dynamic linker/loader."),120 cl::init(JITLinkerKind::Default),121 cl::values(clEnumValN(JITLinkerKind::Default, "default",122 "Default for platform and JIT-kind"),123 clEnumValN(JITLinkerKind::RuntimeDyld, "rtdyld", "RuntimeDyld"),124 clEnumValN(JITLinkerKind::JITLink, "jitlink",125 "Orc-specific linker")));126static cl::opt<std::string>127 OrcRuntime("orc-runtime", cl::desc("Use ORC runtime from given path"),128 cl::init(""));129 130static cl::opt<unsigned>131 LazyJITCompileThreads("compile-threads",132 cl::desc("Choose the number of compile threads "133 "(jit-kind=orc-lazy only)"),134 cl::init(0));135 136static cl::list<std::string>137 ThreadEntryPoints("thread-entry",138 cl::desc("calls the given entry-point on a new thread "139 "(jit-kind=orc-lazy only)"));140 141static cl::opt<bool> PerModuleLazy(142 "per-module-lazy",143 cl::desc("Performs lazy compilation on whole module boundaries "144 "rather than individual functions"),145 cl::init(false));146 147static cl::list<std::string>148 JITDylibs("jd",149 cl::desc("Specifies the JITDylib to be used for any subsequent "150 "-extra-module arguments."));151 152static cl::list<std::string>153 Dylibs("dlopen", cl::desc("Dynamic libraries to load before linking"));154 155// The MCJIT supports building for a target address space separate from156// the JIT compilation process. Use a forked process and a copying157// memory manager with IPC to execute using this functionality.158static cl::opt<bool>159 RemoteMCJIT("remote-mcjit",160 cl::desc("Execute MCJIT'ed code in a separate process."),161 cl::init(false));162 163// Manually specify the child process for remote execution. This overrides164// the simulated remote execution that allocates address space for child165// execution. The child process will be executed and will communicate with166// lli via stdin/stdout pipes.167static cl::opt<std::string> ChildExecPath(168 "mcjit-remote-process",169 cl::desc("Specify the filename of the process to launch "170 "for remote MCJIT execution. If none is specified,"171 "\n\tremote execution will be simulated in-process."),172 cl::value_desc("filename"), cl::init(""));173 174// Determine optimization level.175static cl::opt<char>176 OptLevel("O",177 cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "178 "(default = '-O2')"),179 cl::Prefix, cl::init('2'));180 181static cl::opt<std::string>182 TargetTriple("mtriple", cl::desc("Override target triple for module"));183 184static cl::opt<std::string>185 EntryFunc("entry-function",186 cl::desc("Specify the entry function (default = 'main') "187 "of the executable"),188 cl::value_desc("function"), cl::init("main"));189 190static cl::list<std::string>191 ExtraModules("extra-module", cl::desc("Extra modules to be loaded"),192 cl::value_desc("input bitcode"));193 194static cl::list<std::string>195 ExtraObjects("extra-object", cl::desc("Extra object files to be loaded"),196 cl::value_desc("input object"));197 198static cl::list<std::string>199 ExtraArchives("extra-archive", cl::desc("Extra archive files to be loaded"),200 cl::value_desc("input archive"));201 202static cl::opt<bool>203 EnableCacheManager("enable-cache-manager",204 cl::desc("Use cache manager to save/load modules"),205 cl::init(false));206 207static cl::opt<std::string>208 ObjectCacheDir("object-cache-dir",209 cl::desc("Directory to store cached object files "210 "(must be user writable)"),211 cl::init(""));212 213static cl::opt<std::string>214 FakeArgv0("fake-argv0",215 cl::desc("Override the 'argv[0]' value passed into the executing"216 " program"),217 cl::value_desc("executable"));218 219static cl::opt<bool>220 DisableCoreFiles("disable-core-files", cl::Hidden,221 cl::desc("Disable emission of core files if possible"));222 223static cl::opt<bool> NoLazyCompilation("disable-lazy-compilation",224 cl::desc("Disable JIT lazy compilation"),225 cl::init(false));226 227static cl::opt<bool> GenerateSoftFloatCalls(228 "soft-float", cl::desc("Generate software floating point library calls"),229 cl::init(false));230 231static cl::opt<bool> NoProcessSymbols(232 "no-process-syms",233 cl::desc("Do not resolve lli process symbols in JIT'd code"),234 cl::init(false));235 236enum class LLJITPlatform { Inactive, Auto, ExecutorNative, GenericIR };237 238static cl::opt<LLJITPlatform> Platform(239 "lljit-platform", cl::desc("Platform to use with LLJIT"),240 cl::init(LLJITPlatform::Auto),241 cl::values(clEnumValN(LLJITPlatform::Auto, "Auto",242 "Like 'ExecutorNative' if ORC runtime "243 "provided, otherwise like 'GenericIR'"),244 clEnumValN(LLJITPlatform::ExecutorNative, "ExecutorNative",245 "Use the native platform for the executor."246 "Requires -orc-runtime"),247 clEnumValN(LLJITPlatform::GenericIR, "GenericIR",248 "Use LLJITGenericIRPlatform"),249 clEnumValN(LLJITPlatform::Inactive, "Inactive",250 "Disable platform support explicitly")),251 cl::Hidden);252 253enum class DumpKind {254 NoDump,255 DumpFuncsToStdOut,256 DumpModsToStdOut,257 DumpModsToDisk,258 DumpDebugDescriptor,259 DumpDebugObjects,260};261 262static cl::opt<DumpKind> OrcDumpKind(263 "orc-lazy-debug", cl::desc("Debug dumping for the orc-lazy JIT."),264 cl::init(DumpKind::NoDump),265 cl::values(clEnumValN(DumpKind::NoDump, "no-dump", "Don't dump anything."),266 clEnumValN(DumpKind::DumpFuncsToStdOut, "funcs-to-stdout",267 "Dump function names to stdout."),268 clEnumValN(DumpKind::DumpModsToStdOut, "mods-to-stdout",269 "Dump modules to stdout."),270 clEnumValN(DumpKind::DumpModsToDisk, "mods-to-disk",271 "Dump modules to the current "272 "working directory. (WARNING: "273 "will overwrite existing files)."),274 clEnumValN(DumpKind::DumpDebugDescriptor, "jit-debug-descriptor",275 "Dump __jit_debug_descriptor contents to stdout"),276 clEnumValN(DumpKind::DumpDebugObjects, "jit-debug-objects",277 "Dump __jit_debug_descriptor in-memory debug "278 "objects as tool output")),279 cl::Hidden);280 281static ExitOnError ExitOnErr;282 283LLVM_ATTRIBUTE_USED static void linkComponents() {284 errs() << (void *)&llvm_orc_registerEHFrameSectionAllocAction285 << (void *)&llvm_orc_deregisterEHFrameSectionAllocAction286 << (void *)&llvm_orc_registerJITLoaderGDBAllocAction;287}288 289namespace {290//===----------------------------------------------------------------------===//291// Object cache292//293// This object cache implementation writes cached objects to disk to the294// directory specified by CacheDir, using a filename provided in the module295// descriptor. The cache tries to load a saved object using that path if the296// file exists. CacheDir defaults to "", in which case objects are cached297// alongside their originating bitcodes.298//299class LLIObjectCache : public ObjectCache {300public:301 LLIObjectCache(const std::string& CacheDir) : CacheDir(CacheDir) {302 // Add trailing '/' to cache dir if necessary.303 if (!this->CacheDir.empty() &&304 this->CacheDir[this->CacheDir.size() - 1] != '/')305 this->CacheDir += '/';306 }307 ~LLIObjectCache() override = default;308 309 void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override {310 const std::string &ModuleID = M->getModuleIdentifier();311 std::string CacheName;312 if (!getCacheFilename(ModuleID, CacheName))313 return;314 if (!CacheDir.empty()) { // Create user-defined cache dir.315 SmallString<128> dir(sys::path::parent_path(CacheName));316 sys::fs::create_directories(Twine(dir));317 }318 319 std::error_code EC;320 raw_fd_ostream outfile(CacheName, EC, sys::fs::OF_None);321 outfile.write(Obj.getBufferStart(), Obj.getBufferSize());322 outfile.close();323 }324 325 std::unique_ptr<MemoryBuffer> getObject(const Module* M) override {326 const std::string &ModuleID = M->getModuleIdentifier();327 std::string CacheName;328 if (!getCacheFilename(ModuleID, CacheName))329 return nullptr;330 // Load the object from the cache filename331 ErrorOr<std::unique_ptr<MemoryBuffer>> IRObjectBuffer =332 MemoryBuffer::getFile(CacheName, /*IsText=*/false,333 /*RequiresNullTerminator=*/false);334 // If the file isn't there, that's OK.335 if (!IRObjectBuffer)336 return nullptr;337 // MCJIT will want to write into this buffer, and we don't want that338 // because the file has probably just been mmapped. Instead we make339 // a copy. The filed-based buffer will be released when it goes340 // out of scope.341 return MemoryBuffer::getMemBufferCopy(IRObjectBuffer.get()->getBuffer());342 }343 344private:345 std::string CacheDir;346 347 bool getCacheFilename(StringRef ModID, std::string &CacheName) {348 if (!ModID.consume_front("file:"))349 return false;350 351 std::string CacheSubdir = std::string(ModID);352 // Transform "X:\foo" => "/X\foo" for convenience on Windows.353 if (is_style_windows(llvm::sys::path::Style::native) &&354 isalpha(CacheSubdir[0]) && CacheSubdir[1] == ':') {355 CacheSubdir[1] = CacheSubdir[0];356 CacheSubdir[0] = '/';357 }358 359 CacheName = CacheDir + CacheSubdir;360 size_t pos = CacheName.rfind('.');361 CacheName.replace(pos, CacheName.length() - pos, ".o");362 return true;363 }364};365} // namespace366 367// On Mingw and Cygwin, an external symbol named '__main' is called from the368// generated 'main' function to allow static initialization. To avoid linking369// problems with remote targets (because lli's remote target support does not370// currently handle external linking) we add a secondary module which defines371// an empty '__main' function.372static void addCygMingExtraModule(ExecutionEngine &EE, LLVMContext &Context,373 const Triple &TargetTriple) {374 IRBuilder<> Builder(Context);375 376 // Create a new module.377 std::unique_ptr<Module> M = std::make_unique<Module>("CygMingHelper", Context);378 M->setTargetTriple(TargetTriple);379 380 // Create an empty function named "__main".381 Type *ReturnTy;382 if (TargetTriple.isArch64Bit())383 ReturnTy = Type::getInt64Ty(Context);384 else385 ReturnTy = Type::getInt32Ty(Context);386 Function *Result =387 Function::Create(FunctionType::get(ReturnTy, {}, false),388 GlobalValue::ExternalLinkage, "__main", M.get());389 390 BasicBlock *BB = BasicBlock::Create(Context, "__main", Result);391 Builder.SetInsertPoint(BB);392 Value *ReturnVal = ConstantInt::get(ReturnTy, 0);393 Builder.CreateRet(ReturnVal);394 395 // Add this new module to the ExecutionEngine.396 EE.addModule(std::move(M));397}398 399static CodeGenOptLevel getOptLevel() {400 if (auto Level = CodeGenOpt::parseLevel(OptLevel))401 return *Level;402 WithColor::error(errs(), "lli") << "invalid optimization level.\n";403 exit(1);404}405 406[[noreturn]] static void reportError(SMDiagnostic Err, const char *ProgName) {407 Err.print(ProgName, errs());408 exit(1);409}410 411static Error loadDylibs();412static int runOrcJIT(const char *ProgName);413static void disallowOrcOptions();414static Expected<std::unique_ptr<orc::ExecutorProcessControl>> launchRemote();415 416//===----------------------------------------------------------------------===//417// main Driver function418//419int main(int argc, char **argv, char * const *envp) {420 InitLLVM X(argc, argv);421 422 if (argc > 1)423 ExitOnErr.setBanner(std::string(argv[0]) + ": ");424 425 // If we have a native target, initialize it to ensure it is linked in and426 // usable by the JIT.427 InitializeNativeTarget();428 InitializeNativeTargetAsmPrinter();429 InitializeNativeTargetAsmParser();430 431 cl::ParseCommandLineOptions(argc, argv,432 "llvm interpreter & dynamic compiler\n");433 434 // If the user doesn't want core files, disable them.435 if (DisableCoreFiles)436 sys::Process::PreventCoreFiles();437 438 ExitOnErr(loadDylibs());439 440 if (EntryFunc.empty()) {441 WithColor::error(errs(), argv[0])442 << "--entry-function name cannot be empty\n";443 exit(1);444 }445 446 if (UseJITKind == JITKind::MCJIT || ForceInterpreter)447 disallowOrcOptions();448 else449 return runOrcJIT(argv[0]);450 451 // Old lli implementation based on ExecutionEngine and MCJIT.452 LLVMContext Context;453 454 // Load the bitcode...455 SMDiagnostic Err;456 std::unique_ptr<Module> Owner = parseIRFile(InputFile, Err, Context);457 Module *Mod = Owner.get();458 if (!Mod)459 reportError(Err, argv[0]);460 461 if (EnableCacheManager) {462 std::string CacheName("file:");463 CacheName.append(InputFile);464 Mod->setModuleIdentifier(CacheName);465 }466 467 // If not jitting lazily, load the whole bitcode file eagerly too.468 if (NoLazyCompilation) {469 // Use *argv instead of argv[0] to work around a wrong GCC warning.470 ExitOnError ExitOnErr(std::string(*argv) +471 ": bitcode didn't read correctly: ");472 ExitOnErr(Mod->materializeAll());473 }474 475 std::string ErrorMsg;476 EngineBuilder builder(std::move(Owner));477 builder.setMArch(codegen::getMArch());478 builder.setMCPU(codegen::getCPUStr());479 builder.setMAttrs(codegen::getFeatureList());480 if (auto RM = codegen::getExplicitRelocModel())481 builder.setRelocationModel(*RM);482 if (auto CM = codegen::getExplicitCodeModel())483 builder.setCodeModel(*CM);484 builder.setErrorStr(&ErrorMsg);485 builder.setEngineKind(ForceInterpreter486 ? EngineKind::Interpreter487 : EngineKind::JIT);488 489 // If we are supposed to override the target triple, do so now.490 if (!TargetTriple.empty())491 Mod->setTargetTriple(Triple(Triple::normalize(TargetTriple)));492 493 // Enable MCJIT if desired.494 RTDyldMemoryManager *RTDyldMM = nullptr;495 if (!ForceInterpreter) {496 if (RemoteMCJIT)497 RTDyldMM = new ForwardingMemoryManager();498 else499 RTDyldMM = new SectionMemoryManager();500 501 // Deliberately construct a temp std::unique_ptr to pass in. Do not null out502 // RTDyldMM: We still use it below, even though we don't own it.503 builder.setMCJITMemoryManager(504 std::unique_ptr<RTDyldMemoryManager>(RTDyldMM));505 } else if (RemoteMCJIT) {506 WithColor::error(errs(), argv[0])507 << "remote process execution does not work with the interpreter.\n";508 exit(1);509 }510 511 builder.setOptLevel(getOptLevel());512 513 TargetOptions Options =514 codegen::InitTargetOptionsFromCodeGenFlags(Triple(TargetTriple));515 if (codegen::getFloatABIForCalls() != FloatABI::Default)516 Options.FloatABIType = codegen::getFloatABIForCalls();517 518 builder.setTargetOptions(Options);519 520 std::unique_ptr<ExecutionEngine> EE(builder.create());521 if (!EE) {522 if (!ErrorMsg.empty())523 WithColor::error(errs(), argv[0])524 << "error creating EE: " << ErrorMsg << "\n";525 else526 WithColor::error(errs(), argv[0]) << "unknown error creating EE!\n";527 exit(1);528 }529 530 std::unique_ptr<LLIObjectCache> CacheManager;531 if (EnableCacheManager) {532 CacheManager.reset(new LLIObjectCache(ObjectCacheDir));533 EE->setObjectCache(CacheManager.get());534 }535 536 // Load any additional modules specified on the command line.537 for (unsigned i = 0, e = ExtraModules.size(); i != e; ++i) {538 std::unique_ptr<Module> XMod = parseIRFile(ExtraModules[i], Err, Context);539 if (!XMod)540 reportError(Err, argv[0]);541 if (EnableCacheManager) {542 std::string CacheName("file:");543 CacheName.append(ExtraModules[i]);544 XMod->setModuleIdentifier(CacheName);545 }546 EE->addModule(std::move(XMod));547 }548 549 for (unsigned i = 0, e = ExtraObjects.size(); i != e; ++i) {550 Expected<object::OwningBinary<object::ObjectFile>> Obj =551 object::ObjectFile::createObjectFile(ExtraObjects[i]);552 if (!Obj) {553 // TODO: Actually report errors helpfully.554 consumeError(Obj.takeError());555 reportError(Err, argv[0]);556 }557 object::OwningBinary<object::ObjectFile> &O = Obj.get();558 EE->addObjectFile(std::move(O));559 }560 561 for (unsigned i = 0, e = ExtraArchives.size(); i != e; ++i) {562 ErrorOr<std::unique_ptr<MemoryBuffer>> ArBufOrErr =563 MemoryBuffer::getFileOrSTDIN(ExtraArchives[i]);564 if (!ArBufOrErr)565 reportError(Err, argv[0]);566 std::unique_ptr<MemoryBuffer> &ArBuf = ArBufOrErr.get();567 568 Expected<std::unique_ptr<object::Archive>> ArOrErr =569 object::Archive::create(ArBuf->getMemBufferRef());570 if (!ArOrErr) {571 std::string Buf;572 raw_string_ostream OS(Buf);573 logAllUnhandledErrors(ArOrErr.takeError(), OS);574 OS.flush();575 errs() << Buf;576 exit(1);577 }578 std::unique_ptr<object::Archive> &Ar = ArOrErr.get();579 580 object::OwningBinary<object::Archive> OB(std::move(Ar), std::move(ArBuf));581 582 EE->addArchive(std::move(OB));583 }584 585 // If the target is Cygwin/MingW and we are generating remote code, we586 // need an extra module to help out with linking.587 if (RemoteMCJIT && Mod->getTargetTriple().isOSCygMing()) {588 addCygMingExtraModule(*EE, Context, Mod->getTargetTriple());589 }590 591 // The following functions have no effect if their respective profiling592 // support wasn't enabled in the build configuration.593 EE->RegisterJITEventListener(594 JITEventListener::createOProfileJITEventListener());595 EE->RegisterJITEventListener(596 JITEventListener::createIntelJITEventListener());597 if (!RemoteMCJIT)598 EE->RegisterJITEventListener(599 JITEventListener::createPerfJITEventListener());600 601 if (!NoLazyCompilation && RemoteMCJIT) {602 WithColor::warning(errs(), argv[0])603 << "remote mcjit does not support lazy compilation\n";604 NoLazyCompilation = true;605 }606 EE->DisableLazyCompilation(NoLazyCompilation);607 608 // If the user specifically requested an argv[0] to pass into the program,609 // do it now.610 if (!FakeArgv0.empty()) {611 InputFile = static_cast<std::string>(FakeArgv0);612 } else {613 // Otherwise, if there is a .bc suffix on the executable strip it off, it614 // might confuse the program.615 if (StringRef(InputFile).ends_with(".bc"))616 InputFile.erase(InputFile.length() - 3);617 }618 619 // Add the module's name to the start of the vector of arguments to main().620 InputArgv.insert(InputArgv.begin(), InputFile);621 622 // Call the main function from M as if its signature were:623 // int main (int argc, char **argv, const char **envp)624 // using the contents of Args to determine argc & argv, and the contents of625 // EnvVars to determine envp.626 //627 Function *EntryFn = Mod->getFunction(EntryFunc);628 if (!EntryFn) {629 WithColor::error(errs(), argv[0])630 << '\'' << EntryFunc << "\' function not found in module.\n";631 return -1;632 }633 634 // Reset errno to zero on entry to main.635 errno = 0;636 637 int Result = -1;638 639 // Sanity check use of remote-jit: LLI currently only supports use of the640 // remote JIT on Unix platforms.641 if (RemoteMCJIT) {642#ifndef LLVM_ON_UNIX643 WithColor::warning(errs(), argv[0])644 << "host does not support external remote targets.\n";645 WithColor::note() << "defaulting to local execution\n";646 return -1;647#else648 if (ChildExecPath.empty()) {649 WithColor::error(errs(), argv[0])650 << "-remote-mcjit requires -mcjit-remote-process.\n";651 exit(1);652 } else if (!sys::fs::can_execute(ChildExecPath)) {653 WithColor::error(errs(), argv[0])654 << "unable to find usable child executable: '" << ChildExecPath655 << "'\n";656 return -1;657 }658#endif659 }660 661 if (!RemoteMCJIT) {662 // If the program doesn't explicitly call exit, we will need the Exit663 // function later on to make an explicit call, so get the function now.664 FunctionCallee Exit = Mod->getOrInsertFunction(665 "exit", Type::getVoidTy(Context), Type::getInt32Ty(Context));666 667 // Run static constructors.668 if (!ForceInterpreter) {669 // Give MCJIT a chance to apply relocations and set page permissions.670 EE->finalizeObject();671 }672 EE->runStaticConstructorsDestructors(false);673 674 // Trigger compilation separately so code regions that need to be675 // invalidated will be known.676 (void)EE->getPointerToFunction(EntryFn);677 // Clear instruction cache before code will be executed.678 if (RTDyldMM)679 static_cast<SectionMemoryManager*>(RTDyldMM)->invalidateInstructionCache();680 681 // Run main.682 Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp);683 684 // Run static destructors.685 EE->runStaticConstructorsDestructors(true);686 687 // If the program didn't call exit explicitly, we should call it now.688 // This ensures that any atexit handlers get called correctly.689 if (Function *ExitF =690 dyn_cast<Function>(Exit.getCallee()->stripPointerCasts())) {691 if (ExitF->getFunctionType() == Exit.getFunctionType()) {692 std::vector<GenericValue> Args;693 GenericValue ResultGV;694 ResultGV.IntVal = APInt(32, Result);695 Args.push_back(ResultGV);696 EE->runFunction(ExitF, Args);697 WithColor::error(errs(), argv[0])698 << "exit(" << Result << ") returned!\n";699 abort();700 }701 }702 WithColor::error(errs(), argv[0]) << "exit defined with wrong prototype!\n";703 abort();704 } else {705 // else == "if (RemoteMCJIT)"706 std::unique_ptr<orc::ExecutorProcessControl> EPC = ExitOnErr(launchRemote());707 708 // Remote target MCJIT doesn't (yet) support static constructors. No reason709 // it couldn't. This is a limitation of the LLI implementation, not the710 // MCJIT itself. FIXME.711 712 // Create a remote memory manager.713 auto RemoteMM = ExitOnErr(714 orc::EPCGenericRTDyldMemoryManager::CreateWithDefaultBootstrapSymbols(715 *EPC));716 717 // Forward MCJIT's memory manager calls to the remote memory manager.718 static_cast<ForwardingMemoryManager*>(RTDyldMM)->setMemMgr(719 std::move(RemoteMM));720 721 // Forward MCJIT's symbol resolution calls to the remote.722 static_cast<ForwardingMemoryManager *>(RTDyldMM)->setResolver(723 ExitOnErr(RemoteResolver::Create(*EPC)));724 // Grab the target address of the JIT'd main function on the remote and call725 // it.726 // FIXME: argv and envp handling.727 auto Entry =728 orc::ExecutorAddr(EE->getFunctionAddress(EntryFn->getName().str()));729 EE->finalizeObject();730 LLVM_DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"731 << format("%llx", Entry.getValue()) << "\n");732 Result = ExitOnErr(EPC->runAsMain(Entry, {}));733 734 // Like static constructors, the remote target MCJIT support doesn't handle735 // this yet. It could. FIXME.736 737 // Delete the EE - we need to tear it down *before* we terminate the session738 // with the remote, otherwise it'll crash when it tries to release resources739 // on a remote that has already been disconnected.740 EE.reset();741 742 // Signal the remote target that we're done JITing.743 ExitOnErr(EPC->disconnect());744 }745 746 return Result;747}748 749// JITLink debug support plugins put information about JITed code in this GDB750// JIT Interface global from OrcTargetProcess.751extern "C" LLVM_ABI struct jit_descriptor __jit_debug_descriptor;752 753static struct jit_code_entry *754findNextDebugDescriptorEntry(struct jit_code_entry *Latest) {755 if (Latest == nullptr)756 return __jit_debug_descriptor.first_entry;757 if (Latest->next_entry)758 return Latest->next_entry;759 return nullptr;760}761 762static ToolOutputFile &claimToolOutput() {763 static std::unique_ptr<ToolOutputFile> ToolOutput = nullptr;764 if (ToolOutput) {765 WithColor::error(errs(), "lli")766 << "Can not claim stdout for tool output twice\n";767 exit(1);768 }769 std::error_code EC;770 ToolOutput = std::make_unique<ToolOutputFile>("-", EC, sys::fs::OF_None);771 if (EC) {772 WithColor::error(errs(), "lli")773 << "Failed to create tool output file: " << EC.message() << "\n";774 exit(1);775 }776 return *ToolOutput;777}778 779static std::function<void(Module &)> createIRDebugDumper() {780 switch (OrcDumpKind) {781 case DumpKind::NoDump:782 case DumpKind::DumpDebugDescriptor:783 case DumpKind::DumpDebugObjects:784 return [](Module &M) {};785 786 case DumpKind::DumpFuncsToStdOut:787 return [](Module &M) {788 printf("[ ");789 790 for (const auto &F : M) {791 if (F.isDeclaration())792 continue;793 794 if (F.hasName()) {795 std::string Name(std::string(F.getName()));796 printf("%s ", Name.c_str());797 } else798 printf("<anon> ");799 }800 801 printf("]\n");802 };803 804 case DumpKind::DumpModsToStdOut:805 return [](Module &M) {806 outs() << "----- Module Start -----\n" << M << "----- Module End -----\n";807 };808 809 case DumpKind::DumpModsToDisk:810 return [](Module &M) {811 std::error_code EC;812 raw_fd_ostream Out(M.getModuleIdentifier() + ".ll", EC,813 sys::fs::OF_TextWithCRLF);814 if (EC) {815 errs() << "Couldn't open " << M.getModuleIdentifier()816 << " for dumping.\nError:" << EC.message() << "\n";817 exit(1);818 }819 Out << M;820 };821 }822 llvm_unreachable("Unknown DumpKind");823}824 825static std::function<void(MemoryBuffer &)> createObjDebugDumper() {826 switch (OrcDumpKind) {827 case DumpKind::NoDump:828 case DumpKind::DumpFuncsToStdOut:829 case DumpKind::DumpModsToStdOut:830 case DumpKind::DumpModsToDisk:831 return [](MemoryBuffer &) {};832 833 case DumpKind::DumpDebugDescriptor: {834 // Dump the empty descriptor at startup once835 fprintf(stderr, "jit_debug_descriptor 0x%016" PRIx64 "\n",836 pointerToJITTargetAddress(__jit_debug_descriptor.first_entry));837 return [](MemoryBuffer &) {838 // Dump new entries as they appear839 static struct jit_code_entry *Latest = nullptr;840 while (auto *NewEntry = findNextDebugDescriptorEntry(Latest)) {841 fprintf(stderr, "jit_debug_descriptor 0x%016" PRIx64 "\n",842 pointerToJITTargetAddress(NewEntry));843 Latest = NewEntry;844 }845 };846 }847 848 case DumpKind::DumpDebugObjects: {849 return [](MemoryBuffer &Obj) {850 static struct jit_code_entry *Latest = nullptr;851 static ToolOutputFile &ToolOutput = claimToolOutput();852 while (auto *NewEntry = findNextDebugDescriptorEntry(Latest)) {853 ToolOutput.os().write(NewEntry->symfile_addr, NewEntry->symfile_size);854 Latest = NewEntry;855 }856 };857 }858 }859 llvm_unreachable("Unknown DumpKind");860}861 862static Error loadDylibs() {863 for (const auto &Dylib : Dylibs) {864 std::string ErrMsg;865 if (sys::DynamicLibrary::LoadLibraryPermanently(Dylib.c_str(), &ErrMsg))866 return make_error<StringError>(ErrMsg, inconvertibleErrorCode());867 }868 869 return Error::success();870}871 872static void exitOnLazyCallThroughFailure() { exit(1); }873 874static Expected<orc::ThreadSafeModule>875loadModule(StringRef Path, orc::ThreadSafeContext TSCtx) {876 SMDiagnostic Err;877 auto M = TSCtx.withContextDo(878 [&](LLVMContext *Ctx) { return parseIRFile(Path, Err, *Ctx); });879 if (!M) {880 std::string ErrMsg;881 {882 raw_string_ostream ErrMsgStream(ErrMsg);883 Err.print("lli", ErrMsgStream);884 }885 return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());886 }887 888 if (EnableCacheManager)889 M->setModuleIdentifier("file:" + M->getModuleIdentifier());890 891 return orc::ThreadSafeModule(std::move(M), std::move(TSCtx));892}893 894static int mingw_noop_main(void) {895 // Cygwin and MinGW insert calls from the main function to the runtime896 // function __main. The __main function is responsible for setting up main's897 // environment (e.g. running static constructors), however this is not needed898 // when running under lli: the executor process will have run non-JIT ctors,899 // and ORC will take care of running JIT'd ctors. To avoid a missing symbol900 // error we just implement __main as a no-op.901 //902 // FIXME: Move this to ORC-RT (and the ORC-RT substitution library once it903 // exists). That will allow it to work out-of-process, and for all904 // ORC tools (the problem isn't lli specific).905 return 0;906}907 908// Try to enable debugger support for the given instance.909// This alway returns success, but prints a warning if it's not able to enable910// debugger support.911static Error tryEnableDebugSupport(orc::LLJIT &J) {912 if (auto Err = enableDebuggerSupport(J)) {913 [[maybe_unused]] std::string ErrMsg = toString(std::move(Err));914 LLVM_DEBUG(dbgs() << "lli: " << ErrMsg << "\n");915 }916 return Error::success();917}918 919static int runOrcJIT(const char *ProgName) {920 // Start setting up the JIT environment.921 922 // Parse the main module.923 orc::ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());924 auto MainModule = ExitOnErr(loadModule(InputFile, TSCtx));925 926 // Get TargetTriple and DataLayout from the main module if they're explicitly927 // set.928 std::optional<Triple> TT;929 std::optional<DataLayout> DL;930 MainModule.withModuleDo([&](Module &M) {931 if (!M.getTargetTriple().empty())932 TT = M.getTargetTriple();933 if (!M.getDataLayout().isDefault())934 DL = M.getDataLayout();935 });936 937 orc::LLLazyJITBuilder Builder;938 939 Builder.setJITTargetMachineBuilder(940 TT ? orc::JITTargetMachineBuilder(*TT)941 : ExitOnErr(orc::JITTargetMachineBuilder::detectHost()));942 943 TT = Builder.getJITTargetMachineBuilder()->getTargetTriple();944 if (DL)945 Builder.setDataLayout(DL);946 947 if (!codegen::getMArch().empty())948 Builder.getJITTargetMachineBuilder()->getTargetTriple().setArchName(949 codegen::getMArch());950 951 Builder.getJITTargetMachineBuilder()952 ->setCPU(codegen::getCPUStr())953 .addFeatures(codegen::getFeatureList())954 .setRelocationModel(codegen::getExplicitRelocModel())955 .setCodeModel(codegen::getExplicitCodeModel());956 957 // Link process symbols unless NoProcessSymbols is set.958 Builder.setLinkProcessSymbolsByDefault(!NoProcessSymbols);959 960 // FIXME: Setting a dummy call-through manager in non-lazy mode prevents the961 // JIT builder to instantiate a default (which would fail with an error for962 // unsupported architectures).963 if (UseJITKind != JITKind::OrcLazy) {964 auto ES = std::make_unique<orc::ExecutionSession>(965 ExitOnErr(orc::SelfExecutorProcessControl::Create()));966 Builder.setLazyCallthroughManager(967 std::make_unique<orc::LazyCallThroughManager>(*ES, orc::ExecutorAddr(),968 nullptr));969 Builder.setExecutionSession(std::move(ES));970 }971 972 Builder.setLazyCompileFailureAddr(973 orc::ExecutorAddr::fromPtr(exitOnLazyCallThroughFailure));974 Builder.setNumCompileThreads(LazyJITCompileThreads);975 976 // If the object cache is enabled then set a custom compile function977 // creator to use the cache.978 std::unique_ptr<LLIObjectCache> CacheManager;979 if (EnableCacheManager) {980 981 CacheManager = std::make_unique<LLIObjectCache>(ObjectCacheDir);982 983 Builder.setCompileFunctionCreator(984 [&](orc::JITTargetMachineBuilder JTMB)985 -> Expected<std::unique_ptr<orc::IRCompileLayer::IRCompiler>> {986 if (LazyJITCompileThreads > 0)987 return std::make_unique<orc::ConcurrentIRCompiler>(std::move(JTMB),988 CacheManager.get());989 990 auto TM = JTMB.createTargetMachine();991 if (!TM)992 return TM.takeError();993 994 return std::make_unique<orc::TMOwningSimpleCompiler>(std::move(*TM),995 CacheManager.get());996 });997 }998 999 // Enable debugging of JIT'd code (only works on JITLink for ELF and MachO).1000 Builder.setPrePlatformSetup(tryEnableDebugSupport);1001 1002 // Set up LLJIT platform.1003 LLJITPlatform P = Platform;1004 if (P == LLJITPlatform::Auto)1005 P = OrcRuntime.empty() ? LLJITPlatform::GenericIR1006 : LLJITPlatform::ExecutorNative;1007 1008 switch (P) {1009 case LLJITPlatform::ExecutorNative: {1010 Builder.setPlatformSetUp(orc::ExecutorNativePlatform(OrcRuntime));1011 break;1012 }1013 case LLJITPlatform::GenericIR:1014 // Nothing to do: LLJITBuilder will use this by default.1015 break;1016 case LLJITPlatform::Inactive:1017 Builder.setPlatformSetUp(orc::setUpInactivePlatform);1018 break;1019 default:1020 llvm_unreachable("Unrecognized platform value");1021 }1022 1023 std::unique_ptr<orc::ExecutorProcessControl> EPC = nullptr;1024 if (JITLinker == JITLinkerKind::JITLink) {1025 EPC = ExitOnErr(orc::SelfExecutorProcessControl::Create(1026 std::make_shared<orc::SymbolStringPool>()));1027 1028 Builder.getJITTargetMachineBuilder()1029 ->setRelocationModel(Reloc::PIC_)1030 .setCodeModel(CodeModel::Small);1031 Builder.setObjectLinkingLayerCreator([&](orc::ExecutionSession &ES) {1032 return std::make_unique<orc::ObjectLinkingLayer>(ES);1033 });1034 }1035 1036 auto J = ExitOnErr(Builder.create());1037 1038 auto *ObjLayer = &J->getObjLinkingLayer();1039 if (auto *RTDyldObjLayer = dyn_cast<orc::RTDyldObjectLinkingLayer>(ObjLayer)) {1040 RTDyldObjLayer->registerJITEventListener(1041 *JITEventListener::createGDBRegistrationListener());1042#if LLVM_USE_OPROFILE1043 RTDyldObjLayer->registerJITEventListener(1044 *JITEventListener::createOProfileJITEventListener());1045#endif1046#if LLVM_USE_INTEL_JITEVENTS1047 RTDyldObjLayer->registerJITEventListener(1048 *JITEventListener::createIntelJITEventListener());1049#endif1050#if LLVM_USE_PERF1051 RTDyldObjLayer->registerJITEventListener(1052 *JITEventListener::createPerfJITEventListener());1053#endif1054 }1055 1056 if (PerModuleLazy)1057 J->setPartitionFunction(orc::IRPartitionLayer::compileWholeModule);1058 1059 auto IRDump = createIRDebugDumper();1060 J->getIRTransformLayer().setTransform(1061 [&](orc::ThreadSafeModule TSM,1062 const orc::MaterializationResponsibility &R) {1063 TSM.withModuleDo([&](Module &M) {1064 if (verifyModule(M, &dbgs())) {1065 dbgs() << "Bad module: " << &M << "\n";1066 exit(1);1067 }1068 IRDump(M);1069 });1070 return TSM;1071 });1072 1073 auto ObjDump = createObjDebugDumper();1074 J->getObjTransformLayer().setTransform(1075 [&](std::unique_ptr<MemoryBuffer> Obj)1076 -> Expected<std::unique_ptr<MemoryBuffer>> {1077 ObjDump(*Obj);1078 return std::move(Obj);1079 });1080 1081 // If this is a Mingw or Cygwin executor then we need to alias __main to1082 // orc_rt_int_void_return_0.1083 if (J->getTargetTriple().isOSCygMing()) {1084 auto &WorkaroundJD = J->getProcessSymbolsJITDylib()1085 ? *J->getProcessSymbolsJITDylib()1086 : J->getMainJITDylib();1087 ExitOnErr(WorkaroundJD.define(1088 orc::absoluteSymbols({{J->mangleAndIntern("__main"),1089 {orc::ExecutorAddr::fromPtr(mingw_noop_main),1090 JITSymbolFlags::Exported}}})));1091 }1092 1093 // Regular modules are greedy: They materialize as a whole and trigger1094 // materialization for all required symbols recursively. Lazy modules go1095 // through partitioning and they replace outgoing calls with reexport stubs1096 // that resolve on call-through.1097 auto AddModule = [&](orc::JITDylib &JD, orc::ThreadSafeModule M) {1098 return UseJITKind == JITKind::OrcLazy ? J->addLazyIRModule(JD, std::move(M))1099 : J->addIRModule(JD, std::move(M));1100 };1101 1102 // Add the main module.1103 ExitOnErr(AddModule(J->getMainJITDylib(), std::move(MainModule)));1104 1105 // Create JITDylibs and add any extra modules.1106 {1107 // Create JITDylibs, keep a map from argument index to dylib. We will use1108 // -extra-module argument indexes to determine what dylib to use for each1109 // -extra-module.1110 std::map<unsigned, orc::JITDylib *> IdxToDylib;1111 IdxToDylib[0] = &J->getMainJITDylib();1112 for (auto JDItr = JITDylibs.begin(), JDEnd = JITDylibs.end();1113 JDItr != JDEnd; ++JDItr) {1114 orc::JITDylib *JD = J->getJITDylibByName(*JDItr);1115 if (!JD) {1116 JD = &ExitOnErr(J->createJITDylib(*JDItr));1117 J->getMainJITDylib().addToLinkOrder(*JD);1118 JD->addToLinkOrder(J->getMainJITDylib());1119 }1120 IdxToDylib[JITDylibs.getPosition(JDItr - JITDylibs.begin())] = JD;1121 }1122 1123 for (auto EMItr = ExtraModules.begin(), EMEnd = ExtraModules.end();1124 EMItr != EMEnd; ++EMItr) {1125 auto M = ExitOnErr(loadModule(*EMItr, TSCtx));1126 1127 auto EMIdx = ExtraModules.getPosition(EMItr - ExtraModules.begin());1128 assert(EMIdx != 0 && "ExtraModule should have index > 0");1129 auto JDItr = std::prev(IdxToDylib.lower_bound(EMIdx));1130 auto &JD = *JDItr->second;1131 ExitOnErr(AddModule(JD, std::move(M)));1132 }1133 1134 for (auto EAItr = ExtraArchives.begin(), EAEnd = ExtraArchives.end();1135 EAItr != EAEnd; ++EAItr) {1136 auto EAIdx = ExtraArchives.getPosition(EAItr - ExtraArchives.begin());1137 assert(EAIdx != 0 && "ExtraArchive should have index > 0");1138 auto JDItr = std::prev(IdxToDylib.lower_bound(EAIdx));1139 auto &JD = *JDItr->second;1140 ExitOnErr(J->linkStaticLibraryInto(JD, EAItr->c_str()));1141 }1142 }1143 1144 // Add the objects.1145 for (auto &ObjPath : ExtraObjects) {1146 auto Obj = ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(ObjPath)));1147 ExitOnErr(J->addObjectFile(std::move(Obj)));1148 }1149 1150 // Run any static constructors.1151 ExitOnErr(J->initialize(J->getMainJITDylib()));1152 1153 // Run any -thread-entry points.1154 std::vector<std::thread> AltEntryThreads;1155 for (auto &ThreadEntryPoint : ThreadEntryPoints) {1156 auto EntryPointSym = ExitOnErr(J->lookup(ThreadEntryPoint));1157 typedef void (*EntryPointPtr)();1158 auto EntryPoint = EntryPointSym.toPtr<EntryPointPtr>();1159 AltEntryThreads.push_back(std::thread([EntryPoint]() { EntryPoint(); }));1160 }1161 1162 // Resolve and run the main function.1163 auto MainAddr = ExitOnErr(J->lookup(EntryFunc));1164 int Result;1165 1166 if (EPC) {1167 // ExecutorProcessControl-based execution with JITLink.1168 Result = ExitOnErr(EPC->runAsMain(MainAddr, InputArgv));1169 } else {1170 // Manual in-process execution with RuntimeDyld.1171 using MainFnTy = int(int, char *[]);1172 auto MainFn = MainAddr.toPtr<MainFnTy *>();1173 Result = orc::runAsMain(MainFn, InputArgv, StringRef(InputFile));1174 }1175 1176 // Wait for -entry-point threads.1177 for (auto &AltEntryThread : AltEntryThreads)1178 AltEntryThread.join();1179 1180 // Run destructors.1181 ExitOnErr(J->deinitialize(J->getMainJITDylib()));1182 1183 return Result;1184}1185 1186static void disallowOrcOptions() {1187 // Make sure nobody used an orc-lazy specific option accidentally.1188 1189 if (LazyJITCompileThreads != 0) {1190 errs() << "-compile-threads requires -jit-kind=orc-lazy\n";1191 exit(1);1192 }1193 1194 if (!ThreadEntryPoints.empty()) {1195 errs() << "-thread-entry requires -jit-kind=orc-lazy\n";1196 exit(1);1197 }1198 1199 if (PerModuleLazy) {1200 errs() << "-per-module-lazy requires -jit-kind=orc-lazy\n";1201 exit(1);1202 }1203}1204 1205static Expected<std::unique_ptr<orc::ExecutorProcessControl>> launchRemote() {1206#ifndef LLVM_ON_UNIX1207 llvm_unreachable("launchRemote not supported on non-Unix platforms");1208#else1209 int PipeFD[2][2];1210 pid_t ChildPID;1211 1212 // Create two pipes.1213 if (pipe(PipeFD[0]) != 0 || pipe(PipeFD[1]) != 0)1214 perror("Error creating pipe: ");1215 1216 ChildPID = fork();1217 1218 if (ChildPID == 0) {1219 // In the child...1220 1221 // Close the parent ends of the pipes1222 close(PipeFD[0][1]);1223 close(PipeFD[1][0]);1224 1225 1226 // Execute the child process.1227 std::unique_ptr<char[]> ChildPath, ChildIn, ChildOut;1228 {1229 ChildPath.reset(new char[ChildExecPath.size() + 1]);1230 llvm::copy(ChildExecPath, &ChildPath[0]);1231 ChildPath[ChildExecPath.size()] = '\0';1232 std::string ChildInStr = utostr(PipeFD[0][0]);1233 ChildIn.reset(new char[ChildInStr.size() + 1]);1234 llvm::copy(ChildInStr, &ChildIn[0]);1235 ChildIn[ChildInStr.size()] = '\0';1236 std::string ChildOutStr = utostr(PipeFD[1][1]);1237 ChildOut.reset(new char[ChildOutStr.size() + 1]);1238 llvm::copy(ChildOutStr, &ChildOut[0]);1239 ChildOut[ChildOutStr.size()] = '\0';1240 }1241 1242 char * const args[] = { &ChildPath[0], &ChildIn[0], &ChildOut[0], nullptr };1243 int rc = execv(ChildExecPath.c_str(), args);1244 if (rc != 0)1245 perror("Error executing child process: ");1246 llvm_unreachable("Error executing child process");1247 }1248 // else we're the parent...1249 1250 // Close the child ends of the pipes1251 close(PipeFD[0][0]);1252 close(PipeFD[1][1]);1253 1254 // Return a SimpleRemoteEPC instance connected to our end of the pipes.1255 return orc::SimpleRemoteEPC::Create<orc::FDSimpleRemoteEPCTransport>(1256 std::make_unique<llvm::orc::InPlaceTaskDispatcher>(),1257 llvm::orc::SimpleRemoteEPC::Setup(), PipeFD[1][0], PipeFD[0][1]);1258#endif1259}1260 1261// For MinGW environments, manually export the __chkstk function from the lli1262// executable.1263//1264// Normally, this function is provided by compiler-rt builtins or libgcc.1265// It is named "_alloca" on i386, "___chkstk_ms" on x86_64, and "__chkstk" on1266// arm/aarch64. In MSVC configurations, it's named "__chkstk" in all1267// configurations.1268//1269// When Orc tries to resolve symbols at runtime, this succeeds in MSVC1270// configurations, somewhat by accident/luck; kernelbase.dll does export a1271// symbol named "__chkstk" which gets found by Orc, even if regular applications1272// never link against that function from that DLL (it's linked in statically1273// from a compiler support library).1274//1275// The MinGW specific symbol names aren't available in that DLL though.1276// Therefore, manually export the relevant symbol from lli, to let it be1277// found at runtime during tests.1278//1279// For real JIT uses, the real compiler support libraries should be linked1280// in, somehow; this is a workaround to let tests pass.1281//1282// We need to make sure that this symbol actually is linked in when we1283// try to export it; if no functions allocate a large enough stack area,1284// nothing would reference it. Therefore, manually declare it and add a1285// reference to it. (Note, the declarations of _alloca/___chkstk_ms/__chkstk1286// are somewhat bogus, these functions use a different custom calling1287// convention.)1288//1289// TODO: Move this into libORC at some point, see1290// https://github.com/llvm/llvm-project/issues/56603.1291#ifdef __MINGW32__1292// This is a MinGW version of #pragma comment(linker, "...") that doesn't1293// require compiling with -fms-extensions.1294#if defined(__i386__)1295#undef _alloca1296extern "C" void _alloca(void);1297static __attribute__((used)) void (*const ref_func)(void) = _alloca;1298static __attribute__((section(".drectve"), used)) const char export_chkstk[] =1299 "-export:_alloca";1300#elif defined(__x86_64__)1301extern "C" void ___chkstk_ms(void);1302static __attribute__((used)) void (*const ref_func)(void) = ___chkstk_ms;1303static __attribute__((section(".drectve"), used)) const char export_chkstk[] =1304 "-export:___chkstk_ms";1305#else1306extern "C" void __chkstk(void);1307static __attribute__((used)) void (*const ref_func)(void) = __chkstk;1308static __attribute__((section(".drectve"), used)) const char export_chkstk[] =1309 "-export:__chkstk";1310#endif1311#endif1312