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