IndirectionUtils.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- IndirectionUtils.h - Utilities for adding indirections ---*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // Contains utilities for adding indirections and breaking up modules.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
  18. #define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
  19. #include "llvm/ADT/StringMap.h"
  20. #include "llvm/ADT/StringRef.h"
  21. #include "llvm/ExecutionEngine/JITSymbol.h"
  22. #include "llvm/ExecutionEngine/Orc/Core.h"
  23. #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
  24. #include "llvm/Support/Error.h"
  25. #include "llvm/Support/Memory.h"
  26. #include "llvm/Support/Process.h"
  27. #include "llvm/Transforms/Utils/ValueMapper.h"
  28. #include <algorithm>
  29. #include <cassert>
  30. #include <cstdint>
  31. #include <functional>
  32. #include <future>
  33. #include <map>
  34. #include <memory>
  35. #include <system_error>
  36. #include <utility>
  37. #include <vector>
  38. namespace llvm {
  39. class Constant;
  40. class Function;
  41. class FunctionType;
  42. class GlobalAlias;
  43. class GlobalVariable;
  44. class Module;
  45. class PointerType;
  46. class Triple;
  47. class Twine;
  48. class Value;
  49. class MCDisassembler;
  50. class MCInstrAnalysis;
  51. namespace jitlink {
  52. class LinkGraph;
  53. class Symbol;
  54. } // namespace jitlink
  55. namespace orc {
  56. /// Base class for pools of compiler re-entry trampolines.
  57. /// These trampolines are callable addresses that save all register state
  58. /// before calling a supplied function to return the trampoline landing
  59. /// address, then restore all state before jumping to that address. They
  60. /// are used by various ORC APIs to support lazy compilation
  61. class TrampolinePool {
  62. public:
  63. using NotifyLandingResolvedFunction =
  64. unique_function<void(JITTargetAddress) const>;
  65. using ResolveLandingFunction = unique_function<void(
  66. JITTargetAddress TrampolineAddr,
  67. NotifyLandingResolvedFunction OnLandingResolved) const>;
  68. virtual ~TrampolinePool();
  69. /// Get an available trampoline address.
  70. /// Returns an error if no trampoline can be created.
  71. Expected<JITTargetAddress> getTrampoline() {
  72. std::lock_guard<std::mutex> Lock(TPMutex);
  73. if (AvailableTrampolines.empty()) {
  74. if (auto Err = grow())
  75. return std::move(Err);
  76. }
  77. assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool");
  78. auto TrampolineAddr = AvailableTrampolines.back();
  79. AvailableTrampolines.pop_back();
  80. return TrampolineAddr;
  81. }
  82. /// Returns the given trampoline to the pool for re-use.
  83. void releaseTrampoline(JITTargetAddress TrampolineAddr) {
  84. std::lock_guard<std::mutex> Lock(TPMutex);
  85. AvailableTrampolines.push_back(TrampolineAddr);
  86. }
  87. protected:
  88. virtual Error grow() = 0;
  89. std::mutex TPMutex;
  90. std::vector<JITTargetAddress> AvailableTrampolines;
  91. };
  92. /// A trampoline pool for trampolines within the current process.
  93. template <typename ORCABI> class LocalTrampolinePool : public TrampolinePool {
  94. public:
  95. /// Creates a LocalTrampolinePool with the given RunCallback function.
  96. /// Returns an error if this function is unable to correctly allocate, write
  97. /// and protect the resolver code block.
  98. static Expected<std::unique_ptr<LocalTrampolinePool>>
  99. Create(ResolveLandingFunction ResolveLanding) {
  100. Error Err = Error::success();
  101. auto LTP = std::unique_ptr<LocalTrampolinePool>(
  102. new LocalTrampolinePool(std::move(ResolveLanding), Err));
  103. if (Err)
  104. return std::move(Err);
  105. return std::move(LTP);
  106. }
  107. private:
  108. static JITTargetAddress reenter(void *TrampolinePoolPtr, void *TrampolineId) {
  109. LocalTrampolinePool<ORCABI> *TrampolinePool =
  110. static_cast<LocalTrampolinePool *>(TrampolinePoolPtr);
  111. std::promise<JITTargetAddress> LandingAddressP;
  112. auto LandingAddressF = LandingAddressP.get_future();
  113. TrampolinePool->ResolveLanding(pointerToJITTargetAddress(TrampolineId),
  114. [&](JITTargetAddress LandingAddress) {
  115. LandingAddressP.set_value(LandingAddress);
  116. });
  117. return LandingAddressF.get();
  118. }
  119. LocalTrampolinePool(ResolveLandingFunction ResolveLanding, Error &Err)
  120. : ResolveLanding(std::move(ResolveLanding)) {
  121. ErrorAsOutParameter _(&Err);
  122. /// Try to set up the resolver block.
  123. std::error_code EC;
  124. ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
  125. ORCABI::ResolverCodeSize, nullptr,
  126. sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
  127. if (EC) {
  128. Err = errorCodeToError(EC);
  129. return;
  130. }
  131. ORCABI::writeResolverCode(static_cast<char *>(ResolverBlock.base()),
  132. pointerToJITTargetAddress(ResolverBlock.base()),
  133. pointerToJITTargetAddress(&reenter),
  134. pointerToJITTargetAddress(this));
  135. EC = sys::Memory::protectMappedMemory(ResolverBlock.getMemoryBlock(),
  136. sys::Memory::MF_READ |
  137. sys::Memory::MF_EXEC);
  138. if (EC) {
  139. Err = errorCodeToError(EC);
  140. return;
  141. }
  142. }
  143. Error grow() override {
  144. assert(AvailableTrampolines.empty() && "Growing prematurely?");
  145. std::error_code EC;
  146. auto TrampolineBlock =
  147. sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
  148. sys::Process::getPageSizeEstimate(), nullptr,
  149. sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
  150. if (EC)
  151. return errorCodeToError(EC);
  152. unsigned NumTrampolines =
  153. (sys::Process::getPageSizeEstimate() - ORCABI::PointerSize) /
  154. ORCABI::TrampolineSize;
  155. char *TrampolineMem = static_cast<char *>(TrampolineBlock.base());
  156. ORCABI::writeTrampolines(
  157. TrampolineMem, pointerToJITTargetAddress(TrampolineMem),
  158. pointerToJITTargetAddress(ResolverBlock.base()), NumTrampolines);
  159. for (unsigned I = 0; I < NumTrampolines; ++I)
  160. AvailableTrampolines.push_back(pointerToJITTargetAddress(
  161. TrampolineMem + (I * ORCABI::TrampolineSize)));
  162. if (auto EC = sys::Memory::protectMappedMemory(
  163. TrampolineBlock.getMemoryBlock(),
  164. sys::Memory::MF_READ | sys::Memory::MF_EXEC))
  165. return errorCodeToError(EC);
  166. TrampolineBlocks.push_back(std::move(TrampolineBlock));
  167. return Error::success();
  168. }
  169. ResolveLandingFunction ResolveLanding;
  170. sys::OwningMemoryBlock ResolverBlock;
  171. std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
  172. };
  173. /// Target-independent base class for compile callback management.
  174. class JITCompileCallbackManager {
  175. public:
  176. using CompileFunction = std::function<JITTargetAddress()>;
  177. virtual ~JITCompileCallbackManager() = default;
  178. /// Reserve a compile callback.
  179. Expected<JITTargetAddress> getCompileCallback(CompileFunction Compile);
  180. /// Execute the callback for the given trampoline id. Called by the JIT
  181. /// to compile functions on demand.
  182. JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr);
  183. protected:
  184. /// Construct a JITCompileCallbackManager.
  185. JITCompileCallbackManager(std::unique_ptr<TrampolinePool> TP,
  186. ExecutionSession &ES,
  187. JITTargetAddress ErrorHandlerAddress)
  188. : TP(std::move(TP)), ES(ES),
  189. CallbacksJD(ES.createBareJITDylib("<Callbacks>")),
  190. ErrorHandlerAddress(ErrorHandlerAddress) {}
  191. void setTrampolinePool(std::unique_ptr<TrampolinePool> TP) {
  192. this->TP = std::move(TP);
  193. }
  194. private:
  195. std::mutex CCMgrMutex;
  196. std::unique_ptr<TrampolinePool> TP;
  197. ExecutionSession &ES;
  198. JITDylib &CallbacksJD;
  199. JITTargetAddress ErrorHandlerAddress;
  200. std::map<JITTargetAddress, SymbolStringPtr> AddrToSymbol;
  201. size_t NextCallbackId = 0;
  202. };
  203. /// Manage compile callbacks for in-process JITs.
  204. template <typename ORCABI>
  205. class LocalJITCompileCallbackManager : public JITCompileCallbackManager {
  206. public:
  207. /// Create a new LocalJITCompileCallbackManager.
  208. static Expected<std::unique_ptr<LocalJITCompileCallbackManager>>
  209. Create(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddress) {
  210. Error Err = Error::success();
  211. auto CCMgr = std::unique_ptr<LocalJITCompileCallbackManager>(
  212. new LocalJITCompileCallbackManager(ES, ErrorHandlerAddress, Err));
  213. if (Err)
  214. return std::move(Err);
  215. return std::move(CCMgr);
  216. }
  217. private:
  218. /// Construct a InProcessJITCompileCallbackManager.
  219. /// @param ErrorHandlerAddress The address of an error handler in the target
  220. /// process to be used if a compile callback fails.
  221. LocalJITCompileCallbackManager(ExecutionSession &ES,
  222. JITTargetAddress ErrorHandlerAddress,
  223. Error &Err)
  224. : JITCompileCallbackManager(nullptr, ES, ErrorHandlerAddress) {
  225. using NotifyLandingResolvedFunction =
  226. TrampolinePool::NotifyLandingResolvedFunction;
  227. ErrorAsOutParameter _(&Err);
  228. auto TP = LocalTrampolinePool<ORCABI>::Create(
  229. [this](JITTargetAddress TrampolineAddr,
  230. NotifyLandingResolvedFunction NotifyLandingResolved) {
  231. NotifyLandingResolved(executeCompileCallback(TrampolineAddr));
  232. });
  233. if (!TP) {
  234. Err = TP.takeError();
  235. return;
  236. }
  237. setTrampolinePool(std::move(*TP));
  238. }
  239. };
  240. /// Base class for managing collections of named indirect stubs.
  241. class IndirectStubsManager {
  242. public:
  243. /// Map type for initializing the manager. See init.
  244. using StubInitsMap = StringMap<std::pair<JITTargetAddress, JITSymbolFlags>>;
  245. virtual ~IndirectStubsManager() = default;
  246. /// Create a single stub with the given name, target address and flags.
  247. virtual Error createStub(StringRef StubName, JITTargetAddress StubAddr,
  248. JITSymbolFlags StubFlags) = 0;
  249. /// Create StubInits.size() stubs with the given names, target
  250. /// addresses, and flags.
  251. virtual Error createStubs(const StubInitsMap &StubInits) = 0;
  252. /// Find the stub with the given name. If ExportedStubsOnly is true,
  253. /// this will only return a result if the stub's flags indicate that it
  254. /// is exported.
  255. virtual JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) = 0;
  256. /// Find the implementation-pointer for the stub.
  257. virtual JITEvaluatedSymbol findPointer(StringRef Name) = 0;
  258. /// Change the value of the implementation pointer for the stub.
  259. virtual Error updatePointer(StringRef Name, JITTargetAddress NewAddr) = 0;
  260. private:
  261. virtual void anchor();
  262. };
  263. template <typename ORCABI> class LocalIndirectStubsInfo {
  264. public:
  265. LocalIndirectStubsInfo(unsigned NumStubs, sys::OwningMemoryBlock StubsMem)
  266. : NumStubs(NumStubs), StubsMem(std::move(StubsMem)) {}
  267. static Expected<LocalIndirectStubsInfo> create(unsigned MinStubs,
  268. unsigned PageSize) {
  269. auto ISAS = getIndirectStubsBlockSizes<ORCABI>(MinStubs, PageSize);
  270. assert((ISAS.StubBytes % PageSize == 0) &&
  271. "StubBytes is not a page size multiple");
  272. uint64_t PointerAlloc = alignTo(ISAS.PointerBytes, PageSize);
  273. // Allocate memory for stubs and pointers in one call.
  274. std::error_code EC;
  275. auto StubsAndPtrsMem =
  276. sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
  277. ISAS.StubBytes + PointerAlloc, nullptr,
  278. sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
  279. if (EC)
  280. return errorCodeToError(EC);
  281. sys::MemoryBlock StubsBlock(StubsAndPtrsMem.base(), ISAS.StubBytes);
  282. auto StubsBlockMem = static_cast<char *>(StubsAndPtrsMem.base());
  283. auto PtrBlockAddress =
  284. pointerToJITTargetAddress(StubsBlockMem) + ISAS.StubBytes;
  285. ORCABI::writeIndirectStubsBlock(StubsBlockMem,
  286. pointerToJITTargetAddress(StubsBlockMem),
  287. PtrBlockAddress, ISAS.NumStubs);
  288. if (auto EC = sys::Memory::protectMappedMemory(
  289. StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC))
  290. return errorCodeToError(EC);
  291. return LocalIndirectStubsInfo(ISAS.NumStubs, std::move(StubsAndPtrsMem));
  292. }
  293. unsigned getNumStubs() const { return NumStubs; }
  294. void *getStub(unsigned Idx) const {
  295. return static_cast<char *>(StubsMem.base()) + Idx * ORCABI::StubSize;
  296. }
  297. void **getPtr(unsigned Idx) const {
  298. char *PtrsBase =
  299. static_cast<char *>(StubsMem.base()) + NumStubs * ORCABI::StubSize;
  300. return reinterpret_cast<void **>(PtrsBase) + Idx;
  301. }
  302. private:
  303. unsigned NumStubs = 0;
  304. sys::OwningMemoryBlock StubsMem;
  305. };
  306. /// IndirectStubsManager implementation for the host architecture, e.g.
  307. /// OrcX86_64. (See OrcArchitectureSupport.h).
  308. template <typename TargetT>
  309. class LocalIndirectStubsManager : public IndirectStubsManager {
  310. public:
  311. Error createStub(StringRef StubName, JITTargetAddress StubAddr,
  312. JITSymbolFlags StubFlags) override {
  313. std::lock_guard<std::mutex> Lock(StubsMutex);
  314. if (auto Err = reserveStubs(1))
  315. return Err;
  316. createStubInternal(StubName, StubAddr, StubFlags);
  317. return Error::success();
  318. }
  319. Error createStubs(const StubInitsMap &StubInits) override {
  320. std::lock_guard<std::mutex> Lock(StubsMutex);
  321. if (auto Err = reserveStubs(StubInits.size()))
  322. return Err;
  323. for (const auto &Entry : StubInits)
  324. createStubInternal(Entry.first(), Entry.second.first,
  325. Entry.second.second);
  326. return Error::success();
  327. }
  328. JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
  329. std::lock_guard<std::mutex> Lock(StubsMutex);
  330. auto I = StubIndexes.find(Name);
  331. if (I == StubIndexes.end())
  332. return nullptr;
  333. auto Key = I->second.first;
  334. void *StubAddr = IndirectStubsInfos[Key.first].getStub(Key.second);
  335. assert(StubAddr && "Missing stub address");
  336. auto StubTargetAddr =
  337. static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(StubAddr));
  338. auto StubSymbol = JITEvaluatedSymbol(StubTargetAddr, I->second.second);
  339. if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
  340. return nullptr;
  341. return StubSymbol;
  342. }
  343. JITEvaluatedSymbol findPointer(StringRef Name) override {
  344. std::lock_guard<std::mutex> Lock(StubsMutex);
  345. auto I = StubIndexes.find(Name);
  346. if (I == StubIndexes.end())
  347. return nullptr;
  348. auto Key = I->second.first;
  349. void *PtrAddr = IndirectStubsInfos[Key.first].getPtr(Key.second);
  350. assert(PtrAddr && "Missing pointer address");
  351. auto PtrTargetAddr =
  352. static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(PtrAddr));
  353. return JITEvaluatedSymbol(PtrTargetAddr, I->second.second);
  354. }
  355. Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
  356. using AtomicIntPtr = std::atomic<uintptr_t>;
  357. std::lock_guard<std::mutex> Lock(StubsMutex);
  358. auto I = StubIndexes.find(Name);
  359. assert(I != StubIndexes.end() && "No stub pointer for symbol");
  360. auto Key = I->second.first;
  361. AtomicIntPtr *AtomicStubPtr = reinterpret_cast<AtomicIntPtr *>(
  362. IndirectStubsInfos[Key.first].getPtr(Key.second));
  363. *AtomicStubPtr = static_cast<uintptr_t>(NewAddr);
  364. return Error::success();
  365. }
  366. private:
  367. Error reserveStubs(unsigned NumStubs) {
  368. if (NumStubs <= FreeStubs.size())
  369. return Error::success();
  370. unsigned NewStubsRequired = NumStubs - FreeStubs.size();
  371. unsigned NewBlockId = IndirectStubsInfos.size();
  372. auto ISI =
  373. LocalIndirectStubsInfo<TargetT>::create(NewStubsRequired, PageSize);
  374. if (!ISI)
  375. return ISI.takeError();
  376. for (unsigned I = 0; I < ISI->getNumStubs(); ++I)
  377. FreeStubs.push_back(std::make_pair(NewBlockId, I));
  378. IndirectStubsInfos.push_back(std::move(*ISI));
  379. return Error::success();
  380. }
  381. void createStubInternal(StringRef StubName, JITTargetAddress InitAddr,
  382. JITSymbolFlags StubFlags) {
  383. auto Key = FreeStubs.back();
  384. FreeStubs.pop_back();
  385. *IndirectStubsInfos[Key.first].getPtr(Key.second) =
  386. jitTargetAddressToPointer<void *>(InitAddr);
  387. StubIndexes[StubName] = std::make_pair(Key, StubFlags);
  388. }
  389. unsigned PageSize = sys::Process::getPageSizeEstimate();
  390. std::mutex StubsMutex;
  391. std::vector<LocalIndirectStubsInfo<TargetT>> IndirectStubsInfos;
  392. using StubKey = std::pair<uint16_t, uint16_t>;
  393. std::vector<StubKey> FreeStubs;
  394. StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
  395. };
  396. /// Create a local compile callback manager.
  397. ///
  398. /// The given target triple will determine the ABI, and the given
  399. /// ErrorHandlerAddress will be used by the resulting compile callback
  400. /// manager if a compile callback fails.
  401. Expected<std::unique_ptr<JITCompileCallbackManager>>
  402. createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
  403. JITTargetAddress ErrorHandlerAddress);
  404. /// Create a local indriect stubs manager builder.
  405. ///
  406. /// The given target triple will determine the ABI.
  407. std::function<std::unique_ptr<IndirectStubsManager>()>
  408. createLocalIndirectStubsManagerBuilder(const Triple &T);
  409. /// Build a function pointer of FunctionType with the given constant
  410. /// address.
  411. ///
  412. /// Usage example: Turn a trampoline address into a function pointer constant
  413. /// for use in a stub.
  414. Constant *createIRTypedAddress(FunctionType &FT, JITTargetAddress Addr);
  415. /// Create a function pointer with the given type, name, and initializer
  416. /// in the given Module.
  417. GlobalVariable *createImplPointer(PointerType &PT, Module &M, const Twine &Name,
  418. Constant *Initializer);
  419. /// Turn a function declaration into a stub function that makes an
  420. /// indirect call using the given function pointer.
  421. void makeStub(Function &F, Value &ImplPointer);
  422. /// Promotes private symbols to global hidden, and renames to prevent clashes
  423. /// with other promoted symbols. The same SymbolPromoter instance should be
  424. /// used for all symbols to be added to a single JITDylib.
  425. class SymbolLinkagePromoter {
  426. public:
  427. /// Promote symbols in the given module. Returns the set of global values
  428. /// that have been renamed/promoted.
  429. std::vector<GlobalValue *> operator()(Module &M);
  430. private:
  431. unsigned NextId = 0;
  432. };
  433. /// Clone a function declaration into a new module.
  434. ///
  435. /// This function can be used as the first step towards creating a callback
  436. /// stub (see makeStub), or moving a function body (see moveFunctionBody).
  437. ///
  438. /// If the VMap argument is non-null, a mapping will be added between F and
  439. /// the new declaration, and between each of F's arguments and the new
  440. /// declaration's arguments. This map can then be passed in to moveFunction to
  441. /// move the function body if required. Note: When moving functions between
  442. /// modules with these utilities, all decls should be cloned (and added to a
  443. /// single VMap) before any bodies are moved. This will ensure that references
  444. /// between functions all refer to the versions in the new module.
  445. Function *cloneFunctionDecl(Module &Dst, const Function &F,
  446. ValueToValueMapTy *VMap = nullptr);
  447. /// Move the body of function 'F' to a cloned function declaration in a
  448. /// different module (See related cloneFunctionDecl).
  449. ///
  450. /// If the target function declaration is not supplied via the NewF parameter
  451. /// then it will be looked up via the VMap.
  452. ///
  453. /// This will delete the body of function 'F' from its original parent module,
  454. /// but leave its declaration.
  455. void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
  456. ValueMaterializer *Materializer = nullptr,
  457. Function *NewF = nullptr);
  458. /// Clone a global variable declaration into a new module.
  459. GlobalVariable *cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
  460. ValueToValueMapTy *VMap = nullptr);
  461. /// Move global variable GV from its parent module to cloned global
  462. /// declaration in a different module.
  463. ///
  464. /// If the target global declaration is not supplied via the NewGV parameter
  465. /// then it will be looked up via the VMap.
  466. ///
  467. /// This will delete the initializer of GV from its original parent module,
  468. /// but leave its declaration.
  469. void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
  470. ValueToValueMapTy &VMap,
  471. ValueMaterializer *Materializer = nullptr,
  472. GlobalVariable *NewGV = nullptr);
  473. /// Clone a global alias declaration into a new module.
  474. GlobalAlias *cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
  475. ValueToValueMapTy &VMap);
  476. /// Clone module flags metadata into the destination module.
  477. void cloneModuleFlagsMetadata(Module &Dst, const Module &Src,
  478. ValueToValueMapTy &VMap);
  479. /// Introduce relocations to \p Sym in its own definition if there are any
  480. /// pointers formed via PC-relative address that do not already have a
  481. /// relocation.
  482. ///
  483. /// This is useful when introducing indirection via a stub function at link time
  484. /// without compiler support. If a function pointer is formed without a
  485. /// relocation, e.g. in the definition of \c foo
  486. ///
  487. /// \code
  488. /// _foo:
  489. /// leaq -7(%rip), rax # form pointer to _foo without relocation
  490. /// _bar:
  491. /// leaq (%rip), %rax # uses X86_64_RELOC_SIGNED to '_foo'
  492. /// \endcode
  493. ///
  494. /// the pointer to \c _foo computed by \c _foo and \c _bar may differ if we
  495. /// introduce a stub for _foo. If the pointer is used as a key, this may be
  496. /// observable to the program. This pass will attempt to introduce the missing
  497. /// "self-relocation" on the leaq instruction.
  498. ///
  499. /// This is based on disassembly and should be considered "best effort". It may
  500. /// silently fail to add relocations.
  501. Error addFunctionPointerRelocationsToCurrentSymbol(jitlink::Symbol &Sym,
  502. jitlink::LinkGraph &G,
  503. MCDisassembler &Disassembler,
  504. MCInstrAnalysis &MIA);
  505. } // end namespace orc
  506. } // end namespace llvm
  507. #endif // LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
  508. #ifdef __GNUC__
  509. #pragma GCC diagnostic pop
  510. #endif