[Orc] Add a JITSymbol class to the Orc APIs, refactor APIs, update clients.
[oota-llvm.git] / include / llvm / ExecutionEngine / Orc / IndirectionUtils.h
1 //===-- 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 "JITSymbol.h"
18 #include "llvm/IR/Mangler.h"
19 #include "llvm/IR/Module.h"
20 #include <sstream>
21
22 namespace llvm {
23
24 /// @brief Persistent name mangling.
25 ///
26 ///   This class provides name mangling that can outlive a Module (and its
27 /// DataLayout).
28 class PersistentMangler {
29 public:
30   PersistentMangler(DataLayout DL) : DL(std::move(DL)), M(&this->DL) {}
31
32   std::string getMangledName(StringRef Name) const {
33     std::string MangledName;
34     {
35       raw_string_ostream MangledNameStream(MangledName);
36       M.getNameWithPrefix(MangledNameStream, Name);
37     }
38     return MangledName;
39   }
40
41 private:
42   DataLayout DL;
43   Mangler M;
44 };
45
46 /// @brief Handle callbacks from the JIT process requesting the definitions of
47 ///        symbols.
48 ///
49 ///   This utility is intended to be used to support compile-on-demand for
50 /// functions.
51 class JITResolveCallbackHandler {
52 private:
53   typedef std::vector<std::string> FuncNameList;
54
55 public:
56   typedef FuncNameList::size_type StubIndex;
57
58 public:
59   /// @brief Create a JITResolveCallbackHandler with the given functors for
60   ///        looking up symbols and updating their use-sites.
61   ///
62   /// @return A JITResolveCallbackHandler instance that will invoke the
63   ///         Lookup and Update functors as needed to resolve missing symbol
64   ///         definitions.
65   template <typename LookupFtor, typename UpdateFtor>
66   static std::unique_ptr<JITResolveCallbackHandler> create(LookupFtor Lookup,
67                                                            UpdateFtor Update);
68
69   /// @brief Destroy instance. Does not modify existing emitted symbols.
70   ///
71   ///   Not-yet-emitted symbols will need to be resolved some other way after
72   /// this class is destroyed.
73   virtual ~JITResolveCallbackHandler() {}
74
75   /// @brief Add a function to be resolved on demand.
76   void addFuncName(std::string Name) { FuncNames.push_back(std::move(Name)); }
77
78   /// @brief Get the name associated with the given index.
79   const std::string &getFuncName(StubIndex Idx) const { return FuncNames[Idx]; }
80
81   /// @brief Returns the number of symbols being managed by this instance.
82   StubIndex getNumFuncs() const { return FuncNames.size(); }
83
84   /// @brief Get the address for the symbol associated with the given index.
85   ///
86   ///   This is expected to be called by code in the JIT process itself, in
87   /// order to resolve a function.
88   virtual TargetAddress resolve(StubIndex StubIdx) = 0;
89
90 private:
91   FuncNameList FuncNames;
92 };
93
94 // Implementation class for JITResolveCallbackHandler.
95 template <typename LookupFtor, typename UpdateFtor>
96 class JITResolveCallbackHandlerImpl : public JITResolveCallbackHandler {
97 public:
98   JITResolveCallbackHandlerImpl(LookupFtor Lookup, UpdateFtor Update)
99       : Lookup(std::move(Lookup)), Update(std::move(Update)) {}
100
101   TargetAddress resolve(StubIndex StubIdx) override {
102     const std::string &FuncName = getFuncName(StubIdx);
103     TargetAddress Addr = Lookup(FuncName);
104     Update(FuncName, Addr);
105     return Addr;
106   }
107
108 private:
109   LookupFtor Lookup;
110   UpdateFtor Update;
111 };
112
113 template <typename LookupFtor, typename UpdateFtor>
114 std::unique_ptr<JITResolveCallbackHandler>
115 JITResolveCallbackHandler::create(LookupFtor Lookup, UpdateFtor Update) {
116   typedef JITResolveCallbackHandlerImpl<LookupFtor, UpdateFtor> Impl;
117   return make_unique<Impl>(std::move(Lookup), std::move(Update));
118 }
119
120 /// @brief Holds a list of the function names that were indirected, plus
121 ///        mappings from each of these names to (a) the name of function
122 ///        providing the implementation for that name (GetImplNames), and
123 ///        (b) the name of the global variable holding the address of the
124 ///        implementation.
125 ///
126 ///   This data structure can be used with a JITCallbackHandler to look up and
127 /// update function implementations when lazily compiling.
128 class JITIndirections {
129 public:
130   JITIndirections(std::vector<std::string> IndirectedNames,
131                   std::function<std::string(StringRef)> GetImplName,
132                   std::function<std::string(StringRef)> GetAddrName)
133       : IndirectedNames(std::move(IndirectedNames)),
134         GetImplName(std::move(GetImplName)),
135         GetAddrName(std::move(GetAddrName)) {}
136
137   std::vector<std::string> IndirectedNames;
138   std::function<std::string(StringRef Name)> GetImplName;
139   std::function<std::string(StringRef Name)> GetAddrName;
140 };
141
142 /// @brief Indirect all calls to functions matching the predicate
143 ///        ShouldIndirect through a global variable containing the address
144 ///        of the implementation.
145 ///
146 /// @return An indirection structure containing the functions that had their
147 ///         call-sites re-written.
148 ///
149 ///   For each function 'F' that meets the ShouldIndirect predicate, and that
150 /// is called in this Module, add a common-linkage global variable to the
151 /// module that will hold the address of the implementation of that function.
152 /// Rewrite all call-sites of 'F' to be indirect calls (via the global).
153 /// This allows clients, either directly or via a JITCallbackHandler, to
154 /// change the address of the implementation of 'F' at runtime.
155 ///
156 /// Important notes:
157 ///
158 ///   Single indirection does not preserve pointer equality for 'F'. If the
159 /// program was already calling 'F' indirectly through function pointers, or
160 /// if it was taking the address of 'F' for the purpose of pointer comparisons
161 /// or arithmetic double indirection should be used instead.
162 ///
163 ///   This method does *not* initialize the function implementation addresses.
164 /// The client must do this prior to running any call-sites that have been
165 /// indirected.
166 JITIndirections makeCallsSingleIndirect(
167     llvm::Module &M,
168     const std::function<bool(const Function &)> &ShouldIndirect,
169     const char *JITImplSuffix, const char *JITAddrSuffix);
170
171 /// @brief Replace the body of functions matching the predicate ShouldIndirect
172 ///        with indirect calls to the implementation.
173 ///
174 /// @return An indirections structure containing the functions that had their
175 ///         implementations re-written.
176 ///
177 ///   For each function 'F' that meets the ShouldIndirect predicate, add a
178 /// common-linkage global variable to the module that will hold the address of
179 /// the implementation of that function and rewrite the implementation of 'F'
180 /// to call through to the implementation indirectly (via the global).
181 /// This allows clients, either directly or via a JITCallbackHandler, to
182 /// change the address of the implementation of 'F' at runtime.
183 ///
184 /// Important notes:
185 ///
186 ///   Double indirection is slower than single indirection, but preserves
187 /// function pointer relation tests and correct behavior for function pointers
188 /// (all calls to 'F', direct or indirect) go the address stored in the global
189 /// variable at the time of the call.
190 ///
191 ///   This method does *not* initialize the function implementation addresses.
192 /// The client must do this prior to running any call-sites that have been
193 /// indirected.
194 JITIndirections makeCallsDoubleIndirect(
195     llvm::Module &M,
196     const std::function<bool(const Function &)> &ShouldIndirect,
197     const char *JITImplSuffix, const char *JITAddrSuffix);
198
199 /// @brief Given a set of indirections and a symbol lookup functor, create a
200 ///        JITResolveCallbackHandler instance that will resolve the
201 ///        implementations for the indirected symbols on demand.
202 template <typename SymbolLookupFtor>
203 std::unique_ptr<JITResolveCallbackHandler>
204 createCallbackHandlerFromJITIndirections(const JITIndirections &Indirs,
205                                          const PersistentMangler &NM,
206                                          SymbolLookupFtor Lookup) {
207   auto GetImplName = Indirs.GetImplName;
208   auto GetAddrName = Indirs.GetAddrName;
209
210   std::unique_ptr<JITResolveCallbackHandler> J =
211       JITResolveCallbackHandler::create(
212           [=](const std::string &S) {
213             return Lookup(NM.getMangledName(GetImplName(S)));
214           },
215           [=](const std::string &S, TargetAddress Addr) {
216             void *ImplPtr = reinterpret_cast<void *>(
217                 Lookup(NM.getMangledName(GetAddrName(S))));
218             memcpy(ImplPtr, &Addr, sizeof(TargetAddress));
219           });
220
221   for (const auto &FuncName : Indirs.IndirectedNames)
222     J->addFuncName(FuncName);
223
224   return J;
225 }
226
227 /// @brief Insert callback asm into module M for the symbols managed by
228 ///        JITResolveCallbackHandler J.
229 void insertX86CallbackAsm(Module &M, JITResolveCallbackHandler &J);
230
231 /// @brief Initialize global indirects to point into the callback asm.
232 template <typename LookupFtor>
233 void initializeFuncAddrs(JITResolveCallbackHandler &J,
234                          const JITIndirections &Indirs,
235                          const PersistentMangler &NM, LookupFtor Lookup) {
236   // Forward declare so that we can access this, even though it's an
237   // implementation detail.
238   std::string getJITResolveCallbackIndexLabel(unsigned I);
239
240   if (J.getNumFuncs() == 0)
241     return;
242
243   //   Force a look up one of the global addresses for a function that has been
244   // indirected. We need to do this to trigger the emission of the module
245   // holding the callback asm. We can't rely on that emission happening
246   // automatically when we look up the callback asm symbols, since lazy-emitting
247   // layers can't see those.
248   Lookup(NM.getMangledName(Indirs.GetAddrName(J.getFuncName(0))));
249
250   // Now update indirects to point to the JIT resolve callback asm.
251   for (JITResolveCallbackHandler::StubIndex I = 0; I < J.getNumFuncs(); ++I) {
252     TargetAddress ResolveCallbackIdxAddr =
253         Lookup(getJITResolveCallbackIndexLabel(I));
254     void *AddrPtr = reinterpret_cast<void *>(
255         Lookup(NM.getMangledName(Indirs.GetAddrName(J.getFuncName(I)))));
256     assert(AddrPtr && "Can't find stub addr global to initialize.");
257     memcpy(AddrPtr, &ResolveCallbackIdxAddr, sizeof(TargetAddress));
258   }
259 }
260
261 /// @brief Extract all functions matching the predicate ShouldExtract in to
262 ///        their own modules. (Does not modify the original module.)
263 ///
264 /// @return A set of modules, the first containing all symbols (including
265 ///         globals and aliases) that did not pass ShouldExtract, and each
266 ///         subsequent module containing one of the functions that did meet
267 ///         ShouldExtract.
268 ///
269 ///   By adding the resulting modules separately (not as a set) to a
270 /// LazyEmittingLayer instance, compilation can be deferred until symbols are
271 /// actually needed.
272 std::vector<std::unique_ptr<llvm::Module>>
273 explode(const llvm::Module &OrigMod,
274         const std::function<bool(const Function &)> &ShouldExtract);
275
276 /// @brief Given a module that has been indirectified, break each function
277 ///        that has been indirected out into its own module. (Does not modify
278 ///        the original module).
279 ///
280 /// @returns A set of modules covering the symbols provided by OrigMod.
281 std::vector<std::unique_ptr<llvm::Module>>
282 explode(const llvm::Module &OrigMod, const JITIndirections &Indirections);
283 }
284
285 #endif // LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H