[Orc] New JIT APIs.
[oota-llvm.git] / include / llvm / ExecutionEngine / Orc / CompileOnDemandLayer.h
1 //===- CompileOnDemandLayer.h - Compile each function on demand -*- 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 // JIT layer for breaking up modules and inserting callbacks to allow
11 // individual functions to be compiled on demand.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
16 #define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
17
18 #include "IndirectionUtils.h"
19
20 namespace llvm {
21
22 /// @brief Compile-on-demand layer.
23 ///
24 ///   Modules added to this layer have their calls indirected, and are then
25 /// broken up into a set of single-function modules, each of which is added
26 /// to the layer below in a singleton set. The lower layer can be any layer that
27 /// accepts IR module sets.
28 ///
29 /// It is expected that this layer will frequently be used on top of a
30 /// LazyEmittingLayer. The combination of the two ensures that each function is
31 /// compiled only when it is first called.
32 template <typename BaseLayerT> class CompileOnDemandLayer {
33 public:
34   /// @brief Lookup helper that provides compatibility with the classic
35   ///        static-compilation symbol resolution process.
36   ///
37   ///   The CompileOnDemand (COD) layer splits modules up into multiple
38   /// sub-modules, each held in its own llvm::Module instance, in order to
39   /// support lazy compilation. When a module that contains private symbols is
40   /// broken up symbol linkage changes may be required to enable access to
41   /// "private" data that now resides in a different llvm::Module instance. To
42   /// retain expected symbol resolution behavior for clients of the COD layer,
43   /// the CODScopedLookup class uses a two-tiered lookup system to resolve
44   /// symbols. Lookup first scans sibling modules that were split from the same
45   /// original module (logical-module scoped lookup), then scans all other
46   /// modules that have been added to the lookup scope (logical-dylib scoped
47   /// lookup).
48   class CODScopedLookup {
49   private:
50     typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
51     typedef std::vector<BaseLayerModuleSetHandleT> SiblingHandlesList;
52     typedef std::list<SiblingHandlesList> PseudoDylibModuleSetHandlesList;
53
54   public:
55     /// @brief Handle for a logical module.
56     typedef typename PseudoDylibModuleSetHandlesList::iterator LMHandle;
57
58     /// @brief Construct a scoped lookup.
59     CODScopedLookup(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
60
61     /// @brief Start a new context for a single logical module.
62     LMHandle createLogicalModule() {
63       Handles.push_back(SiblingHandlesList());
64       return std::prev(Handles.end());
65     }
66
67     /// @brief Add a concrete Module's handle to the given logical Module's
68     ///        lookup scope.
69     void addToLogicalModule(LMHandle LMH, BaseLayerModuleSetHandleT H) {
70       LMH->push_back(H);
71     }
72
73     /// @brief Remove a logical Module from the CODScopedLookup entirely.
74     void removeLogicalModule(LMHandle LMH) { Handles.erase(LMH); }
75
76     /// @brief Look up a symbol in this context.
77     uint64_t lookup(LMHandle LMH, const std::string &Name) {
78       if (uint64_t Addr = lookupOnlyIn(LMH, Name))
79         return Addr;
80
81       for (auto I = Handles.begin(), E = Handles.end(); I != E; ++I)
82         if (I != LMH)
83           if (uint64_t Addr = lookupOnlyIn(I, Name))
84             return Addr;
85
86       return 0;
87     }
88
89   private:
90     uint64_t lookupOnlyIn(LMHandle LMH, const std::string &Name) {
91       for (auto H : *LMH)
92         if (uint64_t Addr = BaseLayer.lookupSymbolAddressIn(H, Name, false))
93           return Addr;
94       return 0;
95     }
96
97     BaseLayerT &BaseLayer;
98     PseudoDylibModuleSetHandlesList Handles;
99   };
100
101 private:
102   typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
103   typedef std::vector<BaseLayerModuleSetHandleT> BaseLayerModuleSetHandleListT;
104
105   struct ModuleSetInfo {
106     // Symbol lookup - just one for the whole module set.
107     std::shared_ptr<CODScopedLookup> Lookup;
108
109     // Logical module handles.
110     std::vector<typename CODScopedLookup::LMHandle> LMHandles;
111
112     // Persistent manglers - one per TU.
113     std::vector<PersistentMangler> PersistentManglers;
114
115     // Symbol resolution callback handlers - one per TU.
116     std::vector<std::unique_ptr<JITResolveCallbackHandler>>
117         JITResolveCallbackHandlers;
118
119     // List of vectors of module set handles:
120     // One vector per logical module - each vector holds the handles for the
121     // exploded modules for that logical module in the base layer.
122     BaseLayerModuleSetHandleListT BaseLayerModuleSetHandles;
123
124     ModuleSetInfo(std::shared_ptr<CODScopedLookup> Lookup)
125         : Lookup(std::move(Lookup)) {}
126
127     void releaseResources(BaseLayerT &BaseLayer) {
128       for (auto LMH : LMHandles)
129         Lookup->removeLogicalModule(LMH);
130       for (auto H : BaseLayerModuleSetHandles)
131         BaseLayer.removeModuleSet(H);
132     }
133   };
134
135   typedef std::list<ModuleSetInfo> ModuleSetInfoListT;
136
137 public:
138   /// @brief Handle to a set of loaded modules.
139   typedef typename ModuleSetInfoListT::iterator ModuleSetHandleT;
140
141   /// @brief Convenience typedef for callback inserter.
142   typedef std::function<void(Module&, JITResolveCallbackHandler&)>
143     InsertCallbackAsmFtor;
144
145   /// @brief Construct a compile-on-demand layer instance.
146   CompileOnDemandLayer(BaseLayerT &BaseLayer,
147                        InsertCallbackAsmFtor InsertCallbackAsm)
148     : BaseLayer(BaseLayer), InsertCallbackAsm(InsertCallbackAsm) {}
149
150   /// @brief Add a module to the compile-on-demand layer.
151   template <typename ModuleSetT>
152   ModuleSetHandleT addModuleSet(ModuleSetT Ms,
153                                 std::unique_ptr<RTDyldMemoryManager> MM) {
154
155     const char *JITAddrSuffix = "$orc_addr";
156     const char *JITImplSuffix = "$orc_impl";
157
158     // Create a symbol lookup context and ModuleSetInfo for this module set.
159     auto DylibLookup = std::make_shared<CODScopedLookup>(BaseLayer);
160     ModuleSetHandleT H =
161         ModuleSetInfos.insert(ModuleSetInfos.end(), ModuleSetInfo(DylibLookup));
162     ModuleSetInfo &MSI = ModuleSetInfos.back();
163
164     // Process each of the modules in this module set. All modules share the
165     // same lookup context, but each will get its own TU lookup context.
166     for (auto &M : Ms) {
167
168       // Create a TU lookup context for this module.
169       auto LMH = DylibLookup->createLogicalModule();
170       MSI.LMHandles.push_back(LMH);
171
172       // Create a persistent mangler for this module.
173       MSI.PersistentManglers.emplace_back(*M->getDataLayout());
174
175       // Make all calls to functions defined in this module indirect.
176       JITIndirections Indirections =
177           makeCallsDoubleIndirect(*M, [](const Function &) { return true; },
178                                   JITImplSuffix, JITAddrSuffix);
179
180       // Then carve up the module into a bunch of single-function modules.
181       std::vector<std::unique_ptr<Module>> ExplodedModules =
182           explode(*M, Indirections);
183
184       // Add a resolve-callback handler for this module to look up symbol
185       // addresses when requested via a callback.
186       MSI.JITResolveCallbackHandlers.push_back(
187           createCallbackHandlerFromJITIndirections(
188               Indirections, MSI.PersistentManglers.back(),
189               [=](StringRef S) { return DylibLookup->lookup(LMH, S); }));
190
191       // Insert callback asm code into the first module.
192       InsertCallbackAsm(*ExplodedModules[0],
193                         *MSI.JITResolveCallbackHandlers.back());
194
195       // Now we need to take each of the extracted Modules and add them to
196       // base layer. Each Module will be added individually to make sure they
197       // can be compiled separately, and each will get its own lookaside
198       // memory manager with lookup functors that resolve symbols in sibling
199       // modules first.OA
200       for (auto &M : ExplodedModules) {
201         std::vector<std::unique_ptr<Module>> MSet;
202         MSet.push_back(std::move(M));
203
204         BaseLayerModuleSetHandleT H = BaseLayer.addModuleSet(
205             std::move(MSet),
206             createLookasideRTDyldMM<SectionMemoryManager>(
207                 [=](const std::string &Name) {
208                   if (uint64_t Addr = DylibLookup->lookup(LMH, Name))
209                     return Addr;
210                   return getSymbolAddress(Name, true);
211                 },
212                 [=](const std::string &Name) {
213                   return DylibLookup->lookup(LMH, Name);
214                 }));
215         DylibLookup->addToLogicalModule(LMH, H);
216         MSI.BaseLayerModuleSetHandles.push_back(H);
217       }
218
219       initializeFuncAddrs(*MSI.JITResolveCallbackHandlers.back(), Indirections,
220                           MSI.PersistentManglers.back(), [=](StringRef S) {
221                             return DylibLookup->lookup(LMH, S);
222                           });
223     }
224
225     return H;
226   }
227
228   /// @brief Remove the module represented by the given handle.
229   ///
230   ///   This will remove all modules in the layers below that were derived from
231   /// the module represented by H.
232   void removeModuleSet(ModuleSetHandleT H) {
233     H->releaseResources(BaseLayer);
234     ModuleSetInfos.erase(H);
235   }
236
237   /// @brief Get the address of a symbol provided by this layer, or some layer
238   ///        below this one.
239   uint64_t getSymbolAddress(const std::string &Name, bool ExportedSymbolsOnly) {
240     return BaseLayer.getSymbolAddress(Name, ExportedSymbolsOnly);
241   }
242
243   /// @brief Get the address of a symbol provided by this layer, or some layer
244   ///        below this one.
245   uint64_t lookupSymbolAddressIn(ModuleSetHandleT H, const std::string &Name,
246                                  bool ExportedSymbolsOnly) {
247     BaseLayerModuleSetHandleListT &BaseLayerHandles = H->second;
248     for (auto &BH : BaseLayerHandles) {
249       if (uint64_t Addr =
250             BaseLayer.lookupSymbolAddressIn(BH, Name, ExportedSymbolsOnly))
251         return Addr;
252     }
253     return 0;
254   }
255
256 private:
257   BaseLayerT &BaseLayer;
258   InsertCallbackAsmFtor InsertCallbackAsm;
259   ModuleSetInfoListT ModuleSetInfos;
260 };
261 }
262
263 #endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H