LLVM  3.7.0
LazyEmittingLayer.h
Go to the documentation of this file.
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"
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:
42  EmissionDeferredSet() : EmitState(NotEmitted) {}
43  virtual ~EmissionDeferredSet() {}
44 
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;
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 external symbol lookup (e.g. to check for
71  // pre-existing definitions of common-symbol), but it will never find in
72  // this module that it would not have found already, so return null from
73  // here.
74  return nullptr;
75  case Emitted:
76  return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
77  }
78  llvm_unreachable("Invalid emit-state.");
79  }
80 
81  void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
82  if (EmitState != NotEmitted)
83  BaseLayer.removeModuleSet(Handle);
84  }
85 
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:
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 
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 
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.
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.
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.
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>
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.
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.
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.
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.
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>
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
BaseLayerT::ModuleSetHandleT BaseLayerHandleT
Lazy-emitting IR layer.
ModuleSetHandleT addModuleSet(ModuleSetT Ms, MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver)
Add the given set of modules to the lazy emitting layer.
void removeModuleSet(ModuleSetHandleT H)
Remove the module set represented by the given handle.
F(f)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
JITSymbolFlags
Flags for symbols in the JIT.
#define H(x, y, z)
Definition: MD5.cpp:53
void emitAndFinalize(ModuleSetHandleT H)
Immediately emit and finalize the moduleOB set represented by the given handle.
Represents a symbol in the JIT.
Definition: JITSymbol.h:29
LazyEmittingLayer(BaseLayerT &BaseLayer)
Construct a lazy emitting layer.
ModuleSetListT::iterator ModuleSetHandleT
Handle to a set of loaded modules.
static JITSymbolFlags flagsFromGlobalValue(const GlobalValue &GV)
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly)
Search for the given named symbol.
Module.h This file contains the declarations for the Module class.
uint64_t TargetAddress
Represents an address in the target process's address space.
Definition: JITSymbol.h:26
JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, bool ExportedSymbolsOnly)
Get the address of the given symbol in the context of the set of compiled modules represented by the ...
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40