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