62cbf291d2db18686667a261e1ed324edf0ac199
[gem5.git] / src / sim / guest_abi / dispatch.hh
1 /*
2 * Copyright 2019 Google Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met: redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer;
8 * redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution;
11 * neither the name of the copyright holders nor the names of its
12 * contributors may be used to endorse or promote products derived from
13 * this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifndef __SIM_GUEST_ABI_DISPATCH_HH__
29 #define __SIM_GUEST_ABI_DISPATCH_HH__
30
31 #include <functional>
32 #include <sstream>
33 #include <type_traits>
34
35 #include "sim/guest_abi/definition.hh"
36 #include "sim/guest_abi/layout.hh"
37
38 class ThreadContext;
39
40 namespace GuestABI
41 {
42
43 /*
44 * These functions will likely be common among all ABIs and implement the
45 * mechanism of gathering arguments, calling the target function, and then
46 * storing the result. They might need to be overridden if, for instance,
47 * the location of arguments need to be determined in a different order.
48 * For example, there might be an ABI which gathers arguments starting
49 * from the last in the list instead of the first. This is unlikely but
50 * still possible to support by redefining these functions..
51 */
52
53 // With no arguments to gather, call the target function and store the
54 // result.
55 template <typename ABI, typename Ret>
56 static typename std::enable_if<!std::is_void<Ret>::value, Ret>::type
57 callFrom(ThreadContext *tc, typename ABI::State &state,
58 std::function<Ret(ThreadContext *)> target)
59 {
60 Ret ret = target(tc);
61 storeResult<ABI, Ret>(tc, ret, state);
62 return ret;
63 }
64
65 // With no arguments to gather and nothing to return, call the target function.
66 template <typename ABI>
67 static void
68 callFrom(ThreadContext *tc, typename ABI::State &state,
69 std::function<void(ThreadContext *)> target)
70 {
71 target(tc);
72 }
73
74 // Recursively gather arguments for target from tc until we get to the base
75 // case above.
76 template <typename ABI, typename Ret, typename NextArg, typename ...Args>
77 static typename std::enable_if<!std::is_void<Ret>::value, Ret>::type
78 callFrom(ThreadContext *tc, typename ABI::State &state,
79 std::function<Ret(ThreadContext *, NextArg, Args...)> target)
80 {
81 // Extract the next argument from the thread context.
82 NextArg next = getArgument<ABI, NextArg>(tc, state);
83
84 // Build a partial function which adds the next argument to the call.
85 std::function<Ret(ThreadContext *, Args...)> partial =
86 [target,next](ThreadContext *_tc, Args... args) {
87 return target(_tc, next, args...);
88 };
89
90 // Recursively handle any remaining arguments.
91 return callFrom<ABI, Ret, Args...>(tc, state, partial);
92 }
93
94 // Recursively gather arguments for target from tc until we get to the base
95 // case above. This version is for functions that don't return anything.
96 template <typename ABI, typename NextArg, typename ...Args>
97 static void
98 callFrom(ThreadContext *tc, typename ABI::State &state,
99 std::function<void(ThreadContext *, NextArg, Args...)> target)
100 {
101 // Extract the next argument from the thread context.
102 NextArg next = getArgument<ABI, NextArg>(tc, state);
103
104 // Build a partial function which adds the next argument to the call.
105 std::function<void(ThreadContext *, Args...)> partial =
106 [target,next](ThreadContext *_tc, Args... args) {
107 target(_tc, next, args...);
108 };
109
110 // Recursively handle any remaining arguments.
111 callFrom<ABI, Args...>(tc, state, partial);
112 }
113
114
115
116 /*
117 * These functions are like the ones above, except they print the arguments
118 * a target function would be called with instead of actually calling it.
119 */
120
121 // With no arguments to print, add the closing parenthesis and return.
122 template <typename ABI, typename Ret>
123 static void
124 dumpArgsFrom(int count, std::ostream &os, ThreadContext *tc,
125 typename ABI::State &state)
126 {
127 os << ")";
128 }
129
130 // Recursively gather arguments for target from tc until we get to the base
131 // case above, and append those arguments to the string stream being
132 // constructed.
133 template <typename ABI, typename Ret, typename NextArg, typename ...Args>
134 static void
135 dumpArgsFrom(int count, std::ostream &os, ThreadContext *tc,
136 typename ABI::State &state)
137 {
138 // Either open the parenthesis or add a comma, depending on where we are
139 // in the argument list.
140 os << (count ? ", " : "(");
141
142 // Extract the next argument from the thread context.
143 NextArg next = getArgument<ABI, NextArg>(tc, state);
144
145 // Add this argument to the list.
146 os << next;
147
148 // Recursively handle any remaining arguments.
149 dumpArgsFrom<ABI, Ret, Args...>(count + 1, os, tc, state);
150 }
151
152 } // namespace GuestABI
153
154 #endif // __SIM_GUEST_ABI_DISPATCH_HH__