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