JITLinkGeneric.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. #ifndef LIB_EXECUTIONENGINE_JITLINK_JITLINKGENERIC_H
  13. #define LIB_EXECUTIONENGINE_JITLINK_JITLINKGENERIC_H
  14. #include "llvm/ADT/DenseSet.h"
  15. #include "llvm/ExecutionEngine/JITLink/JITLink.h"
  16. #define DEBUG_TYPE "jitlink"
  17. namespace llvm {
  18. namespace jitlink {
  19. /// Base class for a JIT linker.
  20. ///
  21. /// A JITLinkerBase instance links one object file into an ongoing JIT
  22. /// session. Symbol resolution and finalization operations are pluggable,
  23. /// and called using continuation passing (passing a continuation for the
  24. /// remaining linker work) to allow them to be performed asynchronously.
  25. class JITLinkerBase {
  26. public:
  27. JITLinkerBase(std::unique_ptr<JITLinkContext> Ctx,
  28. std::unique_ptr<LinkGraph> G, PassConfiguration Passes)
  29. : Ctx(std::move(Ctx)), G(std::move(G)), Passes(std::move(Passes)) {
  30. assert(this->Ctx && "Ctx can not be null");
  31. assert(this->G && "G can not be null");
  32. }
  33. virtual ~JITLinkerBase();
  34. protected:
  35. using InFlightAlloc = JITLinkMemoryManager::InFlightAlloc;
  36. using AllocResult = Expected<std::unique_ptr<InFlightAlloc>>;
  37. using FinalizeResult = Expected<JITLinkMemoryManager::FinalizedAlloc>;
  38. // Returns the PassConfiguration for this instance. This can be used by
  39. // JITLinkerBase implementations to add late passes that reference their
  40. // own data structures (e.g. for ELF implementations to locate / construct
  41. // a GOT start symbol prior to fixup).
  42. PassConfiguration &getPassConfig() { return Passes; }
  43. // Phase 1:
  44. // 1.1: Run pre-prune passes
  45. // 1.2: Prune graph
  46. // 1.3: Run post-prune passes
  47. // 1.4: Allocate memory.
  48. void linkPhase1(std::unique_ptr<JITLinkerBase> Self);
  49. // Phase 2:
  50. // 2.2: Run post-allocation passes
  51. // 2.3: Notify context of final assigned symbol addresses
  52. // 2.4: Identify external symbols and make an async call to resolve
  53. void linkPhase2(std::unique_ptr<JITLinkerBase> Self, AllocResult AR);
  54. // Phase 3:
  55. // 3.1: Apply resolution results
  56. // 3.2: Run pre-fixup passes
  57. // 3.3: Fix up block contents
  58. // 3.4: Run post-fixup passes
  59. // 3.5: Make an async call to transfer and finalize memory.
  60. void linkPhase3(std::unique_ptr<JITLinkerBase> Self,
  61. Expected<AsyncLookupResult> LookupResult);
  62. // Phase 4:
  63. // 4.1: Call OnFinalized callback, handing off allocation.
  64. void linkPhase4(std::unique_ptr<JITLinkerBase> Self, FinalizeResult FR);
  65. private:
  66. // Run all passes in the given pass list, bailing out immediately if any pass
  67. // returns an error.
  68. Error runPasses(LinkGraphPassList &Passes);
  69. // Copy block contents and apply relocations.
  70. // Implemented in JITLinker.
  71. virtual Error fixUpBlocks(LinkGraph &G) const = 0;
  72. JITLinkContext::LookupMap getExternalSymbolNames() const;
  73. void applyLookupResult(AsyncLookupResult LR);
  74. void abandonAllocAndBailOut(std::unique_ptr<JITLinkerBase> Self, Error Err);
  75. std::unique_ptr<JITLinkContext> Ctx;
  76. std::unique_ptr<LinkGraph> G;
  77. PassConfiguration Passes;
  78. std::unique_ptr<InFlightAlloc> Alloc;
  79. };
  80. template <typename LinkerImpl> class JITLinker : public JITLinkerBase {
  81. public:
  82. using JITLinkerBase::JITLinkerBase;
  83. /// Link constructs a LinkerImpl instance and calls linkPhase1.
  84. /// Link should be called with the constructor arguments for LinkerImpl, which
  85. /// will be forwarded to the constructor.
  86. template <typename... ArgTs> static void link(ArgTs &&... Args) {
  87. auto L = std::make_unique<LinkerImpl>(std::forward<ArgTs>(Args)...);
  88. // Ownership of the linker is passed into the linker's doLink function to
  89. // allow it to be passed on to async continuations.
  90. //
  91. // FIXME: Remove LTmp once we have c++17.
  92. // C++17 sequencing rules guarantee that function name expressions are
  93. // sequenced before arguments, so L->linkPhase1(std::move(L), ...) will be
  94. // well formed.
  95. auto &LTmp = *L;
  96. LTmp.linkPhase1(std::move(L));
  97. }
  98. private:
  99. const LinkerImpl &impl() const {
  100. return static_cast<const LinkerImpl &>(*this);
  101. }
  102. Error fixUpBlocks(LinkGraph &G) const override {
  103. LLVM_DEBUG(dbgs() << "Fixing up blocks:\n");
  104. for (auto *B : G.blocks()) {
  105. LLVM_DEBUG(dbgs() << " " << *B << ":\n");
  106. // Copy Block data and apply fixups.
  107. LLVM_DEBUG(dbgs() << " Applying fixups.\n");
  108. assert((!B->isZeroFill() || B->edges_size() == 0) &&
  109. "Edges in zero-fill block?");
  110. for (auto &E : B->edges()) {
  111. // Skip non-relocation edges.
  112. if (!E.isRelocation())
  113. continue;
  114. // Dispatch to LinkerImpl for fixup.
  115. if (auto Err = impl().applyFixup(G, *B, E))
  116. return Err;
  117. }
  118. }
  119. return Error::success();
  120. }
  121. };
  122. /// Removes dead symbols/blocks/addressables.
  123. ///
  124. /// Finds the set of symbols and addressables reachable from any symbol
  125. /// initially marked live. All symbols/addressables not marked live at the end
  126. /// of this process are removed.
  127. void prune(LinkGraph &G);
  128. } // end namespace jitlink
  129. } // end namespace llvm
  130. #undef DEBUG_TYPE // "jitlink"
  131. #endif // LIB_EXECUTIONENGINE_JITLINK_JITLINKGENERIC_H