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 "LookasideRTDyldMM.h"
18 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
19 #include "llvm/IR/GlobalValue.h"
20 #include "llvm/IR/Mangler.h"
25 /// @brief Lazy-emitting IR layer.
27 /// This layer accepts sets of LLVM IR Modules (via addModuleSet), but does
28 /// not immediately emit them the layer below. Instead, emissing to the base
29 /// layer is deferred until some symbol in the module set is requested via
31 template <typename BaseLayerT> class LazyEmittingLayer {
33 typedef typename BaseLayerT::ModuleSetHandleT BaseLayerHandleT;
36 class EmissionDeferredSet {
38 EmissionDeferredSet() : EmitState(NotEmitted) {}
39 virtual ~EmissionDeferredSet() {}
41 uint64_t Search(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
44 if (Provides(Name, ExportedSymbolsOnly)) {
52 // The module has been added to the base layer but we haven't gotten a
53 // handle back yet so we can't use lookupSymbolAddressIn. Just return
54 // '0' here - LazyEmittingLayer::getSymbolAddress will do a global
55 // search in the base layer when it doesn't find the symbol here, so
56 // we'll find it in the end.
59 // Nothing to do. Go ahead and search the base layer.
63 return B.lookupSymbolAddressIn(Handle, Name, ExportedSymbolsOnly);
66 void RemoveModulesFromBaseLayer(BaseLayerT &BaseLayer) {
67 if (EmitState != NotEmitted)
68 BaseLayer.removeModuleSet(Handle);
71 template <typename ModuleSetT>
72 static std::unique_ptr<EmissionDeferredSet>
73 create(BaseLayerT &B, ModuleSetT Ms,
74 std::unique_ptr<RTDyldMemoryManager> MM);
77 virtual bool Provides(StringRef Name, bool ExportedSymbolsOnly) const = 0;
78 virtual BaseLayerHandleT Emit(BaseLayerT &BaseLayer) = 0;
81 enum { NotEmitted, Emitting, Emitted } EmitState;
82 BaseLayerHandleT Handle;
85 template <typename ModuleSetT>
86 class EmissionDeferredSetImpl : public EmissionDeferredSet {
88 EmissionDeferredSetImpl(ModuleSetT Ms,
89 std::unique_ptr<RTDyldMemoryManager> MM)
90 : Ms(std::move(Ms)), MM(std::move(MM)) {}
93 BaseLayerHandleT Emit(BaseLayerT &BaseLayer) override {
94 // We don't need the mangled names set any more: Once we've emitted this
95 // to the base layer we'll just look for symbols there.
97 return BaseLayer.addModuleSet(std::move(Ms), std::move(MM));
100 bool Provides(StringRef Name, bool ExportedSymbolsOnly) const override {
101 // FIXME: We could clean all this up if we had a way to reliably demangle
102 // names: We could just demangle name and search, rather than
103 // mangling everything else.
105 // If we have already built the mangled name set then just search it.
107 auto VI = MangledNames->find(Name);
108 if (VI == MangledNames->end())
110 return !ExportedSymbolsOnly || VI->second;
113 // If we haven't built the mangled name set yet, try to build it. As an
114 // optimization this will leave MangledNames set to nullptr if we find
115 // Name in the process of building the set.
116 buildMangledNames(Name, ExportedSymbolsOnly);
123 // If the mangled name of the given GlobalValue matches the given search
124 // name (and its visibility conforms to the ExportedSymbolsOnly flag) then
125 // just return 'true'. Otherwise, add the mangled name to the Names map and
127 bool addGlobalValue(StringMap<bool> &Names, const GlobalValue &GV,
128 const Mangler &Mang, StringRef SearchName,
129 bool ExportedSymbolsOnly) const {
130 // Modules don't "provide" decls or common symbols.
131 if (GV.isDeclaration() || GV.hasCommonLinkage())
134 // Mangle the GV name.
135 std::string MangledName;
137 raw_string_ostream MangledNameStream(MangledName);
138 Mang.getNameWithPrefix(MangledNameStream, &GV, false);
141 // Check whether this is the name we were searching for, and if it is then
143 if (MangledName == SearchName)
144 if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
147 // Otherwise add this to the map for later.
148 Names[MangledName] = GV.hasDefaultVisibility();
152 // Build the MangledNames map. Bails out early (with MangledNames left set
153 // to nullptr) if the given SearchName is found while building the map.
154 void buildMangledNames(StringRef SearchName,
155 bool ExportedSymbolsOnly) const {
156 assert(!MangledNames && "Mangled names map already exists?");
158 auto Names = llvm::make_unique<StringMap<bool>>();
160 for (const auto &M : Ms) {
161 Mangler Mang(M->getDataLayout());
163 for (const auto &GV : M->globals())
164 if (addGlobalValue(*Names, GV, Mang, SearchName, ExportedSymbolsOnly))
167 for (const auto &F : *M)
168 if (addGlobalValue(*Names, F, Mang, SearchName, ExportedSymbolsOnly))
172 MangledNames = std::move(Names);
176 std::unique_ptr<RTDyldMemoryManager> MM;
177 mutable std::unique_ptr<StringMap<bool>> MangledNames;
180 typedef std::list<std::unique_ptr<EmissionDeferredSet>> ModuleSetListT;
182 BaseLayerT &BaseLayer;
183 ModuleSetListT ModuleSetList;
186 /// @brief Handle to a set of loaded modules.
187 typedef typename ModuleSetListT::iterator ModuleSetHandleT;
189 /// @brief Construct a lazy emitting layer.
190 LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
192 /// @brief Add the given set of modules to the lazy emitting layer.
194 /// This method stores the set of modules in a side table, rather than
195 /// immediately emitting them to the next layer of the JIT. When the address
196 /// of a symbol provided by this set is requested (via getSymbolAddress) it
197 /// triggers the emission of this set to the layer below (along with the given
198 /// memory manager instance), and returns the address of the requested symbol.
199 template <typename ModuleSetT>
200 ModuleSetHandleT addModuleSet(ModuleSetT Ms,
201 std::unique_ptr<RTDyldMemoryManager> MM) {
202 return ModuleSetList.insert(
204 EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MM)));
207 /// @brief Remove the module set represented by the given handle.
209 /// This method will free the memory associated with the given module set,
210 /// both in this layer, and the base layer.
211 void removeModuleSet(ModuleSetHandleT H) {
212 (*H)->RemoveModulesFromBaseLayer(BaseLayer);
213 ModuleSetList.erase(H);
216 /// @brief Get the address of a symbol provided by this layer, or some layer
219 /// When called for a symbol that has been added to this layer (via
220 /// addModuleSet) but not yet emitted, this will trigger the emission of the
221 /// module set containing the definiton of the symbol.
222 uint64_t getSymbolAddress(const std::string &Name, bool ExportedSymbolsOnly) {
223 // Look up symbol among existing definitions.
224 if (uint64_t Addr = BaseLayer.getSymbolAddress(Name, ExportedSymbolsOnly))
227 // If not found then search the deferred sets. The call to 'Search' will
228 // cause the set to be emitted to the next layer if it provides a definition
230 for (auto &DeferredSet : ModuleSetList)
232 DeferredSet->Search(Name, ExportedSymbolsOnly, BaseLayer))
235 // If no definition found anywhere return 0.
239 /// @brief Get the address of the given symbol in the context of the set of
240 /// compiled modules represented by the handle H. This call is
241 /// forwarded to the base layer's implementation.
242 uint64_t lookupSymbolAddressIn(ModuleSetHandleT H, const std::string &Name,
243 bool ExportedSymbolsOnly) {
244 return (*H)->Search(Name, ExportedSymbolsOnly, BaseLayer);
248 template <typename BaseLayerT>
249 template <typename ModuleSetT>
250 std::unique_ptr<typename LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet>
251 LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet::create(
252 BaseLayerT &B, ModuleSetT Ms, std::unique_ptr<RTDyldMemoryManager> MM) {
253 return llvm::make_unique<EmissionDeferredSetImpl<ModuleSetT>>(std::move(Ms),
258 #endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H