1 //===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
10 #include "llvm/ADT/Optional.h"
11 #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
12 #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
13 #include "llvm/Support/MemoryBuffer.h"
17 #define DEBUG_TYPE "orc"
20 using namespace llvm::jitlink
;
21 using namespace llvm::orc
;
25 class LinkGraphMaterializationUnit
: public MaterializationUnit
{
27 struct LinkGraphInterface
{
28 SymbolFlagsMap SymbolFlags
;
29 SymbolStringPtr InitSymbol
;
33 static std::unique_ptr
<LinkGraphMaterializationUnit
>
34 Create(ObjectLinkingLayer
&ObjLinkingLayer
, std::unique_ptr
<LinkGraph
> G
) {
35 auto LGI
= scanLinkGraph(ObjLinkingLayer
.getExecutionSession(), *G
);
36 return std::unique_ptr
<LinkGraphMaterializationUnit
>(
37 new LinkGraphMaterializationUnit(ObjLinkingLayer
, std::move(G
),
41 StringRef
getName() const override
{ return G
->getName(); }
42 void materialize(std::unique_ptr
<MaterializationResponsibility
> MR
) override
{
43 ObjLinkingLayer
.emit(std::move(MR
), std::move(G
));
47 static LinkGraphInterface
scanLinkGraph(ExecutionSession
&ES
, LinkGraph
&G
) {
49 LinkGraphInterface LGI
;
51 for (auto *Sym
: G
.defined_symbols()) {
52 // Skip local symbols.
53 if (Sym
->getScope() == Scope::Local
)
55 assert(Sym
->hasName() && "Anonymous non-local symbol?");
58 if (Sym
->getScope() == Scope::Default
)
59 Flags
|= JITSymbolFlags::Exported
;
61 if (Sym
->isCallable())
62 Flags
|= JITSymbolFlags::Callable
;
64 LGI
.SymbolFlags
[ES
.intern(Sym
->getName())] = Flags
;
67 if (G
.getTargetTriple().isOSBinFormatMachO())
68 if (hasMachOInitSection(G
))
69 LGI
.InitSymbol
= makeInitSymbol(ES
, G
);
74 static bool hasMachOInitSection(LinkGraph
&G
) {
75 for (auto &Sec
: G
.sections())
76 if (Sec
.getName() == "__DATA,__obj_selrefs" ||
77 Sec
.getName() == "__DATA,__objc_classlist" ||
78 Sec
.getName() == "__TEXT,__swift5_protos" ||
79 Sec
.getName() == "__TEXT,__swift5_proto" ||
80 Sec
.getName() == "__DATA,__mod_init_func")
85 static SymbolStringPtr
makeInitSymbol(ExecutionSession
&ES
, LinkGraph
&G
) {
86 std::string InitSymString
;
87 raw_string_ostream(InitSymString
)
88 << "$." << G
.getName() << ".__inits" << Counter
++;
89 return ES
.intern(InitSymString
);
92 LinkGraphMaterializationUnit(ObjectLinkingLayer
&ObjLinkingLayer
,
93 std::unique_ptr
<LinkGraph
> G
,
94 LinkGraphInterface LGI
)
95 : MaterializationUnit(std::move(LGI
.SymbolFlags
),
96 std::move(LGI
.InitSymbol
)),
97 ObjLinkingLayer(ObjLinkingLayer
), G(std::move(G
)) {}
99 void discard(const JITDylib
&JD
, const SymbolStringPtr
&Name
) override
{
100 for (auto *Sym
: G
->defined_symbols())
101 if (Sym
->getName() == *Name
) {
102 assert(Sym
->getLinkage() == Linkage::Weak
&&
103 "Discarding non-weak definition");
104 G
->makeExternal(*Sym
);
109 ObjectLinkingLayer
&ObjLinkingLayer
;
110 std::unique_ptr
<LinkGraph
> G
;
111 static std::atomic
<uint64_t> Counter
;
114 std::atomic
<uint64_t> LinkGraphMaterializationUnit::Counter
{0};
116 } // end anonymous namespace
121 class ObjectLinkingLayerJITLinkContext final
: public JITLinkContext
{
123 ObjectLinkingLayerJITLinkContext(
124 ObjectLinkingLayer
&Layer
,
125 std::unique_ptr
<MaterializationResponsibility
> MR
,
126 std::unique_ptr
<MemoryBuffer
> ObjBuffer
)
127 : JITLinkContext(&MR
->getTargetJITDylib()), Layer(Layer
),
128 MR(std::move(MR
)), ObjBuffer(std::move(ObjBuffer
)) {}
130 ~ObjectLinkingLayerJITLinkContext() {
131 // If there is an object buffer return function then use it to
132 // return ownership of the buffer.
133 if (Layer
.ReturnObjectBuffer
&& ObjBuffer
)
134 Layer
.ReturnObjectBuffer(std::move(ObjBuffer
));
137 JITLinkMemoryManager
&getMemoryManager() override
{ return Layer
.MemMgr
; }
139 void notifyMaterializing(LinkGraph
&G
) {
140 for (auto &P
: Layer
.Plugins
)
141 P
->notifyMaterializing(*MR
, G
, *this,
142 ObjBuffer
? ObjBuffer
->getMemBufferRef()
143 : MemoryBufferRef());
146 void notifyFailed(Error Err
) override
{
147 for (auto &P
: Layer
.Plugins
)
148 Err
= joinErrors(std::move(Err
), P
->notifyFailed(*MR
));
149 Layer
.getExecutionSession().reportError(std::move(Err
));
150 MR
->failMaterialization();
153 void lookup(const LookupMap
&Symbols
,
154 std::unique_ptr
<JITLinkAsyncLookupContinuation
> LC
) override
{
156 JITDylibSearchOrder LinkOrder
;
157 MR
->getTargetJITDylib().withLinkOrderDo(
158 [&](const JITDylibSearchOrder
&LO
) { LinkOrder
= LO
; });
160 auto &ES
= Layer
.getExecutionSession();
162 SymbolLookupSet LookupSet
;
163 for (auto &KV
: Symbols
) {
164 orc::SymbolLookupFlags LookupFlags
;
166 case jitlink::SymbolLookupFlags::RequiredSymbol
:
167 LookupFlags
= orc::SymbolLookupFlags::RequiredSymbol
;
169 case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol
:
170 LookupFlags
= orc::SymbolLookupFlags::WeaklyReferencedSymbol
;
173 LookupSet
.add(ES
.intern(KV
.first
), LookupFlags
);
176 // OnResolve -- De-intern the symbols and pass the result to the linker.
177 auto OnResolve
= [LookupContinuation
=
178 std::move(LC
)](Expected
<SymbolMap
> Result
) mutable {
180 LookupContinuation
->run(Result
.takeError());
182 AsyncLookupResult LR
;
183 for (auto &KV
: *Result
)
184 LR
[*KV
.first
] = KV
.second
;
185 LookupContinuation
->run(std::move(LR
));
189 for (auto &KV
: InternalNamedSymbolDeps
) {
190 SymbolDependenceMap InternalDeps
;
191 InternalDeps
[&MR
->getTargetJITDylib()] = std::move(KV
.second
);
192 MR
->addDependencies(KV
.first
, InternalDeps
);
195 ES
.lookup(LookupKind::Static
, LinkOrder
, std::move(LookupSet
),
196 SymbolState::Resolved
, std::move(OnResolve
),
197 [this](const SymbolDependenceMap
&Deps
) {
198 registerDependencies(Deps
);
202 Error
notifyResolved(LinkGraph
&G
) override
{
203 auto &ES
= Layer
.getExecutionSession();
205 SymbolFlagsMap ExtraSymbolsToClaim
;
206 bool AutoClaim
= Layer
.AutoClaimObjectSymbols
;
208 SymbolMap InternedResult
;
209 for (auto *Sym
: G
.defined_symbols())
210 if (Sym
->hasName() && Sym
->getScope() != Scope::Local
) {
211 auto InternedName
= ES
.intern(Sym
->getName());
212 JITSymbolFlags Flags
;
214 if (Sym
->isCallable())
215 Flags
|= JITSymbolFlags::Callable
;
216 if (Sym
->getScope() == Scope::Default
)
217 Flags
|= JITSymbolFlags::Exported
;
219 InternedResult
[InternedName
] =
220 JITEvaluatedSymbol(Sym
->getAddress(), Flags
);
221 if (AutoClaim
&& !MR
->getSymbols().count(InternedName
)) {
222 assert(!ExtraSymbolsToClaim
.count(InternedName
) &&
223 "Duplicate symbol to claim?");
224 ExtraSymbolsToClaim
[InternedName
] = Flags
;
228 for (auto *Sym
: G
.absolute_symbols())
229 if (Sym
->hasName()) {
230 auto InternedName
= ES
.intern(Sym
->getName());
231 JITSymbolFlags Flags
;
232 Flags
|= JITSymbolFlags::Absolute
;
233 if (Sym
->isCallable())
234 Flags
|= JITSymbolFlags::Callable
;
235 if (Sym
->getLinkage() == Linkage::Weak
)
236 Flags
|= JITSymbolFlags::Weak
;
237 InternedResult
[InternedName
] =
238 JITEvaluatedSymbol(Sym
->getAddress(), Flags
);
239 if (AutoClaim
&& !MR
->getSymbols().count(InternedName
)) {
240 assert(!ExtraSymbolsToClaim
.count(InternedName
) &&
241 "Duplicate symbol to claim?");
242 ExtraSymbolsToClaim
[InternedName
] = Flags
;
246 if (!ExtraSymbolsToClaim
.empty())
247 if (auto Err
= MR
->defineMaterializing(ExtraSymbolsToClaim
))
252 // Check that InternedResult matches up with MR->getSymbols().
253 // This guards against faulty transformations / compilers / object caches.
255 // First check that there aren't any missing symbols.
256 size_t NumMaterializationSideEffectsOnlySymbols
= 0;
257 SymbolNameVector ExtraSymbols
;
258 SymbolNameVector MissingSymbols
;
259 for (auto &KV
: MR
->getSymbols()) {
261 // If this is a materialization-side-effects only symbol then bump
262 // the counter and make sure it's *not* defined, otherwise make
263 // sure that it is defined.
264 if (KV
.second
.hasMaterializationSideEffectsOnly()) {
265 ++NumMaterializationSideEffectsOnlySymbols
;
266 if (InternedResult
.count(KV
.first
))
267 ExtraSymbols
.push_back(KV
.first
);
269 } else if (!InternedResult
.count(KV
.first
))
270 MissingSymbols
.push_back(KV
.first
);
273 // If there were missing symbols then report the error.
274 if (!MissingSymbols
.empty())
275 return make_error
<MissingSymbolDefinitions
>(G
.getName(),
276 std::move(MissingSymbols
));
278 // If there are more definitions than expected, add them to the
279 // ExtraSymbols vector.
280 if (InternedResult
.size() >
281 MR
->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols
) {
282 for (auto &KV
: InternedResult
)
283 if (!MR
->getSymbols().count(KV
.first
))
284 ExtraSymbols
.push_back(KV
.first
);
287 // If there were extra definitions then report the error.
288 if (!ExtraSymbols
.empty())
289 return make_error
<UnexpectedSymbolDefinitions
>(G
.getName(),
290 std::move(ExtraSymbols
));
293 if (auto Err
= MR
->notifyResolved(InternedResult
))
296 Layer
.notifyLoaded(*MR
);
297 return Error::success();
300 void notifyFinalized(
301 std::unique_ptr
<JITLinkMemoryManager::Allocation
> A
) override
{
302 if (auto Err
= Layer
.notifyEmitted(*MR
, std::move(A
))) {
303 Layer
.getExecutionSession().reportError(std::move(Err
));
304 MR
->failMaterialization();
307 if (auto Err
= MR
->notifyEmitted()) {
308 Layer
.getExecutionSession().reportError(std::move(Err
));
309 MR
->failMaterialization();
313 LinkGraphPassFunction
getMarkLivePass(const Triple
&TT
) const override
{
314 return [this](LinkGraph
&G
) { return markResponsibilitySymbolsLive(G
); };
317 Error
modifyPassConfig(LinkGraph
&LG
, PassConfiguration
&Config
) override
{
318 // Add passes to mark duplicate defs as should-discard, and to walk the
319 // link graph to build the symbol dependence graph.
320 Config
.PrePrunePasses
.push_back([this](LinkGraph
&G
) {
321 return claimOrExternalizeWeakAndCommonSymbols(G
);
324 Layer
.modifyPassConfig(*MR
, LG
, Config
);
326 Config
.PostPrunePasses
.push_back(
327 [this](LinkGraph
&G
) { return computeNamedSymbolDependencies(G
); });
329 return Error::success();
333 // Symbol name dependencies:
334 // Internal: Defined in this graph.
335 // External: Defined externally.
336 struct BlockSymbolDependencies
{
337 SymbolNameSet Internal
, External
;
340 // Lazily populated map of blocks to BlockSymbolDependencies values.
341 class BlockDependenciesMap
{
343 BlockDependenciesMap(ExecutionSession
&ES
,
344 DenseMap
<const Block
*, DenseSet
<Block
*>> BlockDeps
)
345 : ES(ES
), BlockDeps(std::move(BlockDeps
)) {}
347 const BlockSymbolDependencies
&operator[](const Block
&B
) {
348 // Check the cache first.
349 auto I
= BlockTransitiveDepsCache
.find(&B
);
350 if (I
!= BlockTransitiveDepsCache
.end())
353 // No value. Populate the cache.
354 BlockSymbolDependencies BTDCacheVal
;
355 auto BDI
= BlockDeps
.find(&B
);
356 assert(BDI
!= BlockDeps
.end() && "No block dependencies");
358 for (auto *BDep
: BDI
->second
) {
359 auto &BID
= getBlockImmediateDeps(*BDep
);
360 for (auto &ExternalDep
: BID
.External
)
361 BTDCacheVal
.External
.insert(ExternalDep
);
362 for (auto &InternalDep
: BID
.Internal
)
363 BTDCacheVal
.Internal
.insert(InternalDep
);
366 return BlockTransitiveDepsCache
367 .insert(std::make_pair(&B
, std::move(BTDCacheVal
)))
371 SymbolStringPtr
&getInternedName(Symbol
&Sym
) {
372 auto I
= NameCache
.find(&Sym
);
373 if (I
!= NameCache
.end())
376 return NameCache
.insert(std::make_pair(&Sym
, ES
.intern(Sym
.getName())))
381 BlockSymbolDependencies
&getBlockImmediateDeps(Block
&B
) {
382 // Check the cache first.
383 auto I
= BlockImmediateDepsCache
.find(&B
);
384 if (I
!= BlockImmediateDepsCache
.end())
387 BlockSymbolDependencies BIDCacheVal
;
388 for (auto &E
: B
.edges()) {
389 auto &Tgt
= E
.getTarget();
390 if (Tgt
.getScope() != Scope::Local
) {
391 if (Tgt
.isExternal())
392 BIDCacheVal
.External
.insert(getInternedName(Tgt
));
394 BIDCacheVal
.Internal
.insert(getInternedName(Tgt
));
398 return BlockImmediateDepsCache
399 .insert(std::make_pair(&B
, std::move(BIDCacheVal
)))
403 ExecutionSession
&ES
;
404 DenseMap
<const Block
*, DenseSet
<Block
*>> BlockDeps
;
405 DenseMap
<const Symbol
*, SymbolStringPtr
> NameCache
;
406 DenseMap
<const Block
*, BlockSymbolDependencies
> BlockImmediateDepsCache
;
407 DenseMap
<const Block
*, BlockSymbolDependencies
> BlockTransitiveDepsCache
;
410 Error
claimOrExternalizeWeakAndCommonSymbols(LinkGraph
&G
) {
411 auto &ES
= Layer
.getExecutionSession();
413 SymbolFlagsMap NewSymbolsToClaim
;
414 std::vector
<std::pair
<SymbolStringPtr
, Symbol
*>> NameToSym
;
416 auto ProcessSymbol
= [&](Symbol
*Sym
) {
417 if (Sym
->hasName() && Sym
->getLinkage() == Linkage::Weak
) {
418 auto Name
= ES
.intern(Sym
->getName());
419 if (!MR
->getSymbols().count(ES
.intern(Sym
->getName()))) {
420 JITSymbolFlags SF
= JITSymbolFlags::Weak
;
421 if (Sym
->getScope() == Scope::Default
)
422 SF
|= JITSymbolFlags::Exported
;
423 NewSymbolsToClaim
[Name
] = SF
;
424 NameToSym
.push_back(std::make_pair(std::move(Name
), Sym
));
429 for (auto *Sym
: G
.defined_symbols())
431 for (auto *Sym
: G
.absolute_symbols())
434 // Attempt to claim all weak defs that we're not already responsible for.
435 // This cannot fail -- any clashes will just result in rejection of our
436 // claim, at which point we'll externalize that symbol.
437 cantFail(MR
->defineMaterializing(std::move(NewSymbolsToClaim
)));
439 for (auto &KV
: NameToSym
)
440 if (!MR
->getSymbols().count(KV
.first
))
441 G
.makeExternal(*KV
.second
);
443 return Error::success();
446 Error
markResponsibilitySymbolsLive(LinkGraph
&G
) const {
447 auto &ES
= Layer
.getExecutionSession();
448 for (auto *Sym
: G
.defined_symbols())
449 if (Sym
->hasName() && MR
->getSymbols().count(ES
.intern(Sym
->getName())))
451 return Error::success();
454 Error
computeNamedSymbolDependencies(LinkGraph
&G
) {
455 auto &ES
= MR
->getTargetJITDylib().getExecutionSession();
456 auto BlockDeps
= computeBlockNonLocalDeps(G
);
458 // Compute dependencies for symbols defined in the JITLink graph.
459 for (auto *Sym
: G
.defined_symbols()) {
461 // Skip local symbols: we do not track dependencies for these.
462 if (Sym
->getScope() == Scope::Local
)
464 assert(Sym
->hasName() &&
465 "Defined non-local jitlink::Symbol should have a name");
467 auto &SymDeps
= BlockDeps
[Sym
->getBlock()];
468 if (SymDeps
.External
.empty() && SymDeps
.Internal
.empty())
471 auto SymName
= ES
.intern(Sym
->getName());
472 if (!SymDeps
.External
.empty())
473 ExternalNamedSymbolDeps
[SymName
] = SymDeps
.External
;
474 if (!SymDeps
.Internal
.empty())
475 InternalNamedSymbolDeps
[SymName
] = SymDeps
.Internal
;
478 for (auto &P
: Layer
.Plugins
) {
479 auto SynthDeps
= P
->getSyntheticSymbolDependencies(*MR
);
480 if (SynthDeps
.empty())
483 DenseSet
<Block
*> BlockVisited
;
484 for (auto &KV
: SynthDeps
) {
485 auto &Name
= KV
.first
;
486 auto &DepsForName
= KV
.second
;
487 for (auto *Sym
: DepsForName
) {
488 if (Sym
->getScope() == Scope::Local
) {
489 auto &BDeps
= BlockDeps
[Sym
->getBlock()];
490 for (auto &S
: BDeps
.Internal
)
491 InternalNamedSymbolDeps
[Name
].insert(S
);
492 for (auto &S
: BDeps
.External
)
493 ExternalNamedSymbolDeps
[Name
].insert(S
);
495 if (Sym
->isExternal())
496 ExternalNamedSymbolDeps
[Name
].insert(
497 BlockDeps
.getInternedName(*Sym
));
499 InternalNamedSymbolDeps
[Name
].insert(
500 BlockDeps
.getInternedName(*Sym
));
506 return Error::success();
509 BlockDependenciesMap
computeBlockNonLocalDeps(LinkGraph
&G
) {
510 // First calculate the reachable-via-non-local-symbol blocks for each block.
512 DenseSet
<Block
*> Dependencies
;
513 DenseSet
<Block
*> Dependants
;
514 bool DependenciesChanged
= true;
516 DenseMap
<Block
*, BlockInfo
> BlockInfos
;
517 SmallVector
<Block
*> WorkList
;
519 // Pre-allocate map entries. This prevents any iterator/reference
520 // invalidation in the next loop.
521 for (auto *B
: G
.blocks())
524 // Build initial worklist, record block dependencies/dependants and
525 // non-local symbol dependencies.
526 for (auto *B
: G
.blocks()) {
527 auto &BI
= BlockInfos
[B
];
528 for (auto &E
: B
->edges()) {
529 if (E
.getTarget().getScope() == Scope::Local
) {
530 auto &TgtB
= E
.getTarget().getBlock();
532 BI
.Dependencies
.insert(&TgtB
);
533 BlockInfos
[&TgtB
].Dependants
.insert(B
);
538 // If this node has both dependants and dependencies then add it to the
539 // worklist to propagate the dependencies to the dependants.
540 if (!BI
.Dependants
.empty() && !BI
.Dependencies
.empty())
541 WorkList
.push_back(B
);
544 // Propagate block-level dependencies through the block-dependence graph.
545 while (!WorkList
.empty()) {
546 auto *B
= WorkList
.back();
549 auto &BI
= BlockInfos
[B
];
550 assert(BI
.DependenciesChanged
&&
551 "Block in worklist has unchanged dependencies");
552 BI
.DependenciesChanged
= false;
553 for (auto *Dependant
: BI
.Dependants
) {
554 auto &DependantBI
= BlockInfos
[Dependant
];
555 for (auto *Dependency
: BI
.Dependencies
) {
556 if (Dependant
!= Dependency
&&
557 DependantBI
.Dependencies
.insert(Dependency
).second
)
558 if (!DependantBI
.DependenciesChanged
) {
559 DependantBI
.DependenciesChanged
= true;
560 WorkList
.push_back(Dependant
);
566 DenseMap
<const Block
*, DenseSet
<Block
*>> BlockDeps
;
567 for (auto &KV
: BlockInfos
)
568 BlockDeps
[KV
.first
] = std::move(KV
.second
.Dependencies
);
570 return BlockDependenciesMap(Layer
.getExecutionSession(),
571 std::move(BlockDeps
));
574 void registerDependencies(const SymbolDependenceMap
&QueryDeps
) {
575 for (auto &NamedDepsEntry
: ExternalNamedSymbolDeps
) {
576 auto &Name
= NamedDepsEntry
.first
;
577 auto &NameDeps
= NamedDepsEntry
.second
;
578 SymbolDependenceMap SymbolDeps
;
580 for (const auto &QueryDepsEntry
: QueryDeps
) {
581 JITDylib
&SourceJD
= *QueryDepsEntry
.first
;
582 const SymbolNameSet
&Symbols
= QueryDepsEntry
.second
;
583 auto &DepsForJD
= SymbolDeps
[&SourceJD
];
585 for (const auto &S
: Symbols
)
586 if (NameDeps
.count(S
))
589 if (DepsForJD
.empty())
590 SymbolDeps
.erase(&SourceJD
);
593 MR
->addDependencies(Name
, SymbolDeps
);
597 ObjectLinkingLayer
&Layer
;
598 std::unique_ptr
<MaterializationResponsibility
> MR
;
599 std::unique_ptr
<MemoryBuffer
> ObjBuffer
;
600 DenseMap
<SymbolStringPtr
, SymbolNameSet
> ExternalNamedSymbolDeps
;
601 DenseMap
<SymbolStringPtr
, SymbolNameSet
> InternalNamedSymbolDeps
;
604 ObjectLinkingLayer::Plugin::~Plugin() {}
606 char ObjectLinkingLayer::ID
;
608 using BaseT
= RTTIExtends
<ObjectLinkingLayer
, ObjectLayer
>;
610 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession
&ES
)
611 : BaseT(ES
), MemMgr(ES
.getExecutorProcessControl().getMemMgr()) {
612 ES
.registerResourceManager(*this);
615 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession
&ES
,
616 JITLinkMemoryManager
&MemMgr
)
617 : BaseT(ES
), MemMgr(MemMgr
) {
618 ES
.registerResourceManager(*this);
621 ObjectLinkingLayer::ObjectLinkingLayer(
622 ExecutionSession
&ES
, std::unique_ptr
<JITLinkMemoryManager
> MemMgr
)
623 : BaseT(ES
), MemMgr(*MemMgr
), MemMgrOwnership(std::move(MemMgr
)) {
624 ES
.registerResourceManager(*this);
627 ObjectLinkingLayer::~ObjectLinkingLayer() {
628 assert(Allocs
.empty() && "Layer destroyed with resources still attached");
629 getExecutionSession().deregisterResourceManager(*this);
632 Error
ObjectLinkingLayer::add(ResourceTrackerSP RT
,
633 std::unique_ptr
<LinkGraph
> G
) {
634 auto &JD
= RT
->getJITDylib();
635 return JD
.define(LinkGraphMaterializationUnit::Create(*this, std::move(G
)),
639 void ObjectLinkingLayer::emit(std::unique_ptr
<MaterializationResponsibility
> R
,
640 std::unique_ptr
<MemoryBuffer
> O
) {
641 assert(O
&& "Object must not be null");
642 MemoryBufferRef ObjBuffer
= O
->getMemBufferRef();
644 auto Ctx
= std::make_unique
<ObjectLinkingLayerJITLinkContext
>(
645 *this, std::move(R
), std::move(O
));
646 if (auto G
= createLinkGraphFromObject(ObjBuffer
)) {
647 Ctx
->notifyMaterializing(**G
);
648 link(std::move(*G
), std::move(Ctx
));
650 Ctx
->notifyFailed(G
.takeError());
654 void ObjectLinkingLayer::emit(std::unique_ptr
<MaterializationResponsibility
> R
,
655 std::unique_ptr
<LinkGraph
> G
) {
656 auto Ctx
= std::make_unique
<ObjectLinkingLayerJITLinkContext
>(
657 *this, std::move(R
), nullptr);
658 Ctx
->notifyMaterializing(*G
);
659 link(std::move(G
), std::move(Ctx
));
662 void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility
&MR
,
664 PassConfiguration
&PassConfig
) {
665 for (auto &P
: Plugins
)
666 P
->modifyPassConfig(MR
, G
, PassConfig
);
669 void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility
&MR
) {
670 for (auto &P
: Plugins
)
674 Error
ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility
&MR
,
676 Error Err
= Error::success();
677 for (auto &P
: Plugins
)
678 Err
= joinErrors(std::move(Err
), P
->notifyEmitted(MR
));
683 return MR
.withResourceKeyDo(
684 [&](ResourceKey K
) { Allocs
[K
].push_back(std::move(Alloc
)); });
687 Error
ObjectLinkingLayer::handleRemoveResources(ResourceKey K
) {
689 Error Err
= Error::success();
691 for (auto &P
: Plugins
)
692 Err
= joinErrors(std::move(Err
), P
->notifyRemovingResources(K
));
694 std::vector
<AllocPtr
> AllocsToRemove
;
695 getExecutionSession().runSessionLocked([&] {
696 auto I
= Allocs
.find(K
);
697 if (I
!= Allocs
.end()) {
698 std::swap(AllocsToRemove
, I
->second
);
703 while (!AllocsToRemove
.empty()) {
704 Err
= joinErrors(std::move(Err
), AllocsToRemove
.back()->deallocate());
705 AllocsToRemove
.pop_back();
711 void ObjectLinkingLayer::handleTransferResources(ResourceKey DstKey
,
712 ResourceKey SrcKey
) {
713 auto I
= Allocs
.find(SrcKey
);
714 if (I
!= Allocs
.end()) {
715 auto &SrcAllocs
= I
->second
;
716 auto &DstAllocs
= Allocs
[DstKey
];
717 DstAllocs
.reserve(DstAllocs
.size() + SrcAllocs
.size());
718 for (auto &Alloc
: SrcAllocs
)
719 DstAllocs
.push_back(std::move(Alloc
));
721 // Erase SrcKey entry using value rather than iterator I: I may have been
722 // invalidated when we looked up DstKey.
723 Allocs
.erase(SrcKey
);
726 for (auto &P
: Plugins
)
727 P
->notifyTransferringResources(DstKey
, SrcKey
);
730 EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
731 ExecutionSession
&ES
, std::unique_ptr
<EHFrameRegistrar
> Registrar
)
732 : ES(ES
), Registrar(std::move(Registrar
)) {}
734 void EHFrameRegistrationPlugin::modifyPassConfig(
735 MaterializationResponsibility
&MR
, LinkGraph
&G
,
736 PassConfiguration
&PassConfig
) {
738 PassConfig
.PostFixupPasses
.push_back(createEHFrameRecorderPass(
739 G
.getTargetTriple(), [this, &MR
](JITTargetAddress Addr
, size_t Size
) {
741 std::lock_guard
<std::mutex
> Lock(EHFramePluginMutex
);
742 assert(!InProcessLinks
.count(&MR
) &&
743 "Link for MR already being tracked?");
744 InProcessLinks
[&MR
] = {Addr
, Size
};
749 Error
EHFrameRegistrationPlugin::notifyEmitted(
750 MaterializationResponsibility
&MR
) {
752 EHFrameRange EmittedRange
;
754 std::lock_guard
<std::mutex
> Lock(EHFramePluginMutex
);
756 auto EHFrameRangeItr
= InProcessLinks
.find(&MR
);
757 if (EHFrameRangeItr
== InProcessLinks
.end())
758 return Error::success();
760 EmittedRange
= EHFrameRangeItr
->second
;
761 assert(EmittedRange
.Addr
&& "eh-frame addr to register can not be null");
762 InProcessLinks
.erase(EHFrameRangeItr
);
765 if (auto Err
= MR
.withResourceKeyDo(
766 [&](ResourceKey K
) { EHFrameRanges
[K
].push_back(EmittedRange
); }))
769 return Registrar
->registerEHFrames(EmittedRange
.Addr
, EmittedRange
.Size
);
772 Error
EHFrameRegistrationPlugin::notifyFailed(
773 MaterializationResponsibility
&MR
) {
774 std::lock_guard
<std::mutex
> Lock(EHFramePluginMutex
);
775 InProcessLinks
.erase(&MR
);
776 return Error::success();
779 Error
EHFrameRegistrationPlugin::notifyRemovingResources(ResourceKey K
) {
780 std::vector
<EHFrameRange
> RangesToRemove
;
782 ES
.runSessionLocked([&] {
783 auto I
= EHFrameRanges
.find(K
);
784 if (I
!= EHFrameRanges
.end()) {
785 RangesToRemove
= std::move(I
->second
);
786 EHFrameRanges
.erase(I
);
790 Error Err
= Error::success();
791 while (!RangesToRemove
.empty()) {
792 auto RangeToRemove
= RangesToRemove
.back();
793 RangesToRemove
.pop_back();
794 assert(RangeToRemove
.Addr
&& "Untracked eh-frame range must not be null");
797 Registrar
->deregisterEHFrames(RangeToRemove
.Addr
, RangeToRemove
.Size
));
803 void EHFrameRegistrationPlugin::notifyTransferringResources(
804 ResourceKey DstKey
, ResourceKey SrcKey
) {
805 auto SI
= EHFrameRanges
.find(SrcKey
);
806 if (SI
== EHFrameRanges
.end())
809 auto DI
= EHFrameRanges
.find(DstKey
);
810 if (DI
!= EHFrameRanges
.end()) {
811 auto &SrcRanges
= SI
->second
;
812 auto &DstRanges
= DI
->second
;
813 DstRanges
.reserve(DstRanges
.size() + SrcRanges
.size());
814 for (auto &SrcRange
: SrcRanges
)
815 DstRanges
.push_back(std::move(SrcRange
));
816 EHFrameRanges
.erase(SI
);
818 // We need to move SrcKey's ranges over without invalidating the SI
820 auto Tmp
= std::move(SI
->second
);
821 EHFrameRanges
.erase(SI
);
822 EHFrameRanges
[DstKey
] = std::move(Tmp
);
826 } // End namespace orc.
827 } // End namespace llvm.