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 23namespace llvm { 24namespace 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. 32template <typename BaseLayerT> class IRCompileLayer { 33public: 34 typedef std::function<object::OwningBinary<object::ObjectFile>(Module &)> 35 CompileFtor; 36 37private: 38 typedef typename BaseLayerT::ObjSetHandleT ObjSetHandleT; 39 40 typedef std::vector<std::unique_ptr<object::ObjectFile>> OwningObjectVec; 41 typedef std::vector<std::unique_ptr<MemoryBuffer>> OwningBufferVec; 42 43public: 44 /// @brief Handle to a set of compiled modules. 45 typedef ObjSetHandleT ModuleSetHandleT; 46 47 /// @brief Construct an IRCompileLayer with the given BaseLayer, which must 48 /// implement the ObjectLayer concept. 49 IRCompileLayer(BaseLayerT &BaseLayer, CompileFtor Compile) 50 : BaseLayer(BaseLayer), Compile(std::move(Compile)), ObjCache(nullptr) {} 51 52 /// @brief Set an ObjectCache to query before compiling. 53 void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; } 54 55 /// @brief Compile each module in the given module set, then add the resulting 56 /// set of objects to the base layer along with the memory manager and 57 /// symbol resolver. 58 /// 59 /// @return A handle for the added modules. 60 template <typename ModuleSetT, typename MemoryManagerPtrT, 61 typename SymbolResolverPtrT> 62 ModuleSetHandleT addModuleSet(ModuleSetT Ms, 63 MemoryManagerPtrT MemMgr, 64 SymbolResolverPtrT Resolver) { 65 OwningObjectVec Objects; 66 OwningBufferVec Buffers; 67 68 for (const auto &M : Ms) { 69 std::unique_ptr<object::ObjectFile> Object; 70 std::unique_ptr<MemoryBuffer> Buffer; 71 72 if (ObjCache) 73 std::tie(Object, Buffer) = tryToLoadFromObjectCache(*M).takeBinary(); 74 75 if (!Object) { 76 std::tie(Object, Buffer) = Compile(*M).takeBinary(); 77 if (ObjCache) 78 ObjCache->notifyObjectCompiled(&*M, Buffer->getMemBufferRef()); 79 } 80 81 Objects.push_back(std::move(Object)); 82 Buffers.push_back(std::move(Buffer)); 83 } 84 85 ModuleSetHandleT H = 86 BaseLayer.addObjectSet(Objects, std::move(MemMgr), std::move(Resolver)); 87 88 return H; 89 } 90 91 /// @brief Remove the module set associated with the handle H. 92 void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeObjectSet(H); } 93 94 /// @brief Search for the given named symbol. 95 /// @param Name The name of the symbol to search for. 96 /// @param ExportedSymbolsOnly If true, search only for exported symbols. 97 /// @return A handle for the given named symbol, if it exists. 98 JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { 99 return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); 100 } 101 102 /// @brief Get the address of the given symbol in the context of the set of 103 /// compiled modules represented by the handle H. This call is 104 /// forwarded to the base layer's implementation. 105 /// @param H The handle for the module set to search in. 106 /// @param Name The name of the symbol to search for. 107 /// @param ExportedSymbolsOnly If true, search only for exported symbols. 108 /// @return A handle for the given named symbol, if it is found in the 109 /// given module set. 110 JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, 111 bool ExportedSymbolsOnly) { 112 return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); 113 } 114 115 /// @brief Immediately emit and finalize the moduleOB set represented by the 116 /// given handle. 117 /// @param H Handle for module set to emit/finalize. 118 void emitAndFinalize(ModuleSetHandleT H) { 119 BaseLayer.emitAndFinalize(H); 120 } 121 122private: 123 object::OwningBinary<object::ObjectFile> 124 tryToLoadFromObjectCache(const Module &M) { 125 std::unique_ptr<MemoryBuffer> ObjBuffer = ObjCache->getObject(&M); 126 if (!ObjBuffer) 127 return object::OwningBinary<object::ObjectFile>(); 128 129 ErrorOr<std::unique_ptr<object::ObjectFile>> Obj = 130 object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); 131 if (!Obj) 132 return object::OwningBinary<object::ObjectFile>(); 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