1//===--- OrcLazyJIT.h - Basic Orc-based JIT for lazy execution --*- C++ -*-===//
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// Simple Orc-based JIT. Uses the compile-on-demand layer to break up and
11// lazily compile modules.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_TOOLS_LLI_ORCLAZYJIT_H
16#define LLVM_TOOLS_LLI_ORCLAZYJIT_H
17
18#include "llvm/ADT/Triple.h"
19#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
20#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
21#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
22#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
23#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
24#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
25#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
26
27namespace llvm {
28
29class OrcLazyJIT {
30public:
31
32  typedef orc::JITCompileCallbackManager CompileCallbackMgr;
33  typedef orc::ObjectLinkingLayer<> ObjLayerT;
34  typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT;
35  typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>
36    TransformFtor;
37  typedef orc::IRTransformLayer<CompileLayerT, TransformFtor> IRDumpLayerT;
38  typedef orc::CompileOnDemandLayer<IRDumpLayerT, CompileCallbackMgr> CODLayerT;
39  typedef CODLayerT::IndirectStubsManagerBuilderT
40    IndirectStubsManagerBuilder;
41  typedef CODLayerT::ModuleSetHandleT ModuleHandleT;
42
43  OrcLazyJIT(std::unique_ptr<TargetMachine> TM,
44             std::unique_ptr<CompileCallbackMgr> CCMgr,
45             IndirectStubsManagerBuilder IndirectStubsMgrBuilder,
46             bool InlineStubs)
47      : TM(std::move(TM)), DL(this->TM->createDataLayout()),
48	CCMgr(std::move(CCMgr)),
49	ObjectLayer(),
50        CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)),
51        IRDumpLayer(CompileLayer, createDebugDumper()),
52        CODLayer(IRDumpLayer, extractSingleFunction, *this->CCMgr,
53                 std::move(IndirectStubsMgrBuilder), InlineStubs),
54        CXXRuntimeOverrides(
55            [this](const std::string &S) { return mangle(S); }) {}
56
57  ~OrcLazyJIT() {
58    // Run any destructors registered with __cxa_atexit.
59    CXXRuntimeOverrides.runDestructors();
60    // Run any IR destructors.
61    for (auto &DtorRunner : IRStaticDestructorRunners)
62      DtorRunner.runViaLayer(CODLayer);
63  }
64
65  static std::unique_ptr<CompileCallbackMgr> createCompileCallbackMgr(Triple T);
66  static IndirectStubsManagerBuilder createIndirectStubsMgrBuilder(Triple T);
67
68  ModuleHandleT addModule(std::unique_ptr<Module> M) {
69    // Attach a data-layout if one isn't already present.
70    if (M->getDataLayout().isDefault())
71      M->setDataLayout(DL);
72
73    // Record the static constructors and destructors. We have to do this before
74    // we hand over ownership of the module to the JIT.
75    std::vector<std::string> CtorNames, DtorNames;
76    for (auto Ctor : orc::getConstructors(*M))
77      CtorNames.push_back(mangle(Ctor.Func->getName()));
78    for (auto Dtor : orc::getDestructors(*M))
79      DtorNames.push_back(mangle(Dtor.Func->getName()));
80
81    // Symbol resolution order:
82    //   1) Search the JIT symbols.
83    //   2) Check for C++ runtime overrides.
84    //   3) Search the host process (LLI)'s symbol table.
85    std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver =
86      orc::createLambdaResolver(
87        [this](const std::string &Name) {
88          if (auto Sym = CODLayer.findSymbol(Name, true))
89            return RuntimeDyld::SymbolInfo(Sym.getAddress(),
90                                           Sym.getFlags());
91          if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name))
92            return Sym;
93
94          if (auto Addr =
95              RTDyldMemoryManager::getSymbolAddressInProcess(Name))
96            return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported);
97
98          return RuntimeDyld::SymbolInfo(nullptr);
99        },
100        [](const std::string &Name) {
101          return RuntimeDyld::SymbolInfo(nullptr);
102        }
103      );
104
105    // Add the module to the JIT.
106    std::vector<std::unique_ptr<Module>> S;
107    S.push_back(std::move(M));
108    auto H = CODLayer.addModuleSet(std::move(S), nullptr, std::move(Resolver));
109
110    // Run the static constructors, and save the static destructor runner for
111    // execution when the JIT is torn down.
112    orc::CtorDtorRunner<CODLayerT> CtorRunner(std::move(CtorNames), H);
113    CtorRunner.runViaLayer(CODLayer);
114
115    IRStaticDestructorRunners.emplace_back(std::move(DtorNames), H);
116
117    return H;
118  }
119
120  orc::JITSymbol findSymbol(const std::string &Name) {
121    return CODLayer.findSymbol(mangle(Name), true);
122  }
123
124  orc::JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) {
125    return CODLayer.findSymbolIn(H, mangle(Name), true);
126  }
127
128private:
129
130  std::string mangle(const std::string &Name) {
131    std::string MangledName;
132    {
133      raw_string_ostream MangledNameStream(MangledName);
134      Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
135    }
136    return MangledName;
137  }
138
139  static std::set<Function*> extractSingleFunction(Function &F) {
140    std::set<Function*> Partition;
141    Partition.insert(&F);
142    return Partition;
143  }
144
145  static TransformFtor createDebugDumper();
146
147  std::unique_ptr<TargetMachine> TM;
148  DataLayout DL;
149  SectionMemoryManager CCMgrMemMgr;
150
151  std::unique_ptr<CompileCallbackMgr> CCMgr;
152  ObjLayerT ObjectLayer;
153  CompileLayerT CompileLayer;
154  IRDumpLayerT IRDumpLayer;
155  CODLayerT CODLayer;
156
157  orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
158  std::vector<orc::CtorDtorRunner<CODLayerT>> IRStaticDestructorRunners;
159};
160
161int runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]);
162
163} // end namespace llvm
164
165#endif
166