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