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. IRCompileLayer(BaseLayerT & BaseLayer,CompileFtor Compile)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. setObjectCache(ObjectCache * NewCache)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> addModuleSet(ModuleSetT Ms,MemoryManagerPtrT MemMgr,SymbolResolverPtrT Resolver)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. removeModuleSet(ModuleSetHandleT 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. findSymbol(const std::string & Name,bool ExportedSymbolsOnly)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. findSymbolIn(ModuleSetHandleT H,const std::string & Name,bool ExportedSymbolsOnly)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. emitAndFinalize(ModuleSetHandleT H)116 void emitAndFinalize(ModuleSetHandleT H) { 117 BaseLayer.emitAndFinalize(H); 118 } 119 120 private: 121 object::OwningBinary<object::ObjectFile> tryToLoadFromObjectCache(const Module & M)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