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;
418 ES.registerResourceManager(*
this);
429 "Layer destroyed with resources still attached "
430 "(ExecutionSession::endSession() must be called prior to "
436 std::unique_ptr<MaterializationResponsibility> R,
437 std::unique_ptr<LinkGraph>
G) {
438 assert(R &&
"R must not be null");
439 assert(
G &&
"G must not be null");
440 auto Ctx = std::make_unique<JITLinkCtx>(*
this, std::move(R),
nullptr);
441 Ctx->notifyMaterializing(*
G);
442 link(std::move(
G), std::move(Ctx));
446 std::unique_ptr<MaterializationResponsibility> R,
447 std::unique_ptr<LinkGraph>
G, std::unique_ptr<MemoryBuffer> ObjBuf) {
448 assert(R &&
"R must not be null");
449 assert(
G &&
"G must not be null");
450 assert(ObjBuf &&
"Object must not be null");
452 std::make_unique<JITLinkCtx>(*
this, std::move(R), std::move(ObjBuf));
453 Ctx->notifyMaterializing(*
G);
454 link(std::move(
G), std::move(Ctx));
458LinkGraphLinkingLayer::calculateDepGroups(
LinkGraph &
G) {
463 for (
auto *Sym :
G.defined_symbols())
465 BlockDepInfos[&Sym->
getBlock()].SymbolDefs.push_back(Sym);
477 for (
auto &[
B, BDInfo] : BlockDepInfos) {
478 BDInfo.Graph = &BlockDepInfos;
490 while (!Worklist.
empty()) {
492 BlockDepInfo *BDInfo =
nullptr;
494 for (
auto &
E :
B->edges()) {
495 if (
E.getTarget().isAbsolute())
499 BDInfo = &BlockDepInfos[
B];
501 if (
E.getTarget().isExternal()) {
507 auto *TgtB = &
E.getTarget().getBlock();
508 auto I = BlockDepInfos.find(TgtB);
510 if (
I != BlockDepInfos.end()) {
513 auto &TgtBInfo =
I->second;
514 if (!TgtBInfo.SymbolDefs.empty())
525 BlockDepInfos[TgtB].Graph = &BlockDepInfos;
536 for (
auto &[
B, BDInfo] : BlockDepInfos) {
539 auto &SCCRootInfo = *
SCC.front();
544 if (SCCRootInfo.SCCRoot)
546 SCCRootInfo.SCCRoot = &SCCRootInfo;
550 auto SCCSymbolDefs = std::move(SCCRootInfo.SymbolDefs);
551 auto SCCSymbolDeps = std::move(SCCRootInfo.SymbolDeps);
552 auto SCCAnonBlockDeps = std::move(SCCRootInfo.AnonBlockDeps);
554 SCCBInfo->SCCRoot = &SCCRootInfo;
555 SCCSymbolDefs.append(SCCBInfo->SymbolDefs);
556 SCCBInfo->SymbolDefs.clear();
557 SCCSymbolDeps.insert(SCCBInfo->SymbolDeps.begin(),
558 SCCBInfo->SymbolDeps.end());
559 SCCBInfo->SymbolDeps.clear();
560 SCCAnonBlockDeps.insert(SCCBInfo->AnonBlockDeps.begin(),
561 SCCBInfo->AnonBlockDeps.end());
562 SCCBInfo->AnonBlockDeps.clear();
567 DenseSet<size_t> SrcDepGroups;
568 for (
auto *DepB : SCCAnonBlockDeps) {
569 assert(BlockDepInfos.count(DepB) &&
"Unrecognized block");
570 auto &DepBRootInfo = *BlockDepInfos[DepB].SCCRoot;
571 if (DepBRootInfo.DepGroupIndex)
572 SrcDepGroups.
insert(*DepBRootInfo.DepGroupIndex);
577 if (SrcDepGroups.
empty()) {
581 if (!SCCSymbolDeps.empty()) {
582 SCCRootInfo.DepGroupIndex = DGs.
size();
584 DGs.
back().Defs = std::move(SCCSymbolDefs);
585 DGs.
back().Deps = std::move(SCCSymbolDeps);
594 if (SrcDepGroups.
size() == 1 && SCCSymbolDeps.empty()) {
595 SCCRootInfo.DepGroupIndex = *SrcDepGroups.
begin();
596 DGs[*SCCRootInfo.DepGroupIndex].Defs.
append(SCCSymbolDefs);
602 SCCRootInfo.DepGroupIndex = DGs.
size();
604 auto &DG = DGs.
back();
605 DG.Defs = std::move(SCCSymbolDefs);
606 for (
auto &DGIndex : SrcDepGroups)
607 DG.Deps.insert(DGs[DGIndex].Deps.begin(), DGs[DGIndex].Deps.end());
608 DG.Deps.insert(SCCSymbolDeps.begin(), SCCSymbolDeps.end());
614 for (
size_t I = 0;
I != DGs.
size();) {
618 for (
auto &Def : DG.Defs)
622 if (DG.Defs.empty() || DG.Deps.empty()) {
632Error LinkGraphLinkingLayer::recordFinalizedAlloc(
635 [&](
ResourceKey K) { Allocs[
K].push_back(std::move(FA)); });
638 Err =
joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA)));
643Error LinkGraphLinkingLayer::handleRemoveResources(
JITDylib &JD,
648 for (
auto &
P : Plugins)
649 Err =
joinErrors(std::move(Err),
P->notifyRemovingResources(JD, K));
654 std::vector<FinalizedAlloc> AllocsToRemove;
656 auto I = Allocs.find(K);
657 if (
I != Allocs.end()) {
663 if (AllocsToRemove.empty())
666 return MemMgr.deallocate(std::move(AllocsToRemove));
669void LinkGraphLinkingLayer::handleTransferResources(
JITDylib &JD,
672 if (Allocs.contains(SrcKey)) {
675 auto &DstAllocs = Allocs[DstKey];
676 auto &SrcAllocs = Allocs[SrcKey];
677 DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
678 for (
auto &
Alloc : SrcAllocs)
679 DstAllocs.push_back(std::move(
Alloc));
681 Allocs.erase(SrcKey);
684 for (
auto &
P : Plugins)
685 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, jitlink::JITLinkMemoryManager &MemMgr)
Construct a LinkGraphLinkingLayer.
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.