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