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"
20#include "llvm/ExecutionEngine/JITSymbol.h"
21#include "llvm/IR/GlobalValue.h"
22#include "llvm/IR/Mangler.h"
23#include "llvm/IR/Module.h"
24#include "llvm/Support/ErrorHandling.h"
25#include "llvm/Support/raw_ostream.h"
26#include <algorithm>
27#include <cassert>
28#include <list>
29#include <memory>
30#include <string>
31
32namespace llvm {
33namespace orc {
34
35/// @brief 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, emissing 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.
41template <typename BaseLayerT> class LazyEmittingLayer {
42public:
43
44  using BaseLayerHandleT = typename BaseLayerT::ModuleHandleT;
45
46private:
47  class EmissionDeferredModule {
48  public:
49    EmissionDeferredModule(std::shared_ptr<Module> M,
50                           std::shared_ptr<JITSymbolResolver> Resolver)
51      : M(std::move(M)), Resolver(std::move(Resolver)) {}
52
53    JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
54      switch (EmitState) {
55      case NotEmitted:
56        if (auto GV = searchGVs(Name, ExportedSymbolsOnly)) {
57          // Create a std::string version of Name to capture here - the argument
58          // (a StringRef) may go away before the lambda is executed.
59          // FIXME: Use capture-init when we move to C++14.
60          std::string PName = Name;
61          JITSymbolFlags Flags = JITSymbolFlags::fromGlobalValue(*GV);
62          auto GetAddress =
63            [this, ExportedSymbolsOnly, PName, &B]() -> Expected<JITTargetAddress> {
64              if (this->EmitState == Emitting)
65                return 0;
66              else if (this->EmitState == NotEmitted) {
67                this->EmitState = Emitting;
68                if (auto HandleOrErr = this->emitToBaseLayer(B))
69                  Handle = std::move(*HandleOrErr);
70                else
71                  return HandleOrErr.takeError();
72                this->EmitState = Emitted;
73              }
74              if (auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly))
75                return Sym.getAddress();
76              else if (auto Err = Sym.takeError())
77                return std::move(Err);
78              else
79                llvm_unreachable("Successful symbol lookup should return "
80                                 "definition address here");
81          };
82          return JITSymbol(std::move(GetAddress), Flags);
83        } else
84          return nullptr;
85      case Emitting:
86        // Calling "emit" can trigger a recursive call to 'find' (e.g. to check
87        // for pre-existing definitions of common-symbol), but any symbol in
88        // this module would already have been found internally (in the
89        // RuntimeDyld that did the lookup), so just return a nullptr here.
90        return nullptr;
91      case Emitted:
92        return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
93      }
94      llvm_unreachable("Invalid emit-state.");
95    }
96
97    Error removeModuleFromBaseLayer(BaseLayerT& BaseLayer) {
98      return EmitState != NotEmitted ? BaseLayer.removeModule(Handle)
99                                     : Error::success();
100    }
101
102    void emitAndFinalize(BaseLayerT &BaseLayer) {
103      assert(EmitState != Emitting &&
104             "Cannot emitAndFinalize while already emitting");
105      if (EmitState == NotEmitted) {
106        EmitState = Emitting;
107        Handle = emitToBaseLayer(BaseLayer);
108        EmitState = Emitted;
109      }
110      BaseLayer.emitAndFinalize(Handle);
111    }
112
113  private:
114
115    const GlobalValue* searchGVs(StringRef Name,
116                                 bool ExportedSymbolsOnly) const {
117      // FIXME: We could clean all this up if we had a way to reliably demangle
118      //        names: We could just demangle name and search, rather than
119      //        mangling everything else.
120
121      // If we have already built the mangled name set then just search it.
122      if (MangledSymbols) {
123        auto VI = MangledSymbols->find(Name);
124        if (VI == MangledSymbols->end())
125          return nullptr;
126        auto GV = VI->second;
127        if (!ExportedSymbolsOnly || GV->hasDefaultVisibility())
128          return GV;
129        return nullptr;
130      }
131
132      // If we haven't built the mangled name set yet, try to build it. As an
133      // optimization this will leave MangledNames set to nullptr if we find
134      // Name in the process of building the set.
135      return buildMangledSymbols(Name, ExportedSymbolsOnly);
136    }
137
138    Expected<BaseLayerHandleT> emitToBaseLayer(BaseLayerT &BaseLayer) {
139      // We don't need the mangled names set any more: Once we've emitted this
140      // to the base layer we'll just look for symbols there.
141      MangledSymbols.reset();
142      return BaseLayer.addModule(std::move(M), std::move(Resolver));
143    }
144
145    // If the mangled name of the given GlobalValue matches the given search
146    // name (and its visibility conforms to the ExportedSymbolsOnly flag) then
147    // return the symbol. Otherwise, add the mangled name to the Names map and
148    // return nullptr.
149    const GlobalValue* addGlobalValue(StringMap<const GlobalValue*> &Names,
150                                      const GlobalValue &GV,
151                                      const Mangler &Mang, StringRef SearchName,
152                                      bool ExportedSymbolsOnly) const {
153      // Modules don't "provide" decls or common symbols.
154      if (GV.isDeclaration() || GV.hasCommonLinkage())
155        return nullptr;
156
157      // Mangle the GV name.
158      std::string MangledName;
159      {
160        raw_string_ostream MangledNameStream(MangledName);
161        Mang.getNameWithPrefix(MangledNameStream, &GV, false);
162      }
163
164      // Check whether this is the name we were searching for, and if it is then
165      // bail out early.
166      if (MangledName == SearchName)
167        if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
168          return &GV;
169
170      // Otherwise add this to the map for later.
171      Names[MangledName] = &GV;
172      return nullptr;
173    }
174
175    // Build the MangledSymbols map. Bails out early (with MangledSymbols left set
176    // to nullptr) if the given SearchName is found while building the map.
177    const GlobalValue* buildMangledSymbols(StringRef SearchName,
178                                           bool ExportedSymbolsOnly) const {
179      assert(!MangledSymbols && "Mangled symbols map already exists?");
180
181      auto Symbols = llvm::make_unique<StringMap<const GlobalValue*>>();
182
183      Mangler Mang;
184
185      for (const auto &GO : M->global_objects())
186          if (auto GV = addGlobalValue(*Symbols, GO, Mang, SearchName,
187                                       ExportedSymbolsOnly))
188            return GV;
189
190      MangledSymbols = std::move(Symbols);
191      return nullptr;
192    }
193
194    enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted;
195    BaseLayerHandleT Handle;
196    std::shared_ptr<Module> M;
197    std::shared_ptr<JITSymbolResolver> Resolver;
198    mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols;
199  };
200
201  using ModuleListT = std::list<std::unique_ptr<EmissionDeferredModule>>;
202
203  BaseLayerT &BaseLayer;
204  ModuleListT ModuleList;
205
206public:
207
208  /// @brief Handle to a loaded module.
209  using ModuleHandleT = typename ModuleListT::iterator;
210
211  /// @brief Construct a lazy emitting layer.
212  LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
213
214  /// @brief Add the given module to the lazy emitting layer.
215  Expected<ModuleHandleT>
216  addModule(std::shared_ptr<Module> M,
217            std::shared_ptr<JITSymbolResolver> Resolver) {
218    return ModuleList.insert(
219        ModuleList.end(),
220        llvm::make_unique<EmissionDeferredModule>(std::move(M),
221                                                  std::move(Resolver)));
222  }
223
224  /// @brief Remove the module represented by the given handle.
225  ///
226  ///   This method will free the memory associated with the given module, both
227  /// in this layer, and the base layer.
228  Error removeModule(ModuleHandleT H) {
229    Error Err = (*H)->removeModuleFromBaseLayer(BaseLayer);
230    ModuleList.erase(H);
231    return Err;
232  }
233
234  /// @brief Search for the given named symbol.
235  /// @param Name The name of the symbol to search for.
236  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
237  /// @return A handle for the given named symbol, if it exists.
238  JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
239    // Look for the symbol among existing definitions.
240    if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
241      return Symbol;
242
243    // If not found then search the deferred modules. If any of these contain a
244    // definition of 'Name' then they will return a JITSymbol that will emit
245    // the corresponding module when the symbol address is requested.
246    for (auto &DeferredMod : ModuleList)
247      if (auto Symbol = DeferredMod->find(Name, ExportedSymbolsOnly, BaseLayer))
248        return Symbol;
249
250    // If no definition found anywhere return a null symbol.
251    return nullptr;
252  }
253
254  /// @brief Get the address of the given symbol in the context of the of
255  ///        compiled modules represented by the handle H.
256  JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
257                         bool ExportedSymbolsOnly) {
258    return (*H)->find(Name, ExportedSymbolsOnly, BaseLayer);
259  }
260
261  /// @brief Immediately emit and finalize the module represented by the given
262  ///        handle.
263  /// @param H Handle for module to emit/finalize.
264  Error emitAndFinalize(ModuleHandleT H) {
265    return (*H)->emitAndFinalize(BaseLayer);
266  }
267};
268
269} // end namespace orc
270} // end namespace llvm
271
272#endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
273