[Alignment][NFC] Use Align with TargetLowering::setMinFunctionAlignment
[llvm-core.git] / include / llvm / ExecutionEngine / Orc / RTDyldObjectLinkingLayer.h
blobc5106cf09ecc70e6c303bcf7ae001115cda70ad0
1 //===- RTDyldObjectLinkingLayer.h - RTDyld-based jit linking ---*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Contains the definition for an RTDyld-based, in-process object linking layer.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
14 #define LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ExecutionEngine/JITSymbol.h"
20 #include "llvm/ExecutionEngine/Orc/Core.h"
21 #include "llvm/ExecutionEngine/Orc/Layer.h"
22 #include "llvm/ExecutionEngine/Orc/Legacy.h"
23 #include "llvm/ExecutionEngine/RuntimeDyld.h"
24 #include "llvm/Object/ObjectFile.h"
25 #include "llvm/Support/Error.h"
26 #include <algorithm>
27 #include <cassert>
28 #include <functional>
29 #include <list>
30 #include <memory>
31 #include <string>
32 #include <utility>
33 #include <vector>
35 namespace llvm {
36 namespace orc {
38 class RTDyldObjectLinkingLayer : public ObjectLayer {
39 public:
40 /// Functor for receiving object-loaded notifications.
41 using NotifyLoadedFunction =
42 std::function<void(VModuleKey, const object::ObjectFile &Obj,
43 const RuntimeDyld::LoadedObjectInfo &)>;
45 /// Functor for receiving finalization notifications.
46 using NotifyEmittedFunction =
47 std::function<void(VModuleKey, std::unique_ptr<MemoryBuffer>)>;
49 using GetMemoryManagerFunction =
50 std::function<std::unique_ptr<RuntimeDyld::MemoryManager>()>;
52 /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
53 /// and NotifyEmitted functors.
54 RTDyldObjectLinkingLayer(ExecutionSession &ES,
55 GetMemoryManagerFunction GetMemoryManager);
57 /// Emit the object.
58 void emit(MaterializationResponsibility R,
59 std::unique_ptr<MemoryBuffer> O) override;
61 /// Set the NotifyLoaded callback.
62 RTDyldObjectLinkingLayer &setNotifyLoaded(NotifyLoadedFunction NotifyLoaded) {
63 this->NotifyLoaded = std::move(NotifyLoaded);
64 return *this;
67 /// Set the NotifyEmitted callback.
68 RTDyldObjectLinkingLayer &
69 setNotifyEmitted(NotifyEmittedFunction NotifyEmitted) {
70 this->NotifyEmitted = std::move(NotifyEmitted);
71 return *this;
74 /// Set the 'ProcessAllSections' flag.
75 ///
76 /// If set to true, all sections in each object file will be allocated using
77 /// the memory manager, rather than just the sections required for execution.
78 ///
79 /// This is kludgy, and may be removed in the future.
80 RTDyldObjectLinkingLayer &setProcessAllSections(bool ProcessAllSections) {
81 this->ProcessAllSections = ProcessAllSections;
82 return *this;
85 /// Instructs this RTDyldLinkingLayer2 instance to override the symbol flags
86 /// returned by RuntimeDyld for any given object file with the flags supplied
87 /// by the MaterializationResponsibility instance. This is a workaround to
88 /// support symbol visibility in COFF, which does not use the libObject's
89 /// SF_Exported flag. Use only when generating / adding COFF object files.
90 ///
91 /// FIXME: We should be able to remove this if/when COFF properly tracks
92 /// exported symbols.
93 RTDyldObjectLinkingLayer &
94 setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags) {
95 this->OverrideObjectFlags = OverrideObjectFlags;
96 return *this;
99 /// If set, this RTDyldObjectLinkingLayer instance will claim responsibility
100 /// for any symbols provided by a given object file that were not already in
101 /// the MaterializationResponsibility instance. Setting this flag allows
102 /// higher-level program representations (e.g. LLVM IR) to be added based on
103 /// only a subset of the symbols they provide, without having to write
104 /// intervening layers to scan and add the additional symbols. This trades
105 /// diagnostic quality for convenience however: If all symbols are enumerated
106 /// up-front then clashes can be detected and reported early (and usually
107 /// deterministically). If this option is set, clashes for the additional
108 /// symbols may not be detected until late, and detection may depend on
109 /// the flow of control through JIT'd code. Use with care.
110 RTDyldObjectLinkingLayer &
111 setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols) {
112 this->AutoClaimObjectSymbols = AutoClaimObjectSymbols;
113 return *this;
116 private:
117 Error onObjLoad(VModuleKey K, MaterializationResponsibility &R,
118 object::ObjectFile &Obj,
119 std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
120 std::map<StringRef, JITEvaluatedSymbol> Resolved,
121 std::set<StringRef> &InternalSymbols);
123 void onObjEmit(VModuleKey K, std::unique_ptr<MemoryBuffer> ObjBuffer,
124 MaterializationResponsibility &R, Error Err);
126 mutable std::mutex RTDyldLayerMutex;
127 GetMemoryManagerFunction GetMemoryManager;
128 NotifyLoadedFunction NotifyLoaded;
129 NotifyEmittedFunction NotifyEmitted;
130 bool ProcessAllSections = false;
131 bool OverrideObjectFlags = false;
132 bool AutoClaimObjectSymbols = false;
133 std::vector<std::unique_ptr<RuntimeDyld::MemoryManager>> MemMgrs;
136 class LegacyRTDyldObjectLinkingLayerBase {
137 public:
138 using ObjectPtr = std::unique_ptr<MemoryBuffer>;
140 protected:
142 /// Holds an object to be allocated/linked as a unit in the JIT.
144 /// An instance of this class will be created for each object added
145 /// via JITObjectLayer::addObject. Deleting the instance (via
146 /// removeObject) frees its memory, removing all symbol definitions that
147 /// had been provided by this instance. Higher level layers are responsible
148 /// for taking any action required to handle the missing symbols.
149 class LinkedObject {
150 public:
151 LinkedObject() = default;
152 LinkedObject(const LinkedObject&) = delete;
153 void operator=(const LinkedObject&) = delete;
154 virtual ~LinkedObject() = default;
156 virtual Error finalize() = 0;
158 virtual JITSymbol::GetAddressFtor
159 getSymbolMaterializer(std::string Name) = 0;
161 virtual void mapSectionAddress(const void *LocalAddress,
162 JITTargetAddress TargetAddr) const = 0;
164 JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
165 auto SymEntry = SymbolTable.find(Name);
166 if (SymEntry == SymbolTable.end())
167 return nullptr;
168 if (!SymEntry->second.getFlags().isExported() && ExportedSymbolsOnly)
169 return nullptr;
170 if (!Finalized)
171 return JITSymbol(getSymbolMaterializer(Name),
172 SymEntry->second.getFlags());
173 return JITSymbol(SymEntry->second);
176 protected:
177 StringMap<JITEvaluatedSymbol> SymbolTable;
178 bool Finalized = false;
182 /// Bare bones object linking layer.
184 /// This class is intended to be used as the base layer for a JIT. It allows
185 /// object files to be loaded into memory, linked, and the addresses of their
186 /// symbols queried. All objects added to this layer can see each other's
187 /// symbols.
188 class LegacyRTDyldObjectLinkingLayer : public LegacyRTDyldObjectLinkingLayerBase {
189 public:
191 using LegacyRTDyldObjectLinkingLayerBase::ObjectPtr;
193 /// Functor for receiving object-loaded notifications.
194 using NotifyLoadedFtor =
195 std::function<void(VModuleKey, const object::ObjectFile &Obj,
196 const RuntimeDyld::LoadedObjectInfo &)>;
198 /// Functor for receiving finalization notifications.
199 using NotifyFinalizedFtor =
200 std::function<void(VModuleKey, const object::ObjectFile &Obj,
201 const RuntimeDyld::LoadedObjectInfo &)>;
203 /// Functor for receiving deallocation notifications.
204 using NotifyFreedFtor = std::function<void(VModuleKey, const object::ObjectFile &Obj)>;
206 private:
207 using OwnedObject = object::OwningBinary<object::ObjectFile>;
209 template <typename MemoryManagerPtrT>
210 class ConcreteLinkedObject : public LinkedObject {
211 public:
212 ConcreteLinkedObject(LegacyRTDyldObjectLinkingLayer &Parent, VModuleKey K,
213 OwnedObject Obj, MemoryManagerPtrT MemMgr,
214 std::shared_ptr<SymbolResolver> Resolver,
215 bool ProcessAllSections)
216 : K(std::move(K)),
217 Parent(Parent),
218 MemMgr(std::move(MemMgr)),
219 PFC(std::make_unique<PreFinalizeContents>(
220 std::move(Obj), std::move(Resolver),
221 ProcessAllSections)) {
222 buildInitialSymbolTable(PFC->Obj);
225 ~ConcreteLinkedObject() override {
226 if (this->Parent.NotifyFreed && ObjForNotify.getBinary())
227 this->Parent.NotifyFreed(K, *ObjForNotify.getBinary());
229 MemMgr->deregisterEHFrames();
232 Error finalize() override {
233 assert(PFC && "mapSectionAddress called on finalized LinkedObject");
235 JITSymbolResolverAdapter ResolverAdapter(Parent.ES, *PFC->Resolver,
236 nullptr);
237 PFC->RTDyld = std::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter);
238 PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections);
240 Finalized = true;
242 std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info =
243 PFC->RTDyld->loadObject(*PFC->Obj.getBinary());
245 // Copy the symbol table out of the RuntimeDyld instance.
247 auto SymTab = PFC->RTDyld->getSymbolTable();
248 for (auto &KV : SymTab)
249 SymbolTable[KV.first] = KV.second;
252 if (Parent.NotifyLoaded)
253 Parent.NotifyLoaded(K, *PFC->Obj.getBinary(), *Info);
255 PFC->RTDyld->finalizeWithMemoryManagerLocking();
257 if (PFC->RTDyld->hasError())
258 return make_error<StringError>(PFC->RTDyld->getErrorString(),
259 inconvertibleErrorCode());
261 if (Parent.NotifyFinalized)
262 Parent.NotifyFinalized(K, *PFC->Obj.getBinary(), *Info);
264 // Release resources.
265 if (this->Parent.NotifyFreed)
266 ObjForNotify = std::move(PFC->Obj); // needed for callback
267 PFC = nullptr;
268 return Error::success();
271 JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
272 return [this, Name]() -> Expected<JITTargetAddress> {
273 // The symbol may be materialized between the creation of this lambda
274 // and its execution, so we need to double check.
275 if (!this->Finalized)
276 if (auto Err = this->finalize())
277 return std::move(Err);
278 return this->getSymbol(Name, false).getAddress();
282 void mapSectionAddress(const void *LocalAddress,
283 JITTargetAddress TargetAddr) const override {
284 assert(PFC && "mapSectionAddress called on finalized LinkedObject");
285 assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObject");
286 PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
289 private:
290 void buildInitialSymbolTable(const OwnedObject &Obj) {
291 for (auto &Symbol : Obj.getBinary()->symbols()) {
292 if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
293 continue;
294 Expected<StringRef> SymbolName = Symbol.getName();
295 // FIXME: Raise an error for bad symbols.
296 if (!SymbolName) {
297 consumeError(SymbolName.takeError());
298 continue;
300 // FIXME: Raise an error for bad symbols.
301 auto Flags = JITSymbolFlags::fromObjectSymbol(Symbol);
302 if (!Flags) {
303 consumeError(Flags.takeError());
304 continue;
306 SymbolTable.insert(
307 std::make_pair(*SymbolName, JITEvaluatedSymbol(0, *Flags)));
311 // Contains the information needed prior to finalization: the object files,
312 // memory manager, resolver, and flags needed for RuntimeDyld.
313 struct PreFinalizeContents {
314 PreFinalizeContents(OwnedObject Obj,
315 std::shared_ptr<SymbolResolver> Resolver,
316 bool ProcessAllSections)
317 : Obj(std::move(Obj)),
318 Resolver(std::move(Resolver)),
319 ProcessAllSections(ProcessAllSections) {}
321 OwnedObject Obj;
322 std::shared_ptr<SymbolResolver> Resolver;
323 bool ProcessAllSections;
324 std::unique_ptr<RuntimeDyld> RTDyld;
327 VModuleKey K;
328 LegacyRTDyldObjectLinkingLayer &Parent;
329 MemoryManagerPtrT MemMgr;
330 OwnedObject ObjForNotify;
331 std::unique_ptr<PreFinalizeContents> PFC;
334 template <typename MemoryManagerPtrT>
335 std::unique_ptr<ConcreteLinkedObject<MemoryManagerPtrT>>
336 createLinkedObject(LegacyRTDyldObjectLinkingLayer &Parent, VModuleKey K,
337 OwnedObject Obj, MemoryManagerPtrT MemMgr,
338 std::shared_ptr<SymbolResolver> Resolver,
339 bool ProcessAllSections) {
340 using LOS = ConcreteLinkedObject<MemoryManagerPtrT>;
341 return std::make_unique<LOS>(Parent, std::move(K), std::move(Obj),
342 std::move(MemMgr), std::move(Resolver),
343 ProcessAllSections);
346 public:
347 struct Resources {
348 std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr;
349 std::shared_ptr<SymbolResolver> Resolver;
352 using ResourcesGetter = std::function<Resources(VModuleKey)>;
354 /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
355 /// and NotifyFinalized functors.
356 LLVM_ATTRIBUTE_DEPRECATED(
357 LegacyRTDyldObjectLinkingLayer(
358 ExecutionSession &ES, ResourcesGetter GetResources,
359 NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
360 NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(),
361 NotifyFreedFtor NotifyFreed = NotifyFreedFtor()),
362 "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please "
363 "use "
364 "ORCv2 (see docs/ORCv2.rst)");
366 // Legacy layer constructor with deprecation acknowledgement.
367 LegacyRTDyldObjectLinkingLayer(
368 ORCv1DeprecationAcknowledgement, ExecutionSession &ES,
369 ResourcesGetter GetResources,
370 NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
371 NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(),
372 NotifyFreedFtor NotifyFreed = NotifyFreedFtor())
373 : ES(ES), GetResources(std::move(GetResources)),
374 NotifyLoaded(std::move(NotifyLoaded)),
375 NotifyFinalized(std::move(NotifyFinalized)),
376 NotifyFreed(std::move(NotifyFreed)), ProcessAllSections(false) {}
378 /// Set the 'ProcessAllSections' flag.
380 /// If set to true, all sections in each object file will be allocated using
381 /// the memory manager, rather than just the sections required for execution.
383 /// This is kludgy, and may be removed in the future.
384 void setProcessAllSections(bool ProcessAllSections) {
385 this->ProcessAllSections = ProcessAllSections;
388 /// Add an object to the JIT.
389 Error addObject(VModuleKey K, ObjectPtr ObjBuffer) {
391 auto Obj =
392 object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
393 if (!Obj)
394 return Obj.takeError();
396 assert(!LinkedObjects.count(K) && "VModuleKey already in use");
398 auto R = GetResources(K);
400 LinkedObjects[K] = createLinkedObject(
401 *this, K, OwnedObject(std::move(*Obj), std::move(ObjBuffer)),
402 std::move(R.MemMgr), std::move(R.Resolver), ProcessAllSections);
404 return Error::success();
407 /// Remove the object associated with VModuleKey K.
409 /// All memory allocated for the object will be freed, and the sections and
410 /// symbols it provided will no longer be available. No attempt is made to
411 /// re-emit the missing symbols, and any use of these symbols (directly or
412 /// indirectly) will result in undefined behavior. If dependence tracking is
413 /// required to detect or resolve such issues it should be added at a higher
414 /// layer.
415 Error removeObject(VModuleKey K) {
416 assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
417 // How do we invalidate the symbols in H?
418 LinkedObjects.erase(K);
419 return Error::success();
422 /// Search for the given named symbol.
423 /// @param Name The name of the symbol to search for.
424 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
425 /// @return A handle for the given named symbol, if it exists.
426 JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
427 for (auto &KV : LinkedObjects)
428 if (auto Sym = KV.second->getSymbol(Name, ExportedSymbolsOnly))
429 return Sym;
430 else if (auto Err = Sym.takeError())
431 return std::move(Err);
433 return nullptr;
436 /// Search for the given named symbol in the context of the loaded
437 /// object represented by the VModuleKey K.
438 /// @param K The VModuleKey for the object to search in.
439 /// @param Name The name of the symbol to search for.
440 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
441 /// @return A handle for the given named symbol, if it is found in the
442 /// given object.
443 JITSymbol findSymbolIn(VModuleKey K, StringRef Name,
444 bool ExportedSymbolsOnly) {
445 assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
446 return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly);
449 /// Map section addresses for the object associated with the
450 /// VModuleKey K.
451 void mapSectionAddress(VModuleKey K, const void *LocalAddress,
452 JITTargetAddress TargetAddr) {
453 assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
454 LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr);
457 /// Immediately emit and finalize the object represented by the given
458 /// VModuleKey.
459 /// @param K VModuleKey for object to emit/finalize.
460 Error emitAndFinalize(VModuleKey K) {
461 assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
462 return LinkedObjects[K]->finalize();
465 private:
466 ExecutionSession &ES;
468 ResourcesGetter GetResources;
469 NotifyLoadedFtor NotifyLoaded;
470 NotifyFinalizedFtor NotifyFinalized;
471 NotifyFreedFtor NotifyFreed;
473 // NB! `LinkedObjects` needs to be destroyed before `NotifyFreed` because
474 // `~ConcreteLinkedObject` calls `NotifyFreed`
475 std::map<VModuleKey, std::unique_ptr<LinkedObject>> LinkedObjects;
476 bool ProcessAllSections = false;
479 } // end namespace orc
480 } // end namespace llvm
482 #endif // LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H