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,
60 auto *TmpSelf = S.get();
61 TmpSelf->linkPhase2(std::move(S), std::move(AR));
71 Alloc = std::move(*AR);
76 dbgs() <<
"Link graph before post-allocation passes:\n";
81 if (
auto Err = runPasses(Passes.PostAllocationPasses))
82 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
85 LLVM_DEBUG(
dbgs() <<
"Resolving symbols defined in " << G->getName() <<
"\n");
87 if (
auto Err = Ctx->notifyResolved(*G))
88 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
90 auto ExternalSymbols = getExternalSymbolNames();
93 if (ExternalSymbols.empty()) {
95 dbgs() <<
"No external symbols for " << G->getName()
96 <<
". Proceeding immediately with link phase 3.\n";
100 auto &TmpSelf = *Self;
107 dbgs() <<
"Issuing lookup for external symbols for " << G->getName()
108 <<
" (may trigger materialization/linking of other graphs)...\n";
121 Ctx->lookup(std::move(ExternalSymbols),
123 [S = std::move(Self)](
126 TmpSelf.linkPhase3(std::move(S), std::move(LookupResult));
137 return abandonAllocAndBailOut(std::move(Self), LR.
takeError());
140 applyLookupResult(*LR);
143 dbgs() <<
"Link graph before pre-fixup passes:\n";
147 if (
auto Err = runPasses(Passes.PreFixupPasses))
148 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
151 dbgs() <<
"Link graph before copy-and-fixup:\n";
156 if (
auto Err = fixUpBlocks(*G))
157 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
160 dbgs() <<
"Link graph after copy-and-fixup:\n";
164 if (
auto Err = runPasses(Passes.PostFixupPasses))
165 return abandonAllocAndBailOut(std::move(Self), std::move(Err));
173 Alloc->finalize([S = std::move(Self)](
FinalizeResult FR)
mutable {
177 auto *TmpSelf = S.get();
178 TmpSelf->linkPhase4(std::move(S), std::move(FR));
188 return Ctx->notifyFailed(FR.
takeError());
190 Ctx->notifyFinalized(std::move(*FR));
197 if (
auto Err =
P(*
G))
205 for (
auto *Sym :
G->external_symbols()) {
206 assert(!Sym->getAddress() &&
207 "External has already been assigned an address");
208 assert(Sym->hasName() &&
"Externals must be named");
212 UnresolvedExternals[Sym->getName()] = LookupFlags;
214 return UnresolvedExternals;
218 for (
auto *Sym : G->external_symbols()) {
219 assert(Sym->getOffset() == 0 &&
220 "External symbol is not at the start of its addressable block");
221 assert(!Sym->getAddress() &&
"Symbol already resolved");
222 assert(!Sym->isDefined() &&
"Symbol being resolved is already defined");
223 auto ResultI =
Result.find(Sym->getName());
224 if (ResultI !=
Result.end()) {
225 Sym->getAddressable().setAddress(ResultI->second.getAddress());
226 Sym->setLinkage(ResultI->second.getFlags().isWeak() ?
Linkage::Weak
228 Sym->setScope(ResultI->second.getFlags().isExported() ?
Scope::Default
231 assert(Sym->isWeaklyReferenced() &&
232 "Failed to resolve non-weak reference");
236 dbgs() <<
"Externals after applying lookup result:\n";
237 for (
auto *Sym : G->external_symbols()) {
238 dbgs() <<
" " << Sym->getName() <<
": "
239 <<
formatv(
"{0:x16}", Sym->getAddress().getValue());
240 switch (Sym->getLinkage()) {
247 switch (Sym->getScope()) {
251 "side-effects-only linkage");
255 dbgs() <<
" (exported)";
263void JITLinkerBase::abandonAllocAndBailOut(std::unique_ptr<JITLinkerBase> Self,
265 assert(Err &&
"Should not be bailing out on success value");
266 assert(Alloc &&
"can not call abandonAllocAndBailOut before allocation");
267 Alloc->abandon([S = std::move(Self), E1 = std::move(Err)](
Error E2)
mutable {
268 S->Ctx->notifyFailed(
joinErrors(std::move(E1), std::move(E2)));
273 std::vector<Symbol *> Worklist;
277 for (
auto *Sym :
G.defined_symbols())
279 Worklist.push_back(Sym);
282 while (!Worklist.empty()) {
283 auto *Sym = Worklist.back();
286 auto &
B = Sym->getBlock();
294 for (
auto &
E : Sym->getBlock().edges()) {
297 if (
E.getTarget().isDefined() && !
E.getTarget().isLive())
298 Worklist.push_back(&
E.getTarget());
301 E.getTarget().setLive(
true);
308 std::vector<Symbol *> SymbolsToRemove;
309 for (
auto *Sym :
G.defined_symbols())
311 SymbolsToRemove.push_back(Sym);
312 for (
auto *Sym : SymbolsToRemove) {
314 G.removeDefinedSymbol(*Sym);
321 std::vector<Block *> BlocksToRemove;
322 for (
auto *
B :
G.blocks())
324 BlocksToRemove.push_back(
B);
325 for (
auto *
B : BlocksToRemove) {
334 std::vector<Symbol *> SymbolsToRemove;
335 for (
auto *Sym :
G.external_symbols())
337 SymbolsToRemove.push_back(Sym);
338 for (
auto *Sym : SymbolsToRemove) {
340 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.