1 //===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Contains the definition for a lazy-emitting layer for the JIT.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
14 #define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
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"
35 /// Lazy-emitting IR layer.
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 {
43 class EmissionDeferredModule {
45 EmissionDeferredModule(VModuleKey K, std::unique_ptr<Module> M)
46 : K(std::move(K)), M(std::move(M)) {}
48 JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
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)
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;
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);
68 llvm_unreachable("Successful symbol lookup should return "
69 "definition address here");
71 return JITSymbol(std::move(GetAddress), Flags);
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.
81 return B.findSymbolIn(K, Name, ExportedSymbolsOnly);
83 llvm_unreachable("Invalid emit-state.");
86 Error removeModuleFromBaseLayer(BaseLayerT& BaseLayer) {
87 return EmitState != NotEmitted ? BaseLayer.removeModule(K)
91 void emitAndFinalize(BaseLayerT &BaseLayer) {
92 assert(EmitState != Emitting &&
93 "Cannot emitAndFinalize while already emitting");
94 if (EmitState == NotEmitted) {
96 emitToBaseLayer(BaseLayer);
99 BaseLayer.emitAndFinalize(K);
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.
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())
115 auto GV = VI->second;
116 if (!ExportedSymbolsOnly || GV->hasDefaultVisibility())
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);
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));
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
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())
146 // Mangle the GV name.
147 std::string MangledName;
149 raw_string_ostream MangledNameStream(MangledName);
150 Mang.getNameWithPrefix(MangledNameStream, &GV, false);
153 // Check whether this is the name we were searching for, and if it is then
155 if (MangledName == SearchName)
156 if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
159 // Otherwise add this to the map for later.
160 Names[MangledName] = &GV;
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?");
170 auto Symbols = std::make_unique<StringMap<const GlobalValue*>>();
174 for (const auto &GO : M->global_objects())
175 if (auto GV = addGlobalValue(*Symbols, GO, Mang, SearchName,
176 ExportedSymbolsOnly))
179 MangledSymbols = std::move(Symbols);
183 enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted;
185 std::unique_ptr<Module> M;
186 mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols;
189 BaseLayerT &BaseLayer;
190 std::map<VModuleKey, std::unique_ptr<EmissionDeferredModule>> ModuleMap;
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");
200 /// Construct a lazy emitting layer.
201 LazyEmittingLayer(ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer)
202 : BaseLayer(BaseLayer) {}
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");
208 std::make_unique<EmissionDeferredModule>(std::move(K), std::move(M));
209 return Error::success();
212 /// Remove the module represented by the given handle.
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);
221 return EDM->removeModuleFromBaseLayer(BaseLayer);
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))
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))
240 // If no definition found anywhere return a null symbol.
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);
252 /// Immediately emit and finalize the module represented by the given
254 Error emitAndFinalize(VModuleKey K) {
255 assert(ModuleMap.count(K) && "VModuleKey K not valid here");
256 return ModuleMap[K]->emitAndFinalize(BaseLayer);
260 template <typename BaseLayerT>
261 LazyEmittingLayer<BaseLayerT>::LazyEmittingLayer(BaseLayerT &BaseLayer)
262 : BaseLayer(BaseLayer) {}
264 } // end namespace orc
265 } // end namespace llvm
267 #endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H