LLVM  14.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 
21 namespace llvm {
22 
23 class MemoryBufferRef;
24 
25 namespace jitlink {
26 
27 /// Base class for a JIT linker.
28 ///
29 /// A JITLinkerBase instance links one object file into an ongoing JIT
30 /// session. Symbol resolution and finalization operations are pluggable,
31 /// and called using continuation passing (passing a continuation for the
32 /// remaining linker work) to allow them to be performed asynchronously.
34 public:
35  JITLinkerBase(std::unique_ptr<JITLinkContext> Ctx,
36  std::unique_ptr<LinkGraph> G, PassConfiguration Passes)
37  : Ctx(std::move(Ctx)), G(std::move(G)), Passes(std::move(Passes)) {
38  assert(this->Ctx && "Ctx can not be null");
39  assert(this->G && "G can not be null");
40  }
41 
42  virtual ~JITLinkerBase();
43 
44 protected:
45  struct SegmentLayout {
46  using BlocksList = std::vector<Block *>;
47 
50  };
51 
53 
54  // Returns the PassConfiguration for this instance. This can be used by
55  // JITLinkerBase implementations to add late passes that reference their
56  // own data structures (e.g. for ELF implementations to locate / construct
57  // a GOT start symbol prior to fixup).
58  PassConfiguration &getPassConfig() { return Passes; }
59 
60  // Phase 1:
61  // 1.1: Run pre-prune passes
62  // 1.2: Prune graph
63  // 1.3: Run post-prune passes
64  // 1.4: Sort blocks into segments
65  // 1.5: Allocate segment memory, update node vmaddrs to target vmaddrs
66  // 1.6: Run post-allocation passes
67  // 1.7: Notify context of final assigned symbol addresses
68  // 1.8: Identify external symbols and make an async call to resolve
69  void linkPhase1(std::unique_ptr<JITLinkerBase> Self);
70 
71  // Phase 2:
72  // 2.1: Apply resolution results
73  // 2.2: Run pre-fixup passes
74  // 2.3: Fix up block contents
75  // 2.4: Run post-fixup passes
76  // 2.5: Make an async call to transfer and finalize memory.
77  void linkPhase2(std::unique_ptr<JITLinkerBase> Self,
79  SegmentLayoutMap Layout);
80 
81  // Phase 3:
82  // 3.1: Call OnFinalized callback, handing off allocation.
83  void linkPhase3(std::unique_ptr<JITLinkerBase> Self, Error Err);
84 
85  // Align a JITTargetAddress to conform with block alignment requirements.
87  uint64_t Delta = (B.getAlignmentOffset() - Addr) % B.getAlignment();
88  return Addr + Delta;
89  }
90 
91  // Align a pointer to conform with block alignment requirements.
92  static char *alignToBlock(char *P, Block &B) {
93  uint64_t PAddr = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(P));
94  uint64_t Delta = (B.getAlignmentOffset() - PAddr) % B.getAlignment();
95  return P + Delta;
96  }
97 
98 private:
99  // Run all passes in the given pass list, bailing out immediately if any pass
100  // returns an error.
101  Error runPasses(LinkGraphPassList &Passes);
102 
103  // Copy block contents and apply relocations.
104  // Implemented in JITLinker.
105  virtual Error fixUpBlocks(LinkGraph &G) const = 0;
106 
107  SegmentLayoutMap layOutBlocks();
108  Error allocateSegments(const SegmentLayoutMap &Layout);
109  JITLinkContext::LookupMap getExternalSymbolNames() const;
110  void applyLookupResult(AsyncLookupResult LR);
111  void copyBlockContentToWorkingMemory(const SegmentLayoutMap &Layout,
113  void deallocateAndBailOut(Error Err);
114 
115  std::unique_ptr<JITLinkContext> Ctx;
116  std::unique_ptr<LinkGraph> G;
117  PassConfiguration Passes;
118  std::unique_ptr<JITLinkMemoryManager::Allocation> Alloc;
119 };
120 
121 template <typename LinkerImpl> class JITLinker : public JITLinkerBase {
122 public:
124 
125  /// Link constructs a LinkerImpl instance and calls linkPhase1.
126  /// Link should be called with the constructor arguments for LinkerImpl, which
127  /// will be forwarded to the constructor.
128  template <typename... ArgTs> static void link(ArgTs &&... Args) {
129  auto L = std::make_unique<LinkerImpl>(std::forward<ArgTs>(Args)...);
130 
131  // Ownership of the linker is passed into the linker's doLink function to
132  // allow it to be passed on to async continuations.
133  //
134  // FIXME: Remove LTmp once we have c++17.
135  // C++17 sequencing rules guarantee that function name expressions are
136  // sequenced before arguments, so L->linkPhase1(std::move(L), ...) will be
137  // well formed.
138  auto &LTmp = *L;
139  LTmp.linkPhase1(std::move(L));
140  }
141 
142 private:
143  const LinkerImpl &impl() const {
144  return static_cast<const LinkerImpl &>(*this);
145  }
146 
147  Error fixUpBlocks(LinkGraph &G) const override {
148  LLVM_DEBUG(dbgs() << "Fixing up blocks:\n");
149 
150  for (auto *B : G.blocks()) {
151  LLVM_DEBUG(dbgs() << " " << *B << ":\n");
152 
153  // Copy Block data and apply fixups.
154  LLVM_DEBUG(dbgs() << " Applying fixups.\n");
155  for (auto &E : B->edges()) {
156 
157  // Skip non-relocation edges.
158  if (!E.isRelocation())
159  continue;
160 
161  // Dispatch to LinkerImpl for fixup.
162  if (auto Err = impl().applyFixup(G, *B, E))
163  return Err;
164  }
165  }
166 
167  return Error::success();
168  }
169 };
170 
171 /// Removes dead symbols/blocks/addressables.
172 ///
173 /// Finds the set of symbols and addressables reachable from any symbol
174 /// initially marked live. All symbols/addressables not marked live at the end
175 /// of this process are removed.
176 void prune(LinkGraph &G);
177 
178 } // end namespace jitlink
179 } // end namespace llvm
180 
181 #undef DEBUG_TYPE // "jitlink"
182 
183 #endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINKGENERIC_H
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
Passes
const char * Passes
Definition: PassBuilderBindings.cpp:46
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::orc::tpctypes::LookupResult
std::vector< JITTargetAddress > LookupResult
Definition: TargetProcessControlTypes.h:144
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
DenseSet.h
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:202
uint64_t
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:80
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::DenseMap
Definition: DenseMap.h:714
G
#define G(x, y, z)
Definition: MD5.cpp:57
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::move
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:1605
std
Definition: BitVector.h:838
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:389