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