1 //===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Contains the definition for a lazy-emitting layer for the JIT.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
15 #define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
17 #include "JITSymbol.h"
18 #include "LookasideRTDyldMM.h"
19 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
20 #include "llvm/IR/GlobalValue.h"
21 #include "llvm/IR/Mangler.h"
22 #include "llvm/IR/Module.h"
23 #include "llvm/ADT/StringMap.h"
29 /// @brief Lazy-emitting IR layer.
31 /// This layer accepts sets of LLVM IR Modules (via addModuleSet), but does
32 /// not immediately emit them the layer below. Instead, emissing to the base
33 /// layer is deferred until the first time the client requests the address
34 /// (via JITSymbol::getAddress) for a symbol contained in this layer.
35 template <typename BaseLayerT> class LazyEmittingLayer {
37 typedef typename BaseLayerT::ModuleSetHandleT BaseLayerHandleT;
40 class EmissionDeferredSet {
42 EmissionDeferredSet() : EmitState(NotEmitted) {}
43 virtual ~EmissionDeferredSet() {}
45 JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
48 if (auto GV = searchGVs(Name, ExportedSymbolsOnly)) {
49 // Create a std::string version of Name to capture here - the argument
50 // (a StringRef) may go away before the lambda is executed.
51 // FIXME: Use capture-init when we move to C++14.
52 std::string PName = Name;
53 JITSymbolFlags Flags = JITSymbolBase::flagsFromGlobalValue(*GV);
55 [this, ExportedSymbolsOnly, PName, &B]() -> TargetAddress {
56 if (this->EmitState == Emitting)
58 else if (this->EmitState == NotEmitted) {
59 this->EmitState = Emitting;
60 Handle = this->emitToBaseLayer(B);
61 this->EmitState = Emitted;
63 auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly);
64 return Sym.getAddress();
66 return JITSymbol(std::move(GetAddress), Flags);
70 // Calling "emit" can trigger external symbol lookup (e.g. to check for
71 // pre-existing definitions of common-symbol), but it will never find in
72 // this module that it would not have found already, so return null from
76 return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
78 llvm_unreachable("Invalid emit-state.");
81 void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
82 if (EmitState != NotEmitted)
83 BaseLayer.removeModuleSet(Handle);
86 void emitAndFinalize(BaseLayerT &BaseLayer) {
87 assert(EmitState != Emitting &&
88 "Cannot emitAndFinalize while already emitting");
89 if (EmitState == NotEmitted) {
91 Handle = emitToBaseLayer(BaseLayer);
94 BaseLayer.emitAndFinalize(Handle);
97 template <typename ModuleSetT>
98 static std::unique_ptr<EmissionDeferredSet>
99 create(BaseLayerT &B, ModuleSetT Ms,
100 std::unique_ptr<RTDyldMemoryManager> MM);
103 virtual const GlobalValue* searchGVs(StringRef Name,
104 bool ExportedSymbolsOnly) const = 0;
105 virtual BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) = 0;
108 enum { NotEmitted, Emitting, Emitted } EmitState;
109 BaseLayerHandleT Handle;
112 template <typename ModuleSetT>
113 class EmissionDeferredSetImpl : public EmissionDeferredSet {
115 EmissionDeferredSetImpl(ModuleSetT Ms,
116 std::unique_ptr<RTDyldMemoryManager> MM)
117 : Ms(std::move(Ms)), MM(std::move(MM)) {}
121 const GlobalValue* searchGVs(StringRef Name,
122 bool ExportedSymbolsOnly) const override {
123 // FIXME: We could clean all this up if we had a way to reliably demangle
124 // names: We could just demangle name and search, rather than
125 // mangling everything else.
127 // If we have already built the mangled name set then just search it.
128 if (MangledSymbols) {
129 auto VI = MangledSymbols->find(Name);
130 if (VI == MangledSymbols->end())
132 auto GV = VI->second;
133 if (!ExportedSymbolsOnly || GV->hasDefaultVisibility())
138 // If we haven't built the mangled name set yet, try to build it. As an
139 // optimization this will leave MangledNames set to nullptr if we find
140 // Name in the process of building the set.
141 return buildMangledSymbols(Name, ExportedSymbolsOnly);
144 BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) override {
145 // We don't need the mangled names set any more: Once we've emitted this
146 // to the base layer we'll just look for symbols there.
147 MangledSymbols.reset();
148 return BaseLayer.addModuleSet(std::move(Ms), std::move(MM));
152 // If the mangled name of the given GlobalValue matches the given search
153 // name (and its visibility conforms to the ExportedSymbolsOnly flag) then
154 // return the symbol. Otherwise, add the mangled name to the Names map and
156 const GlobalValue* addGlobalValue(StringMap<const GlobalValue*> &Names,
157 const GlobalValue &GV,
158 const Mangler &Mang, StringRef SearchName,
159 bool ExportedSymbolsOnly) const {
160 // Modules don't "provide" decls or common symbols.
161 if (GV.isDeclaration() || GV.hasCommonLinkage())
164 // Mangle the GV name.
165 std::string MangledName;
167 raw_string_ostream MangledNameStream(MangledName);
168 Mang.getNameWithPrefix(MangledNameStream, &GV, false);
171 // Check whether this is the name we were searching for, and if it is then
173 if (MangledName == SearchName)
174 if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
177 // Otherwise add this to the map for later.
178 Names[MangledName] = &GV;
182 // Build the MangledSymbols map. Bails out early (with MangledSymbols left set
183 // to nullptr) if the given SearchName is found while building the map.
184 const GlobalValue* buildMangledSymbols(StringRef SearchName,
185 bool ExportedSymbolsOnly) const {
186 assert(!MangledSymbols && "Mangled symbols map already exists?");
188 auto Symbols = llvm::make_unique<StringMap<const GlobalValue*>>();
190 for (const auto &M : Ms) {
191 Mangler Mang(&M->getDataLayout());
193 for (const auto &V : M->globals())
194 if (auto GV = addGlobalValue(*Symbols, V, Mang, SearchName,
195 ExportedSymbolsOnly))
198 for (const auto &F : *M)
199 if (auto GV = addGlobalValue(*Symbols, F, Mang, SearchName,
200 ExportedSymbolsOnly))
204 MangledSymbols = std::move(Symbols);
209 std::unique_ptr<RTDyldMemoryManager> MM;
210 mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols;
213 typedef std::list<std::unique_ptr<EmissionDeferredSet>> ModuleSetListT;
215 BaseLayerT &BaseLayer;
216 ModuleSetListT ModuleSetList;
219 /// @brief Handle to a set of loaded modules.
220 typedef typename ModuleSetListT::iterator ModuleSetHandleT;
222 /// @brief Construct a lazy emitting layer.
223 LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
225 /// @brief Add the given set of modules to the lazy emitting layer.
226 template <typename ModuleSetT>
227 ModuleSetHandleT addModuleSet(ModuleSetT Ms,
228 std::unique_ptr<RTDyldMemoryManager> MM) {
229 return ModuleSetList.insert(
231 EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MM)));
234 /// @brief Remove the module set represented by the given handle.
236 /// This method will free the memory associated with the given module set,
237 /// both in this layer, and the base layer.
238 void removeModuleSet(ModuleSetHandleT H) {
239 (*H)->removeModulesFromBaseLayer(BaseLayer);
240 ModuleSetList.erase(H);
243 /// @brief Search for the given named symbol.
244 /// @param Name The name of the symbol to search for.
245 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
246 /// @return A handle for the given named symbol, if it exists.
247 JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
248 // Look for the symbol among existing definitions.
249 if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
252 // If not found then search the deferred sets. If any of these contain a
253 // definition of 'Name' then they will return a JITSymbol that will emit
254 // the corresponding module when the symbol address is requested.
255 for (auto &DeferredSet : ModuleSetList)
256 if (auto Symbol = DeferredSet->find(Name, ExportedSymbolsOnly, BaseLayer))
259 // If no definition found anywhere return a null symbol.
263 /// @brief Get the address of the given symbol in the context of the set of
264 /// compiled modules represented by the handle H.
265 JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
266 bool ExportedSymbolsOnly) {
267 return (*H)->find(Name, ExportedSymbolsOnly, BaseLayer);
270 /// @brief Immediately emit and finalize the moduleOB set represented by the
272 /// @param H Handle for module set to emit/finalize.
273 void emitAndFinalize(ModuleSetHandleT H) {
274 (*H)->emitAndFinalize(BaseLayer);
279 template <typename BaseLayerT>
280 template <typename ModuleSetT>
281 std::unique_ptr<typename LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet>
282 LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet::create(
283 BaseLayerT &B, ModuleSetT Ms, std::unique_ptr<RTDyldMemoryManager> MM) {
284 return llvm::make_unique<EmissionDeferredSetImpl<ModuleSetT>>(std::move(Ms),
288 } // End namespace orc.
289 } // End namespace llvm.
291 #endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H