15#define DEBUG_TYPE "jitlink"
27 if (
auto Err = runPasses(Passes.PrePrunePasses))
28 return Ctx->notifyFailed(std::move(Err));
31 dbgs() <<
"Link graph pre-pruning:\n";
38 dbgs() <<
"Link graph post-pruning:\n";
43 if (
auto Err = runPasses(Passes.PostPrunePasses))
44 return Ctx->notifyFailed(std::move(Err));
48 return S.getMemLifetime() == orc::MemLifetime::NoAlloc;
54 Ctx->getMemoryManager().allocate(
55 Ctx->getJITLinkDylib(), *G,
57 S->linkPhase2(std::move(S), std::move(AR));
67 Alloc = std::move(*AR);
72 dbgs() <<
"Link graph before post-allocation passes:\n";
77 if (
auto Err = runPasses(Passes.PostAllocationPasses))
78 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
81 LLVM_DEBUG(
dbgs() <<
"Resolving symbols defined in " << G->getName() <<
"\n");
83 if (
auto Err = Ctx->notifyResolved(*G))
84 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
86 auto ExternalSymbols = getExternalSymbolNames();
89 if (ExternalSymbols.empty()) {
91 dbgs() <<
"No external symbols for " << G->getName()
92 <<
". Proceeding immediately with link phase 3.\n";
100 dbgs() <<
"Issuing lookup for external symbols for " << G->getName()
101 <<
" (may trigger materialization/linking of other graphs)...\n";
104 Ctx->lookup(std::move(ExternalSymbols),
106 [S = std::move(Self)](
108 S->linkPhase3(std::move(S), std::move(LookupResult));
119 return abandonAllocAndBailOut(std::move(Self), LR.
takeError());
122 applyLookupResult(*LR);
125 dbgs() <<
"Link graph before pre-fixup passes:\n";
129 if (
auto Err = runPasses(Passes.PreFixupPasses))
130 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
133 dbgs() <<
"Link graph before copy-and-fixup:\n";
138 if (
auto Err = fixUpBlocks(*G))
139 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
142 dbgs() <<
"Link graph after copy-and-fixup:\n";
146 if (
auto Err = runPasses(Passes.PostFixupPasses))
147 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
155 Alloc->finalize([S = std::move(Self)](
FinalizeResult FR)
mutable {
156 S->linkPhase4(std::move(S), std::move(FR));
166 return Ctx->notifyFailed(FR.
takeError());
168 Ctx->notifyFinalized(std::move(*FR));
175 if (
auto Err =
P(*
G))
183 for (
auto *Sym :
G->external_symbols()) {
184 assert(!Sym->getAddress() &&
185 "External has already been assigned an address");
186 assert(Sym->hasName() &&
"Externals must be named");
190 UnresolvedExternals[Sym->getName()] = LookupFlags;
192 return UnresolvedExternals;
196 for (
auto *Sym : G->external_symbols()) {
197 assert(Sym->getOffset() == 0 &&
198 "External symbol is not at the start of its addressable block");
199 assert(!Sym->getAddress() &&
"Symbol already resolved");
200 assert(!Sym->isDefined() &&
"Symbol being resolved is already defined");
201 auto ResultI =
Result.find(Sym->getName());
202 if (ResultI !=
Result.end()) {
203 Sym->getAddressable().setAddress(ResultI->second.getAddress());
204 Sym->setLinkage(ResultI->second.getFlags().isWeak() ?
Linkage::Weak
206 Sym->setScope(ResultI->second.getFlags().isExported() ?
Scope::Default
209 assert(Sym->isWeaklyReferenced() &&
210 "Failed to resolve non-weak reference");
214 dbgs() <<
"Externals after applying lookup result:\n";
215 for (
auto *Sym : G->external_symbols()) {
216 dbgs() <<
" " << Sym->getName() <<
": "
217 <<
formatv(
"{0:x16}", Sym->getAddress().getValue());
218 switch (Sym->getLinkage()) {
225 switch (Sym->getScope()) {
229 "side-effects-only linkage");
233 dbgs() <<
" (exported)";
241void JITLinkerBase::abandonAllocAndBailOut(std::unique_ptr<JITLinkerBase> Self,
243 assert(Err &&
"Should not be bailing out on success value");
244 assert(Alloc &&
"can not call abandonAllocAndBailOut before allocation");
245 Alloc->abandon([S = std::move(Self), E1 = std::move(Err)](
Error E2)
mutable {
246 S->Ctx->notifyFailed(
joinErrors(std::move(E1), std::move(E2)));
251 std::vector<Symbol *> Worklist;
255 for (
auto *Sym :
G.defined_symbols())
257 Worklist.push_back(Sym);
260 while (!Worklist.empty()) {
261 auto *Sym = Worklist.back();
264 auto &
B = Sym->getBlock();
272 for (
auto &
E : Sym->getBlock().edges()) {
275 if (
E.getTarget().isDefined() && !
E.getTarget().isLive())
276 Worklist.push_back(&
E.getTarget());
279 E.getTarget().setLive(
true);
286 std::vector<Symbol *> SymbolsToRemove;
287 for (
auto *Sym :
G.defined_symbols())
289 SymbolsToRemove.push_back(Sym);
290 for (
auto *Sym : SymbolsToRemove) {
292 G.removeDefinedSymbol(*Sym);
299 std::vector<Block *> BlocksToRemove;
300 for (
auto *
B :
G.blocks())
302 BlocksToRemove.push_back(
B);
303 for (
auto *
B : BlocksToRemove) {
312 std::vector<Symbol *> SymbolsToRemove;
313 for (
auto *Sym :
G.external_symbols())
315 SymbolsToRemove.push_back(Sym);
316 for (
auto *Sym : SymbolsToRemove) {
318 G.removeExternalSymbol(*Sym);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
SmallPtrSet< const BasicBlock *, 8 > VisitedBlocks
Function const char * Passes
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.
Error takeError()
Take ownership of the stored error.
DenseMap< orc::SymbolStringPtr, SymbolLookupFlags > LookupMap
Represents a finalized allocation.
void linkPhase4(std::unique_ptr< JITLinkerBase > Self, FinalizeResult FR)
void linkPhase3(std::unique_ptr< JITLinkerBase > Self, Expected< AsyncLookupResult > LookupResult)
Expected< std::unique_ptr< InFlightAlloc > > AllocResult
void linkPhase1(std::unique_ptr< JITLinkerBase > Self)
Expected< JITLinkMemoryManager::FinalizedAlloc > FinalizeResult
void linkPhase2(std::unique_ptr< JITLinkerBase > Self, AllocResult AR)
Represents an object file section.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::unique_ptr< JITLinkAsyncLookupContinuation > createLookupContinuation(Continuation Cont)
Create a lookup continuation from a function object.
SymbolLookupFlags
Flags for symbol lookup.
void prune(LinkGraph &G)
Removes dead symbols/blocks/addressables.
DenseMap< orc::SymbolStringPtr, orc::ExecutorSymbolDef > AsyncLookupResult
A map of symbol names to resolved addresses.
std::vector< LinkGraphPassFunction > LinkGraphPassList
A list of LinkGraph passes.
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
Error joinErrors(Error E1, Error E2)
Concatenate errors.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.