18#define DEBUG_TYPE "orc"
51 : Parent(Parent), I(
std::
move(I)) {}
55 return LHS.I == RHS.I;
59 return LHS.I != RHS.I;
72 assert(Parent->Graph &&
"No pointer to BlockDepInfoMap");
73 return &(*Parent->Graph)[*I];
96 switch (
TT.getArch()) {
121 std::unique_ptr<MaterializationResponsibility> MR,
122 std::unique_ptr<MemoryBuffer> ObjBuffer)
125 std::lock_guard<std::mutex> Lock(Layer.LayerMutex);
126 Plugins = Layer.Plugins;
132 if (Layer.ReturnObjectBuffer && ObjBuffer)
133 Layer.ReturnObjectBuffer(std::move(ObjBuffer));
139 for (
auto &
P : Plugins)
140 P->notifyMaterializing(*MR,
G, *
this,
141 ObjBuffer ? ObjBuffer->getMemBufferRef()
146 for (
auto &
P : Plugins)
147 Err =
joinErrors(std::move(Err),
P->notifyFailed(*MR));
148 Layer.getExecutionSession().reportError(std::move(Err));
149 MR->failMaterialization();
153 std::unique_ptr<JITLinkAsyncLookupContinuation> LC)
override {
156 MR->getTargetJITDylib().withLinkOrderDo(
159 auto &ES = Layer.getExecutionSession();
162 for (
auto &KV : Symbols) {
172 LookupSet.
add(KV.first, LookupFlags);
176 auto OnResolve = [LookupContinuation =
179 LookupContinuation->run(
Result.takeError());
183 LookupContinuation->run(std::move(LR));
191 for (
auto &[DepJD, Deps] : Deps)
192 for (
auto &DepSym : Deps)
200 bool AutoClaim = Layer.AutoClaimObjectSymbols;
203 for (
auto *Sym :
G.defined_symbols())
205 auto Ptr = getJITSymbolPtrForSymbol(*Sym,
G.getTargetTriple());
207 InternedResult[Sym->
getName()] = {Ptr, Flags};
208 if (AutoClaim && !MR->getSymbols().count(Sym->
getName())) {
210 "Duplicate symbol to claim?");
211 ExtraSymbolsToClaim[Sym->
getName()] = Flags;
215 for (
auto *Sym :
G.absolute_symbols())
217 auto Ptr = getJITSymbolPtrForSymbol(*Sym,
G.getTargetTriple());
219 InternedResult[Sym->
getName()] = {Ptr, Flags};
220 if (AutoClaim && !MR->getSymbols().count(Sym->
getName())) {
222 "Duplicate symbol to claim?");
223 ExtraSymbolsToClaim[Sym->
getName()] = Flags;
227 if (!ExtraSymbolsToClaim.
empty())
228 if (
auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
238 size_t NumMaterializationSideEffectsOnlySymbols = 0;
240 for (
auto &[Sym, Flags] : MR->getSymbols()) {
242 auto I = InternedResult.
find(Sym);
247 if (Flags.hasMaterializationSideEffectsOnly())
248 ++NumMaterializationSideEffectsOnlySymbols;
249 else if (
I == InternedResult.
end())
250 MissingSymbols.push_back(Sym);
251 else if (Layer.OverrideObjectFlags)
252 I->second.setFlags(Flags);
256 if (!MissingSymbols.empty())
258 Layer.getExecutionSession().getSymbolStringPool(),
G.getName(),
259 std::move(MissingSymbols));
264 if (InternedResult.
size() >
265 MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
266 for (
auto &KV : InternedResult)
267 if (!MR->getSymbols().count(KV.first))
268 ExtraSymbols.push_back(KV.first);
272 if (!ExtraSymbols.empty())
274 Layer.getExecutionSession().getSymbolStringPool(),
G.getName(),
275 std::move(ExtraSymbols));
278 if (
auto Err = MR->notifyResolved(InternedResult))
286 Layer.getExecutionSession().reportError(std::move(Err));
287 MR->failMaterialization();
291 if (
auto Err = MR->notifyEmitted(SymbolDepGroups)) {
292 Layer.getExecutionSession().reportError(std::move(Err));
293 MR->failMaterialization();
298 return [
this](
LinkGraph &
G) {
return markResponsibilitySymbolsLive(
G); };
305 return claimOrExternalizeWeakAndCommonSymbols(
G);
308 for (
auto &
P : Plugins)
309 P->modifyPassConfig(*MR, LG, Config);
312 [
this](
LinkGraph &
G) {
return registerDependencies(
G); });
319 for (
auto &
P : Plugins)
320 Err =
joinErrors(std::move(Err),
P->notifyEmitted(*MR));
325 joinErrors(std::move(Err), Layer.MemMgr.deallocate(std::move(FA)));
330 return Layer.recordFinalizedAlloc(*MR, std::move(FA));
338 std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
340 auto ProcessSymbol = [&](
Symbol *Sym) {
343 if (!MR->getSymbols().count(Sym->
getName())) {
344 NewSymbolsToClaim[Sym->
getName()] =
346 NameToSym.push_back(std::make_pair(Sym->
getName(), Sym));
351 for (
auto *Sym :
G.defined_symbols())
353 for (
auto *Sym :
G.absolute_symbols())
359 if (
auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim)))
365 for (
auto &KV : NameToSym) {
366 if (MR->getSymbols().count(KV.first))
367 KV.second->setLive(
true);
369 G.makeExternal(*KV.second);
375 Error markResponsibilitySymbolsLive(LinkGraph &
G)
const {
376 for (
auto *Sym :
G.defined_symbols())
382 Error registerDependencies(LinkGraph &
G) {
383 auto &TargetJD = MR->getTargetJITDylib();
384 for (
auto &[Defs, Deps] : calculateDepGroups(
G)) {
385 SymbolDepGroups.push_back(SymbolDependenceGroup());
386 auto &SDG = SymbolDepGroups.back();
387 for (
auto *Def : Defs)
388 SDG.Symbols.insert(
Def->getName());
389 for (
auto *Dep : Deps) {
390 if (Dep->isDefined())
391 SDG.Dependencies[&TargetJD].insert(Dep->getName());
394 SymbolSourceJDs.find(NonOwningSymbolStringPtr(Dep->getName()));
395 if (
I != SymbolSourceJDs.end()) {
396 auto &SymJD = *
I->second;
397 SDG.Dependencies[&SymJD].insert(Dep->getName());
406 std::vector<std::shared_ptr<LinkGraphLinkingLayer::Plugin>> Plugins;
407 std::unique_ptr<MaterializationResponsibility> MR;
408 std::unique_ptr<MemoryBuffer> ObjBuffer;
409 DenseMap<NonOwningSymbolStringPtr, JITDylib *> SymbolSourceJDs;
410 std::vector<SymbolDependenceGroup> SymbolDepGroups;
416 :
LinkGraphLayer(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
417 ES.registerResourceManager(*
this);
423 ES.registerResourceManager(*
this);
434 "Layer destroyed with resources still attached "
435 "(ExecutionSession::endSession() must be called prior to "
441 std::unique_ptr<MaterializationResponsibility> R,
442 std::unique_ptr<LinkGraph>
G) {
443 assert(R &&
"R must not be null");
444 assert(
G &&
"G must not be null");
445 auto Ctx = std::make_unique<JITLinkCtx>(*
this, std::move(R),
nullptr);
446 Ctx->notifyMaterializing(*
G);
447 link(std::move(
G), std::move(Ctx));
451 std::unique_ptr<MaterializationResponsibility> R,
452 std::unique_ptr<LinkGraph>
G, std::unique_ptr<MemoryBuffer> ObjBuf) {
453 assert(R &&
"R must not be null");
454 assert(
G &&
"G must not be null");
455 assert(ObjBuf &&
"Object must not be null");
457 std::make_unique<JITLinkCtx>(*
this, std::move(R), std::move(ObjBuf));
458 Ctx->notifyMaterializing(*
G);
459 link(std::move(
G), std::move(Ctx));
463LinkGraphLinkingLayer::calculateDepGroups(
LinkGraph &
G) {
468 for (
auto *Sym :
G.defined_symbols())
470 BlockDepInfos[&Sym->
getBlock()].SymbolDefs.push_back(Sym);
482 for (
auto &[
B, BDInfo] : BlockDepInfos) {
483 BDInfo.Graph = &BlockDepInfos;
495 while (!Worklist.
empty()) {
497 BlockDepInfo *BDInfo =
nullptr;
499 for (
auto &
E :
B->edges()) {
500 if (
E.getTarget().isAbsolute())
504 BDInfo = &BlockDepInfos[
B];
506 if (
E.getTarget().isExternal()) {
512 auto *TgtB = &
E.getTarget().getBlock();
513 auto I = BlockDepInfos.find(TgtB);
515 if (
I != BlockDepInfos.end()) {
518 auto &TgtBInfo =
I->second;
519 if (!TgtBInfo.SymbolDefs.empty())
530 BlockDepInfos[TgtB].Graph = &BlockDepInfos;
541 for (
auto &[
B, BDInfo] : BlockDepInfos) {
544 auto &SCCRootInfo = *
SCC.front();
549 if (SCCRootInfo.SCCRoot)
551 SCCRootInfo.SCCRoot = &SCCRootInfo;
555 auto SCCSymbolDefs = std::move(SCCRootInfo.SymbolDefs);
556 auto SCCSymbolDeps = std::move(SCCRootInfo.SymbolDeps);
557 auto SCCAnonBlockDeps = std::move(SCCRootInfo.AnonBlockDeps);
559 SCCBInfo->SCCRoot = &SCCRootInfo;
560 SCCSymbolDefs.append(SCCBInfo->SymbolDefs);
561 SCCBInfo->SymbolDefs.clear();
562 SCCSymbolDeps.insert(SCCBInfo->SymbolDeps.begin(),
563 SCCBInfo->SymbolDeps.end());
564 SCCBInfo->SymbolDeps.clear();
565 SCCAnonBlockDeps.insert(SCCBInfo->AnonBlockDeps.begin(),
566 SCCBInfo->AnonBlockDeps.end());
567 SCCBInfo->AnonBlockDeps.clear();
572 DenseSet<size_t> SrcDepGroups;
573 for (
auto *DepB : SCCAnonBlockDeps) {
574 assert(BlockDepInfos.count(DepB) &&
"Unrecognized block");
575 auto &DepBRootInfo = *BlockDepInfos[DepB].SCCRoot;
576 if (DepBRootInfo.DepGroupIndex)
577 SrcDepGroups.
insert(*DepBRootInfo.DepGroupIndex);
582 if (SrcDepGroups.
empty()) {
586 if (!SCCSymbolDeps.empty()) {
587 SCCRootInfo.DepGroupIndex = DGs.
size();
589 DGs.
back().Defs = std::move(SCCSymbolDefs);
590 DGs.
back().Deps = std::move(SCCSymbolDeps);
599 if (SrcDepGroups.
size() == 1 && SCCSymbolDeps.empty()) {
600 SCCRootInfo.DepGroupIndex = *SrcDepGroups.
begin();
601 DGs[*SCCRootInfo.DepGroupIndex].Defs.
append(SCCSymbolDefs);
607 SCCRootInfo.DepGroupIndex = DGs.
size();
609 auto &DG = DGs.
back();
610 DG.Defs = std::move(SCCSymbolDefs);
611 for (
auto &DGIndex : SrcDepGroups)
612 DG.Deps.insert(DGs[DGIndex].Deps.begin(), DGs[DGIndex].Deps.end());
613 DG.Deps.insert(SCCSymbolDeps.begin(), SCCSymbolDeps.end());
619 for (
size_t I = 0;
I != DGs.
size();) {
623 for (
auto &Def : DG.Defs)
627 if (DG.Defs.empty() || DG.Deps.empty()) {
637Error LinkGraphLinkingLayer::recordFinalizedAlloc(
640 [&](
ResourceKey K) { Allocs[
K].push_back(std::move(FA)); });
643 Err =
joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA)));
648Error LinkGraphLinkingLayer::handleRemoveResources(
JITDylib &JD,
653 for (
auto &
P : Plugins)
654 Err =
joinErrors(std::move(Err),
P->notifyRemovingResources(JD, K));
659 std::vector<FinalizedAlloc> AllocsToRemove;
661 auto I = Allocs.find(K);
662 if (
I != Allocs.end()) {
668 if (AllocsToRemove.empty())
671 return MemMgr.deallocate(std::move(AllocsToRemove));
674void LinkGraphLinkingLayer::handleTransferResources(
JITDylib &JD,
677 if (Allocs.contains(SrcKey)) {
680 auto &DstAllocs = Allocs[DstKey];
681 auto &SrcAllocs = Allocs[SrcKey];
682 DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
683 for (
auto &
Alloc : SrcAllocs)
684 DstAllocs.push_back(std::move(
Alloc));
686 Allocs.erase(SrcKey);
689 for (
auto &
P : Plugins)
690 P->notifyTransferringResources(JD, DstKey, SrcKey);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
iterator find(const_arg_type_t< KeyT > Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
void insert_range(Range &&R)
Inserts range of 'std::pair<KeyT, ValueT>' values into the map.
Implements a dense probed hash-table based set.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
friend bool operator!=(const ChildIteratorType &LHS, const ChildIteratorType &RHS)
ChildIteratorType(NodeRef Parent, impl_iterator I)
friend bool operator==(const ChildIteratorType &LHS, const ChildIteratorType &RHS)
ChildIteratorType & operator++()
ChildIteratorType operator++(int)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Triple - Helper class for working with autoconf configuration names.
std::pair< iterator, bool > insert(const ValueT &V)
DenseSetIterator< false > iterator
JITLinkContext(const JITLinkDylib *JD)
Create a JITLinkContext.
DenseMap< orc::SymbolStringPtr, SymbolLookupFlags > LookupMap
Represents a finalized allocation.
Manages allocations of JIT memory.
bool isCallable() const
Returns true is this symbol is callable.
const orc::SymbolStringPtr & getName() const
Returns the name of this symbol (empty if the symbol is anonymous).
Scope getScope() const
Get the visibility for this Symbol.
Linkage getLinkage() const
Get the linkage for this Symbol.
orc::ExecutorAddr getAddress() const
Returns the address of this symbol.
void setLive(bool IsLive)
Set this symbol's live bit.
Block & getBlock()
Return the Block for this Symbol (Symbol must be defined).
bool hasName() const
Returns true if this symbol has a name.
An ExecutionSession represents a running JIT program.
LLVM_ABI void registerResourceManager(ResourceManager &RM)
Register the given ResourceManager with this ExecutionSession.
LLVM_ABI void deregisterResourceManager(ResourceManager &RM)
Deregister the given ResourceManager with this ExecutionSession.
decltype(auto) runSessionLocked(Func &&F)
Run the given lambda with the session mutex locked.
Represents an address in the executor process.
uint64_t getValue() const
Represents a JIT'd dynamic library.
LinkGraphLayer(ExecutionSession &ES)
ExecutionSession & getExecutionSession()
static JITSymbolFlags getJITSymbolFlagsForSymbol(jitlink::Symbol &Sym)
Get the JITSymbolFlags for the given symbol.
JITLinkCtx(LinkGraphLinkingLayer &Layer, std::unique_ptr< MaterializationResponsibility > MR, std::unique_ptr< MemoryBuffer > ObjBuffer)
void notifyFailed(Error Err) override
Notify this context that linking failed.
void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override
Called by JITLink to notify the context that the object has been finalized (i.e.
JITLinkMemoryManager & getMemoryManager() override
Return the MemoryManager to be used for this link.
Error notifyResolved(LinkGraph &G) override
Called by JITLink once all defined symbols in the graph have been assigned their final memory locatio...
void lookup(const LookupMap &Symbols, std::unique_ptr< JITLinkAsyncLookupContinuation > LC) override
Called by JITLink to resolve external symbols.
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.
void notifyMaterializing(LinkGraph &G)
Error notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA)
~LinkGraphLinkingLayer() override
Destroy the LinkGraphLinkingLayer.
void emit(std::unique_ptr< MaterializationResponsibility > R, std::unique_ptr< jitlink::LinkGraph > G) override
Emit a LinkGraph.
LinkGraphLinkingLayer(ExecutionSession &ES)
Construct a LinkGraphLinkingLayer using the ExecutorProcessControl instance's memory manager.
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Error withResourceKeyDo(Func &&F) const
Runs the given callback under the session lock, passing in the associated ResourceKey.
Non-owning SymbolStringPool entry pointer.
A set of symbols to look up, each associated with a SymbolLookupFlags value.
SymbolLookupSet & add(SymbolStringPtr Name, SymbolLookupFlags Flags=SymbolLookupFlags::RequiredSymbol)
Add an element to the set.
LLVM_ABI bool hasTargetFlags(Symbol &Sym, TargetFlagsType Flags)
Check whether the given target flags are set for this Symbol.
unique_function< Error(LinkGraph &)> LinkGraphPassFunction
A function for mutating LinkGraphs.
LLVM_ABI void link(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
Link the given graph.
DenseMap< orc::SymbolStringPtr, orc::ExecutorSymbolDef > AsyncLookupResult
A map of symbol names to resolved addresses.
std::vector< std::pair< JITDylib *, JITDylibLookupFlags > > JITDylibSearchOrder
A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search order during symbol lookup.
SymbolLookupFlags
Lookup flags that apply to each symbol in a lookup.
DenseMap< SymbolStringPtr, ExecutorSymbolDef > SymbolMap
A map from symbol names (as SymbolStringPtrs) to JITSymbols (address/flags pairs).
std::vector< SymbolStringPtr > SymbolNameVector
A vector of symbol names.
DenseMap< JITDylib *, SymbolNameSet > SymbolDependenceMap
A map from JITDylibs to sets of symbols.
@ Resolved
Queried, materialization begun.
DenseMap< SymbolStringPtr, JITSymbolFlags > SymbolFlagsMap
A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
DenseMap< jitlink::Block *, BlockDepInfo > BlockDepInfoMap
Error joinErrors(Error E1, Error E2)
Concatenate errors.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
scc_iterator< T > scc_end(const T &G)
Construct the end iterator for a deduced graph type T.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
SmallVector< jitlink::Symbol * > SymbolDefList
AnonBlockDepSet AnonBlockDeps
DenseSet< jitlink::Symbol * > SymbolDepSet
std::optional< size_t > DepGroupIndex
DenseSet< jitlink::Block * > AnonBlockDepSet
static NodeRef getEntryNode(NodeRef N)
static ChildIteratorType child_end(NodeRef N)
static ChildIteratorType child_begin(NodeRef N)
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
LinkGraphPassList PreFixupPasses
Pre-fixup passes.
LinkGraphPassList PrePrunePasses
Pre-prune passes.