blob: 4117a9226eee2e2c6d3c9343e2b0ce80f393af4c [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- 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
33namespace llvm {
34namespace orc {
35
36/// @brief 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.
42template <typename BaseLayerT> class LazyEmittingLayer {
43private:
44 class EmissionDeferredModule {
45 public:
46 EmissionDeferredModule(VModuleKey K, std::unique_ptr<Module> M)
47 : K(std::move(K)), M(std::move(M)) {}
48
49 JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
50 switch (EmitState) {
51 case NotEmitted:
52 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 JITSymbolFlags Flags = JITSymbolFlags::fromGlobalValue(*GV);
58 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 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 case Emitted:
86 return B.findSymbolIn(K, Name, ExportedSymbolsOnly);
87 }
88 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 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 if (MangledSymbols) {
117 auto VI = MangledSymbols->find(Name);
118 if (VI == MangledSymbols->end())
119 return nullptr;
120 auto GV = VI->second;
121 if (!ExportedSymbolsOnly || GV->hasDefaultVisibility())
122 return GV;
123 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 return buildMangledSymbols(Name, ExportedSymbolsOnly);
130 }
131
132 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 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 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 if (GV.isDeclaration() || GV.hasCommonLinkage())
149 return nullptr;
150
151 // Mangle the GV name.
152 std::string MangledName;
153 {
154 raw_string_ostream MangledNameStream(MangledName);
155 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 if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
162 return &GV;
163
164 // Otherwise add this to the map for later.
165 Names[MangledName] = &GV;
166 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 const GlobalValue* buildMangledSymbols(StringRef SearchName,
172 bool ExportedSymbolsOnly) const {
173 assert(!MangledSymbols && "Mangled symbols map already exists?");
174
175 auto Symbols = llvm::make_unique<StringMap<const GlobalValue*>>();
176
177 Mangler Mang;
178
179 for (const auto &GO : M->global_objects())
180 if (auto GV = addGlobalValue(*Symbols, GO, Mang, SearchName,
181 ExportedSymbolsOnly))
182 return GV;
183
184 MangledSymbols = std::move(Symbols);
185 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
197public:
198
199 /// @brief Construct a lazy emitting layer.
200 LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
201
202 /// @brief Add the given module to the lazy emitting layer.
203 Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
204 assert(!ModuleMap.count(K) && "VModuleKey K already in use");
205 ModuleMap[K] =
206 llvm::make_unique<EmissionDeferredModule>(std::move(K), std::move(M));
207 return Error::success();
208 }
209
210 /// @brief 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 /// @brief 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 JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
227 // Look for the symbol among existing definitions.
228 if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
229 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 for (auto &KV : ModuleMap)
235 if (auto Symbol = KV.second->find(Name, ExportedSymbolsOnly, BaseLayer))
236 return Symbol;
237
238 // If no definition found anywhere return a null symbol.
239 return nullptr;
240 }
241
242 /// @brief Get the address of the given symbol in the context of the of
243 /// compiled modules represented by the key K.
244 JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
245 bool ExportedSymbolsOnly) {
246 assert(ModuleMap.count(K) && "VModuleKey K not valid here");
247 return ModuleMap[K]->find(Name, ExportedSymbolsOnly, BaseLayer);
248 }
249
250 /// @brief 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