1*0b57cec5SDimitry Andric //===- lli.cpp - LLVM Interpreter / Dynamic compiler ----------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This utility provides a simple wrapper around the LLVM Execution Engines, 10*0b57cec5SDimitry Andric // which allow the direct execution of LLVM programs through a Just-In-Time 11*0b57cec5SDimitry Andric // compiler, or through an interpreter if no JIT is available for this platform. 12*0b57cec5SDimitry Andric // 13*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14*0b57cec5SDimitry Andric 15*0b57cec5SDimitry Andric #include "RemoteJITUtils.h" 16*0b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 17*0b57cec5SDimitry Andric #include "llvm/ADT/Triple.h" 18*0b57cec5SDimitry Andric #include "llvm/Bitcode/BitcodeReader.h" 19*0b57cec5SDimitry Andric #include "llvm/CodeGen/CommandFlags.inc" 20*0b57cec5SDimitry Andric #include "llvm/CodeGen/LinkAllCodegenComponents.h" 21*0b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 22*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/GenericValue.h" 23*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Interpreter.h" 24*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITEventListener.h" 25*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/MCJIT.h" 26*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/ObjectCache.h" 27*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 28*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" 29*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/LLJIT.h" 30*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" 31*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/OrcMCJITReplacement.h" 32*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/SectionMemoryManager.h" 33*0b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h" 34*0b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h" 35*0b57cec5SDimitry Andric #include "llvm/IR/Module.h" 36*0b57cec5SDimitry Andric #include "llvm/IR/Type.h" 37*0b57cec5SDimitry Andric #include "llvm/IR/Verifier.h" 38*0b57cec5SDimitry Andric #include "llvm/IRReader/IRReader.h" 39*0b57cec5SDimitry Andric #include "llvm/Object/Archive.h" 40*0b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 41*0b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 42*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 43*0b57cec5SDimitry Andric #include "llvm/Support/DynamicLibrary.h" 44*0b57cec5SDimitry Andric #include "llvm/Support/Format.h" 45*0b57cec5SDimitry Andric #include "llvm/Support/InitLLVM.h" 46*0b57cec5SDimitry Andric #include "llvm/Support/ManagedStatic.h" 47*0b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 48*0b57cec5SDimitry Andric #include "llvm/Support/Memory.h" 49*0b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 50*0b57cec5SDimitry Andric #include "llvm/Support/Path.h" 51*0b57cec5SDimitry Andric #include "llvm/Support/PluginLoader.h" 52*0b57cec5SDimitry Andric #include "llvm/Support/Process.h" 53*0b57cec5SDimitry Andric #include "llvm/Support/Program.h" 54*0b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h" 55*0b57cec5SDimitry Andric #include "llvm/Support/TargetSelect.h" 56*0b57cec5SDimitry Andric #include "llvm/Support/WithColor.h" 57*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 58*0b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation.h" 59*0b57cec5SDimitry Andric #include <cerrno> 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric #ifdef __CYGWIN__ 62*0b57cec5SDimitry Andric #include <cygwin/version.h> 63*0b57cec5SDimitry Andric #if defined(CYGWIN_VERSION_DLL_MAJOR) && CYGWIN_VERSION_DLL_MAJOR<1007 64*0b57cec5SDimitry Andric #define DO_NOTHING_ATEXIT 1 65*0b57cec5SDimitry Andric #endif 66*0b57cec5SDimitry Andric #endif 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric using namespace llvm; 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric #define DEBUG_TYPE "lli" 71*0b57cec5SDimitry Andric 72*0b57cec5SDimitry Andric namespace { 73*0b57cec5SDimitry Andric 74*0b57cec5SDimitry Andric enum class JITKind { MCJIT, OrcMCJITReplacement, OrcLazy }; 75*0b57cec5SDimitry Andric 76*0b57cec5SDimitry Andric cl::opt<std::string> 77*0b57cec5SDimitry Andric InputFile(cl::desc("<input bitcode>"), cl::Positional, cl::init("-")); 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric cl::list<std::string> 80*0b57cec5SDimitry Andric InputArgv(cl::ConsumeAfter, cl::desc("<program arguments>...")); 81*0b57cec5SDimitry Andric 82*0b57cec5SDimitry Andric cl::opt<bool> ForceInterpreter("force-interpreter", 83*0b57cec5SDimitry Andric cl::desc("Force interpretation: disable JIT"), 84*0b57cec5SDimitry Andric cl::init(false)); 85*0b57cec5SDimitry Andric 86*0b57cec5SDimitry Andric cl::opt<JITKind> UseJITKind( 87*0b57cec5SDimitry Andric "jit-kind", cl::desc("Choose underlying JIT kind."), 88*0b57cec5SDimitry Andric cl::init(JITKind::MCJIT), 89*0b57cec5SDimitry Andric cl::values(clEnumValN(JITKind::MCJIT, "mcjit", "MCJIT"), 90*0b57cec5SDimitry Andric clEnumValN(JITKind::OrcMCJITReplacement, "orc-mcjit", 91*0b57cec5SDimitry Andric "Orc-based MCJIT replacement " 92*0b57cec5SDimitry Andric "(deprecated)"), 93*0b57cec5SDimitry Andric clEnumValN(JITKind::OrcLazy, "orc-lazy", 94*0b57cec5SDimitry Andric "Orc-based lazy JIT."))); 95*0b57cec5SDimitry Andric 96*0b57cec5SDimitry Andric cl::opt<unsigned> 97*0b57cec5SDimitry Andric LazyJITCompileThreads("compile-threads", 98*0b57cec5SDimitry Andric cl::desc("Choose the number of compile threads " 99*0b57cec5SDimitry Andric "(jit-kind=orc-lazy only)"), 100*0b57cec5SDimitry Andric cl::init(0)); 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric cl::list<std::string> 103*0b57cec5SDimitry Andric ThreadEntryPoints("thread-entry", 104*0b57cec5SDimitry Andric cl::desc("calls the given entry-point on a new thread " 105*0b57cec5SDimitry Andric "(jit-kind=orc-lazy only)")); 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric cl::opt<bool> PerModuleLazy( 108*0b57cec5SDimitry Andric "per-module-lazy", 109*0b57cec5SDimitry Andric cl::desc("Performs lazy compilation on whole module boundaries " 110*0b57cec5SDimitry Andric "rather than individual functions"), 111*0b57cec5SDimitry Andric cl::init(false)); 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric cl::list<std::string> 114*0b57cec5SDimitry Andric JITDylibs("jd", 115*0b57cec5SDimitry Andric cl::desc("Specifies the JITDylib to be used for any subsequent " 116*0b57cec5SDimitry Andric "-extra-module arguments.")); 117*0b57cec5SDimitry Andric 118*0b57cec5SDimitry Andric // The MCJIT supports building for a target address space separate from 119*0b57cec5SDimitry Andric // the JIT compilation process. Use a forked process and a copying 120*0b57cec5SDimitry Andric // memory manager with IPC to execute using this functionality. 121*0b57cec5SDimitry Andric cl::opt<bool> RemoteMCJIT("remote-mcjit", 122*0b57cec5SDimitry Andric cl::desc("Execute MCJIT'ed code in a separate process."), 123*0b57cec5SDimitry Andric cl::init(false)); 124*0b57cec5SDimitry Andric 125*0b57cec5SDimitry Andric // Manually specify the child process for remote execution. This overrides 126*0b57cec5SDimitry Andric // the simulated remote execution that allocates address space for child 127*0b57cec5SDimitry Andric // execution. The child process will be executed and will communicate with 128*0b57cec5SDimitry Andric // lli via stdin/stdout pipes. 129*0b57cec5SDimitry Andric cl::opt<std::string> 130*0b57cec5SDimitry Andric ChildExecPath("mcjit-remote-process", 131*0b57cec5SDimitry Andric cl::desc("Specify the filename of the process to launch " 132*0b57cec5SDimitry Andric "for remote MCJIT execution. If none is specified," 133*0b57cec5SDimitry Andric "\n\tremote execution will be simulated in-process."), 134*0b57cec5SDimitry Andric cl::value_desc("filename"), cl::init("")); 135*0b57cec5SDimitry Andric 136*0b57cec5SDimitry Andric // Determine optimization level. 137*0b57cec5SDimitry Andric cl::opt<char> 138*0b57cec5SDimitry Andric OptLevel("O", 139*0b57cec5SDimitry Andric cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " 140*0b57cec5SDimitry Andric "(default = '-O2')"), 141*0b57cec5SDimitry Andric cl::Prefix, 142*0b57cec5SDimitry Andric cl::ZeroOrMore, 143*0b57cec5SDimitry Andric cl::init(' ')); 144*0b57cec5SDimitry Andric 145*0b57cec5SDimitry Andric cl::opt<std::string> 146*0b57cec5SDimitry Andric TargetTriple("mtriple", cl::desc("Override target triple for module")); 147*0b57cec5SDimitry Andric 148*0b57cec5SDimitry Andric cl::opt<std::string> 149*0b57cec5SDimitry Andric EntryFunc("entry-function", 150*0b57cec5SDimitry Andric cl::desc("Specify the entry function (default = 'main') " 151*0b57cec5SDimitry Andric "of the executable"), 152*0b57cec5SDimitry Andric cl::value_desc("function"), 153*0b57cec5SDimitry Andric cl::init("main")); 154*0b57cec5SDimitry Andric 155*0b57cec5SDimitry Andric cl::list<std::string> 156*0b57cec5SDimitry Andric ExtraModules("extra-module", 157*0b57cec5SDimitry Andric cl::desc("Extra modules to be loaded"), 158*0b57cec5SDimitry Andric cl::value_desc("input bitcode")); 159*0b57cec5SDimitry Andric 160*0b57cec5SDimitry Andric cl::list<std::string> 161*0b57cec5SDimitry Andric ExtraObjects("extra-object", 162*0b57cec5SDimitry Andric cl::desc("Extra object files to be loaded"), 163*0b57cec5SDimitry Andric cl::value_desc("input object")); 164*0b57cec5SDimitry Andric 165*0b57cec5SDimitry Andric cl::list<std::string> 166*0b57cec5SDimitry Andric ExtraArchives("extra-archive", 167*0b57cec5SDimitry Andric cl::desc("Extra archive files to be loaded"), 168*0b57cec5SDimitry Andric cl::value_desc("input archive")); 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric cl::opt<bool> 171*0b57cec5SDimitry Andric EnableCacheManager("enable-cache-manager", 172*0b57cec5SDimitry Andric cl::desc("Use cache manager to save/load modules"), 173*0b57cec5SDimitry Andric cl::init(false)); 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric cl::opt<std::string> 176*0b57cec5SDimitry Andric ObjectCacheDir("object-cache-dir", 177*0b57cec5SDimitry Andric cl::desc("Directory to store cached object files " 178*0b57cec5SDimitry Andric "(must be user writable)"), 179*0b57cec5SDimitry Andric cl::init("")); 180*0b57cec5SDimitry Andric 181*0b57cec5SDimitry Andric cl::opt<std::string> 182*0b57cec5SDimitry Andric FakeArgv0("fake-argv0", 183*0b57cec5SDimitry Andric cl::desc("Override the 'argv[0]' value passed into the executing" 184*0b57cec5SDimitry Andric " program"), cl::value_desc("executable")); 185*0b57cec5SDimitry Andric 186*0b57cec5SDimitry Andric cl::opt<bool> 187*0b57cec5SDimitry Andric DisableCoreFiles("disable-core-files", cl::Hidden, 188*0b57cec5SDimitry Andric cl::desc("Disable emission of core files if possible")); 189*0b57cec5SDimitry Andric 190*0b57cec5SDimitry Andric cl::opt<bool> 191*0b57cec5SDimitry Andric NoLazyCompilation("disable-lazy-compilation", 192*0b57cec5SDimitry Andric cl::desc("Disable JIT lazy compilation"), 193*0b57cec5SDimitry Andric cl::init(false)); 194*0b57cec5SDimitry Andric 195*0b57cec5SDimitry Andric cl::opt<bool> 196*0b57cec5SDimitry Andric GenerateSoftFloatCalls("soft-float", 197*0b57cec5SDimitry Andric cl::desc("Generate software floating point library calls"), 198*0b57cec5SDimitry Andric cl::init(false)); 199*0b57cec5SDimitry Andric 200*0b57cec5SDimitry Andric enum class DumpKind { 201*0b57cec5SDimitry Andric NoDump, 202*0b57cec5SDimitry Andric DumpFuncsToStdOut, 203*0b57cec5SDimitry Andric DumpModsToStdOut, 204*0b57cec5SDimitry Andric DumpModsToDisk 205*0b57cec5SDimitry Andric }; 206*0b57cec5SDimitry Andric 207*0b57cec5SDimitry Andric cl::opt<DumpKind> OrcDumpKind( 208*0b57cec5SDimitry Andric "orc-lazy-debug", cl::desc("Debug dumping for the orc-lazy JIT."), 209*0b57cec5SDimitry Andric cl::init(DumpKind::NoDump), 210*0b57cec5SDimitry Andric cl::values(clEnumValN(DumpKind::NoDump, "no-dump", 211*0b57cec5SDimitry Andric "Don't dump anything."), 212*0b57cec5SDimitry Andric clEnumValN(DumpKind::DumpFuncsToStdOut, "funcs-to-stdout", 213*0b57cec5SDimitry Andric "Dump function names to stdout."), 214*0b57cec5SDimitry Andric clEnumValN(DumpKind::DumpModsToStdOut, "mods-to-stdout", 215*0b57cec5SDimitry Andric "Dump modules to stdout."), 216*0b57cec5SDimitry Andric clEnumValN(DumpKind::DumpModsToDisk, "mods-to-disk", 217*0b57cec5SDimitry Andric "Dump modules to the current " 218*0b57cec5SDimitry Andric "working directory. (WARNING: " 219*0b57cec5SDimitry Andric "will overwrite existing files).")), 220*0b57cec5SDimitry Andric cl::Hidden); 221*0b57cec5SDimitry Andric 222*0b57cec5SDimitry Andric ExitOnError ExitOnErr; 223*0b57cec5SDimitry Andric } 224*0b57cec5SDimitry Andric 225*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 226*0b57cec5SDimitry Andric // Object cache 227*0b57cec5SDimitry Andric // 228*0b57cec5SDimitry Andric // This object cache implementation writes cached objects to disk to the 229*0b57cec5SDimitry Andric // directory specified by CacheDir, using a filename provided in the module 230*0b57cec5SDimitry Andric // descriptor. The cache tries to load a saved object using that path if the 231*0b57cec5SDimitry Andric // file exists. CacheDir defaults to "", in which case objects are cached 232*0b57cec5SDimitry Andric // alongside their originating bitcodes. 233*0b57cec5SDimitry Andric // 234*0b57cec5SDimitry Andric class LLIObjectCache : public ObjectCache { 235*0b57cec5SDimitry Andric public: 236*0b57cec5SDimitry Andric LLIObjectCache(const std::string& CacheDir) : CacheDir(CacheDir) { 237*0b57cec5SDimitry Andric // Add trailing '/' to cache dir if necessary. 238*0b57cec5SDimitry Andric if (!this->CacheDir.empty() && 239*0b57cec5SDimitry Andric this->CacheDir[this->CacheDir.size() - 1] != '/') 240*0b57cec5SDimitry Andric this->CacheDir += '/'; 241*0b57cec5SDimitry Andric } 242*0b57cec5SDimitry Andric ~LLIObjectCache() override {} 243*0b57cec5SDimitry Andric 244*0b57cec5SDimitry Andric void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override { 245*0b57cec5SDimitry Andric const std::string &ModuleID = M->getModuleIdentifier(); 246*0b57cec5SDimitry Andric std::string CacheName; 247*0b57cec5SDimitry Andric if (!getCacheFilename(ModuleID, CacheName)) 248*0b57cec5SDimitry Andric return; 249*0b57cec5SDimitry Andric if (!CacheDir.empty()) { // Create user-defined cache dir. 250*0b57cec5SDimitry Andric SmallString<128> dir(sys::path::parent_path(CacheName)); 251*0b57cec5SDimitry Andric sys::fs::create_directories(Twine(dir)); 252*0b57cec5SDimitry Andric } 253*0b57cec5SDimitry Andric std::error_code EC; 254*0b57cec5SDimitry Andric raw_fd_ostream outfile(CacheName, EC, sys::fs::F_None); 255*0b57cec5SDimitry Andric outfile.write(Obj.getBufferStart(), Obj.getBufferSize()); 256*0b57cec5SDimitry Andric outfile.close(); 257*0b57cec5SDimitry Andric } 258*0b57cec5SDimitry Andric 259*0b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> getObject(const Module* M) override { 260*0b57cec5SDimitry Andric const std::string &ModuleID = M->getModuleIdentifier(); 261*0b57cec5SDimitry Andric std::string CacheName; 262*0b57cec5SDimitry Andric if (!getCacheFilename(ModuleID, CacheName)) 263*0b57cec5SDimitry Andric return nullptr; 264*0b57cec5SDimitry Andric // Load the object from the cache filename 265*0b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> IRObjectBuffer = 266*0b57cec5SDimitry Andric MemoryBuffer::getFile(CacheName, -1, false); 267*0b57cec5SDimitry Andric // If the file isn't there, that's OK. 268*0b57cec5SDimitry Andric if (!IRObjectBuffer) 269*0b57cec5SDimitry Andric return nullptr; 270*0b57cec5SDimitry Andric // MCJIT will want to write into this buffer, and we don't want that 271*0b57cec5SDimitry Andric // because the file has probably just been mmapped. Instead we make 272*0b57cec5SDimitry Andric // a copy. The filed-based buffer will be released when it goes 273*0b57cec5SDimitry Andric // out of scope. 274*0b57cec5SDimitry Andric return MemoryBuffer::getMemBufferCopy(IRObjectBuffer.get()->getBuffer()); 275*0b57cec5SDimitry Andric } 276*0b57cec5SDimitry Andric 277*0b57cec5SDimitry Andric private: 278*0b57cec5SDimitry Andric std::string CacheDir; 279*0b57cec5SDimitry Andric 280*0b57cec5SDimitry Andric bool getCacheFilename(const std::string &ModID, std::string &CacheName) { 281*0b57cec5SDimitry Andric std::string Prefix("file:"); 282*0b57cec5SDimitry Andric size_t PrefixLength = Prefix.length(); 283*0b57cec5SDimitry Andric if (ModID.substr(0, PrefixLength) != Prefix) 284*0b57cec5SDimitry Andric return false; 285*0b57cec5SDimitry Andric std::string CacheSubdir = ModID.substr(PrefixLength); 286*0b57cec5SDimitry Andric #if defined(_WIN32) 287*0b57cec5SDimitry Andric // Transform "X:\foo" => "/X\foo" for convenience. 288*0b57cec5SDimitry Andric if (isalpha(CacheSubdir[0]) && CacheSubdir[1] == ':') { 289*0b57cec5SDimitry Andric CacheSubdir[1] = CacheSubdir[0]; 290*0b57cec5SDimitry Andric CacheSubdir[0] = '/'; 291*0b57cec5SDimitry Andric } 292*0b57cec5SDimitry Andric #endif 293*0b57cec5SDimitry Andric CacheName = CacheDir + CacheSubdir; 294*0b57cec5SDimitry Andric size_t pos = CacheName.rfind('.'); 295*0b57cec5SDimitry Andric CacheName.replace(pos, CacheName.length() - pos, ".o"); 296*0b57cec5SDimitry Andric return true; 297*0b57cec5SDimitry Andric } 298*0b57cec5SDimitry Andric }; 299*0b57cec5SDimitry Andric 300*0b57cec5SDimitry Andric // On Mingw and Cygwin, an external symbol named '__main' is called from the 301*0b57cec5SDimitry Andric // generated 'main' function to allow static initialization. To avoid linking 302*0b57cec5SDimitry Andric // problems with remote targets (because lli's remote target support does not 303*0b57cec5SDimitry Andric // currently handle external linking) we add a secondary module which defines 304*0b57cec5SDimitry Andric // an empty '__main' function. 305*0b57cec5SDimitry Andric static void addCygMingExtraModule(ExecutionEngine &EE, LLVMContext &Context, 306*0b57cec5SDimitry Andric StringRef TargetTripleStr) { 307*0b57cec5SDimitry Andric IRBuilder<> Builder(Context); 308*0b57cec5SDimitry Andric Triple TargetTriple(TargetTripleStr); 309*0b57cec5SDimitry Andric 310*0b57cec5SDimitry Andric // Create a new module. 311*0b57cec5SDimitry Andric std::unique_ptr<Module> M = make_unique<Module>("CygMingHelper", Context); 312*0b57cec5SDimitry Andric M->setTargetTriple(TargetTripleStr); 313*0b57cec5SDimitry Andric 314*0b57cec5SDimitry Andric // Create an empty function named "__main". 315*0b57cec5SDimitry Andric Type *ReturnTy; 316*0b57cec5SDimitry Andric if (TargetTriple.isArch64Bit()) 317*0b57cec5SDimitry Andric ReturnTy = Type::getInt64Ty(Context); 318*0b57cec5SDimitry Andric else 319*0b57cec5SDimitry Andric ReturnTy = Type::getInt32Ty(Context); 320*0b57cec5SDimitry Andric Function *Result = 321*0b57cec5SDimitry Andric Function::Create(FunctionType::get(ReturnTy, {}, false), 322*0b57cec5SDimitry Andric GlobalValue::ExternalLinkage, "__main", M.get()); 323*0b57cec5SDimitry Andric 324*0b57cec5SDimitry Andric BasicBlock *BB = BasicBlock::Create(Context, "__main", Result); 325*0b57cec5SDimitry Andric Builder.SetInsertPoint(BB); 326*0b57cec5SDimitry Andric Value *ReturnVal = ConstantInt::get(ReturnTy, 0); 327*0b57cec5SDimitry Andric Builder.CreateRet(ReturnVal); 328*0b57cec5SDimitry Andric 329*0b57cec5SDimitry Andric // Add this new module to the ExecutionEngine. 330*0b57cec5SDimitry Andric EE.addModule(std::move(M)); 331*0b57cec5SDimitry Andric } 332*0b57cec5SDimitry Andric 333*0b57cec5SDimitry Andric CodeGenOpt::Level getOptLevel() { 334*0b57cec5SDimitry Andric switch (OptLevel) { 335*0b57cec5SDimitry Andric default: 336*0b57cec5SDimitry Andric WithColor::error(errs(), "lli") << "invalid optimization level.\n"; 337*0b57cec5SDimitry Andric exit(1); 338*0b57cec5SDimitry Andric case '0': return CodeGenOpt::None; 339*0b57cec5SDimitry Andric case '1': return CodeGenOpt::Less; 340*0b57cec5SDimitry Andric case ' ': 341*0b57cec5SDimitry Andric case '2': return CodeGenOpt::Default; 342*0b57cec5SDimitry Andric case '3': return CodeGenOpt::Aggressive; 343*0b57cec5SDimitry Andric } 344*0b57cec5SDimitry Andric llvm_unreachable("Unrecognized opt level."); 345*0b57cec5SDimitry Andric } 346*0b57cec5SDimitry Andric 347*0b57cec5SDimitry Andric LLVM_ATTRIBUTE_NORETURN 348*0b57cec5SDimitry Andric static void reportError(SMDiagnostic Err, const char *ProgName) { 349*0b57cec5SDimitry Andric Err.print(ProgName, errs()); 350*0b57cec5SDimitry Andric exit(1); 351*0b57cec5SDimitry Andric } 352*0b57cec5SDimitry Andric 353*0b57cec5SDimitry Andric int runOrcLazyJIT(const char *ProgName); 354*0b57cec5SDimitry Andric void disallowOrcOptions(); 355*0b57cec5SDimitry Andric 356*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 357*0b57cec5SDimitry Andric // main Driver function 358*0b57cec5SDimitry Andric // 359*0b57cec5SDimitry Andric int main(int argc, char **argv, char * const *envp) { 360*0b57cec5SDimitry Andric InitLLVM X(argc, argv); 361*0b57cec5SDimitry Andric 362*0b57cec5SDimitry Andric if (argc > 1) 363*0b57cec5SDimitry Andric ExitOnErr.setBanner(std::string(argv[0]) + ": "); 364*0b57cec5SDimitry Andric 365*0b57cec5SDimitry Andric // If we have a native target, initialize it to ensure it is linked in and 366*0b57cec5SDimitry Andric // usable by the JIT. 367*0b57cec5SDimitry Andric InitializeNativeTarget(); 368*0b57cec5SDimitry Andric InitializeNativeTargetAsmPrinter(); 369*0b57cec5SDimitry Andric InitializeNativeTargetAsmParser(); 370*0b57cec5SDimitry Andric 371*0b57cec5SDimitry Andric cl::ParseCommandLineOptions(argc, argv, 372*0b57cec5SDimitry Andric "llvm interpreter & dynamic compiler\n"); 373*0b57cec5SDimitry Andric 374*0b57cec5SDimitry Andric // If the user doesn't want core files, disable them. 375*0b57cec5SDimitry Andric if (DisableCoreFiles) 376*0b57cec5SDimitry Andric sys::Process::PreventCoreFiles(); 377*0b57cec5SDimitry Andric 378*0b57cec5SDimitry Andric if (UseJITKind == JITKind::OrcLazy) 379*0b57cec5SDimitry Andric return runOrcLazyJIT(argv[0]); 380*0b57cec5SDimitry Andric else 381*0b57cec5SDimitry Andric disallowOrcOptions(); 382*0b57cec5SDimitry Andric 383*0b57cec5SDimitry Andric LLVMContext Context; 384*0b57cec5SDimitry Andric 385*0b57cec5SDimitry Andric // Load the bitcode... 386*0b57cec5SDimitry Andric SMDiagnostic Err; 387*0b57cec5SDimitry Andric std::unique_ptr<Module> Owner = parseIRFile(InputFile, Err, Context); 388*0b57cec5SDimitry Andric Module *Mod = Owner.get(); 389*0b57cec5SDimitry Andric if (!Mod) 390*0b57cec5SDimitry Andric reportError(Err, argv[0]); 391*0b57cec5SDimitry Andric 392*0b57cec5SDimitry Andric if (EnableCacheManager) { 393*0b57cec5SDimitry Andric std::string CacheName("file:"); 394*0b57cec5SDimitry Andric CacheName.append(InputFile); 395*0b57cec5SDimitry Andric Mod->setModuleIdentifier(CacheName); 396*0b57cec5SDimitry Andric } 397*0b57cec5SDimitry Andric 398*0b57cec5SDimitry Andric // If not jitting lazily, load the whole bitcode file eagerly too. 399*0b57cec5SDimitry Andric if (NoLazyCompilation) { 400*0b57cec5SDimitry Andric // Use *argv instead of argv[0] to work around a wrong GCC warning. 401*0b57cec5SDimitry Andric ExitOnError ExitOnErr(std::string(*argv) + 402*0b57cec5SDimitry Andric ": bitcode didn't read correctly: "); 403*0b57cec5SDimitry Andric ExitOnErr(Mod->materializeAll()); 404*0b57cec5SDimitry Andric } 405*0b57cec5SDimitry Andric 406*0b57cec5SDimitry Andric std::string ErrorMsg; 407*0b57cec5SDimitry Andric EngineBuilder builder(std::move(Owner)); 408*0b57cec5SDimitry Andric builder.setMArch(MArch); 409*0b57cec5SDimitry Andric builder.setMCPU(getCPUStr()); 410*0b57cec5SDimitry Andric builder.setMAttrs(getFeatureList()); 411*0b57cec5SDimitry Andric if (RelocModel.getNumOccurrences()) 412*0b57cec5SDimitry Andric builder.setRelocationModel(RelocModel); 413*0b57cec5SDimitry Andric if (CMModel.getNumOccurrences()) 414*0b57cec5SDimitry Andric builder.setCodeModel(CMModel); 415*0b57cec5SDimitry Andric builder.setErrorStr(&ErrorMsg); 416*0b57cec5SDimitry Andric builder.setEngineKind(ForceInterpreter 417*0b57cec5SDimitry Andric ? EngineKind::Interpreter 418*0b57cec5SDimitry Andric : EngineKind::JIT); 419*0b57cec5SDimitry Andric builder.setUseOrcMCJITReplacement(AcknowledgeORCv1Deprecation, 420*0b57cec5SDimitry Andric UseJITKind == JITKind::OrcMCJITReplacement); 421*0b57cec5SDimitry Andric 422*0b57cec5SDimitry Andric // If we are supposed to override the target triple, do so now. 423*0b57cec5SDimitry Andric if (!TargetTriple.empty()) 424*0b57cec5SDimitry Andric Mod->setTargetTriple(Triple::normalize(TargetTriple)); 425*0b57cec5SDimitry Andric 426*0b57cec5SDimitry Andric // Enable MCJIT if desired. 427*0b57cec5SDimitry Andric RTDyldMemoryManager *RTDyldMM = nullptr; 428*0b57cec5SDimitry Andric if (!ForceInterpreter) { 429*0b57cec5SDimitry Andric if (RemoteMCJIT) 430*0b57cec5SDimitry Andric RTDyldMM = new ForwardingMemoryManager(); 431*0b57cec5SDimitry Andric else 432*0b57cec5SDimitry Andric RTDyldMM = new SectionMemoryManager(); 433*0b57cec5SDimitry Andric 434*0b57cec5SDimitry Andric // Deliberately construct a temp std::unique_ptr to pass in. Do not null out 435*0b57cec5SDimitry Andric // RTDyldMM: We still use it below, even though we don't own it. 436*0b57cec5SDimitry Andric builder.setMCJITMemoryManager( 437*0b57cec5SDimitry Andric std::unique_ptr<RTDyldMemoryManager>(RTDyldMM)); 438*0b57cec5SDimitry Andric } else if (RemoteMCJIT) { 439*0b57cec5SDimitry Andric WithColor::error(errs(), argv[0]) 440*0b57cec5SDimitry Andric << "remote process execution does not work with the interpreter.\n"; 441*0b57cec5SDimitry Andric exit(1); 442*0b57cec5SDimitry Andric } 443*0b57cec5SDimitry Andric 444*0b57cec5SDimitry Andric builder.setOptLevel(getOptLevel()); 445*0b57cec5SDimitry Andric 446*0b57cec5SDimitry Andric TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 447*0b57cec5SDimitry Andric if (FloatABIForCalls != FloatABI::Default) 448*0b57cec5SDimitry Andric Options.FloatABIType = FloatABIForCalls; 449*0b57cec5SDimitry Andric 450*0b57cec5SDimitry Andric builder.setTargetOptions(Options); 451*0b57cec5SDimitry Andric 452*0b57cec5SDimitry Andric std::unique_ptr<ExecutionEngine> EE(builder.create()); 453*0b57cec5SDimitry Andric if (!EE) { 454*0b57cec5SDimitry Andric if (!ErrorMsg.empty()) 455*0b57cec5SDimitry Andric WithColor::error(errs(), argv[0]) 456*0b57cec5SDimitry Andric << "error creating EE: " << ErrorMsg << "\n"; 457*0b57cec5SDimitry Andric else 458*0b57cec5SDimitry Andric WithColor::error(errs(), argv[0]) << "unknown error creating EE!\n"; 459*0b57cec5SDimitry Andric exit(1); 460*0b57cec5SDimitry Andric } 461*0b57cec5SDimitry Andric 462*0b57cec5SDimitry Andric std::unique_ptr<LLIObjectCache> CacheManager; 463*0b57cec5SDimitry Andric if (EnableCacheManager) { 464*0b57cec5SDimitry Andric CacheManager.reset(new LLIObjectCache(ObjectCacheDir)); 465*0b57cec5SDimitry Andric EE->setObjectCache(CacheManager.get()); 466*0b57cec5SDimitry Andric } 467*0b57cec5SDimitry Andric 468*0b57cec5SDimitry Andric // Load any additional modules specified on the command line. 469*0b57cec5SDimitry Andric for (unsigned i = 0, e = ExtraModules.size(); i != e; ++i) { 470*0b57cec5SDimitry Andric std::unique_ptr<Module> XMod = parseIRFile(ExtraModules[i], Err, Context); 471*0b57cec5SDimitry Andric if (!XMod) 472*0b57cec5SDimitry Andric reportError(Err, argv[0]); 473*0b57cec5SDimitry Andric if (EnableCacheManager) { 474*0b57cec5SDimitry Andric std::string CacheName("file:"); 475*0b57cec5SDimitry Andric CacheName.append(ExtraModules[i]); 476*0b57cec5SDimitry Andric XMod->setModuleIdentifier(CacheName); 477*0b57cec5SDimitry Andric } 478*0b57cec5SDimitry Andric EE->addModule(std::move(XMod)); 479*0b57cec5SDimitry Andric } 480*0b57cec5SDimitry Andric 481*0b57cec5SDimitry Andric for (unsigned i = 0, e = ExtraObjects.size(); i != e; ++i) { 482*0b57cec5SDimitry Andric Expected<object::OwningBinary<object::ObjectFile>> Obj = 483*0b57cec5SDimitry Andric object::ObjectFile::createObjectFile(ExtraObjects[i]); 484*0b57cec5SDimitry Andric if (!Obj) { 485*0b57cec5SDimitry Andric // TODO: Actually report errors helpfully. 486*0b57cec5SDimitry Andric consumeError(Obj.takeError()); 487*0b57cec5SDimitry Andric reportError(Err, argv[0]); 488*0b57cec5SDimitry Andric } 489*0b57cec5SDimitry Andric object::OwningBinary<object::ObjectFile> &O = Obj.get(); 490*0b57cec5SDimitry Andric EE->addObjectFile(std::move(O)); 491*0b57cec5SDimitry Andric } 492*0b57cec5SDimitry Andric 493*0b57cec5SDimitry Andric for (unsigned i = 0, e = ExtraArchives.size(); i != e; ++i) { 494*0b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> ArBufOrErr = 495*0b57cec5SDimitry Andric MemoryBuffer::getFileOrSTDIN(ExtraArchives[i]); 496*0b57cec5SDimitry Andric if (!ArBufOrErr) 497*0b57cec5SDimitry Andric reportError(Err, argv[0]); 498*0b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> &ArBuf = ArBufOrErr.get(); 499*0b57cec5SDimitry Andric 500*0b57cec5SDimitry Andric Expected<std::unique_ptr<object::Archive>> ArOrErr = 501*0b57cec5SDimitry Andric object::Archive::create(ArBuf->getMemBufferRef()); 502*0b57cec5SDimitry Andric if (!ArOrErr) { 503*0b57cec5SDimitry Andric std::string Buf; 504*0b57cec5SDimitry Andric raw_string_ostream OS(Buf); 505*0b57cec5SDimitry Andric logAllUnhandledErrors(ArOrErr.takeError(), OS); 506*0b57cec5SDimitry Andric OS.flush(); 507*0b57cec5SDimitry Andric errs() << Buf; 508*0b57cec5SDimitry Andric exit(1); 509*0b57cec5SDimitry Andric } 510*0b57cec5SDimitry Andric std::unique_ptr<object::Archive> &Ar = ArOrErr.get(); 511*0b57cec5SDimitry Andric 512*0b57cec5SDimitry Andric object::OwningBinary<object::Archive> OB(std::move(Ar), std::move(ArBuf)); 513*0b57cec5SDimitry Andric 514*0b57cec5SDimitry Andric EE->addArchive(std::move(OB)); 515*0b57cec5SDimitry Andric } 516*0b57cec5SDimitry Andric 517*0b57cec5SDimitry Andric // If the target is Cygwin/MingW and we are generating remote code, we 518*0b57cec5SDimitry Andric // need an extra module to help out with linking. 519*0b57cec5SDimitry Andric if (RemoteMCJIT && Triple(Mod->getTargetTriple()).isOSCygMing()) { 520*0b57cec5SDimitry Andric addCygMingExtraModule(*EE, Context, Mod->getTargetTriple()); 521*0b57cec5SDimitry Andric } 522*0b57cec5SDimitry Andric 523*0b57cec5SDimitry Andric // The following functions have no effect if their respective profiling 524*0b57cec5SDimitry Andric // support wasn't enabled in the build configuration. 525*0b57cec5SDimitry Andric EE->RegisterJITEventListener( 526*0b57cec5SDimitry Andric JITEventListener::createOProfileJITEventListener()); 527*0b57cec5SDimitry Andric EE->RegisterJITEventListener( 528*0b57cec5SDimitry Andric JITEventListener::createIntelJITEventListener()); 529*0b57cec5SDimitry Andric if (!RemoteMCJIT) 530*0b57cec5SDimitry Andric EE->RegisterJITEventListener( 531*0b57cec5SDimitry Andric JITEventListener::createPerfJITEventListener()); 532*0b57cec5SDimitry Andric 533*0b57cec5SDimitry Andric if (!NoLazyCompilation && RemoteMCJIT) { 534*0b57cec5SDimitry Andric WithColor::warning(errs(), argv[0]) 535*0b57cec5SDimitry Andric << "remote mcjit does not support lazy compilation\n"; 536*0b57cec5SDimitry Andric NoLazyCompilation = true; 537*0b57cec5SDimitry Andric } 538*0b57cec5SDimitry Andric EE->DisableLazyCompilation(NoLazyCompilation); 539*0b57cec5SDimitry Andric 540*0b57cec5SDimitry Andric // If the user specifically requested an argv[0] to pass into the program, 541*0b57cec5SDimitry Andric // do it now. 542*0b57cec5SDimitry Andric if (!FakeArgv0.empty()) { 543*0b57cec5SDimitry Andric InputFile = static_cast<std::string>(FakeArgv0); 544*0b57cec5SDimitry Andric } else { 545*0b57cec5SDimitry Andric // Otherwise, if there is a .bc suffix on the executable strip it off, it 546*0b57cec5SDimitry Andric // might confuse the program. 547*0b57cec5SDimitry Andric if (StringRef(InputFile).endswith(".bc")) 548*0b57cec5SDimitry Andric InputFile.erase(InputFile.length() - 3); 549*0b57cec5SDimitry Andric } 550*0b57cec5SDimitry Andric 551*0b57cec5SDimitry Andric // Add the module's name to the start of the vector of arguments to main(). 552*0b57cec5SDimitry Andric InputArgv.insert(InputArgv.begin(), InputFile); 553*0b57cec5SDimitry Andric 554*0b57cec5SDimitry Andric // Call the main function from M as if its signature were: 555*0b57cec5SDimitry Andric // int main (int argc, char **argv, const char **envp) 556*0b57cec5SDimitry Andric // using the contents of Args to determine argc & argv, and the contents of 557*0b57cec5SDimitry Andric // EnvVars to determine envp. 558*0b57cec5SDimitry Andric // 559*0b57cec5SDimitry Andric Function *EntryFn = Mod->getFunction(EntryFunc); 560*0b57cec5SDimitry Andric if (!EntryFn) { 561*0b57cec5SDimitry Andric WithColor::error(errs(), argv[0]) 562*0b57cec5SDimitry Andric << '\'' << EntryFunc << "\' function not found in module.\n"; 563*0b57cec5SDimitry Andric return -1; 564*0b57cec5SDimitry Andric } 565*0b57cec5SDimitry Andric 566*0b57cec5SDimitry Andric // Reset errno to zero on entry to main. 567*0b57cec5SDimitry Andric errno = 0; 568*0b57cec5SDimitry Andric 569*0b57cec5SDimitry Andric int Result = -1; 570*0b57cec5SDimitry Andric 571*0b57cec5SDimitry Andric // Sanity check use of remote-jit: LLI currently only supports use of the 572*0b57cec5SDimitry Andric // remote JIT on Unix platforms. 573*0b57cec5SDimitry Andric if (RemoteMCJIT) { 574*0b57cec5SDimitry Andric #ifndef LLVM_ON_UNIX 575*0b57cec5SDimitry Andric WithColor::warning(errs(), argv[0]) 576*0b57cec5SDimitry Andric << "host does not support external remote targets.\n"; 577*0b57cec5SDimitry Andric WithColor::note() << "defaulting to local execution\n"; 578*0b57cec5SDimitry Andric return -1; 579*0b57cec5SDimitry Andric #else 580*0b57cec5SDimitry Andric if (ChildExecPath.empty()) { 581*0b57cec5SDimitry Andric WithColor::error(errs(), argv[0]) 582*0b57cec5SDimitry Andric << "-remote-mcjit requires -mcjit-remote-process.\n"; 583*0b57cec5SDimitry Andric exit(1); 584*0b57cec5SDimitry Andric } else if (!sys::fs::can_execute(ChildExecPath)) { 585*0b57cec5SDimitry Andric WithColor::error(errs(), argv[0]) 586*0b57cec5SDimitry Andric << "unable to find usable child executable: '" << ChildExecPath 587*0b57cec5SDimitry Andric << "'\n"; 588*0b57cec5SDimitry Andric return -1; 589*0b57cec5SDimitry Andric } 590*0b57cec5SDimitry Andric #endif 591*0b57cec5SDimitry Andric } 592*0b57cec5SDimitry Andric 593*0b57cec5SDimitry Andric if (!RemoteMCJIT) { 594*0b57cec5SDimitry Andric // If the program doesn't explicitly call exit, we will need the Exit 595*0b57cec5SDimitry Andric // function later on to make an explicit call, so get the function now. 596*0b57cec5SDimitry Andric FunctionCallee Exit = Mod->getOrInsertFunction( 597*0b57cec5SDimitry Andric "exit", Type::getVoidTy(Context), Type::getInt32Ty(Context)); 598*0b57cec5SDimitry Andric 599*0b57cec5SDimitry Andric // Run static constructors. 600*0b57cec5SDimitry Andric if (!ForceInterpreter) { 601*0b57cec5SDimitry Andric // Give MCJIT a chance to apply relocations and set page permissions. 602*0b57cec5SDimitry Andric EE->finalizeObject(); 603*0b57cec5SDimitry Andric } 604*0b57cec5SDimitry Andric EE->runStaticConstructorsDestructors(false); 605*0b57cec5SDimitry Andric 606*0b57cec5SDimitry Andric // Trigger compilation separately so code regions that need to be 607*0b57cec5SDimitry Andric // invalidated will be known. 608*0b57cec5SDimitry Andric (void)EE->getPointerToFunction(EntryFn); 609*0b57cec5SDimitry Andric // Clear instruction cache before code will be executed. 610*0b57cec5SDimitry Andric if (RTDyldMM) 611*0b57cec5SDimitry Andric static_cast<SectionMemoryManager*>(RTDyldMM)->invalidateInstructionCache(); 612*0b57cec5SDimitry Andric 613*0b57cec5SDimitry Andric // Run main. 614*0b57cec5SDimitry Andric Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp); 615*0b57cec5SDimitry Andric 616*0b57cec5SDimitry Andric // Run static destructors. 617*0b57cec5SDimitry Andric EE->runStaticConstructorsDestructors(true); 618*0b57cec5SDimitry Andric 619*0b57cec5SDimitry Andric // If the program didn't call exit explicitly, we should call it now. 620*0b57cec5SDimitry Andric // This ensures that any atexit handlers get called correctly. 621*0b57cec5SDimitry Andric if (Function *ExitF = 622*0b57cec5SDimitry Andric dyn_cast<Function>(Exit.getCallee()->stripPointerCasts())) { 623*0b57cec5SDimitry Andric if (ExitF->getFunctionType() == Exit.getFunctionType()) { 624*0b57cec5SDimitry Andric std::vector<GenericValue> Args; 625*0b57cec5SDimitry Andric GenericValue ResultGV; 626*0b57cec5SDimitry Andric ResultGV.IntVal = APInt(32, Result); 627*0b57cec5SDimitry Andric Args.push_back(ResultGV); 628*0b57cec5SDimitry Andric EE->runFunction(ExitF, Args); 629*0b57cec5SDimitry Andric WithColor::error(errs(), argv[0]) 630*0b57cec5SDimitry Andric << "exit(" << Result << ") returned!\n"; 631*0b57cec5SDimitry Andric abort(); 632*0b57cec5SDimitry Andric } 633*0b57cec5SDimitry Andric } 634*0b57cec5SDimitry Andric WithColor::error(errs(), argv[0]) << "exit defined with wrong prototype!\n"; 635*0b57cec5SDimitry Andric abort(); 636*0b57cec5SDimitry Andric } else { 637*0b57cec5SDimitry Andric // else == "if (RemoteMCJIT)" 638*0b57cec5SDimitry Andric 639*0b57cec5SDimitry Andric // Remote target MCJIT doesn't (yet) support static constructors. No reason 640*0b57cec5SDimitry Andric // it couldn't. This is a limitation of the LLI implementation, not the 641*0b57cec5SDimitry Andric // MCJIT itself. FIXME. 642*0b57cec5SDimitry Andric 643*0b57cec5SDimitry Andric // Lanch the remote process and get a channel to it. 644*0b57cec5SDimitry Andric std::unique_ptr<FDRawChannel> C = launchRemote(); 645*0b57cec5SDimitry Andric if (!C) { 646*0b57cec5SDimitry Andric WithColor::error(errs(), argv[0]) << "failed to launch remote JIT.\n"; 647*0b57cec5SDimitry Andric exit(1); 648*0b57cec5SDimitry Andric } 649*0b57cec5SDimitry Andric 650*0b57cec5SDimitry Andric // Create a remote target client running over the channel. 651*0b57cec5SDimitry Andric llvm::orc::ExecutionSession ES; 652*0b57cec5SDimitry Andric ES.setErrorReporter([&](Error Err) { ExitOnErr(std::move(Err)); }); 653*0b57cec5SDimitry Andric typedef orc::remote::OrcRemoteTargetClient MyRemote; 654*0b57cec5SDimitry Andric auto R = ExitOnErr(MyRemote::Create(*C, ES)); 655*0b57cec5SDimitry Andric 656*0b57cec5SDimitry Andric // Create a remote memory manager. 657*0b57cec5SDimitry Andric auto RemoteMM = ExitOnErr(R->createRemoteMemoryManager()); 658*0b57cec5SDimitry Andric 659*0b57cec5SDimitry Andric // Forward MCJIT's memory manager calls to the remote memory manager. 660*0b57cec5SDimitry Andric static_cast<ForwardingMemoryManager*>(RTDyldMM)->setMemMgr( 661*0b57cec5SDimitry Andric std::move(RemoteMM)); 662*0b57cec5SDimitry Andric 663*0b57cec5SDimitry Andric // Forward MCJIT's symbol resolution calls to the remote. 664*0b57cec5SDimitry Andric static_cast<ForwardingMemoryManager *>(RTDyldMM)->setResolver( 665*0b57cec5SDimitry Andric orc::createLambdaResolver( 666*0b57cec5SDimitry Andric AcknowledgeORCv1Deprecation, 667*0b57cec5SDimitry Andric [](const std::string &Name) { return nullptr; }, 668*0b57cec5SDimitry Andric [&](const std::string &Name) { 669*0b57cec5SDimitry Andric if (auto Addr = ExitOnErr(R->getSymbolAddress(Name))) 670*0b57cec5SDimitry Andric return JITSymbol(Addr, JITSymbolFlags::Exported); 671*0b57cec5SDimitry Andric return JITSymbol(nullptr); 672*0b57cec5SDimitry Andric })); 673*0b57cec5SDimitry Andric 674*0b57cec5SDimitry Andric // Grab the target address of the JIT'd main function on the remote and call 675*0b57cec5SDimitry Andric // it. 676*0b57cec5SDimitry Andric // FIXME: argv and envp handling. 677*0b57cec5SDimitry Andric JITTargetAddress Entry = EE->getFunctionAddress(EntryFn->getName().str()); 678*0b57cec5SDimitry Andric EE->finalizeObject(); 679*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x" 680*0b57cec5SDimitry Andric << format("%llx", Entry) << "\n"); 681*0b57cec5SDimitry Andric Result = ExitOnErr(R->callIntVoid(Entry)); 682*0b57cec5SDimitry Andric 683*0b57cec5SDimitry Andric // Like static constructors, the remote target MCJIT support doesn't handle 684*0b57cec5SDimitry Andric // this yet. It could. FIXME. 685*0b57cec5SDimitry Andric 686*0b57cec5SDimitry Andric // Delete the EE - we need to tear it down *before* we terminate the session 687*0b57cec5SDimitry Andric // with the remote, otherwise it'll crash when it tries to release resources 688*0b57cec5SDimitry Andric // on a remote that has already been disconnected. 689*0b57cec5SDimitry Andric EE.reset(); 690*0b57cec5SDimitry Andric 691*0b57cec5SDimitry Andric // Signal the remote target that we're done JITing. 692*0b57cec5SDimitry Andric ExitOnErr(R->terminateSession()); 693*0b57cec5SDimitry Andric } 694*0b57cec5SDimitry Andric 695*0b57cec5SDimitry Andric return Result; 696*0b57cec5SDimitry Andric } 697*0b57cec5SDimitry Andric 698*0b57cec5SDimitry Andric static orc::IRTransformLayer::TransformFunction createDebugDumper() { 699*0b57cec5SDimitry Andric switch (OrcDumpKind) { 700*0b57cec5SDimitry Andric case DumpKind::NoDump: 701*0b57cec5SDimitry Andric return [](orc::ThreadSafeModule TSM, 702*0b57cec5SDimitry Andric const orc::MaterializationResponsibility &R) { return TSM; }; 703*0b57cec5SDimitry Andric 704*0b57cec5SDimitry Andric case DumpKind::DumpFuncsToStdOut: 705*0b57cec5SDimitry Andric return [](orc::ThreadSafeModule TSM, 706*0b57cec5SDimitry Andric const orc::MaterializationResponsibility &R) { 707*0b57cec5SDimitry Andric printf("[ "); 708*0b57cec5SDimitry Andric 709*0b57cec5SDimitry Andric for (const auto &F : *TSM.getModule()) { 710*0b57cec5SDimitry Andric if (F.isDeclaration()) 711*0b57cec5SDimitry Andric continue; 712*0b57cec5SDimitry Andric 713*0b57cec5SDimitry Andric if (F.hasName()) { 714*0b57cec5SDimitry Andric std::string Name(F.getName()); 715*0b57cec5SDimitry Andric printf("%s ", Name.c_str()); 716*0b57cec5SDimitry Andric } else 717*0b57cec5SDimitry Andric printf("<anon> "); 718*0b57cec5SDimitry Andric } 719*0b57cec5SDimitry Andric 720*0b57cec5SDimitry Andric printf("]\n"); 721*0b57cec5SDimitry Andric return TSM; 722*0b57cec5SDimitry Andric }; 723*0b57cec5SDimitry Andric 724*0b57cec5SDimitry Andric case DumpKind::DumpModsToStdOut: 725*0b57cec5SDimitry Andric return [](orc::ThreadSafeModule TSM, 726*0b57cec5SDimitry Andric const orc::MaterializationResponsibility &R) { 727*0b57cec5SDimitry Andric outs() << "----- Module Start -----\n" 728*0b57cec5SDimitry Andric << *TSM.getModule() << "----- Module End -----\n"; 729*0b57cec5SDimitry Andric 730*0b57cec5SDimitry Andric return TSM; 731*0b57cec5SDimitry Andric }; 732*0b57cec5SDimitry Andric 733*0b57cec5SDimitry Andric case DumpKind::DumpModsToDisk: 734*0b57cec5SDimitry Andric return [](orc::ThreadSafeModule TSM, 735*0b57cec5SDimitry Andric const orc::MaterializationResponsibility &R) { 736*0b57cec5SDimitry Andric std::error_code EC; 737*0b57cec5SDimitry Andric raw_fd_ostream Out(TSM.getModule()->getModuleIdentifier() + ".ll", EC, 738*0b57cec5SDimitry Andric sys::fs::F_Text); 739*0b57cec5SDimitry Andric if (EC) { 740*0b57cec5SDimitry Andric errs() << "Couldn't open " << TSM.getModule()->getModuleIdentifier() 741*0b57cec5SDimitry Andric << " for dumping.\nError:" << EC.message() << "\n"; 742*0b57cec5SDimitry Andric exit(1); 743*0b57cec5SDimitry Andric } 744*0b57cec5SDimitry Andric Out << *TSM.getModule(); 745*0b57cec5SDimitry Andric return TSM; 746*0b57cec5SDimitry Andric }; 747*0b57cec5SDimitry Andric } 748*0b57cec5SDimitry Andric llvm_unreachable("Unknown DumpKind"); 749*0b57cec5SDimitry Andric } 750*0b57cec5SDimitry Andric 751*0b57cec5SDimitry Andric static void exitOnLazyCallThroughFailure() { exit(1); } 752*0b57cec5SDimitry Andric 753*0b57cec5SDimitry Andric int runOrcLazyJIT(const char *ProgName) { 754*0b57cec5SDimitry Andric // Start setting up the JIT environment. 755*0b57cec5SDimitry Andric 756*0b57cec5SDimitry Andric // Parse the main module. 757*0b57cec5SDimitry Andric orc::ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 758*0b57cec5SDimitry Andric SMDiagnostic Err; 759*0b57cec5SDimitry Andric auto MainModule = orc::ThreadSafeModule( 760*0b57cec5SDimitry Andric parseIRFile(InputFile, Err, *TSCtx.getContext()), TSCtx); 761*0b57cec5SDimitry Andric if (!MainModule) 762*0b57cec5SDimitry Andric reportError(Err, ProgName); 763*0b57cec5SDimitry Andric 764*0b57cec5SDimitry Andric const auto &TT = MainModule.getModule()->getTargetTriple(); 765*0b57cec5SDimitry Andric orc::LLLazyJITBuilder Builder; 766*0b57cec5SDimitry Andric 767*0b57cec5SDimitry Andric Builder.setJITTargetMachineBuilder( 768*0b57cec5SDimitry Andric TT.empty() ? ExitOnErr(orc::JITTargetMachineBuilder::detectHost()) 769*0b57cec5SDimitry Andric : orc::JITTargetMachineBuilder(Triple(TT))); 770*0b57cec5SDimitry Andric 771*0b57cec5SDimitry Andric if (!MArch.empty()) 772*0b57cec5SDimitry Andric Builder.getJITTargetMachineBuilder()->getTargetTriple().setArchName(MArch); 773*0b57cec5SDimitry Andric 774*0b57cec5SDimitry Andric Builder.getJITTargetMachineBuilder() 775*0b57cec5SDimitry Andric ->setCPU(getCPUStr()) 776*0b57cec5SDimitry Andric .addFeatures(getFeatureList()) 777*0b57cec5SDimitry Andric .setRelocationModel(RelocModel.getNumOccurrences() 778*0b57cec5SDimitry Andric ? Optional<Reloc::Model>(RelocModel) 779*0b57cec5SDimitry Andric : None) 780*0b57cec5SDimitry Andric .setCodeModel(CMModel.getNumOccurrences() 781*0b57cec5SDimitry Andric ? Optional<CodeModel::Model>(CMModel) 782*0b57cec5SDimitry Andric : None); 783*0b57cec5SDimitry Andric 784*0b57cec5SDimitry Andric Builder.setLazyCompileFailureAddr( 785*0b57cec5SDimitry Andric pointerToJITTargetAddress(exitOnLazyCallThroughFailure)); 786*0b57cec5SDimitry Andric Builder.setNumCompileThreads(LazyJITCompileThreads); 787*0b57cec5SDimitry Andric 788*0b57cec5SDimitry Andric auto J = ExitOnErr(Builder.create()); 789*0b57cec5SDimitry Andric 790*0b57cec5SDimitry Andric if (PerModuleLazy) 791*0b57cec5SDimitry Andric J->setPartitionFunction(orc::CompileOnDemandLayer::compileWholeModule); 792*0b57cec5SDimitry Andric 793*0b57cec5SDimitry Andric auto Dump = createDebugDumper(); 794*0b57cec5SDimitry Andric 795*0b57cec5SDimitry Andric J->setLazyCompileTransform([&](orc::ThreadSafeModule TSM, 796*0b57cec5SDimitry Andric const orc::MaterializationResponsibility &R) { 797*0b57cec5SDimitry Andric if (verifyModule(*TSM.getModule(), &dbgs())) { 798*0b57cec5SDimitry Andric dbgs() << "Bad module: " << *TSM.getModule() << "\n"; 799*0b57cec5SDimitry Andric exit(1); 800*0b57cec5SDimitry Andric } 801*0b57cec5SDimitry Andric return Dump(std::move(TSM), R); 802*0b57cec5SDimitry Andric }); 803*0b57cec5SDimitry Andric J->getMainJITDylib().setGenerator( 804*0b57cec5SDimitry Andric ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess( 805*0b57cec5SDimitry Andric J->getDataLayout().getGlobalPrefix()))); 806*0b57cec5SDimitry Andric 807*0b57cec5SDimitry Andric orc::MangleAndInterner Mangle(J->getExecutionSession(), J->getDataLayout()); 808*0b57cec5SDimitry Andric orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides; 809*0b57cec5SDimitry Andric ExitOnErr(CXXRuntimeOverrides.enable(J->getMainJITDylib(), Mangle)); 810*0b57cec5SDimitry Andric 811*0b57cec5SDimitry Andric // Add the main module. 812*0b57cec5SDimitry Andric ExitOnErr(J->addLazyIRModule(std::move(MainModule))); 813*0b57cec5SDimitry Andric 814*0b57cec5SDimitry Andric // Create JITDylibs and add any extra modules. 815*0b57cec5SDimitry Andric { 816*0b57cec5SDimitry Andric // Create JITDylibs, keep a map from argument index to dylib. We will use 817*0b57cec5SDimitry Andric // -extra-module argument indexes to determine what dylib to use for each 818*0b57cec5SDimitry Andric // -extra-module. 819*0b57cec5SDimitry Andric std::map<unsigned, orc::JITDylib *> IdxToDylib; 820*0b57cec5SDimitry Andric IdxToDylib[0] = &J->getMainJITDylib(); 821*0b57cec5SDimitry Andric for (auto JDItr = JITDylibs.begin(), JDEnd = JITDylibs.end(); 822*0b57cec5SDimitry Andric JDItr != JDEnd; ++JDItr) { 823*0b57cec5SDimitry Andric orc::JITDylib *JD = J->getJITDylibByName(*JDItr); 824*0b57cec5SDimitry Andric if (!JD) 825*0b57cec5SDimitry Andric JD = &J->createJITDylib(*JDItr); 826*0b57cec5SDimitry Andric IdxToDylib[JITDylibs.getPosition(JDItr - JITDylibs.begin())] = JD; 827*0b57cec5SDimitry Andric } 828*0b57cec5SDimitry Andric 829*0b57cec5SDimitry Andric for (auto EMItr = ExtraModules.begin(), EMEnd = ExtraModules.end(); 830*0b57cec5SDimitry Andric EMItr != EMEnd; ++EMItr) { 831*0b57cec5SDimitry Andric auto M = parseIRFile(*EMItr, Err, *TSCtx.getContext()); 832*0b57cec5SDimitry Andric if (!M) 833*0b57cec5SDimitry Andric reportError(Err, ProgName); 834*0b57cec5SDimitry Andric 835*0b57cec5SDimitry Andric auto EMIdx = ExtraModules.getPosition(EMItr - ExtraModules.begin()); 836*0b57cec5SDimitry Andric assert(EMIdx != 0 && "ExtraModule should have index > 0"); 837*0b57cec5SDimitry Andric auto JDItr = std::prev(IdxToDylib.lower_bound(EMIdx)); 838*0b57cec5SDimitry Andric auto &JD = *JDItr->second; 839*0b57cec5SDimitry Andric ExitOnErr( 840*0b57cec5SDimitry Andric J->addLazyIRModule(JD, orc::ThreadSafeModule(std::move(M), TSCtx))); 841*0b57cec5SDimitry Andric } 842*0b57cec5SDimitry Andric } 843*0b57cec5SDimitry Andric 844*0b57cec5SDimitry Andric // Add the objects. 845*0b57cec5SDimitry Andric for (auto &ObjPath : ExtraObjects) { 846*0b57cec5SDimitry Andric auto Obj = ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(ObjPath))); 847*0b57cec5SDimitry Andric ExitOnErr(J->addObjectFile(std::move(Obj))); 848*0b57cec5SDimitry Andric } 849*0b57cec5SDimitry Andric 850*0b57cec5SDimitry Andric // Generate a argument string. 851*0b57cec5SDimitry Andric std::vector<std::string> Args; 852*0b57cec5SDimitry Andric Args.push_back(InputFile); 853*0b57cec5SDimitry Andric for (auto &Arg : InputArgv) 854*0b57cec5SDimitry Andric Args.push_back(Arg); 855*0b57cec5SDimitry Andric 856*0b57cec5SDimitry Andric // Run any static constructors. 857*0b57cec5SDimitry Andric ExitOnErr(J->runConstructors()); 858*0b57cec5SDimitry Andric 859*0b57cec5SDimitry Andric // Run any -thread-entry points. 860*0b57cec5SDimitry Andric std::vector<std::thread> AltEntryThreads; 861*0b57cec5SDimitry Andric for (auto &ThreadEntryPoint : ThreadEntryPoints) { 862*0b57cec5SDimitry Andric auto EntryPointSym = ExitOnErr(J->lookup(ThreadEntryPoint)); 863*0b57cec5SDimitry Andric typedef void (*EntryPointPtr)(); 864*0b57cec5SDimitry Andric auto EntryPoint = 865*0b57cec5SDimitry Andric reinterpret_cast<EntryPointPtr>(static_cast<uintptr_t>(EntryPointSym.getAddress())); 866*0b57cec5SDimitry Andric AltEntryThreads.push_back(std::thread([EntryPoint]() { EntryPoint(); })); 867*0b57cec5SDimitry Andric } 868*0b57cec5SDimitry Andric 869*0b57cec5SDimitry Andric // Run main. 870*0b57cec5SDimitry Andric auto MainSym = ExitOnErr(J->lookup("main")); 871*0b57cec5SDimitry Andric typedef int (*MainFnPtr)(int, const char *[]); 872*0b57cec5SDimitry Andric std::vector<const char *> ArgV; 873*0b57cec5SDimitry Andric for (auto &Arg : Args) 874*0b57cec5SDimitry Andric ArgV.push_back(Arg.c_str()); 875*0b57cec5SDimitry Andric ArgV.push_back(nullptr); 876*0b57cec5SDimitry Andric 877*0b57cec5SDimitry Andric int ArgC = ArgV.size() - 1; 878*0b57cec5SDimitry Andric auto Main = 879*0b57cec5SDimitry Andric reinterpret_cast<MainFnPtr>(static_cast<uintptr_t>(MainSym.getAddress())); 880*0b57cec5SDimitry Andric auto Result = Main(ArgC, (const char **)ArgV.data()); 881*0b57cec5SDimitry Andric 882*0b57cec5SDimitry Andric // Wait for -entry-point threads. 883*0b57cec5SDimitry Andric for (auto &AltEntryThread : AltEntryThreads) 884*0b57cec5SDimitry Andric AltEntryThread.join(); 885*0b57cec5SDimitry Andric 886*0b57cec5SDimitry Andric // Run destructors. 887*0b57cec5SDimitry Andric ExitOnErr(J->runDestructors()); 888*0b57cec5SDimitry Andric CXXRuntimeOverrides.runDestructors(); 889*0b57cec5SDimitry Andric 890*0b57cec5SDimitry Andric return Result; 891*0b57cec5SDimitry Andric } 892*0b57cec5SDimitry Andric 893*0b57cec5SDimitry Andric void disallowOrcOptions() { 894*0b57cec5SDimitry Andric // Make sure nobody used an orc-lazy specific option accidentally. 895*0b57cec5SDimitry Andric 896*0b57cec5SDimitry Andric if (LazyJITCompileThreads != 0) { 897*0b57cec5SDimitry Andric errs() << "-compile-threads requires -jit-kind=orc-lazy\n"; 898*0b57cec5SDimitry Andric exit(1); 899*0b57cec5SDimitry Andric } 900*0b57cec5SDimitry Andric 901*0b57cec5SDimitry Andric if (!ThreadEntryPoints.empty()) { 902*0b57cec5SDimitry Andric errs() << "-thread-entry requires -jit-kind=orc-lazy\n"; 903*0b57cec5SDimitry Andric exit(1); 904*0b57cec5SDimitry Andric } 905*0b57cec5SDimitry Andric 906*0b57cec5SDimitry Andric if (PerModuleLazy) { 907*0b57cec5SDimitry Andric errs() << "-per-module-lazy requires -jit-kind=orc-lazy\n"; 908*0b57cec5SDimitry Andric exit(1); 909*0b57cec5SDimitry Andric } 910*0b57cec5SDimitry Andric } 911*0b57cec5SDimitry Andric 912*0b57cec5SDimitry Andric std::unique_ptr<FDRawChannel> launchRemote() { 913*0b57cec5SDimitry Andric #ifndef LLVM_ON_UNIX 914*0b57cec5SDimitry Andric llvm_unreachable("launchRemote not supported on non-Unix platforms"); 915*0b57cec5SDimitry Andric #else 916*0b57cec5SDimitry Andric int PipeFD[2][2]; 917*0b57cec5SDimitry Andric pid_t ChildPID; 918*0b57cec5SDimitry Andric 919*0b57cec5SDimitry Andric // Create two pipes. 920*0b57cec5SDimitry Andric if (pipe(PipeFD[0]) != 0 || pipe(PipeFD[1]) != 0) 921*0b57cec5SDimitry Andric perror("Error creating pipe: "); 922*0b57cec5SDimitry Andric 923*0b57cec5SDimitry Andric ChildPID = fork(); 924*0b57cec5SDimitry Andric 925*0b57cec5SDimitry Andric if (ChildPID == 0) { 926*0b57cec5SDimitry Andric // In the child... 927*0b57cec5SDimitry Andric 928*0b57cec5SDimitry Andric // Close the parent ends of the pipes 929*0b57cec5SDimitry Andric close(PipeFD[0][1]); 930*0b57cec5SDimitry Andric close(PipeFD[1][0]); 931*0b57cec5SDimitry Andric 932*0b57cec5SDimitry Andric 933*0b57cec5SDimitry Andric // Execute the child process. 934*0b57cec5SDimitry Andric std::unique_ptr<char[]> ChildPath, ChildIn, ChildOut; 935*0b57cec5SDimitry Andric { 936*0b57cec5SDimitry Andric ChildPath.reset(new char[ChildExecPath.size() + 1]); 937*0b57cec5SDimitry Andric std::copy(ChildExecPath.begin(), ChildExecPath.end(), &ChildPath[0]); 938*0b57cec5SDimitry Andric ChildPath[ChildExecPath.size()] = '\0'; 939*0b57cec5SDimitry Andric std::string ChildInStr = utostr(PipeFD[0][0]); 940*0b57cec5SDimitry Andric ChildIn.reset(new char[ChildInStr.size() + 1]); 941*0b57cec5SDimitry Andric std::copy(ChildInStr.begin(), ChildInStr.end(), &ChildIn[0]); 942*0b57cec5SDimitry Andric ChildIn[ChildInStr.size()] = '\0'; 943*0b57cec5SDimitry Andric std::string ChildOutStr = utostr(PipeFD[1][1]); 944*0b57cec5SDimitry Andric ChildOut.reset(new char[ChildOutStr.size() + 1]); 945*0b57cec5SDimitry Andric std::copy(ChildOutStr.begin(), ChildOutStr.end(), &ChildOut[0]); 946*0b57cec5SDimitry Andric ChildOut[ChildOutStr.size()] = '\0'; 947*0b57cec5SDimitry Andric } 948*0b57cec5SDimitry Andric 949*0b57cec5SDimitry Andric char * const args[] = { &ChildPath[0], &ChildIn[0], &ChildOut[0], nullptr }; 950*0b57cec5SDimitry Andric int rc = execv(ChildExecPath.c_str(), args); 951*0b57cec5SDimitry Andric if (rc != 0) 952*0b57cec5SDimitry Andric perror("Error executing child process: "); 953*0b57cec5SDimitry Andric llvm_unreachable("Error executing child process"); 954*0b57cec5SDimitry Andric } 955*0b57cec5SDimitry Andric // else we're the parent... 956*0b57cec5SDimitry Andric 957*0b57cec5SDimitry Andric // Close the child ends of the pipes 958*0b57cec5SDimitry Andric close(PipeFD[0][0]); 959*0b57cec5SDimitry Andric close(PipeFD[1][1]); 960*0b57cec5SDimitry Andric 961*0b57cec5SDimitry Andric // Return an RPC channel connected to our end of the pipes. 962*0b57cec5SDimitry Andric return llvm::make_unique<FDRawChannel>(PipeFD[1][0], PipeFD[0][1]); 963*0b57cec5SDimitry Andric #endif 964*0b57cec5SDimitry Andric } 965