LLVM 18.0.0git
JITLinkGeneric.h
Go to the documentation of this file.
1//===------ JITLinkGeneric.h - Generic JIT linker utilities -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Generic JITLinker utilities. E.g. graph pruning, eh-frame parsing.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LIB_EXECUTIONENGINE_JITLINK_JITLINKGENERIC_H
14#define LIB_EXECUTIONENGINE_JITLINK_JITLINKGENERIC_H
15
16#include "llvm/ADT/DenseSet.h"
18
19#define DEBUG_TYPE "jitlink"
20
21namespace llvm {
22namespace jitlink {
23
24/// Base class for a JIT linker.
25///
26/// A JITLinkerBase instance links one object file into an ongoing JIT
27/// session. Symbol resolution and finalization operations are pluggable,
28/// and called using continuation passing (passing a continuation for the
29/// remaining linker work) to allow them to be performed asynchronously.
31public:
32 JITLinkerBase(std::unique_ptr<JITLinkContext> Ctx,
33 std::unique_ptr<LinkGraph> G, PassConfiguration Passes)
34 : Ctx(std::move(Ctx)), G(std::move(G)), Passes(std::move(Passes)) {
35 assert(this->Ctx && "Ctx can not be null");
36 assert(this->G && "G can not be null");
37 }
38
39 virtual ~JITLinkerBase();
40
41protected:
45
46 // Returns a reference to the graph being linked.
47 LinkGraph &getGraph() { return *G; }
48
49 // Returns true if the context says that the linker should add default
50 // passes. This can be used by JITLinkerBase implementations when deciding
51 // whether they should add default passes.
53 return Ctx->shouldAddDefaultTargetPasses(TT);
54 }
55
56 // Returns the PassConfiguration for this instance. This can be used by
57 // JITLinkerBase implementations to add late passes that reference their
58 // own data structures (e.g. for ELF implementations to locate / construct
59 // a GOT start symbol prior to fixup).
60 PassConfiguration &getPassConfig() { return Passes; }
61
62 // Phase 1:
63 // 1.1: Run pre-prune passes
64 // 1.2: Prune graph
65 // 1.3: Run post-prune passes
66 // 1.4: Allocate memory.
67 void linkPhase1(std::unique_ptr<JITLinkerBase> Self);
68
69 // Phase 2:
70 // 2.2: Run post-allocation passes
71 // 2.3: Notify context of final assigned symbol addresses
72 // 2.4: Identify external symbols and make an async call to resolve
73 void linkPhase2(std::unique_ptr<JITLinkerBase> Self, AllocResult AR);
74
75 // Phase 3:
76 // 3.1: Apply resolution results
77 // 3.2: Run pre-fixup passes
78 // 3.3: Fix up block contents
79 // 3.4: Run post-fixup passes
80 // 3.5: Make an async call to transfer and finalize memory.
81 void linkPhase3(std::unique_ptr<JITLinkerBase> Self,
82 Expected<AsyncLookupResult> LookupResult);
83
84 // Phase 4:
85 // 4.1: Call OnFinalized callback, handing off allocation.
86 void linkPhase4(std::unique_ptr<JITLinkerBase> Self, FinalizeResult FR);
87
88private:
89 // Run all passes in the given pass list, bailing out immediately if any pass
90 // returns an error.
91 Error runPasses(LinkGraphPassList &Passes);
92
93 // Copy block contents and apply relocations.
94 // Implemented in JITLinker.
95 virtual Error fixUpBlocks(LinkGraph &G) const = 0;
96
97 JITLinkContext::LookupMap getExternalSymbolNames() const;
98 void applyLookupResult(AsyncLookupResult LR);
99 void abandonAllocAndBailOut(std::unique_ptr<JITLinkerBase> Self, Error Err);
100
101 std::unique_ptr<JITLinkContext> Ctx;
102 std::unique_ptr<LinkGraph> G;
103 PassConfiguration Passes;
104 std::unique_ptr<InFlightAlloc> Alloc;
105};
106
107template <typename LinkerImpl> class JITLinker : public JITLinkerBase {
108public:
110
111 /// Link constructs a LinkerImpl instance and calls linkPhase1.
112 /// Link should be called with the constructor arguments for LinkerImpl, which
113 /// will be forwarded to the constructor.
114 template <typename... ArgTs> static void link(ArgTs &&... Args) {
115 auto L = std::make_unique<LinkerImpl>(std::forward<ArgTs>(Args)...);
116
117 // Ownership of the linker is passed into the linker's doLink function to
118 // allow it to be passed on to async continuations.
119 //
120 // FIXME: Remove LTmp once we have c++17.
121 // C++17 sequencing rules guarantee that function name expressions are
122 // sequenced before arguments, so L->linkPhase1(std::move(L), ...) will be
123 // well formed.
124 auto &LTmp = *L;
125 LTmp.linkPhase1(std::move(L));
126 }
127
128private:
129 const LinkerImpl &impl() const {
130 return static_cast<const LinkerImpl &>(*this);
131 }
132
133 Error fixUpBlocks(LinkGraph &G) const override {
134 LLVM_DEBUG(dbgs() << "Fixing up blocks:\n");
135
136 for (auto &Sec : G.sections()) {
137 bool NoAllocSection =
138 Sec.getMemLifetimePolicy() == orc::MemLifetimePolicy::NoAlloc;
139
140 for (auto *B : Sec.blocks()) {
141 LLVM_DEBUG(dbgs() << " " << *B << ":\n");
142
143 // Copy Block data and apply fixups.
144 LLVM_DEBUG(dbgs() << " Applying fixups.\n");
145 assert((!B->isZeroFill() || all_of(B->edges(),
146 [](const Edge &E) {
147 return E.getKind() ==
148 Edge::KeepAlive;
149 })) &&
150 "Non-KeepAlive edges in zero-fill block?");
151
152 // If this is a no-alloc section then copy the block content into
153 // memory allocated on the Graph's allocator (if it hasn't been
154 // already).
155 if (NoAllocSection)
156 (void)B->getMutableContent(G);
157
158 for (auto &E : B->edges()) {
159
160 // Skip non-relocation edges.
161 if (!E.isRelocation())
162 continue;
163
164 // If B is a block in a Standard or Finalize section then make sure
165 // that no edges point to symbols in NoAlloc sections.
166 assert(
167 (NoAllocSection || !E.getTarget().isDefined() ||
168 E.getTarget().getBlock().getSection().getMemLifetimePolicy() !=
170 "Block in allocated section has edge pointing to no-alloc "
171 "section");
172
173 // Dispatch to LinkerImpl for fixup.
174 if (auto Err = impl().applyFixup(G, *B, E))
175 return Err;
176 }
177 }
178 }
179
180 return Error::success();
181 }
182};
183
184/// Removes dead symbols/blocks/addressables.
185///
186/// Finds the set of symbols and addressables reachable from any symbol
187/// initially marked live. All symbols/addressables not marked live at the end
188/// of this process are removed.
189void prune(LinkGraph &G);
190
191} // end namespace jitlink
192} // end namespace llvm
193
194#undef DEBUG_TYPE // "jitlink"
195
196#endif // LIB_EXECUTIONENGINE_JITLINK_JITLINKGENERIC_H
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DEBUG(X)
Definition: Debug.h:101
This file defines the DenseSet and SmallDenseSet classes.
#define G(x, y, z)
Definition: MD5.cpp:56
const char * Passes
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:154
static ErrorSuccess success()
Create a success value.
Definition: Error.h:328
Tagged union holding either a T or a Error.
Definition: Error.h:468
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
@ NoAlloc
NoAlloc memory should not be allocated by the JITLinkMemoryManager at all.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1727
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1854
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858