1 //===- OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution ------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "OrcLazyJIT.h"
11 #include "llvm/ADT/Triple.h"
12 #include "llvm/ExecutionEngine/ExecutionEngine.h"
13 #include "llvm/Support/CodeGen.h"
14 #include "llvm/Support/CommandLine.h"
15 #include "llvm/Support/DynamicLibrary.h"
16 #include "llvm/Support/ErrorHandling.h"
17 #include "llvm/Support/FileSystem.h"
21 #include <system_error>
34 } // end anonymous namespace
36 static cl::opt<DumpKind> OrcDumpKind(
37 "orc-lazy-debug", cl::desc("Debug dumping for the orc-lazy JIT."),
38 cl::init(DumpKind::NoDump),
39 cl::values(clEnumValN(DumpKind::NoDump, "no-dump", "Don't dump anything."),
40 clEnumValN(DumpKind::DumpFuncsToStdOut, "funcs-to-stdout",
41 "Dump function names to stdout."),
42 clEnumValN(DumpKind::DumpModsToStdOut, "mods-to-stdout",
43 "Dump modules to stdout."),
44 clEnumValN(DumpKind::DumpModsToDisk, "mods-to-disk",
45 "Dump modules to the current "
46 "working directory. (WARNING: "
47 "will overwrite existing files).")),
50 static cl::opt<bool> OrcInlineStubs("orc-lazy-inline-stubs",
51 cl::desc("Try to inline stubs"),
52 cl::init(true), cl::Hidden);
54 OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
55 switch (OrcDumpKind) {
56 case DumpKind::NoDump:
57 return [](std::shared_ptr<Module> M) { return M; };
59 case DumpKind::DumpFuncsToStdOut:
60 return [](std::shared_ptr<Module> M) {
63 for (const auto &F : *M) {
64 if (F.isDeclaration())
68 std::string Name(F.getName());
69 printf("%s ", Name.c_str());
78 case DumpKind::DumpModsToStdOut:
79 return [](std::shared_ptr<Module> M) {
80 outs() << "----- Module Start -----\n" << *M
81 << "----- Module End -----\n";
86 case DumpKind::DumpModsToDisk:
87 return [](std::shared_ptr<Module> M) {
89 raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC,
92 errs() << "Couldn't open " << M->getModuleIdentifier()
93 << " for dumping.\nError:" << EC.message() << "\n";
100 llvm_unreachable("Unknown DumpKind");
103 // Defined in lli.cpp.
104 CodeGenOpt::Level getOptLevel();
106 template <typename PtrTy>
107 static PtrTy fromTargetAddress(JITTargetAddress Addr) {
108 return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
111 int llvm::runOrcLazyJIT(std::vector<std::unique_ptr<Module>> Ms,
112 const std::vector<std::string> &Args) {
113 // Add the program's symbols into the JIT's search space.
114 if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {
115 errs() << "Error loading program symbols.\n";
119 // Grab a target machine and try to build a factory function for the
120 // target-specific Orc callback manager.
122 EB.setOptLevel(getOptLevel());
123 auto TM = std::unique_ptr<TargetMachine>(EB.selectTarget());
124 Triple T(TM->getTargetTriple());
125 auto CompileCallbackMgr = orc::createLocalCompileCallbackManager(T, 0);
127 // If we couldn't build the factory function then there must not be a callback
128 // manager for this target. Bail out.
129 if (!CompileCallbackMgr) {
130 errs() << "No callback manager available for target '"
131 << TM->getTargetTriple().str() << "'.\n";
135 auto IndirectStubsMgrBuilder = orc::createLocalIndirectStubsManagerBuilder(T);
137 // If we couldn't build a stubs-manager-builder for this target then bail out.
138 if (!IndirectStubsMgrBuilder) {
139 errs() << "No indirect stubs manager available for target '"
140 << TM->getTargetTriple().str() << "'.\n";
144 // Everything looks good. Build the JIT.
145 OrcLazyJIT J(std::move(TM), std::move(CompileCallbackMgr),
146 std::move(IndirectStubsMgrBuilder),
149 // Add the module, look up main and run it.
151 J.addModule(std::shared_ptr<Module>(std::move(M)));
152 auto MainSym = J.findSymbol("main");
155 errs() << "Could not find main function.\n";
159 using MainFnPtr = int (*)(int, const char*[]);
160 std::vector<const char *> ArgV;
161 for (auto &Arg : Args)
162 ArgV.push_back(Arg.c_str());
163 auto Main = fromTargetAddress<MainFnPtr>(MainSym.getAddress());
164 return Main(ArgV.size(), (const char**)ArgV.data());