LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/Orc - OrcCBindingsStack.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 86 112 76.8 %
Date: 2017-09-14 15:23:50 Functions: 22 27 81.5 %
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 <memory>
      37             : #include <set>
      38             : #include <string>
      39             : #include <vector>
      40             : 
      41             : namespace llvm {
      42             : 
      43             : class OrcCBindingsStack;
      44             : 
      45             : DEFINE_SIMPLE_CONVERSION_FUNCTIONS(std::shared_ptr<Module>,
      46             :                                    LLVMSharedModuleRef)
      47             : DEFINE_SIMPLE_CONVERSION_FUNCTIONS(std::shared_ptr<MemoryBuffer>,
      48             :                                    LLVMSharedObjectBufferRef)
      49             : DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef)
      50             : DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
      51             : 
      52          15 : class OrcCBindingsStack {
      53             : public:
      54             : 
      55             :   using CompileCallbackMgr = orc::JITCompileCallbackManager;
      56             :   using ObjLayerT = orc::RTDyldObjectLinkingLayer;
      57             :   using CompileLayerT = orc::IRCompileLayer<ObjLayerT, orc::SimpleCompiler>;
      58             :   using CODLayerT =
      59             :         orc::CompileOnDemandLayer<CompileLayerT, CompileCallbackMgr>;
      60             : 
      61             :   using CallbackManagerBuilder =
      62             :       std::function<std::unique_ptr<CompileCallbackMgr>()>;
      63             : 
      64             :   using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT;
      65             : 
      66             : private:
      67             :   class GenericHandle {
      68             :   public:
      69             :     virtual ~GenericHandle() = default;
      70             : 
      71             :     virtual JITSymbol findSymbolIn(const std::string &Name,
      72             :                                    bool ExportedSymbolsOnly) = 0;
      73             :     virtual Error removeModule() = 0;
      74             :   };
      75             : 
      76           3 :   template <typename LayerT> class GenericHandleImpl : public GenericHandle {
      77             :   public:
      78           3 :     GenericHandleImpl(LayerT &Layer, typename LayerT::ModuleHandleT Handle)
      79           3 :         : Layer(Layer), Handle(std::move(Handle)) {}
      80             : 
      81           0 :     JITSymbol findSymbolIn(const std::string &Name,
      82             :                            bool ExportedSymbolsOnly) override {
      83           0 :       return Layer.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
      84             :     }
      85             : 
      86           5 :     Error removeModule() override { return Layer.removeModule(Handle); }
      87             : 
      88             :   private:
      89             :     LayerT &Layer;
      90             :     typename LayerT::ModuleHandleT Handle;
      91             :   };
      92             : 
      93             :   template <typename LayerT>
      94             :   std::unique_ptr<GenericHandleImpl<LayerT>>
      95             :   createGenericHandle(LayerT &Layer, typename LayerT::ModuleHandleT Handle) {
      96             :     return llvm::make_unique<GenericHandleImpl<LayerT>>(Layer,
      97           6 :                                                         std::move(Handle));
      98             :   }
      99             : 
     100             : public:
     101             :   using ModuleHandleT = unsigned;
     102             : 
     103           3 :   OrcCBindingsStack(TargetMachine &TM,
     104             :                     std::unique_ptr<CompileCallbackMgr> CCMgr,
     105             :                     IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
     106           3 :       : DL(TM.createDataLayout()), IndirectStubsMgr(IndirectStubsMgrBuilder()),
     107           3 :         CCMgr(std::move(CCMgr)),
     108             :         ObjectLayer(
     109             :           []() {
     110             :             return std::make_shared<SectionMemoryManager>();
     111             :           }),
     112             :         CompileLayer(ObjectLayer, orc::SimpleCompiler(TM)),
     113             :         CODLayer(CompileLayer,
     114           2 :                  [](Function &F) { return std::set<Function *>({&F}); },
     115           9 :                  *this->CCMgr, std::move(IndirectStubsMgrBuilder), false),
     116             :         CXXRuntimeOverrides(
     117          66 :             [this](const std::string &S) { return mangle(S); }) {}
     118             : 
     119           3 :   LLVMOrcErrorCode shutdown() {
     120             :     // Run any destructors registered with __cxa_atexit.
     121           3 :     CXXRuntimeOverrides.runDestructors();
     122             :     // Run any IR destructors.
     123          15 :     for (auto &DtorRunner : IRStaticDestructorRunners)
     124           9 :       if (auto Err = DtorRunner.runViaLayer(*this))
     125           0 :         return mapError(std::move(Err));
     126             :     return LLVMOrcErrSuccess;
     127             :   }
     128             : 
     129          12 :   std::string mangle(StringRef Name) {
     130          12 :     std::string MangledName;
     131             :     {
     132          24 :       raw_string_ostream MangledNameStream(MangledName);
     133          24 :       Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
     134             :     }
     135          12 :     return MangledName;
     136             :   }
     137             : 
     138             :   template <typename PtrTy>
     139             :   static PtrTy fromTargetAddress(JITTargetAddress Addr) {
     140             :     return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
     141             :   }
     142             : 
     143             : 
     144             :   LLVMOrcErrorCode
     145           1 :   createLazyCompileCallback(JITTargetAddress &RetAddr,
     146             :                             LLVMOrcLazyCompileCallbackFn Callback,
     147             :                             void *CallbackCtx) {
     148           4 :     if (auto CCInfoOrErr = CCMgr->getCompileCallback()) {
     149           1 :       auto &CCInfo = *CCInfoOrErr;
     150           4 :       CCInfo.setCompileAction([=]() -> JITTargetAddress {
     151           1 :           return Callback(wrap(this), CallbackCtx);
     152             :         });
     153           1 :       RetAddr = CCInfo.getAddress();
     154           1 :       return LLVMOrcErrSuccess;
     155             :     } else
     156           0 :       return mapError(CCInfoOrErr.takeError());
     157             :   }
     158             : 
     159           1 :   LLVMOrcErrorCode createIndirectStub(StringRef StubName,
     160             :                                       JITTargetAddress Addr) {
     161             :     return mapError(
     162           4 :         IndirectStubsMgr->createStub(StubName, Addr, JITSymbolFlags::Exported));
     163             :   }
     164             : 
     165           1 :   LLVMOrcErrorCode setIndirectStubPointer(StringRef Name,
     166             :                                           JITTargetAddress Addr) {
     167           3 :     return mapError(IndirectStubsMgr->updatePointer(Name, Addr));
     168             :   }
     169             : 
     170             :   std::shared_ptr<JITSymbolResolver>
     171             :   createResolver(LLVMOrcSymbolResolverFn ExternalResolver,
     172             :                  void *ExternalResolverCtx) {
     173           6 :     return orc::createLambdaResolver(
     174             :         [this, ExternalResolver, ExternalResolverCtx](const std::string &Name)
     175          12 :           -> JITSymbol {
     176             :           // Search order:
     177             :           // 1. JIT'd symbols.
     178             :           // 2. Runtime overrides.
     179             :           // 3. External resolver (if present).
     180             : 
     181           9 :           if (auto Sym = CODLayer.findSymbol(Name, true))
     182           0 :             return Sym;
     183           9 :           else if (auto Err = Sym.takeError())
     184           0 :             return Sym.takeError();
     185             : 
     186           3 :           if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name))
     187           0 :             return Sym;
     188             : 
     189           3 :           if (ExternalResolver)
     190             :             return JITSymbol(
     191             :                 ExternalResolver(Name.c_str(), ExternalResolverCtx),
     192           9 :                 JITSymbolFlags::Exported);
     193             : 
     194             :           return JITSymbol(nullptr);
     195             :         },
     196             :         [](const std::string &Name) -> JITSymbol {
     197           0 :           return JITSymbol(nullptr);
     198           3 :         });
     199             :   }
     200             : 
     201             :   template <typename LayerT>
     202             :   LLVMOrcErrorCode
     203           3 :   addIRModule(ModuleHandleT &RetHandle, LayerT &Layer,
     204             :               std::shared_ptr<Module> M,
     205             :               std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
     206             :               LLVMOrcSymbolResolverFn ExternalResolver,
     207             :               void *ExternalResolverCtx) {
     208             : 
     209             :     // Attach a data-layout if one isn't already present.
     210           6 :     if (M->getDataLayout().isDefault())
     211           3 :       M->setDataLayout(DL);
     212             : 
     213             :     // Record the static constructors and destructors. We have to do this before
     214             :     // we hand over ownership of the module to the JIT.
     215           9 :     std::vector<std::string> CtorNames, DtorNames;
     216           3 :     for (auto Ctor : orc::getConstructors(*M))
     217           0 :       CtorNames.push_back(mangle(Ctor.Func->getName()));
     218           3 :     for (auto Dtor : orc::getDestructors(*M))
     219           0 :       DtorNames.push_back(mangle(Dtor.Func->getName()));
     220             : 
     221             :     // Create the resolver.
     222           6 :     auto Resolver = createResolver(ExternalResolver, ExternalResolverCtx);
     223             : 
     224             :     // Add the module to the JIT.
     225             :     ModuleHandleT H;
     226          21 :     if (auto LHOrErr = Layer.addModule(std::move(M), std::move(Resolver)))
     227           3 :       H = createHandle(Layer, *LHOrErr);
     228             :     else
     229           0 :       return mapError(LHOrErr.takeError());
     230             : 
     231             :     // Run the static constructors, and save the static destructor runner for
     232             :     // execution when the JIT is torn down.
     233           9 :     orc::CtorDtorRunner<OrcCBindingsStack> CtorRunner(std::move(CtorNames), H);
     234           9 :     if (auto Err = CtorRunner.runViaLayer(*this))
     235           0 :       return mapError(std::move(Err));
     236             : 
     237           3 :     IRStaticDestructorRunners.emplace_back(std::move(DtorNames), H);
     238             : 
     239           3 :     RetHandle = H;
     240           3 :     return LLVMOrcErrSuccess;
     241             :   }
     242             : 
     243           2 :   LLVMOrcErrorCode addIRModuleEager(ModuleHandleT &RetHandle,
     244             :                                     std::shared_ptr<Module> M,
     245             :                                     LLVMOrcSymbolResolverFn ExternalResolver,
     246             :                                     void *ExternalResolverCtx) {
     247           8 :     return addIRModule(RetHandle, CompileLayer, std::move(M),
     248           4 :                        llvm::make_unique<SectionMemoryManager>(),
     249           6 :                        std::move(ExternalResolver), ExternalResolverCtx);
     250             :   }
     251             : 
     252           1 :   LLVMOrcErrorCode addIRModuleLazy(ModuleHandleT &RetHandle,
     253             :                                    std::shared_ptr<Module> M,
     254             :                                    LLVMOrcSymbolResolverFn ExternalResolver,
     255             :                                    void *ExternalResolverCtx) {
     256           4 :     return addIRModule(RetHandle, CODLayer, std::move(M),
     257           2 :                        llvm::make_unique<SectionMemoryManager>(),
     258           3 :                        std::move(ExternalResolver), ExternalResolverCtx);
     259             :   }
     260             : 
     261           3 :   LLVMOrcErrorCode removeModule(ModuleHandleT H) {
     262          15 :     if (auto Err = GenericHandles[H]->removeModule())
     263           0 :       return mapError(std::move(Err));
     264           9 :     GenericHandles[H] = nullptr;
     265           3 :     FreeHandleIndexes.push_back(H);
     266           3 :     return LLVMOrcErrSuccess;
     267             :   }
     268             : 
     269           4 :   JITSymbol findSymbol(const std::string &Name,
     270             :                                  bool ExportedSymbolsOnly) {
     271          15 :     if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly))
     272           1 :       return Sym;
     273          12 :     return CODLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
     274             :   }
     275             : 
     276             :   JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
     277             :                          bool ExportedSymbolsOnly) {
     278           0 :     return GenericHandles[H]->findSymbolIn(Name, ExportedSymbolsOnly);
     279             :   }
     280             : 
     281           4 :   LLVMOrcErrorCode findSymbolAddress(JITTargetAddress &RetAddr,
     282             :                                      const std::string &Name,
     283             :                                      bool ExportedSymbolsOnly) {
     284           4 :     RetAddr = 0;
     285           4 :     if (auto Sym = findSymbol(Name, ExportedSymbolsOnly)) {
     286             :       // Successful lookup, non-null symbol:
     287          12 :       if (auto AddrOrErr = Sym.getAddress()) {
     288           4 :         RetAddr = *AddrOrErr;
     289           4 :         return LLVMOrcErrSuccess;
     290             :       } else
     291           0 :         return mapError(AddrOrErr.takeError());
     292           0 :     } else if (auto Err = Sym.takeError()) {
     293             :       // Lookup failure - report error.
     294           0 :       return mapError(std::move(Err));
     295             :     }
     296             :     // Otherwise we had a successful lookup but got a null result. We already
     297             :     // set RetAddr to '0' above, so just return success.
     298           0 :     return LLVMOrcErrSuccess;
     299             :   }
     300             : 
     301             :   const std::string &getErrorMessage() const { return ErrMsg; }
     302             : 
     303             : private:
     304             :   template <typename LayerT>
     305           3 :   unsigned createHandle(LayerT &Layer, typename LayerT::ModuleHandleT Handle) {
     306             :     unsigned NewHandle;
     307           6 :     if (!FreeHandleIndexes.empty()) {
     308           0 :       NewHandle = FreeHandleIndexes.back();
     309           0 :       FreeHandleIndexes.pop_back();
     310           0 :       GenericHandles[NewHandle] = createGenericHandle(Layer, std::move(Handle));
     311             :       return NewHandle;
     312             :     } else {
     313           6 :       NewHandle = GenericHandles.size();
     314          18 :       GenericHandles.push_back(createGenericHandle(Layer, std::move(Handle)));
     315             :     }
     316           3 :     return NewHandle;
     317             :   }
     318             : 
     319           2 :   LLVMOrcErrorCode mapError(Error Err) {
     320           2 :     LLVMOrcErrorCode Result = LLVMOrcErrSuccess;
     321           6 :     handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
     322             :       // Handler of last resort.
     323           0 :       Result = LLVMOrcErrGeneric;
     324           0 :       ErrMsg = "";
     325           0 :       raw_string_ostream ErrStream(ErrMsg);
     326           0 :       EIB.log(ErrStream);
     327           0 :     });
     328           2 :     return Result;
     329             :   }
     330             : 
     331             :   DataLayout DL;
     332             :   SectionMemoryManager CCMgrMemMgr;
     333             : 
     334             :   std::unique_ptr<orc::IndirectStubsManager> IndirectStubsMgr;
     335             : 
     336             :   std::unique_ptr<CompileCallbackMgr> CCMgr;
     337             :   ObjLayerT ObjectLayer;
     338             :   CompileLayerT CompileLayer;
     339             :   CODLayerT CODLayer;
     340             : 
     341             :   std::vector<std::unique_ptr<GenericHandle>> GenericHandles;
     342             :   std::vector<unsigned> FreeHandleIndexes;
     343             : 
     344             :   orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
     345             :   std::vector<orc::CtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
     346             :   std::string ErrMsg;
     347             : };
     348             : 
     349             : } // end namespace llvm
     350             : 
     351             : #endif // LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H

Generated by: LCOV version 1.13