Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

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