LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/Orc - OrcCBindingsStack.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 102 141 72.3 %
Date: 2018-05-20 00:06:23 Functions: 29 39 74.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- OrcCBindingsStack.h - Orc JIT stack for C bindings -----*- 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             : #ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
      11             : #define LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
      12             : 
      13             : #include "llvm-c/OrcBindings.h"
      14             : #include "llvm-c/TargetMachine.h"
      15             : #include "llvm/ADT/STLExtras.h"
      16             : #include "llvm/ADT/StringRef.h"
      17             : #include "llvm/ExecutionEngine/JITSymbol.h"
      18             : #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
      19             : #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
      20             : #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
      21             : #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
      22             : #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
      23             : #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
      24             : #include "llvm/ExecutionEngine/RuntimeDyld.h"
      25             : #include "llvm/ExecutionEngine/SectionMemoryManager.h"
      26             : #include "llvm/IR/DataLayout.h"
      27             : #include "llvm/IR/Mangler.h"
      28             : #include "llvm/IR/Module.h"
      29             : #include "llvm/Support/CBindingWrapping.h"
      30             : #include "llvm/Support/Error.h"
      31             : #include "llvm/Support/raw_ostream.h"
      32             : #include "llvm/Target/TargetMachine.h"
      33             : #include <algorithm>
      34             : #include <cstdint>
      35             : #include <functional>
      36             : #include <map>
      37             : #include <memory>
      38             : #include <set>
      39             : #include <string>
      40             : #include <vector>
      41             : 
      42             : namespace llvm {
      43             : 
      44             : class OrcCBindingsStack;
      45             : 
      46             : DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef)
      47             : DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
      48             : 
      49             : namespace detail {
      50             : 
      51             : // FIXME: Kill this off once the Layer concept becomes an interface.
      52             : class GenericLayer {
      53             : public:
      54             :   virtual ~GenericLayer() = default;
      55             : 
      56             :   virtual JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
      57             :                                  bool ExportedSymbolsOnly) = 0;
      58             :   virtual Error removeModule(orc::VModuleKey K) = 0;
      59             :   };
      60             : 
      61           3 :   template <typename LayerT> class GenericLayerImpl : public GenericLayer {
      62             :   public:
      63           3 :     GenericLayerImpl(LayerT &Layer) : Layer(Layer) {}
      64             : 
      65           0 :     JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
      66             :                            bool ExportedSymbolsOnly) override {
      67           0 :       return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly);
      68             :     }
      69             : 
      70           3 :     Error removeModule(orc::VModuleKey K) override {
      71           5 :       return Layer.removeModule(K);
      72             :     }
      73             : 
      74             :   private:
      75             :     LayerT &Layer;
      76             :   };
      77             : 
      78             :   template <>
      79           1 :   class GenericLayerImpl<orc::RTDyldObjectLinkingLayer> : public GenericLayer {
      80             :   private:
      81             :     using LayerT = orc::RTDyldObjectLinkingLayer;
      82             :   public:
      83           1 :     GenericLayerImpl(LayerT &Layer) : Layer(Layer) {}
      84             : 
      85           0 :     JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
      86             :                            bool ExportedSymbolsOnly) override {
      87           0 :       return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly);
      88             :     }
      89             : 
      90           1 :     Error removeModule(orc::VModuleKey K) override {
      91           2 :       return Layer.removeObject(K);
      92             :     }
      93             : 
      94             :   private:
      95             :     LayerT &Layer;
      96             :   };
      97             : 
      98             :   template <typename LayerT>
      99             :   std::unique_ptr<GenericLayerImpl<LayerT>> createGenericLayer(LayerT &Layer) {
     100             :     return llvm::make_unique<GenericLayerImpl<LayerT>>(Layer);
     101             :   }
     102             : 
     103             : } // end namespace detail
     104             : 
     105          24 : class OrcCBindingsStack {
     106             : public:
     107             : 
     108             :   using CompileCallbackMgr = orc::JITCompileCallbackManager;
     109             :   using ObjLayerT = orc::RTDyldObjectLinkingLayer;
     110             :   using CompileLayerT = orc::IRCompileLayer<ObjLayerT, orc::SimpleCompiler>;
     111             :   using CODLayerT =
     112             :         orc::CompileOnDemandLayer<CompileLayerT, CompileCallbackMgr>;
     113             : 
     114             :   using CallbackManagerBuilder =
     115             :       std::function<std::unique_ptr<CompileCallbackMgr>()>;
     116             : 
     117             :   using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT;
     118             : 
     119             : private:
     120             : 
     121             :   using OwningObject = object::OwningBinary<object::ObjectFile>;
     122             : 
     123           4 :   class CBindingsResolver : public orc::SymbolResolver {
     124             :   public:
     125             :     CBindingsResolver(OrcCBindingsStack &Stack,
     126             :                       LLVMOrcSymbolResolverFn ExternalResolver,
     127             :                       void *ExternalResolverCtx)
     128           4 :         : Stack(Stack), ExternalResolver(std::move(ExternalResolver)),
     129           4 :           ExternalResolverCtx(std::move(ExternalResolverCtx)) {}
     130             : 
     131           4 :     orc::SymbolNameSet lookupFlags(orc::SymbolFlagsMap &SymbolFlags,
     132             :                                    const orc::SymbolNameSet &Symbols) override {
     133             :       orc::SymbolNameSet SymbolsNotFound;
     134             : 
     135           4 :       for (auto &S : Symbols) {
     136           0 :         if (auto Sym = findSymbol(*S))
     137           0 :           SymbolFlags[S] = Sym.getFlags();
     138           0 :         else if (auto Err = Sym.takeError()) {
     139           0 :           Stack.reportError(std::move(Err));
     140           0 :           return orc::SymbolNameSet();
     141             :         } else
     142             :           SymbolsNotFound.insert(S);
     143             :       }
     144             : 
     145             :       return SymbolsNotFound;
     146             :     }
     147             : 
     148             :     orc::SymbolNameSet
     149           4 :     lookup(std::shared_ptr<orc::AsynchronousSymbolQuery> Query,
     150             :            orc::SymbolNameSet Symbols) override {
     151             :       orc::SymbolNameSet UnresolvedSymbols;
     152             : 
     153           8 :       for (auto &S : Symbols) {
     154          12 :         if (auto Sym = findSymbol(*S)) {
     155           8 :           if (auto Addr = Sym.getAddress())
     156           8 :             Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
     157             :           else {
     158           0 :             Stack.ES.failQuery(*Query, Addr.takeError());
     159           0 :             return orc::SymbolNameSet();
     160             :           }
     161           0 :         } else if (auto Err = Sym.takeError()) {
     162           0 :           Stack.ES.failQuery(*Query, std::move(Err));
     163           0 :           return orc::SymbolNameSet();
     164             :         } else
     165             :           UnresolvedSymbols.insert(S);
     166             :       }
     167             : 
     168           4 :       if (Query->isFullyResolved())
     169           4 :         Query->handleFullyResolved();
     170             : 
     171             :       return UnresolvedSymbols;
     172             :     }
     173             : 
     174             :   private:
     175           4 :     JITSymbol findSymbol(const std::string &Name) {
     176             :       // Search order:
     177             :       // 1. JIT'd symbols.
     178             :       // 2. Runtime overrides.
     179             :       // 3. External resolver (if present).
     180             : 
     181          12 :       if (auto Sym = Stack.CODLayer.findSymbol(Name, true))
     182           0 :         return Sym;
     183           4 :       else if (auto Err = Sym.takeError())
     184             :         return Sym.takeError();
     185             : 
     186           4 :       if (auto Sym = Stack.CXXRuntimeOverrides.searchOverrides(Name))
     187           0 :         return Sym;
     188             : 
     189           4 :       if (ExternalResolver)
     190             :         return JITSymbol(ExternalResolver(Name.c_str(), ExternalResolverCtx),
     191           8 :                          JITSymbolFlags::Exported);
     192             : 
     193             :       return JITSymbol(nullptr);
     194             :     }
     195             : 
     196             :     OrcCBindingsStack &Stack;
     197             :     LLVMOrcSymbolResolverFn ExternalResolver;
     198             :     void *ExternalResolverCtx = nullptr;
     199             :   };
     200             : 
     201             : public:
     202             : 
     203           4 :   OrcCBindingsStack(TargetMachine &TM,
     204             :                     std::unique_ptr<CompileCallbackMgr> CCMgr,
     205             :                     IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
     206           4 :       : DL(TM.createDataLayout()),
     207             :         IndirectStubsMgr(IndirectStubsMgrBuilder()), CCMgr(std::move(CCMgr)),
     208             :         ObjectLayer(ES,
     209           4 :                     [this](orc::VModuleKey K) {
     210             :                       auto ResolverI = Resolvers.find(K);
     211             :                       assert(ResolverI != Resolvers.end() &&
     212             :                              "No resolver for module K");
     213             :                       auto Resolver = std::move(ResolverI->second);
     214             :                       Resolvers.erase(ResolverI);
     215             :                       return ObjLayerT::Resources{
     216           8 :                           std::make_shared<SectionMemoryManager>(), Resolver};
     217             :                     }),
     218             :         CompileLayer(ObjectLayer, orc::SimpleCompiler(TM)),
     219             :         CODLayer(ES, CompileLayer,
     220           1 :                  [this](orc::VModuleKey K) {
     221             :                    auto ResolverI = Resolvers.find(K);
     222             :                    assert(ResolverI != Resolvers.end() &&
     223             :                           "No resolver for module K");
     224           1 :                    return ResolverI->second;
     225             :                  },
     226             :                  [this](orc::VModuleKey K,
     227           1 :                         std::shared_ptr<orc::SymbolResolver> Resolver) {
     228             :                    assert(!Resolvers.count(K) && "Resolver already present");
     229           1 :                    Resolvers[K] = std::move(Resolver);
     230           1 :                  },
     231           1 :                  [](Function &F) { return std::set<Function *>({&F}); },
     232             :                  *this->CCMgr, std::move(IndirectStubsMgrBuilder), false),
     233             :         CXXRuntimeOverrides(
     234          84 :             [this](const std::string &S) { return mangle(S); }) {}
     235             : 
     236           4 :   LLVMOrcErrorCode shutdown() {
     237             :     // Run any destructors registered with __cxa_atexit.
     238           4 :     CXXRuntimeOverrides.runDestructors();
     239             :     // Run any IR destructors.
     240           7 :     for (auto &DtorRunner : IRStaticDestructorRunners)
     241           6 :       if (auto Err = DtorRunner.runViaLayer(*this))
     242           0 :         return mapError(std::move(Err));
     243             :     return LLVMOrcErrSuccess;
     244             :   }
     245             : 
     246          16 :   std::string mangle(StringRef Name) {
     247             :     std::string MangledName;
     248             :     {
     249          16 :       raw_string_ostream MangledNameStream(MangledName);
     250          32 :       Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
     251             :     }
     252          16 :     return MangledName;
     253             :   }
     254             : 
     255             :   template <typename PtrTy>
     256             :   static PtrTy fromTargetAddress(JITTargetAddress Addr) {
     257             :     return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
     258             :   }
     259             : 
     260             : 
     261             :   LLVMOrcErrorCode
     262           1 :   createLazyCompileCallback(JITTargetAddress &RetAddr,
     263             :                             LLVMOrcLazyCompileCallbackFn Callback,
     264             :                             void *CallbackCtx) {
     265           2 :     if (auto CCInfoOrErr = CCMgr->getCompileCallback()) {
     266             :       auto &CCInfo = *CCInfoOrErr;
     267           2 :       CCInfo.setCompileAction([=]() -> JITTargetAddress {
     268           1 :           return Callback(wrap(this), CallbackCtx);
     269             :         });
     270           1 :       RetAddr = CCInfo.getAddress();
     271           1 :       return LLVMOrcErrSuccess;
     272             :     } else
     273           0 :       return mapError(CCInfoOrErr.takeError());
     274             :   }
     275             : 
     276           1 :   LLVMOrcErrorCode createIndirectStub(StringRef StubName,
     277             :                                       JITTargetAddress Addr) {
     278             :     return mapError(
     279           3 :         IndirectStubsMgr->createStub(StubName, Addr, JITSymbolFlags::Exported));
     280             :   }
     281             : 
     282           1 :   LLVMOrcErrorCode setIndirectStubPointer(StringRef Name,
     283             :                                           JITTargetAddress Addr) {
     284           2 :     return mapError(IndirectStubsMgr->updatePointer(Name, Addr));
     285             :   }
     286             :   template <typename LayerT>
     287             :   LLVMOrcErrorCode
     288           3 :   addIRModule(orc::VModuleKey &RetKey, LayerT &Layer, std::unique_ptr<Module> M,
     289             :               std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
     290             :               LLVMOrcSymbolResolverFn ExternalResolver,
     291             :               void *ExternalResolverCtx) {
     292             : 
     293             :     // Attach a data-layout if one isn't already present.
     294           6 :     if (M->getDataLayout().isDefault())
     295           3 :       M->setDataLayout(DL);
     296             : 
     297             :     // Record the static constructors and destructors. We have to do this before
     298             :     // we hand over ownership of the module to the JIT.
     299           3 :     std::vector<std::string> CtorNames, DtorNames;
     300           3 :     for (auto Ctor : orc::getConstructors(*M))
     301           0 :       CtorNames.push_back(mangle(Ctor.Func->getName()));
     302           3 :     for (auto Dtor : orc::getDestructors(*M))
     303           0 :       DtorNames.push_back(mangle(Dtor.Func->getName()));
     304             : 
     305             :     // Add the module to the JIT.
     306           3 :     RetKey = ES.allocateVModule();
     307           6 :     Resolvers[RetKey] = std::make_shared<CBindingsResolver>(
     308             :         *this, ExternalResolver, ExternalResolverCtx);
     309           6 :     if (auto Err = Layer.addModule(RetKey, std::move(M)))
     310           0 :       return mapError(std::move(Err));
     311             : 
     312           3 :     KeyLayers[RetKey] = detail::createGenericLayer(Layer);
     313             : 
     314             :     // Run the static constructors, and save the static destructor runner for
     315             :     // execution when the JIT is torn down.
     316           6 :     orc::CtorDtorRunner<OrcCBindingsStack> CtorRunner(std::move(CtorNames),
     317             :                                                       RetKey);
     318           6 :     if (auto Err = CtorRunner.runViaLayer(*this))
     319           0 :       return mapError(std::move(Err));
     320             : 
     321           3 :     IRStaticDestructorRunners.emplace_back(std::move(DtorNames), RetKey);
     322             : 
     323           3 :     return LLVMOrcErrSuccess;
     324             :   }
     325             : 
     326           2 :   LLVMOrcErrorCode addIRModuleEager(orc::VModuleKey &RetKey,
     327             :                                     std::unique_ptr<Module> M,
     328             :                                     LLVMOrcSymbolResolverFn ExternalResolver,
     329             :                                     void *ExternalResolverCtx) {
     330           6 :     return addIRModule(RetKey, CompileLayer, std::move(M),
     331           4 :                        llvm::make_unique<SectionMemoryManager>(),
     332           4 :                        std::move(ExternalResolver), ExternalResolverCtx);
     333             :   }
     334             : 
     335           1 :   LLVMOrcErrorCode addIRModuleLazy(orc::VModuleKey &RetKey,
     336             :                                    std::unique_ptr<Module> M,
     337             :                                    LLVMOrcSymbolResolverFn ExternalResolver,
     338             :                                    void *ExternalResolverCtx) {
     339           3 :     return addIRModule(RetKey, CODLayer, std::move(M),
     340           2 :                        llvm::make_unique<SectionMemoryManager>(),
     341           2 :                        std::move(ExternalResolver), ExternalResolverCtx);
     342             :   }
     343             : 
     344           4 :   LLVMOrcErrorCode removeModule(orc::VModuleKey K) {
     345             :     // FIXME: Should error release the module key?
     346          12 :     if (auto Err = KeyLayers[K]->removeModule(K))
     347           0 :       return mapError(std::move(Err));
     348             :     ES.releaseVModule(K);
     349             :     KeyLayers.erase(K);
     350           4 :     return LLVMOrcErrSuccess;
     351             :   }
     352             : 
     353           1 :   LLVMOrcErrorCode addObject(orc::VModuleKey &RetKey,
     354             :                              std::unique_ptr<MemoryBuffer> ObjBuffer,
     355             :                              LLVMOrcSymbolResolverFn ExternalResolver,
     356             :                              void *ExternalResolverCtx) {
     357           1 :     if (auto Obj = object::ObjectFile::createObjectFile(
     358           2 :             ObjBuffer->getMemBufferRef())) {
     359             : 
     360           1 :       RetKey = ES.allocateVModule();
     361           2 :       Resolvers[RetKey] = std::make_shared<CBindingsResolver>(
     362             :           *this, ExternalResolver, ExternalResolverCtx);
     363             : 
     364           4 :       if (auto Err = ObjectLayer.addObject(RetKey, std::move(ObjBuffer)))
     365           0 :         return mapError(std::move(Err));
     366             : 
     367           1 :       KeyLayers[RetKey] = detail::createGenericLayer(ObjectLayer);
     368             : 
     369             :       return LLVMOrcErrSuccess;
     370             :     } else
     371           0 :       return mapError(Obj.takeError());
     372             :   }
     373             : 
     374           5 :   JITSymbol findSymbol(const std::string &Name,
     375             :                                  bool ExportedSymbolsOnly) {
     376          14 :     if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly))
     377           1 :       return Sym;
     378          16 :     return CODLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
     379             :   }
     380             : 
     381           0 :   JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
     382             :                          bool ExportedSymbolsOnly) {
     383           0 :     return KeyLayers[K]->findSymbolIn(K, Name, ExportedSymbolsOnly);
     384             :   }
     385             : 
     386           5 :   LLVMOrcErrorCode findSymbolAddress(JITTargetAddress &RetAddr,
     387             :                                      const std::string &Name,
     388             :                                      bool ExportedSymbolsOnly) {
     389           5 :     RetAddr = 0;
     390           5 :     if (auto Sym = findSymbol(Name, ExportedSymbolsOnly)) {
     391             :       // Successful lookup, non-null symbol:
     392          10 :       if (auto AddrOrErr = Sym.getAddress()) {
     393           5 :         RetAddr = *AddrOrErr;
     394           5 :         return LLVMOrcErrSuccess;
     395             :       } else
     396           0 :         return mapError(AddrOrErr.takeError());
     397           0 :     } else if (auto Err = Sym.takeError()) {
     398             :       // Lookup failure - report error.
     399           0 :       return mapError(std::move(Err));
     400             :     }
     401             :     // Otherwise we had a successful lookup but got a null result. We already
     402             :     // set RetAddr to '0' above, so just return success.
     403           0 :     return LLVMOrcErrSuccess;
     404             :   }
     405             : 
     406             :   const std::string &getErrorMessage() const { return ErrMsg; }
     407             : 
     408             : private:
     409             : 
     410           2 :   LLVMOrcErrorCode mapError(Error Err) {
     411           2 :     LLVMOrcErrorCode Result = LLVMOrcErrSuccess;
     412           6 :     handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
     413             :       // Handler of last resort.
     414           0 :       Result = LLVMOrcErrGeneric;
     415           0 :       ErrMsg = "";
     416           0 :       raw_string_ostream ErrStream(ErrMsg);
     417           0 :       EIB.log(ErrStream);
     418           0 :     });
     419           2 :     return Result;
     420             :   }
     421             : 
     422           0 :   void reportError(Error Err) {
     423             :     // FIXME: Report errors on the execution session.
     424           0 :     logAllUnhandledErrors(std::move(Err), errs(), "ORC error: ");
     425           0 :   };
     426             : 
     427             :   orc::ExecutionSession ES;
     428             : 
     429             :   DataLayout DL;
     430             :   SectionMemoryManager CCMgrMemMgr;
     431             : 
     432             :   std::unique_ptr<orc::IndirectStubsManager> IndirectStubsMgr;
     433             : 
     434             :   std::unique_ptr<CompileCallbackMgr> CCMgr;
     435             :   ObjLayerT ObjectLayer;
     436             :   CompileLayerT CompileLayer;
     437             :   CODLayerT CODLayer;
     438             : 
     439             :   std::map<orc::VModuleKey, std::unique_ptr<detail::GenericLayer>> KeyLayers;
     440             : 
     441             :   orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
     442             :   std::vector<orc::CtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
     443             :   std::string ErrMsg;
     444             : 
     445             :   std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>> Resolvers;
     446             : };
     447             : 
     448             : } // end namespace llvm
     449             : 
     450             : #endif // LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H

Generated by: LCOV version 1.13