[Orc] Add an emitAndFinalize method to the ObjectLinkingLayer, IRCompileLayer
[oota-llvm.git] / include / llvm / ExecutionEngine / Orc / LazyEmittingLayer.h
1 //===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- 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 // Contains the definition for a lazy-emitting layer for the JIT.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
15 #define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
16
17 #include "JITSymbol.h"
18 #include "LookasideRTDyldMM.h"
19 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
20 #include "llvm/IR/GlobalValue.h"
21 #include "llvm/IR/Mangler.h"
22 #include <list>
23
24 namespace llvm {
25
26 /// @brief Lazy-emitting IR layer.
27 ///
28 ///   This layer accepts sets of LLVM IR Modules (via addModuleSet), but does
29 /// not immediately emit them the layer below. Instead, emissing to the base
30 /// layer is deferred until the first time the client requests the address
31 /// (via JITSymbol::getAddress) for a symbol contained in this layer.
32 template <typename BaseLayerT> class LazyEmittingLayer {
33 public:
34   typedef typename BaseLayerT::ModuleSetHandleT BaseLayerHandleT;
35
36 private:
37   class EmissionDeferredSet {
38   public:
39     EmissionDeferredSet() : EmitState(NotEmitted) {}
40     virtual ~EmissionDeferredSet() {}
41
42     JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
43       switch (EmitState) {
44       case NotEmitted:
45         if (provides(Name, ExportedSymbolsOnly)) {
46           // Create a std::string version of Name to capture here - the argument
47           // (a StringRef) may go away before the lambda is executed.
48           // FIXME: Use capture-init when we move to C++14. 
49           std::string PName = Name;
50           return JITSymbol(
51               [this, ExportedSymbolsOnly, PName, &B]() -> TargetAddress {
52                 if (this->EmitState == Emitting)
53                   return 0;
54                 else if (this->EmitState == NotEmitted) {
55                   this->EmitState = Emitting;
56                   Handle = this->emitToBaseLayer(B);
57                   this->EmitState = Emitted;
58                 }
59                 return B.findSymbolIn(Handle, PName, ExportedSymbolsOnly)
60                           .getAddress();
61               });
62         } else
63           return nullptr;
64       case Emitting:
65         // Calling "emit" can trigger external symbol lookup (e.g. to check for
66         // pre-existing definitions of common-symbol), but it will never find in
67         // this module that it would not have found already, so return null from
68         // here.
69         return nullptr;
70       case Emitted:
71         return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
72       }
73       llvm_unreachable("Invalid emit-state.");
74     }
75
76     void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
77       if (EmitState != NotEmitted)
78         BaseLayer.removeModuleSet(Handle);
79     }
80
81     void emitAndFinalize(BaseLayerT &BaseLayer) {
82       assert(EmitState != Emitting &&
83              "Cannot emitAndFinalize while already emitting");
84       if (EmitState == NotEmitted) {
85         EmitState = Emitting;
86         Handle = emitToBaseLayer(BaseLayer);
87         EmitState = Emitted;
88       }
89       BaseLayer.emitAndFinalize(Handle);
90     }
91
92     template <typename ModuleSetT>
93     static std::unique_ptr<EmissionDeferredSet>
94     create(BaseLayerT &B, ModuleSetT Ms,
95            std::unique_ptr<RTDyldMemoryManager> MM);
96
97   protected:
98     virtual bool provides(StringRef Name, bool ExportedSymbolsOnly) const = 0;
99     virtual BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) = 0;
100
101   private:
102     enum { NotEmitted, Emitting, Emitted } EmitState;
103     BaseLayerHandleT Handle;
104   };
105
106   template <typename ModuleSetT>
107   class EmissionDeferredSetImpl : public EmissionDeferredSet {
108   public:
109     EmissionDeferredSetImpl(ModuleSetT Ms,
110                             std::unique_ptr<RTDyldMemoryManager> MM)
111         : Ms(std::move(Ms)), MM(std::move(MM)) {}
112
113   protected:
114
115     BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) override {
116       // We don't need the mangled names set any more: Once we've emitted this
117       // to the base layer we'll just look for symbols there.
118       MangledNames.reset();
119       return BaseLayer.addModuleSet(std::move(Ms), std::move(MM));
120     }
121
122     bool provides(StringRef Name, bool ExportedSymbolsOnly) const override {
123       // FIXME: We could clean all this up if we had a way to reliably demangle
124       //        names: We could just demangle name and search, rather than
125       //        mangling everything else.
126
127       // If we have already built the mangled name set then just search it.
128       if (MangledNames) {
129         auto VI = MangledNames->find(Name);
130         if (VI == MangledNames->end())
131           return false;
132         return !ExportedSymbolsOnly || VI->second;
133       }
134
135       // If we haven't built the mangled name set yet, try to build it. As an
136       // optimization this will leave MangledNames set to nullptr if we find
137       // Name in the process of building the set.
138       buildMangledNames(Name, ExportedSymbolsOnly);
139       if (!MangledNames)
140         return true;
141       return false;
142     }
143
144   private:
145     // If the mangled name of the given GlobalValue matches the given search
146     // name (and its visibility conforms to the ExportedSymbolsOnly flag) then
147     // just return 'true'. Otherwise, add the mangled name to the Names map and
148     // return 'false'.
149     bool addGlobalValue(StringMap<bool> &Names, const GlobalValue &GV,
150                         const Mangler &Mang, StringRef SearchName,
151                         bool ExportedSymbolsOnly) const {
152       // Modules don't "provide" decls or common symbols.
153       if (GV.isDeclaration() || GV.hasCommonLinkage())
154         return false;
155
156       // Mangle the GV name.
157       std::string MangledName;
158       {
159         raw_string_ostream MangledNameStream(MangledName);
160         Mang.getNameWithPrefix(MangledNameStream, &GV, false);
161       }
162
163       // Check whether this is the name we were searching for, and if it is then
164       // bail out early.
165       if (MangledName == SearchName)
166         if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
167           return true;
168
169       // Otherwise add this to the map for later.
170       Names[MangledName] = GV.hasDefaultVisibility();
171       return false;
172     }
173
174     // Build the MangledNames map. Bails out early (with MangledNames left set
175     // to nullptr) if the given SearchName is found while building the map.
176     void buildMangledNames(StringRef SearchName,
177                            bool ExportedSymbolsOnly) const {
178       assert(!MangledNames && "Mangled names map already exists?");
179
180       auto Names = llvm::make_unique<StringMap<bool>>();
181
182       for (const auto &M : Ms) {
183         Mangler Mang(M->getDataLayout());
184
185         for (const auto &GV : M->globals())
186           if (addGlobalValue(*Names, GV, Mang, SearchName, ExportedSymbolsOnly))
187             return;
188
189         for (const auto &F : *M)
190           if (addGlobalValue(*Names, F, Mang, SearchName, ExportedSymbolsOnly))
191             return;
192       }
193
194       MangledNames = std::move(Names);
195     }
196
197     ModuleSetT Ms;
198     std::unique_ptr<RTDyldMemoryManager> MM;
199     mutable std::unique_ptr<StringMap<bool>> MangledNames;
200   };
201
202   typedef std::list<std::unique_ptr<EmissionDeferredSet>> ModuleSetListT;
203
204   BaseLayerT &BaseLayer;
205   ModuleSetListT ModuleSetList;
206
207 public:
208   /// @brief Handle to a set of loaded modules.
209   typedef typename ModuleSetListT::iterator ModuleSetHandleT;
210
211   /// @brief Construct a lazy emitting layer.
212   LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
213
214   /// @brief Add the given set of modules to the lazy emitting layer.
215   template <typename ModuleSetT>
216   ModuleSetHandleT addModuleSet(ModuleSetT Ms,
217                                 std::unique_ptr<RTDyldMemoryManager> MM) {
218     return ModuleSetList.insert(
219         ModuleSetList.end(),
220         EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MM)));
221   }
222
223   /// @brief Remove the module set represented by the given handle.
224   ///
225   ///   This method will free the memory associated with the given module set,
226   /// both in this layer, and the base layer.
227   void removeModuleSet(ModuleSetHandleT H) {
228     (*H)->removeModulesFromBaseLayer(BaseLayer);
229     ModuleSetList.erase(H);
230   }
231
232   /// @brief Search for the given named symbol.
233   /// @param Name The name of the symbol to search for.
234   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
235   /// @return A handle for the given named symbol, if it exists.
236   JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
237     // Look for the symbol among existing definitions.
238     if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
239       return Symbol;
240
241     // If not found then search the deferred sets. If any of these contain a
242     // definition of 'Name' then they will return a JITSymbol that will emit
243     // the corresponding module when the symbol address is requested.
244     for (auto &DeferredSet : ModuleSetList)
245       if (auto Symbol = DeferredSet->find(Name, ExportedSymbolsOnly, BaseLayer))
246         return Symbol;
247
248     // If no definition found anywhere return a null symbol.
249     return nullptr;
250   }
251
252   /// @brief Get the address of the given symbol in the context of the set of
253   ///        compiled modules represented by the handle H.
254   JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
255                          bool ExportedSymbolsOnly) {
256     return (*H)->find(Name, ExportedSymbolsOnly, BaseLayer);
257   }
258
259   /// @brief Immediately emit and finalize the moduleOB set represented by the
260   ///        given handle.
261   /// @param H Handle for module set to emit/finalize.
262   void emitAndFinalize(ModuleSetHandleT H) {
263     (*H)->emitAndFinalize(BaseLayer);
264   }
265
266 };
267
268 template <typename BaseLayerT>
269 template <typename ModuleSetT>
270 std::unique_ptr<typename LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet>
271 LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet::create(
272     BaseLayerT &B, ModuleSetT Ms, std::unique_ptr<RTDyldMemoryManager> MM) {
273   return llvm::make_unique<EmissionDeferredSetImpl<ModuleSetT>>(std::move(Ms),
274                                                                 std::move(MM));
275 }
276 }
277
278 #endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H