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
//===------ LazyReexports.h -- Utilities for lazy reexports -----*- 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
// Lazy re-exports are similar to normal re-exports, except that for callable
10
// symbols the definitions are replaced with trampolines that will look up and
11
// call through to the re-exported symbol at runtime. This can be used to
12
// enable lazy compilation.
13
//
14
//===----------------------------------------------------------------------===//
15
 
16
#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
17
#define LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
18
 
19
#include "llvm/ADT/STLExtras.h"
20
#include "llvm/ExecutionEngine/Orc/Core.h"
21
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
22
#include "llvm/ExecutionEngine/Orc/Speculation.h"
23
 
24
namespace llvm {
25
 
26
class Triple;
27
 
28
namespace orc {
29
 
30
/// Manages a set of 'lazy call-through' trampolines. These are compiler
31
/// re-entry trampolines that are pre-bound to look up a given symbol in a given
32
/// JITDylib, then jump to that address. Since compilation of symbols is
33
/// triggered on first lookup, these call-through trampolines can be used to
34
/// implement lazy compilation.
35
///
36
/// The easiest way to construct these call-throughs is using the lazyReexport
37
/// function.
38
class LazyCallThroughManager {
39
public:
40
  using NotifyResolvedFunction =
41
      unique_function<Error(JITTargetAddress ResolvedAddr)>;
42
 
43
  LazyCallThroughManager(ExecutionSession &ES,
44
                         JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP);
45
 
46
  // Return a free call-through trampoline and bind it to look up and call
47
  // through to the given symbol.
48
  Expected<JITTargetAddress>
49
  getCallThroughTrampoline(JITDylib &SourceJD, SymbolStringPtr SymbolName,
50
                           NotifyResolvedFunction NotifyResolved);
51
 
52
  void resolveTrampolineLandingAddress(
53
      JITTargetAddress TrampolineAddr,
54
      TrampolinePool::NotifyLandingResolvedFunction NotifyLandingResolved);
55
 
56
  virtual ~LazyCallThroughManager() = default;
57
 
58
protected:
59
  using NotifyLandingResolvedFunction =
60
      TrampolinePool::NotifyLandingResolvedFunction;
61
 
62
  struct ReexportsEntry {
63
    JITDylib *SourceJD;
64
    SymbolStringPtr SymbolName;
65
  };
66
 
67
  JITTargetAddress reportCallThroughError(Error Err);
68
  Expected<ReexportsEntry> findReexport(JITTargetAddress TrampolineAddr);
69
  Error notifyResolved(JITTargetAddress TrampolineAddr,
70
                       JITTargetAddress ResolvedAddr);
71
  void setTrampolinePool(TrampolinePool &TP) { this->TP = &TP; }
72
 
73
private:
74
  using ReexportsMap = std::map<JITTargetAddress, ReexportsEntry>;
75
 
76
  using NotifiersMap = std::map<JITTargetAddress, NotifyResolvedFunction>;
77
 
78
  std::mutex LCTMMutex;
79
  ExecutionSession &ES;
80
  JITTargetAddress ErrorHandlerAddr;
81
  TrampolinePool *TP = nullptr;
82
  ReexportsMap Reexports;
83
  NotifiersMap Notifiers;
84
};
85
 
86
/// A lazy call-through manager that builds trampolines in the current process.
87
class LocalLazyCallThroughManager : public LazyCallThroughManager {
88
private:
89
  using NotifyTargetResolved = unique_function<void(JITTargetAddress)>;
90
 
91
  LocalLazyCallThroughManager(ExecutionSession &ES,
92
                              JITTargetAddress ErrorHandlerAddr)
93
      : LazyCallThroughManager(ES, ErrorHandlerAddr, nullptr) {}
94
 
95
  template <typename ORCABI> Error init() {
96
    auto TP = LocalTrampolinePool<ORCABI>::Create(
97
        [this](JITTargetAddress TrampolineAddr,
98
               TrampolinePool::NotifyLandingResolvedFunction
99
                   NotifyLandingResolved) {
100
          resolveTrampolineLandingAddress(TrampolineAddr,
101
                                          std::move(NotifyLandingResolved));
102
        });
103
 
104
    if (!TP)
105
      return TP.takeError();
106
 
107
    this->TP = std::move(*TP);
108
    setTrampolinePool(*this->TP);
109
    return Error::success();
110
  }
111
 
112
  std::unique_ptr<TrampolinePool> TP;
113
 
114
public:
115
  /// Create a LocalLazyCallThroughManager using the given ABI. See
116
  /// createLocalLazyCallThroughManager.
117
  template <typename ORCABI>
118
  static Expected<std::unique_ptr<LocalLazyCallThroughManager>>
119
  Create(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr) {
120
    auto LLCTM = std::unique_ptr<LocalLazyCallThroughManager>(
121
        new LocalLazyCallThroughManager(ES, ErrorHandlerAddr));
122
 
123
    if (auto Err = LLCTM->init<ORCABI>())
124
      return std::move(Err);
125
 
126
    return std::move(LLCTM);
127
  }
128
};
129
 
130
/// Create a LocalLazyCallThroughManager from the given triple and execution
131
/// session.
132
Expected<std::unique_ptr<LazyCallThroughManager>>
133
createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
134
                                  JITTargetAddress ErrorHandlerAddr);
135
 
136
/// A materialization unit that builds lazy re-exports. These are callable
137
/// entry points that call through to the given symbols.
138
/// Unlike a 'true' re-export, the address of the lazy re-export will not
139
/// match the address of the re-exported symbol, but calling it will behave
140
/// the same as calling the re-exported symbol.
141
class LazyReexportsMaterializationUnit : public MaterializationUnit {
142
public:
143
  LazyReexportsMaterializationUnit(LazyCallThroughManager &LCTManager,
144
                                   IndirectStubsManager &ISManager,
145
                                   JITDylib &SourceJD,
146
                                   SymbolAliasMap CallableAliases,
147
                                   ImplSymbolMap *SrcJDLoc);
148
 
149
  StringRef getName() const override;
150
 
151
private:
152
  void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
153
  void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
154
  static MaterializationUnit::Interface
155
  extractFlags(const SymbolAliasMap &Aliases);
156
 
157
  LazyCallThroughManager &LCTManager;
158
  IndirectStubsManager &ISManager;
159
  JITDylib &SourceJD;
160
  SymbolAliasMap CallableAliases;
161
  ImplSymbolMap *AliaseeTable;
162
};
163
 
164
/// Define lazy-reexports based on the given SymbolAliasMap. Each lazy re-export
165
/// is a callable symbol that will look up and dispatch to the given aliasee on
166
/// first call. All subsequent calls will go directly to the aliasee.
167
inline std::unique_ptr<LazyReexportsMaterializationUnit>
168
lazyReexports(LazyCallThroughManager &LCTManager,
169
              IndirectStubsManager &ISManager, JITDylib &SourceJD,
170
              SymbolAliasMap CallableAliases,
171
              ImplSymbolMap *SrcJDLoc = nullptr) {
172
  return std::make_unique<LazyReexportsMaterializationUnit>(
173
      LCTManager, ISManager, SourceJD, std::move(CallableAliases), SrcJDLoc);
174
}
175
 
176
} // End namespace orc
177
} // End namespace llvm
178
 
179
#endif // LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H