[Orc] New JIT APIs.
[oota-llvm.git] / include / llvm / ExecutionEngine / Orc / ObjectLinkingLayer.h
1 //===- ObjectLinkingLayer.h - Add object files to a JIT process -*- 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 the object layer of the JIT.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
15 #define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
16
17 #include "LookasideRTDyldMM.h"
18 #include "llvm/ExecutionEngine/ExecutionEngine.h"
19 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
20 #include <list>
21 #include <memory>
22
23 namespace llvm {
24
25 class ObjectLinkingLayerBase {
26 protected:
27   /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
28   ///
29   /// An instance of this class will be created for each set of objects added
30   /// via JITObjectLayer::addObjectSet. Deleting the instance (via
31   /// removeObjectSet) frees its memory, removing all symbol definitions that
32   /// had been provided by this instance. Higher level layers are responsible
33   /// for taking any action required to handle the missing symbols.
34   class LinkedObjectSet {
35   public:
36     LinkedObjectSet(std::unique_ptr<RTDyldMemoryManager> MM)
37         : MM(std::move(MM)), RTDyld(llvm::make_unique<RuntimeDyld>(&*this->MM)),
38           State(Raw) {}
39
40     std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
41     addObject(const object::ObjectFile &Obj) {
42       return RTDyld->loadObject(Obj);
43     }
44
45     uint64_t getSymbolAddress(StringRef Name, bool ExportedSymbolsOnly) {
46       if (ExportedSymbolsOnly)
47         return RTDyld->getExportedSymbolLoadAddress(Name);
48       return RTDyld->getSymbolLoadAddress(Name);
49     }
50
51     bool NeedsFinalization() const { return (State == Raw); }
52
53     void Finalize() {
54       State = Finalizing;
55       RTDyld->resolveRelocations();
56       RTDyld->registerEHFrames();
57       MM->finalizeMemory();
58       State = Finalized;
59     }
60
61     void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) {
62       assert((State != Finalized) &&
63              "Attempting to remap sections for finalized objects.");
64       RTDyld->mapSectionAddress(LocalAddress, TargetAddress);
65     }
66
67   private:
68     std::unique_ptr<RTDyldMemoryManager> MM;
69     std::unique_ptr<RuntimeDyld> RTDyld;
70     enum { Raw, Finalizing, Finalized } State;
71   };
72
73   typedef std::list<LinkedObjectSet> LinkedObjectSetListT;
74
75 public:
76   /// @brief Handle to a set of loaded objects.
77   typedef typename LinkedObjectSetListT::iterator ObjSetHandleT;
78 };
79
80 /// @brief Default (no-op) action to perform when loading objects.
81 class DoNothingOnNotifyLoaded {
82 public:
83   template <typename ObjSetT, typename LoadResult>
84   void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &,
85                   const LoadResult &) {}
86 };
87
88 /// @brief Bare bones object linking layer.
89 ///
90 ///   This class is intended to be used as the base layer for a JIT. It allows
91 /// object files to be loaded into memory, linked, and the addresses of their
92 /// symbols queried. All objects added to this layer can see each other's
93 /// symbols.
94 template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
95 class ObjectLinkingLayer : public ObjectLinkingLayerBase {
96 public:
97   /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
98   ///        RuntimeDyld::LoadedObjectInfo instances.
99   typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
100       LoadedObjInfoList;
101
102   /// @brief Default construct an ObjectLinkingLayer.
103   ObjectLinkingLayer() {}
104
105   /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded
106   ///        functor.
107   ObjectLinkingLayer(NotifyLoadedFtor NotifyLoaded)
108       : NotifyLoaded(std::move(NotifyLoaded)) {}
109
110   /// @brief Construct an ObjectLinkingLayer with the given NotifyFinalized
111   ///        functor.
112   ObjectLinkingLayer(std::function<void(ObjSetHandleT)> NotifyFinalized)
113       : NotifyFinalized(std::move(NotifyFinalized)) {}
114
115   /// @brief Construct an ObjectLinkingLayer with the given CreateMemoryManager
116   ///        functor.
117   ObjectLinkingLayer(
118       std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager)
119       : CreateMemoryManager(std::move(CreateMemoryManager)) {}
120
121   /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded and
122   ///        NotifyFinalized functors.
123   ObjectLinkingLayer(NotifyLoadedFtor NotifyLoaded,
124                      std::function<void(ObjSetHandleT)> NotifyFinalized)
125       : NotifyLoaded(std::move(NotifyLoaded)),
126         NotifyFinalized(std::move(NotifyFinalized)) {}
127
128   /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded and
129   ///        CreateMemoryManager functors.
130   ObjectLinkingLayer(
131       NotifyLoadedFtor NotifyLoaded,
132       std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager)
133       : NotifyLoaded(std::move(NotifyLoaded)),
134         CreateMemoryManager(std::move(CreateMemoryManager)) {}
135
136   /// @brief Construct an ObjectLinkingLayer with the given NotifyFinalized and
137   ///        CreateMemoryManager functors.
138   ObjectLinkingLayer(
139       std::function<void(ObjSetHandleT)> NotifyFinalized,
140       std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager)
141       : NotifyFinalized(std::move(NotifyFinalized)),
142         CreateMemoryManager(std::move(CreateMemoryManager)) {}
143
144   /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
145   ///        NotifyFinalized and CreateMemoryManager functors.
146   ObjectLinkingLayer(
147       NotifyLoadedFtor NotifyLoaded,
148       std::function<void(ObjSetHandleT)> NotifyFinalized,
149       std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager)
150       : NotifyLoaded(std::move(NotifyLoaded)),
151         NotifyFinalized(std::move(NotifyFinalized)),
152         CreateMemoryManager(std::move(CreateMemoryManager)) {}
153
154   /// @brief Add a set of objects (or archives) that will be treated as a unit
155   ///        for the purposes of symbol lookup and memory management.
156   ///
157   /// @return A pair containing (1) A handle that can be used to free the memory
158   ///         allocated for the objects, and (2) a LoadedObjInfoList containing
159   ///         one LoadedObjInfo instance for each object at the corresponding
160   ///         index in the Objects list.
161   ///
162   ///   This version of this method allows the client to pass in an
163   /// RTDyldMemoryManager instance that will be used to allocate memory and look
164   /// up external symbol addresses for the given objects.
165   template <typename ObjSetT>
166   ObjSetHandleT addObjectSet(const ObjSetT &Objects,
167                              std::unique_ptr<RTDyldMemoryManager> MM) {
168
169     if (!MM) {
170       assert(CreateMemoryManager &&
171              "No memory manager or memory manager creator provided.");
172       MM = CreateMemoryManager();
173     }
174
175     ObjSetHandleT Handle = LinkedObjSetList.insert(
176         LinkedObjSetList.end(), LinkedObjectSet(std::move(MM)));
177     LinkedObjectSet &LOS = *Handle;
178     LoadedObjInfoList LoadedObjInfos;
179
180     for (auto &Obj : Objects)
181       LoadedObjInfos.push_back(LOS.addObject(*Obj));
182
183     NotifyLoaded(Handle, Objects, LoadedObjInfos);
184
185     return Handle;
186   }
187
188   /// @brief Map section addresses for the objects associated with the handle H.
189   void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
190                          uint64_t TargetAddress) {
191     H->mapSectionAddress(LocalAddress, TargetAddress);
192   }
193
194   /// @brief Remove the set of objects associated with handle H.
195   ///
196   ///   All memory allocated for the objects will be freed, and the sections and
197   /// symbols they provided will no longer be available. No attempt is made to
198   /// re-emit the missing symbols, and any use of these symbols (directly or
199   /// indirectly) will result in undefined behavior. If dependence tracking is
200   /// required to detect or resolve such issues it should be added at a higher
201   /// layer.
202   void removeObjectSet(ObjSetHandleT H) {
203     // How do we invalidate the symbols in H?
204     LinkedObjSetList.erase(H);
205   }
206
207   /// @brief Get the address of a loaded symbol.
208   ///
209   /// @return The address in the target process's address space of the named
210   ///         symbol. Null if no such symbol is known.
211   ///
212   ///   This method will trigger the finalization of the linked object set
213   /// containing the definition of the given symbol, if it is found.
214   uint64_t getSymbolAddress(StringRef Name, bool ExportedSymbolsOnly) {
215     for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
216          ++I)
217       if (uint64_t Addr = lookupSymbolAddressIn(I, Name, ExportedSymbolsOnly))
218         return Addr;
219
220     return 0;
221   }
222
223   /// @brief Search for a given symbol in the context of the set of loaded
224   ///        objects represented by the handle H.
225   ///
226   /// @return The address in the target process's address space of the named
227   ///         symbol. Null if the given object set does not contain a definition
228   ///         of this symbol.
229   ///
230   ///   This method will trigger the finalization of the linked object set
231   /// represented by the handle H if that set contains the requested symbol.
232   uint64_t lookupSymbolAddressIn(ObjSetHandleT H, StringRef Name,
233                                  bool ExportedSymbolsOnly) {
234     if (uint64_t Addr = H->getSymbolAddress(Name, ExportedSymbolsOnly)) {
235       if (H->NeedsFinalization()) {
236         H->Finalize();
237         if (NotifyFinalized)
238           NotifyFinalized(H);
239       }
240       return Addr;
241     }
242     return 0;
243   }
244
245 private:
246   LinkedObjectSetListT LinkedObjSetList;
247   NotifyLoadedFtor NotifyLoaded;
248   std::function<void(ObjSetHandleT)> NotifyFinalized;
249   std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager;
250 };
251
252 } // end namespace llvm
253
254 #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H