gem5  v20.1.0.0
guest_abi.test.cc
Go to the documentation of this file.
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 #include <gtest/gtest.h>
29 
30 #include <type_traits>
31 #include <utility>
32 
33 #include "sim/guest_abi.hh"
34 
35 // Fake ThreadContext which holds data and captures results.
36 class ThreadContext
37 {
38  public:
39  static const int ints[];
40  static const double floats[];
41 
42  static const int DefaultIntResult;
43  static const double DefaultFloatResult;
44 
47 
48  int intOffset = 0;
49 };
50 
51 const int ThreadContext::ints[] = {
52  0, 1, 2, 3, 4, 5, 6, 7
53 };
54 const double ThreadContext::floats[] = {
55  10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0
56 };
57 
59 const double ThreadContext::DefaultFloatResult = 0.0;
60 
61 // ABI anchor for an ABI which has 1D progress. Conceptually, this could be
62 // because integer and floating point arguments are stored in the same
63 // registers.
64 struct TestABI_1D
65 {
66  using State = int;
67 };
68 
69 // ABI anchor for an ABI which uses the prepare() hook.
71 {
72  using State = int;
73 };
74 
75 // ABI anchor for an ABI which has 2D progress. Conceptually, this could be
76 // because integer and floating point arguments are stored in separate
77 // registers.
78 struct TestABI_2D
79 {
81 };
82 
84 {
85  struct State
86  {
87  int pos;
88  State(const ThreadContext *tc) : pos(tc->intOffset) {}
89  };
90 };
91 
92 namespace GuestABI
93 {
94 
95 // Hooks for the 1D ABI arguments and return value. Add 1 or 1.0 to return
96 // values so we can tell they went through the right set of hooks.
97 template <>
98 struct Argument<TestABI_1D, int>
99 {
100  static int
102  {
103  return tc->ints[state++];
104  }
105 };
106 
107 template <typename Arg>
108 struct Argument<TestABI_1D, Arg,
109  typename std::enable_if<std::is_floating_point<Arg>::value>::type>
110 {
111  static Arg
113  {
114  return tc->floats[state++];
115  }
116 };
117 
118 template <>
119 struct Result<TestABI_1D, int>
120 {
121  static void
122  store(ThreadContext *tc, const int &ret)
123  {
124  tc->intResult = ret + 1;
125  }
126 };
127 
128 template <typename Ret>
129 struct Result<TestABI_1D, Ret,
130  typename std::enable_if<std::is_floating_point<Ret>::value>::type>
131 {
132  static void
133  store(ThreadContext *tc, const Ret &ret)
134  {
135  tc->floatResult = ret + 1.0;
136  }
137 };
138 
139 // Hooks for the ABI which uses prepare(). It uses the same rules as the
140 // 1D ABI for arguments, but allocates space for and discards return values
141 // and returns integer arguments in reverse order.
142 template <>
144 {
145  static int
147  {
148  return tc->ints[--state];
149  }
150 
151  static void
153  {
154  state++;
155  }
156 };
157 
158 template <typename Ret>
160 {
161  static void store(ThreadContext *tc, const Ret &ret) {}
162  static void
164  {
165  state++;
166  }
167 };
168 
169 // Hooks for the 2D ABI arguments and return value. Add 2 or 2.0 to return
170 // values so we can tell they went through the right set of hooks.
171 
172 template <>
173 struct Argument<TestABI_2D, int>
174 {
175  static int
177  {
178  return tc->ints[state.first++];
179  }
180 };
181 
182 template <typename Arg>
183 struct Argument<TestABI_2D, Arg,
184  typename std::enable_if<std::is_floating_point<Arg>::value>::type>
185 {
186  static Arg
188  {
189  return tc->floats[state.second++];
190  }
191 };
192 
193 template <>
194 struct Result<TestABI_2D, int>
195 {
196  static void
197  store(ThreadContext *tc, const int &ret)
198  {
199  tc->intResult = ret + 2;
200  }
201 };
202 
203 template <typename Ret>
204 struct Result<TestABI_2D, Ret,
205  typename std::enable_if<std::is_floating_point<Ret>::value>::type>
206 {
207  static void
208  store(ThreadContext *tc, const Ret &ret)
209  {
210  tc->floatResult = ret + 2.0;
211  }
212 };
213 
214 // Hooks for the TcInit ABI arguments.
215 template <>
217 {
218  static int
220  {
221  return tc->ints[state.pos++];
222  }
223 };
224 
225 } // namespace GuestABI
226 
227 // Test function which verifies that its arguments reflect the 1D ABI and
228 // which doesn't return anything.
229 void
230 testIntVoid(ThreadContext *tc, int a, float b, int c, double d,
232 {
233  EXPECT_EQ(a, tc->ints[0]);
234  EXPECT_EQ(b, tc->floats[1]);
235  EXPECT_EQ(c, tc->ints[2]);
236  EXPECT_EQ(d, tc->floats[3]);
237 
238  EXPECT_EQ(varargs.get<int>(), tc->ints[4]);
239  EXPECT_EQ(varargs.get<float>(), tc->floats[5]);
240  EXPECT_EQ(varargs.get<double>(), tc->floats[6]);
241 }
242 
243 // Test functions which verify that the return allocating ABI allocates space
244 // for its return value successfully.
245 void
247 {
248  EXPECT_EQ(a, tc->ints[1]);
249  EXPECT_EQ(b, tc->ints[0]);
250 }
251 
252 int
254 {
255  EXPECT_EQ(a, tc->ints[2]);
256  EXPECT_EQ(b, tc->ints[1]);
257  return 0;
258 }
259 
260 // Test function which verifies that its arguments reflect the 2D ABI and
261 // which doesn't return anything.
262 void
263 test2DVoid(ThreadContext *tc, int a, float b, int c, double d,
265 {
266  EXPECT_EQ(a, tc->ints[0]);
267  EXPECT_EQ(b, tc->floats[0]);
268  EXPECT_EQ(c, tc->ints[1]);
269  EXPECT_EQ(d, tc->floats[1]);
270 
271  EXPECT_EQ(varargs.get<int>(), tc->ints[2]);
272  EXPECT_EQ(varargs.get<float>(), tc->floats[2]);
273  EXPECT_EQ(varargs.get<double>(), tc->floats[3]);
274 }
275 
276 void
278 {
279  EXPECT_EQ(tc->intOffset, 2);
280  EXPECT_EQ(a, tc->ints[2]);
281 }
282 
283 // Test functions which returns various types of values.
284 const int IntRetValue = 50;
285 const float FloatRetValue = 3.14;
286 const double DoubleRetValue = 12.34;
287 
291 
292 
293 // The actual test bodies.
294 TEST(GuestABI, ABI_1D_args)
295 {
296  ThreadContext tc;
297  invokeSimcall<TestABI_1D>(&tc, testIntVoid);
300 }
301 
302 TEST(GuestABI, ABI_Prepare)
303 {
304  ThreadContext tc;
305  invokeSimcall<TestABI_Prepare>(&tc, testPrepareVoid);
306  invokeSimcall<TestABI_Prepare>(&tc, testPrepareInt);
307 }
308 
309 TEST(GuestABI, ABI_2D_args)
310 {
311  ThreadContext tc;
312  invokeSimcall<TestABI_2D>(&tc, test2DVoid);
315 }
316 
317 TEST(GuestABI, ABI_TC_init)
318 {
319  ThreadContext tc;
320  tc.intOffset = 2;
321  invokeSimcall<TestABI_TcInit>(&tc, testTcInit);
322 }
323 
324 TEST(GuestABI, ABI_returns)
325 {
326  // 1D returns.
327  {
328  ThreadContext tc;
329  int ret = invokeSimcall<TestABI_1D>(&tc, testIntRet);
330  EXPECT_EQ(ret, IntRetValue);
333  }
334  {
335  ThreadContext tc;
336  float ret = invokeSimcall<TestABI_1D>(&tc, testFloatRet);
337  EXPECT_EQ(ret, FloatRetValue);
340  }
341  {
342  ThreadContext tc;
343  double ret = invokeSimcall<TestABI_1D>(&tc, testDoubleRet);
347  }
348  {
349  // Disable storing the return value in the ThreadContext.
350  ThreadContext tc;
351  int ret = invokeSimcall<TestABI_1D, false>(&tc, testIntRet);
352  EXPECT_EQ(ret, IntRetValue);
355  }
356 
357 
358  // 2D returns.
359  {
360  ThreadContext tc;
361  int ret = invokeSimcall<TestABI_2D>(&tc, testIntRet);
362  EXPECT_EQ(ret, IntRetValue);
365  }
366  {
367  ThreadContext tc;
368  float ret = invokeSimcall<TestABI_2D>(&tc, testFloatRet);
369  EXPECT_EQ(ret, FloatRetValue);
372  }
373  {
374  ThreadContext tc;
375  double ret = invokeSimcall<TestABI_2D>(&tc, testDoubleRet);
379  }
380 }
381 
383 {
384  ThreadContext tc;
385  std::string dump = dumpSimcall<TestABI_1D>("test", &tc, testIntVoid);
386  EXPECT_EQ(dump, "test(0, 11, 2, 13, ...)");
387 }
388 
389 TEST(GuestABI, isVarArgs)
390 {
394  struct FooStruct {};
396  union FooUnion {};
398 }
TestABI_2D
Definition: guest_abi.test.cc:78
GuestABI::Argument< TestABI_TcInit, int >::get
static int get(ThreadContext *tc, TestABI_TcInit::State &state)
Definition: guest_abi.test.cc:219
GuestABI::Argument< TestABI_1D, int >::get
static int get(ThreadContext *tc, TestABI_1D::State &state)
Definition: guest_abi.test.cc:101
ThreadContext::intOffset
int intOffset
Definition: guest_abi.test.cc:48
GuestABI::IsVarArgs
Definition: varargs.hh:170
GuestABI::Argument< TestABI_Prepare, int >::prepare
static void prepare(ThreadContext *tc, TestABI_Prepare::State &state)
Definition: guest_abi.test.cc:152
TestABI_TcInit
Definition: guest_abi.test.cc:83
GuestABI::Argument< TestABI_Prepare, int >::get
static int get(ThreadContext *tc, TestABI_Prepare::State &state)
Definition: guest_abi.test.cc:146
GuestABI::Result< TestABI_Prepare, Ret >::prepare
static void prepare(ThreadContext *tc, TestABI_Prepare::State &state)
Definition: guest_abi.test.cc:163
TestABI_TcInit::State::pos
int pos
Definition: guest_abi.test.cc:87
IntRetValue
const int IntRetValue
Definition: guest_abi.test.cc:284
type
uint8_t type
Definition: inet.hh:421
testFloatRet
float testFloatRet(ThreadContext *tc)
Definition: guest_abi.test.cc:289
TestABI_TcInit::State
Definition: guest_abi.test.cc:85
GuestABI::Result< TestABI_1D, int >::store
static void store(ThreadContext *tc, const int &ret)
Definition: guest_abi.test.cc:122
GuestABI::Result< TestABI_2D, int >::store
static void store(ThreadContext *tc, const int &ret)
Definition: guest_abi.test.cc:197
TEST
TEST(GuestABI, ABI_1D_args)
Definition: guest_abi.test.cc:294
ThreadContext::floatResult
double floatResult
Definition: guest_abi.test.cc:46
EXPECT_EQ
#define EXPECT_EQ(lhs, rhs)
A macro which verifies that lhs and rhs are equal to each other.
Definition: unittest.hh:110
ThreadContext::DefaultFloatResult
static const double DefaultFloatResult
Definition: guest_abi.test.cc:43
EXPECT_FALSE
#define EXPECT_FALSE(expr)
A macro which verifies that expr evaluates to false.
Definition: unittest.hh:106
GuestABI::Argument< TestABI_1D, Arg, typename std::enable_if< std::is_floating_point< Arg >::value >::type >::get
static Arg get(ThreadContext *tc, TestABI_1D::State &state)
Definition: guest_abi.test.cc:112
GuestABI::VarArgs::get
Arg get()
Definition: varargs.hh:161
testDoubleRet
double testDoubleRet(ThreadContext *tc)
Definition: guest_abi.test.cc:290
TestABI_Prepare::State
int State
Definition: guest_abi.test.cc:72
ArmISA::a
Bitfield< 8 > a
Definition: miscregs_types.hh:62
ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:88
GuestABI::VarArgs
Definition: varargs.hh:146
GuestABI
Definition: aapcs32.hh:66
testPrepareVoid
void testPrepareVoid(ThreadContext *tc, int a, int b)
Definition: guest_abi.test.cc:246
testTcInit
void testTcInit(ThreadContext *tc, int a)
Definition: guest_abi.test.cc:277
ArmISA::d
Bitfield< 9 > d
Definition: miscregs_types.hh:60
EXPECT_TRUE
#define EXPECT_TRUE(expr)
A macro which verifies that expr evaluates to true.
Definition: unittest.hh:103
testIntRet
int testIntRet(ThreadContext *tc)
Definition: guest_abi.test.cc:288
GuestABI::Argument
Definition: definition.hh:93
GuestABI::Result< TestABI_2D, Ret, typename std::enable_if< std::is_floating_point< Ret >::value >::type >::store
static void store(ThreadContext *tc, const Ret &ret)
Definition: guest_abi.test.cc:208
TestABI_1D
Definition: guest_abi.test.cc:64
GuestABI::Argument< TestABI_2D, int >::get
static int get(ThreadContext *tc, TestABI_2D::State &state)
Definition: guest_abi.test.cc:176
std::pair
STL pair class.
Definition: stl.hh:58
ThreadContext::DefaultIntResult
static const int DefaultIntResult
Definition: guest_abi.test.cc:42
test2DVoid
void test2DVoid(ThreadContext *tc, int a, float b, int c, double d, GuestABI::VarArgs< int, float, double > varargs)
Definition: guest_abi.test.cc:263
FloatRetValue
const float FloatRetValue
Definition: guest_abi.test.cc:285
testIntVoid
void testIntVoid(ThreadContext *tc, int a, float b, int c, double d, GuestABI::VarArgs< int, float, double > varargs)
Definition: guest_abi.test.cc:230
GuestABI::Result< TestABI_Prepare, Ret >::store
static void store(ThreadContext *tc, const Ret &ret)
Definition: guest_abi.test.cc:161
TestABI_1D::State
int State
Definition: guest_abi.test.cc:66
GuestABI::Result
Definition: definition.hh:58
ArmISA::b
Bitfield< 7 > b
Definition: miscregs_types.hh:376
std
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
ThreadContext::floats
static const double floats[]
Definition: guest_abi.test.cc:40
Stats::dump
void dump()
Dump all statistics data to the registered outputs.
Definition: statistics.cc:560
guest_abi.hh
TestABI_TcInit::State::State
State(const ThreadContext *tc)
Definition: guest_abi.test.cc:88
ArmISA::c
Bitfield< 29 > c
Definition: miscregs_types.hh:50
ThreadContext::intResult
int intResult
Definition: guest_abi.test.cc:45
GuestABI::Argument< TestABI_2D, Arg, typename std::enable_if< std::is_floating_point< Arg >::value >::type >::get
static Arg get(ThreadContext *tc, TestABI_2D::State &state)
Definition: guest_abi.test.cc:187
testPrepareInt
int testPrepareInt(ThreadContext *tc, int a, int b)
Definition: guest_abi.test.cc:253
GuestABI::Result< TestABI_1D, Ret, typename std::enable_if< std::is_floating_point< Ret >::value >::type >::store
static void store(ThreadContext *tc, const Ret &ret)
Definition: guest_abi.test.cc:133
DoubleRetValue
const double DoubleRetValue
Definition: guest_abi.test.cc:286
TestABI_Prepare
Definition: guest_abi.test.cc:70
dumpSimcall
std::string dumpSimcall(std::string name, ThreadContext *tc, std::function< Ret(ThreadContext *, Args...)> target=std::function< Ret(ThreadContext *, Args...)>())
Definition: guest_abi.hh:107
ThreadContext::ints
static const int ints[]
Definition: guest_abi.test.cc:39

Generated on Wed Sep 30 2020 14:02:14 for gem5 by doxygen 1.8.17