LLVM 18.0.0git
ObjectLinkingLayer.cpp
Go to the documentation of this file.
1//===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===//
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
16#include <string>
17#include <vector>
18
19#define DEBUG_TYPE "orc"
20
21using namespace llvm;
22using namespace llvm::jitlink;
23using namespace llvm::orc;
24
25namespace {
26
27bool hasInitializerSection(jitlink::LinkGraph &G) {
28 bool IsMachO = G.getTargetTriple().isOSBinFormatMachO();
29 bool IsElf = G.getTargetTriple().isOSBinFormatELF();
30 if (!IsMachO && !IsElf)
31 return false;
32
33 for (auto &Sec : G.sections()) {
34 if (IsMachO && isMachOInitializerSection(Sec.getName()))
35 return true;
36 if (IsElf && isELFInitializerSection(Sec.getName()))
37 return true;
38 }
39
40 return false;
41}
42
43ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) {
44 switch (TT.getArch()) {
45 case Triple::arm:
46 case Triple::armeb:
47 case Triple::thumb:
48 case Triple::thumbeb:
49 if (hasTargetFlags(Sym, aarch32::ThumbSymbol)) {
50 // Set LSB to indicate thumb target
51 assert(Sym.isCallable() && "Only callable symbols can have thumb flag");
52 assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear");
53 return Sym.getAddress() + 0x01;
54 }
55 return Sym.getAddress();
56 default:
57 return Sym.getAddress();
58 }
59}
60
61JITSymbolFlags getJITSymbolFlagsForSymbol(Symbol &Sym) {
62 JITSymbolFlags Flags;
63
64 if (Sym.getLinkage() == Linkage::Weak)
65 Flags |= JITSymbolFlags::Weak;
66
67 if (Sym.getScope() == Scope::Default)
69
70 if (Sym.isCallable())
72
73 return Flags;
74}
75
76class LinkGraphMaterializationUnit : public MaterializationUnit {
77public:
78 static std::unique_ptr<LinkGraphMaterializationUnit>
79 Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) {
80 auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G);
81 return std::unique_ptr<LinkGraphMaterializationUnit>(
82 new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G),
83 std::move(LGI)));
84 }
85
86 StringRef getName() const override { return G->getName(); }
87 void materialize(std::unique_ptr<MaterializationResponsibility> MR) override {
88 ObjLinkingLayer.emit(std::move(MR), std::move(G));
89 }
90
91private:
92 static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) {
93
94 Interface LGI;
95
96 for (auto *Sym : G.defined_symbols()) {
97 // Skip local symbols.
98 if (Sym->getScope() == Scope::Local)
99 continue;
100 assert(Sym->hasName() && "Anonymous non-local symbol?");
101
102 LGI.SymbolFlags[ES.intern(Sym->getName())] =
103 getJITSymbolFlagsForSymbol(*Sym);
104 }
105
106 if (hasInitializerSection(G))
107 LGI.InitSymbol = makeInitSymbol(ES, G);
108
109 return LGI;
110 }
111
112 static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) {
113 std::string InitSymString;
114 raw_string_ostream(InitSymString)
115 << "$." << G.getName() << ".__inits" << Counter++;
116 return ES.intern(InitSymString);
117 }
118
119 LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer,
120 std::unique_ptr<LinkGraph> G, Interface LGI)
121 : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer),
122 G(std::move(G)) {}
123
124 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
125 for (auto *Sym : G->defined_symbols())
126 if (Sym->getName() == *Name) {
127 assert(Sym->getLinkage() == Linkage::Weak &&
128 "Discarding non-weak definition");
129 G->makeExternal(*Sym);
130 break;
131 }
132 }
133
134 ObjectLinkingLayer &ObjLinkingLayer;
135 std::unique_ptr<LinkGraph> G;
136 static std::atomic<uint64_t> Counter;
137};
138
139std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0};
140
141} // end anonymous namespace
142
143namespace llvm {
144namespace orc {
145
147public:
149 ObjectLinkingLayer &Layer,
150 std::unique_ptr<MaterializationResponsibility> MR,
151 std::unique_ptr<MemoryBuffer> ObjBuffer)
152 : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer),
153 MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {}
154
156 // If there is an object buffer return function then use it to
157 // return ownership of the buffer.
158 if (Layer.ReturnObjectBuffer && ObjBuffer)
159 Layer.ReturnObjectBuffer(std::move(ObjBuffer));
160 }
161
162 JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
163
165 for (auto &P : Layer.Plugins)
166 P->notifyMaterializing(*MR, G, *this,
167 ObjBuffer ? ObjBuffer->getMemBufferRef()
168 : MemoryBufferRef());
169 }
170
171 void notifyFailed(Error Err) override {
172 for (auto &P : Layer.Plugins)
173 Err = joinErrors(std::move(Err), P->notifyFailed(*MR));
174 Layer.getExecutionSession().reportError(std::move(Err));
175 MR->failMaterialization();
176 }
177
178 void lookup(const LookupMap &Symbols,
179 std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {
180
181 JITDylibSearchOrder LinkOrder;
182 MR->getTargetJITDylib().withLinkOrderDo(
183 [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; });
184
185 auto &ES = Layer.getExecutionSession();
186
187 SymbolLookupSet LookupSet;
188 for (auto &KV : Symbols) {
189 orc::SymbolLookupFlags LookupFlags;
190 switch (KV.second) {
193 break;
196 break;
197 }
198 LookupSet.add(ES.intern(KV.first), LookupFlags);
199 }
200
201 // OnResolve -- De-intern the symbols and pass the result to the linker.
202 auto OnResolve = [LookupContinuation =
203 std::move(LC)](Expected<SymbolMap> Result) mutable {
204 if (!Result)
205 LookupContinuation->run(Result.takeError());
206 else {
208 for (auto &KV : *Result)
209 LR[*KV.first] = KV.second;
210 LookupContinuation->run(std::move(LR));
211 }
212 };
213
214 for (auto &KV : InternalNamedSymbolDeps) {
215 SymbolDependenceMap InternalDeps;
216 InternalDeps[&MR->getTargetJITDylib()] = std::move(KV.second);
217 MR->addDependencies(KV.first, InternalDeps);
218 }
219
220 ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet),
221 SymbolState::Resolved, std::move(OnResolve),
222 [this](const SymbolDependenceMap &Deps) {
223 registerDependencies(Deps);
224 });
225 }
226
228 auto &ES = Layer.getExecutionSession();
229
230 SymbolFlagsMap ExtraSymbolsToClaim;
231 bool AutoClaim = Layer.AutoClaimObjectSymbols;
232
233 SymbolMap InternedResult;
234 for (auto *Sym : G.defined_symbols())
235 if (Sym->hasName() && Sym->getScope() != Scope::Local) {
236 auto InternedName = ES.intern(Sym->getName());
237 auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());
238 auto Flags = getJITSymbolFlagsForSymbol(*Sym);
239 InternedResult[InternedName] = {Ptr, Flags};
240 if (AutoClaim && !MR->getSymbols().count(InternedName)) {
241 assert(!ExtraSymbolsToClaim.count(InternedName) &&
242 "Duplicate symbol to claim?");
243 ExtraSymbolsToClaim[InternedName] = Flags;
244 }
245 }
246
247 for (auto *Sym : G.absolute_symbols())
248 if (Sym->hasName() && Sym->getScope() != Scope::Local) {
249 auto InternedName = ES.intern(Sym->getName());
250 auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());
251 auto Flags = getJITSymbolFlagsForSymbol(*Sym);
252 InternedResult[InternedName] = {Ptr, Flags};
253 if (AutoClaim && !MR->getSymbols().count(InternedName)) {
254 assert(!ExtraSymbolsToClaim.count(InternedName) &&
255 "Duplicate symbol to claim?");
256 ExtraSymbolsToClaim[InternedName] = Flags;
257 }
258 }
259
260 if (!ExtraSymbolsToClaim.empty())
261 if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
262 return Err;
263
264 {
265
266 // Check that InternedResult matches up with MR->getSymbols(), overriding
267 // flags if requested.
268 // This guards against faulty transformations / compilers / object caches.
269
270 // First check that there aren't any missing symbols.
271 size_t NumMaterializationSideEffectsOnlySymbols = 0;
272 SymbolNameVector ExtraSymbols;
273 SymbolNameVector MissingSymbols;
274 for (auto &KV : MR->getSymbols()) {
275
276 auto I = InternedResult.find(KV.first);
277
278 // If this is a materialization-side-effects only symbol then bump
279 // the counter and make sure it's *not* defined, otherwise make
280 // sure that it is defined.
281 if (KV.second.hasMaterializationSideEffectsOnly()) {
282 ++NumMaterializationSideEffectsOnlySymbols;
283 if (I != InternedResult.end())
284 ExtraSymbols.push_back(KV.first);
285 continue;
286 } else if (I == InternedResult.end())
287 MissingSymbols.push_back(KV.first);
288 else if (Layer.OverrideObjectFlags)
289 I->second.setFlags(KV.second);
290 }
291
292 // If there were missing symbols then report the error.
293 if (!MissingSymbols.empty())
294 return make_error<MissingSymbolDefinitions>(
295 Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
296 std::move(MissingSymbols));
297
298 // If there are more definitions than expected, add them to the
299 // ExtraSymbols vector.
300 if (InternedResult.size() >
301 MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
302 for (auto &KV : InternedResult)
303 if (!MR->getSymbols().count(KV.first))
304 ExtraSymbols.push_back(KV.first);
305 }
306
307 // If there were extra definitions then report the error.
308 if (!ExtraSymbols.empty())
309 return make_error<UnexpectedSymbolDefinitions>(
310 Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
311 std::move(ExtraSymbols));
312 }
313
314 if (auto Err = MR->notifyResolved(InternedResult))
315 return Err;
316
317 Layer.notifyLoaded(*MR);
318 return Error::success();
319 }
320
322 if (auto Err = Layer.notifyEmitted(*MR, std::move(A))) {
323 Layer.getExecutionSession().reportError(std::move(Err));
324 MR->failMaterialization();
325 return;
326 }
327 if (auto Err = MR->notifyEmitted()) {
328 Layer.getExecutionSession().reportError(std::move(Err));
329 MR->failMaterialization();
330 }
331 }
332
333 LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
334 return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
335 }
336
338 // Add passes to mark duplicate defs as should-discard, and to walk the
339 // link graph to build the symbol dependence graph.
340 Config.PrePrunePasses.push_back([this](LinkGraph &G) {
341 return claimOrExternalizeWeakAndCommonSymbols(G);
342 });
343
344 Layer.modifyPassConfig(*MR, LG, Config);
345
346 Config.PostPrunePasses.push_back(
347 [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); });
348
349 return Error::success();
350 }
351
352private:
353 // Symbol name dependencies:
354 // Internal: Defined in this graph.
355 // External: Defined externally.
356 struct BlockSymbolDependencies {
357 SymbolNameSet Internal, External;
358 };
359
360 // Lazily populated map of blocks to BlockSymbolDependencies values.
361 class BlockDependenciesMap {
362 public:
363 BlockDependenciesMap(ExecutionSession &ES,
364 DenseMap<const Block *, DenseSet<Block *>> BlockDeps)
365 : ES(ES), BlockDeps(std::move(BlockDeps)) {}
366
367 const BlockSymbolDependencies &operator[](const Block &B) {
368 // Check the cache first.
369 auto I = BlockTransitiveDepsCache.find(&B);
370 if (I != BlockTransitiveDepsCache.end())
371 return I->second;
372
373 // No value. Populate the cache.
374 BlockSymbolDependencies BTDCacheVal;
375 auto BDI = BlockDeps.find(&B);
376 assert(BDI != BlockDeps.end() && "No block dependencies");
377
378 for (auto *BDep : BDI->second) {
379 auto &BID = getBlockImmediateDeps(*BDep);
380 for (auto &ExternalDep : BID.External)
381 BTDCacheVal.External.insert(ExternalDep);
382 for (auto &InternalDep : BID.Internal)
383 BTDCacheVal.Internal.insert(InternalDep);
384 }
385
386 return BlockTransitiveDepsCache
387 .insert(std::make_pair(&B, std::move(BTDCacheVal)))
388 .first->second;
389 }
390
391 SymbolStringPtr &getInternedName(Symbol &Sym) {
392 auto I = NameCache.find(&Sym);
393 if (I != NameCache.end())
394 return I->second;
395
396 return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName())))
397 .first->second;
398 }
399
400 private:
401 BlockSymbolDependencies &getBlockImmediateDeps(Block &B) {
402 // Check the cache first.
403 auto I = BlockImmediateDepsCache.find(&B);
404 if (I != BlockImmediateDepsCache.end())
405 return I->second;
406
407 BlockSymbolDependencies BIDCacheVal;
408 for (auto &E : B.edges()) {
409 auto &Tgt = E.getTarget();
410 if (Tgt.getScope() != Scope::Local) {
411 if (Tgt.isExternal())
412 BIDCacheVal.External.insert(getInternedName(Tgt));
413 else
414 BIDCacheVal.Internal.insert(getInternedName(Tgt));
415 }
416 }
417
418 return BlockImmediateDepsCache
419 .insert(std::make_pair(&B, std::move(BIDCacheVal)))
420 .first->second;
421 }
422
428 };
429
430 Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) {
431 auto &ES = Layer.getExecutionSession();
432
433 SymbolFlagsMap NewSymbolsToClaim;
434 std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
435
436 auto ProcessSymbol = [&](Symbol *Sym) {
437 if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak &&
438 Sym->getScope() != Scope::Local) {
439 auto Name = ES.intern(Sym->getName());
440 if (!MR->getSymbols().count(ES.intern(Sym->getName()))) {
441 NewSymbolsToClaim[Name] =
442 getJITSymbolFlagsForSymbol(*Sym) | JITSymbolFlags::Weak;
443 NameToSym.push_back(std::make_pair(std::move(Name), Sym));
444 }
445 }
446 };
447
448 for (auto *Sym : G.defined_symbols())
449 ProcessSymbol(Sym);
450 for (auto *Sym : G.absolute_symbols())
451 ProcessSymbol(Sym);
452
453 // Attempt to claim all weak defs that we're not already responsible for.
454 // This cannot fail -- any clashes will just result in rejection of our
455 // claim, at which point we'll externalize that symbol.
456 cantFail(MR->defineMaterializing(std::move(NewSymbolsToClaim)));
457
458 // Walk the list of symbols that we just tried to claim. Symbols that we're
459 // responsible for are marked live. Symbols that we're not responsible for
460 // are turned into external references.
461 for (auto &KV : NameToSym) {
462 if (MR->getSymbols().count(KV.first))
463 KV.second->setLive(true);
464 else
465 G.makeExternal(*KV.second);
466 }
467
468 return Error::success();
469 }
470
471 Error markResponsibilitySymbolsLive(LinkGraph &G) const {
472 auto &ES = Layer.getExecutionSession();
473 for (auto *Sym : G.defined_symbols())
474 if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName())))
475 Sym->setLive(true);
476 return Error::success();
477 }
478
479 Error computeNamedSymbolDependencies(LinkGraph &G) {
480 auto &ES = MR->getTargetJITDylib().getExecutionSession();
481 auto BlockDeps = computeBlockNonLocalDeps(G);
482
483 // Compute dependencies for symbols defined in the JITLink graph.
484 for (auto *Sym : G.defined_symbols()) {
485
486 // Skip local symbols: we do not track dependencies for these.
487 if (Sym->getScope() == Scope::Local)
488 continue;
489 assert(Sym->hasName() &&
490 "Defined non-local jitlink::Symbol should have a name");
491
492 auto &SymDeps = BlockDeps[Sym->getBlock()];
493 if (SymDeps.External.empty() && SymDeps.Internal.empty())
494 continue;
495
496 auto SymName = ES.intern(Sym->getName());
497 if (!SymDeps.External.empty())
498 ExternalNamedSymbolDeps[SymName] = SymDeps.External;
499 if (!SymDeps.Internal.empty())
500 InternalNamedSymbolDeps[SymName] = SymDeps.Internal;
501 }
502
503 for (auto &P : Layer.Plugins) {
504 auto SynthDeps = P->getSyntheticSymbolDependencies(*MR);
505 if (SynthDeps.empty())
506 continue;
507
508 DenseSet<Block *> BlockVisited;
509 for (auto &KV : SynthDeps) {
510 auto &Name = KV.first;
511 auto &DepsForName = KV.second;
512 for (auto *Sym : DepsForName) {
513 if (Sym->getScope() == Scope::Local) {
514 auto &BDeps = BlockDeps[Sym->getBlock()];
515 for (auto &S : BDeps.Internal)
516 InternalNamedSymbolDeps[Name].insert(S);
517 for (auto &S : BDeps.External)
518 ExternalNamedSymbolDeps[Name].insert(S);
519 } else {
520 if (Sym->isExternal())
521 ExternalNamedSymbolDeps[Name].insert(
522 BlockDeps.getInternedName(*Sym));
523 else
524 InternalNamedSymbolDeps[Name].insert(
525 BlockDeps.getInternedName(*Sym));
526 }
527 }
528 }
529 }
530
531 return Error::success();
532 }
533
534 BlockDependenciesMap computeBlockNonLocalDeps(LinkGraph &G) {
535 // First calculate the reachable-via-non-local-symbol blocks for each block.
536 struct BlockInfo {
537 DenseSet<Block *> Dependencies;
538 DenseSet<Block *> Dependants;
539 bool DependenciesChanged = true;
540 };
542 SmallVector<Block *> WorkList;
543
544 // Pre-allocate map entries. This prevents any iterator/reference
545 // invalidation in the next loop.
546 for (auto *B : G.blocks())
547 (void)BlockInfos[B];
548
549 // Build initial worklist, record block dependencies/dependants and
550 // non-local symbol dependencies.
551 for (auto *B : G.blocks()) {
552 auto &BI = BlockInfos[B];
553 for (auto &E : B->edges()) {
554 if (E.getTarget().getScope() == Scope::Local &&
555 !E.getTarget().isAbsolute()) {
556 auto &TgtB = E.getTarget().getBlock();
557 if (&TgtB != B) {
558 BI.Dependencies.insert(&TgtB);
559 BlockInfos[&TgtB].Dependants.insert(B);
560 }
561 }
562 }
563
564 // If this node has both dependants and dependencies then add it to the
565 // worklist to propagate the dependencies to the dependants.
566 if (!BI.Dependants.empty() && !BI.Dependencies.empty())
567 WorkList.push_back(B);
568 }
569
570 // Propagate block-level dependencies through the block-dependence graph.
571 while (!WorkList.empty()) {
572 auto *B = WorkList.pop_back_val();
573
574 auto &BI = BlockInfos[B];
575 assert(BI.DependenciesChanged &&
576 "Block in worklist has unchanged dependencies");
577 BI.DependenciesChanged = false;
578 for (auto *Dependant : BI.Dependants) {
579 auto &DependantBI = BlockInfos[Dependant];
580 for (auto *Dependency : BI.Dependencies) {
581 if (Dependant != Dependency &&
582 DependantBI.Dependencies.insert(Dependency).second)
583 if (!DependantBI.DependenciesChanged) {
584 DependantBI.DependenciesChanged = true;
585 WorkList.push_back(Dependant);
586 }
587 }
588 }
589 }
590
592 for (auto &KV : BlockInfos)
593 BlockDeps[KV.first] = std::move(KV.second.Dependencies);
594
595 return BlockDependenciesMap(Layer.getExecutionSession(),
596 std::move(BlockDeps));
597 }
598
599 void registerDependencies(const SymbolDependenceMap &QueryDeps) {
600 for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) {
601 auto &Name = NamedDepsEntry.first;
602 auto &NameDeps = NamedDepsEntry.second;
603 SymbolDependenceMap SymbolDeps;
604
605 for (const auto &QueryDepsEntry : QueryDeps) {
606 JITDylib &SourceJD = *QueryDepsEntry.first;
607 const SymbolNameSet &Symbols = QueryDepsEntry.second;
608 auto &DepsForJD = SymbolDeps[&SourceJD];
609
610 for (const auto &S : Symbols)
611 if (NameDeps.count(S))
612 DepsForJD.insert(S);
613
614 if (DepsForJD.empty())
615 SymbolDeps.erase(&SourceJD);
616 }
617
618 MR->addDependencies(Name, SymbolDeps);
619 }
620 }
621
622 ObjectLinkingLayer &Layer;
623 std::unique_ptr<MaterializationResponsibility> MR;
624 std::unique_ptr<MemoryBuffer> ObjBuffer;
625 DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps;
626 DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps;
627};
628
630
632
634
636 : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
637 ES.registerResourceManager(*this);
638}
639
641 JITLinkMemoryManager &MemMgr)
642 : BaseT(ES), MemMgr(MemMgr) {
643 ES.registerResourceManager(*this);
644}
645
647 ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
648 : BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) {
649 ES.registerResourceManager(*this);
650}
651
653 assert(Allocs.empty() && "Layer destroyed with resources still attached");
654 getExecutionSession().deregisterResourceManager(*this);
655}
656
658 std::unique_ptr<LinkGraph> G) {
659 auto &JD = RT->getJITDylib();
660 return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)),
661 std::move(RT));
662}
663
664void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
665 std::unique_ptr<MemoryBuffer> O) {
666 assert(O && "Object must not be null");
667 MemoryBufferRef ObjBuffer = O->getMemBufferRef();
668
669 auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
670 *this, std::move(R), std::move(O));
671 if (auto G = createLinkGraphFromObject(ObjBuffer)) {
672 Ctx->notifyMaterializing(**G);
673 link(std::move(*G), std::move(Ctx));
674 } else {
675 Ctx->notifyFailed(G.takeError());
676 }
677}
678
679void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
680 std::unique_ptr<LinkGraph> G) {
681 auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
682 *this, std::move(R), nullptr);
683 Ctx->notifyMaterializing(*G);
684 link(std::move(G), std::move(Ctx));
685}
686
687void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
688 LinkGraph &G,
689 PassConfiguration &PassConfig) {
690 for (auto &P : Plugins)
691 P->modifyPassConfig(MR, G, PassConfig);
692}
693
694void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
695 for (auto &P : Plugins)
696 P->notifyLoaded(MR);
697}
698
699Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
700 FinalizedAlloc FA) {
701 Error Err = Error::success();
702 for (auto &P : Plugins)
703 Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
704
705 if (Err)
706 return Err;
707
708 return MR.withResourceKeyDo(
709 [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); });
710}
711
712Error ObjectLinkingLayer::handleRemoveResources(JITDylib &JD, ResourceKey K) {
713
714 {
715 Error Err = Error::success();
716 for (auto &P : Plugins)
717 Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K));
718 if (Err)
719 return Err;
720 }
721
722 std::vector<FinalizedAlloc> AllocsToRemove;
723 getExecutionSession().runSessionLocked([&] {
724 auto I = Allocs.find(K);
725 if (I != Allocs.end()) {
726 std::swap(AllocsToRemove, I->second);
727 Allocs.erase(I);
728 }
729 });
730
731 if (AllocsToRemove.empty())
732 return Error::success();
733
734 return MemMgr.deallocate(std::move(AllocsToRemove));
735}
736
737void ObjectLinkingLayer::handleTransferResources(JITDylib &JD,
738 ResourceKey DstKey,
739 ResourceKey SrcKey) {
740 auto I = Allocs.find(SrcKey);
741 if (I != Allocs.end()) {
742 auto &SrcAllocs = I->second;
743 auto &DstAllocs = Allocs[DstKey];
744 DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
745 for (auto &Alloc : SrcAllocs)
746 DstAllocs.push_back(std::move(Alloc));
747
748 // Erase SrcKey entry using value rather than iterator I: I may have been
749 // invalidated when we looked up DstKey.
750 Allocs.erase(SrcKey);
751 }
752
753 for (auto &P : Plugins)
754 P->notifyTransferringResources(JD, DstKey, SrcKey);
755}
756
758 ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
759 : ES(ES), Registrar(std::move(Registrar)) {}
760
763 PassConfiguration &PassConfig) {
764
765 PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
766 G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
767 if (Addr) {
768 std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
769 assert(!InProcessLinks.count(&MR) &&
770 "Link for MR already being tracked?");
771 InProcessLinks[&MR] = {Addr, Size};
772 }
773 }));
774}
775
778
779 ExecutorAddrRange EmittedRange;
780 {
781 std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
782
783 auto EHFrameRangeItr = InProcessLinks.find(&MR);
784 if (EHFrameRangeItr == InProcessLinks.end())
785 return Error::success();
786
787 EmittedRange = EHFrameRangeItr->second;
788 assert(EmittedRange.Start && "eh-frame addr to register can not be null");
789 InProcessLinks.erase(EHFrameRangeItr);
790 }
791
792 if (auto Err = MR.withResourceKeyDo(
793 [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
794 return Err;
795
796 return Registrar->registerEHFrames(EmittedRange);
797}
798
801 std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
802 InProcessLinks.erase(&MR);
803 return Error::success();
804}
805
807 ResourceKey K) {
808 std::vector<ExecutorAddrRange> RangesToRemove;
809
810 ES.runSessionLocked([&] {
811 auto I = EHFrameRanges.find(K);
812 if (I != EHFrameRanges.end()) {
813 RangesToRemove = std::move(I->second);
814 EHFrameRanges.erase(I);
815 }
816 });
817
818 Error Err = Error::success();
819 while (!RangesToRemove.empty()) {
820 auto RangeToRemove = RangesToRemove.back();
821 RangesToRemove.pop_back();
822 assert(RangeToRemove.Start && "Untracked eh-frame range must not be null");
823 Err = joinErrors(std::move(Err),
824 Registrar->deregisterEHFrames(RangeToRemove));
825 }
826
827 return Err;
828}
829
831 JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {
832 auto SI = EHFrameRanges.find(SrcKey);
833 if (SI == EHFrameRanges.end())
834 return;
835
836 auto DI = EHFrameRanges.find(DstKey);
837 if (DI != EHFrameRanges.end()) {
838 auto &SrcRanges = SI->second;
839 auto &DstRanges = DI->second;
840 DstRanges.reserve(DstRanges.size() + SrcRanges.size());
841 for (auto &SrcRange : SrcRanges)
842 DstRanges.push_back(std::move(SrcRange));
843 EHFrameRanges.erase(SI);
844 } else {
845 // We need to move SrcKey's ranges over without invalidating the SI
846 // iterator.
847 auto Tmp = std::move(SI->second);
848 EHFrameRanges.erase(SI);
849 EHFrameRanges[DstKey] = std::move(Tmp);
850 }
851}
852
853} // End namespace orc.
854} // End namespace llvm.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
uint64_t Addr
std::string Name
uint64_t Size
RelaxConfig Config
Definition: ELF_riscv.cpp:504
Symbol * Sym
Definition: ELF_riscv.cpp:477
#define I(x, y, z)
Definition: MD5.cpp:58
#define G(x, y, z)
Definition: MD5.cpp:56
#define P(N)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:155
bool erase(const KeyT &Val)
Definition: DenseMap.h:329
unsigned size() const
Definition: DenseMap.h:99
bool empty() const
Definition: DenseMap.h:98
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:151
iterator end()
Definition: DenseMap.h:84
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:220
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:334
Tagged union holding either a T or a Error.
Definition: Error.h:474
Flags for symbols in the JIT.
Definition: JITSymbol.h:74
bool empty() const
Definition: SmallVector.h:94
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) override
Error notifyEmitted(MaterializationResponsibility &MR) override
Error notifyFailed(MaterializationResponsibility &MR) override
EHFrameRegistrationPlugin(ExecutionSession &ES, std::unique_ptr< jitlink::EHFrameRegistrar > Registrar)
Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override
void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &G, jitlink::PassConfiguration &PassConfig) override
An ExecutionSession represents a running JIT program.
Definition: Core.h:1389
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
Definition: Core.h:1446
void registerResourceManager(ResourceManager &RM)
Register the given ResourceManager with this ExecutionSession.
Definition: Core.cpp:1956
decltype(auto) runSessionLocked(Func &&F)
Run the given lambda with the session mutex locked.
Definition: Core.h:1456
Represents an address in the executor process.
uint64_t getValue() const
Represents a JIT'd dynamic library.
Definition: Core.h:958
Error define(std::unique_ptr< MaterializationUnitType > &&MU, ResourceTrackerSP RT=nullptr)
Define all symbols provided by the materialization unit to be part of this JITDylib.
Definition: Core.h:1849
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Definition: Core.h:527
Error withResourceKeyDo(Func &&F) const
Runs the given callback under the session lock, passing in the associated ResourceKey.
Definition: Core.h:543
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
Definition: Core.h:662
virtual StringRef getName() const =0
Return the name of this materialization unit.
virtual void materialize(std::unique_ptr< MaterializationResponsibility > R)=0
Implementations of this method should materialize all symbols in the materialzation unit,...
ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer &Layer, std::unique_ptr< MaterializationResponsibility > MR, std::unique_ptr< MemoryBuffer > ObjBuffer)
void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override
Called by JITLink to notify the context that the object has been finalized (i.e.
void notifyFailed(Error Err) override
Notify this context that linking failed.
void lookup(const LookupMap &Symbols, std::unique_ptr< JITLinkAsyncLookupContinuation > LC) override
Called by JITLink to resolve external symbols.
Error notifyResolved(LinkGraph &G) override
Called by JITLink once all defined symbols in the graph have been assigned their final memory locatio...
JITLinkMemoryManager & getMemoryManager() override
Return the MemoryManager to be used for this link.
LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override
Returns the mark-live pass to be used for this link.
Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override
Called by JITLink to modify the pass pipeline prior to linking.
An ObjectLayer implementation built on JITLink.
ObjectLinkingLayer(ExecutionSession &ES)
Construct an ObjectLinkingLayer using the ExecutorProcessControl instance's memory manager.
Error add(ResourceTrackerSP, std::unique_ptr< jitlink::LinkGraph > G)
Add a LinkGraph to the JITDylib targeted by the given tracker.
void emit(std::unique_ptr< MaterializationResponsibility > R, std::unique_ptr< MemoryBuffer > O) override
Emit an object file.
~ObjectLinkingLayer()
Destruct an ObjectLinkingLayer.
JITDylib & getJITDylib() const
Return the JITDylib targeted by this tracker.
Definition: Core.h:71
A set of symbols to look up, each associated with a SymbolLookupFlags value.
Definition: Core.h:183
SymbolLookupSet & add(SymbolStringPtr Name, SymbolLookupFlags Flags=SymbolLookupFlags::RequiredSymbol)
Add an element to the set.
Definition: Core.h:244
Pointer to a pooled string representing a symbol name.
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:642
unique_function is a type-erasing functor similar to std::function.
std::vector< std::pair< JITDylib *, JITDylibLookupFlags > > JITDylibSearchOrder
A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search order during symbol lookup.
Definition: Core.h:162
SymbolLookupFlags
Lookup flags that apply to each symbol in a lookup.
Definition: Core.h:145
bool isMachOInitializerSection(StringRef SegName, StringRef SecName)
std::vector< SymbolStringPtr > SymbolNameVector
A vector of symbol names.
Definition: Core.h:117
@ Resolved
Queried, materialization begun.
uintptr_t ResourceKey
Definition: Core.h:53
bool isELFInitializerSection(StringRef SecName)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:431
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:749
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1853
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
Represents an address range in the exceutor process.