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));
51 Ctx->getMemoryManager().allocate(
52 Ctx->getJITLinkDylib(), *G,
57 auto *TmpSelf = S.get();
58 TmpSelf->linkPhase2(std::move(S), std::move(AR));
66 Alloc = std::move(*AR);
68 return abandonAllocAndBailOut(std::move(Self), AR.
takeError());
71 dbgs() <<
"Link graph \"" << G->getName()
72 <<
"\" before post-allocation passes:\n";
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";
96 auto &TmpSelf = *Self;
103 dbgs() <<
"Issuing lookup for external symbols for " << G->getName()
104 <<
" (may trigger materialization/linking of other graphs)...\n";
117 Ctx->lookup(std::move(ExternalSymbols),
119 [S = std::move(Self)](
122 TmpSelf.linkPhase3(std::move(S), std::move(LookupResult));
130 dbgs() <<
"Starting link phase 3 for graph " << G->getName() <<
"\n";
135 return abandonAllocAndBailOut(std::move(Self), LR.
takeError());
138 applyLookupResult(*LR);
141 dbgs() <<
"Link graph \"" << G->getName()
142 <<
"\" before pre-fixup passes:\n";
147 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
150 dbgs() <<
"Link graph \"" << G->getName() <<
"\" before copy-and-fixup:\n";
155 if (
auto Err = fixUpBlocks(*G))
156 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
159 dbgs() <<
"Link graph \"" << G->getName() <<
"\" after copy-and-fixup:\n";
164 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
166 Alloc->finalize([S = std::move(Self)](
FinalizeResult FR)
mutable {
170 auto *TmpSelf = S.get();
171 TmpSelf->linkPhase4(std::move(S), std::move(FR));
179 dbgs() <<
"Starting link phase 4 for graph " << G->getName() <<
"\n";
183 return Ctx->notifyFailed(FR.
takeError());
185 Ctx->notifyFinalized(std::move(*FR));
187 LLVM_DEBUG({
dbgs() <<
"Link of graph " << G->getName() <<
" complete\n"; });
191 for (
auto &
P : Passes)
192 if (
auto Err =
P(*G))
200 for (
auto *
Sym : G->external_symbols()) {
202 "External has already been assigned an address");
204 "Externals must be named");
208 UnresolvedExternals[
Sym->getName()] = LookupFlags;
210 return UnresolvedExternals;
214 for (
auto *
Sym : G->external_symbols()) {
216 "External symbol is not at the start of its addressable block");
217 assert(!
Sym->getAddress() &&
"Symbol already resolved");
218 assert(!
Sym->isDefined() &&
"Symbol being resolved is already defined");
219 auto ResultI =
Result.find(
Sym->getName());
220 if (ResultI !=
Result.end()) {
221 Sym->getAddressable().setAddress(ResultI->second.getAddress());
228 "Failed to resolve non-weak reference");
232 dbgs() <<
"Externals after applying lookup result:\n";
233 for (
auto *
Sym : G->external_symbols()) {
234 dbgs() <<
" " <<
Sym->getName() <<
": "
235 <<
formatv(
"{0:x16}",
Sym->getAddress().getValue());
236 switch (
Sym->getLinkage()) {
243 switch (
Sym->getScope()) {
249 dbgs() <<
" (exported)";
257void JITLinkerBase::abandonAllocAndBailOut(std::unique_ptr<JITLinkerBase> Self,
259 assert(Err &&
"Should not be bailing out on success value");
260 assert(Alloc &&
"can not call abandonAllocAndBailOut before allocation");
261 Alloc->abandon([S = std::move(Self), E1 = std::move(Err)](Error E2)
mutable {
262 S->Ctx->notifyFailed(
joinErrors(std::move(E1), std::move(E2)));
267 std::vector<Symbol *> Worklist;
271 for (
auto *
Sym :
G.defined_symbols())
273 Worklist.push_back(
Sym);
276 while (!Worklist.empty()) {
277 auto *
Sym = Worklist.back();
283 if (VisitedBlocks.
count(&
B))
291 if (
E.getTarget().isDefined() && !
E.getTarget().isLive())
292 Worklist.push_back(&
E.getTarget());
295 E.getTarget().setLive(
true);
302 std::vector<Symbol *> SymbolsToRemove;
303 for (
auto *
Sym :
G.defined_symbols())
305 SymbolsToRemove.push_back(
Sym);
306 for (
auto *
Sym : SymbolsToRemove) {
308 G.removeDefinedSymbol(*
Sym);
315 std::vector<Block *> BlocksToRemove;
316 for (
auto *
B :
G.blocks())
317 if (!VisitedBlocks.
count(
B))
318 BlocksToRemove.push_back(
B);
319 for (
auto *
B : BlocksToRemove) {
328 std::vector<Symbol *> SymbolsToRemove;
329 for (
auto *
Sym :
G.external_symbols())
331 SymbolsToRemove.push_back(
Sym);
332 for (
auto *
Sym : SymbolsToRemove) {
334 G.removeExternalSymbol(*
Sym);
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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
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)
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.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(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.