LLVM  4.0.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 "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/StringMap.h"
19 #include "llvm/ADT/StringRef.h"
21 #include "llvm/IR/GlobalValue.h"
22 #include "llvm/IR/Mangler.h"
23 #include "llvm/IR/Module.h"
26 #include <algorithm>
27 #include <cassert>
28 #include <list>
29 #include <memory>
30 #include <string>
31 
32 namespace llvm {
33 namespace orc {
34 
35 /// @brief Lazy-emitting IR layer.
36 ///
37 /// This layer accepts sets of LLVM IR Modules (via addModuleSet), but does
38 /// not immediately emit them the layer below. Instead, emissing to the base
39 /// layer is deferred until the first time the client requests the address
40 /// (via JITSymbol::getAddress) for a symbol contained in this layer.
41 template <typename BaseLayerT> class LazyEmittingLayer {
42 public:
43  typedef typename BaseLayerT::ModuleSetHandleT BaseLayerHandleT;
44 
45 private:
46  class EmissionDeferredSet {
47  public:
48  EmissionDeferredSet() = default;
49  virtual ~EmissionDeferredSet() = default;
50 
51  JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
52  switch (EmitState) {
53  case NotEmitted:
54  if (auto GV = searchGVs(Name, ExportedSymbolsOnly)) {
55  // Create a std::string version of Name to capture here - the argument
56  // (a StringRef) may go away before the lambda is executed.
57  // FIXME: Use capture-init when we move to C++14.
58  std::string PName = Name;
60  auto GetAddress =
61  [this, ExportedSymbolsOnly, PName, &B]() -> JITTargetAddress {
62  if (this->EmitState == Emitting)
63  return 0;
64  else if (this->EmitState == NotEmitted) {
65  this->EmitState = Emitting;
66  Handle = this->emitToBaseLayer(B);
67  this->EmitState = Emitted;
68  }
69  auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly);
70  return Sym.getAddress();
71  };
72  return JITSymbol(std::move(GetAddress), Flags);
73  } else
74  return nullptr;
75  case Emitting:
76  // Calling "emit" can trigger a recursive call to 'find' (e.g. to check
77  // for pre-existing definitions of common-symbol), but any symbol in
78  // this module would already have been found internally (in the
79  // RuntimeDyld that did the lookup), so just return a nullptr here.
80  return nullptr;
81  case Emitted:
82  return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
83  }
84  llvm_unreachable("Invalid emit-state.");
85  }
86 
87  void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
88  if (EmitState != NotEmitted)
89  BaseLayer.removeModuleSet(Handle);
90  }
91 
92  void emitAndFinalize(BaseLayerT &BaseLayer) {
93  assert(EmitState != Emitting &&
94  "Cannot emitAndFinalize while already emitting");
95  if (EmitState == NotEmitted) {
96  EmitState = Emitting;
97  Handle = emitToBaseLayer(BaseLayer);
98  EmitState = Emitted;
99  }
100  BaseLayer.emitAndFinalize(Handle);
101  }
102 
103  template <typename ModuleSetT, typename MemoryManagerPtrT,
104  typename SymbolResolverPtrT>
105  static std::unique_ptr<EmissionDeferredSet>
106  create(BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr,
107  SymbolResolverPtrT Resolver);
108 
109  protected:
110  virtual const GlobalValue* searchGVs(StringRef Name,
111  bool ExportedSymbolsOnly) const = 0;
112  virtual BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) = 0;
113 
114  private:
115  enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted;
116  BaseLayerHandleT Handle;
117  };
118 
119  template <typename ModuleSetT, typename MemoryManagerPtrT,
120  typename SymbolResolverPtrT>
121  class EmissionDeferredSetImpl : public EmissionDeferredSet {
122  public:
123  EmissionDeferredSetImpl(ModuleSetT Ms,
124  MemoryManagerPtrT MemMgr,
125  SymbolResolverPtrT Resolver)
126  : Ms(std::move(Ms)), MemMgr(std::move(MemMgr)),
127  Resolver(std::move(Resolver)) {}
128 
129  protected:
130  const GlobalValue* searchGVs(StringRef Name,
131  bool ExportedSymbolsOnly) const override {
132  // FIXME: We could clean all this up if we had a way to reliably demangle
133  // names: We could just demangle name and search, rather than
134  // mangling everything else.
135 
136  // If we have already built the mangled name set then just search it.
137  if (MangledSymbols) {
138  auto VI = MangledSymbols->find(Name);
139  if (VI == MangledSymbols->end())
140  return nullptr;
141  auto GV = VI->second;
142  if (!ExportedSymbolsOnly || GV->hasDefaultVisibility())
143  return GV;
144  return nullptr;
145  }
146 
147  // If we haven't built the mangled name set yet, try to build it. As an
148  // optimization this will leave MangledNames set to nullptr if we find
149  // Name in the process of building the set.
150  return buildMangledSymbols(Name, ExportedSymbolsOnly);
151  }
152 
153  BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) override {
154  // We don't need the mangled names set any more: Once we've emitted this
155  // to the base layer we'll just look for symbols there.
156  MangledSymbols.reset();
157  return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr),
158  std::move(Resolver));
159  }
160 
161  private:
162  // If the mangled name of the given GlobalValue matches the given search
163  // name (and its visibility conforms to the ExportedSymbolsOnly flag) then
164  // return the symbol. Otherwise, add the mangled name to the Names map and
165  // return nullptr.
166  const GlobalValue* addGlobalValue(StringMap<const GlobalValue*> &Names,
167  const GlobalValue &GV,
168  const Mangler &Mang, StringRef SearchName,
169  bool ExportedSymbolsOnly) const {
170  // Modules don't "provide" decls or common symbols.
171  if (GV.isDeclaration() || GV.hasCommonLinkage())
172  return nullptr;
173 
174  // Mangle the GV name.
175  std::string MangledName;
176  {
177  raw_string_ostream MangledNameStream(MangledName);
178  Mang.getNameWithPrefix(MangledNameStream, &GV, false);
179  }
180 
181  // Check whether this is the name we were searching for, and if it is then
182  // bail out early.
183  if (MangledName == SearchName)
184  if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
185  return &GV;
186 
187  // Otherwise add this to the map for later.
188  Names[MangledName] = &GV;
189  return nullptr;
190  }
191 
192  // Build the MangledSymbols map. Bails out early (with MangledSymbols left set
193  // to nullptr) if the given SearchName is found while building the map.
194  const GlobalValue* buildMangledSymbols(StringRef SearchName,
195  bool ExportedSymbolsOnly) const {
196  assert(!MangledSymbols && "Mangled symbols map already exists?");
197 
198  auto Symbols = llvm::make_unique<StringMap<const GlobalValue*>>();
199 
200  for (const auto &M : Ms) {
201  Mangler Mang;
202 
203  for (const auto &GO : M->global_objects())
204  if (auto GV = addGlobalValue(*Symbols, GO, 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 template <typename BaseLayerT>
288 template <typename ModuleSetT, typename MemoryManagerPtrT,
289  typename SymbolResolverPtrT>
290 std::unique_ptr<typename LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet>
291 LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet::create(
292  BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr,
293  SymbolResolverPtrT Resolver) {
294  typedef EmissionDeferredSetImpl<ModuleSetT, MemoryManagerPtrT, SymbolResolverPtrT>
295  EDS;
296  return llvm::make_unique<EDS>(std::move(Ms), std::move(MemMgr),
297  std::move(Resolver));
298 }
299 
300 } // end namespace orc
301 } // end namespace llvm
302 
303 #endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
BaseLayerT::ModuleSetHandleT BaseLayerHandleT
static JITSymbolFlags fromGlobalValue(const GlobalValue &GV)
Construct a JITSymbolFlags value based on the flags of the given global value.
Definition: JITSymbol.cpp:20
Represents a symbol in the JIT.
Definition: JITSymbol.h:113
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.
struct fuzzer::@269 Flags
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
#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.
Flags for symbols in the JIT.
Definition: JITSymbol.h:36
LazyEmittingLayer(BaseLayerT &BaseLayer)
Construct a lazy emitting layer.
uint64_t JITTargetAddress
Represents an address in the target process's address space.
Definition: JITSymbol.h:33
ModuleSetListT::iterator ModuleSetHandleT
Handle to a set of loaded modules.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly)
Search for the given named symbol.
auto find(R &&Range, const T &Val) -> decltype(std::begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:757
Module.h This file contains the declarations for the Module class.
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 ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47