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

Generated by: LCOV version 1.13