16#define DEBUG_TYPE "orc"
49 : Parent(Parent), I(
std::
move(I)) {}
53 return LHS.I == RHS.I;
57 return LHS.I != RHS.I;
70 assert(Parent->Graph &&
"No pointer to BlockDepInfoMap");
71 return &(*Parent->Graph)[*I];
94 switch (
TT.getArch()) {
119 std::unique_ptr<MaterializationResponsibility> MR,
120 std::unique_ptr<MemoryBuffer> ObjBuffer)
123 std::lock_guard<std::mutex> Lock(Layer.LayerMutex);
124 Plugins = Layer.Plugins;
130 if (Layer.ReturnObjectBuffer && ObjBuffer)
131 Layer.ReturnObjectBuffer(std::move(ObjBuffer));
137 for (
auto &
P : Plugins)
138 P->notifyMaterializing(*MR,
G, *
this,
139 ObjBuffer ? ObjBuffer->getMemBufferRef()
144 for (
auto &
P : Plugins)
145 Err =
joinErrors(std::move(Err),
P->notifyFailed(*MR));
146 Layer.getExecutionSession().reportError(std::move(Err));
147 MR->failMaterialization();
151 std::unique_ptr<JITLinkAsyncLookupContinuation> LC)
override {
154 MR->getTargetJITDylib().withLinkOrderDo(
157 auto &ES = Layer.getExecutionSession();
160 for (
auto &KV : Symbols) {
170 LookupSet.
add(KV.first, LookupFlags);
174 auto OnResolve = [LookupContinuation =
177 LookupContinuation->run(
Result.takeError());
181 LookupContinuation->run(std::move(LR));
189 for (
auto &[DepJD, Deps] : Deps)
190 for (
auto &DepSym : Deps)
198 bool AutoClaim = Layer.AutoClaimObjectSymbols;
201 for (
auto *Sym :
G.defined_symbols())
203 auto Ptr = getJITSymbolPtrForSymbol(*Sym,
G.getTargetTriple());
205 InternedResult[Sym->
getName()] = {Ptr, Flags};
206 if (AutoClaim && !MR->getSymbols().count(Sym->
getName())) {
208 "Duplicate symbol to claim?");
209 ExtraSymbolsToClaim[Sym->
getName()] = Flags;
213 for (
auto *Sym :
G.absolute_symbols())
215 auto Ptr = getJITSymbolPtrForSymbol(*Sym,
G.getTargetTriple());
217 InternedResult[Sym->
getName()] = {Ptr, Flags};
218 if (AutoClaim && !MR->getSymbols().count(Sym->
getName())) {
220 "Duplicate symbol to claim?");
221 ExtraSymbolsToClaim[Sym->
getName()] = Flags;
225 if (!ExtraSymbolsToClaim.
empty())
226 if (
auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
236 size_t NumMaterializationSideEffectsOnlySymbols = 0;
238 for (
auto &[Sym, Flags] : MR->getSymbols()) {
240 auto I = InternedResult.
find(Sym);
245 if (Flags.hasMaterializationSideEffectsOnly())
246 ++NumMaterializationSideEffectsOnlySymbols;
247 else if (
I == InternedResult.
end())
248 MissingSymbols.push_back(Sym);
249 else if (Layer.OverrideObjectFlags)
250 I->second.setFlags(Flags);
254 if (!MissingSymbols.empty())
256 Layer.getExecutionSession().getSymbolStringPool(),
G.getName(),
257 std::move(MissingSymbols));
262 if (InternedResult.
size() >
263 MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
264 for (
auto &KV : InternedResult)
265 if (!MR->getSymbols().count(KV.first))
266 ExtraSymbols.push_back(KV.first);
270 if (!ExtraSymbols.empty())
272 Layer.getExecutionSession().getSymbolStringPool(),
G.getName(),
273 std::move(ExtraSymbols));
276 if (
auto Err = MR->notifyResolved(InternedResult))
284 Layer.getExecutionSession().reportError(std::move(Err));
285 MR->failMaterialization();
289 if (
auto Err = MR->notifyEmitted(SymbolDepGroups)) {
290 Layer.getExecutionSession().reportError(std::move(Err));
291 MR->failMaterialization();
296 return [
this](
LinkGraph &
G) {
return markResponsibilitySymbolsLive(
G); };
303 return claimOrExternalizeWeakAndCommonSymbols(
G);
306 for (
auto &
P : Plugins)
307 P->modifyPassConfig(*MR, LG, Config);
310 [
this](
LinkGraph &
G) {
return registerDependencies(
G); });
317 for (
auto &
P : Plugins)
318 Err =
joinErrors(std::move(Err),
P->notifyEmitted(*MR));
323 joinErrors(std::move(Err), Layer.MemMgr.deallocate(std::move(FA)));
328 return Layer.recordFinalizedAlloc(*MR, std::move(FA));
336 std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
338 auto ProcessSymbol = [&](
Symbol *Sym) {
341 if (!MR->getSymbols().count(Sym->
getName())) {
342 NewSymbolsToClaim[Sym->
getName()] =
344 NameToSym.push_back(std::make_pair(Sym->
getName(), Sym));
349 for (
auto *Sym :
G.defined_symbols())
351 for (
auto *Sym :
G.absolute_symbols())
357 if (
auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim)))
363 for (
auto &KV : NameToSym) {
364 if (MR->getSymbols().count(KV.first))
365 KV.second->setLive(
true);
367 G.makeExternal(*KV.second);
373 Error markResponsibilitySymbolsLive(LinkGraph &
G)
const {
374 for (
auto *Sym :
G.defined_symbols())
380 Error registerDependencies(LinkGraph &
G) {
381 auto &TargetJD = MR->getTargetJITDylib();
382 for (
auto &[Defs, Deps] : calculateDepGroups(
G)) {
383 SymbolDepGroups.push_back(SymbolDependenceGroup());
384 auto &SDG = SymbolDepGroups.back();
385 for (
auto *Def : Defs)
386 SDG.Symbols.insert(
Def->getName());
387 for (
auto *Dep : Deps) {
388 if (Dep->isDefined())
389 SDG.Dependencies[&TargetJD].insert(Dep->getName());
392 SymbolSourceJDs.find(NonOwningSymbolStringPtr(Dep->getName()));
393 if (
I != SymbolSourceJDs.end()) {
394 auto &SymJD = *
I->second;
395 SDG.Dependencies[&SymJD].insert(Dep->getName());
404 std::vector<std::shared_ptr<LinkGraphLinkingLayer::Plugin>> Plugins;
405 std::unique_ptr<MaterializationResponsibility> MR;
406 std::unique_ptr<MemoryBuffer> ObjBuffer;
407 DenseMap<NonOwningSymbolStringPtr, JITDylib *> SymbolSourceJDs;
408 std::vector<SymbolDependenceGroup> SymbolDepGroups;
416 ES.registerResourceManager(*
this);
427 "Layer destroyed with resources still attached "
428 "(ExecutionSession::endSession() must be called prior to "
434 std::unique_ptr<MaterializationResponsibility> R,
435 std::unique_ptr<LinkGraph>
G) {
436 assert(R &&
"R must not be null");
437 assert(
G &&
"G must not be null");
438 auto Ctx = std::make_unique<JITLinkCtx>(*
this, std::move(R),
nullptr);
439 Ctx->notifyMaterializing(*
G);
440 link(std::move(
G), std::move(Ctx));
444 std::unique_ptr<MaterializationResponsibility> R,
445 std::unique_ptr<LinkGraph>
G, std::unique_ptr<MemoryBuffer> ObjBuf) {
446 assert(R &&
"R must not be null");
447 assert(
G &&
"G must not be null");
448 assert(ObjBuf &&
"Object must not be null");
450 std::make_unique<JITLinkCtx>(*
this, std::move(R), std::move(ObjBuf));
451 Ctx->notifyMaterializing(*
G);
452 link(std::move(
G), std::move(Ctx));
456LinkGraphLinkingLayer::calculateDepGroups(
LinkGraph &
G) {
461 for (
auto *Sym :
G.defined_symbols())
463 BlockDepInfos[&Sym->
getBlock()].SymbolDefs.push_back(Sym);
475 for (
auto &[
B, BDInfo] : BlockDepInfos) {
476 BDInfo.Graph = &BlockDepInfos;
488 while (!Worklist.
empty()) {
490 BlockDepInfo *BDInfo =
nullptr;
492 for (
auto &
E :
B->edges()) {
493 if (
E.getTarget().isAbsolute())
497 BDInfo = &BlockDepInfos[
B];
499 if (
E.getTarget().isExternal()) {
505 auto *TgtB = &
E.getTarget().getBlock();
506 auto I = BlockDepInfos.find(TgtB);
508 if (
I != BlockDepInfos.end()) {
511 auto &TgtBInfo =
I->second;
512 if (!TgtBInfo.SymbolDefs.empty())
523 BlockDepInfos[TgtB].Graph = &BlockDepInfos;
534 for (
auto &[
B, BDInfo] : BlockDepInfos) {
537 auto &SCCRootInfo = *
SCC.front();
542 if (SCCRootInfo.SCCRoot)
544 SCCRootInfo.SCCRoot = &SCCRootInfo;
548 auto SCCSymbolDefs = std::move(SCCRootInfo.SymbolDefs);
549 auto SCCSymbolDeps = std::move(SCCRootInfo.SymbolDeps);
550 auto SCCAnonBlockDeps = std::move(SCCRootInfo.AnonBlockDeps);
552 SCCBInfo->SCCRoot = &SCCRootInfo;
553 SCCSymbolDefs.append(SCCBInfo->SymbolDefs);
554 SCCBInfo->SymbolDefs.clear();
555 SCCSymbolDeps.insert(SCCBInfo->SymbolDeps.begin(),
556 SCCBInfo->SymbolDeps.end());
557 SCCBInfo->SymbolDeps.clear();
558 SCCAnonBlockDeps.insert(SCCBInfo->AnonBlockDeps.begin(),
559 SCCBInfo->AnonBlockDeps.end());
560 SCCBInfo->AnonBlockDeps.clear();
565 DenseSet<size_t> SrcDepGroups;
566 for (
auto *DepB : SCCAnonBlockDeps) {
567 assert(BlockDepInfos.count(DepB) &&
"Unrecognized block");
568 auto &DepBRootInfo = *BlockDepInfos[DepB].SCCRoot;
569 if (DepBRootInfo.DepGroupIndex)
570 SrcDepGroups.
insert(*DepBRootInfo.DepGroupIndex);
575 if (SrcDepGroups.
empty()) {
579 if (!SCCSymbolDeps.empty()) {
580 SCCRootInfo.DepGroupIndex = DGs.
size();
582 DGs.
back().Defs = std::move(SCCSymbolDefs);
583 DGs.
back().Deps = std::move(SCCSymbolDeps);
592 if (SrcDepGroups.
size() == 1 && SCCSymbolDeps.empty()) {
593 SCCRootInfo.DepGroupIndex = *SrcDepGroups.
begin();
594 DGs[*SCCRootInfo.DepGroupIndex].Defs.
append(SCCSymbolDefs);
600 SCCRootInfo.DepGroupIndex = DGs.
size();
602 auto &DG = DGs.
back();
603 DG.Defs = std::move(SCCSymbolDefs);
604 for (
auto &DGIndex : SrcDepGroups)
605 DG.Deps.insert(DGs[DGIndex].Deps.begin(), DGs[DGIndex].Deps.end());
606 DG.Deps.insert(SCCSymbolDeps.begin(), SCCSymbolDeps.end());
612 for (
size_t I = 0;
I != DGs.
size();) {
616 for (
auto &Def : DG.Defs)
620 if (DG.Defs.empty() || DG.Deps.empty()) {
630Error LinkGraphLinkingLayer::recordFinalizedAlloc(
633 [&](
ResourceKey K) { Allocs[
K].push_back(std::move(FA)); });
636 Err =
joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA)));
641Error LinkGraphLinkingLayer::handleRemoveResources(
JITDylib &JD,
646 for (
auto &
P : Plugins)
647 Err =
joinErrors(std::move(Err),
P->notifyRemovingResources(JD, K));
652 std::vector<FinalizedAlloc> AllocsToRemove;
654 auto I = Allocs.find(K);
655 if (
I != Allocs.end()) {
661 if (AllocsToRemove.empty())
664 return MemMgr.deallocate(std::move(AllocsToRemove));
667void LinkGraphLinkingLayer::handleTransferResources(
JITDylib &JD,
670 if (Allocs.contains(SrcKey)) {
673 auto &DstAllocs = Allocs[DstKey];
674 auto &SrcAllocs = Allocs[SrcKey];
675 DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
676 for (
auto &
Alloc : SrcAllocs)
677 DstAllocs.push_back(std::move(
Alloc));
679 Allocs.erase(SrcKey);
682 for (
auto &
P : Plugins)
683 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.