blob: e5c5feb22812647a6844858b7bad96e1d97f086a [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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
32namespace llvm {
33namespace orc {
34
Andrew Scullcdfcccc2018-10-05 20:58:37 +010035/// Lazy-emitting IR layer.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010036///
Andrew Walbran3d2c1972020-04-07 12:24:26 +010037/// This layer accepts LLVM IR Modules (via addModule) but does not
38/// immediately emit them the layer below. Instead, emission to the base layer
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010039/// is deferred until the first time the client requests the address (via
40/// JITSymbol::getAddress) for a symbol contained in this layer.
41template <typename BaseLayerT> class LazyEmittingLayer {
42private:
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 // 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);
57 auto GetAddress =
58 [this, ExportedSymbolsOnly, PName, &B]() -> Expected<JITTargetAddress> {
59 if (this->EmitState == Emitting)
60 return 0;
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;
66 }
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);
71 else
72 llvm_unreachable("Successful symbol lookup should return "
73 "definition address here");
74 };
75 return JITSymbol(std::move(GetAddress), Flags);
76 } else
77 return nullptr;
78 case Emitting:
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.
83 return nullptr;
84 case Emitted:
85 return B.findSymbolIn(K, Name, ExportedSymbolsOnly);
86 }
87 llvm_unreachable("Invalid emit-state.");
88 }
89
90 Error removeModuleFromBaseLayer(BaseLayerT& BaseLayer) {
91 return EmitState != NotEmitted ? BaseLayer.removeModule(K)
92 : Error::success();
93 }
94
95 void emitAndFinalize(BaseLayerT &BaseLayer) {
96 assert(EmitState != Emitting &&
97 "Cannot emitAndFinalize while already emitting");
98 if (EmitState == NotEmitted) {
99 EmitState = Emitting;
100 emitToBaseLayer(BaseLayer);
101 EmitState = Emitted;
102 }
103 BaseLayer.emitAndFinalize(K);
104 }
105
106 private:
107
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.
113
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())
118 return nullptr;
119 auto GV = VI->second;
120 if (!ExportedSymbolsOnly || GV->hasDefaultVisibility())
121 return GV;
122 return nullptr;
123 }
124
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);
129 }
130
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));
136 }
137
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
141 // return nullptr.
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())
148 return nullptr;
149
150 // Mangle the GV name.
151 std::string MangledName;
152 {
153 raw_string_ostream MangledNameStream(MangledName);
154 Mang.getNameWithPrefix(MangledNameStream, &GV, false);
155 }
156
157 // Check whether this is the name we were searching for, and if it is then
158 // bail out early.
159 if (MangledName == SearchName)
160 if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
161 return &GV;
162
163 // Otherwise add this to the map for later.
164 Names[MangledName] = &GV;
165 return nullptr;
166 }
167
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?");
173
174 auto Symbols = llvm::make_unique<StringMap<const GlobalValue*>>();
175
176 Mangler Mang;
177
178 for (const auto &GO : M->global_objects())
179 if (auto GV = addGlobalValue(*Symbols, GO, Mang, SearchName,
180 ExportedSymbolsOnly))
181 return GV;
182
183 MangledSymbols = std::move(Symbols);
184 return nullptr;
185 }
186
187 enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted;
188 VModuleKey K;
189 std::unique_ptr<Module> M;
190 mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols;
191 };
192
193 BaseLayerT &BaseLayer;
194 std::map<VModuleKey, std::unique_ptr<EmissionDeferredModule>> ModuleMap;
195
196public:
197
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100198 /// Construct a lazy emitting layer.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100199 LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
200
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100201 /// Add the given module to the lazy emitting layer.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100202 Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
203 assert(!ModuleMap.count(K) && "VModuleKey K already in use");
204 ModuleMap[K] =
205 llvm::make_unique<EmissionDeferredModule>(std::move(K), std::move(M));
206 return Error::success();
207 }
208
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100209 /// Remove the module represented by the given handle.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100210 ///
211 /// This method will free the memory associated with the given module, both
212 /// in this layer, and the base layer.
213 Error removeModule(VModuleKey K) {
214 auto I = ModuleMap.find(K);
215 assert(I != ModuleMap.end() && "VModuleKey K not valid here");
216 auto EDM = std::move(I.second);
217 ModuleMap.erase(I);
218 return EDM->removeModuleFromBaseLayer(BaseLayer);
219 }
220
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100221 /// Search for the given named symbol.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100222 /// @param Name The name of the symbol to search for.
223 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
224 /// @return A handle for the given named symbol, if it exists.
225 JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
226 // Look for the symbol among existing definitions.
227 if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
228 return Symbol;
229
230 // If not found then search the deferred modules. If any of these contain a
231 // definition of 'Name' then they will return a JITSymbol that will emit
232 // the corresponding module when the symbol address is requested.
233 for (auto &KV : ModuleMap)
234 if (auto Symbol = KV.second->find(Name, ExportedSymbolsOnly, BaseLayer))
235 return Symbol;
236
237 // If no definition found anywhere return a null symbol.
238 return nullptr;
239 }
240
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100241 /// Get the address of the given symbol in the context of the of
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100242 /// compiled modules represented by the key K.
243 JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
244 bool ExportedSymbolsOnly) {
245 assert(ModuleMap.count(K) && "VModuleKey K not valid here");
246 return ModuleMap[K]->find(Name, ExportedSymbolsOnly, BaseLayer);
247 }
248
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100249 /// Immediately emit and finalize the module represented by the given
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100250 /// key.
251 Error emitAndFinalize(VModuleKey K) {
252 assert(ModuleMap.count(K) && "VModuleKey K not valid here");
253 return ModuleMap[K]->emitAndFinalize(BaseLayer);
254 }
255};
256
257} // end namespace orc
258} // end namespace llvm
259
260#endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H