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