LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine/Orc - CompileOnDemandLayer.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 204 230 88.7 %
Date: 2017-09-14 15:23:50 Functions: 45 51 88.2 %
Legend: Lines: hit not hit

          Line data    Source code
       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/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/OrcError.h"
      26             : #include "llvm/ExecutionEngine/RuntimeDyld.h"
      27             : #include "llvm/IR/Attributes.h"
      28             : #include "llvm/IR/Constant.h"
      29             : #include "llvm/IR/Constants.h"
      30             : #include "llvm/IR/DataLayout.h"
      31             : #include "llvm/IR/Function.h"
      32             : #include "llvm/IR/GlobalAlias.h"
      33             : #include "llvm/IR/GlobalValue.h"
      34             : #include "llvm/IR/GlobalVariable.h"
      35             : #include "llvm/IR/Instruction.h"
      36             : #include "llvm/IR/Mangler.h"
      37             : #include "llvm/IR/Module.h"
      38             : #include "llvm/IR/Type.h"
      39             : #include "llvm/Support/Casting.h"
      40             : #include "llvm/Support/raw_ostream.h"
      41             : #include "llvm/Transforms/Utils/ValueMapper.h"
      42             : #include <algorithm>
      43             : #include <cassert>
      44             : #include <functional>
      45             : #include <iterator>
      46             : #include <list>
      47             : #include <memory>
      48             : #include <set>
      49             : #include <string>
      50             : #include <utility>
      51             : #include <vector>
      52             : 
      53             : namespace llvm {
      54             : 
      55             : class Value;
      56             : 
      57             : namespace orc {
      58             : 
      59             : /// @brief Compile-on-demand layer.
      60             : ///
      61             : ///   When a module is added to this layer a stub is created for each of its
      62             : /// function definitions. The stubs and other global values are immediately
      63             : /// added to the layer below. When a stub is called it triggers the extraction
      64             : /// of the function body from the original module. The extracted body is then
      65             : /// compiled and executed.
      66             : template <typename BaseLayerT,
      67             :           typename CompileCallbackMgrT = JITCompileCallbackManager,
      68             :           typename IndirectStubsMgrT = IndirectStubsManager>
      69             : class CompileOnDemandLayer {
      70             : private:
      71             :   template <typename MaterializerFtor>
      72             :   class LambdaMaterializer final : public ValueMaterializer {
      73             :   public:
      74          20 :     LambdaMaterializer(MaterializerFtor M) : M(std::move(M)) {}
      75             : 
      76          51 :     Value *materialize(Value *V) final { return M(V); }
      77             : 
      78             :   private:
      79             :     MaterializerFtor M;
      80             :   };
      81             : 
      82             :   template <typename MaterializerFtor>
      83             :   LambdaMaterializer<MaterializerFtor>
      84             :   createLambdaMaterializer(MaterializerFtor M) {
      85          40 :     return LambdaMaterializer<MaterializerFtor>(std::move(M));
      86             :   }
      87             : 
      88             :   using BaseLayerModuleHandleT = typename BaseLayerT::ModuleHandleT;
      89             : 
      90             :   // Provide type-erasure for the Modules and MemoryManagers.
      91             :   template <typename ResourceT>
      92             :   class ResourceOwner {
      93             :   public:
      94             :     ResourceOwner() = default;
      95             :     ResourceOwner(const ResourceOwner &) = delete;
      96             :     ResourceOwner &operator=(const ResourceOwner &) = delete;
      97             :     virtual ~ResourceOwner() = default;
      98             : 
      99             :     virtual ResourceT& getResource() const = 0;
     100             :   };
     101             : 
     102             :   template <typename ResourceT, typename ResourcePtrT>
     103             :   class ResourceOwnerImpl : public ResourceOwner<ResourceT> {
     104             :   public:
     105             :     ResourceOwnerImpl(ResourcePtrT ResourcePtr)
     106             :       : ResourcePtr(std::move(ResourcePtr)) {}
     107             : 
     108             :     ResourceT& getResource() const override { return *ResourcePtr; }
     109             : 
     110             :   private:
     111             :     ResourcePtrT ResourcePtr;
     112             :   };
     113             : 
     114             :   template <typename ResourceT, typename ResourcePtrT>
     115             :   std::unique_ptr<ResourceOwner<ResourceT>>
     116             :   wrapOwnership(ResourcePtrT ResourcePtr) {
     117             :     using RO = ResourceOwnerImpl<ResourceT, ResourcePtrT>;
     118             :     return llvm::make_unique<RO>(std::move(ResourcePtr));
     119             :   }
     120             : 
     121             :   class StaticGlobalRenamer {
     122             :   public:
     123             :     StaticGlobalRenamer() = default;
     124             :     StaticGlobalRenamer(StaticGlobalRenamer &&) = default;
     125             :     StaticGlobalRenamer &operator=(StaticGlobalRenamer &&) = default;
     126             : 
     127           9 :     void rename(Module &M) {
     128          50 :       for (auto &F : M)
     129          23 :         if (F.hasLocalLinkage())
     130          12 :           F.setName("$static." + Twine(NextId++));
     131          17 :       for (auto &G : M.globals())
     132           8 :         if (G.hasLocalLinkage())
     133          12 :           G.setName("$static." + Twine(NextId++));
     134           9 :     }
     135             : 
     136             :   private:
     137             :     unsigned NextId = 0;
     138             :   };
     139             : 
     140         144 :   struct LogicalDylib {
     141             :     using SymbolResolverFtor = std::function<JITSymbol(const std::string&)>;
     142             : 
     143         104 :     struct SourceModuleEntry {
     144             :       std::shared_ptr<Module> SourceMod;
     145             :       std::set<Function*> StubsToClone;
     146             :     };
     147             : 
     148             :     using SourceModulesList = std::vector<SourceModuleEntry>;
     149             :     using SourceModuleHandle = typename SourceModulesList::size_type;
     150             : 
     151             :     SourceModuleHandle
     152           9 :     addSourceModule(std::shared_ptr<Module> M) {
     153          18 :       SourceModuleHandle H = SourceModules.size();
     154          27 :       SourceModules.push_back(SourceModuleEntry());
     155          27 :       SourceModules.back().SourceMod = std::move(M);
     156           9 :       return H;
     157             :     }
     158             : 
     159             :     Module& getSourceModule(SourceModuleHandle H) {
     160          96 :       return *SourceModules[H].SourceMod;
     161             :     }
     162             : 
     163             :     std::set<Function*>& getStubsToClone(SourceModuleHandle H) {
     164          58 :       return SourceModules[H].StubsToClone;
     165             :     }
     166             : 
     167          34 :     JITSymbol findSymbol(BaseLayerT &BaseLayer, const std::string &Name,
     168             :                          bool ExportedSymbolsOnly) {
     169         125 :       if (auto Sym = StubsMgr->findStub(Name, ExportedSymbolsOnly))
     170          11 :         return Sym;
     171         108 :       for (auto BLH : BaseLayerHandles)
     172          62 :         if (auto Sym = BaseLayer.findSymbolIn(BLH, Name, ExportedSymbolsOnly))
     173          14 :           return Sym;
     174          48 :         else if (auto Err = Sym.takeError())
     175           0 :           return std::move(Err);
     176             :       return nullptr;
     177             :     }
     178             : 
     179             :     Error removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
     180          52 :       for (auto &BLH : BaseLayerHandles)
     181          80 :         if (auto Err = BaseLayer.removeModule(BLH))
     182             :           return Err;
     183          24 :       return Error::success();
     184             :     }
     185             : 
     186             :     std::shared_ptr<JITSymbolResolver> ExternalSymbolResolver;
     187             :     std::unique_ptr<IndirectStubsMgrT> StubsMgr;
     188             :     StaticGlobalRenamer StaticRenamer;
     189             :     SourceModulesList SourceModules;
     190             :     std::vector<BaseLayerModuleHandleT> BaseLayerHandles;
     191             :   };
     192             : 
     193             :   using LogicalDylibList = std::list<LogicalDylib>;
     194             : 
     195             : public:
     196             : 
     197             :   /// @brief Handle to loaded module.
     198             :   using ModuleHandleT = typename LogicalDylibList::iterator;
     199             : 
     200             :   /// @brief Module partitioning functor.
     201             :   using PartitioningFtor = std::function<std::set<Function*>(Function&)>;
     202             : 
     203             :   /// @brief Builder for IndirectStubsManagers.
     204             :   using IndirectStubsManagerBuilderT =
     205             :       std::function<std::unique_ptr<IndirectStubsMgrT>()>;
     206             : 
     207             :   /// @brief Construct a compile-on-demand layer instance.
     208          11 :   CompileOnDemandLayer(BaseLayerT &BaseLayer, PartitioningFtor Partition,
     209             :                        CompileCallbackMgrT &CallbackMgr,
     210             :                        IndirectStubsManagerBuilderT CreateIndirectStubsManager,
     211             :                        bool CloneStubsIntoPartitions = true)
     212          11 :       : BaseLayer(BaseLayer), Partition(std::move(Partition)),
     213             :         CompileCallbackMgr(CallbackMgr),
     214          11 :         CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)),
     215          44 :         CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
     216             : 
     217          11 :   ~CompileOnDemandLayer() {
     218             :     // FIXME: Report error on log.
     219          43 :     while (!LogicalDylibs.empty())
     220          21 :       consumeError(removeModule(LogicalDylibs.begin()));
     221          44 :   }
     222             : 
     223             :   /// @brief Add a module to the compile-on-demand layer.
     224             :   Expected<ModuleHandleT>
     225           8 :   addModule(std::shared_ptr<Module> M,
     226             :             std::shared_ptr<JITSymbolResolver> Resolver) {
     227             : 
     228          24 :     LogicalDylibs.push_back(LogicalDylib());
     229          16 :     auto &LD = LogicalDylibs.back();
     230          16 :     LD.ExternalSymbolResolver = std::move(Resolver);
     231          32 :     LD.StubsMgr = CreateIndirectStubsManager();
     232             : 
     233             :     // Process each of the modules in this module set.
     234          40 :     if (auto Err = addLogicalModule(LD, std::move(M)))
     235           0 :       return std::move(Err);
     236             : 
     237          32 :     return std::prev(LogicalDylibs.end());
     238             :   }
     239             : 
     240             :   /// @brief Add extra modules to an existing logical module.
     241           1 :   Error addExtraModule(ModuleHandleT H, std::shared_ptr<Module> M) {
     242           4 :     return addLogicalModule(*H, std::move(M));
     243             :   }
     244             : 
     245             :   /// @brief Remove the module represented by the given handle.
     246             :   ///
     247             :   ///   This will remove all modules in the layers below that were derived from
     248             :   /// the module represented by H.
     249           8 :   Error removeModule(ModuleHandleT H) {
     250          16 :     auto Err = H->removeModulesFromBaseLayer(BaseLayer);
     251          16 :     LogicalDylibs.erase(H);
     252           8 :     return Err;
     253             :   }
     254             : 
     255             :   /// @brief Search for the given named symbol.
     256             :   /// @param Name The name of the symbol to search for.
     257             :   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
     258             :   /// @return A handle for the given named symbol, if it exists.
     259          20 :   JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
     260          60 :     for (auto LDI = LogicalDylibs.begin(), LDE = LogicalDylibs.end();
     261          27 :          LDI != LDE; ++LDI) {
     262          37 :       if (auto Sym = LDI->StubsMgr->findStub(Name, ExportedSymbolsOnly))
     263           8 :         return Sym;
     264          35 :       if (auto Sym = findSymbolIn(LDI, Name, ExportedSymbolsOnly))
     265           0 :         return Sym;
     266          21 :       else if (auto Err = Sym.takeError())
     267           0 :         return std::move(Err);
     268             :     }
     269          48 :     return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
     270             :   }
     271             : 
     272             :   /// @brief Get the address of a symbol provided by this layer, or some layer
     273             :   ///        below this one.
     274             :   JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
     275             :                          bool ExportedSymbolsOnly) {
     276           8 :     return H->findSymbol(BaseLayer, Name, ExportedSymbolsOnly);
     277             :   }
     278             : 
     279             :   /// @brief Update the stub for the given function to point at FnBodyAddr.
     280             :   /// This can be used to support re-optimization.
     281             :   /// @return true if the function exists and the stub is updated, false
     282             :   ///         otherwise.
     283             :   //
     284             :   // FIXME: We should track and free associated resources (unused compile
     285             :   //        callbacks, uncompiled IR, and no-longer-needed/reachable function
     286             :   //        implementations).
     287             :   Error updatePointer(std::string FuncName, JITTargetAddress FnBodyAddr) {
     288             :     //Find out which logical dylib contains our symbol
     289             :     auto LDI = LogicalDylibs.begin();
     290             :     for (auto LDE = LogicalDylibs.end(); LDI != LDE; ++LDI) {
     291             :       if (auto LMResources =
     292             :             LDI->getLogicalModuleResourcesForSymbol(FuncName, false)) {
     293             :         Module &SrcM = LMResources->SourceModule->getResource();
     294             :         std::string CalledFnName = mangle(FuncName, SrcM.getDataLayout());
     295             :         if (auto Err = LMResources->StubsMgr->updatePointer(CalledFnName,
     296             :                                                             FnBodyAddr))
     297             :           return Err;
     298             :         return Error::success();
     299             :       }
     300             :     }
     301             :     return make_error<JITSymbolNotFound>(FuncName);
     302             :   }
     303             : 
     304             : private:
     305             : 
     306           9 :   Error addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcMPtr) {
     307             : 
     308             :     // Rename all static functions / globals to $static.X :
     309             :     // This will unique the names across all modules in the logical dylib,
     310             :     // simplifying symbol lookup.
     311          18 :     LD.StaticRenamer.rename(*SrcMPtr);
     312             : 
     313             :     // Bump the linkage and rename any anonymous/privote members in SrcM to
     314             :     // ensure that everything will resolve properly after we partition SrcM.
     315           9 :     makeAllSymbolsExternallyAccessible(*SrcMPtr);
     316             : 
     317             :     // Create a logical module handle for SrcM within the logical dylib.
     318           9 :     Module &SrcM = *SrcMPtr;
     319          27 :     auto LMId = LD.addSourceModule(std::move(SrcMPtr));
     320             : 
     321             :     // Create stub functions.
     322           9 :     const DataLayout &DL = SrcM.getDataLayout();
     323             :     {
     324          18 :       typename IndirectStubsMgrT::StubInitsMap StubInits;
     325          50 :       for (auto &F : SrcM) {
     326             :         // Skip declarations.
     327          23 :         if (F.isDeclaration())
     328          11 :           continue;
     329             : 
     330             :         // Skip weak functions for which we already have definitions.
     331          35 :         auto MangledName = mangle(F.getName(), DL);
     332          54 :         if (F.hasWeakLinkage() || F.hasLinkOnceLinkage()) {
     333           6 :           if (auto Sym = LD.findSymbol(BaseLayer, MangledName, false))
     334           1 :             continue;
     335           6 :           else if (auto Err = Sym.takeError())
     336           0 :             return std::move(Err);
     337             :         }
     338             : 
     339             :         // Record all functions defined by this module.
     340          17 :         if (CloneStubsIntoPartitions)
     341          32 :           LD.getStubsToClone(LMId).insert(&F);
     342             : 
     343             :         // Create a callback, associate it with the stub for the function,
     344             :         // and set the compile action to compile the partition containing the
     345             :         // function.
     346          51 :         if (auto CCInfoOrErr = CompileCallbackMgr.getCompileCallback()) {
     347          17 :           auto &CCInfo = *CCInfoOrErr;
     348          51 :           StubInits[MangledName] =
     349          34 :             std::make_pair(CCInfo.getAddress(),
     350          34 :                            JITSymbolFlags::fromGlobalValue(F));
     351          84 :           CCInfo.setCompileAction([this, &LD, LMId, &F]() -> JITTargetAddress {
     352          48 :               if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
     353          16 :                 return *FnImplAddrOrErr;
     354             :               else {
     355             :                 // FIXME: Report error, return to 'abort' or something similar.
     356           0 :                 consumeError(FnImplAddrOrErr.takeError());
     357           0 :                 return 0;
     358             :               }
     359             :             });
     360             :         } else
     361           0 :           return CCInfoOrErr.takeError();
     362             :       }
     363             : 
     364          36 :       if (auto Err = LD.StubsMgr->createStubs(StubInits))
     365           0 :         return Err;
     366             :     }
     367             : 
     368             :     // If this module doesn't contain any globals, aliases, or module flags then
     369             :     // we can bail out early and avoid the overhead of creating and managing an
     370             :     // empty globals module.
     371          21 :     if (SrcM.global_empty() && SrcM.alias_empty() &&
     372           6 :         !SrcM.getModuleFlagsMetadata())
     373          15 :       return Error::success();
     374             : 
     375             :     // Create the GlobalValues module.
     376          20 :     auto GVsM = llvm::make_unique<Module>((SrcM.getName() + ".globals").str(),
     377             :                                           SrcM.getContext());
     378           4 :     GVsM->setDataLayout(DL);
     379             : 
     380           8 :     ValueToValueMapTy VMap;
     381             : 
     382             :     // Clone global variable decls.
     383          12 :     for (auto &GV : SrcM.globals())
     384          16 :       if (!GV.isDeclaration() && !VMap.count(&GV))
     385           7 :         cloneGlobalVariableDecl(*GVsM, GV, &VMap);
     386             : 
     387             :     // And the aliases.
     388           6 :     for (auto &A : SrcM.aliases())
     389           4 :       if (!VMap.count(&A))
     390           2 :         cloneGlobalAliasDecl(*GVsM, A, VMap);
     391             : 
     392             :     // Clone the module flags.
     393           4 :     cloneModuleFlagsMetadata(*GVsM, SrcM, VMap);
     394             : 
     395             :     // Now we need to clone the GV and alias initializers.
     396             : 
     397             :     // Initializers may refer to functions declared (but not defined) in this
     398             :     // module. Build a materializer to clone decls on demand.
     399          12 :     Error MaterializerErrors = Error::success();
     400           8 :     auto Materializer = createLambdaMaterializer(
     401          20 :       [&LD, &GVsM, &MaterializerErrors](Value *V) -> Value* {
     402           2 :         if (auto *F = dyn_cast<Function>(V)) {
     403             :           // Decls in the original module just get cloned.
     404           2 :           if (F->isDeclaration())
     405           0 :             return cloneFunctionDecl(*GVsM, *F);
     406             : 
     407             :           // Definitions in the original module (which we have emitted stubs
     408             :           // for at this point) get turned into a constant alias to the stub
     409             :           // instead.
     410           2 :           const DataLayout &DL = GVsM->getDataLayout();
     411           2 :           std::string FName = mangle(F->getName(), DL);
     412           4 :           unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
     413           2 :           JITTargetAddress StubAddr = 0;
     414             : 
     415             :           // Get the address for the stub. If we encounter an error while
     416             :           // doing so, stash it in the MaterializerErrors variable and use a
     417             :           // null address as a placeholder.
     418           8 :           if (auto StubSym = LD.StubsMgr->findStub(FName, false)) {
     419           6 :             if (auto StubAddrOrErr = StubSym.getAddress())
     420           2 :               StubAddr = *StubAddrOrErr;
     421             :             else
     422           0 :               MaterializerErrors = joinErrors(std::move(MaterializerErrors),
     423             :                                               StubAddrOrErr.takeError());
     424             :           }
     425             : 
     426           2 :           ConstantInt *StubAddrCI =
     427           6 :             ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr));
     428           2 :           Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr,
     429           4 :                                                  StubAddrCI, F->getType());
     430          12 :           return GlobalAlias::create(F->getFunctionType(),
     431             :                                      F->getType()->getAddressSpace(),
     432           4 :                                      F->getLinkage(), F->getName(),
     433           2 :                                      Init, GVsM.get());
     434             :         }
     435             :         // else....
     436             :         return nullptr;
     437             :       });
     438             : 
     439             :     // Clone the global variable initializers.
     440          12 :     for (auto &GV : SrcM.globals())
     441           8 :       if (!GV.isDeclaration())
     442           7 :         moveGlobalVariableInitializer(GV, VMap, &Materializer);
     443             : 
     444             :     // Clone the global alias initializers.
     445           6 :     for (auto &A : SrcM.aliases()) {
     446           4 :       auto *NewA = cast<GlobalAlias>(VMap[&A]);
     447             :       assert(NewA && "Alias not cloned?");
     448           2 :       Value *Init = MapValue(A.getAliasee(), VMap, RF_None, nullptr,
     449             :                              &Materializer);
     450           2 :       NewA->setAliasee(cast<Constant>(Init));
     451             :     }
     452             : 
     453           4 :     if (MaterializerErrors)
     454             :       return MaterializerErrors;
     455             : 
     456             :     // Build a resolver for the globals module and add it to the base layer.
     457           4 :     auto GVsResolver = createLambdaResolver(
     458           3 :         [this, &LD](const std::string &Name) -> JITSymbol {
     459           4 :           if (auto Sym = LD.StubsMgr->findStub(Name, false))
     460           0 :             return Sym;
     461           2 :           if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
     462           0 :             return Sym;
     463           3 :           else if (auto Err = Sym.takeError())
     464           0 :             return std::move(Err);
     465           2 :           return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name);
     466             :         },
     467           0 :         [&LD](const std::string &Name) {
     468           0 :           return LD.ExternalSymbolResolver->findSymbol(Name);
     469           0 :         });
     470             : 
     471          24 :     if (auto GVsHOrErr =
     472           8 :           BaseLayer.addModule(std::move(GVsM), std::move(GVsResolver)))
     473           8 :       LD.BaseLayerHandles.push_back(*GVsHOrErr);
     474             :     else
     475           0 :       return GVsHOrErr.takeError();
     476             : 
     477          12 :     return Error::success();
     478             :   }
     479             : 
     480          52 :   static std::string mangle(StringRef Name, const DataLayout &DL) {
     481          52 :     std::string MangledName;
     482             :     {
     483         104 :       raw_string_ostream MangledNameStream(MangledName);
     484          52 :       Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
     485             :     }
     486          52 :     return MangledName;
     487             :   }
     488             : 
     489             :   Expected<JITTargetAddress>
     490          16 :   extractAndCompile(LogicalDylib &LD,
     491             :                     typename LogicalDylib::SourceModuleHandle LMId,
     492             :                     Function &F) {
     493          16 :     Module &SrcM = LD.getSourceModule(LMId);
     494             : 
     495             :     // If F is a declaration we must already have compiled it.
     496          16 :     if (F.isDeclaration())
     497           0 :       return 0;
     498             : 
     499             :     // Grab the name of the function being called here.
     500          16 :     std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout());
     501             : 
     502          16 :     JITTargetAddress CalledAddr = 0;
     503          48 :     auto Part = Partition(F);
     504          48 :     if (auto PartHOrErr = emitPartition(LD, LMId, Part)) {
     505          16 :       auto &PartH = *PartHOrErr;
     506          64 :       for (auto *SubF : Part) {
     507          32 :         std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
     508          48 :         if (auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false)) {
     509          48 :           if (auto FnBodyAddrOrErr = FnBodySym.getAddress()) {
     510          16 :             JITTargetAddress FnBodyAddr = *FnBodyAddrOrErr;
     511             : 
     512             :             // If this is the function we're calling record the address so we can
     513             :             // return it from this function.
     514          16 :             if (SubF == &F)
     515          16 :               CalledAddr = FnBodyAddr;
     516             : 
     517             :             // Update the function body pointer for the stub.
     518          80 :             if (auto EC = LD.StubsMgr->updatePointer(FnName, FnBodyAddr))
     519           0 :               return 0;
     520             : 
     521             :           } else
     522           0 :             return FnBodyAddrOrErr.takeError();
     523           0 :         } else if (auto Err = FnBodySym.takeError())
     524           0 :           return std::move(Err);
     525             :         else
     526           0 :           llvm_unreachable("Function not emitted for partition");
     527             :       }
     528             : 
     529          16 :       LD.BaseLayerHandles.push_back(PartH);
     530             :     } else
     531           0 :       return PartHOrErr.takeError();
     532             : 
     533             :     return CalledAddr;
     534             :   }
     535             : 
     536             :   template <typename PartitionT>
     537             :   Expected<BaseLayerModuleHandleT>
     538          16 :   emitPartition(LogicalDylib &LD,
     539             :                 typename LogicalDylib::SourceModuleHandle LMId,
     540             :                 const PartitionT &Part) {
     541          32 :     Module &SrcM = LD.getSourceModule(LMId);
     542             : 
     543             :     // Create the module.
     544          48 :     std::string NewName = SrcM.getName();
     545          64 :     for (auto *F : Part) {
     546          16 :       NewName += ".";
     547          32 :       NewName += F->getName();
     548             :     }
     549             : 
     550          32 :     auto M = llvm::make_unique<Module>(NewName, SrcM.getContext());
     551          16 :     M->setDataLayout(SrcM.getDataLayout());
     552          32 :     ValueToValueMapTy VMap;
     553             : 
     554          32 :     auto Materializer = createLambdaMaterializer([&LD, &LMId,
     555          79 :                                                   &M](Value *V) -> Value * {
     556           6 :       if (auto *GV = dyn_cast<GlobalVariable>(V))
     557           6 :         return cloneGlobalVariableDecl(*M, *GV);
     558             : 
     559          13 :       if (auto *F = dyn_cast<Function>(V)) {
     560             :         // Check whether we want to clone an available_externally definition.
     561          39 :         if (!LD.getStubsToClone(LMId).count(F))
     562           7 :           return cloneFunctionDecl(*M, *F);
     563             : 
     564             :         // Ok - we want an inlinable stub. For that to work we need a decl
     565             :         // for the stub pointer.
     566          12 :         auto *StubPtr = createImplPointer(*F->getType(), *M,
     567          18 :                                           F->getName() + "$stub_ptr", nullptr);
     568           6 :         auto *ClonedF = cloneFunctionDecl(*M, *F);
     569           6 :         makeStub(*ClonedF, *StubPtr);
     570          12 :         ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage);
     571           6 :         ClonedF->addFnAttr(Attribute::AlwaysInline);
     572           6 :         return ClonedF;
     573             :       }
     574             : 
     575           2 :       if (auto *A = dyn_cast<GlobalAlias>(V)) {
     576           2 :         auto *Ty = A->getValueType();
     577           2 :         if (Ty->isFunctionTy())
     578           4 :           return Function::Create(cast<FunctionType>(Ty),
     579           2 :                                   GlobalValue::ExternalLinkage, A->getName(),
     580           1 :                                   M.get());
     581             : 
     582           1 :         return new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage,
     583           2 :                                   nullptr, A->getName(), nullptr,
     584             :                                   GlobalValue::NotThreadLocal,
     585           5 :                                   A->getType()->getAddressSpace());
     586             :       }
     587             : 
     588             :       return nullptr;
     589             :     });
     590             : 
     591             :     // Create decls in the new module.
     592          64 :     for (auto *F : Part)
     593          16 :       cloneFunctionDecl(*M, *F, &VMap);
     594             : 
     595             :     // Move the function bodies.
     596          64 :     for (auto *F : Part)
     597          16 :       moveFunctionBody(*F, VMap, &Materializer);
     598             : 
     599             :     // Create memory manager and symbol resolver.
     600          32 :     auto Resolver = createLambdaResolver(
     601          28 :         [this, &LD](const std::string &Name) -> JITSymbol {
     602          28 :           if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
     603          32 :             return Sym;
     604          18 :           else if (auto Err = Sym.takeError())
     605           0 :             return std::move(Err);
     606          12 :           return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name);
     607             :         },
     608           3 :         [&LD](const std::string &Name) {
     609           6 :           return LD.ExternalSymbolResolver->findSymbol(Name);
     610           3 :         });
     611             : 
     612          96 :     return BaseLayer.addModule(std::move(M), std::move(Resolver));
     613             :   }
     614             : 
     615             :   BaseLayerT &BaseLayer;
     616             :   PartitioningFtor Partition;
     617             :   CompileCallbackMgrT &CompileCallbackMgr;
     618             :   IndirectStubsManagerBuilderT CreateIndirectStubsManager;
     619             : 
     620             :   LogicalDylibList LogicalDylibs;
     621             :   bool CloneStubsIntoPartitions;
     622             : };
     623             : 
     624             : } // end namespace orc
     625             : 
     626             : } // end namespace llvm
     627             : 
     628             : #endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H

Generated by: LCOV version 1.13