18#define DEBUG_TYPE "jitlink"
28 dbgs() <<
"Starting link phase 1 for graph " << G->getName() <<
"\n";
33 return Ctx->notifyFailed(std::move(Err));
36 dbgs() <<
"Link graph \"" << G->getName() <<
"\" pre-pruning:\n";
43 dbgs() <<
"Link graph \"" << G->getName() <<
"\" post-pruning:\n";
49 return Ctx->notifyFailed(std::move(Err));
53 return S.getMemLifetime() == orc::MemLifetime::NoAlloc;
59 Ctx->getMemoryManager().allocate(
60 Ctx->getJITLinkDylib(), *G,
65 auto *TmpSelf = S.get();
66 TmpSelf->linkPhase2(std::move(S), std::move(AR));
74 Alloc = std::move(*AR);
79 dbgs() <<
"Link graph \"" << G->getName()
80 <<
"\" before post-allocation passes:\n";
86 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
89 LLVM_DEBUG(
dbgs() <<
"Resolving symbols defined in " << G->getName() <<
"\n");
91 if (
auto Err = Ctx->notifyResolved(*G))
92 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
94 auto ExternalSymbols = getExternalSymbolNames();
97 if (ExternalSymbols.empty()) {
99 dbgs() <<
"No external symbols for " << G->getName()
100 <<
". Proceeding immediately with link phase 3.\n";
104 auto &TmpSelf = *Self;
111 dbgs() <<
"Issuing lookup for external symbols for " << G->getName()
112 <<
" (may trigger materialization/linking of other graphs)...\n";
125 Ctx->lookup(std::move(ExternalSymbols),
127 [S = std::move(Self)](
130 TmpSelf.linkPhase3(std::move(S), std::move(LookupResult));
138 dbgs() <<
"Starting link phase 3 for graph " << G->getName() <<
"\n";
143 return abandonAllocAndBailOut(std::move(Self), LR.
takeError());
146 applyLookupResult(*LR);
149 dbgs() <<
"Link graph \"" << G->getName()
150 <<
"\" before pre-fixup passes:\n";
155 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
158 dbgs() <<
"Link graph \"" << G->getName() <<
"\" before copy-and-fixup:\n";
163 if (
auto Err = fixUpBlocks(*G))
164 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
167 dbgs() <<
"Link graph \"" << G->getName() <<
"\" after copy-and-fixup:\n";
172 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
180 Alloc->finalize([S = std::move(Self)](
FinalizeResult FR)
mutable {
184 auto *TmpSelf = S.get();
185 TmpSelf->linkPhase4(std::move(S), std::move(FR));
193 dbgs() <<
"Starting link phase 4 for graph " << G->getName() <<
"\n";
197 return Ctx->notifyFailed(FR.
takeError());
199 Ctx->notifyFinalized(std::move(*FR));
201 LLVM_DEBUG({
dbgs() <<
"Link of graph " << G->getName() <<
" complete\n"; });
205 for (
auto &
P : Passes)
206 if (
auto Err =
P(*G))
214 for (
auto *
Sym : G->external_symbols()) {
216 "External has already been assigned an address");
218 "Externals must be named");
222 UnresolvedExternals[
Sym->getName()] = LookupFlags;
224 return UnresolvedExternals;
228 for (
auto *
Sym : G->external_symbols()) {
230 "External symbol is not at the start of its addressable block");
231 assert(!
Sym->getAddress() &&
"Symbol already resolved");
232 assert(!
Sym->isDefined() &&
"Symbol being resolved is already defined");
233 auto ResultI =
Result.find(
Sym->getName());
234 if (ResultI !=
Result.end()) {
235 Sym->getAddressable().setAddress(ResultI->second.getAddress());
242 "Failed to resolve non-weak reference");
246 dbgs() <<
"Externals after applying lookup result:\n";
247 for (
auto *
Sym : G->external_symbols()) {
248 dbgs() <<
" " <<
Sym->getName() <<
": "
249 <<
formatv(
"{0:x16}",
Sym->getAddress().getValue());
250 switch (
Sym->getLinkage()) {
257 switch (
Sym->getScope()) {
263 dbgs() <<
" (exported)";
271void JITLinkerBase::abandonAllocAndBailOut(std::unique_ptr<JITLinkerBase> Self,
273 assert(Err &&
"Should not be bailing out on success value");
274 assert(Alloc &&
"can not call abandonAllocAndBailOut before allocation");
275 Alloc->abandon([S = std::move(Self), E1 = std::move(Err)](Error E2)
mutable {
276 S->Ctx->notifyFailed(
joinErrors(std::move(E1), std::move(E2)));
281 std::vector<Symbol *> Worklist;
285 for (
auto *
Sym :
G.defined_symbols())
287 Worklist.push_back(
Sym);
290 while (!Worklist.empty()) {
291 auto *
Sym = Worklist.back();
297 if (VisitedBlocks.
count(&
B))
305 if (
E.getTarget().isDefined() && !
E.getTarget().isLive())
306 Worklist.push_back(&
E.getTarget());
309 E.getTarget().setLive(
true);
316 std::vector<Symbol *> SymbolsToRemove;
317 for (
auto *
Sym :
G.defined_symbols())
319 SymbolsToRemove.push_back(
Sym);
320 for (
auto *
Sym : SymbolsToRemove) {
322 G.removeDefinedSymbol(*
Sym);
329 std::vector<Block *> BlocksToRemove;
330 for (
auto *
B :
G.blocks())
331 if (!VisitedBlocks.
count(
B))
332 BlocksToRemove.push_back(
B);
333 for (
auto *
B : BlocksToRemove) {
342 std::vector<Symbol *> SymbolsToRemove;
343 for (
auto *
Sym :
G.external_symbols())
345 SymbolsToRemove.push_back(
Sym);
346 for (
auto *
Sym : SymbolsToRemove) {
348 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.
StringRef - Represent a constant reference to a string, i.e.
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< StringRef, 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< StringRef, 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(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< 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.