LLVM  10.0.0svn
LazyEmittingLayer.h
Go to the documentation of this file.
1 //===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Contains the definition for a lazy-emitting layer for the JIT.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
14 #define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
15 
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringMap.h"
18 #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 /// Lazy-emitting IR layer.
36 ///
37 /// This layer accepts LLVM IR Modules (via addModule) but does not
38 /// immediately emit them the layer below. Instead, emission to the base layer
39 /// is deferred until the first time the client requests the address (via
40 /// JITSymbol::getAddress) for a symbol contained in this layer.
41 template <typename BaseLayerT> class LazyEmittingLayer {
42 private:
43  class EmissionDeferredModule {
44  public:
45  EmissionDeferredModule(VModuleKey K, std::unique_ptr<Module> M)
46  : K(std::move(K)), M(std::move(M)) {}
47 
48  JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
49  switch (EmitState) {
50  case NotEmitted:
51  if (auto GV = searchGVs(Name, ExportedSymbolsOnly)) {
53  auto GetAddress = [this, ExportedSymbolsOnly, Name = Name.str(),
55  if (this->EmitState == Emitting)
56  return 0;
57  else if (this->EmitState == NotEmitted) {
58  this->EmitState = Emitting;
59  if (auto Err = this->emitToBaseLayer(B))
60  return std::move(Err);
61  this->EmitState = Emitted;
62  }
63  if (auto Sym = B.findSymbolIn(K, Name, ExportedSymbolsOnly))
64  return Sym.getAddress();
65  else if (auto Err = Sym.takeError())
66  return std::move(Err);
67  else
68  llvm_unreachable("Successful symbol lookup should return "
69  "definition address here");
70  };
71  return JITSymbol(std::move(GetAddress), Flags);
72  } else
73  return nullptr;
74  case Emitting:
75  // Calling "emit" can trigger a recursive call to 'find' (e.g. to check
76  // for pre-existing definitions of common-symbol), but any symbol in
77  // this module would already have been found internally (in the
78  // RuntimeDyld that did the lookup), so just return a nullptr here.
79  return nullptr;
80  case Emitted:
81  return B.findSymbolIn(K, Name, ExportedSymbolsOnly);
82  }
83  llvm_unreachable("Invalid emit-state.");
84  }
85 
86  Error removeModuleFromBaseLayer(BaseLayerT& BaseLayer) {
87  return EmitState != NotEmitted ? BaseLayer.removeModule(K)
88  : Error::success();
89  }
90 
91  void emitAndFinalize(BaseLayerT &BaseLayer) {
92  assert(EmitState != Emitting &&
93  "Cannot emitAndFinalize while already emitting");
94  if (EmitState == NotEmitted) {
95  EmitState = Emitting;
96  emitToBaseLayer(BaseLayer);
97  EmitState = Emitted;
98  }
99  BaseLayer.emitAndFinalize(K);
100  }
101 
102  private:
103 
104  const GlobalValue* searchGVs(StringRef Name,
105  bool ExportedSymbolsOnly) const {
106  // FIXME: We could clean all this up if we had a way to reliably demangle
107  // names: We could just demangle name and search, rather than
108  // mangling everything else.
109 
110  // If we have already built the mangled name set then just search it.
111  if (MangledSymbols) {
112  auto VI = MangledSymbols->find(Name);
113  if (VI == MangledSymbols->end())
114  return nullptr;
115  auto GV = VI->second;
116  if (!ExportedSymbolsOnly || GV->hasDefaultVisibility())
117  return GV;
118  return nullptr;
119  }
120 
121  // If we haven't built the mangled name set yet, try to build it. As an
122  // optimization this will leave MangledNames set to nullptr if we find
123  // Name in the process of building the set.
124  return buildMangledSymbols(Name, ExportedSymbolsOnly);
125  }
126 
127  Error emitToBaseLayer(BaseLayerT &BaseLayer) {
128  // We don't need the mangled names set any more: Once we've emitted this
129  // to the base layer we'll just look for symbols there.
130  MangledSymbols.reset();
131  return BaseLayer.addModule(std::move(K), std::move(M));
132  }
133 
134  // If the mangled name of the given GlobalValue matches the given search
135  // name (and its visibility conforms to the ExportedSymbolsOnly flag) then
136  // return the symbol. Otherwise, add the mangled name to the Names map and
137  // return nullptr.
138  const GlobalValue* addGlobalValue(StringMap<const GlobalValue*> &Names,
139  const GlobalValue &GV,
140  const Mangler &Mang, StringRef SearchName,
141  bool ExportedSymbolsOnly) const {
142  // Modules don't "provide" decls or common symbols.
143  if (GV.isDeclaration() || GV.hasCommonLinkage())
144  return nullptr;
145 
146  // Mangle the GV name.
147  std::string MangledName;
148  {
149  raw_string_ostream MangledNameStream(MangledName);
150  Mang.getNameWithPrefix(MangledNameStream, &GV, false);
151  }
152 
153  // Check whether this is the name we were searching for, and if it is then
154  // bail out early.
155  if (MangledName == SearchName)
156  if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
157  return &GV;
158 
159  // Otherwise add this to the map for later.
160  Names[MangledName] = &GV;
161  return nullptr;
162  }
163 
164  // Build the MangledSymbols map. Bails out early (with MangledSymbols left set
165  // to nullptr) if the given SearchName is found while building the map.
166  const GlobalValue* buildMangledSymbols(StringRef SearchName,
167  bool ExportedSymbolsOnly) const {
168  assert(!MangledSymbols && "Mangled symbols map already exists?");
169 
170  auto Symbols = std::make_unique<StringMap<const GlobalValue*>>();
171 
172  Mangler Mang;
173 
174  for (const auto &GO : M->global_objects())
175  if (auto GV = addGlobalValue(*Symbols, GO, Mang, SearchName,
176  ExportedSymbolsOnly))
177  return GV;
178 
179  MangledSymbols = std::move(Symbols);
180  return nullptr;
181  }
182 
183  enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted;
184  VModuleKey K;
185  std::unique_ptr<Module> M;
186  mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols;
187  };
188 
189  BaseLayerT &BaseLayer;
190  std::map<VModuleKey, std::unique_ptr<EmissionDeferredModule>> ModuleMap;
191 
192 public:
193 
194  /// Construct a lazy emitting layer.
196  LazyEmittingLayer(BaseLayerT &BaseLayer),
197  "ORCv1 layers (including LazyEmittingLayer) are deprecated. Please use "
198  "ORCv2, where lazy emission is the default");
199 
200  /// Construct a lazy emitting layer.
202  : BaseLayer(BaseLayer) {}
203 
204  /// Add the given module to the lazy emitting layer.
205  Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
206  assert(!ModuleMap.count(K) && "VModuleKey K already in use");
207  ModuleMap[K] =
208  std::make_unique<EmissionDeferredModule>(std::move(K), std::move(M));
209  return Error::success();
210  }
211 
212  /// Remove the module represented by the given handle.
213  ///
214  /// This method will free the memory associated with the given module, both
215  /// in this layer, and the base layer.
217  auto I = ModuleMap.find(K);
218  assert(I != ModuleMap.end() && "VModuleKey K not valid here");
219  auto EDM = std::move(I.second);
220  ModuleMap.erase(I);
221  return EDM->removeModuleFromBaseLayer(BaseLayer);
222  }
223 
224  /// Search for the given named symbol.
225  /// @param Name The name of the symbol to search for.
226  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
227  /// @return A handle for the given named symbol, if it exists.
228  JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
229  // Look for the symbol among existing definitions.
230  if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
231  return Symbol;
232 
233  // If not found then search the deferred modules. If any of these contain a
234  // definition of 'Name' then they will return a JITSymbol that will emit
235  // the corresponding module when the symbol address is requested.
236  for (auto &KV : ModuleMap)
237  if (auto Symbol = KV.second->find(Name, ExportedSymbolsOnly, BaseLayer))
238  return Symbol;
239 
240  // If no definition found anywhere return a null symbol.
241  return nullptr;
242  }
243 
244  /// Get the address of the given symbol in the context of the of
245  /// compiled modules represented by the key K.
246  JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
247  bool ExportedSymbolsOnly) {
248  assert(ModuleMap.count(K) && "VModuleKey K not valid here");
249  return ModuleMap[K]->find(Name, ExportedSymbolsOnly, BaseLayer);
250  }
251 
252  /// Immediately emit and finalize the module represented by the given
253  /// key.
255  assert(ModuleMap.count(K) && "VModuleKey K not valid here");
256  return ModuleMap[K]->emitAndFinalize(BaseLayer);
257  }
258 };
259 
260 template <typename BaseLayerT>
262  : BaseLayer(BaseLayer) {}
263 
264 } // end namespace orc
265 } // end namespace llvm
266 
267 #endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
Error emitAndFinalize(VModuleKey K)
Immediately emit and finalize the module represented by the given key.
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:232
static JITSymbolFlags fromGlobalValue(const GlobalValue &GV)
Construct a JITSymbolFlags value based on the flags of the given global value.
Definition: JITSymbol.cpp:21
Represents a symbol in the JIT.
Definition: JITSymbol.h:219
This class represents lattice values for constants.
Definition: AllocatorList.h:23
Lazy-emitting IR layer.
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
LLVM_ATTRIBUTE_DEPRECATED(LazyEmittingLayer(BaseLayerT &BaseLayer), "ORCv1 layers (including LazyEmittingLayer) are deprecated. Please use " "ORCv2, where lazy emission is the default")
Construct a lazy emitting layer.
Error removeModule(VModuleKey K)
Remove the module represented by the given handle.
Tagged union holding either a T or a Error.
Definition: yaml2obj.h:21
bool hasCommonLinkage() const
Definition: GlobalValue.h:449
ORCv1DeprecationAcknowledgement
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Flags for symbols in the JIT.
Definition: JITSymbol.h:56
LazyEmittingLayer(ORCv1DeprecationAcknowledgement, 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:1186
#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:326
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:219
uint8_t uint64_t VModuleKey
VModuleKey provides a unique identifier (allocated and managed by ExecutionSessions) for a module add...
Definition: Core.h:42
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:231
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:503
Assigned address, still materializing.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
bool hasDefaultVisibility() const
Definition: GlobalValue.h:237
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:111
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
Error addModule(VModuleKey K, std::unique_ptr< Module > M)
Add the given module to the lazy emitting layer.