16#define DEBUG_TYPE "orc"
25 switch (TT.getArch()) {
50 std::unique_ptr<MaterializationResponsibility> MR,
51 std::unique_ptr<MemoryBuffer> ObjBuffer)
54 std::lock_guard<std::mutex> Lock(Layer.LayerMutex);
55 Plugins = Layer.Plugins;
68 for (
auto &
P : Plugins)
69 P->notifyMaterializing(*MR,
G, *
this,
70 ObjBuffer ? ObjBuffer->getMemBufferRef()
75 for (
auto &
P : Plugins)
76 Err =
joinErrors(std::move(Err),
P->notifyFailed(*MR));
78 MR->failMaterialization();
82 std::unique_ptr<JITLinkAsyncLookupContinuation> LC)
override {
85 MR->getTargetJITDylib().withLinkOrderDo(
91 for (
auto &KV : Symbols) {
101 LookupSet.
add(KV.first, LookupFlags);
105 auto OnResolve = [LookupContinuation =
108 LookupContinuation->run(
Result.takeError());
112 LookupContinuation->run(std::move(LR));
120 for (
auto &[DepJD, Deps] : Deps)
121 for (
auto &DepSym : Deps)
129 bool AutoClaim = Layer.AutoClaimObjectSymbols;
132 for (
auto *
Sym :
G.defined_symbols())
134 auto Ptr = getJITSymbolPtrForSymbol(*
Sym,
G.getTargetTriple());
137 if (AutoClaim && !MR->getSymbols().count(
Sym->
getName())) {
139 "Duplicate symbol to claim?");
144 for (
auto *
Sym :
G.absolute_symbols())
146 auto Ptr = getJITSymbolPtrForSymbol(*
Sym,
G.getTargetTriple());
149 if (AutoClaim && !MR->getSymbols().count(
Sym->
getName())) {
151 "Duplicate symbol to claim?");
156 if (!ExtraSymbolsToClaim.
empty())
157 if (
auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
167 size_t NumMaterializationSideEffectsOnlySymbols = 0;
169 for (
auto &[
Sym, Flags] : MR->getSymbols()) {
176 if (Flags.hasMaterializationSideEffectsOnly())
177 ++NumMaterializationSideEffectsOnlySymbols;
178 else if (
I == InternedResult.
end())
179 MissingSymbols.push_back(
Sym);
180 else if (Layer.OverrideObjectFlags)
181 I->second.setFlags(Flags);
185 if (!MissingSymbols.empty())
186 return make_error<MissingSymbolDefinitions>(
188 std::move(MissingSymbols));
193 if (InternedResult.
size() >
194 MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
195 for (
auto &KV : InternedResult)
196 if (!MR->getSymbols().count(KV.first))
197 ExtraSymbols.push_back(KV.first);
201 if (!ExtraSymbols.empty())
202 return make_error<UnexpectedSymbolDefinitions>(
204 std::move(ExtraSymbols));
207 if (
auto Err = MR->notifyResolved(InternedResult))
216 MR->failMaterialization();
220 if (
auto Err = MR->notifyEmitted(SymbolDepGroups)) {
222 MR->failMaterialization();
227 return [
this](
LinkGraph &
G) {
return markResponsibilitySymbolsLive(
G); };
234 return claimOrExternalizeWeakAndCommonSymbols(
G);
237 for (
auto &
P : Plugins)
238 P->modifyPassConfig(*MR, LG,
Config);
240 Config.PreFixupPasses.push_back(
241 [
this](
LinkGraph &
G) {
return registerDependencies(
G); });
248 for (
auto &
P : Plugins)
249 Err =
joinErrors(std::move(Err),
P->notifyEmitted(*MR));
259 return Layer.recordFinalizedAlloc(*MR, std::move(FA));
267 std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
272 if (!MR->getSymbols().count(
Sym->
getName())) {
280 for (
auto *
Sym :
G.defined_symbols())
282 for (
auto *
Sym :
G.absolute_symbols())
288 if (
auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim)))
294 for (
auto &KV : NameToSym) {
295 if (MR->getSymbols().count(KV.first))
296 KV.second->setLive(
true);
298 G.makeExternal(*KV.second);
305 for (
auto *
Sym :
G.defined_symbols())
314 bool InWorklist =
false;
325 size_t NumBlocks = 0;
326 for (
auto &Sec :
G.sections())
327 NumBlocks += Sec.blocks_size();
332 for (
auto *
Sym :
G.defined_symbols()) {
338 for (
auto *
B :
G.blocks()) {
339 auto &BI = BlockInfos[
B];
341 for (
auto &E :
B->edges()) {
344 if (E.getTarget().isExternal()) {
345 BI.SymbolDeps.
insert(&E.getTarget());
351 if (E.getTarget().isAbsolute())
356 auto &TgtBI = BlockInfos[&E.getTarget().getBlock()];
362 if (!TgtBI.Defs.empty()) {
363 BI.SymbolDeps.
insert(*TgtBI.Defs.begin());
369 BI.AnonEdges.insert(&E.getTarget().getBlock());
370 TgtBI.AnonBackEdges.insert(
B);
376 std::vector<Block *> BlocksToRemove;
377 for (
auto &[
B, BI] : BlockInfos) {
379 if (!BI.Defs.empty())
382 BlocksToRemove.push_back(
B);
384 for (
auto *FB : BI.AnonEdges)
385 BlockInfos[FB].AnonBackEdges.erase(
B);
387 for (
auto *BB : BI.AnonBackEdges)
388 BlockInfos[BB].AnonEdges.erase(
B);
390 for (
auto *FB : BI.AnonEdges) {
391 auto &FBI = BlockInfos[FB];
392 FBI.AnonBackEdges.insert_range(BI.AnonBackEdges);
395 for (
auto *BB : BI.AnonBackEdges) {
396 auto &BBI = BlockInfos[BB];
397 BBI.SymbolDeps.insert_range(BI.SymbolDeps);
398 BBI.AnonEdges.insert_range(BI.AnonEdges);
402 for (
auto *
B : BlocksToRemove)
407 std::deque<Block *> Worklist;
408 for (
auto &[
B, BI] : BlockInfos) {
409 if (!BI.SymbolDeps.empty() && !BI.AnonBackEdges.empty()) {
410 Worklist.push_back(
B);
411 BI.InWorklist =
true;
416 while (!Worklist.empty()) {
417 auto *
B = Worklist.front();
418 Worklist.pop_front();
420 auto &BI = BlockInfos[
B];
421 BI.InWorklist =
false;
423 for (
auto *DB : BI.AnonBackEdges) {
424 auto &DBI = BlockInfos[
DB];
425 for (
auto *
Sym : BI.SymbolDeps) {
426 if (DBI.SymbolDeps.insert(
Sym).second && !DBI.InWorklist) {
427 Worklist.push_back(DB);
428 DBI.InWorklist =
true;
437 auto &TargetJD = MR->getTargetJITDylib();
439 for (
auto &[
B, BI] : BlockInfos) {
440 if (!BI.Defs.empty()) {
442 auto &SDG = SymbolDepGroups.back();
444 for (
auto *Def : BI.Defs)
445 SDG.Symbols.insert(
Def->getName());
447 for (
auto *Dep : BI.SymbolDeps) {
448 auto DepName = Dep->getName();
449 if (Dep->isDefined())
450 SDG.Dependencies[&TargetJD].insert(std::move(DepName));
454 if (SourceJDItr != SymbolSourceJDs.end())
455 SDG.Dependencies[SourceJDItr->second].insert(std::move(DepName));
465 std::vector<std::shared_ptr<LinkGraphLinkingLayer::Plugin>> Plugins;
466 std::unique_ptr<MaterializationResponsibility> MR;
467 std::unique_ptr<MemoryBuffer> ObjBuffer;
469 std::vector<SymbolDependenceGroup> SymbolDepGroups;
475 :
LinkGraphLayer(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
493 "Layer destroyed with resources still attached "
494 "(ExecutionSession::endSession() must be called prior to "
500 std::unique_ptr<MaterializationResponsibility> R,
501 std::unique_ptr<LinkGraph>
G) {
502 assert(R &&
"R must not be null");
503 assert(
G &&
"G must not be null");
504 auto Ctx = std::make_unique<JITLinkCtx>(*
this, std::move(R),
nullptr);
505 Ctx->notifyMaterializing(*
G);
506 link(std::move(
G), std::move(Ctx));
510 std::unique_ptr<MaterializationResponsibility> R,
511 std::unique_ptr<LinkGraph>
G, std::unique_ptr<MemoryBuffer> ObjBuf) {
512 assert(R &&
"R must not be null");
513 assert(
G &&
"G must not be null");
514 assert(ObjBuf &&
"Object must not be null");
516 std::make_unique<JITLinkCtx>(*
this, std::move(R), std::move(ObjBuf));
517 Ctx->notifyMaterializing(*
G);
518 link(std::move(
G), std::move(Ctx));
521Error LinkGraphLinkingLayer::recordFinalizedAlloc(
524 [&](
ResourceKey K) { Allocs[K].push_back(std::move(FA)); });
527 Err =
joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA)));
532Error LinkGraphLinkingLayer::handleRemoveResources(
JITDylib &JD,
537 for (
auto &
P : Plugins)
538 Err =
joinErrors(std::move(Err),
P->notifyRemovingResources(JD, K));
543 std::vector<FinalizedAlloc> AllocsToRemove;
545 auto I = Allocs.find(K);
546 if (
I != Allocs.end()) {
547 std::swap(AllocsToRemove, I->second);
552 if (AllocsToRemove.empty())
555 return MemMgr.deallocate(std::move(AllocsToRemove));
558void LinkGraphLinkingLayer::handleTransferResources(
JITDylib &JD,
561 if (Allocs.contains(SrcKey)) {
564 auto &DstAllocs = Allocs[DstKey];
565 auto &SrcAllocs = Allocs[SrcKey];
566 DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
567 for (
auto &
Alloc : SrcAllocs)
568 DstAllocs.push_back(std::move(
Alloc));
570 Allocs.erase(SrcKey);
573 for (
auto &
P : Plugins)
574 P->notifyTransferringResources(JD, DstKey, SrcKey);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
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.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
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.
Triple - Helper class for working with autoconf configuration names.
Holds context for a single jitLink invocation.
Represents a finalized allocation.
Manages allocations of JIT memory.
virtual void deallocate(std::vector< FinalizedAlloc > Allocs, OnDeallocatedFunction OnDeallocated)=0
Deallocate a list of allocation objects.
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.
void reportError(Error Err)
Report a error for this execution session.
std::shared_ptr< SymbolStringPool > getSymbolStringPool()
Get the SymbolStringPool for this instance.
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.
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 links LinkGraphs into the Executor using JITLink.
void emit(std::unique_ptr< MaterializationResponsibility > R, std::unique_ptr< jitlink::LinkGraph > G) override
Emit a LinkGraph.
std::function< void(std::unique_ptr< MemoryBuffer >)> ReturnObjectBuffer
~LinkGraphLinkingLayer()
Destroy the LinkGraphLinkingLayer.
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.
unique_function is a type-erasing functor similar to std::function.
LLVM_ABI void link(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
Link the given graph.
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.
std::vector< SymbolStringPtr > SymbolNameVector
A vector of symbol names.
@ Resolved
Queried, materialization begun.
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
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.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
A set of symbols and the their dependencies.