1 //===- CompileOnDemandLayer.h - Compile each function on demand -*- 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 // JIT layer for breaking up modules and inserting callbacks to allow 10 // individual functions to be compiled on demand. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H 15 #define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H 16 17 #include "llvm/ADT/APInt.h" 18 #include "llvm/ADT/Optional.h" 19 #include "llvm/ADT/STLExtras.h" 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/ADT/Twine.h" 22 #include "llvm/ExecutionEngine/JITSymbol.h" 23 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" 24 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" 25 #include "llvm/ExecutionEngine/Orc/Layer.h" 26 #include "llvm/ExecutionEngine/Orc/LazyReexports.h" 27 #include "llvm/ExecutionEngine/Orc/Legacy.h" 28 #include "llvm/ExecutionEngine/Orc/OrcError.h" 29 #include "llvm/ExecutionEngine/Orc/Speculation.h" 30 #include "llvm/ExecutionEngine/RuntimeDyld.h" 31 #include "llvm/IR/Attributes.h" 32 #include "llvm/IR/Constant.h" 33 #include "llvm/IR/Constants.h" 34 #include "llvm/IR/DataLayout.h" 35 #include "llvm/IR/Function.h" 36 #include "llvm/IR/GlobalAlias.h" 37 #include "llvm/IR/GlobalValue.h" 38 #include "llvm/IR/GlobalVariable.h" 39 #include "llvm/IR/Instruction.h" 40 #include "llvm/IR/Mangler.h" 41 #include "llvm/IR/Module.h" 42 #include "llvm/IR/Type.h" 43 #include "llvm/Support/Casting.h" 44 #include "llvm/Support/raw_ostream.h" 45 #include "llvm/Transforms/Utils/ValueMapper.h" 46 #include <algorithm> 47 #include <cassert> 48 #include <functional> 49 #include <iterator> 50 #include <list> 51 #include <memory> 52 #include <set> 53 #include <string> 54 #include <utility> 55 #include <vector> 56 57 namespace llvm { 58 59 class Value; 60 61 namespace orc { 62 63 class ExtractingIRMaterializationUnit; 64 65 class CompileOnDemandLayer : public IRLayer { 66 friend class PartitioningIRMaterializationUnit; 67 68 public: 69 /// Builder for IndirectStubsManagers. 70 using IndirectStubsManagerBuilder = 71 std::function<std::unique_ptr<IndirectStubsManager>()>; 72 73 using GlobalValueSet = std::set<const GlobalValue *>; 74 75 /// Partitioning function. 76 using PartitionFunction = 77 std::function<Optional<GlobalValueSet>(GlobalValueSet Requested)>; 78 79 /// Off-the-shelf partitioning which compiles all requested symbols (usually 80 /// a single function at a time). 81 static Optional<GlobalValueSet> compileRequested(GlobalValueSet Requested); 82 83 /// Off-the-shelf partitioning which compiles whole modules whenever any 84 /// symbol in them is requested. 85 static Optional<GlobalValueSet> compileWholeModule(GlobalValueSet Requested); 86 87 /// Construct a CompileOnDemandLayer. 88 CompileOnDemandLayer(ExecutionSession &ES, IRLayer &BaseLayer, 89 LazyCallThroughManager &LCTMgr, 90 IndirectStubsManagerBuilder BuildIndirectStubsManager); 91 92 /// Sets the partition function. 93 void setPartitionFunction(PartitionFunction Partition); 94 95 /// Sets the ImplSymbolMap 96 void setImplMap(ImplSymbolMap *Imp); 97 /// Emits the given module. This should not be called by clients: it will be 98 /// called by the JIT when a definition added via the add method is requested. 99 void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override; 100 101 private: 102 struct PerDylibResources { 103 public: PerDylibResourcesPerDylibResources104 PerDylibResources(JITDylib &ImplD, 105 std::unique_ptr<IndirectStubsManager> ISMgr) 106 : ImplD(ImplD), ISMgr(std::move(ISMgr)) {} getImplDylibPerDylibResources107 JITDylib &getImplDylib() { return ImplD; } getISManagerPerDylibResources108 IndirectStubsManager &getISManager() { return *ISMgr; } 109 110 private: 111 JITDylib &ImplD; 112 std::unique_ptr<IndirectStubsManager> ISMgr; 113 }; 114 115 using PerDylibResourcesMap = std::map<const JITDylib *, PerDylibResources>; 116 117 PerDylibResources &getPerDylibResources(JITDylib &TargetD); 118 119 void cleanUpModule(Module &M); 120 121 void expandPartition(GlobalValueSet &Partition); 122 123 void emitPartition(MaterializationResponsibility R, ThreadSafeModule TSM, 124 IRMaterializationUnit::SymbolNameToDefinitionMap Defs); 125 126 mutable std::mutex CODLayerMutex; 127 128 IRLayer &BaseLayer; 129 LazyCallThroughManager &LCTMgr; 130 IndirectStubsManagerBuilder BuildIndirectStubsManager; 131 PerDylibResourcesMap DylibResources; 132 PartitionFunction Partition = compileRequested; 133 SymbolLinkagePromoter PromoteSymbols; 134 ImplSymbolMap *AliaseeImpls = nullptr; 135 }; 136 137 /// Compile-on-demand layer. 138 /// 139 /// When a module is added to this layer a stub is created for each of its 140 /// function definitions. The stubs and other global values are immediately 141 /// added to the layer below. When a stub is called it triggers the extraction 142 /// of the function body from the original module. The extracted body is then 143 /// compiled and executed. 144 template <typename BaseLayerT, 145 typename CompileCallbackMgrT = JITCompileCallbackManager, 146 typename IndirectStubsMgrT = IndirectStubsManager> 147 class LegacyCompileOnDemandLayer { 148 private: 149 template <typename MaterializerFtor> 150 class LambdaMaterializer final : public ValueMaterializer { 151 public: LambdaMaterializer(MaterializerFtor M)152 LambdaMaterializer(MaterializerFtor M) : M(std::move(M)) {} 153 materialize(Value * V)154 Value *materialize(Value *V) final { return M(V); } 155 156 private: 157 MaterializerFtor M; 158 }; 159 160 template <typename MaterializerFtor> 161 LambdaMaterializer<MaterializerFtor> createLambdaMaterializer(MaterializerFtor M)162 createLambdaMaterializer(MaterializerFtor M) { 163 return LambdaMaterializer<MaterializerFtor>(std::move(M)); 164 } 165 166 // Provide type-erasure for the Modules and MemoryManagers. 167 template <typename ResourceT> 168 class ResourceOwner { 169 public: 170 ResourceOwner() = default; 171 ResourceOwner(const ResourceOwner &) = delete; 172 ResourceOwner &operator=(const ResourceOwner &) = delete; 173 virtual ~ResourceOwner() = default; 174 175 virtual ResourceT& getResource() const = 0; 176 }; 177 178 template <typename ResourceT, typename ResourcePtrT> 179 class ResourceOwnerImpl : public ResourceOwner<ResourceT> { 180 public: ResourceOwnerImpl(ResourcePtrT ResourcePtr)181 ResourceOwnerImpl(ResourcePtrT ResourcePtr) 182 : ResourcePtr(std::move(ResourcePtr)) {} 183 getResource()184 ResourceT& getResource() const override { return *ResourcePtr; } 185 186 private: 187 ResourcePtrT ResourcePtr; 188 }; 189 190 template <typename ResourceT, typename ResourcePtrT> 191 std::unique_ptr<ResourceOwner<ResourceT>> wrapOwnership(ResourcePtrT ResourcePtr)192 wrapOwnership(ResourcePtrT ResourcePtr) { 193 using RO = ResourceOwnerImpl<ResourceT, ResourcePtrT>; 194 return std::make_unique<RO>(std::move(ResourcePtr)); 195 } 196 197 struct LogicalDylib { 198 struct SourceModuleEntry { 199 std::unique_ptr<Module> SourceMod; 200 std::set<Function*> StubsToClone; 201 }; 202 203 using SourceModulesList = std::vector<SourceModuleEntry>; 204 using SourceModuleHandle = typename SourceModulesList::size_type; 205 206 LogicalDylib() = default; 207 LogicalDylibLogicalDylib208 LogicalDylib(VModuleKey K, std::shared_ptr<SymbolResolver> BackingResolver, 209 std::unique_ptr<IndirectStubsMgrT> StubsMgr) 210 : K(std::move(K)), BackingResolver(std::move(BackingResolver)), 211 StubsMgr(std::move(StubsMgr)) {} 212 addSourceModuleLogicalDylib213 SourceModuleHandle addSourceModule(std::unique_ptr<Module> M) { 214 SourceModuleHandle H = SourceModules.size(); 215 SourceModules.push_back(SourceModuleEntry()); 216 SourceModules.back().SourceMod = std::move(M); 217 return H; 218 } 219 getSourceModuleLogicalDylib220 Module& getSourceModule(SourceModuleHandle H) { 221 return *SourceModules[H].SourceMod; 222 } 223 getStubsToCloneLogicalDylib224 std::set<Function*>& getStubsToClone(SourceModuleHandle H) { 225 return SourceModules[H].StubsToClone; 226 } 227 findSymbolLogicalDylib228 JITSymbol findSymbol(BaseLayerT &BaseLayer, const std::string &Name, 229 bool ExportedSymbolsOnly) { 230 if (auto Sym = StubsMgr->findStub(Name, ExportedSymbolsOnly)) 231 return Sym; 232 for (auto BLK : BaseLayerVModuleKeys) 233 if (auto Sym = BaseLayer.findSymbolIn(BLK, Name, ExportedSymbolsOnly)) 234 return Sym; 235 else if (auto Err = Sym.takeError()) 236 return std::move(Err); 237 return nullptr; 238 } 239 removeModulesFromBaseLayerLogicalDylib240 Error removeModulesFromBaseLayer(BaseLayerT &BaseLayer) { 241 for (auto &BLK : BaseLayerVModuleKeys) 242 if (auto Err = BaseLayer.removeModule(BLK)) 243 return Err; 244 return Error::success(); 245 } 246 247 VModuleKey K; 248 std::shared_ptr<SymbolResolver> BackingResolver; 249 std::unique_ptr<IndirectStubsMgrT> StubsMgr; 250 SymbolLinkagePromoter PromoteSymbols; 251 SourceModulesList SourceModules; 252 std::vector<VModuleKey> BaseLayerVModuleKeys; 253 }; 254 255 public: 256 257 /// Module partitioning functor. 258 using PartitioningFtor = std::function<std::set<Function*>(Function&)>; 259 260 /// Builder for IndirectStubsManagers. 261 using IndirectStubsManagerBuilderT = 262 std::function<std::unique_ptr<IndirectStubsMgrT>()>; 263 264 using SymbolResolverGetter = 265 std::function<std::shared_ptr<SymbolResolver>(VModuleKey K)>; 266 267 using SymbolResolverSetter = 268 std::function<void(VModuleKey K, std::shared_ptr<SymbolResolver> R)>; 269 270 /// Construct a compile-on-demand layer instance. 271 LLVM_ATTRIBUTE_DEPRECATED( 272 LegacyCompileOnDemandLayer( 273 ExecutionSession &ES, BaseLayerT &BaseLayer, 274 SymbolResolverGetter GetSymbolResolver, 275 SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition, 276 CompileCallbackMgrT &CallbackMgr, 277 IndirectStubsManagerBuilderT CreateIndirectStubsManager, 278 bool CloneStubsIntoPartitions = true), 279 "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " 280 "use " 281 "the ORCv2 LegacyCompileOnDemandLayer instead"); 282 283 /// Legacy layer constructor with deprecation acknowledgement. 284 LegacyCompileOnDemandLayer( 285 ORCv1DeprecationAcknowledgement, ExecutionSession &ES, 286 BaseLayerT &BaseLayer, SymbolResolverGetter GetSymbolResolver, 287 SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition, 288 CompileCallbackMgrT &CallbackMgr, 289 IndirectStubsManagerBuilderT CreateIndirectStubsManager, 290 bool CloneStubsIntoPartitions = true) ES(ES)291 : ES(ES), BaseLayer(BaseLayer), 292 GetSymbolResolver(std::move(GetSymbolResolver)), 293 SetSymbolResolver(std::move(SetSymbolResolver)), 294 Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr), 295 CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)), 296 CloneStubsIntoPartitions(CloneStubsIntoPartitions) {} 297 ~LegacyCompileOnDemandLayer()298 ~LegacyCompileOnDemandLayer() { 299 // FIXME: Report error on log. 300 while (!LogicalDylibs.empty()) 301 consumeError(removeModule(LogicalDylibs.begin()->first)); 302 } 303 304 /// Add a module to the compile-on-demand layer. addModule(VModuleKey K,std::unique_ptr<Module> M)305 Error addModule(VModuleKey K, std::unique_ptr<Module> M) { 306 307 assert(!LogicalDylibs.count(K) && "VModuleKey K already in use"); 308 auto I = LogicalDylibs.insert( 309 LogicalDylibs.end(), 310 std::make_pair(K, LogicalDylib(K, GetSymbolResolver(K), 311 CreateIndirectStubsManager()))); 312 313 return addLogicalModule(I->second, std::move(M)); 314 } 315 316 /// Add extra modules to an existing logical module. addExtraModule(VModuleKey K,std::unique_ptr<Module> M)317 Error addExtraModule(VModuleKey K, std::unique_ptr<Module> M) { 318 return addLogicalModule(LogicalDylibs[K], std::move(M)); 319 } 320 321 /// Remove the module represented by the given key. 322 /// 323 /// This will remove all modules in the layers below that were derived from 324 /// the module represented by K. removeModule(VModuleKey K)325 Error removeModule(VModuleKey K) { 326 auto I = LogicalDylibs.find(K); 327 assert(I != LogicalDylibs.end() && "VModuleKey K not valid here"); 328 auto Err = I->second.removeModulesFromBaseLayer(BaseLayer); 329 LogicalDylibs.erase(I); 330 return Err; 331 } 332 333 /// Search for the given named symbol. 334 /// @param Name The name of the symbol to search for. 335 /// @param ExportedSymbolsOnly If true, search only for exported symbols. 336 /// @return A handle for the given named symbol, if it exists. findSymbol(StringRef Name,bool ExportedSymbolsOnly)337 JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { 338 for (auto &KV : LogicalDylibs) { 339 if (auto Sym = KV.second.StubsMgr->findStub(Name, ExportedSymbolsOnly)) 340 return Sym; 341 if (auto Sym = findSymbolIn(KV.first, Name, ExportedSymbolsOnly)) 342 return Sym; 343 else if (auto Err = Sym.takeError()) 344 return std::move(Err); 345 } 346 return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); 347 } 348 349 /// Get the address of a symbol provided by this layer, or some layer 350 /// below this one. findSymbolIn(VModuleKey K,const std::string & Name,bool ExportedSymbolsOnly)351 JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, 352 bool ExportedSymbolsOnly) { 353 assert(LogicalDylibs.count(K) && "VModuleKey K is not valid here"); 354 return LogicalDylibs[K].findSymbol(BaseLayer, Name, ExportedSymbolsOnly); 355 } 356 357 /// Update the stub for the given function to point at FnBodyAddr. 358 /// This can be used to support re-optimization. 359 /// @return true if the function exists and the stub is updated, false 360 /// otherwise. 361 // 362 // FIXME: We should track and free associated resources (unused compile 363 // callbacks, uncompiled IR, and no-longer-needed/reachable function 364 // implementations). updatePointer(std::string FuncName,JITTargetAddress FnBodyAddr)365 Error updatePointer(std::string FuncName, JITTargetAddress FnBodyAddr) { 366 //Find out which logical dylib contains our symbol 367 auto LDI = LogicalDylibs.begin(); 368 for (auto LDE = LogicalDylibs.end(); LDI != LDE; ++LDI) { 369 if (auto LMResources = 370 LDI->getLogicalModuleResourcesForSymbol(FuncName, false)) { 371 Module &SrcM = LMResources->SourceModule->getResource(); 372 std::string CalledFnName = mangle(FuncName, SrcM.getDataLayout()); 373 if (auto Err = LMResources->StubsMgr->updatePointer(CalledFnName, 374 FnBodyAddr)) 375 return Err; 376 return Error::success(); 377 } 378 } 379 return make_error<JITSymbolNotFound>(FuncName); 380 } 381 382 private: addLogicalModule(LogicalDylib & LD,std::unique_ptr<Module> SrcMPtr)383 Error addLogicalModule(LogicalDylib &LD, std::unique_ptr<Module> SrcMPtr) { 384 385 // Rename anonymous globals and promote linkage to ensure that everything 386 // will resolve properly after we partition SrcM. 387 LD.PromoteSymbols(*SrcMPtr); 388 389 // Create a logical module handle for SrcM within the logical dylib. 390 Module &SrcM = *SrcMPtr; 391 auto LMId = LD.addSourceModule(std::move(SrcMPtr)); 392 393 // Create stub functions. 394 const DataLayout &DL = SrcM.getDataLayout(); 395 { 396 typename IndirectStubsMgrT::StubInitsMap StubInits; 397 for (auto &F : SrcM) { 398 // Skip declarations. 399 if (F.isDeclaration()) 400 continue; 401 402 // Skip weak functions for which we already have definitions. 403 auto MangledName = mangle(F.getName(), DL); 404 if (F.hasWeakLinkage() || F.hasLinkOnceLinkage()) { 405 if (auto Sym = LD.findSymbol(BaseLayer, MangledName, false)) 406 continue; 407 else if (auto Err = Sym.takeError()) 408 return std::move(Err); 409 } 410 411 // Record all functions defined by this module. 412 if (CloneStubsIntoPartitions) 413 LD.getStubsToClone(LMId).insert(&F); 414 415 // Create a callback, associate it with the stub for the function, 416 // and set the compile action to compile the partition containing the 417 // function. 418 auto CompileAction = [this, &LD, LMId, &F]() -> JITTargetAddress { 419 if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F)) 420 return *FnImplAddrOrErr; 421 else { 422 // FIXME: Report error, return to 'abort' or something similar. 423 consumeError(FnImplAddrOrErr.takeError()); 424 return 0; 425 } 426 }; 427 if (auto CCAddr = 428 CompileCallbackMgr.getCompileCallback(std::move(CompileAction))) 429 StubInits[MangledName] = 430 std::make_pair(*CCAddr, JITSymbolFlags::fromGlobalValue(F)); 431 else 432 return CCAddr.takeError(); 433 } 434 435 if (auto Err = LD.StubsMgr->createStubs(StubInits)) 436 return Err; 437 } 438 439 // If this module doesn't contain any globals, aliases, or module flags then 440 // we can bail out early and avoid the overhead of creating and managing an 441 // empty globals module. 442 if (SrcM.global_empty() && SrcM.alias_empty() && 443 !SrcM.getModuleFlagsMetadata()) 444 return Error::success(); 445 446 // Create the GlobalValues module. 447 auto GVsM = std::make_unique<Module>((SrcM.getName() + ".globals").str(), 448 SrcM.getContext()); 449 GVsM->setDataLayout(DL); 450 451 ValueToValueMapTy VMap; 452 453 // Clone global variable decls. 454 for (auto &GV : SrcM.globals()) 455 if (!GV.isDeclaration() && !VMap.count(&GV)) 456 cloneGlobalVariableDecl(*GVsM, GV, &VMap); 457 458 // And the aliases. 459 for (auto &A : SrcM.aliases()) 460 if (!VMap.count(&A)) 461 cloneGlobalAliasDecl(*GVsM, A, VMap); 462 463 // Clone the module flags. 464 cloneModuleFlagsMetadata(*GVsM, SrcM, VMap); 465 466 // Now we need to clone the GV and alias initializers. 467 468 // Initializers may refer to functions declared (but not defined) in this 469 // module. Build a materializer to clone decls on demand. 470 auto Materializer = createLambdaMaterializer( 471 [&LD, &GVsM](Value *V) -> Value* { 472 if (auto *F = dyn_cast<Function>(V)) { 473 // Decls in the original module just get cloned. 474 if (F->isDeclaration()) 475 return cloneFunctionDecl(*GVsM, *F); 476 477 // Definitions in the original module (which we have emitted stubs 478 // for at this point) get turned into a constant alias to the stub 479 // instead. 480 const DataLayout &DL = GVsM->getDataLayout(); 481 std::string FName = mangle(F->getName(), DL); 482 unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType()); 483 JITTargetAddress StubAddr = 484 LD.StubsMgr->findStub(FName, false).getAddress(); 485 486 ConstantInt *StubAddrCI = 487 ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr)); 488 Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr, 489 StubAddrCI, F->getType()); 490 return GlobalAlias::create(F->getFunctionType(), 491 F->getType()->getAddressSpace(), 492 F->getLinkage(), F->getName(), 493 Init, GVsM.get()); 494 } 495 // else.... 496 return nullptr; 497 }); 498 499 // Clone the global variable initializers. 500 for (auto &GV : SrcM.globals()) 501 if (!GV.isDeclaration()) 502 moveGlobalVariableInitializer(GV, VMap, &Materializer); 503 504 // Clone the global alias initializers. 505 for (auto &A : SrcM.aliases()) { 506 auto *NewA = cast<GlobalAlias>(VMap[&A]); 507 assert(NewA && "Alias not cloned?"); 508 Value *Init = MapValue(A.getAliasee(), VMap, RF_None, nullptr, 509 &Materializer); 510 NewA->setAliasee(cast<Constant>(Init)); 511 } 512 513 // Build a resolver for the globals module and add it to the base layer. 514 auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol { 515 if (auto Sym = LD.StubsMgr->findStub(Name, false)) 516 return Sym; 517 518 if (auto Sym = LD.findSymbol(BaseLayer, Name, false)) 519 return Sym; 520 else if (auto Err = Sym.takeError()) 521 return std::move(Err); 522 523 return nullptr; 524 }; 525 526 auto GVsResolver = createSymbolResolver( 527 [&LD, LegacyLookup](const SymbolNameSet &Symbols) { 528 auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup); 529 530 if (!RS) { 531 logAllUnhandledErrors( 532 RS.takeError(), errs(), 533 "CODLayer/GVsResolver responsibility set lookup failed: "); 534 return SymbolNameSet(); 535 } 536 537 if (RS->size() == Symbols.size()) 538 return *RS; 539 540 SymbolNameSet NotFoundViaLegacyLookup; 541 for (auto &S : Symbols) 542 if (!RS->count(S)) 543 NotFoundViaLegacyLookup.insert(S); 544 auto RS2 = 545 LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup); 546 547 for (auto &S : RS2) 548 (*RS).insert(S); 549 550 return *RS; 551 }, 552 [this, &LD, 553 LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Query, 554 SymbolNameSet Symbols) { 555 auto NotFoundViaLegacyLookup = 556 lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup); 557 return LD.BackingResolver->lookup(Query, NotFoundViaLegacyLookup); 558 }); 559 560 SetSymbolResolver(LD.K, std::move(GVsResolver)); 561 562 if (auto Err = BaseLayer.addModule(LD.K, std::move(GVsM))) 563 return Err; 564 565 LD.BaseLayerVModuleKeys.push_back(LD.K); 566 567 return Error::success(); 568 } 569 mangle(StringRef Name,const DataLayout & DL)570 static std::string mangle(StringRef Name, const DataLayout &DL) { 571 std::string MangledName; 572 { 573 raw_string_ostream MangledNameStream(MangledName); 574 Mangler::getNameWithPrefix(MangledNameStream, Name, DL); 575 } 576 return MangledName; 577 } 578 579 Expected<JITTargetAddress> extractAndCompile(LogicalDylib & LD,typename LogicalDylib::SourceModuleHandle LMId,Function & F)580 extractAndCompile(LogicalDylib &LD, 581 typename LogicalDylib::SourceModuleHandle LMId, 582 Function &F) { 583 Module &SrcM = LD.getSourceModule(LMId); 584 585 // If F is a declaration we must already have compiled it. 586 if (F.isDeclaration()) 587 return 0; 588 589 // Grab the name of the function being called here. 590 std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout()); 591 592 JITTargetAddress CalledAddr = 0; 593 auto Part = Partition(F); 594 if (auto PartKeyOrErr = emitPartition(LD, LMId, Part)) { 595 auto &PartKey = *PartKeyOrErr; 596 for (auto *SubF : Part) { 597 std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout()); 598 if (auto FnBodySym = BaseLayer.findSymbolIn(PartKey, FnName, false)) { 599 if (auto FnBodyAddrOrErr = FnBodySym.getAddress()) { 600 JITTargetAddress FnBodyAddr = *FnBodyAddrOrErr; 601 602 // If this is the function we're calling record the address so we can 603 // return it from this function. 604 if (SubF == &F) 605 CalledAddr = FnBodyAddr; 606 607 // Update the function body pointer for the stub. 608 if (auto EC = LD.StubsMgr->updatePointer(FnName, FnBodyAddr)) 609 return 0; 610 611 } else 612 return FnBodyAddrOrErr.takeError(); 613 } else if (auto Err = FnBodySym.takeError()) 614 return std::move(Err); 615 else 616 llvm_unreachable("Function not emitted for partition"); 617 } 618 619 LD.BaseLayerVModuleKeys.push_back(PartKey); 620 } else 621 return PartKeyOrErr.takeError(); 622 623 return CalledAddr; 624 } 625 626 template <typename PartitionT> 627 Expected<VModuleKey> emitPartition(LogicalDylib & LD,typename LogicalDylib::SourceModuleHandle LMId,const PartitionT & Part)628 emitPartition(LogicalDylib &LD, 629 typename LogicalDylib::SourceModuleHandle LMId, 630 const PartitionT &Part) { 631 Module &SrcM = LD.getSourceModule(LMId); 632 633 // Create the module. 634 std::string NewName = SrcM.getName(); 635 for (auto *F : Part) { 636 NewName += "."; 637 NewName += F->getName(); 638 } 639 640 auto M = std::make_unique<Module>(NewName, SrcM.getContext()); 641 M->setDataLayout(SrcM.getDataLayout()); 642 ValueToValueMapTy VMap; 643 644 auto Materializer = createLambdaMaterializer([&LD, &LMId, 645 &M](Value *V) -> Value * { 646 if (auto *GV = dyn_cast<GlobalVariable>(V)) 647 return cloneGlobalVariableDecl(*M, *GV); 648 649 if (auto *F = dyn_cast<Function>(V)) { 650 // Check whether we want to clone an available_externally definition. 651 if (!LD.getStubsToClone(LMId).count(F)) 652 return cloneFunctionDecl(*M, *F); 653 654 // Ok - we want an inlinable stub. For that to work we need a decl 655 // for the stub pointer. 656 auto *StubPtr = createImplPointer(*F->getType(), *M, 657 F->getName() + "$stub_ptr", nullptr); 658 auto *ClonedF = cloneFunctionDecl(*M, *F); 659 makeStub(*ClonedF, *StubPtr); 660 ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage); 661 ClonedF->addFnAttr(Attribute::AlwaysInline); 662 return ClonedF; 663 } 664 665 if (auto *A = dyn_cast<GlobalAlias>(V)) { 666 auto *Ty = A->getValueType(); 667 if (Ty->isFunctionTy()) 668 return Function::Create(cast<FunctionType>(Ty), 669 GlobalValue::ExternalLinkage, A->getName(), 670 M.get()); 671 672 return new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage, 673 nullptr, A->getName(), nullptr, 674 GlobalValue::NotThreadLocal, 675 A->getType()->getAddressSpace()); 676 } 677 678 return nullptr; 679 }); 680 681 // Create decls in the new module. 682 for (auto *F : Part) 683 cloneFunctionDecl(*M, *F, &VMap); 684 685 // Move the function bodies. 686 for (auto *F : Part) 687 moveFunctionBody(*F, VMap, &Materializer); 688 689 auto K = ES.allocateVModule(); 690 691 auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol { 692 return LD.findSymbol(BaseLayer, Name, false); 693 }; 694 695 // Create memory manager and symbol resolver. 696 auto Resolver = createSymbolResolver( 697 [&LD, LegacyLookup](const SymbolNameSet &Symbols) { 698 auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup); 699 if (!RS) { 700 logAllUnhandledErrors( 701 RS.takeError(), errs(), 702 "CODLayer/SubResolver responsibility set lookup failed: "); 703 return SymbolNameSet(); 704 } 705 706 if (RS->size() == Symbols.size()) 707 return *RS; 708 709 SymbolNameSet NotFoundViaLegacyLookup; 710 for (auto &S : Symbols) 711 if (!RS->count(S)) 712 NotFoundViaLegacyLookup.insert(S); 713 714 auto RS2 = 715 LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup); 716 717 for (auto &S : RS2) 718 (*RS).insert(S); 719 720 return *RS; 721 }, 722 [this, &LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Q, 723 SymbolNameSet Symbols) { 724 auto NotFoundViaLegacyLookup = 725 lookupWithLegacyFn(ES, *Q, Symbols, LegacyLookup); 726 return LD.BackingResolver->lookup(Q, 727 std::move(NotFoundViaLegacyLookup)); 728 }); 729 SetSymbolResolver(K, std::move(Resolver)); 730 731 if (auto Err = BaseLayer.addModule(std::move(K), std::move(M))) 732 return std::move(Err); 733 734 return K; 735 } 736 737 ExecutionSession &ES; 738 BaseLayerT &BaseLayer; 739 SymbolResolverGetter GetSymbolResolver; 740 SymbolResolverSetter SetSymbolResolver; 741 PartitioningFtor Partition; 742 CompileCallbackMgrT &CompileCallbackMgr; 743 IndirectStubsManagerBuilderT CreateIndirectStubsManager; 744 745 std::map<VModuleKey, LogicalDylib> LogicalDylibs; 746 bool CloneStubsIntoPartitions; 747 }; 748 749 template <typename BaseLayerT, typename CompileCallbackMgrT, 750 typename IndirectStubsMgrT> 751 LegacyCompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT, IndirectStubsMgrT>:: LegacyCompileOnDemandLayer(ExecutionSession & ES,BaseLayerT & BaseLayer,SymbolResolverGetter GetSymbolResolver,SymbolResolverSetter SetSymbolResolver,PartitioningFtor Partition,CompileCallbackMgrT & CallbackMgr,IndirectStubsManagerBuilderT CreateIndirectStubsManager,bool CloneStubsIntoPartitions)752 LegacyCompileOnDemandLayer( 753 ExecutionSession &ES, BaseLayerT &BaseLayer, 754 SymbolResolverGetter GetSymbolResolver, 755 SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition, 756 CompileCallbackMgrT &CallbackMgr, 757 IndirectStubsManagerBuilderT CreateIndirectStubsManager, 758 bool CloneStubsIntoPartitions) 759 : ES(ES), BaseLayer(BaseLayer), 760 GetSymbolResolver(std::move(GetSymbolResolver)), 761 SetSymbolResolver(std::move(SetSymbolResolver)), 762 Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr), 763 CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)), 764 CloneStubsIntoPartitions(CloneStubsIntoPartitions) {} 765 766 } // end namespace orc 767 } // end namespace llvm 768 769 #endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H 770