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