xref: /freebsd/contrib/llvm-project/llvm/tools/lli/lli.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
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