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