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
//===--- EPCIndirectionUtils.h - EPC based indirection utils ----*- 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
// Indirection utilities (stubs, trampolines, lazy call-throughs) that use the
10
// ExecutorProcessControl API to interact with the executor process.
11
//
12
//===----------------------------------------------------------------------===//
13
 
14
#ifndef LLVM_EXECUTIONENGINE_ORC_EPCINDIRECTIONUTILS_H
15
#define LLVM_EXECUTIONENGINE_ORC_EPCINDIRECTIONUTILS_H
16
 
17
#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
18
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
19
#include "llvm/ExecutionEngine/Orc/LazyReexports.h"
20
 
21
#include <mutex>
22
 
23
namespace llvm {
24
namespace orc {
25
 
26
class ExecutorProcessControl;
27
 
28
/// Provides ExecutorProcessControl based indirect stubs, trampoline pool and
29
/// lazy call through manager.
30
class EPCIndirectionUtils {
31
  friend class EPCIndirectionUtilsAccess;
32
 
33
public:
34
  /// ABI support base class. Used to write resolver, stub, and trampoline
35
  /// blocks.
36
  class ABISupport {
37
  protected:
38
    ABISupport(unsigned PointerSize, unsigned TrampolineSize, unsigned StubSize,
39
               unsigned StubToPointerMaxDisplacement, unsigned ResolverCodeSize)
40
        : PointerSize(PointerSize), TrampolineSize(TrampolineSize),
41
          StubSize(StubSize),
42
          StubToPointerMaxDisplacement(StubToPointerMaxDisplacement),
43
          ResolverCodeSize(ResolverCodeSize) {}
44
 
45
  public:
46
    virtual ~ABISupport();
47
 
48
    unsigned getPointerSize() const { return PointerSize; }
49
    unsigned getTrampolineSize() const { return TrampolineSize; }
50
    unsigned getStubSize() const { return StubSize; }
51
    unsigned getStubToPointerMaxDisplacement() const {
52
      return StubToPointerMaxDisplacement;
53
    }
54
    unsigned getResolverCodeSize() const { return ResolverCodeSize; }
55
 
56
    virtual void writeResolverCode(char *ResolverWorkingMem,
57
                                   JITTargetAddress ResolverTargetAddr,
58
                                   JITTargetAddress ReentryFnAddr,
59
                                   JITTargetAddress ReentryCtxAddr) const = 0;
60
 
61
    virtual void writeTrampolines(char *TrampolineBlockWorkingMem,
62
                                  JITTargetAddress TrampolineBlockTragetAddr,
63
                                  JITTargetAddress ResolverAddr,
64
                                  unsigned NumTrampolines) const = 0;
65
 
66
    virtual void
67
    writeIndirectStubsBlock(char *StubsBlockWorkingMem,
68
                            JITTargetAddress StubsBlockTargetAddress,
69
                            JITTargetAddress PointersBlockTargetAddress,
70
                            unsigned NumStubs) const = 0;
71
 
72
  private:
73
    unsigned PointerSize = 0;
74
    unsigned TrampolineSize = 0;
75
    unsigned StubSize = 0;
76
    unsigned StubToPointerMaxDisplacement = 0;
77
    unsigned ResolverCodeSize = 0;
78
  };
79
 
80
  /// Create using the given ABI class.
81
  template <typename ORCABI>
82
  static std::unique_ptr<EPCIndirectionUtils>
83
  CreateWithABI(ExecutorProcessControl &EPC);
84
 
85
  /// Create based on the ExecutorProcessControl triple.
86
  static Expected<std::unique_ptr<EPCIndirectionUtils>>
87
  Create(ExecutorProcessControl &EPC);
88
 
89
  /// Return a reference to the ExecutorProcessControl object.
90
  ExecutorProcessControl &getExecutorProcessControl() const { return EPC; }
91
 
92
  /// Return a reference to the ABISupport object for this instance.
93
  ABISupport &getABISupport() const { return *ABI; }
94
 
95
  /// Release memory for resources held by this instance. This *must* be called
96
  /// prior to destruction of the class.
97
  Error cleanup();
98
 
99
  /// Write resolver code to the executor process and return its address.
100
  /// This must be called before any call to createTrampolinePool or
101
  /// createLazyCallThroughManager.
102
  Expected<JITTargetAddress>
103
  writeResolverBlock(JITTargetAddress ReentryFnAddr,
104
                     JITTargetAddress ReentryCtxAddr);
105
 
106
  /// Returns the address of the Resolver block. Returns zero if the
107
  /// writeResolverBlock method has not previously been called.
108
  JITTargetAddress getResolverBlockAddress() const { return ResolverBlockAddr; }
109
 
110
  /// Create an IndirectStubsManager for the executor process.
111
  std::unique_ptr<IndirectStubsManager> createIndirectStubsManager();
112
 
113
  /// Create a TrampolinePool for the executor process.
114
  TrampolinePool &getTrampolinePool();
115
 
116
  /// Create a LazyCallThroughManager.
117
  /// This function should only be called once.
118
  LazyCallThroughManager &
119
  createLazyCallThroughManager(ExecutionSession &ES,
120
                               JITTargetAddress ErrorHandlerAddr);
121
 
122
  /// Create a LazyCallThroughManager for the executor process.
123
  LazyCallThroughManager &getLazyCallThroughManager() {
124
    assert(LCTM && "createLazyCallThroughManager must be called first");
125
    return *LCTM;
126
  }
127
 
128
private:
129
  using FinalizedAlloc = jitlink::JITLinkMemoryManager::FinalizedAlloc;
130
 
131
  struct IndirectStubInfo {
132
    IndirectStubInfo() = default;
133
    IndirectStubInfo(JITTargetAddress StubAddress,
134
                     JITTargetAddress PointerAddress)
135
        : StubAddress(StubAddress), PointerAddress(PointerAddress) {}
136
    JITTargetAddress StubAddress = 0;
137
    JITTargetAddress PointerAddress = 0;
138
  };
139
 
140
  using IndirectStubInfoVector = std::vector<IndirectStubInfo>;
141
 
142
  /// Create an EPCIndirectionUtils instance.
143
  EPCIndirectionUtils(ExecutorProcessControl &EPC,
144
                      std::unique_ptr<ABISupport> ABI);
145
 
146
  Expected<IndirectStubInfoVector> getIndirectStubs(unsigned NumStubs);
147
 
148
  std::mutex EPCUIMutex;
149
  ExecutorProcessControl &EPC;
150
  std::unique_ptr<ABISupport> ABI;
151
  JITTargetAddress ResolverBlockAddr = 0;
152
  FinalizedAlloc ResolverBlock;
153
  std::unique_ptr<TrampolinePool> TP;
154
  std::unique_ptr<LazyCallThroughManager> LCTM;
155
 
156
  std::vector<IndirectStubInfo> AvailableIndirectStubs;
157
  std::vector<FinalizedAlloc> IndirectStubAllocs;
158
};
159
 
160
/// This will call writeResolver on the given EPCIndirectionUtils instance
161
/// to set up re-entry via a function that will directly return the trampoline
162
/// landing address.
163
///
164
/// The EPCIndirectionUtils' LazyCallThroughManager must have been previously
165
/// created via EPCIndirectionUtils::createLazyCallThroughManager.
166
///
167
/// The EPCIndirectionUtils' writeResolver method must not have been previously
168
/// called.
169
///
170
/// This function is experimental and likely subject to revision.
171
Error setUpInProcessLCTMReentryViaEPCIU(EPCIndirectionUtils &EPCIU);
172
 
173
namespace detail {
174
 
175
template <typename ORCABI>
176
class ABISupportImpl : public EPCIndirectionUtils::ABISupport {
177
public:
178
  ABISupportImpl()
179
      : ABISupport(ORCABI::PointerSize, ORCABI::TrampolineSize,
180
                   ORCABI::StubSize, ORCABI::StubToPointerMaxDisplacement,
181
                   ORCABI::ResolverCodeSize) {}
182
 
183
  void writeResolverCode(char *ResolverWorkingMem,
184
                         JITTargetAddress ResolverTargetAddr,
185
                         JITTargetAddress ReentryFnAddr,
186
                         JITTargetAddress ReentryCtxAddr) const override {
187
    ORCABI::writeResolverCode(ResolverWorkingMem, ResolverTargetAddr,
188
                              ReentryFnAddr, ReentryCtxAddr);
189
  }
190
 
191
  void writeTrampolines(char *TrampolineBlockWorkingMem,
192
                        JITTargetAddress TrampolineBlockTargetAddr,
193
                        JITTargetAddress ResolverAddr,
194
                        unsigned NumTrampolines) const override {
195
    ORCABI::writeTrampolines(TrampolineBlockWorkingMem,
196
                             TrampolineBlockTargetAddr, ResolverAddr,
197
                             NumTrampolines);
198
  }
199
 
200
  void writeIndirectStubsBlock(char *StubsBlockWorkingMem,
201
                               JITTargetAddress StubsBlockTargetAddress,
202
                               JITTargetAddress PointersBlockTargetAddress,
203
                               unsigned NumStubs) const override {
204
    ORCABI::writeIndirectStubsBlock(StubsBlockWorkingMem,
205
                                    StubsBlockTargetAddress,
206
                                    PointersBlockTargetAddress, NumStubs);
207
  }
208
};
209
 
210
} // end namespace detail
211
 
212
template <typename ORCABI>
213
std::unique_ptr<EPCIndirectionUtils>
214
EPCIndirectionUtils::CreateWithABI(ExecutorProcessControl &EPC) {
215
  return std::unique_ptr<EPCIndirectionUtils>(new EPCIndirectionUtils(
216
      EPC, std::make_unique<detail::ABISupportImpl<ORCABI>>()));
217
}
218
 
219
} // end namespace orc
220
} // end namespace llvm
221
 
222
#endif // LLVM_EXECUTIONENGINE_ORC_EPCINDIRECTIONUTILS_H