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