]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / include / llvm / ExecutionEngine / Orc / LazyEmittingLayer.h
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
32 namespace llvm {
33 namespace 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.
41 template <typename BaseLayerT> class LazyEmittingLayer {
42 private:
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
192 public:
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
260 template <typename BaseLayerT>
261 LazyEmittingLayer<BaseLayerT>::LazyEmittingLayer(BaseLayerT &BaseLayer)
262     : BaseLayer(BaseLayer) {}
263
264 } // end namespace orc
265 } // end namespace llvm
266
267 #endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H