1*9880d681SAndroid Build Coastguard Worker //===------ OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution -------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "OrcLazyJIT.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/DynamicLibrary.h"
14*9880d681SAndroid Build Coastguard Worker #include <cstdio>
15*9880d681SAndroid Build Coastguard Worker #include <system_error>
16*9880d681SAndroid Build Coastguard Worker
17*9880d681SAndroid Build Coastguard Worker using namespace llvm;
18*9880d681SAndroid Build Coastguard Worker
19*9880d681SAndroid Build Coastguard Worker namespace {
20*9880d681SAndroid Build Coastguard Worker
21*9880d681SAndroid Build Coastguard Worker enum class DumpKind { NoDump, DumpFuncsToStdOut, DumpModsToStdErr,
22*9880d681SAndroid Build Coastguard Worker DumpModsToDisk };
23*9880d681SAndroid Build Coastguard Worker
24*9880d681SAndroid Build Coastguard Worker cl::opt<DumpKind> OrcDumpKind("orc-lazy-debug",
25*9880d681SAndroid Build Coastguard Worker cl::desc("Debug dumping for the orc-lazy JIT."),
26*9880d681SAndroid Build Coastguard Worker cl::init(DumpKind::NoDump),
27*9880d681SAndroid Build Coastguard Worker cl::values(
28*9880d681SAndroid Build Coastguard Worker clEnumValN(DumpKind::NoDump, "no-dump",
29*9880d681SAndroid Build Coastguard Worker "Don't dump anything."),
30*9880d681SAndroid Build Coastguard Worker clEnumValN(DumpKind::DumpFuncsToStdOut,
31*9880d681SAndroid Build Coastguard Worker "funcs-to-stdout",
32*9880d681SAndroid Build Coastguard Worker "Dump function names to stdout."),
33*9880d681SAndroid Build Coastguard Worker clEnumValN(DumpKind::DumpModsToStdErr,
34*9880d681SAndroid Build Coastguard Worker "mods-to-stderr",
35*9880d681SAndroid Build Coastguard Worker "Dump modules to stderr."),
36*9880d681SAndroid Build Coastguard Worker clEnumValN(DumpKind::DumpModsToDisk,
37*9880d681SAndroid Build Coastguard Worker "mods-to-disk",
38*9880d681SAndroid Build Coastguard Worker "Dump modules to the current "
39*9880d681SAndroid Build Coastguard Worker "working directory. (WARNING: "
40*9880d681SAndroid Build Coastguard Worker "will overwrite existing files)."),
41*9880d681SAndroid Build Coastguard Worker clEnumValEnd),
42*9880d681SAndroid Build Coastguard Worker cl::Hidden);
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Worker cl::opt<bool> OrcInlineStubs("orc-lazy-inline-stubs",
45*9880d681SAndroid Build Coastguard Worker cl::desc("Try to inline stubs"),
46*9880d681SAndroid Build Coastguard Worker cl::init(true), cl::Hidden);
47*9880d681SAndroid Build Coastguard Worker }
48*9880d681SAndroid Build Coastguard Worker
createDebugDumper()49*9880d681SAndroid Build Coastguard Worker OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
50*9880d681SAndroid Build Coastguard Worker
51*9880d681SAndroid Build Coastguard Worker switch (OrcDumpKind) {
52*9880d681SAndroid Build Coastguard Worker case DumpKind::NoDump:
53*9880d681SAndroid Build Coastguard Worker return [](std::unique_ptr<Module> M) { return M; };
54*9880d681SAndroid Build Coastguard Worker
55*9880d681SAndroid Build Coastguard Worker case DumpKind::DumpFuncsToStdOut:
56*9880d681SAndroid Build Coastguard Worker return [](std::unique_ptr<Module> M) {
57*9880d681SAndroid Build Coastguard Worker printf("[ ");
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Worker for (const auto &F : *M) {
60*9880d681SAndroid Build Coastguard Worker if (F.isDeclaration())
61*9880d681SAndroid Build Coastguard Worker continue;
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Worker if (F.hasName()) {
64*9880d681SAndroid Build Coastguard Worker std::string Name(F.getName());
65*9880d681SAndroid Build Coastguard Worker printf("%s ", Name.c_str());
66*9880d681SAndroid Build Coastguard Worker } else
67*9880d681SAndroid Build Coastguard Worker printf("<anon> ");
68*9880d681SAndroid Build Coastguard Worker }
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker printf("]\n");
71*9880d681SAndroid Build Coastguard Worker return M;
72*9880d681SAndroid Build Coastguard Worker };
73*9880d681SAndroid Build Coastguard Worker
74*9880d681SAndroid Build Coastguard Worker case DumpKind::DumpModsToStdErr:
75*9880d681SAndroid Build Coastguard Worker return [](std::unique_ptr<Module> M) {
76*9880d681SAndroid Build Coastguard Worker dbgs() << "----- Module Start -----\n" << *M
77*9880d681SAndroid Build Coastguard Worker << "----- Module End -----\n";
78*9880d681SAndroid Build Coastguard Worker
79*9880d681SAndroid Build Coastguard Worker return M;
80*9880d681SAndroid Build Coastguard Worker };
81*9880d681SAndroid Build Coastguard Worker
82*9880d681SAndroid Build Coastguard Worker case DumpKind::DumpModsToDisk:
83*9880d681SAndroid Build Coastguard Worker return [](std::unique_ptr<Module> M) {
84*9880d681SAndroid Build Coastguard Worker std::error_code EC;
85*9880d681SAndroid Build Coastguard Worker raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC,
86*9880d681SAndroid Build Coastguard Worker sys::fs::F_Text);
87*9880d681SAndroid Build Coastguard Worker if (EC) {
88*9880d681SAndroid Build Coastguard Worker errs() << "Couldn't open " << M->getModuleIdentifier()
89*9880d681SAndroid Build Coastguard Worker << " for dumping.\nError:" << EC.message() << "\n";
90*9880d681SAndroid Build Coastguard Worker exit(1);
91*9880d681SAndroid Build Coastguard Worker }
92*9880d681SAndroid Build Coastguard Worker Out << *M;
93*9880d681SAndroid Build Coastguard Worker return M;
94*9880d681SAndroid Build Coastguard Worker };
95*9880d681SAndroid Build Coastguard Worker }
96*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown DumpKind");
97*9880d681SAndroid Build Coastguard Worker }
98*9880d681SAndroid Build Coastguard Worker
99*9880d681SAndroid Build Coastguard Worker // Defined in lli.cpp.
100*9880d681SAndroid Build Coastguard Worker CodeGenOpt::Level getOptLevel();
101*9880d681SAndroid Build Coastguard Worker
102*9880d681SAndroid Build Coastguard Worker
103*9880d681SAndroid Build Coastguard Worker template <typename PtrTy>
fromTargetAddress(orc::TargetAddress Addr)104*9880d681SAndroid Build Coastguard Worker static PtrTy fromTargetAddress(orc::TargetAddress Addr) {
105*9880d681SAndroid Build Coastguard Worker return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
106*9880d681SAndroid Build Coastguard Worker }
107*9880d681SAndroid Build Coastguard Worker
runOrcLazyJIT(std::unique_ptr<Module> M,int ArgC,char * ArgV[])108*9880d681SAndroid Build Coastguard Worker int llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) {
109*9880d681SAndroid Build Coastguard Worker // Add the program's symbols into the JIT's search space.
110*9880d681SAndroid Build Coastguard Worker if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {
111*9880d681SAndroid Build Coastguard Worker errs() << "Error loading program symbols.\n";
112*9880d681SAndroid Build Coastguard Worker return 1;
113*9880d681SAndroid Build Coastguard Worker }
114*9880d681SAndroid Build Coastguard Worker
115*9880d681SAndroid Build Coastguard Worker // Grab a target machine and try to build a factory function for the
116*9880d681SAndroid Build Coastguard Worker // target-specific Orc callback manager.
117*9880d681SAndroid Build Coastguard Worker EngineBuilder EB;
118*9880d681SAndroid Build Coastguard Worker EB.setOptLevel(getOptLevel());
119*9880d681SAndroid Build Coastguard Worker auto TM = std::unique_ptr<TargetMachine>(EB.selectTarget());
120*9880d681SAndroid Build Coastguard Worker Triple T(TM->getTargetTriple());
121*9880d681SAndroid Build Coastguard Worker auto CompileCallbackMgr = orc::createLocalCompileCallbackManager(T, 0);
122*9880d681SAndroid Build Coastguard Worker
123*9880d681SAndroid Build Coastguard Worker // If we couldn't build the factory function then there must not be a callback
124*9880d681SAndroid Build Coastguard Worker // manager for this target. Bail out.
125*9880d681SAndroid Build Coastguard Worker if (!CompileCallbackMgr) {
126*9880d681SAndroid Build Coastguard Worker errs() << "No callback manager available for target '"
127*9880d681SAndroid Build Coastguard Worker << TM->getTargetTriple().str() << "'.\n";
128*9880d681SAndroid Build Coastguard Worker return 1;
129*9880d681SAndroid Build Coastguard Worker }
130*9880d681SAndroid Build Coastguard Worker
131*9880d681SAndroid Build Coastguard Worker auto IndirectStubsMgrBuilder = orc::createLocalIndirectStubsManagerBuilder(T);
132*9880d681SAndroid Build Coastguard Worker
133*9880d681SAndroid Build Coastguard Worker // If we couldn't build a stubs-manager-builder for this target then bail out.
134*9880d681SAndroid Build Coastguard Worker if (!IndirectStubsMgrBuilder) {
135*9880d681SAndroid Build Coastguard Worker errs() << "No indirect stubs manager available for target '"
136*9880d681SAndroid Build Coastguard Worker << TM->getTargetTriple().str() << "'.\n";
137*9880d681SAndroid Build Coastguard Worker return 1;
138*9880d681SAndroid Build Coastguard Worker }
139*9880d681SAndroid Build Coastguard Worker
140*9880d681SAndroid Build Coastguard Worker // Everything looks good. Build the JIT.
141*9880d681SAndroid Build Coastguard Worker OrcLazyJIT J(std::move(TM), std::move(CompileCallbackMgr),
142*9880d681SAndroid Build Coastguard Worker std::move(IndirectStubsMgrBuilder),
143*9880d681SAndroid Build Coastguard Worker OrcInlineStubs);
144*9880d681SAndroid Build Coastguard Worker
145*9880d681SAndroid Build Coastguard Worker // Add the module, look up main and run it.
146*9880d681SAndroid Build Coastguard Worker auto MainHandle = J.addModule(std::move(M));
147*9880d681SAndroid Build Coastguard Worker auto MainSym = J.findSymbolIn(MainHandle, "main");
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker if (!MainSym) {
150*9880d681SAndroid Build Coastguard Worker errs() << "Could not find main function.\n";
151*9880d681SAndroid Build Coastguard Worker return 1;
152*9880d681SAndroid Build Coastguard Worker }
153*9880d681SAndroid Build Coastguard Worker
154*9880d681SAndroid Build Coastguard Worker typedef int (*MainFnPtr)(int, char*[]);
155*9880d681SAndroid Build Coastguard Worker auto Main = fromTargetAddress<MainFnPtr>(MainSym.getAddress());
156*9880d681SAndroid Build Coastguard Worker return Main(ArgC, ArgV);
157*9880d681SAndroid Build Coastguard Worker }
158*9880d681SAndroid Build Coastguard Worker
159