1#!/usr/bin/python
2#
3# Copyright (C) 2015 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18import sys
19import unittest
20
21import gen_intrinsics
22
23
24class GenIntrinsicsTests(unittest.TestCase):
25
26  def test_get_semantics_player_hook_proto_smoke(self):
27    out = gen_intrinsics._get_semantics_player_hook_proto("Foo", {
28        "in": ["uint32_t"],
29        "out": []
30    })
31    self.assertEqual(out, "void Foo(Register arg0)")
32
33  def test_get_semantics_player_hook_proto_template_types(self):
34    intr = {
35        "Foo": {
36            "in": ["uint32_t", "uint8_t", "Type0", "Type1", "vec", "uimm8"],
37            "out": ["uint32_t"],
38            "class": "template",
39            "variants": ["Float32, int32", "Float64, int64"]
40        }}
41    gen_intrinsics._gen_semantic_player_types(intr.items())
42    out = gen_intrinsics._get_semantics_player_hook_proto("Foo", intr["Foo"])
43    self.assertEqual(out,
44                     "template<typename Type0, typename Type1>\n"
45                     "Register Foo(Register arg0, "
46                                  "Register arg1, "
47                                  "FpRegister arg2, "
48                                  "Register arg3, "
49                                  "SimdRegister arg4, "
50                                  "uint8_t arg5)" ) # pyformat: disable
51
52  def test_get_semantics_player_hook_proto_operand_types(self):
53    out = gen_intrinsics._get_semantics_player_hook_proto(
54        "Foo", {
55            "in": ["uint32_t", "uint8_t", "Float32", "Float64", "vec", "uimm8"],
56            "out": ["uint32_t"]
57        })
58    self.assertEqual(out,
59                     "Register Foo(Register arg0, "
60                                  "Register arg1, "
61                                  "SimdRegister arg2, "
62                                  "SimdRegister arg3, "
63                                  "SimdRegister arg4, "
64                                  "uint8_t arg5)" ) # pyformat: disable
65
66  def test_get_semantics_player_hook_proto_multiple_results(self):
67    out = gen_intrinsics._get_semantics_player_hook_proto("Foo", {
68        "in": ["uint32_t"],
69        "out": ["vec", "uint32_t"]
70    })
71    self.assertEqual(out,
72                     "std::tuple<SimdRegister, Register> Foo(Register arg0)")
73
74  def test_get_interpreter_hook_call_expr_smoke(self):
75    out = gen_intrinsics._get_interpreter_hook_call_expr(
76        "Foo", {
77            "in": ["uint32_t"],
78            "out": []
79        })
80    self.assertEqual(out, "intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0))")
81
82  def test_get_interpreter_hook_call_expr_template_types(self):
83    intr = {
84        "Foo": {
85            "in": ["uint32_t", "uint8_t", "Type0", "Type1", "vec", "uimm8"],
86            "out": ["uint32_t"],
87            "class": "template",
88            "variants": ["Float32, int32", "Float64, int64"]
89        }}
90    gen_intrinsics._gen_semantic_player_types(intr.items())
91    out = gen_intrinsics._get_interpreter_hook_call_expr("Foo", intr["Foo"])
92    self.assertEqual(
93        out,
94        "IntegerToGPRReg(std::get<0>(intrinsics::Foo<Type0, Type1>("
95            "GPRRegToInteger<uint32_t>(arg0), "
96            "GPRRegToInteger<uint8_t>(arg1), "
97            "FPRegToFloat<Type0>(arg2), "
98            "GPRRegToInteger<Type1>(arg3), "
99            "arg4, "
100            "GPRRegToInteger<uint8_t>(arg5))))" ) # pyforman: disable
101
102  def test_get_interpreter_hook_call_expr_operand_types(self):
103    out = gen_intrinsics._get_interpreter_hook_call_expr(
104        "Foo", {
105            "in": ["uint32_t", "uint8_t", "Float32", "Float64", "vec", "uimm8"],
106            "out": []
107        })
108    self.assertEqual(out,
109                     "intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0), "
110                                     "GPRRegToInteger<uint8_t>(arg1), "
111                                     "FPRegToFloat<intrinsics::Float32>(arg2), "
112                                     "FPRegToFloat<intrinsics::Float64>(arg3), "
113                                     "arg4, "
114                                     "GPRRegToInteger<uint8_t>(arg5))" ) # pyforman: disable
115
116  def test_get_interpreter_hook_call_expr_single_result(self):
117    out = gen_intrinsics._get_interpreter_hook_call_expr(
118        "Foo", {
119            "in": ["uint32_t"],
120            "out": ["uint32_t"]
121        })
122    self.assertEqual(out, "std::get<0>(intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0)))")
123
124  def test_get_interpreter_hook_call_expr_multiple_result(self):
125    out = gen_intrinsics._get_interpreter_hook_call_expr(
126        "Foo", {
127            "in": ["uint32_t"],
128            "out": ["vec", "uint32_t"]
129        })
130    self.assertEqual(out, "intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0))")
131
132  def test_get_interpreter_hook_call_expr_float32_result(self):
133    out = gen_intrinsics._get_interpreter_hook_call_expr(
134        "Foo", {
135            "in": ["uint32_t"],
136            "out": ["Float32"]
137        })
138    self.assertEqual(out, "FloatToFPReg(std::get<0>(intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0))))")
139
140  def test_get_interpreter_hook_call_expr_float64_result(self):
141    out = gen_intrinsics._get_interpreter_hook_call_expr(
142        "Foo", {
143            "in": ["uint32_t"],
144            "out": ["Float64"]
145        })
146    self.assertEqual(out, "FloatToFPReg(std::get<0>(intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0))))")
147
148  def test_get_interpreter_hook_call_expr_precise_nan(self):
149    out = gen_intrinsics._get_interpreter_hook_call_expr(
150        "Foo", {
151            "in": ["uint32_t"],
152            "out": [],
153            "precise_nans": True,
154        })
155    self.assertEqual(
156        out, "intrinsics::Foo<config::kPreciseNaNOperationsHandling>("
157             "GPRRegToInteger<uint32_t>(arg0))")
158
159  def test_gen_interpreter_hook_return_stmt(self):
160    out = gen_intrinsics._get_interpreter_hook_return_stmt(
161        "Foo", {
162            "in": ["uint32_t"],
163            "out": ["uint32_t"]
164        })
165    self.assertEqual(out, "return std::get<0>(intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0)));")
166
167  def test_gen_interpreter_hook_return_stmt_void(self):
168    out = gen_intrinsics._get_interpreter_hook_return_stmt(
169        "Foo", {
170            "in": ["uint32_t"],
171            "out": []
172        })
173    self.assertEqual(out, "return intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0));")
174
175
176  def test_get_semantics_player_hook_proto_raw_variant(self):
177    out = gen_intrinsics._get_semantics_player_hook_proto(
178        "Foo", {
179            "class": "vector_8/16",
180            "in": ["vec", "vec"],
181            "out": ["vec"],
182            "variants": ["raw"],
183        })
184    self.assertEqual(out, "SimdRegister Foo(uint8_t size, "
185                                           "SimdRegister arg0, "
186                                           "SimdRegister arg1)") # pyformat: disable
187
188
189  def test_get_interpreter_hook_raw_vector_body(self):
190    out = gen_intrinsics._get_semantics_player_hook_raw_vector_body(
191        "Foo", {
192            "class": "vector_8/16",
193            "in": ["vec", "vec"],
194            "out": ["vec"],
195        }, gen_intrinsics._get_interpreter_hook_return_stmt)
196    self.assertSequenceEqual(list(out),
197                             ("switch (size) {",
198                              "  case 64:" ,
199                              "    return std::get<0>(intrinsics::Foo<64>(arg0, arg1));",
200                              "  case 128:",
201                              "    return std::get<0>(intrinsics::Foo<128>(arg0, arg1));",
202                              "  default:",
203                              "    LOG_ALWAYS_FATAL(\"Unsupported size\");",
204                              "}")) # pyformat: disable
205
206  def test_get_interpreter_hook_vector_body_fp(self):
207    out = gen_intrinsics._get_interpreter_hook_vector_body(
208        "Foo", {
209            "class": "vector_16",
210            "in": ["vec", "vec"],
211            "out": ["vec"],
212            "variants": ["Float32"],
213        })
214    self.assertSequenceEqual(list(out),
215                             ("auto format = intrinsics::GetVectorFormatFP(elem_size, elem_num);",
216                              "switch (format) {",
217                              "  case intrinsics::kVectorF32x4:" ,
218                              "    return std::get<0>(intrinsics::Foo<intrinsics::Float32, 4>(arg0, arg1));",
219                              "  default:",
220                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
221                              "}")) # pyformat: disable
222
223
224  def test_get_interpreter_hook_vector_body_unsigned_int(self):
225    out = gen_intrinsics._get_interpreter_hook_vector_body(
226        "Foo", {
227            "class": "vector_16",
228            "in": ["vec", "vec"],
229            "out": ["vec"],
230            "variants": ["unsigned_16/32/64"],
231        })
232    self.assertSequenceEqual(list(out),
233                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, false);",
234                              "switch (format) {",
235                              "  case intrinsics::kVectorU16x8:" ,
236                              "    return std::get<0>(intrinsics::Foo<uint16_t, 8>(arg0, arg1));",
237                              "  case intrinsics::kVectorU32x4:" ,
238                              "    return std::get<0>(intrinsics::Foo<uint32_t, 4>(arg0, arg1));",
239                              "  case intrinsics::kVectorU64x2:" ,
240                              "    return std::get<0>(intrinsics::Foo<uint64_t, 2>(arg0, arg1));",
241                              "  default:",
242                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
243                              "}")) # pyformat: disable
244
245
246  def test_get_interpreter_hook_vector_body_signed_int(self):
247    out = gen_intrinsics._get_interpreter_hook_vector_body(
248        "Foo", {
249            "class": "vector_16",
250            "in": ["vec", "vec"],
251            "out": ["vec"],
252            "variants": ["signed_16/32"],
253        })
254    self.assertSequenceEqual(list(out),
255                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, true);",
256                              "switch (format) {",
257                              "  case intrinsics::kVectorI16x8:" ,
258                              "    return std::get<0>(intrinsics::Foo<int16_t, 8>(arg0, arg1));",
259                              "  case intrinsics::kVectorI32x4:" ,
260                              "    return std::get<0>(intrinsics::Foo<int32_t, 4>(arg0, arg1));",
261                              "  default:",
262                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
263                              "}")) # pyformat: disable
264
265
266  def test_get_interpreter_hook_vector_body_signed_and_unsigned_int(self):
267    out = gen_intrinsics._get_interpreter_hook_vector_body(
268        "Foo", {
269            "class": "vector_16",
270            "in": ["vec", "vec"],
271            "out": ["vec"],
272            "variants": ["signed_32", "unsigned_32"],
273        })
274    self.assertSequenceEqual(list(out),
275                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, is_signed);",
276                              "switch (format) {",
277                              "  case intrinsics::kVectorI32x4:" ,
278                              "    return std::get<0>(intrinsics::Foo<int32_t, 4>(arg0, arg1));",
279                              "  case intrinsics::kVectorU32x4:" ,
280                              "    return std::get<0>(intrinsics::Foo<uint32_t, 4>(arg0, arg1));",
281                              "  default:",
282                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
283                              "}")) # pyformat: disable
284
285
286  def test_get_interpreter_hook_vector_body_vector_8(self):
287    out = gen_intrinsics._get_interpreter_hook_vector_body(
288        "Foo", {
289            "class": "vector_8",
290            "in": ["vec", "vec"],
291            "out": ["vec"],
292            "variants": ["unsigned_32"],
293        })
294    self.assertSequenceEqual(list(out),
295                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, false);",
296                              "switch (format) {",
297                              "  case intrinsics::kVectorU32x2:" ,
298                              "    return std::get<0>(intrinsics::Foo<uint32_t, 2>(arg0, arg1));",
299                              "  default:",
300                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
301                              "}")) # pyformat: disable
302
303
304  def test_get_interpreter_hook_vector_body_single(self):
305    out = gen_intrinsics._get_interpreter_hook_vector_body(
306        "Foo", {
307            "class": "vector_8/16/single",
308            "variants": ["signed_32"],
309            "in": ["vec", "fp_flags"],
310            "out": ["vec", "fp_flags"],
311        })
312    self.assertSequenceEqual(list(out),
313                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, true);",
314                              "switch (format) {",
315                              "  case intrinsics::kVectorI32x2:" ,
316                              "    return intrinsics::Foo<int32_t, 2>(arg0, GPRRegToInteger<uint32_t>(arg1));",
317                              "  case intrinsics::kVectorI32x4:" ,
318                              "    return intrinsics::Foo<int32_t, 4>(arg0, GPRRegToInteger<uint32_t>(arg1));",
319                              "  case intrinsics::kVectorI32x1:" ,
320                              "    return intrinsics::Foo<int32_t, 1>(arg0, GPRRegToInteger<uint32_t>(arg1));",
321                              "  default:",
322                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
323                              "}")) # pyformat: disable
324
325
326  def test_get_translator_hook_call_expr_smoke(self):
327    out = gen_intrinsics._get_translator_hook_call_expr(
328        "Foo", {
329            "in": ["uint32_t"],
330            "out": ["uint32_t"],
331        })
332    self.assertEqual(out, "CallIntrinsic<&intrinsics::Foo, Register>(arg0)")
333
334
335  def test_get_translator_hook_call_expr_void(self):
336    out = gen_intrinsics._get_translator_hook_call_expr(
337        "Foo", {
338            "in": [],
339            "out": [],
340        })
341    self.assertEqual(out, "CallIntrinsic<&intrinsics::Foo, void>()")
342
343
344  def test_get_translator_hook_raw_vector_body(self):
345    out = gen_intrinsics._get_semantics_player_hook_raw_vector_body(
346        "Foo", {
347            "class": "vector_8/16",
348            "in": ["vec", "vec"],
349            "out": ["vec"],
350        }, gen_intrinsics._get_translator_hook_return_stmt)
351    self.assertSequenceEqual(list(out),
352                             ("switch (size) {",
353                              "  case 64:",
354                              "    return CallIntrinsic<&intrinsics::Foo<64>, SimdRegister>(arg0, arg1);",
355                              "  case 128:",
356                              "    return CallIntrinsic<&intrinsics::Foo<128>, SimdRegister>(arg0, arg1);",
357                              "  default:",
358                              "    LOG_ALWAYS_FATAL(\"Unsupported size\");",
359                              "}")) # pyformat: disable
360
361
362  def test_get_translator_hook_vector_body(self):
363    out = gen_intrinsics._get_semantics_player_hook_vector_body(
364        "Foo", {
365            "class": "vector_8/16/single",
366            "variants": ["signed_32"],
367            "in": ["vec", "fp_flags"],
368            "out": ["vec", "fp_flags"],
369        }, gen_intrinsics._get_translator_hook_return_stmt)
370    self.assertSequenceEqual(list(out),
371                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, true);",
372                              "switch (format) {",
373                              "  case intrinsics::kVectorI32x2:" ,
374                              "    return CallIntrinsic<&intrinsics::Foo<int32_t, 2>, std::tuple<SimdRegister, Register>>(arg0, arg1);",
375                              "  case intrinsics::kVectorI32x4:" ,
376                              "    return CallIntrinsic<&intrinsics::Foo<int32_t, 4>, std::tuple<SimdRegister, Register>>(arg0, arg1);",
377                              "  case intrinsics::kVectorI32x1:" ,
378                              "    return CallIntrinsic<&intrinsics::Foo<int32_t, 1>, std::tuple<SimdRegister, Register>>(arg0, arg1);",
379                              "  default:",
380                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
381                              "}")) # pyformat: disable
382
383if __name__ == "__main__":
384  unittest.main(verbosity=2)
385