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                              "    return {};",
205                              "}")) # pyformat: disable
206
207  def test_get_interpreter_hook_vector_body_fp(self):
208    out = gen_intrinsics._get_interpreter_hook_vector_body(
209        "Foo", {
210            "class": "vector_16",
211            "in": ["vec", "vec"],
212            "out": ["vec"],
213            "variants": ["Float32"],
214        })
215    self.assertSequenceEqual(list(out),
216                             ("auto format = intrinsics::GetVectorFormatFP(elem_size, elem_num);",
217                              "switch (format) {",
218                              "  case intrinsics::kVectorF32x4:" ,
219                              "    return std::get<0>(intrinsics::Foo<intrinsics::Float32, 4>(arg0, arg1));",
220                              "  default:",
221                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
222                              "    return {};",
223                              "}")) # pyformat: disable
224
225
226  def test_get_interpreter_hook_vector_body_unsigned_int(self):
227    out = gen_intrinsics._get_interpreter_hook_vector_body(
228        "Foo", {
229            "class": "vector_16",
230            "in": ["vec", "vec"],
231            "out": ["vec"],
232            "variants": ["unsigned_16/32/64"],
233        })
234    self.assertSequenceEqual(list(out),
235                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, false);",
236                              "switch (format) {",
237                              "  case intrinsics::kVectorU16x8:" ,
238                              "    return std::get<0>(intrinsics::Foo<uint16_t, 8>(arg0, arg1));",
239                              "  case intrinsics::kVectorU32x4:" ,
240                              "    return std::get<0>(intrinsics::Foo<uint32_t, 4>(arg0, arg1));",
241                              "  case intrinsics::kVectorU64x2:" ,
242                              "    return std::get<0>(intrinsics::Foo<uint64_t, 2>(arg0, arg1));",
243                              "  default:",
244                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
245                              "    return {};",
246                              "}")) # pyformat: disable
247
248
249  def test_get_interpreter_hook_vector_body_signed_int(self):
250    out = gen_intrinsics._get_interpreter_hook_vector_body(
251        "Foo", {
252            "class": "vector_16",
253            "in": ["vec", "vec"],
254            "out": ["vec"],
255            "variants": ["signed_16/32"],
256        })
257    self.assertSequenceEqual(list(out),
258                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, true);",
259                              "switch (format) {",
260                              "  case intrinsics::kVectorI16x8:" ,
261                              "    return std::get<0>(intrinsics::Foo<int16_t, 8>(arg0, arg1));",
262                              "  case intrinsics::kVectorI32x4:" ,
263                              "    return std::get<0>(intrinsics::Foo<int32_t, 4>(arg0, arg1));",
264                              "  default:",
265                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
266                              "    return {};",
267                              "}")) # pyformat: disable
268
269
270  def test_get_interpreter_hook_vector_body_signed_and_unsigned_int(self):
271    out = gen_intrinsics._get_interpreter_hook_vector_body(
272        "Foo", {
273            "class": "vector_16",
274            "in": ["vec", "vec"],
275            "out": ["vec"],
276            "variants": ["signed_32", "unsigned_32"],
277        })
278    self.assertSequenceEqual(list(out),
279                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, is_signed);",
280                              "switch (format) {",
281                              "  case intrinsics::kVectorI32x4:" ,
282                              "    return std::get<0>(intrinsics::Foo<int32_t, 4>(arg0, arg1));",
283                              "  case intrinsics::kVectorU32x4:" ,
284                              "    return std::get<0>(intrinsics::Foo<uint32_t, 4>(arg0, arg1));",
285                              "  default:",
286                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
287                              "    return {};",
288                              "}")) # pyformat: disable
289
290
291  def test_get_interpreter_hook_vector_body_vector_8(self):
292    out = gen_intrinsics._get_interpreter_hook_vector_body(
293        "Foo", {
294            "class": "vector_8",
295            "in": ["vec", "vec"],
296            "out": ["vec"],
297            "variants": ["unsigned_32"],
298        })
299    self.assertSequenceEqual(list(out),
300                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, false);",
301                              "switch (format) {",
302                              "  case intrinsics::kVectorU32x2:" ,
303                              "    return std::get<0>(intrinsics::Foo<uint32_t, 2>(arg0, arg1));",
304                              "  default:",
305                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
306                              "    return {};",
307                              "}")) # pyformat: disable
308
309
310  def test_get_interpreter_hook_vector_body_single(self):
311    out = gen_intrinsics._get_interpreter_hook_vector_body(
312        "Foo", {
313            "class": "vector_8/16/single",
314            "variants": ["signed_32"],
315            "in": ["vec", "fp_flags"],
316            "out": ["vec", "fp_flags"],
317        })
318    self.assertSequenceEqual(list(out),
319                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, true);",
320                              "switch (format) {",
321                              "  case intrinsics::kVectorI32x2:" ,
322                              "    return intrinsics::Foo<int32_t, 2>(arg0, GPRRegToInteger<uint32_t>(arg1));",
323                              "  case intrinsics::kVectorI32x4:" ,
324                              "    return intrinsics::Foo<int32_t, 4>(arg0, GPRRegToInteger<uint32_t>(arg1));",
325                              "  case intrinsics::kVectorI32x1:" ,
326                              "    return intrinsics::Foo<int32_t, 1>(arg0, GPRRegToInteger<uint32_t>(arg1));",
327                              "  default:",
328                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
329                              "    return {};",
330                              "}")) # pyformat: disable
331
332
333  def test_get_translator_hook_call_expr_smoke(self):
334    out = gen_intrinsics._get_translator_hook_call_expr(
335        "Foo", {
336            "in": ["uint32_t"],
337            "out": ["uint32_t"],
338        })
339    self.assertEqual(out, "CallIntrinsic<&intrinsics::Foo, Register>(arg0)")
340
341
342  def test_get_translator_hook_call_expr_void(self):
343    out = gen_intrinsics._get_translator_hook_call_expr(
344        "Foo", {
345            "in": [],
346            "out": [],
347        })
348    self.assertEqual(out, "CallIntrinsic<&intrinsics::Foo, void>()")
349
350
351  def test_get_translator_hook_raw_vector_body(self):
352    out = gen_intrinsics._get_semantics_player_hook_raw_vector_body(
353        "Foo", {
354            "class": "vector_8/16",
355            "in": ["vec", "vec"],
356            "out": ["vec"],
357        }, gen_intrinsics._get_translator_hook_return_stmt)
358    self.assertSequenceEqual(list(out),
359                             ("switch (size) {",
360                              "  case 64:",
361                              "    return CallIntrinsic<&intrinsics::Foo<64>, SimdRegister>(arg0, arg1);",
362                              "  case 128:",
363                              "    return CallIntrinsic<&intrinsics::Foo<128>, SimdRegister>(arg0, arg1);",
364                              "  default:",
365                              "    LOG_ALWAYS_FATAL(\"Unsupported size\");",
366                              "    return {};",
367                              "}")) # pyformat: disable
368
369
370  def test_get_translator_hook_vector_body(self):
371    out = gen_intrinsics._get_semantics_player_hook_vector_body(
372        "Foo", {
373            "class": "vector_8/16/single",
374            "variants": ["signed_32"],
375            "in": ["vec", "fp_flags"],
376            "out": ["vec", "fp_flags"],
377        }, gen_intrinsics._get_translator_hook_return_stmt)
378    self.assertSequenceEqual(list(out),
379                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, true);",
380                              "switch (format) {",
381                              "  case intrinsics::kVectorI32x2:" ,
382                              "    return CallIntrinsic<&intrinsics::Foo<int32_t, 2>, std::tuple<SimdRegister, Register>>(arg0, arg1);",
383                              "  case intrinsics::kVectorI32x4:" ,
384                              "    return CallIntrinsic<&intrinsics::Foo<int32_t, 4>, std::tuple<SimdRegister, Register>>(arg0, arg1);",
385                              "  case intrinsics::kVectorI32x1:" ,
386                              "    return CallIntrinsic<&intrinsics::Foo<int32_t, 1>, std::tuple<SimdRegister, Register>>(arg0, arg1);",
387                              "  default:",
388                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
389                              "    return {};",
390                              "}")) # pyformat: disable
391
392if __name__ == "__main__":
393  unittest.main(verbosity=2)
394