15#define DEBUG_TYPE "jitlink"
25 dbgs() <<
"Starting link phase 1 for graph " << G->getName() <<
"\n";
30 return Ctx->notifyFailed(std::move(Err));
33 dbgs() <<
"Link graph \"" << G->getName() <<
"\" pre-pruning:\n";
40 dbgs() <<
"Link graph \"" << G->getName() <<
"\" post-pruning:\n";
46 return Ctx->notifyFailed(std::move(Err));
50 return S.getMemLifetime() == orc::MemLifetime::NoAlloc;
56 Ctx->getMemoryManager().allocate(
57 Ctx->getJITLinkDylib(), *G,
62 auto *TmpSelf = S.get();
63 TmpSelf->linkPhase2(std::move(S), std::move(AR));
71 Alloc = std::move(*AR);
76 dbgs() <<
"Link graph \"" << G->getName()
77 <<
"\" before post-allocation passes:\n";
83 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
86 LLVM_DEBUG(
dbgs() <<
"Resolving symbols defined in " << G->getName() <<
"\n");
88 if (
auto Err = Ctx->notifyResolved(*G))
89 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
91 auto ExternalSymbols = getExternalSymbolNames();
94 if (ExternalSymbols.empty()) {
96 dbgs() <<
"No external symbols for " << G->getName()
97 <<
". Proceeding immediately with link phase 3.\n";
101 auto &TmpSelf = *Self;
108 dbgs() <<
"Issuing lookup for external symbols for " << G->getName()
109 <<
" (may trigger materialization/linking of other graphs)...\n";
122 Ctx->lookup(std::move(ExternalSymbols),
124 [S = std::move(Self)](
127 TmpSelf.linkPhase3(std::move(S), std::move(LookupResult));
135 dbgs() <<
"Starting link phase 3 for graph " << G->getName() <<
"\n";
140 return abandonAllocAndBailOut(std::move(Self), LR.
takeError());
143 applyLookupResult(*LR);
146 dbgs() <<
"Link graph \"" << G->getName()
147 <<
"\" before pre-fixup passes:\n";
152 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
155 dbgs() <<
"Link graph \"" << G->getName() <<
"\" before copy-and-fixup:\n";
160 if (
auto Err = fixUpBlocks(*G))
161 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
164 dbgs() <<
"Link graph \"" << G->getName() <<
"\" after copy-and-fixup:\n";
169 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
177 Alloc->finalize([S = std::move(Self)](
FinalizeResult FR)
mutable {
181 auto *TmpSelf = S.get();
182 TmpSelf->linkPhase4(std::move(S), std::move(FR));
190 dbgs() <<
"Starting link phase 4 for graph " << G->getName() <<
"\n";
194 return Ctx->notifyFailed(FR.
takeError());
196 Ctx->notifyFinalized(std::move(*FR));
198 LLVM_DEBUG({
dbgs() <<
"Link of graph " << G->getName() <<
" complete\n"; });
202 for (
auto &
P : Passes)
203 if (
auto Err =
P(*G))
211 for (
auto *
Sym : G->external_symbols()) {
213 "External has already been assigned an address");
214 assert(
Sym->hasName() &&
"Externals must be named");
218 UnresolvedExternals[
Sym->getName()] = LookupFlags;
220 return UnresolvedExternals;
224 for (
auto *
Sym : G->external_symbols()) {
226 "External symbol is not at the start of its addressable block");
227 assert(!
Sym->getAddress() &&
"Symbol already resolved");
228 assert(!
Sym->isDefined() &&
"Symbol being resolved is already defined");
229 auto ResultI =
Result.find(
Sym->getName());
230 if (ResultI !=
Result.end()) {
231 Sym->getAddressable().setAddress(ResultI->second.getAddress());
238 "Failed to resolve non-weak reference");
242 dbgs() <<
"Externals after applying lookup result:\n";
243 for (
auto *
Sym : G->external_symbols()) {
244 dbgs() <<
" " <<
Sym->getName() <<
": "
245 <<
formatv(
"{0:x16}",
Sym->getAddress().getValue());
246 switch (
Sym->getLinkage()) {
253 switch (
Sym->getScope()) {
257 "side-effects-only linkage");
261 dbgs() <<
" (exported)";
269void JITLinkerBase::abandonAllocAndBailOut(std::unique_ptr<JITLinkerBase> Self,
271 assert(Err &&
"Should not be bailing out on success value");
272 assert(Alloc &&
"can not call abandonAllocAndBailOut before allocation");
273 Alloc->abandon([S = std::move(Self), E1 = std::move(Err)](Error E2)
mutable {
274 S->Ctx->notifyFailed(
joinErrors(std::move(E1), std::move(E2)));
279 std::vector<Symbol *> Worklist;
283 for (
auto *
Sym :
G.defined_symbols())
285 Worklist.push_back(
Sym);
288 while (!Worklist.empty()) {
289 auto *
Sym = Worklist.back();
295 if (VisitedBlocks.
count(&
B))
303 if (
E.getTarget().isDefined() && !
E.getTarget().isLive())
304 Worklist.push_back(&
E.getTarget());
307 E.getTarget().setLive(
true);
314 std::vector<Symbol *> SymbolsToRemove;
315 for (
auto *
Sym :
G.defined_symbols())
317 SymbolsToRemove.push_back(
Sym);
318 for (
auto *
Sym : SymbolsToRemove) {
320 G.removeDefinedSymbol(*
Sym);
327 std::vector<Block *> BlocksToRemove;
328 for (
auto *
B :
G.blocks())
329 if (!VisitedBlocks.
count(
B))
330 BlocksToRemove.push_back(
B);
331 for (
auto *
B : BlocksToRemove) {
340 std::vector<Symbol *> SymbolsToRemove;
341 for (
auto *
Sym :
G.external_symbols())
343 SymbolsToRemove.push_back(
Sym);
344 for (
auto *
Sym : SymbolsToRemove) {
346 G.removeExternalSymbol(*
Sym);
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Function const char * Passes
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
iterator_range< edge_iterator > edges()
Return the list of edges attached to this content.
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)
void linkPhase1(std::unique_ptr< JITLinkerBase > Self)
void linkPhase2(std::unique_ptr< JITLinkerBase > Self, AllocResult AR)
Represents an object file section.
bool isLive() const
Returns true if this symbol is live (i.e.
Block & getBlock()
Return the Block for this Symbol (Symbol must be defined).
#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.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LinkGraphPassList PostAllocationPasses
Post-allocation passes.
LinkGraphPassList PreFixupPasses
Pre-fixup passes.
LinkGraphPassList PostFixupPasses
Post-fixup passes.
LinkGraphPassList PostPrunePasses
Post-prune passes.
LinkGraphPassList PrePrunePasses
Pre-prune passes.