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