]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lli/OrcLazyJIT.cpp
Merge bmake-20180512
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lli / OrcLazyJIT.cpp
1 //===- OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution ------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
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"
18 #include <cstdint>
19 #include <cstdio>
20 #include <cstdlib>
21 #include <system_error>
22
23 using namespace llvm;
24
25 namespace {
26
27 enum class DumpKind {
28   NoDump,
29   DumpFuncsToStdOut,
30   DumpModsToStdOut,
31   DumpModsToDisk
32 };
33
34 } // end anonymous namespace
35
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).")),
48     cl::Hidden);
49
50 static cl::opt<bool> OrcInlineStubs("orc-lazy-inline-stubs",
51                                     cl::desc("Try to inline stubs"),
52                                     cl::init(true), cl::Hidden);
53
54 OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
55   switch (OrcDumpKind) {
56   case DumpKind::NoDump:
57     return [](std::shared_ptr<Module> M) { return M; };
58
59   case DumpKind::DumpFuncsToStdOut:
60     return [](std::shared_ptr<Module> M) {
61       printf("[ ");
62
63       for (const auto &F : *M) {
64         if (F.isDeclaration())
65           continue;
66
67         if (F.hasName()) {
68           std::string Name(F.getName());
69           printf("%s ", Name.c_str());
70         } else
71           printf("<anon> ");
72       }
73
74       printf("]\n");
75       return M;
76     };
77
78   case DumpKind::DumpModsToStdOut:
79     return [](std::shared_ptr<Module> M) {
80              outs() << "----- Module Start -----\n" << *M
81                     << "----- Module End -----\n";
82
83              return M;
84            };
85
86   case DumpKind::DumpModsToDisk:
87     return [](std::shared_ptr<Module> M) {
88              std::error_code EC;
89              raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC,
90                                 sys::fs::F_Text);
91              if (EC) {
92                errs() << "Couldn't open " << M->getModuleIdentifier()
93                       << " for dumping.\nError:" << EC.message() << "\n";
94                exit(1);
95              }
96              Out << *M;
97              return M;
98            };
99   }
100   llvm_unreachable("Unknown DumpKind");
101 }
102
103 // Defined in lli.cpp.
104 CodeGenOpt::Level getOptLevel();
105
106 template <typename PtrTy>
107 static PtrTy fromTargetAddress(JITTargetAddress Addr) {
108   return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
109 }
110
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";
116     return 1;
117   }
118
119   // Grab a target machine and try to build a factory function for the
120   // target-specific Orc callback manager.
121   EngineBuilder EB;
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);
126
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";
132     return 1;
133   }
134
135   auto IndirectStubsMgrBuilder = orc::createLocalIndirectStubsManagerBuilder(T);
136
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";
141     return 1;
142   }
143
144   // Everything looks good. Build the JIT.
145   OrcLazyJIT J(std::move(TM), std::move(CompileCallbackMgr),
146                std::move(IndirectStubsMgrBuilder),
147                OrcInlineStubs);
148
149   // Add the module, look up main and run it.
150   for (auto &M : Ms)
151     cantFail(J.addModule(std::shared_ptr<Module>(std::move(M))));
152
153   if (auto MainSym = J.findSymbol("main")) {
154     typedef int (*MainFnPtr)(int, const char*[]);
155     std::vector<const char *> ArgV;
156     for (auto &Arg : Args)
157       ArgV.push_back(Arg.c_str());
158     auto Main = fromTargetAddress<MainFnPtr>(cantFail(MainSym.getAddress()));
159     return Main(ArgV.size(), (const char**)ArgV.data());
160   } else if (auto Err = MainSym.takeError())
161     logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
162   else
163     errs() << "Could not find main function.\n";
164
165   return 1;
166 }