[Orc] Add missing #include. Hopefully this will appease the modules buildbots.
[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 "JITSymbol.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ExecutionEngine/ExecutionEngine.h"
20 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
21 #include <list>
22 #include <memory>
23
24 namespace llvm {
25 namespace orc {
26
27 class ObjectLinkingLayerBase {
28 protected:
29
30   /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
31   ///
32   /// An instance of this class will be created for each set of objects added
33   /// via JITObjectLayer::addObjectSet. Deleting the instance (via
34   /// removeObjectSet) frees its memory, removing all symbol definitions that
35   /// had been provided by this instance. Higher level layers are responsible
36   /// for taking any action required to handle the missing symbols.
37   class LinkedObjectSet {
38     LinkedObjectSet(const LinkedObjectSet&) = delete;
39     void operator=(const LinkedObjectSet&) = delete;
40   public:
41     LinkedObjectSet(RuntimeDyld::MemoryManager &MemMgr,
42                     RuntimeDyld::SymbolResolver &Resolver)
43         : RTDyld(llvm::make_unique<RuntimeDyld>(MemMgr, Resolver)),
44           State(Raw) {}
45
46     virtual ~LinkedObjectSet() {}
47
48     std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
49     addObject(const object::ObjectFile &Obj) {
50       return RTDyld->loadObject(Obj);
51     }
52
53     RuntimeDyld::SymbolInfo getSymbol(StringRef Name) const {
54       return RTDyld->getSymbol(Name);
55     }
56
57     bool NeedsFinalization() const { return (State == Raw); }
58
59     virtual void Finalize() = 0;
60
61     void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) {
62       assert((State != Finalized) &&
63              "Attempting to remap sections for finalized objects.");
64       RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
65     }
66
67     void takeOwnershipOfBuffer(std::unique_ptr<MemoryBuffer> B) {
68       OwnedBuffers.push_back(std::move(B));
69     }
70
71   protected:
72     std::unique_ptr<RuntimeDyld> RTDyld;
73     enum { Raw, Finalizing, Finalized } State;
74
75     // FIXME: This ownership hack only exists because RuntimeDyldELF still
76     //        wants to be able to inspect the original object when resolving
77     //        relocations. As soon as that can be fixed this should be removed.
78     std::vector<std::unique_ptr<MemoryBuffer>> OwnedBuffers;
79   };
80
81   typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT;
82
83 public:
84   /// @brief Handle to a set of loaded objects.
85   typedef LinkedObjectSetListT::iterator ObjSetHandleT;
86
87   // Ownership hack.
88   // FIXME: Remove this as soon as RuntimeDyldELF can apply relocations without
89   //        referencing the original object.
90   template <typename OwningMBSet>
91   void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs) {
92     for (auto &MB : MBs)
93       (*H)->takeOwnershipOfBuffer(std::move(MB));
94   }
95
96 };
97
98 /// @brief Default (no-op) action to perform when loading objects.
99 class DoNothingOnNotifyLoaded {
100 public:
101   template <typename ObjSetT, typename LoadResult>
102   void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &,
103                   const LoadResult &) {}
104 };
105
106 /// @brief Bare bones object linking layer.
107 ///
108 ///   This class is intended to be used as the base layer for a JIT. It allows
109 /// object files to be loaded into memory, linked, and the addresses of their
110 /// symbols queried. All objects added to this layer can see each other's
111 /// symbols.
112 template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
113 class ObjectLinkingLayer : public ObjectLinkingLayerBase {
114 private:
115
116   template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
117   class ConcreteLinkedObjectSet : public LinkedObjectSet {
118   public:
119     ConcreteLinkedObjectSet(MemoryManagerPtrT MemMgr,
120                             SymbolResolverPtrT Resolver)
121       : LinkedObjectSet(*MemMgr, *Resolver), MemMgr(std::move(MemMgr)),
122         Resolver(std::move(Resolver)) { }
123
124     void Finalize() override {
125       State = Finalizing;
126       RTDyld->resolveRelocations();
127       RTDyld->registerEHFrames();
128       MemMgr->finalizeMemory();
129       OwnedBuffers.clear();
130       State = Finalized;
131     }
132
133   private:
134     MemoryManagerPtrT MemMgr;
135     SymbolResolverPtrT Resolver;
136   };
137
138   template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
139   std::unique_ptr<LinkedObjectSet>
140   createLinkedObjectSet(MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver) {
141     typedef ConcreteLinkedObjectSet<MemoryManagerPtrT, SymbolResolverPtrT> LOS;
142     return llvm::make_unique<LOS>(std::move(MemMgr), std::move(Resolver));
143   }
144
145 public:
146
147   /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
148   ///        RuntimeDyld::LoadedObjectInfo instances.
149   typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
150       LoadedObjInfoList;
151
152   /// @brief Functor for receiving finalization notifications.
153   typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
154
155   /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
156   ///        and NotifyFinalized functors.
157   ObjectLinkingLayer(
158       NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
159       NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
160       : NotifyLoaded(std::move(NotifyLoaded)),
161         NotifyFinalized(std::move(NotifyFinalized)) {}
162
163   /// @brief Add a set of objects (or archives) that will be treated as a unit
164   ///        for the purposes of symbol lookup and memory management.
165   ///
166   /// @return A pair containing (1) A handle that can be used to free the memory
167   ///         allocated for the objects, and (2) a LoadedObjInfoList containing
168   ///         one LoadedObjInfo instance for each object at the corresponding
169   ///         index in the Objects list.
170   ///
171   ///   This version of this method allows the client to pass in an
172   /// RTDyldMemoryManager instance that will be used to allocate memory and look
173   /// up external symbol addresses for the given objects.
174   template <typename ObjSetT,
175             typename MemoryManagerPtrT,
176             typename SymbolResolverPtrT>
177   ObjSetHandleT addObjectSet(const ObjSetT &Objects,
178                              MemoryManagerPtrT MemMgr,
179                              SymbolResolverPtrT Resolver) {
180     ObjSetHandleT Handle =
181       LinkedObjSetList.insert(
182         LinkedObjSetList.end(),
183         createLinkedObjectSet(std::move(MemMgr), std::move(Resolver)));
184
185     LinkedObjectSet &LOS = **Handle;
186     LoadedObjInfoList LoadedObjInfos;
187
188     for (auto &Obj : Objects)
189       LoadedObjInfos.push_back(LOS.addObject(*Obj));
190
191     NotifyLoaded(Handle, Objects, LoadedObjInfos);
192
193     return Handle;
194   }
195
196   /// @brief Remove the set of objects associated with handle H.
197   ///
198   ///   All memory allocated for the objects will be freed, and the sections and
199   /// symbols they provided will no longer be available. No attempt is made to
200   /// re-emit the missing symbols, and any use of these symbols (directly or
201   /// indirectly) will result in undefined behavior. If dependence tracking is
202   /// required to detect or resolve such issues it should be added at a higher
203   /// layer.
204   void removeObjectSet(ObjSetHandleT H) {
205     // How do we invalidate the symbols in H?
206     LinkedObjSetList.erase(H);
207   }
208
209   /// @brief Search for the given named symbol.
210   /// @param Name The name of the symbol to search for.
211   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
212   /// @return A handle for the given named symbol, if it exists.
213   JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
214     for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
215          ++I)
216       if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly))
217         return Symbol;
218
219     return nullptr;
220   }
221
222   /// @brief Search for the given named symbol in the context of the set of
223   ///        loaded objects represented by the handle H.
224   /// @param H The handle for the object set to search in.
225   /// @param Name The name of the symbol to search for.
226   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
227   /// @return A handle for the given named symbol, if it is found in the
228   ///         given object set.
229   JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name,
230                          bool ExportedSymbolsOnly) {
231     if (auto Sym = (*H)->getSymbol(Name)) {
232       if (Sym.isExported() || !ExportedSymbolsOnly) {
233         auto Addr = Sym.getAddress();
234         auto Flags = Sym.getFlags();
235         if (!(*H)->NeedsFinalization()) {
236           // If this instance has already been finalized then we can just return
237           // the address.
238           return JITSymbol(Addr, Flags);
239         } else {
240           // If this instance needs finalization return a functor that will do
241           // it. The functor still needs to double-check whether finalization is
242           // required, in case someone else finalizes this set before the
243           // functor is called.
244           auto GetAddress =
245             [this, Addr, H]() {
246               if ((*H)->NeedsFinalization()) {
247                 (*H)->Finalize();
248                 if (NotifyFinalized)
249                   NotifyFinalized(H);
250               }
251               return Addr;
252             };
253           return JITSymbol(std::move(GetAddress), Flags);
254         }
255       }
256     }
257     return nullptr;
258   }
259
260   /// @brief Map section addresses for the objects associated with the handle H.
261   void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
262                          TargetAddress TargetAddr) {
263     (*H)->mapSectionAddress(LocalAddress, TargetAddr);
264   }
265
266   /// @brief Immediately emit and finalize the object set represented by the
267   ///        given handle.
268   /// @param H Handle for object set to emit/finalize.
269   void emitAndFinalize(ObjSetHandleT H) {
270     (*H)->Finalize();
271     if (NotifyFinalized)
272       NotifyFinalized(H);
273   }
274
275 private:
276   LinkedObjectSetListT LinkedObjSetList;
277   NotifyLoadedFtor NotifyLoaded;
278   NotifyFinalizedFtor NotifyFinalized;
279 };
280
281 } // End namespace orc.
282 } // End namespace llvm
283
284 #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H