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