Taints the non-acquire RMW's store address with the load part
[oota-llvm.git] / include / llvm / ExecutionEngine / Orc / RPCUtils.h
1 //===----- RPCUTils.h - Basic tilities for building RPC APIs ----*- 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 // Basic utilities for building RPC APIs.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H
15 #define LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H
16
17 #include "llvm/ADT/STLExtras.h"
18
19 namespace llvm {
20 namespace orc {
21 namespace remote {
22
23 // Base class containing utilities that require partial specialization.
24 // These cannot be included in RPC, as template class members cannot be
25 // partially specialized.
26 class RPCBase {
27 protected:
28   template <typename ProcedureIdT, ProcedureIdT ProcId, typename... Ts>
29   class ProcedureHelper {
30   public:
31     static const ProcedureIdT Id = ProcId;
32   };
33
34   template <typename ChannelT, typename Proc> class CallHelper;
35
36   template <typename ChannelT, typename ProcedureIdT, ProcedureIdT ProcId,
37             typename... ArgTs>
38   class CallHelper<ChannelT, ProcedureHelper<ProcedureIdT, ProcId, ArgTs...>> {
39   public:
40     static std::error_code call(ChannelT &C, const ArgTs &... Args) {
41       if (auto EC = serialize(C, ProcId))
42         return EC;
43       // If you see a compile-error on this line you're probably calling a
44       // function with the wrong signature.
45       return serialize_seq(C, Args...);
46     }
47   };
48
49   template <typename ChannelT, typename Proc> class HandlerHelper;
50
51   template <typename ChannelT, typename ProcedureIdT, ProcedureIdT ProcId,
52             typename... ArgTs>
53   class HandlerHelper<ChannelT,
54                       ProcedureHelper<ProcedureIdT, ProcId, ArgTs...>> {
55   public:
56     template <typename HandlerT>
57     static std::error_code handle(ChannelT &C, HandlerT Handler) {
58       return readAndHandle(C, Handler, llvm::index_sequence_for<ArgTs...>());
59     }
60
61   private:
62     template <typename HandlerT, size_t... Is>
63     static std::error_code readAndHandle(ChannelT &C, HandlerT Handler,
64                                          llvm::index_sequence<Is...> _) {
65       std::tuple<ArgTs...> RPCArgs;
66       if (auto EC = deserialize_seq(C, std::get<Is>(RPCArgs)...))
67         return EC;
68       return Handler(std::get<Is>(RPCArgs)...);
69     }
70   };
71
72   template <typename ClassT, typename... ArgTs> class MemberFnWrapper {
73   public:
74     typedef std::error_code (ClassT::*MethodT)(ArgTs...);
75     MemberFnWrapper(ClassT &Instance, MethodT Method)
76         : Instance(Instance), Method(Method) {}
77     std::error_code operator()(ArgTs &... Args) {
78       return (Instance.*Method)(Args...);
79     }
80
81   private:
82     ClassT &Instance;
83     MethodT Method;
84   };
85
86   template <typename... ArgTs> class ReadArgs {
87   public:
88     std::error_code operator()() { return std::error_code(); }
89   };
90
91   template <typename ArgT, typename... ArgTs>
92   class ReadArgs<ArgT, ArgTs...> : public ReadArgs<ArgTs...> {
93   public:
94     ReadArgs(ArgT &Arg, ArgTs &... Args)
95         : ReadArgs<ArgTs...>(Args...), Arg(Arg) {}
96
97     std::error_code operator()(ArgT &ArgVal, ArgTs &... ArgVals) {
98       this->Arg = std::move(ArgVal);
99       return ReadArgs<ArgTs...>::operator()(ArgVals...);
100     }
101
102   private:
103     ArgT &Arg;
104   };
105 };
106
107 /// Contains primitive utilities for defining, calling and handling calls to
108 /// remote procedures. ChannelT is a bidirectional stream conforming to the
109 /// RPCChannel interface (see RPCChannel.h), and ProcedureIdT is a procedure
110 /// identifier type that must be serializable on ChannelT.
111 ///
112 /// These utilities support the construction of very primitive RPC utilities.
113 /// Their intent is to ensure correct serialization and deserialization of
114 /// procedure arguments, and to keep the client and server's view of the API in
115 /// sync.
116 ///
117 /// These utilities do not support return values. These can be handled by
118 /// declaring a corresponding '.*Response' procedure and expecting it after a
119 /// call). They also do not support versioning: the client and server *must* be
120 /// compiled with the same procedure definitions.
121 ///
122 ///
123 ///
124 /// Overview (see comments individual types/methods for details):
125 ///
126 /// Procedure<Id, Args...> :
127 ///
128 ///   associates a unique serializable id with an argument list.
129 ///
130 ///
131 /// call<Proc>(Channel, Args...) :
132 ///
133 ///   Calls the remote procedure 'Proc' by serializing Proc's id followed by its
134 /// arguments and sending the resulting bytes to 'Channel'.
135 ///
136 ///
137 /// handle<Proc>(Channel, <functor matching std::error_code(Args...)> :
138 ///
139 ///   Handles a call to 'Proc' by deserializing its arguments and calling the
140 /// given functor. This assumes that the id for 'Proc' has already been
141 /// deserialized.
142 ///
143 /// expect<Proc>(Channel, <functor matching std::error_code(Args...)> :
144 ///
145 ///   The same as 'handle', except that the procedure id should not have been
146 /// read yet. Expect will deserialize the id and assert that it matches Proc's
147 /// id. If it does not, and unexpected RPC call error is returned.
148
149 template <typename ChannelT, typename ProcedureIdT = uint32_t>
150 class RPC : public RPCBase {
151 public:
152   /// Utility class for defining/referring to RPC procedures.
153   ///
154   /// Typedefs of this utility are used when calling/handling remote procedures.
155   ///
156   /// ProcId should be a unique value of ProcedureIdT (i.e. not used with any
157   /// other Procedure typedef in the RPC API being defined.
158   ///
159   /// the template argument Ts... gives the argument list for the remote
160   /// procedure.
161   ///
162   /// E.g.
163   ///
164   ///   typedef Procedure<0, bool> Proc1;
165   ///   typedef Procedure<1, std::string, std::vector<int>> Proc2;
166   ///
167   ///   if (auto EC = call<Proc1>(Channel, true))
168   ///     /* handle EC */;
169   ///
170   ///   if (auto EC = expect<Proc2>(Channel,
171   ///         [](std::string &S, std::vector<int> &V) {
172   ///           // Stuff.
173   ///           return std::error_code();
174   ///         })
175   ///     /* handle EC */;
176   ///
177   template <ProcedureIdT ProcId, typename... Ts>
178   using Procedure = ProcedureHelper<ProcedureIdT, ProcId, Ts...>;
179
180   /// Serialize Args... to channel C, but do not call C.send().
181   ///
182   /// For buffered channels, this can be used to queue up several calls before
183   /// flushing the channel.
184   template <typename Proc, typename... ArgTs>
185   static std::error_code appendCall(ChannelT &C, const ArgTs &... Args) {
186     return CallHelper<ChannelT, Proc>::call(C, Args...);
187   }
188
189   /// Serialize Args... to channel C and call C.send().
190   template <typename Proc, typename... ArgTs>
191   static std::error_code call(ChannelT &C, const ArgTs &... Args) {
192     if (auto EC = appendCall<Proc>(C, Args...))
193       return EC;
194     return C.send();
195   }
196
197   /// Deserialize and return an enum whose underlying type is ProcedureIdT.
198   static std::error_code getNextProcId(ChannelT &C, ProcedureIdT &Id) {
199     return deserialize(C, Id);
200   }
201
202   /// Deserialize args for Proc from C and call Handler. The signature of
203   /// handler must conform to 'std::error_code(Args...)' where Args... matches
204   /// the arguments used in the Proc typedef.
205   template <typename Proc, typename HandlerT>
206   static std::error_code handle(ChannelT &C, HandlerT Handler) {
207     return HandlerHelper<ChannelT, Proc>::handle(C, Handler);
208   }
209
210   /// Helper version of 'handle' for calling member functions.
211   template <typename Proc, typename ClassT, typename... ArgTs>
212   static std::error_code
213   handle(ChannelT &C, ClassT &Instance,
214          std::error_code (ClassT::*HandlerMethod)(ArgTs...)) {
215     return handle<Proc>(
216         C, MemberFnWrapper<ClassT, ArgTs...>(Instance, HandlerMethod));
217   }
218
219   /// Deserialize a ProcedureIdT from C and verify it matches the id for Proc.
220   /// If the id does match, deserialize the arguments and call the handler
221   /// (similarly to handle).
222   /// If the id does not match, return an unexpect RPC call error and do not
223   /// deserialize any further bytes.
224   template <typename Proc, typename HandlerT>
225   static std::error_code expect(ChannelT &C, HandlerT Handler) {
226     ProcedureIdT ProcId;
227     if (auto EC = getNextProcId(C, ProcId))
228       return EC;
229     if (ProcId != Proc::Id)
230       return orcError(OrcErrorCode::UnexpectedRPCCall);
231     return handle<Proc>(C, Handler);
232   }
233
234   /// Helper version of expect for calling member functions.
235   template <typename Proc, typename ClassT, typename... ArgTs>
236   static std::error_code
237   expect(ChannelT &C, ClassT &Instance,
238          std::error_code (ClassT::*HandlerMethod)(ArgTs...)) {
239     return expect<Proc>(
240         C, MemberFnWrapper<ClassT, ArgTs...>(Instance, HandlerMethod));
241   }
242
243   /// Helper for handling setter procedures - this method returns a functor that
244   /// sets the variables referred to by Args... to values deserialized from the
245   /// channel.
246   /// E.g.
247   ///
248   ///   typedef Procedure<0, bool, int> Proc1;
249   ///
250   ///   ...
251   ///   bool B;
252   ///   int I;
253   ///   if (auto EC = expect<Proc1>(Channel, readArgs(B, I)))
254   ///     /* Handle Args */ ;
255   ///
256   template <typename... ArgTs>
257   static ReadArgs<ArgTs...> readArgs(ArgTs &... Args) {
258     return ReadArgs<ArgTs...>(Args...);
259   }
260 };
261
262 } // end namespace remote
263 } // end namespace orc
264 } // end namespace llvm
265
266 #endif