Home | History | Annotate | Download | only in Orc
      1 //===------ IRCompileLayer.h -- Eagerly compile IR for JIT ------*- 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 // Contains the definition for a basic, eagerly compiling layer of the JIT.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H
     15 #define LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H
     16 
     17 #include "JITSymbol.h"
     18 #include "llvm/ExecutionEngine/ObjectCache.h"
     19 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
     20 #include "llvm/Object/ObjectFile.h"
     21 #include <memory>
     22 
     23 namespace llvm {
     24 namespace orc {
     25 
     26 /// @brief Eager IR compiling layer.
     27 ///
     28 ///   This layer accepts sets of LLVM IR Modules (via addModuleSet). It
     29 /// immediately compiles each IR module to an object file (each IR Module is
     30 /// compiled separately). The resulting set of object files is then added to
     31 /// the layer below, which must implement the object layer concept.
     32 template <typename BaseLayerT> class IRCompileLayer {
     33 public:
     34   typedef std::function<object::OwningBinary<object::ObjectFile>(Module &)>
     35       CompileFtor;
     36 
     37 private:
     38   typedef typename BaseLayerT::ObjSetHandleT ObjSetHandleT;
     39 
     40 public:
     41   /// @brief Handle to a set of compiled modules.
     42   typedef ObjSetHandleT ModuleSetHandleT;
     43 
     44   /// @brief Construct an IRCompileLayer with the given BaseLayer, which must
     45   ///        implement the ObjectLayer concept.
     46   IRCompileLayer(BaseLayerT &BaseLayer, CompileFtor Compile)
     47       : BaseLayer(BaseLayer), Compile(std::move(Compile)), ObjCache(nullptr) {}
     48 
     49   /// @brief Set an ObjectCache to query before compiling.
     50   void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; }
     51 
     52   /// @brief Compile each module in the given module set, then add the resulting
     53   ///        set of objects to the base layer along with the memory manager and
     54   ///        symbol resolver.
     55   ///
     56   /// @return A handle for the added modules.
     57   template <typename ModuleSetT, typename MemoryManagerPtrT,
     58             typename SymbolResolverPtrT>
     59   ModuleSetHandleT addModuleSet(ModuleSetT Ms,
     60                                 MemoryManagerPtrT MemMgr,
     61                                 SymbolResolverPtrT Resolver) {
     62     std::vector<std::unique_ptr<object::OwningBinary<object::ObjectFile>>>
     63       Objects;
     64 
     65     for (const auto &M : Ms) {
     66       auto Object =
     67         llvm::make_unique<object::OwningBinary<object::ObjectFile>>();
     68 
     69       if (ObjCache)
     70         *Object = tryToLoadFromObjectCache(*M);
     71 
     72       if (!Object->getBinary()) {
     73         *Object = Compile(*M);
     74         if (ObjCache)
     75           ObjCache->notifyObjectCompiled(&*M,
     76                                      Object->getBinary()->getMemoryBufferRef());
     77       }
     78 
     79       Objects.push_back(std::move(Object));
     80     }
     81 
     82     ModuleSetHandleT H =
     83       BaseLayer.addObjectSet(std::move(Objects), std::move(MemMgr),
     84                              std::move(Resolver));
     85 
     86     return H;
     87   }
     88 
     89   /// @brief Remove the module set associated with the handle H.
     90   void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeObjectSet(H); }
     91 
     92   /// @brief Search for the given named symbol.
     93   /// @param Name The name of the symbol to search for.
     94   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
     95   /// @return A handle for the given named symbol, if it exists.
     96   JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
     97     return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
     98   }
     99 
    100   /// @brief Get the address of the given symbol in the context of the set of
    101   ///        compiled modules represented by the handle H. This call is
    102   ///        forwarded to the base layer's implementation.
    103   /// @param H The handle for the module set to search in.
    104   /// @param Name The name of the symbol to search for.
    105   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
    106   /// @return A handle for the given named symbol, if it is found in the
    107   ///         given module set.
    108   JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
    109                          bool ExportedSymbolsOnly) {
    110     return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
    111   }
    112 
    113   /// @brief Immediately emit and finalize the moduleOB set represented by the
    114   ///        given handle.
    115   /// @param H Handle for module set to emit/finalize.
    116   void emitAndFinalize(ModuleSetHandleT H) {
    117     BaseLayer.emitAndFinalize(H);
    118   }
    119 
    120 private:
    121   object::OwningBinary<object::ObjectFile>
    122   tryToLoadFromObjectCache(const Module &M) {
    123     std::unique_ptr<MemoryBuffer> ObjBuffer = ObjCache->getObject(&M);
    124     if (!ObjBuffer)
    125       return object::OwningBinary<object::ObjectFile>();
    126 
    127     Expected<std::unique_ptr<object::ObjectFile>> Obj =
    128         object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
    129     if (!Obj) {
    130       // TODO: Actually report errors helpfully.
    131       consumeError(Obj.takeError());
    132       return object::OwningBinary<object::ObjectFile>();
    133     }
    134 
    135     return object::OwningBinary<object::ObjectFile>(std::move(*Obj),
    136                                                     std::move(ObjBuffer));
    137   }
    138 
    139   BaseLayerT &BaseLayer;
    140   CompileFtor Compile;
    141   ObjectCache *ObjCache;
    142 };
    143 
    144 } // End namespace orc.
    145 } // End namespace llvm.
    146 
    147 #endif // LLVM_EXECUTIONENGINE_ORC_IRCOMPILINGLAYER_H
    148