7fb25db0322a5a986a2b0f3c45243d22d6957d4d
[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 #include "LookasideRTDyldMM.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
22 #include <list>
23
24 namespace llvm {
25
26 /// @brief Compile-on-demand layer.
27 ///
28 ///   Modules added to this layer have their calls indirected, and are then
29 /// broken up into a set of single-function modules, each of which is added
30 /// to the layer below in a singleton set. The lower layer can be any layer that
31 /// accepts IR module sets.
32 ///
33 /// It is expected that this layer will frequently be used on top of a
34 /// LazyEmittingLayer. The combination of the two ensures that each function is
35 /// compiled only when it is first called.
36 template <typename BaseLayerT, typename CompileCallbackMgrT>
37 class CompileOnDemandLayer {
38 public:
39   /// @brief Lookup helper that provides compatibility with the classic
40   ///        static-compilation symbol resolution process.
41   ///
42   ///   The CompileOnDemand (COD) layer splits modules up into multiple
43   /// sub-modules, each held in its own llvm::Module instance, in order to
44   /// support lazy compilation. When a module that contains private symbols is
45   /// broken up symbol linkage changes may be required to enable access to
46   /// "private" data that now resides in a different llvm::Module instance. To
47   /// retain expected symbol resolution behavior for clients of the COD layer,
48   /// the CODScopedLookup class uses a two-tiered lookup system to resolve
49   /// symbols. Lookup first scans sibling modules that were split from the same
50   /// original module (logical-module scoped lookup), then scans all other
51   /// modules that have been added to the lookup scope (logical-dylib scoped
52   /// lookup).
53   class CODScopedLookup {
54   private:
55     typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
56     typedef std::vector<BaseLayerModuleSetHandleT> SiblingHandlesList;
57     typedef std::list<SiblingHandlesList> PseudoDylibModuleSetHandlesList;
58
59   public:
60     /// @brief Handle for a logical module.
61     typedef typename PseudoDylibModuleSetHandlesList::iterator LMHandle;
62
63     /// @brief Construct a scoped lookup.
64     CODScopedLookup(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
65
66     /// @brief Start a new context for a single logical module.
67     LMHandle createLogicalModule() {
68       Handles.push_back(SiblingHandlesList());
69       return std::prev(Handles.end());
70     }
71
72     /// @brief Add a concrete Module's handle to the given logical Module's
73     ///        lookup scope.
74     void addToLogicalModule(LMHandle LMH, BaseLayerModuleSetHandleT H) {
75       LMH->push_back(H);
76     }
77
78     /// @brief Remove a logical Module from the CODScopedLookup entirely.
79     void removeLogicalModule(LMHandle LMH) { Handles.erase(LMH); }
80
81     /// @brief Look up a symbol in this context.
82     JITSymbol findSymbol(LMHandle LMH, const std::string &Name) {
83       if (auto Symbol = findSymbolIn(LMH, Name))
84         return Symbol;
85
86       for (auto I = Handles.begin(), E = Handles.end(); I != E; ++I)
87         if (I != LMH)
88           if (auto Symbol = findSymbolIn(I, Name))
89             return Symbol;
90
91       return nullptr;
92     }
93
94   private:
95
96     JITSymbol findSymbolIn(LMHandle LMH, const std::string &Name) {
97       for (auto H : *LMH)
98         if (auto Symbol = BaseLayer.findSymbolIn(H, Name, false))
99           return Symbol;
100       return nullptr;
101     }
102
103     BaseLayerT &BaseLayer;
104     PseudoDylibModuleSetHandlesList Handles;
105   };
106
107 private:
108   typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
109   typedef std::vector<BaseLayerModuleSetHandleT> BaseLayerModuleSetHandleListT;
110
111   struct ModuleSetInfo {
112     // Symbol lookup - just one for the whole module set.
113     std::shared_ptr<CODScopedLookup> Lookup;
114
115     // Logical module handles.
116     std::vector<typename CODScopedLookup::LMHandle> LMHandles;
117
118     // List of vectors of module set handles:
119     // One vector per logical module - each vector holds the handles for the
120     // exploded modules for that logical module in the base layer.
121     BaseLayerModuleSetHandleListT BaseLayerModuleSetHandles;
122
123     ModuleSetInfo(std::shared_ptr<CODScopedLookup> Lookup)
124         : Lookup(std::move(Lookup)) {}
125
126     void releaseResources(BaseLayerT &BaseLayer) {
127       for (auto LMH : LMHandles)
128         Lookup->removeLogicalModule(LMH);
129       for (auto H : BaseLayerModuleSetHandles)
130         BaseLayer.removeModuleSet(H);
131     }
132   };
133
134   typedef std::list<ModuleSetInfo> ModuleSetInfoListT;
135
136 public:
137   /// @brief Handle to a set of loaded modules.
138   typedef typename ModuleSetInfoListT::iterator ModuleSetHandleT;
139
140   // @brief Fallback lookup functor.
141   typedef std::function<uint64_t(const std::string &)> LookupFtor;
142
143   /// @brief Construct a compile-on-demand layer instance.
144   CompileOnDemandLayer(BaseLayerT &BaseLayer, LLVMContext &Context)
145     : BaseLayer(BaseLayer),
146       CompileCallbackMgr(BaseLayer, Context, 0, 64) {}
147
148   /// @brief Add a module to the compile-on-demand layer.
149   template <typename ModuleSetT>
150   ModuleSetHandleT addModuleSet(ModuleSetT Ms,
151                                 LookupFtor FallbackLookup = nullptr) {
152
153     // If the user didn't supply a fallback lookup then just use
154     // getSymbolAddress.
155     if (!FallbackLookup)
156       FallbackLookup = [=](const std::string &Name) {
157                          return findSymbol(Name, true).getAddress();
158                        };
159
160     // Create a lookup context and ModuleSetInfo for this module set.
161     // For the purposes of symbol resolution the set Ms will be treated as if
162     // the modules it contained had been linked together as a dylib.
163     auto DylibLookup = std::make_shared<CODScopedLookup>(BaseLayer);
164     ModuleSetHandleT H =
165         ModuleSetInfos.insert(ModuleSetInfos.end(), ModuleSetInfo(DylibLookup));
166     ModuleSetInfo &MSI = ModuleSetInfos.back();
167
168     // Process each of the modules in this module set.
169     for (auto &M : Ms)
170       partitionAndAdd(*M, MSI, FallbackLookup);
171
172     return H;
173   }
174
175   /// @brief Remove the module represented by the given handle.
176   ///
177   ///   This will remove all modules in the layers below that were derived from
178   /// the module represented by H.
179   void removeModuleSet(ModuleSetHandleT H) {
180     H->releaseResources(BaseLayer);
181     ModuleSetInfos.erase(H);
182   }
183
184   /// @brief Search for the given named symbol.
185   /// @param Name The name of the symbol to search for.
186   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
187   /// @return A handle for the given named symbol, if it exists.
188   JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
189     return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
190   }
191
192   /// @brief Get the address of a symbol provided by this layer, or some layer
193   ///        below this one.
194   JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
195                          bool ExportedSymbolsOnly) {
196     BaseLayerModuleSetHandleListT &BaseLayerHandles = H->second;
197     for (auto &BH : BaseLayerHandles) {
198       if (auto Symbol = BaseLayer.findSymbolIn(BH, Name, ExportedSymbolsOnly))
199         return Symbol;
200     }
201     return nullptr;
202   }
203
204 private:
205
206   void partitionAndAdd(Module &M, ModuleSetInfo &MSI,
207                        LookupFtor FallbackLookup) {
208     const char *AddrSuffix = "$orc_addr";
209     const char *BodySuffix = "$orc_body";
210
211     // We're going to break M up into a bunch of sub-modules, but we want
212     // internal linkage symbols to still resolve sensibly. CODScopedLookup
213     // provides the "logical module" concept to make this work, so create a
214     // new logical module for M.
215     auto DylibLookup = MSI.Lookup;
216     auto LogicalModule = DylibLookup->createLogicalModule();
217     MSI.LMHandles.push_back(LogicalModule);
218
219     // Partition M into a "globals and stubs" module, a "common symbols" module,
220     // and a list of single-function modules.
221     auto PartitionedModule = fullyPartition(M);
222     auto StubsModule = std::move(PartitionedModule.GlobalVars);
223     auto CommonsModule = std::move(PartitionedModule.Commons);
224     auto FunctionModules = std::move(PartitionedModule.Functions);
225
226     // Emit the commons stright away.
227     auto CommonHandle = addModule(std::move(CommonsModule), MSI, LogicalModule,
228                                   FallbackLookup);
229     BaseLayer.emitAndFinalize(CommonHandle);
230
231     // Map of definition names to callback-info data structures. We'll use
232     // this to build the compile actions for the stubs below.
233     typedef std::map<std::string,
234                      typename CompileCallbackMgrT::CompileCallbackInfo>
235       StubInfoMap;
236     StubInfoMap StubInfos;
237
238     // Now we need to take each of the extracted Modules and add them to
239     // base layer. Each Module will be added individually to make sure they
240     // can be compiled separately, and each will get its own lookaside
241     // memory manager that will resolve within this logical module first.
242     for (auto &SubM : FunctionModules) {
243
244       // Keep track of the stubs we create for this module so that we can set
245       // their compile actions.
246       std::vector<typename StubInfoMap::iterator> NewStubInfos;
247
248       // Search for function definitions and insert stubs into the stubs
249       // module.
250       for (auto &F : *SubM) {
251         if (F.isDeclaration())
252           continue;
253
254         std::string Name = F.getName();
255         Function *Proto = StubsModule->getFunction(Name);
256         assert(Proto && "Failed to clone function decl into stubs module.");
257         auto CallbackInfo =
258           CompileCallbackMgr.getCompileCallback(*Proto->getFunctionType());
259         GlobalVariable *FunctionBodyPointer =
260           createImplPointer(*Proto, Name + AddrSuffix,
261                             CallbackInfo.getAddress());
262         makeStub(*Proto, *FunctionBodyPointer);
263
264         F.setName(Name + BodySuffix);
265         F.setVisibility(GlobalValue::HiddenVisibility);
266
267         auto KV = std::make_pair(std::move(Name), std::move(CallbackInfo));
268         NewStubInfos.push_back(StubInfos.insert(StubInfos.begin(), KV));
269       }
270
271       auto H = addModule(std::move(SubM), MSI, LogicalModule, FallbackLookup);
272
273       // Set the compile actions for this module:
274       for (auto &KVPair : NewStubInfos) {
275         std::string BodyName = Mangle(KVPair->first + BodySuffix,
276                                       *M.getDataLayout());
277         auto &CCInfo = KVPair->second;
278         CCInfo.setCompileAction(
279           [=](){
280             return BaseLayer.findSymbolIn(H, BodyName, false).getAddress();
281           });
282       }
283
284     }
285
286     // Ok - we've processed all the partitioned modules. Now add the
287     // stubs/globals module and set the update actions.
288     auto StubsH =
289       addModule(std::move(StubsModule), MSI, LogicalModule, FallbackLookup);
290
291     for (auto &KVPair : StubInfos) {
292       std::string AddrName = Mangle(KVPair.first + AddrSuffix,
293                                     *M.getDataLayout());
294       auto &CCInfo = KVPair.second;
295       CCInfo.setUpdateAction(
296         CompileCallbackMgr.getLocalFPUpdater(StubsH, AddrName));
297     }
298   }
299
300   // Add the given Module to the base layer using a memory manager that will
301   // perform the appropriate scoped lookup (i.e. will look first with in the
302   // module from which it was extracted, then into the set to which that module
303   // belonged, and finally externally).
304   BaseLayerModuleSetHandleT addModule(
305                                std::unique_ptr<Module> M,
306                                ModuleSetInfo &MSI,
307                                typename CODScopedLookup::LMHandle LogicalModule,
308                                LookupFtor FallbackLookup) {
309
310     // Add this module to the JIT with a memory manager that uses the
311     // DylibLookup to resolve symbols.
312     std::vector<std::unique_ptr<Module>> MSet;
313     MSet.push_back(std::move(M));
314
315     auto DylibLookup = MSI.Lookup;
316     auto MM =
317       createLookasideRTDyldMM<SectionMemoryManager>(
318         [=](const std::string &Name) {
319           if (auto Symbol = DylibLookup->findSymbol(LogicalModule, Name))
320             return Symbol.getAddress();
321           return FallbackLookup(Name);
322         },
323         [=](const std::string &Name) {
324           return DylibLookup->findSymbol(LogicalModule, Name).getAddress();
325         });
326
327     BaseLayerModuleSetHandleT H =
328       BaseLayer.addModuleSet(std::move(MSet), std::move(MM));
329     // Add this module to the logical module lookup.
330     DylibLookup->addToLogicalModule(LogicalModule, H);
331     MSI.BaseLayerModuleSetHandles.push_back(H);
332
333     return H;
334   }
335
336   static std::string Mangle(StringRef Name, const DataLayout &DL) {
337     Mangler M(&DL);
338     std::string MangledName;
339     {
340       raw_string_ostream MangledNameStream(MangledName);
341       M.getNameWithPrefix(MangledNameStream, Name);
342     }
343     return MangledName;
344   }
345
346   BaseLayerT &BaseLayer;
347   CompileCallbackMgrT CompileCallbackMgr;
348   ModuleSetInfoListT ModuleSetInfos;
349 };
350 }
351
352 #endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H