blob: 31edabd6a29848aaf2b1b176210d2ff317c7a4ba [file] [log] [blame]
Eugene Zelenkof292a2f2017-06-19 23:37:52 +00001//===- OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution ------------===//
Lang Hames9528bba2015-03-25 12:11:48 +00002//
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"
Eugene Zelenkof292a2f2017-06-19 23:37:52 +000011#include "llvm/ADT/Triple.h"
12#include "llvm/ExecutionEngine/ExecutionEngine.h"
13#include "llvm/Support/CodeGen.h"
14#include "llvm/Support/CommandLine.h"
Lang Hames5a9808b2015-04-01 04:42:56 +000015#include "llvm/Support/DynamicLibrary.h"
Eugene Zelenkof292a2f2017-06-19 23:37:52 +000016#include "llvm/Support/ErrorHandling.h"
17#include "llvm/Support/FileSystem.h"
18#include <cstdint>
NAKAMURA Takumi57ac0572015-04-17 10:01:30 +000019#include <cstdio>
Eugene Zelenkof292a2f2017-06-19 23:37:52 +000020#include <cstdlib>
Lang Hamescd3fd832015-04-13 22:12:54 +000021#include <system_error>
Lang Hames9528bba2015-03-25 12:11:48 +000022
23using namespace llvm;
24
Lang Hamescd3fd832015-04-13 22:12:54 +000025namespace {
26
Eugene Zelenkof292a2f2017-06-19 23:37:52 +000027enum class DumpKind {
28 NoDump,
29 DumpFuncsToStdOut,
30 DumpModsToStdOut,
31 DumpModsToDisk
32};
Lang Hamescd3fd832015-04-13 22:12:54 +000033
Eugene Zelenkof292a2f2017-06-19 23:37:52 +000034} // end anonymous namespace
Lang Hames98c2ac12015-10-19 17:43:51 +000035
Eugene Zelenkof292a2f2017-06-19 23:37:52 +000036static 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
50static cl::opt<bool> OrcInlineStubs("orc-lazy-inline-stubs",
51 cl::desc("Try to inline stubs"),
52 cl::init(true), cl::Hidden);
Lang Hamescd3fd832015-04-13 22:12:54 +000053
Lang Hamescd3fd832015-04-13 22:12:54 +000054OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
Lang Hamescd3fd832015-04-13 22:12:54 +000055 switch (OrcDumpKind) {
56 case DumpKind::NoDump:
Lang Hames5721ee42018-03-15 00:30:14 +000057 return [](std::unique_ptr<Module> M) { return M; };
Lang Hamescd3fd832015-04-13 22:12:54 +000058
Lang Hames42859b842015-04-14 16:58:05 +000059 case DumpKind::DumpFuncsToStdOut:
Lang Hames5721ee42018-03-15 00:30:14 +000060 return [](std::unique_ptr<Module> M) {
Lang Hames42859b842015-04-14 16:58:05 +000061 printf("[ ");
Lang Hamescd3fd832015-04-13 22:12:54 +000062
63 for (const auto &F : *M) {
64 if (F.isDeclaration())
65 continue;
66
Lang Hames42859b842015-04-14 16:58:05 +000067 if (F.hasName()) {
68 std::string Name(F.getName());
69 printf("%s ", Name.c_str());
70 } else
71 printf("<anon> ");
Lang Hamescd3fd832015-04-13 22:12:54 +000072 }
73
Lang Hames42859b842015-04-14 16:58:05 +000074 printf("]\n");
Richard Trieu6ae37962015-04-30 23:07:00 +000075 return M;
Lang Hamescd3fd832015-04-13 22:12:54 +000076 };
77
Lang Hames38c79272016-09-04 17:53:30 +000078 case DumpKind::DumpModsToStdOut:
Lang Hames5721ee42018-03-15 00:30:14 +000079 return [](std::unique_ptr<Module> M) {
80 outs() << "----- Module Start -----\n"
81 << *M << "----- Module End -----\n";
Lang Hamescd3fd832015-04-13 22:12:54 +000082
Lang Hames5721ee42018-03-15 00:30:14 +000083 return M;
84 };
Lang Hamescd3fd832015-04-13 22:12:54 +000085
86 case DumpKind::DumpModsToDisk:
Lang Hames5721ee42018-03-15 00:30:14 +000087 return [](std::unique_ptr<Module> M) {
88 std::error_code EC;
89 raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC, sys::fs::F_Text);
90 if (EC) {
91 errs() << "Couldn't open " << M->getModuleIdentifier()
92 << " for dumping.\nError:" << EC.message() << "\n";
93 exit(1);
94 }
95 Out << *M;
96 return M;
97 };
Lang Hamescd3fd832015-04-13 22:12:54 +000098 }
Aaron Ballmanfc3530a2015-04-14 13:26:11 +000099 llvm_unreachable("Unknown DumpKind");
Lang Hamescd3fd832015-04-13 22:12:54 +0000100}
101
Lang Hames1899d0c2015-06-09 02:43:27 +0000102// Defined in lli.cpp.
103CodeGenOpt::Level getOptLevel();
104
Lang Hames98c2ac12015-10-19 17:43:51 +0000105template <typename PtrTy>
Lang Hamesad4a9112016-08-01 20:49:11 +0000106static PtrTy fromTargetAddress(JITTargetAddress Addr) {
Lang Hames98c2ac12015-10-19 17:43:51 +0000107 return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
108}
109
Lang Hames1a2e6562016-10-28 16:52:34 +0000110int llvm::runOrcLazyJIT(std::vector<std::unique_ptr<Module>> Ms,
111 const std::vector<std::string> &Args) {
Lang Hames5a9808b2015-04-01 04:42:56 +0000112 // Add the program's symbols into the JIT's search space.
113 if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {
114 errs() << "Error loading program symbols.\n";
115 return 1;
116 }
117
118 // Grab a target machine and try to build a factory function for the
119 // target-specific Orc callback manager.
Lang Hames1899d0c2015-06-09 02:43:27 +0000120 EngineBuilder EB;
121 EB.setOptLevel(getOptLevel());
122 auto TM = std::unique_ptr<TargetMachine>(EB.selectTarget());
Lang Hames105518f2016-05-26 17:20:35 +0000123 Triple T(TM->getTargetTriple());
Lang Hames9528bba2015-03-25 12:11:48 +0000124
Lang Hames105518f2016-05-26 17:20:35 +0000125 auto IndirectStubsMgrBuilder = orc::createLocalIndirectStubsManagerBuilder(T);
Lang Hames98c2ac12015-10-19 17:43:51 +0000126
127 // If we couldn't build a stubs-manager-builder for this target then bail out.
128 if (!IndirectStubsMgrBuilder) {
129 errs() << "No indirect stubs manager available for target '"
130 << TM->getTargetTriple().str() << "'.\n";
131 return 1;
132 }
133
Lang Hames5a9808b2015-04-01 04:42:56 +0000134 // Everything looks good. Build the JIT.
Lang Hamesbd0cb782018-05-30 01:57:45 +0000135 OrcLazyJIT J(std::move(TM), std::move(IndirectStubsMgrBuilder),
Lang Hames98c2ac12015-10-19 17:43:51 +0000136 OrcInlineStubs);
Lang Hames3c9e20d2015-03-30 18:37:01 +0000137
Lang Hames5a9808b2015-04-01 04:42:56 +0000138 // Add the module, look up main and run it.
Lang Hamescd9d49b2017-06-23 23:25:28 +0000139 for (auto &M : Ms)
Lang Hames5721ee42018-03-15 00:30:14 +0000140 cantFail(J.addModule(std::move(M)));
Lang Hames9528bba2015-03-25 12:11:48 +0000141
Lang Hames4ce98662017-07-07 02:59:13 +0000142 if (auto MainSym = J.findSymbol("main")) {
143 typedef int (*MainFnPtr)(int, const char*[]);
144 std::vector<const char *> ArgV;
145 for (auto &Arg : Args)
146 ArgV.push_back(Arg.c_str());
147 auto Main = fromTargetAddress<MainFnPtr>(cantFail(MainSym.getAddress()));
148 return Main(ArgV.size(), (const char**)ArgV.data());
149 } else if (auto Err = MainSym.takeError())
150 logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
151 else
Lang Hames9528bba2015-03-25 12:11:48 +0000152 errs() << "Could not find main function.\n";
Lang Hames9528bba2015-03-25 12:11:48 +0000153
Lang Hames4ce98662017-07-07 02:59:13 +0000154 return 1;
Lang Hames9528bba2015-03-25 12:11:48 +0000155}