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