blob: c2527802f6a75bf2bdea38a4096b71a5b22bad6b [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- IndirectionUtils.h - Utilities for adding indirections ---*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Contains utilities for adding indirections and breaking up modules.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
15#define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
16
17#include "llvm/ADT/StringMap.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/ADT/Twine.h"
20#include "llvm/ExecutionEngine/JITSymbol.h"
Andrew Scullcdfcccc2018-10-05 20:58:37 +010021#include "llvm/ExecutionEngine/Orc/Core.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010022#include "llvm/Support/Error.h"
23#include "llvm/Support/Memory.h"
24#include "llvm/Support/Process.h"
25#include "llvm/Transforms/Utils/ValueMapper.h"
26#include <algorithm>
27#include <cassert>
28#include <cstdint>
29#include <functional>
30#include <map>
31#include <memory>
32#include <system_error>
33#include <utility>
34#include <vector>
35
36namespace llvm {
37
38class Constant;
39class Function;
40class FunctionType;
41class GlobalAlias;
42class GlobalVariable;
43class Module;
44class PointerType;
45class Triple;
46class Value;
47
48namespace orc {
49
Andrew Scull0372a572018-11-16 15:47:06 +000050/// Base class for pools of compiler re-entry trampolines.
51/// These trampolines are callable addresses that save all register state
52/// before calling a supplied function to return the trampoline landing
53/// address, then restore all state before jumping to that address. They
54/// are used by various ORC APIs to support lazy compilation
55class TrampolinePool {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010056public:
Andrew Scull0372a572018-11-16 15:47:06 +000057 virtual ~TrampolinePool() {}
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010058
Andrew Scull0372a572018-11-16 15:47:06 +000059 /// Get an available trampoline address.
60 /// Returns an error if no trampoline can be created.
61 virtual Expected<JITTargetAddress> getTrampoline() = 0;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010062
63private:
Andrew Scull0372a572018-11-16 15:47:06 +000064 virtual void anchor();
65};
66
67/// A trampoline pool for trampolines within the current process.
68template <typename ORCABI> class LocalTrampolinePool : public TrampolinePool {
69public:
70 using GetTrampolineLandingFunction =
71 std::function<JITTargetAddress(JITTargetAddress TrampolineAddr)>;
72
73 /// Creates a LocalTrampolinePool with the given RunCallback function.
74 /// Returns an error if this function is unable to correctly allocate, write
75 /// and protect the resolver code block.
76 static Expected<std::unique_ptr<LocalTrampolinePool>>
77 Create(GetTrampolineLandingFunction GetTrampolineLanding) {
78 Error Err = Error::success();
79
80 auto LTP = std::unique_ptr<LocalTrampolinePool>(
81 new LocalTrampolinePool(std::move(GetTrampolineLanding), Err));
82
83 if (Err)
84 return std::move(Err);
85 return std::move(LTP);
86 }
87
88 /// Get a free trampoline. Returns an error if one can not be provide (e.g.
89 /// because the pool is empty and can not be grown).
90 Expected<JITTargetAddress> getTrampoline() override {
91 std::lock_guard<std::mutex> Lock(LTPMutex);
92 if (AvailableTrampolines.empty()) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010093 if (auto Err = grow())
94 return std::move(Err);
Andrew Scull0372a572018-11-16 15:47:06 +000095 }
96 assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool");
97 auto TrampolineAddr = AvailableTrampolines.back();
98 AvailableTrampolines.pop_back();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010099 return TrampolineAddr;
100 }
101
Andrew Scull0372a572018-11-16 15:47:06 +0000102 /// Returns the given trampoline to the pool for re-use.
103 void releaseTrampoline(JITTargetAddress TrampolineAddr) {
104 std::lock_guard<std::mutex> Lock(LTPMutex);
105 AvailableTrampolines.push_back(TrampolineAddr);
106 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100107
Andrew Scull0372a572018-11-16 15:47:06 +0000108private:
109 static JITTargetAddress reenter(void *TrampolinePoolPtr, void *TrampolineId) {
110 LocalTrampolinePool<ORCABI> *TrampolinePool =
111 static_cast<LocalTrampolinePool *>(TrampolinePoolPtr);
112 return TrampolinePool->GetTrampolineLanding(static_cast<JITTargetAddress>(
113 reinterpret_cast<uintptr_t>(TrampolineId)));
114 }
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100115
Andrew Scull0372a572018-11-16 15:47:06 +0000116 LocalTrampolinePool(GetTrampolineLandingFunction GetTrampolineLanding,
117 Error &Err)
118 : GetTrampolineLanding(std::move(GetTrampolineLanding)) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100119
Andrew Scull0372a572018-11-16 15:47:06 +0000120 ErrorAsOutParameter _(&Err);
121
122 /// Try to set up the resolver block.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100123 std::error_code EC;
124 ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
Andrew Scull0372a572018-11-16 15:47:06 +0000125 ORCABI::ResolverCodeSize, nullptr,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100126 sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
Andrew Scull0372a572018-11-16 15:47:06 +0000127 if (EC) {
128 Err = errorCodeToError(EC);
129 return;
130 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100131
Andrew Scull0372a572018-11-16 15:47:06 +0000132 ORCABI::writeResolverCode(static_cast<uint8_t *>(ResolverBlock.base()),
133 &reenter, this);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100134
135 EC = sys::Memory::protectMappedMemory(ResolverBlock.getMemoryBlock(),
136 sys::Memory::MF_READ |
137 sys::Memory::MF_EXEC);
Andrew Scull0372a572018-11-16 15:47:06 +0000138 if (EC) {
139 Err = errorCodeToError(EC);
140 return;
141 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100142 }
143
Andrew Scull0372a572018-11-16 15:47:06 +0000144 Error grow() {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100145 assert(this->AvailableTrampolines.empty() && "Growing prematurely?");
146
147 std::error_code EC;
148 auto TrampolineBlock =
149 sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
150 sys::Process::getPageSize(), nullptr,
151 sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
152 if (EC)
153 return errorCodeToError(EC);
154
155 unsigned NumTrampolines =
Andrew Scull0372a572018-11-16 15:47:06 +0000156 (sys::Process::getPageSize() - ORCABI::PointerSize) /
157 ORCABI::TrampolineSize;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100158
159 uint8_t *TrampolineMem = static_cast<uint8_t *>(TrampolineBlock.base());
Andrew Scull0372a572018-11-16 15:47:06 +0000160 ORCABI::writeTrampolines(TrampolineMem, ResolverBlock.base(),
161 NumTrampolines);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100162
163 for (unsigned I = 0; I < NumTrampolines; ++I)
164 this->AvailableTrampolines.push_back(
165 static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(
Andrew Scull0372a572018-11-16 15:47:06 +0000166 TrampolineMem + (I * ORCABI::TrampolineSize))));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100167
168 if (auto EC = sys::Memory::protectMappedMemory(
169 TrampolineBlock.getMemoryBlock(),
170 sys::Memory::MF_READ | sys::Memory::MF_EXEC))
171 return errorCodeToError(EC);
172
173 TrampolineBlocks.push_back(std::move(TrampolineBlock));
174 return Error::success();
175 }
176
Andrew Scull0372a572018-11-16 15:47:06 +0000177 GetTrampolineLandingFunction GetTrampolineLanding;
178
179 std::mutex LTPMutex;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100180 sys::OwningMemoryBlock ResolverBlock;
181 std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
Andrew Scull0372a572018-11-16 15:47:06 +0000182 std::vector<JITTargetAddress> AvailableTrampolines;
183};
184
185/// Target-independent base class for compile callback management.
186class JITCompileCallbackManager {
187public:
188 using CompileFunction = std::function<JITTargetAddress()>;
189
190 virtual ~JITCompileCallbackManager() = default;
191
192 /// Reserve a compile callback.
193 Expected<JITTargetAddress> getCompileCallback(CompileFunction Compile);
194
195 /// Execute the callback for the given trampoline id. Called by the JIT
196 /// to compile functions on demand.
197 JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr);
198
199protected:
200 /// Construct a JITCompileCallbackManager.
201 JITCompileCallbackManager(std::unique_ptr<TrampolinePool> TP,
202 ExecutionSession &ES,
203 JITTargetAddress ErrorHandlerAddress)
204 : TP(std::move(TP)), ES(ES),
205 CallbacksJD(ES.createJITDylib("<Callbacks>")),
206 ErrorHandlerAddress(ErrorHandlerAddress) {}
207
208 void setTrampolinePool(std::unique_ptr<TrampolinePool> TP) {
209 this->TP = std::move(TP);
210 }
211
212private:
213 std::mutex CCMgrMutex;
214 std::unique_ptr<TrampolinePool> TP;
215 ExecutionSession &ES;
216 JITDylib &CallbacksJD;
217 JITTargetAddress ErrorHandlerAddress;
218 std::map<JITTargetAddress, SymbolStringPtr> AddrToSymbol;
219 size_t NextCallbackId = 0;
220};
221
222/// Manage compile callbacks for in-process JITs.
223template <typename ORCABI>
224class LocalJITCompileCallbackManager : public JITCompileCallbackManager {
225public:
226 /// Create a new LocalJITCompileCallbackManager.
227 static Expected<std::unique_ptr<LocalJITCompileCallbackManager>>
228 Create(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddress) {
229 Error Err = Error::success();
230 auto CCMgr = std::unique_ptr<LocalJITCompileCallbackManager>(
231 new LocalJITCompileCallbackManager(ES, ErrorHandlerAddress, Err));
232 if (Err)
233 return std::move(Err);
234 return std::move(CCMgr);
235 }
236
237private:
238 /// Construct a InProcessJITCompileCallbackManager.
239 /// @param ErrorHandlerAddress The address of an error handler in the target
240 /// process to be used if a compile callback fails.
241 LocalJITCompileCallbackManager(ExecutionSession &ES,
242 JITTargetAddress ErrorHandlerAddress,
243 Error &Err)
244 : JITCompileCallbackManager(nullptr, ES, ErrorHandlerAddress) {
245 ErrorAsOutParameter _(&Err);
246 auto TP = LocalTrampolinePool<ORCABI>::Create(
247 [this](JITTargetAddress TrampolineAddr) {
248 return executeCompileCallback(TrampolineAddr);
249 });
250
251 if (!TP) {
252 Err = TP.takeError();
253 return;
254 }
255
256 setTrampolinePool(std::move(*TP));
257 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100258};
259
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100260/// Base class for managing collections of named indirect stubs.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100261class IndirectStubsManager {
262public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100263 /// Map type for initializing the manager. See init.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100264 using StubInitsMap = StringMap<std::pair<JITTargetAddress, JITSymbolFlags>>;
265
266 virtual ~IndirectStubsManager() = default;
267
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100268 /// Create a single stub with the given name, target address and flags.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100269 virtual Error createStub(StringRef StubName, JITTargetAddress StubAddr,
270 JITSymbolFlags StubFlags) = 0;
271
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100272 /// Create StubInits.size() stubs with the given names, target
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100273 /// addresses, and flags.
274 virtual Error createStubs(const StubInitsMap &StubInits) = 0;
275
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100276 /// Find the stub with the given name. If ExportedStubsOnly is true,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100277 /// this will only return a result if the stub's flags indicate that it
278 /// is exported.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100279 virtual JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) = 0;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100280
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100281 /// Find the implementation-pointer for the stub.
282 virtual JITEvaluatedSymbol findPointer(StringRef Name) = 0;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100283
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100284 /// Change the value of the implementation pointer for the stub.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100285 virtual Error updatePointer(StringRef Name, JITTargetAddress NewAddr) = 0;
286
287private:
288 virtual void anchor();
289};
290
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100291/// IndirectStubsManager implementation for the host architecture, e.g.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100292/// OrcX86_64. (See OrcArchitectureSupport.h).
293template <typename TargetT>
294class LocalIndirectStubsManager : public IndirectStubsManager {
295public:
296 Error createStub(StringRef StubName, JITTargetAddress StubAddr,
297 JITSymbolFlags StubFlags) override {
Andrew Scull0372a572018-11-16 15:47:06 +0000298 std::lock_guard<std::mutex> Lock(StubsMutex);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100299 if (auto Err = reserveStubs(1))
300 return Err;
301
302 createStubInternal(StubName, StubAddr, StubFlags);
303
304 return Error::success();
305 }
306
307 Error createStubs(const StubInitsMap &StubInits) override {
Andrew Scull0372a572018-11-16 15:47:06 +0000308 std::lock_guard<std::mutex> Lock(StubsMutex);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100309 if (auto Err = reserveStubs(StubInits.size()))
310 return Err;
311
312 for (auto &Entry : StubInits)
313 createStubInternal(Entry.first(), Entry.second.first,
314 Entry.second.second);
315
316 return Error::success();
317 }
318
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100319 JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
Andrew Scull0372a572018-11-16 15:47:06 +0000320 std::lock_guard<std::mutex> Lock(StubsMutex);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100321 auto I = StubIndexes.find(Name);
322 if (I == StubIndexes.end())
323 return nullptr;
324 auto Key = I->second.first;
325 void *StubAddr = IndirectStubsInfos[Key.first].getStub(Key.second);
326 assert(StubAddr && "Missing stub address");
327 auto StubTargetAddr =
328 static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(StubAddr));
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100329 auto StubSymbol = JITEvaluatedSymbol(StubTargetAddr, I->second.second);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100330 if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
331 return nullptr;
332 return StubSymbol;
333 }
334
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100335 JITEvaluatedSymbol findPointer(StringRef Name) override {
Andrew Scull0372a572018-11-16 15:47:06 +0000336 std::lock_guard<std::mutex> Lock(StubsMutex);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100337 auto I = StubIndexes.find(Name);
338 if (I == StubIndexes.end())
339 return nullptr;
340 auto Key = I->second.first;
341 void *PtrAddr = IndirectStubsInfos[Key.first].getPtr(Key.second);
342 assert(PtrAddr && "Missing pointer address");
343 auto PtrTargetAddr =
344 static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(PtrAddr));
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100345 return JITEvaluatedSymbol(PtrTargetAddr, I->second.second);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100346 }
347
348 Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
Andrew Scull0372a572018-11-16 15:47:06 +0000349 using AtomicIntPtr = std::atomic<uintptr_t>;
350
351 std::lock_guard<std::mutex> Lock(StubsMutex);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100352 auto I = StubIndexes.find(Name);
353 assert(I != StubIndexes.end() && "No stub pointer for symbol");
354 auto Key = I->second.first;
Andrew Scull0372a572018-11-16 15:47:06 +0000355 AtomicIntPtr *AtomicStubPtr = reinterpret_cast<AtomicIntPtr *>(
356 IndirectStubsInfos[Key.first].getPtr(Key.second));
357 *AtomicStubPtr = static_cast<uintptr_t>(NewAddr);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100358 return Error::success();
359 }
360
361private:
362 Error reserveStubs(unsigned NumStubs) {
363 if (NumStubs <= FreeStubs.size())
364 return Error::success();
365
366 unsigned NewStubsRequired = NumStubs - FreeStubs.size();
367 unsigned NewBlockId = IndirectStubsInfos.size();
368 typename TargetT::IndirectStubsInfo ISI;
369 if (auto Err =
370 TargetT::emitIndirectStubsBlock(ISI, NewStubsRequired, nullptr))
371 return Err;
372 for (unsigned I = 0; I < ISI.getNumStubs(); ++I)
373 FreeStubs.push_back(std::make_pair(NewBlockId, I));
374 IndirectStubsInfos.push_back(std::move(ISI));
375 return Error::success();
376 }
377
378 void createStubInternal(StringRef StubName, JITTargetAddress InitAddr,
379 JITSymbolFlags StubFlags) {
380 auto Key = FreeStubs.back();
381 FreeStubs.pop_back();
382 *IndirectStubsInfos[Key.first].getPtr(Key.second) =
383 reinterpret_cast<void *>(static_cast<uintptr_t>(InitAddr));
384 StubIndexes[StubName] = std::make_pair(Key, StubFlags);
385 }
386
Andrew Scull0372a572018-11-16 15:47:06 +0000387 std::mutex StubsMutex;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100388 std::vector<typename TargetT::IndirectStubsInfo> IndirectStubsInfos;
389 using StubKey = std::pair<uint16_t, uint16_t>;
390 std::vector<StubKey> FreeStubs;
391 StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
392};
393
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100394/// Create a local compile callback manager.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100395///
396/// The given target triple will determine the ABI, and the given
397/// ErrorHandlerAddress will be used by the resulting compile callback
398/// manager if a compile callback fails.
Andrew Scull0372a572018-11-16 15:47:06 +0000399Expected<std::unique_ptr<JITCompileCallbackManager>>
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100400createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100401 JITTargetAddress ErrorHandlerAddress);
402
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100403/// Create a local indriect stubs manager builder.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100404///
405/// The given target triple will determine the ABI.
406std::function<std::unique_ptr<IndirectStubsManager>()>
407createLocalIndirectStubsManagerBuilder(const Triple &T);
408
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100409/// Build a function pointer of FunctionType with the given constant
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100410/// address.
411///
412/// Usage example: Turn a trampoline address into a function pointer constant
413/// for use in a stub.
414Constant *createIRTypedAddress(FunctionType &FT, JITTargetAddress Addr);
415
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100416/// Create a function pointer with the given type, name, and initializer
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100417/// in the given Module.
418GlobalVariable *createImplPointer(PointerType &PT, Module &M, const Twine &Name,
419 Constant *Initializer);
420
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100421/// Turn a function declaration into a stub function that makes an
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100422/// indirect call using the given function pointer.
423void makeStub(Function &F, Value &ImplPointer);
424
Andrew Scull0372a572018-11-16 15:47:06 +0000425/// Promotes private symbols to global hidden, and renames to prevent clashes
426/// with other promoted symbols. The same SymbolPromoter instance should be
427/// used for all symbols to be added to a single JITDylib.
428class SymbolLinkagePromoter {
429public:
430 /// Promote symbols in the given module. Returns the set of global values
431 /// that have been renamed/promoted.
432 std::vector<GlobalValue *> operator()(Module &M);
433
434private:
435 unsigned NextId = 0;
436};
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100437
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100438/// Clone a function declaration into a new module.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100439///
440/// This function can be used as the first step towards creating a callback
441/// stub (see makeStub), or moving a function body (see moveFunctionBody).
442///
443/// If the VMap argument is non-null, a mapping will be added between F and
444/// the new declaration, and between each of F's arguments and the new
445/// declaration's arguments. This map can then be passed in to moveFunction to
446/// move the function body if required. Note: When moving functions between
447/// modules with these utilities, all decls should be cloned (and added to a
448/// single VMap) before any bodies are moved. This will ensure that references
449/// between functions all refer to the versions in the new module.
450Function *cloneFunctionDecl(Module &Dst, const Function &F,
451 ValueToValueMapTy *VMap = nullptr);
452
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100453/// Move the body of function 'F' to a cloned function declaration in a
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100454/// different module (See related cloneFunctionDecl).
455///
456/// If the target function declaration is not supplied via the NewF parameter
457/// then it will be looked up via the VMap.
458///
459/// This will delete the body of function 'F' from its original parent module,
460/// but leave its declaration.
461void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
462 ValueMaterializer *Materializer = nullptr,
463 Function *NewF = nullptr);
464
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100465/// Clone a global variable declaration into a new module.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100466GlobalVariable *cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
467 ValueToValueMapTy *VMap = nullptr);
468
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100469/// Move global variable GV from its parent module to cloned global
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100470/// declaration in a different module.
471///
472/// If the target global declaration is not supplied via the NewGV parameter
473/// then it will be looked up via the VMap.
474///
475/// This will delete the initializer of GV from its original parent module,
476/// but leave its declaration.
477void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
478 ValueToValueMapTy &VMap,
479 ValueMaterializer *Materializer = nullptr,
480 GlobalVariable *NewGV = nullptr);
481
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100482/// Clone a global alias declaration into a new module.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100483GlobalAlias *cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
484 ValueToValueMapTy &VMap);
485
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100486/// Clone module flags metadata into the destination module.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100487void cloneModuleFlagsMetadata(Module &Dst, const Module &Src,
488 ValueToValueMapTy &VMap);
489
490} // end namespace orc
491
492} // end namespace llvm
493
494#endif // LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H