LazyEmittingLayer.h revision 360784
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 32namespace llvm { 33namespace 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. 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 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 192public: 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 260template <typename BaseLayerT> 261LazyEmittingLayer<BaseLayerT>::LazyEmittingLayer(BaseLayerT &BaseLayer) 262 : BaseLayer(BaseLayer) {} 263 264} // end namespace orc 265} // end namespace llvm 266 267#endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H 268