]> git.ipfire.org Git - thirdparty/gcc.git/blame - libcc1/rpc.hh
x86: Always return pseudo register in ix86_gen_scratch_sse_rtx
[thirdparty/gcc.git] / libcc1 / rpc.hh
CommitLineData
ddc8de03 1/* RPC call and callback templates
7adcbafe 2 Copyright (C) 2014-2022 Free Software Foundation, Inc.
ddc8de03
PM
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
19
20#ifndef CC1_PLUGIN_RPC_HH
21#define CC1_PLUGIN_RPC_HH
22
23#include "status.hh"
ddc8de03 24#include "connection.hh"
0f237df2 25#include "deleter.hh"
ddc8de03
PM
26
27namespace cc1_plugin
28{
29 // The plugin API may contain some "const" method parameters.
30 // However, when unmarshalling we cannot unmarshall into a const
31 // object; and furthermore we want to be able to deallocate pointers
32 // when finished with them. This wrapper class lets us properly
33 // remove the "const" and handle deallocation from pointer types.
34
35 template<typename T>
36 class argument_wrapper
37 {
38 public:
39
40 argument_wrapper () { }
41 ~argument_wrapper () { }
42
c10a3b13
TT
43 argument_wrapper (const argument_wrapper &) = delete;
44 argument_wrapper &operator= (const argument_wrapper &) = delete;
45
8fdffa48 46 T get () const { return m_object; }
ddc8de03
PM
47
48 status unmarshall (connection *conn)
49 {
50 return ::cc1_plugin::unmarshall (conn, &m_object);
51 }
52
53 private:
54
55 T m_object;
ddc8de03
PM
56 };
57
0d5a0b9a
TT
58 // Specialization for any kind of pointer.
59 template<typename T>
60 class argument_wrapper<T *>
8db29d88
AO
61 {
62 public:
0d5a0b9a
TT
63 argument_wrapper () = default;
64 ~argument_wrapper () = default;
8db29d88 65
c10a3b13
TT
66 argument_wrapper (const argument_wrapper &) = delete;
67 argument_wrapper &operator= (const argument_wrapper &) = delete;
68
0d5a0b9a
TT
69 typedef typename std::remove_const<T>::type type;
70
8fdffa48 71 const type *get () const
8db29d88 72 {
0d5a0b9a 73 return m_object.get ();
8db29d88
AO
74 }
75
76 status unmarshall (connection *conn)
77 {
0d5a0b9a
TT
78 type *ptr;
79 if (!::cc1_plugin::unmarshall (conn, &ptr))
80 return FAIL;
81 m_object.reset (ptr);
82 return OK;
8db29d88
AO
83 }
84
85 private:
86
0f237df2 87 unique_ptr<type> m_object;
8db29d88 88 };
8db29d88 89
ddc8de03 90 // There are two kinds of template functions here: "call" and
8fdffa48 91 // "invoker".
ddc8de03
PM
92
93 // The "call" template is used for making a remote procedure call.
94 // It starts a query ('Q') packet, marshalls its arguments, waits
95 // for a result, and finally reads and returns the result via an
96 // "out" parameter.
97
8fdffa48 98 // The "invoker" template is used when receiving a remote procedure
ddc8de03
PM
99 // call. This template function is suitable for use with the
100 // "callbacks" and "connection" classes. It decodes incoming
101 // arguments, passes them to the wrapped function, and finally
102 // marshalls a reply packet.
103
dc6be7c0 104 template<typename R, typename... Arg>
ddc8de03 105 status
dc6be7c0 106 call (connection *conn, const char *method, R *result, Arg... args)
ddc8de03
PM
107 {
108 if (!conn->send ('Q'))
109 return FAIL;
110 if (!marshall (conn, method))
111 return FAIL;
dc6be7c0
TT
112 if (!marshall (conn, (int) sizeof... (Arg)))
113 return FAIL;
114 if (!marshall (conn, args...))
ddc8de03
PM
115 return FAIL;
116 if (!conn->wait_for_result ())
117 return FAIL;
118 if (!unmarshall (conn, result))
119 return FAIL;
120 return OK;
121 }
122
8fdffa48
TT
123 // The base case -- just return OK.
124 template<int I, typename... T>
125 typename std::enable_if<I == sizeof... (T), status>::type
126 unmarshall (connection *, std::tuple<T...> &)
ddc8de03 127 {
8fdffa48 128 return OK;
ddc8de03
PM
129 }
130
8fdffa48
TT
131 // Unmarshall this argument, then unmarshall all subsequent args.
132 template<int I, typename... T>
133 typename std::enable_if<I < sizeof... (T), status>::type
134 unmarshall (connection *conn, std::tuple<T...> &value)
ddc8de03 135 {
8fdffa48 136 if (!std::get<I> (value).unmarshall (conn))
ddc8de03 137 return FAIL;
8fdffa48 138 return unmarshall<I + 1, T...> (conn, value);
ddc8de03
PM
139 }
140
8fdffa48
TT
141 // Wrap a static function that is suitable for use as a callback.
142 // This is a template function inside a template class to work
143 // around limitations with multiple variadic packs.
144 template<typename R, typename... Arg>
145 class invoker
ddc8de03 146 {
8fdffa48
TT
147 // Base case -- we can call the function.
148 template<int I, R func (connection *, Arg...), typename... T>
149 static typename std::enable_if<I == sizeof... (Arg), R>::type
150 call (connection *conn, const std::tuple<argument_wrapper<Arg>...> &,
151 T... args)
152 {
153 return func (conn, args...);
154 }
ddc8de03 155
8fdffa48
TT
156 // Unpack one argument and continue the recursion.
157 template<int I, R func (connection *, Arg...), typename... T>
158 static typename std::enable_if<I < sizeof... (Arg), R>::type
159 call (connection *conn, const std::tuple<argument_wrapper<Arg>...> &value,
160 T... args)
161 {
162 return call<I + 1, func> (conn, value, args...,
163 std::get<I> (value).get ());
164 }
ddc8de03 165
8fdffa48 166 public:
ddc8de03 167
8fdffa48
TT
168 // A callback function that reads arguments from the connection,
169 // calls the wrapped function, and then sends the result back on
170 // the connection.
171 template<R func (connection *, Arg...)>
172 static status
173 invoke (connection *conn)
174 {
175 if (!unmarshall_check (conn, sizeof... (Arg)))
176 return FAIL;
177 std::tuple<argument_wrapper<Arg>...> wrapped;
178 if (!unmarshall<0> (conn, wrapped))
179 return FAIL;
ddc8de03 180
8fdffa48 181 R result = call<0, func> (conn, wrapped);
ddc8de03 182
8fdffa48
TT
183 if (!conn->send ('R'))
184 return FAIL;
185 return marshall (conn, result);
186 }
187 };
ddc8de03
PM
188};
189
190#endif // CC1_PLUGIN_RPC_HH