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 // Create a std::string version of Name to capture here - the argument
53 // (a StringRef) may go away before the lambda is executed.
54 // FIXME: Use capture-init when we move to C++14.
55 std::string PName
= Name
;
56 JITSymbolFlags Flags
= JITSymbolFlags::fromGlobalValue(*GV
);
58 [this, ExportedSymbolsOnly
, PName
, &B
]() -> Expected
<JITTargetAddress
> {
59 if (this->EmitState
== Emitting
)
61 else if (this->EmitState
== NotEmitted
) {
62 this->EmitState
= Emitting
;
63 if (auto Err
= this->emitToBaseLayer(B
))
64 return std::move(Err
);
65 this->EmitState
= Emitted
;
67 if (auto Sym
= B
.findSymbolIn(K
, PName
, ExportedSymbolsOnly
))
68 return Sym
.getAddress();
69 else if (auto Err
= Sym
.takeError())
70 return std::move(Err
);
72 llvm_unreachable("Successful symbol lookup should return "
73 "definition address here");
75 return JITSymbol(std::move(GetAddress
), Flags
);
79 // Calling "emit" can trigger a recursive call to 'find' (e.g. to check
80 // for pre-existing definitions of common-symbol), but any symbol in
81 // this module would already have been found internally (in the
82 // RuntimeDyld that did the lookup), so just return a nullptr here.
85 return B
.findSymbolIn(K
, Name
, ExportedSymbolsOnly
);
87 llvm_unreachable("Invalid emit-state.");
90 Error
removeModuleFromBaseLayer(BaseLayerT
& BaseLayer
) {
91 return EmitState
!= NotEmitted
? BaseLayer
.removeModule(K
)
95 void emitAndFinalize(BaseLayerT
&BaseLayer
) {
96 assert(EmitState
!= Emitting
&&
97 "Cannot emitAndFinalize while already emitting");
98 if (EmitState
== NotEmitted
) {
100 emitToBaseLayer(BaseLayer
);
103 BaseLayer
.emitAndFinalize(K
);
108 const GlobalValue
* searchGVs(StringRef Name
,
109 bool ExportedSymbolsOnly
) const {
110 // FIXME: We could clean all this up if we had a way to reliably demangle
111 // names: We could just demangle name and search, rather than
112 // mangling everything else.
114 // If we have already built the mangled name set then just search it.
115 if (MangledSymbols
) {
116 auto VI
= MangledSymbols
->find(Name
);
117 if (VI
== MangledSymbols
->end())
119 auto GV
= VI
->second
;
120 if (!ExportedSymbolsOnly
|| GV
->hasDefaultVisibility())
125 // If we haven't built the mangled name set yet, try to build it. As an
126 // optimization this will leave MangledNames set to nullptr if we find
127 // Name in the process of building the set.
128 return buildMangledSymbols(Name
, ExportedSymbolsOnly
);
131 Error
emitToBaseLayer(BaseLayerT
&BaseLayer
) {
132 // We don't need the mangled names set any more: Once we've emitted this
133 // to the base layer we'll just look for symbols there.
134 MangledSymbols
.reset();
135 return BaseLayer
.addModule(std::move(K
), std::move(M
));
138 // If the mangled name of the given GlobalValue matches the given search
139 // name (and its visibility conforms to the ExportedSymbolsOnly flag) then
140 // return the symbol. Otherwise, add the mangled name to the Names map and
142 const GlobalValue
* addGlobalValue(StringMap
<const GlobalValue
*> &Names
,
143 const GlobalValue
&GV
,
144 const Mangler
&Mang
, StringRef SearchName
,
145 bool ExportedSymbolsOnly
) const {
146 // Modules don't "provide" decls or common symbols.
147 if (GV
.isDeclaration() || GV
.hasCommonLinkage())
150 // Mangle the GV name.
151 std::string MangledName
;
153 raw_string_ostream
MangledNameStream(MangledName
);
154 Mang
.getNameWithPrefix(MangledNameStream
, &GV
, false);
157 // Check whether this is the name we were searching for, and if it is then
159 if (MangledName
== SearchName
)
160 if (!ExportedSymbolsOnly
|| GV
.hasDefaultVisibility())
163 // Otherwise add this to the map for later.
164 Names
[MangledName
] = &GV
;
168 // Build the MangledSymbols map. Bails out early (with MangledSymbols left set
169 // to nullptr) if the given SearchName is found while building the map.
170 const GlobalValue
* buildMangledSymbols(StringRef SearchName
,
171 bool ExportedSymbolsOnly
) const {
172 assert(!MangledSymbols
&& "Mangled symbols map already exists?");
174 auto Symbols
= std::make_unique
<StringMap
<const GlobalValue
*>>();
178 for (const auto &GO
: M
->global_objects())
179 if (auto GV
= addGlobalValue(*Symbols
, GO
, Mang
, SearchName
,
180 ExportedSymbolsOnly
))
183 MangledSymbols
= std::move(Symbols
);
187 enum { NotEmitted
, Emitting
, Emitted
} EmitState
= NotEmitted
;
189 std::unique_ptr
<Module
> M
;
190 mutable std::unique_ptr
<StringMap
<const GlobalValue
*>> MangledSymbols
;
193 BaseLayerT
&BaseLayer
;
194 std::map
<VModuleKey
, std::unique_ptr
<EmissionDeferredModule
>> ModuleMap
;
198 /// Construct a lazy emitting layer.
199 LLVM_ATTRIBUTE_DEPRECATED(
200 LazyEmittingLayer(BaseLayerT
&BaseLayer
),
201 "ORCv1 layers (including LazyEmittingLayer) are deprecated. Please use "
202 "ORCv2, where lazy emission is the default");
204 /// Construct a lazy emitting layer.
205 LazyEmittingLayer(ORCv1DeprecationAcknowledgement
, BaseLayerT
&BaseLayer
)
206 : BaseLayer(BaseLayer
) {}
208 /// Add the given module to the lazy emitting layer.
209 Error
addModule(VModuleKey K
, std::unique_ptr
<Module
> M
) {
210 assert(!ModuleMap
.count(K
) && "VModuleKey K already in use");
212 std::make_unique
<EmissionDeferredModule
>(std::move(K
), std::move(M
));
213 return Error::success();
216 /// Remove the module represented by the given handle.
218 /// This method will free the memory associated with the given module, both
219 /// in this layer, and the base layer.
220 Error
removeModule(VModuleKey K
) {
221 auto I
= ModuleMap
.find(K
);
222 assert(I
!= ModuleMap
.end() && "VModuleKey K not valid here");
223 auto EDM
= std::move(I
.second
);
225 return EDM
->removeModuleFromBaseLayer(BaseLayer
);
228 /// Search for the given named symbol.
229 /// @param Name The name of the symbol to search for.
230 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
231 /// @return A handle for the given named symbol, if it exists.
232 JITSymbol
findSymbol(const std::string
&Name
, bool ExportedSymbolsOnly
) {
233 // Look for the symbol among existing definitions.
234 if (auto Symbol
= BaseLayer
.findSymbol(Name
, ExportedSymbolsOnly
))
237 // If not found then search the deferred modules. If any of these contain a
238 // definition of 'Name' then they will return a JITSymbol that will emit
239 // the corresponding module when the symbol address is requested.
240 for (auto &KV
: ModuleMap
)
241 if (auto Symbol
= KV
.second
->find(Name
, ExportedSymbolsOnly
, BaseLayer
))
244 // If no definition found anywhere return a null symbol.
248 /// Get the address of the given symbol in the context of the of
249 /// compiled modules represented by the key K.
250 JITSymbol
findSymbolIn(VModuleKey K
, const std::string
&Name
,
251 bool ExportedSymbolsOnly
) {
252 assert(ModuleMap
.count(K
) && "VModuleKey K not valid here");
253 return ModuleMap
[K
]->find(Name
, ExportedSymbolsOnly
, BaseLayer
);
256 /// Immediately emit and finalize the module represented by the given
258 Error
emitAndFinalize(VModuleKey K
) {
259 assert(ModuleMap
.count(K
) && "VModuleKey K not valid here");
260 return ModuleMap
[K
]->emitAndFinalize(BaseLayer
);
264 template <typename BaseLayerT
>
265 LazyEmittingLayer
<BaseLayerT
>::LazyEmittingLayer(BaseLayerT
&BaseLayer
)
266 : BaseLayer(BaseLayer
) {}
268 } // end namespace orc
269 } // end namespace llvm
271 #endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H