LLVM  8.0.1
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"
22 #include "llvm/IR/GlobalValue.h"
23 #include "llvm/IR/Mangler.h"
24 #include "llvm/IR/Module.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  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;
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 
197 public:
198 
199  /// Construct a lazy emitting layer.
200  LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
201 
202  /// 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  /// 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.
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  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  /// 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  /// Immediately emit and finalize the module represented by the given
251  /// key.
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
Error emitAndFinalize(VModuleKey K)
Immediately emit and finalize the module represented by the given key.
static JITSymbolFlags fromGlobalValue(const GlobalValue &GV)
Construct a JITSymbolFlags value based on the flags of the given global value.
Definition: JITSymbol.cpp:22
Represents a symbol in the JIT.
Definition: JITSymbol.h:238
This class represents lattice values for constants.
Definition: AllocatorList.h:24
Lazy-emitting IR layer.
uint64_t VModuleKey
VModuleKey provides a unique identifier (allocated and managed by ExecutionSessions) for a module add...
Definition: Core.h:40
amdgpu Simplify well known AMD library false Value Value const Twine & Name
Error removeModule(VModuleKey K)
Remove the module represented by the given handle.
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
bool hasCommonLinkage() const
Definition: GlobalValue.h:440
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Flags for symbols in the JIT.
Definition: JITSymbol.h:56
LazyEmittingLayer(BaseLayerT &BaseLayer)
Construct a lazy emitting layer.
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1207
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static ErrorSuccess success()
Create a success value.
Definition: Error.h:327
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.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:220
JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, bool ExportedSymbolsOnly)
Get the address of the given symbol in the context of the of compiled modules represented by the key ...
#define I(x, y, z)
Definition: MD5.cpp:58
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition: Globals.cpp:206
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:483
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
bool hasDefaultVisibility() const
Definition: GlobalValue.h:234
void getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, bool CannotUsePrivateLabel) const
Print the appropriate prefix and the specified global variable&#39;s name.
Definition: Mangler.cpp:112
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
Error addModule(VModuleKey K, std::unique_ptr< Module > M)
Add the given module to the lazy emitting layer.