3076c12089ad305e379455cb0a6d08d5789cb6b7
[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 "llvm/ExecutionEngine/ObjectCache.h"
18 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
19 #include "llvm/Object/ObjectFile.h"
20 #include <memory>
21
22 namespace llvm {
23
24 /// @brief Eager IR compiling layer.
25 ///
26 ///   This layer accepts sets of LLVM IR Modules (via addModuleSet). It
27 /// immediately compiles each IR module to an object file (each IR Module is
28 /// compiled separately). The resulting set of object files is then added to
29 /// the layer below, which must implement the object layer concept.
30 template <typename BaseLayerT> class IRCompileLayer {
31 public:
32   typedef std::function<object::OwningBinary<object::ObjectFile>(Module &)>
33       CompileFtor;
34
35 private:
36   typedef typename BaseLayerT::ObjSetHandleT ObjSetHandleT;
37
38   typedef std::vector<std::unique_ptr<object::ObjectFile>> OwningObjectVec;
39   typedef std::vector<std::unique_ptr<MemoryBuffer>> OwningBufferVec;
40
41 public:
42   /// @brief Handle to a set of compiled modules.
43   typedef ObjSetHandleT ModuleSetHandleT;
44
45   /// @brief Construct an IRCompileLayer with the given BaseLayer, which must
46   ///        implement the ObjectLayer concept.
47   IRCompileLayer(BaseLayerT &BaseLayer, CompileFtor Compile)
48       : BaseLayer(BaseLayer), Compile(std::move(Compile)), ObjCache(nullptr) {}
49
50   /// @brief Set an ObjectCache to query before compiling.
51   void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; }
52
53   /// @brief Compile each module in the given module set, then then add the
54   ///        resulting set of objects to the base layer, along with the memory
55   //         manager MM.
56   ///
57   /// @return A handle for the added modules.
58   template <typename ModuleSetT>
59   ModuleSetHandleT addModuleSet(ModuleSetT Ms,
60                                 std::unique_ptr<RTDyldMemoryManager> MM) {
61     OwningObjectVec Objects;
62     OwningBufferVec Buffers;
63
64     for (const auto &M : Ms) {
65       std::unique_ptr<object::ObjectFile> Object;
66       std::unique_ptr<MemoryBuffer> Buffer;
67
68       if (ObjCache)
69         std::tie(Object, Buffer) = tryToLoadFromObjectCache(*M).takeBinary();
70
71       if (!Object) {
72         std::tie(Object, Buffer) = Compile(*M).takeBinary();
73         if (ObjCache)
74           ObjCache->notifyObjectCompiled(&*M, Buffer->getMemBufferRef());
75       }
76
77       Objects.push_back(std::move(Object));
78       Buffers.push_back(std::move(Buffer));
79     }
80
81     ModuleSetHandleT H =
82       BaseLayer.addObjectSet(Objects, std::move(MM));
83
84     BaseLayer.takeOwnershipOfBuffers(H, std::move(Buffers));
85
86     return H;
87   }
88
89   /// @brief Remove the module set associated with the handle H.
90   void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeObjectSet(H); }
91
92   /// @brief Get the address of a loaded symbol. This call is forwarded to the
93   ///        base layer's getSymbolAddress implementation.
94   uint64_t getSymbolAddress(const std::string &Name, bool ExportedSymbolsOnly) {
95     return BaseLayer.getSymbolAddress(Name, ExportedSymbolsOnly);
96   }
97
98   /// @brief Get the address of the given symbol in the context of the set of
99   ///        compiled modules represented by the handle H. This call is
100   ///        forwarded to the base layer's implementation.
101   uint64_t lookupSymbolAddressIn(ModuleSetHandleT H, const std::string &Name,
102                                  bool ExportedSymbolsOnly) {
103     return BaseLayer.lookupSymbolAddressIn(H, Name, ExportedSymbolsOnly);
104   }
105
106 private:
107   object::OwningBinary<object::ObjectFile>
108   tryToLoadFromObjectCache(const Module &M) {
109     std::unique_ptr<MemoryBuffer> ObjBuffer = ObjCache->getObject(&M);
110     if (!ObjBuffer)
111       return object::OwningBinary<object::ObjectFile>();
112
113     ErrorOr<std::unique_ptr<object::ObjectFile>> Obj =
114         object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
115     if (!Obj)
116       return object::OwningBinary<object::ObjectFile>();
117
118     return object::OwningBinary<object::ObjectFile>(std::move(*Obj),
119                                                     std::move(ObjBuffer));
120   }
121
122   BaseLayerT &BaseLayer;
123   CompileFtor Compile;
124   ObjectCache *ObjCache;
125 };
126 }
127
128 #endif // LLVM_EXECUTIONENGINE_ORC_IRCOMPILINGLAYER_H