LazyEmittingLayer.h revision 360784
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"
19#include "llvm/ExecutionEngine/JITSymbol.h"
20#include "llvm/ExecutionEngine/Orc/Core.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/// 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.
41template <typename BaseLayerT> class LazyEmittingLayer {
42private:
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)) {
52          JITSymbolFlags Flags = JITSymbolFlags::fromGlobalValue(*GV);
53          auto GetAddress = [this, ExportedSymbolsOnly, Name = Name.str(),
54                             &B]() -> Expected<JITTargetAddress> {
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
192public:
193
194  /// Construct a lazy emitting layer.
195  LLVM_ATTRIBUTE_DEPRECATED(
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.
201  LazyEmittingLayer(ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer)
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.
216  Error removeModule(VModuleKey K) {
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.
254  Error emitAndFinalize(VModuleKey K) {
255    assert(ModuleMap.count(K) && "VModuleKey K not valid here");
256    return ModuleMap[K]->emitAndFinalize(BaseLayer);
257  }
258};
259
260template <typename BaseLayerT>
261LazyEmittingLayer<BaseLayerT>::LazyEmittingLayer(BaseLayerT &BaseLayer)
262    : BaseLayer(BaseLayer) {}
263
264} // end namespace orc
265} // end namespace llvm
266
267#endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
268