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