llvm.org GIT mirror llvm / 67191c1
[Orc] Rename ObjectLinkingLayer -> RTDyldObjectLinkingLayer. The current ObjectLinkingLayer (now RTDyldObjectLinkingLayer) links objects in-process using MCJIT's RuntimeDyld class. In the near future I hope to add new object linking layers (e.g. a remote linking layer that links objects in the JIT target process, rather than the client), so I'm renaming this class to be more descriptive. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@295636 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 2 years ago
9 changed file(s) with 620 addition(s) and 620 deletion(s). Raw diff Collapse all Expand all
+0
-362
include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h less more
None //===- ObjectLinkingLayer.h - Add object files to a JIT process -*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Contains the definition for the object layer of the JIT.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
14 #define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
15
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ExecutionEngine/ExecutionEngine.h"
20 #include "llvm/ExecutionEngine/JITSymbol.h"
21 #include "llvm/ExecutionEngine/RuntimeDyld.h"
22 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
23 #include "llvm/Object/ObjectFile.h"
24 #include "llvm/Support/Error.h"
25 #include
26 #include
27 #include
28 #include
29 #include
30 #include
31 #include
32 #include
33
34 namespace llvm {
35 namespace orc {
36
37 class ObjectLinkingLayerBase {
38 protected:
39 /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
40 ///
41 /// An instance of this class will be created for each set of objects added
42 /// via JITObjectLayer::addObjectSet. Deleting the instance (via
43 /// removeObjectSet) frees its memory, removing all symbol definitions that
44 /// had been provided by this instance. Higher level layers are responsible
45 /// for taking any action required to handle the missing symbols.
46 class LinkedObjectSet {
47 public:
48 LinkedObjectSet() = default;
49 LinkedObjectSet(const LinkedObjectSet&) = delete;
50 void operator=(const LinkedObjectSet&) = delete;
51 virtual ~LinkedObjectSet() = default;
52
53 virtual void finalize() = 0;
54
55 virtual JITSymbol::GetAddressFtor
56 getSymbolMaterializer(std::string Name) = 0;
57
58 virtual void mapSectionAddress(const void *LocalAddress,
59 JITTargetAddress TargetAddr) const = 0;
60
61 JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
62 auto SymEntry = SymbolTable.find(Name);
63 if (SymEntry == SymbolTable.end())
64 return nullptr;
65 if (!SymEntry->second.getFlags().isExported() && ExportedSymbolsOnly)
66 return nullptr;
67 if (!Finalized)
68 return JITSymbol(getSymbolMaterializer(Name),
69 SymEntry->second.getFlags());
70 return JITSymbol(SymEntry->second);
71 }
72
73 protected:
74 StringMap SymbolTable;
75 bool Finalized = false;
76 };
77
78 typedef std::list> LinkedObjectSetListT;
79
80 public:
81 /// @brief Handle to a set of loaded objects.
82 typedef LinkedObjectSetListT::iterator ObjSetHandleT;
83 };
84
85 /// @brief Default (no-op) action to perform when loading objects.
86 class DoNothingOnNotifyLoaded {
87 public:
88 template
89 void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &,
90 const LoadResult &) {}
91 };
92
93 /// @brief Bare bones object linking layer.
94 ///
95 /// This class is intended to be used as the base layer for a JIT. It allows
96 /// object files to be loaded into memory, linked, and the addresses of their
97 /// symbols queried. All objects added to this layer can see each other's
98 /// symbols.
99 template
100 class ObjectLinkingLayer : public ObjectLinkingLayerBase {
101 public:
102 /// @brief Functor for receiving finalization notifications.
103 typedef std::function NotifyFinalizedFtor;
104
105 private:
106 template
107 typename SymbolResolverPtrT, typename FinalizerFtor>
108 class ConcreteLinkedObjectSet : public LinkedObjectSet {
109 public:
110 ConcreteLinkedObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
111 SymbolResolverPtrT Resolver,
112 FinalizerFtor Finalizer,
113 bool ProcessAllSections)
114 : MemMgr(std::move(MemMgr)),
115 PFC(llvm::make_unique(std::move(Objects),
116 std::move(Resolver),
117 std::move(Finalizer),
118 ProcessAllSections)) {
119 buildInitialSymbolTable(PFC->Objects);
120 }
121
122 void setHandle(ObjSetHandleT H) {
123 PFC->Handle = H;
124 }
125
126 void finalize() override {
127 assert(PFC && "mapSectionAddress called on finalized LinkedObjectSet");
128
129 RuntimeDyld RTDyld(*MemMgr, *PFC->Resolver);
130 RTDyld.setProcessAllSections(PFC->ProcessAllSections);
131 PFC->RTDyld = &RTDyld;
132
133 this->Finalized = true;
134 PFC->Finalizer(PFC->Handle, RTDyld, std::move(PFC->Objects),
135 [&]() {
136 this->updateSymbolTable(RTDyld);
137 });
138
139 // Release resources.
140 PFC = nullptr;
141 }
142
143 JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
144 return
145 [this, Name]() {
146 // The symbol may be materialized between the creation of this lambda
147 // and its execution, so we need to double check.
148 if (!this->Finalized)
149 this->finalize();
150 return this->getSymbol(Name, false).getAddress();
151 };
152 }
153
154 void mapSectionAddress(const void *LocalAddress,
155 JITTargetAddress TargetAddr) const override {
156 assert(PFC && "mapSectionAddress called on finalized LinkedObjectSet");
157 assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObjectSet");
158 PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
159 }
160
161 private:
162 void buildInitialSymbolTable(const ObjSetT &Objects) {
163 for (const auto &Obj : Objects)
164 for (auto &Symbol : getObject(*Obj).symbols()) {
165 if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
166 continue;
167 Expected SymbolName = Symbol.getName();
168 // FIXME: Raise an error for bad symbols.
169 if (!SymbolName) {
170 consumeError(SymbolName.takeError());
171 continue;
172 }
173 auto Flags = JITSymbolFlags::fromObjectSymbol(Symbol);
174 SymbolTable.insert(
175 std::make_pair(*SymbolName, JITEvaluatedSymbol(0, Flags)));
176 }
177 }
178
179 void updateSymbolTable(const RuntimeDyld &RTDyld) {
180 for (auto &SymEntry : SymbolTable)
181 SymEntry.second = RTDyld.getSymbol(SymEntry.first());
182 }
183
184 // Contains the information needed prior to finalization: the object files,
185 // memory manager, resolver, and flags needed for RuntimeDyld.
186 struct PreFinalizeContents {
187 PreFinalizeContents(ObjSetT Objects, SymbolResolverPtrT Resolver,
188 FinalizerFtor Finalizer, bool ProcessAllSections)
189 : Objects(std::move(Objects)), Resolver(std::move(Resolver)),
190 Finalizer(std::move(Finalizer)),
191 ProcessAllSections(ProcessAllSections) {}
192
193 ObjSetT Objects;
194 SymbolResolverPtrT Resolver;
195 FinalizerFtor Finalizer;
196 bool ProcessAllSections;
197 ObjSetHandleT Handle;
198 RuntimeDyld *RTDyld;
199 };
200
201 MemoryManagerPtrT MemMgr;
202 std::unique_ptr PFC;
203 };
204
205 template
206 typename SymbolResolverPtrT, typename FinalizerFtor>
207 std::unique_ptr<
208 ConcreteLinkedObjectSet
209 SymbolResolverPtrT, FinalizerFtor>>
210 createLinkedObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
211 SymbolResolverPtrT Resolver,
212 FinalizerFtor Finalizer,
213 bool ProcessAllSections) {
214 typedef ConcreteLinkedObjectSet
215 SymbolResolverPtrT, FinalizerFtor> LOS;
216 return llvm::make_unique(std::move(Objects), std::move(MemMgr),
217 std::move(Resolver), std::move(Finalizer),
218 ProcessAllSections);
219 }
220
221 public:
222 /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
223 /// RuntimeDyld::LoadedObjectInfo instances.
224 typedef std::vector>
225 LoadedObjInfoList;
226
227 /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
228 /// and NotifyFinalized functors.
229 ObjectLinkingLayer(
230 NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
231 NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
232 : NotifyLoaded(std::move(NotifyLoaded)),
233 NotifyFinalized(std::move(NotifyFinalized)),
234 ProcessAllSections(false) {}
235
236 /// @brief Set the 'ProcessAllSections' flag.
237 ///
238 /// If set to true, all sections in each object file will be allocated using
239 /// the memory manager, rather than just the sections required for execution.
240 ///
241 /// This is kludgy, and may be removed in the future.
242 void setProcessAllSections(bool ProcessAllSections) {
243 this->ProcessAllSections = ProcessAllSections;
244 }
245
246 /// @brief Add a set of objects (or archives) that will be treated as a unit
247 /// for the purposes of symbol lookup and memory management.
248 ///
249 /// @return A handle that can be used to refer to the loaded objects (for
250 /// symbol searching, finalization, freeing memory, etc.).
251 template
252 typename MemoryManagerPtrT,
253 typename SymbolResolverPtrT>
254 ObjSetHandleT addObjectSet(ObjSetT Objects,
255 MemoryManagerPtrT MemMgr,
256 SymbolResolverPtrT Resolver) {
257 auto Finalizer = [&](ObjSetHandleT H, RuntimeDyld &RTDyld,
258 const ObjSetT &Objs,
259 std::function LOSHandleLoad) {
260 LoadedObjInfoList LoadedObjInfos;
261
262 for (auto &Obj : Objs)
263 LoadedObjInfos.push_back(RTDyld.loadObject(this->getObject(*Obj)));
264
265 LOSHandleLoad();
266
267 this->NotifyLoaded(H, Objs, LoadedObjInfos);
268
269 RTDyld.finalizeWithMemoryManagerLocking();
270
271 if (this->NotifyFinalized)
272 this->NotifyFinalized(H);
273 };
274
275 auto LOS =
276 createLinkedObjectSet(std::move(Objects), std::move(MemMgr),
277 std::move(Resolver), std::move(Finalizer),
278 ProcessAllSections);
279 // LOS is an owning-ptr. Keep a non-owning one so that we can set the handle
280 // below.
281 auto *LOSPtr = LOS.get();
282
283 ObjSetHandleT Handle = LinkedObjSetList.insert(LinkedObjSetList.end(),
284 std::move(LOS));
285 LOSPtr->setHandle(Handle);
286
287 return Handle;
288 }
289
290 /// @brief Remove the set of objects associated with handle H.
291 ///
292 /// All memory allocated for the objects will be freed, and the sections and
293 /// symbols they provided will no longer be available. No attempt is made to
294 /// re-emit the missing symbols, and any use of these symbols (directly or
295 /// indirectly) will result in undefined behavior. If dependence tracking is
296 /// required to detect or resolve such issues it should be added at a higher
297 /// layer.
298 void removeObjectSet(ObjSetHandleT H) {
299 // How do we invalidate the symbols in H?
300 LinkedObjSetList.erase(H);
301 }
302
303 /// @brief Search for the given named symbol.
304 /// @param Name The name of the symbol to search for.
305 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
306 /// @return A handle for the given named symbol, if it exists.
307 JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
308 for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
309 ++I)
310 if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly))
311 return Symbol;
312
313 return nullptr;
314 }
315
316 /// @brief Search for the given named symbol in the context of the set of
317 /// loaded objects represented by the handle H.
318 /// @param H The handle for the object set to search in.
319 /// @param Name The name of the symbol to search for.
320 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
321 /// @return A handle for the given named symbol, if it is found in the
322 /// given object set.
323 JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name,
324 bool ExportedSymbolsOnly) {
325 return (*H)->getSymbol(Name, ExportedSymbolsOnly);
326 }
327
328 /// @brief Map section addresses for the objects associated with the handle H.
329 void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
330 JITTargetAddress TargetAddr) {
331 (*H)->mapSectionAddress(LocalAddress, TargetAddr);
332 }
333
334 /// @brief Immediately emit and finalize the object set represented by the
335 /// given handle.
336 /// @param H Handle for object set to emit/finalize.
337 void emitAndFinalize(ObjSetHandleT H) {
338 (*H)->finalize();
339 }
340
341 private:
342 static const object::ObjectFile& getObject(const object::ObjectFile &Obj) {
343 return Obj;
344 }
345
346 template
347 static const object::ObjectFile&
348 getObject(const object::OwningBinary &Obj) {
349 return *Obj.getBinary();
350 }
351
352 LinkedObjectSetListT LinkedObjSetList;
353 NotifyLoadedFtor NotifyLoaded;
354 NotifyFinalizedFtor NotifyFinalized;
355 bool ProcessAllSections;
356 };
357
358 } // end namespace orc
359 } // end namespace llvm
360
361 #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
0 //===-- RTDyldObjectLinkingLayer.h - RTDyld-based jit linking --*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Contains the definition for an RTDyld-based, in-process object linking layer.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
14 #define LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
15
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ExecutionEngine/ExecutionEngine.h"
20 #include "llvm/ExecutionEngine/JITSymbol.h"
21 #include "llvm/ExecutionEngine/RuntimeDyld.h"
22 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
23 #include "llvm/Object/ObjectFile.h"
24 #include "llvm/Support/Error.h"
25 #include
26 #include
27 #include
28 #include
29 #include
30 #include
31 #include
32 #include
33
34 namespace llvm {
35 namespace orc {
36
37 class RTDyldObjectLinkingLayerBase {
38 protected:
39 /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
40 ///
41 /// An instance of this class will be created for each set of objects added
42 /// via JITObjectLayer::addObjectSet. Deleting the instance (via
43 /// removeObjectSet) frees its memory, removing all symbol definitions that
44 /// had been provided by this instance. Higher level layers are responsible
45 /// for taking any action required to handle the missing symbols.
46 class LinkedObjectSet {
47 public:
48 LinkedObjectSet() = default;
49 LinkedObjectSet(const LinkedObjectSet&) = delete;
50 void operator=(const LinkedObjectSet&) = delete;
51 virtual ~LinkedObjectSet() = default;
52
53 virtual void finalize() = 0;
54
55 virtual JITSymbol::GetAddressFtor
56 getSymbolMaterializer(std::string Name) = 0;
57
58 virtual void mapSectionAddress(const void *LocalAddress,
59 JITTargetAddress TargetAddr) const = 0;
60
61 JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
62 auto SymEntry = SymbolTable.find(Name);
63 if (SymEntry == SymbolTable.end())
64 return nullptr;
65 if (!SymEntry->second.getFlags().isExported() && ExportedSymbolsOnly)
66 return nullptr;
67 if (!Finalized)
68 return JITSymbol(getSymbolMaterializer(Name),
69 SymEntry->second.getFlags());
70 return JITSymbol(SymEntry->second);
71 }
72
73 protected:
74 StringMap SymbolTable;
75 bool Finalized = false;
76 };
77
78 typedef std::list> LinkedObjectSetListT;
79
80 public:
81 /// @brief Handle to a set of loaded objects.
82 typedef LinkedObjectSetListT::iterator ObjSetHandleT;
83 };
84
85 /// @brief Default (no-op) action to perform when loading objects.
86 class DoNothingOnNotifyLoaded {
87 public:
88 template
89 void operator()(RTDyldObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &,
90 const LoadResult &) {}
91 };
92
93 /// @brief Bare bones object linking layer.
94 ///
95 /// This class is intended to be used as the base layer for a JIT. It allows
96 /// object files to be loaded into memory, linked, and the addresses of their
97 /// symbols queried. All objects added to this layer can see each other's
98 /// symbols.
99 template
100 class RTDyldObjectLinkingLayer : public RTDyldObjectLinkingLayerBase {
101 public:
102 /// @brief Functor for receiving finalization notifications.
103 typedef std::function NotifyFinalizedFtor;
104
105 private:
106 template
107 typename SymbolResolverPtrT, typename FinalizerFtor>
108 class ConcreteLinkedObjectSet : public LinkedObjectSet {
109 public:
110 ConcreteLinkedObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
111 SymbolResolverPtrT Resolver,
112 FinalizerFtor Finalizer,
113 bool ProcessAllSections)
114 : MemMgr(std::move(MemMgr)),
115 PFC(llvm::make_unique(std::move(Objects),
116 std::move(Resolver),
117 std::move(Finalizer),
118 ProcessAllSections)) {
119 buildInitialSymbolTable(PFC->Objects);
120 }
121
122 void setHandle(ObjSetHandleT H) {
123 PFC->Handle = H;
124 }
125
126 void finalize() override {
127 assert(PFC && "mapSectionAddress called on finalized LinkedObjectSet");
128
129 RuntimeDyld RTDyld(*MemMgr, *PFC->Resolver);
130 RTDyld.setProcessAllSections(PFC->ProcessAllSections);
131 PFC->RTDyld = &RTDyld;
132
133 this->Finalized = true;
134 PFC->Finalizer(PFC->Handle, RTDyld, std::move(PFC->Objects),
135 [&]() {
136 this->updateSymbolTable(RTDyld);
137 });
138
139 // Release resources.
140 PFC = nullptr;
141 }
142
143 JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
144 return
145 [this, Name]() {
146 // The symbol may be materialized between the creation of this lambda
147 // and its execution, so we need to double check.
148 if (!this->Finalized)
149 this->finalize();
150 return this->getSymbol(Name, false).getAddress();
151 };
152 }
153
154 void mapSectionAddress(const void *LocalAddress,
155 JITTargetAddress TargetAddr) const override {
156 assert(PFC && "mapSectionAddress called on finalized LinkedObjectSet");
157 assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObjectSet");
158 PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
159 }
160
161 private:
162 void buildInitialSymbolTable(const ObjSetT &Objects) {
163 for (const auto &Obj : Objects)
164 for (auto &Symbol : getObject(*Obj).symbols()) {
165 if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
166 continue;
167 Expected SymbolName = Symbol.getName();
168 // FIXME: Raise an error for bad symbols.
169 if (!SymbolName) {
170 consumeError(SymbolName.takeError());
171 continue;
172 }
173 auto Flags = JITSymbolFlags::fromObjectSymbol(Symbol);
174 SymbolTable.insert(
175 std::make_pair(*SymbolName, JITEvaluatedSymbol(0, Flags)));
176 }
177 }
178
179 void updateSymbolTable(const RuntimeDyld &RTDyld) {
180 for (auto &SymEntry : SymbolTable)
181 SymEntry.second = RTDyld.getSymbol(SymEntry.first());
182 }
183
184 // Contains the information needed prior to finalization: the object files,
185 // memory manager, resolver, and flags needed for RuntimeDyld.
186 struct PreFinalizeContents {
187 PreFinalizeContents(ObjSetT Objects, SymbolResolverPtrT Resolver,
188 FinalizerFtor Finalizer, bool ProcessAllSections)
189 : Objects(std::move(Objects)), Resolver(std::move(Resolver)),
190 Finalizer(std::move(Finalizer)),
191 ProcessAllSections(ProcessAllSections) {}
192
193 ObjSetT Objects;
194 SymbolResolverPtrT Resolver;
195 FinalizerFtor Finalizer;
196 bool ProcessAllSections;
197 ObjSetHandleT Handle;
198 RuntimeDyld *RTDyld;
199 };
200
201 MemoryManagerPtrT MemMgr;
202 std::unique_ptr PFC;
203 };
204
205 template
206 typename SymbolResolverPtrT, typename FinalizerFtor>
207 std::unique_ptr<
208 ConcreteLinkedObjectSet
209 SymbolResolverPtrT, FinalizerFtor>>
210 createLinkedObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
211 SymbolResolverPtrT Resolver,
212 FinalizerFtor Finalizer,
213 bool ProcessAllSections) {
214 typedef ConcreteLinkedObjectSet
215 SymbolResolverPtrT, FinalizerFtor> LOS;
216 return llvm::make_unique(std::move(Objects), std::move(MemMgr),
217 std::move(Resolver), std::move(Finalizer),
218 ProcessAllSections);
219 }
220
221 public:
222 /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
223 /// RuntimeDyld::LoadedObjectInfo instances.
224 typedef std::vector>
225 LoadedObjInfoList;
226
227 /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
228 /// and NotifyFinalized functors.
229 RTDyldObjectLinkingLayer(
230 NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
231 NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
232 : NotifyLoaded(std::move(NotifyLoaded)),
233 NotifyFinalized(std::move(NotifyFinalized)),
234 ProcessAllSections(false) {}
235
236 /// @brief Set the 'ProcessAllSections' flag.
237 ///
238 /// If set to true, all sections in each object file will be allocated using
239 /// the memory manager, rather than just the sections required for execution.
240 ///
241 /// This is kludgy, and may be removed in the future.
242 void setProcessAllSections(bool ProcessAllSections) {
243 this->ProcessAllSections = ProcessAllSections;
244 }
245
246 /// @brief Add a set of objects (or archives) that will be treated as a unit
247 /// for the purposes of symbol lookup and memory management.
248 ///
249 /// @return A handle that can be used to refer to the loaded objects (for
250 /// symbol searching, finalization, freeing memory, etc.).
251 template
252 typename MemoryManagerPtrT,
253 typename SymbolResolverPtrT>
254 ObjSetHandleT addObjectSet(ObjSetT Objects,
255 MemoryManagerPtrT MemMgr,
256 SymbolResolverPtrT Resolver) {
257 auto Finalizer = [&](ObjSetHandleT H, RuntimeDyld &RTDyld,
258 const ObjSetT &Objs,
259 std::function LOSHandleLoad) {
260 LoadedObjInfoList LoadedObjInfos;
261
262 for (auto &Obj : Objs)
263 LoadedObjInfos.push_back(RTDyld.loadObject(this->getObject(*Obj)));
264
265 LOSHandleLoad();
266
267 this->NotifyLoaded(H, Objs, LoadedObjInfos);
268
269 RTDyld.finalizeWithMemoryManagerLocking();
270
271 if (this->NotifyFinalized)
272 this->NotifyFinalized(H);
273 };
274
275 auto LOS =
276 createLinkedObjectSet(std::move(Objects), std::move(MemMgr),
277 std::move(Resolver), std::move(Finalizer),
278 ProcessAllSections);
279 // LOS is an owning-ptr. Keep a non-owning one so that we can set the handle
280 // below.
281 auto *LOSPtr = LOS.get();
282
283 ObjSetHandleT Handle = LinkedObjSetList.insert(LinkedObjSetList.end(),
284 std::move(LOS));
285 LOSPtr->setHandle(Handle);
286
287 return Handle;
288 }
289
290 /// @brief Remove the set of objects associated with handle H.
291 ///
292 /// All memory allocated for the objects will be freed, and the sections and
293 /// symbols they provided will no longer be available. No attempt is made to
294 /// re-emit the missing symbols, and any use of these symbols (directly or
295 /// indirectly) will result in undefined behavior. If dependence tracking is
296 /// required to detect or resolve such issues it should be added at a higher
297 /// layer.
298 void removeObjectSet(ObjSetHandleT H) {
299 // How do we invalidate the symbols in H?
300 LinkedObjSetList.erase(H);
301 }
302
303 /// @brief Search for the given named symbol.
304 /// @param Name The name of the symbol to search for.
305 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
306 /// @return A handle for the given named symbol, if it exists.
307 JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
308 for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
309 ++I)
310 if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly))
311 return Symbol;
312
313 return nullptr;
314 }
315
316 /// @brief Search for the given named symbol in the context of the set of
317 /// loaded objects represented by the handle H.
318 /// @param H The handle for the object set to search in.
319 /// @param Name The name of the symbol to search for.
320 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
321 /// @return A handle for the given named symbol, if it is found in the
322 /// given object set.
323 JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name,
324 bool ExportedSymbolsOnly) {
325 return (*H)->getSymbol(Name, ExportedSymbolsOnly);
326 }
327
328 /// @brief Map section addresses for the objects associated with the handle H.
329 void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
330 JITTargetAddress TargetAddr) {
331 (*H)->mapSectionAddress(LocalAddress, TargetAddr);
332 }
333
334 /// @brief Immediately emit and finalize the object set represented by the
335 /// given handle.
336 /// @param H Handle for object set to emit/finalize.
337 void emitAndFinalize(ObjSetHandleT H) {
338 (*H)->finalize();
339 }
340
341 private:
342 static const object::ObjectFile& getObject(const object::ObjectFile &Obj) {
343 return Obj;
344 }
345
346 template
347 static const object::ObjectFile&
348 getObject(const object::OwningBinary &Obj) {
349 return *Obj.getBinary();
350 }
351
352 LinkedObjectSetListT LinkedObjSetList;
353 NotifyLoadedFtor NotifyLoaded;
354 NotifyFinalizedFtor NotifyFinalized;
355 bool ProcessAllSections;
356 };
357
358 } // end namespace orc
359 } // end namespace llvm
360
361 #endif // LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
1515 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
1616 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
1717 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
18 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
18 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
1919 #include "llvm/IR/LLVMContext.h"
2020 #include "llvm/Support/Error.h"
2121
2929 class OrcCBindingsStack {
3030 public:
3131 typedef orc::JITCompileCallbackManager CompileCallbackMgr;
32 typedef orc::ObjectLinkingLayer<> ObjLayerT;
32 typedef orc::RTDyldObjectLinkingLayer<> ObjLayerT;
3333 typedef orc::IRCompileLayer CompileLayerT;
3434 typedef orc::CompileOnDemandLayer
3535 CODLayerT;
2323 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
2424 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
2525 #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
26 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
26 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
2727 #include "llvm/IR/Function.h"
2828 #include "llvm/IR/Mangler.h"
2929 #include "llvm/Object/Archive.h"
314314 NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {}
315315
316316 template
317 void operator()(ObjectLinkingLayerBase::ObjSetHandleT H,
317 void operator()(RTDyldObjectLinkingLayerBase::ObjSetHandleT H,
318318 const ObjListT &Objects,
319319 const LoadedObjInfoListT &Infos) const {
320320 M.UnfinalizedSections[H] = std::move(M.SectionsAllocatedSinceLastLoad);
343343 public:
344344 NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {}
345345
346 void operator()(ObjectLinkingLayerBase::ObjSetHandleT H) {
346 void operator()(RTDyldObjectLinkingLayerBase::ObjSetHandleT H) {
347347 M.UnfinalizedSections.erase(H);
348348 }
349349
360360 return MangledName;
361361 }
362362
363 typedef ObjectLinkingLayer ObjectLayerT;
363 typedef RTDyldObjectLinkingLayer ObjectLayerT;
364364 typedef IRCompileLayer CompileLayerT;
365365 typedef LazyEmittingLayer LazyEmitLayerT;
366366
2020 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
2121 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
2222 #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
23 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
23 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
2424 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
2525
2626 namespace llvm {
2929 public:
3030
3131 typedef orc::JITCompileCallbackManager CompileCallbackMgr;
32 typedef orc::ObjectLinkingLayer<> ObjLayerT;
32 typedef orc::RTDyldObjectLinkingLayer<> ObjLayerT;
3333 typedef orc::IRCompileLayer CompileLayerT;
3434 typedef std::function(std::unique_ptr)>
3535 TransformFtor;
1313 IndirectionUtilsTest.cpp
1414 GlobalMappingLayerTest.cpp
1515 LazyEmittingLayerTest.cpp
16 ObjectLinkingLayerTest.cpp
16 RTDyldObjectLinkingLayerTest.cpp
1717 ObjectTransformLayerTest.cpp
1818 OrcCAPITest.cpp
1919 OrcTestCommon.cpp
+0
-247
unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp less more
None //===-- ObjectLinkingLayerTest.cpp - Unit tests for object linking layer --===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "OrcTestCommon.h"
10 #include "llvm/ExecutionEngine/ExecutionEngine.h"
11 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
12 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
13 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
14 #include "llvm/ExecutionEngine/Orc/NullResolver.h"
15 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/LLVMContext.h"
18 #include "gtest/gtest.h"
19
20 using namespace llvm;
21 using namespace llvm::orc;
22
23 namespace {
24
25 class ObjectLinkingLayerExecutionTest : public testing::Test,
26 public OrcExecutionTest {
27
28 };
29
30 class SectionMemoryManagerWrapper : public SectionMemoryManager {
31 public:
32 int FinalizationCount = 0;
33 int NeedsToReserveAllocationSpaceCount = 0;
34
35 bool needsToReserveAllocationSpace() override {
36 ++NeedsToReserveAllocationSpaceCount;
37 return SectionMemoryManager::needsToReserveAllocationSpace();
38 }
39
40 bool finalizeMemory(std::string *ErrMsg = nullptr) override {
41 ++FinalizationCount;
42 return SectionMemoryManager::finalizeMemory(ErrMsg);
43 }
44 };
45
46 TEST(ObjectLinkingLayerTest, TestSetProcessAllSections) {
47 class SectionMemoryManagerWrapper : public SectionMemoryManager {
48 public:
49 SectionMemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {}
50 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
51 unsigned SectionID,
52 StringRef SectionName,
53 bool IsReadOnly) override {
54 if (SectionName == ".debug_str")
55 DebugSeen = true;
56 return SectionMemoryManager::allocateDataSection(Size, Alignment,
57 SectionID,
58 SectionName,
59 IsReadOnly);
60 }
61 private:
62 bool DebugSeen;
63 };
64
65 ObjectLinkingLayer<> ObjLayer;
66
67 LLVMContext Context;
68 auto M = llvm::make_unique("", Context);
69 M->setTargetTriple("x86_64-unknown-linux-gnu");
70 Type *Int32Ty = IntegerType::get(Context, 32);
71 GlobalVariable *GV =
72 new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
73 ConstantInt::get(Int32Ty, 42), "foo");
74
75 GV->setSection(".debug_str");
76
77 std::unique_ptr TM(
78 EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
79 SmallVector()));
80 if (!TM)
81 return;
82
83 auto OwningObj = SimpleCompiler(*TM)(*M);
84 std::vector Objs;
85 Objs.push_back(OwningObj.getBinary());
86
87 bool DebugSectionSeen = false;
88 SectionMemoryManagerWrapper SMMW(DebugSectionSeen);
89 auto Resolver =
90 createLambdaResolver(
91 [](const std::string &Name) {
92 return JITSymbol(nullptr);
93 },
94 [](const std::string &Name) {
95 return JITSymbol(nullptr);
96 });
97
98 {
99 // Test with ProcessAllSections = false (the default).
100 auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
101 EXPECT_EQ(DebugSectionSeen, false)
102 << "Unexpected debug info section";
103 ObjLayer.removeObjectSet(H);
104 }
105
106 {
107 // Test with ProcessAllSections = true.
108 ObjLayer.setProcessAllSections(true);
109 auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
110 EXPECT_EQ(DebugSectionSeen, true)
111 << "Expected debug info section not seen";
112 ObjLayer.removeObjectSet(H);
113 }
114 }
115
116 TEST_F(ObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
117 if (!TM)
118 return;
119
120 ObjectLinkingLayer<> ObjLayer;
121 SimpleCompiler Compile(*TM);
122
123 // Create a pair of modules that will trigger recursive finalization:
124 // Module 1:
125 // int bar() { return 42; }
126 // Module 2:
127 // int bar();
128 // int foo() { return bar(); }
129 //
130 // Verify that the memory manager is only finalized once (for Module 2).
131 // Failure suggests that finalize is being called on the inner RTDyld
132 // instance (for Module 1) which is unsafe, as it will prevent relocation of
133 // Module 2.
134
135 ModuleBuilder MB1(Context, "", "dummy");
136 {
137 MB1.getModule()->setDataLayout(TM->createDataLayout());
138 Function *BarImpl = MB1.createFunctionDecl("bar");
139 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
140 IRBuilder<> Builder(BarEntry);
141 IntegerType *Int32Ty = IntegerType::get(Context, 32);
142 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
143 Builder.CreateRet(FourtyTwo);
144 }
145
146 auto Obj1 = Compile(*MB1.getModule());
147 std::vector Obj1Set;
148 Obj1Set.push_back(Obj1.getBinary());
149
150 ModuleBuilder MB2(Context, "", "dummy");
151 {
152 MB2.getModule()->setDataLayout(TM->createDataLayout());
153 Function *BarDecl = MB2.createFunctionDecl("bar");
154 Function *FooImpl = MB2.createFunctionDecl("foo");
155 BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl);
156 IRBuilder<> Builder(FooEntry);
157 Builder.CreateRet(Builder.CreateCall(BarDecl));
158 }
159 auto Obj2 = Compile(*MB2.getModule());
160 std::vector Obj2Set;
161 Obj2Set.push_back(Obj2.getBinary());
162
163 auto Resolver =
164 createLambdaResolver(
165 [&](const std::string &Name) {
166 if (auto Sym = ObjLayer.findSymbol(Name, true))
167 return Sym;
168 return JITSymbol(nullptr);
169 },
170 [](const std::string &Name) {
171 return JITSymbol(nullptr);
172 });
173
174 SectionMemoryManagerWrapper SMMW;
175 ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &*Resolver);
176 auto H = ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &*Resolver);
177 ObjLayer.emitAndFinalize(H);
178
179 // Finalization of module 2 should trigger finalization of module 1.
180 // Verify that finalize on SMMW is only called once.
181 EXPECT_EQ(SMMW.FinalizationCount, 1)
182 << "Extra call to finalize";
183 }
184
185 TEST_F(ObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
186 if (!TM)
187 return;
188
189 ObjectLinkingLayer<> ObjLayer;
190 SimpleCompiler Compile(*TM);
191
192 // Create a pair of unrelated modules:
193 //
194 // Module 1:
195 // int foo() { return 42; }
196 // Module 2:
197 // int bar() { return 7; }
198 //
199 // Both modules will share a memory manager. We want to verify that the
200 // second object is not loaded before the first one is finalized. To do this
201 // in a portable way, we abuse the
202 // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
203 // called once per object before any sections are allocated.
204
205 ModuleBuilder MB1(Context, "", "dummy");
206 {
207 MB1.getModule()->setDataLayout(TM->createDataLayout());
208 Function *BarImpl = MB1.createFunctionDecl("foo");
209 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
210 IRBuilder<> Builder(BarEntry);
211 IntegerType *Int32Ty = IntegerType::get(Context, 32);
212 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
213 Builder.CreateRet(FourtyTwo);
214 }
215
216 auto Obj1 = Compile(*MB1.getModule());
217 std::vector Obj1Set;
218 Obj1Set.push_back(Obj1.getBinary());
219
220 ModuleBuilder MB2(Context, "", "dummy");
221 {
222 MB2.getModule()->setDataLayout(TM->createDataLayout());
223 Function *BarImpl = MB2.createFunctionDecl("bar");
224 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
225 IRBuilder<> Builder(BarEntry);
226 IntegerType *Int32Ty = IntegerType::get(Context, 32);
227 Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
228 Builder.CreateRet(Seven);
229 }
230 auto Obj2 = Compile(*MB2.getModule());
231 std::vector Obj2Set;
232 Obj2Set.push_back(Obj2.getBinary());
233
234 SectionMemoryManagerWrapper SMMW;
235 NullResolver NR;
236 auto H = ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &NR);
237 ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &NR);
238 ObjLayer.emitAndFinalize(H);
239
240 // Only one call to needsToReserveAllocationSpace should have been made.
241 EXPECT_EQ(SMMW.NeedsToReserveAllocationSpaceCount, 1)
242 << "More than one call to needsToReserveAllocationSpace "
243 "(multiple unrelated objects loaded prior to finalization)";
244 }
245
246 } // end anonymous namespace
1111 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
1212 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
1313 #include "llvm/ExecutionEngine/Orc/NullResolver.h"
14 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
14 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
1515 #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
1616 #include "llvm/Object/ObjectFile.h"
1717 #include "gtest/gtest.h"
308308 };
309309
310310 // Construct the jit layers.
311 ObjectLinkingLayer<> BaseLayer;
311 RTDyldObjectLinkingLayer<> BaseLayer;
312312 auto IdentityTransform = [](
313313 std::unique_ptr>
314314 Obj) { return Obj; };
0 //===- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer unit tests -===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "OrcTestCommon.h"
10 #include "llvm/ExecutionEngine/ExecutionEngine.h"
11 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
12 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
13 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
14 #include "llvm/ExecutionEngine/Orc/NullResolver.h"
15 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/LLVMContext.h"
18 #include "gtest/gtest.h"
19
20 using namespace llvm;
21 using namespace llvm::orc;
22
23 namespace {
24
25 class RTDyldObjectLinkingLayerExecutionTest : public testing::Test,
26 public OrcExecutionTest {
27
28 };
29
30 class SectionMemoryManagerWrapper : public SectionMemoryManager {
31 public:
32 int FinalizationCount = 0;
33 int NeedsToReserveAllocationSpaceCount = 0;
34
35 bool needsToReserveAllocationSpace() override {
36 ++NeedsToReserveAllocationSpaceCount;
37 return SectionMemoryManager::needsToReserveAllocationSpace();
38 }
39
40 bool finalizeMemory(std::string *ErrMsg = nullptr) override {
41 ++FinalizationCount;
42 return SectionMemoryManager::finalizeMemory(ErrMsg);
43 }
44 };
45
46 TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
47 class SectionMemoryManagerWrapper : public SectionMemoryManager {
48 public:
49 SectionMemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {}
50 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
51 unsigned SectionID,
52 StringRef SectionName,
53 bool IsReadOnly) override {
54 if (SectionName == ".debug_str")
55 DebugSeen = true;
56 return SectionMemoryManager::allocateDataSection(Size, Alignment,
57 SectionID,
58 SectionName,
59 IsReadOnly);
60 }
61 private:
62 bool DebugSeen;
63 };
64
65 RTDyldObjectLinkingLayer<> ObjLayer;
66
67 LLVMContext Context;
68 auto M = llvm::make_unique("", Context);
69 M->setTargetTriple("x86_64-unknown-linux-gnu");
70 Type *Int32Ty = IntegerType::get(Context, 32);
71 GlobalVariable *GV =
72 new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
73 ConstantInt::get(Int32Ty, 42), "foo");
74
75 GV->setSection(".debug_str");
76
77 std::unique_ptr TM(
78 EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
79 SmallVector()));
80 if (!TM)
81 return;
82
83 auto OwningObj = SimpleCompiler(*TM)(*M);
84 std::vector Objs;
85 Objs.push_back(OwningObj.getBinary());
86
87 bool DebugSectionSeen = false;
88 SectionMemoryManagerWrapper SMMW(DebugSectionSeen);
89 auto Resolver =
90 createLambdaResolver(
91 [](const std::string &Name) {
92 return JITSymbol(nullptr);
93 },
94 [](const std::string &Name) {
95 return JITSymbol(nullptr);
96 });
97
98 {
99 // Test with ProcessAllSections = false (the default).
100 auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
101 EXPECT_EQ(DebugSectionSeen, false)
102 << "Unexpected debug info section";
103 ObjLayer.removeObjectSet(H);
104 }
105
106 {
107 // Test with ProcessAllSections = true.
108 ObjLayer.setProcessAllSections(true);
109 auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
110 EXPECT_EQ(DebugSectionSeen, true)
111 << "Expected debug info section not seen";
112 ObjLayer.removeObjectSet(H);
113 }
114 }
115
116 TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
117 if (!TM)
118 return;
119
120 RTDyldObjectLinkingLayer<> ObjLayer;
121 SimpleCompiler Compile(*TM);
122
123 // Create a pair of modules that will trigger recursive finalization:
124 // Module 1:
125 // int bar() { return 42; }
126 // Module 2:
127 // int bar();
128 // int foo() { return bar(); }
129 //
130 // Verify that the memory manager is only finalized once (for Module 2).
131 // Failure suggests that finalize is being called on the inner RTDyld
132 // instance (for Module 1) which is unsafe, as it will prevent relocation of
133 // Module 2.
134
135 ModuleBuilder MB1(Context, "", "dummy");
136 {
137 MB1.getModule()->setDataLayout(TM->createDataLayout());
138 Function *BarImpl = MB1.createFunctionDecl("bar");
139 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
140 IRBuilder<> Builder(BarEntry);
141 IntegerType *Int32Ty = IntegerType::get(Context, 32);
142 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
143 Builder.CreateRet(FourtyTwo);
144 }
145
146 auto Obj1 = Compile(*MB1.getModule());
147 std::vector Obj1Set;
148 Obj1Set.push_back(Obj1.getBinary());
149
150 ModuleBuilder MB2(Context, "", "dummy");
151 {
152 MB2.getModule()->setDataLayout(TM->createDataLayout());
153 Function *BarDecl = MB2.createFunctionDecl("bar");
154 Function *FooImpl = MB2.createFunctionDecl("foo");
155 BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl);
156 IRBuilder<> Builder(FooEntry);
157 Builder.CreateRet(Builder.CreateCall(BarDecl));
158 }
159 auto Obj2 = Compile(*MB2.getModule());
160 std::vector Obj2Set;
161 Obj2Set.push_back(Obj2.getBinary());
162
163 auto Resolver =
164 createLambdaResolver(
165 [&](const std::string &Name) {
166 if (auto Sym = ObjLayer.findSymbol(Name, true))
167 return Sym;
168 return JITSymbol(nullptr);
169 },
170 [](const std::string &Name) {
171 return JITSymbol(nullptr);
172 });
173
174 SectionMemoryManagerWrapper SMMW;
175 ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &*Resolver);
176 auto H = ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &*Resolver);
177 ObjLayer.emitAndFinalize(H);
178
179 // Finalization of module 2 should trigger finalization of module 1.
180 // Verify that finalize on SMMW is only called once.
181 EXPECT_EQ(SMMW.FinalizationCount, 1)
182 << "Extra call to finalize";
183 }
184
185 TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
186 if (!TM)
187 return;
188
189 RTDyldObjectLinkingLayer<> ObjLayer;
190 SimpleCompiler Compile(*TM);
191
192 // Create a pair of unrelated modules:
193 //
194 // Module 1:
195 // int foo() { return 42; }
196 // Module 2:
197 // int bar() { return 7; }
198 //
199 // Both modules will share a memory manager. We want to verify that the
200 // second object is not loaded before the first one is finalized. To do this
201 // in a portable way, we abuse the
202 // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
203 // called once per object before any sections are allocated.
204
205 ModuleBuilder MB1(Context, "", "dummy");
206 {
207 MB1.getModule()->setDataLayout(TM->createDataLayout());
208 Function *BarImpl = MB1.createFunctionDecl("foo");
209 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
210 IRBuilder<> Builder(BarEntry);
211 IntegerType *Int32Ty = IntegerType::get(Context, 32);
212 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
213 Builder.CreateRet(FourtyTwo);
214 }
215
216 auto Obj1 = Compile(*MB1.getModule());
217 std::vector Obj1Set;
218 Obj1Set.push_back(Obj1.getBinary());
219
220 ModuleBuilder MB2(Context, "", "dummy");
221 {
222 MB2.getModule()->setDataLayout(TM->createDataLayout());
223 Function *BarImpl = MB2.createFunctionDecl("bar");
224 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
225 IRBuilder<> Builder(BarEntry);
226 IntegerType *Int32Ty = IntegerType::get(Context, 32);
227 Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
228 Builder.CreateRet(Seven);
229 }
230 auto Obj2 = Compile(*MB2.getModule());
231 std::vector Obj2Set;
232 Obj2Set.push_back(Obj2.getBinary());
233
234 SectionMemoryManagerWrapper SMMW;
235 NullResolver NR;
236 auto H = ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &NR);
237 ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &NR);
238 ObjLayer.emitAndFinalize(H);
239
240 // Only one call to needsToReserveAllocationSpace should have been made.
241 EXPECT_EQ(SMMW.NeedsToReserveAllocationSpaceCount, 1)
242 << "More than one call to needsToReserveAllocationSpace "
243 "(multiple unrelated objects loaded prior to finalization)";
244 }
245
246 } // end anonymous namespace