• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 io
19import sys
20import unittest
21
22import gen_intrinsics
23
24
25class GenIntrinsicsTests(unittest.TestCase):
26
27  def test_get_semantics_player_hook_proto_smoke(self):
28    out = gen_intrinsics._get_semantics_player_hook_proto("Foo", {
29        "in": ["uint32_t"],
30        "out": []
31    })
32    self.assertEqual(out, "void Foo(Register arg0)")
33
34  def test_get_semantics_player_hook_proto_template_types(self):
35    intr = {
36        "Foo": {
37            "in": ["uint32_t", "uint8_t", "Type0", "Type1", "vec", "uimm8"],
38            "out": ["uint32_t"],
39            "class": "template",
40            "variants": ["Float32, int32", "Float64, int64"]
41        }}
42    gen_intrinsics._gen_semantic_player_types(intr.items())
43    out = gen_intrinsics._get_semantics_player_hook_proto("Foo", intr["Foo"])
44    self.assertEqual(out,
45                     "template<typename Type0, typename Type1>\n"
46                     "Register Foo(Register arg0, "
47                                  "Register arg1, "
48                                  "FpRegister arg2, "
49                                  "Register arg3, "
50                                  "SimdRegister arg4, "
51                                  "uint8_t arg5)" ) # pyformat: disable
52    out = gen_intrinsics._get_semantics_player_hook_proto("Foo", intr["Foo"], use_type_id=True)
53    self.assertEqual(out,
54                     "template<intrinsics::TemplateTypeId Type0, intrinsics::TemplateTypeId Type1>\n"
55                     "Register Foo(Register arg0, "
56                                  "Register arg1, "
57                                  "FpRegister arg2, "
58                                  "Register arg3, "
59                                  "SimdRegister arg4, "
60                                  "uint8_t arg5, "
61                                  "intrinsics::Value<Type0>, "
62                                  "intrinsics::Value<Type1>)" ) # pyformat: disable
63
64  def test_get_semantics_player_hook_proto_operand_types(self):
65    out = gen_intrinsics._get_semantics_player_hook_proto(
66        "Foo", {
67            "in": ["uint32_t", "uint8_t", "Float32", "Float64", "vec", "uimm8"],
68            "out": ["uint32_t"]
69        })
70    self.assertEqual(out,
71                     "Register Foo(Register arg0, "
72                                  "Register arg1, "
73                                  "SimdRegister arg2, "
74                                  "SimdRegister arg3, "
75                                  "SimdRegister arg4, "
76                                  "uint8_t arg5)" ) # pyformat: disable
77
78  def test_get_semantics_player_hook_proto_multiple_results(self):
79    out = gen_intrinsics._get_semantics_player_hook_proto("Foo", {
80        "in": ["uint32_t"],
81        "out": ["vec", "uint32_t"]
82    })
83    self.assertEqual(out,
84                     "std::tuple<SimdRegister, Register> Foo(Register arg0)")
85
86  def test_get_interpreter_hook_call_expr_smoke(self):
87    out = gen_intrinsics._get_interpreter_hook_call_expr(
88        "Foo", {
89            "in": ["uint32_t"],
90            "out": []
91        })
92    self.assertEqual(out, "intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0))")
93
94  def test_get_interpreter_hook_call_expr_template_types(self):
95    intr = {
96        "Foo": {
97            "in": ["uint32_t", "uint8_t", "Type0", "Type1", "vec", "uimm8"],
98            "out": ["uint32_t"],
99            "class": "template",
100            "variants": ["Float32, int32", "Float64, int64"]
101        }}
102    gen_intrinsics._gen_semantic_player_types(intr.items())
103    out = gen_intrinsics._get_interpreter_hook_call_expr("Foo", intr["Foo"])
104    self.assertEqual(
105        out,
106        "IntegerToGPRReg(std::get<0>(intrinsics::Foo<Type0, Type1>("
107            "GPRRegToInteger<uint32_t>(arg0), "
108            "GPRRegToInteger<uint8_t>(arg1), "
109            "FPRegToFloat<Type0>(arg2), "
110            "GPRRegToInteger<Type1>(arg3), "
111            "arg4, "
112            "GPRRegToInteger<uint8_t>(arg5))))" ) # pyforman: disable
113    out = gen_intrinsics._get_interpreter_hook_call_expr("Foo", intr["Foo"], use_type_id=True)
114    self.maxDiff = None
115    self.assertEqual(
116        out,
117        "IntegerToGPRReg(std::get<0>(intrinsics::Foo<"
118                "intrinsics::TypeFromId<Type0>, intrinsics::TypeFromId<Type1>>("
119            "GPRRegToInteger<uint32_t>(arg0), "
120            "GPRRegToInteger<uint8_t>(arg1), "
121            "FPRegToFloat<intrinsics::TypeFromId<Type0>>(arg2), "
122            "GPRRegToInteger<intrinsics::TypeFromId<Type1>>(arg3), "
123            "arg4, "
124            "GPRRegToInteger<uint8_t>(arg5))))" ) # pyforman: disable
125
126  def test_get_interpreter_hook_call_expr_operand_types(self):
127    out = gen_intrinsics._get_interpreter_hook_call_expr(
128        "Foo", {
129            "in": ["uint32_t", "uint8_t", "Float32", "Float64", "vec", "uimm8"],
130            "out": []
131        })
132    self.assertEqual(out,
133                     "intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0), "
134                                     "GPRRegToInteger<uint8_t>(arg1), "
135                                     "FPRegToFloat<Float32>(arg2), "
136                                     "FPRegToFloat<Float64>(arg3), "
137                                     "arg4, "
138                                     "GPRRegToInteger<uint8_t>(arg5))" ) # pyforman: disable
139
140  def test_get_interpreter_hook_call_expr_single_result(self):
141    out = gen_intrinsics._get_interpreter_hook_call_expr(
142        "Foo", {
143            "in": ["uint32_t"],
144            "out": ["uint32_t"]
145        })
146    self.assertEqual(out, "std::get<0>(intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0)))")
147
148  def test_get_interpreter_hook_call_expr_multiple_result(self):
149    out = gen_intrinsics._get_interpreter_hook_call_expr(
150        "Foo", {
151            "in": ["uint32_t"],
152            "out": ["vec", "uint32_t"]
153        })
154    self.assertEqual(out, "intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0))")
155
156  def test_get_interpreter_hook_call_expr_float32_result(self):
157    out = gen_intrinsics._get_interpreter_hook_call_expr(
158        "Foo", {
159            "in": ["uint32_t"],
160            "out": ["Float32"]
161        })
162    self.assertEqual(out, "FloatToFPReg(std::get<0>(intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0))))")
163
164  def test_get_interpreter_hook_call_expr_float64_result(self):
165    out = gen_intrinsics._get_interpreter_hook_call_expr(
166        "Foo", {
167            "in": ["uint32_t"],
168            "out": ["Float64"]
169        })
170    self.assertEqual(out, "FloatToFPReg(std::get<0>(intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0))))")
171
172  def test_get_interpreter_hook_call_expr_precise_nan(self):
173    out = gen_intrinsics._get_interpreter_hook_call_expr(
174        "Foo", {
175            "in": ["uint32_t"],
176            "out": [],
177            "precise_nans": True,
178        })
179    self.assertEqual(
180        out, "intrinsics::Foo<config::kPreciseNaNOperationsHandling>("
181             "GPRRegToInteger<uint32_t>(arg0))")
182
183  def test_gen_interpreter_hook_return_stmt(self):
184    out = gen_intrinsics._get_interpreter_hook_return_stmt(
185        "Foo", {
186            "in": ["uint32_t"],
187            "out": ["uint32_t"]
188        })
189    self.assertEqual(out, "return std::get<0>(intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0)));")
190
191  def test_gen_interpreter_hook_return_stmt_void(self):
192    out = gen_intrinsics._get_interpreter_hook_return_stmt(
193        "Foo", {
194            "in": ["uint32_t"],
195            "out": []
196        })
197    self.assertEqual(out, "return intrinsics::Foo(GPRRegToInteger<uint32_t>(arg0));")
198
199
200  def test_get_semantics_player_hook_proto_raw_variant(self):
201    out = gen_intrinsics._get_semantics_player_hook_proto(
202        "Foo", {
203            "class": "vector_8/16",
204            "in": ["vec", "vec"],
205            "out": ["vec"],
206            "variants": ["raw"],
207        })
208    self.assertEqual(out, "SimdRegister Foo(uint8_t size, "
209                                           "SimdRegister arg0, "
210                                           "SimdRegister arg1)") # pyformat: disable
211
212
213  def test_get_interpreter_hook_raw_vector_body(self):
214    out = gen_intrinsics._get_semantics_player_hook_raw_vector_body(
215        "Foo", {
216            "class": "vector_8/16",
217            "in": ["vec", "vec"],
218            "out": ["vec"],
219        }, gen_intrinsics._get_interpreter_hook_return_stmt)
220    self.assertSequenceEqual(list(out),
221                             ("switch (size) {",
222                              "  case 64:" ,
223                              "    return std::get<0>(intrinsics::Foo<64>(arg0, arg1));",
224                              "  case 128:",
225                              "    return std::get<0>(intrinsics::Foo<128>(arg0, arg1));",
226                              "  default:",
227                              "    LOG_ALWAYS_FATAL(\"Unsupported size\");",
228                              "}")) # pyformat: disable
229
230  def test_get_interpreter_hook_vector_body_fp(self):
231    out = gen_intrinsics._get_interpreter_hook_vector_body(
232        "Foo", {
233            "class": "vector_16",
234            "in": ["vec", "vec"],
235            "out": ["vec"],
236            "variants": ["Float32"],
237        })
238    self.assertSequenceEqual(list(out),
239                             ("auto format = intrinsics::GetVectorFormatFP(elem_size, elem_num);",
240                              "switch (format) {",
241                              "  case intrinsics::kVectorF32x4:" ,
242                              "    return std::get<0>(intrinsics::Foo<Float32, 4>(arg0, arg1));",
243                              "  default:",
244                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
245                              "}")) # pyformat: disable
246
247
248  def test_get_interpreter_hook_vector_body_unsigned_int(self):
249    out = gen_intrinsics._get_interpreter_hook_vector_body(
250        "Foo", {
251            "class": "vector_16",
252            "in": ["vec", "vec"],
253            "out": ["vec"],
254            "variants": ["unsigned_16/32/64"],
255        })
256    self.assertSequenceEqual(list(out),
257                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, false);",
258                              "switch (format) {",
259                              "  case intrinsics::kVectorU16x8:" ,
260                              "    return std::get<0>(intrinsics::Foo<uint16_t, 8>(arg0, arg1));",
261                              "  case intrinsics::kVectorU32x4:" ,
262                              "    return std::get<0>(intrinsics::Foo<uint32_t, 4>(arg0, arg1));",
263                              "  case intrinsics::kVectorU64x2:" ,
264                              "    return std::get<0>(intrinsics::Foo<uint64_t, 2>(arg0, arg1));",
265                              "  default:",
266                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
267                              "}")) # pyformat: disable
268
269
270  def test_get_interpreter_hook_vector_body_signed_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_16/32"],
277        })
278    self.assertSequenceEqual(list(out),
279                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, true);",
280                              "switch (format) {",
281                              "  case intrinsics::kVectorI16x8:" ,
282                              "    return std::get<0>(intrinsics::Foo<int16_t, 8>(arg0, arg1));",
283                              "  case intrinsics::kVectorI32x4:" ,
284                              "    return std::get<0>(intrinsics::Foo<int32_t, 4>(arg0, arg1));",
285                              "  default:",
286                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
287                              "}")) # pyformat: disable
288
289
290  def test_get_interpreter_hook_vector_body_signed_and_unsigned_int(self):
291    out = gen_intrinsics._get_interpreter_hook_vector_body(
292        "Foo", {
293            "class": "vector_16",
294            "in": ["vec", "vec"],
295            "out": ["vec"],
296            "variants": ["signed_32", "unsigned_32"],
297        })
298    self.assertSequenceEqual(list(out),
299                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, is_signed);",
300                              "switch (format) {",
301                              "  case intrinsics::kVectorI32x4:" ,
302                              "    return std::get<0>(intrinsics::Foo<int32_t, 4>(arg0, arg1));",
303                              "  case intrinsics::kVectorU32x4:" ,
304                              "    return std::get<0>(intrinsics::Foo<uint32_t, 4>(arg0, arg1));",
305                              "  default:",
306                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
307                              "}")) # pyformat: disable
308
309
310  def test_get_interpreter_hook_vector_body_vector_8(self):
311    out = gen_intrinsics._get_interpreter_hook_vector_body(
312        "Foo", {
313            "class": "vector_8",
314            "in": ["vec", "vec"],
315            "out": ["vec"],
316            "variants": ["unsigned_32"],
317        })
318    self.assertSequenceEqual(list(out),
319                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, false);",
320                              "switch (format) {",
321                              "  case intrinsics::kVectorU32x2:" ,
322                              "    return std::get<0>(intrinsics::Foo<uint32_t, 2>(arg0, arg1));",
323                              "  default:",
324                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
325                              "}")) # pyformat: disable
326
327
328  def test_get_interpreter_hook_vector_body_single(self):
329    out = gen_intrinsics._get_interpreter_hook_vector_body(
330        "Foo", {
331            "class": "vector_8/16/single",
332            "variants": ["signed_32"],
333            "in": ["vec", "fp_flags"],
334            "out": ["vec", "fp_flags"],
335        })
336    self.assertSequenceEqual(list(out),
337                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, true);",
338                              "switch (format) {",
339                              "  case intrinsics::kVectorI32x2:" ,
340                              "    return intrinsics::Foo<int32_t, 2>(arg0, GPRRegToInteger<uint32_t>(arg1));",
341                              "  case intrinsics::kVectorI32x4:" ,
342                              "    return intrinsics::Foo<int32_t, 4>(arg0, GPRRegToInteger<uint32_t>(arg1));",
343                              "  case intrinsics::kVectorI32x1:" ,
344                              "    return intrinsics::Foo<int32_t, 1>(arg0, GPRRegToInteger<uint32_t>(arg1));",
345                              "  default:",
346                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
347                              "}")) # pyformat: disable
348
349
350  def test_get_translator_hook_call_expr_smoke(self):
351    out = gen_intrinsics._get_translator_hook_call_expr(
352        "Foo", {
353            "in": ["uint32_t"],
354            "out": ["uint32_t"],
355        })
356    self.assertEqual(out, "CallIntrinsic<&intrinsics::Foo, Register>(arg0)")
357
358
359  def test_get_translator_hook_call_expr_void(self):
360    out = gen_intrinsics._get_translator_hook_call_expr(
361        "Foo", {
362            "in": [],
363            "out": [],
364        })
365    self.assertEqual(out, "CallIntrinsic<&intrinsics::Foo, void>()")
366
367
368  def test_get_translator_hook_raw_vector_body(self):
369    out = gen_intrinsics._get_semantics_player_hook_raw_vector_body(
370        "Foo", {
371            "class": "vector_8/16",
372            "in": ["vec", "vec"],
373            "out": ["vec"],
374        }, gen_intrinsics._get_translator_hook_return_stmt)
375    self.assertSequenceEqual(list(out),
376                             ("switch (size) {",
377                              "  case 64:",
378                              "    return CallIntrinsic<&intrinsics::Foo<64>, SimdRegister>(arg0, arg1);",
379                              "  case 128:",
380                              "    return CallIntrinsic<&intrinsics::Foo<128>, SimdRegister>(arg0, arg1);",
381                              "  default:",
382                              "    LOG_ALWAYS_FATAL(\"Unsupported size\");",
383                              "}")) # pyformat: disable
384
385
386  def test_get_translator_hook_vector_body(self):
387    out = gen_intrinsics._get_semantics_player_hook_vector_body(
388        "Foo", {
389            "class": "vector_8/16/single",
390            "variants": ["signed_32"],
391            "in": ["vec", "fp_flags"],
392            "out": ["vec", "fp_flags"],
393        }, gen_intrinsics._get_translator_hook_return_stmt)
394    self.assertSequenceEqual(list(out),
395                             ("auto format = intrinsics::GetVectorFormatInt(elem_size, elem_num, true);",
396                              "switch (format) {",
397                              "  case intrinsics::kVectorI32x2:" ,
398                              "    return CallIntrinsic<&intrinsics::Foo<int32_t, 2>, std::tuple<SimdRegister, Register>>(arg0, arg1);",
399                              "  case intrinsics::kVectorI32x4:" ,
400                              "    return CallIntrinsic<&intrinsics::Foo<int32_t, 4>, std::tuple<SimdRegister, Register>>(arg0, arg1);",
401                              "  case intrinsics::kVectorI32x1:" ,
402                              "    return CallIntrinsic<&intrinsics::Foo<int32_t, 1>, std::tuple<SimdRegister, Register>>(arg0, arg1);",
403                              "  default:",
404                              "    LOG_ALWAYS_FATAL(\"Unsupported format\");",
405                              "}")) # pyformat: disable
406
407
408  def test_gen_template_parameters_verifier(self):
409    intrinsic = {
410            "class": "template",
411            "variants": [ "int32_t", "int64_t" ],
412            "in": [ "Type0", "int8_t" ],
413            "out": [ "Type0" ]
414        }
415    out = io.StringIO()
416    gen_intrinsics._gen_template_parameters_verifier(out, intrinsic)
417    self.assertSequenceEqual(out.getvalue(),
418                             "  static_assert(std::tuple{intrinsics::kIdFromType<Type0>} == "
419                             "std::tuple{intrinsics::kIdFromType<int32_t>} || "
420                             "std::tuple{intrinsics::kIdFromType<Type0>} == "
421                             "std::tuple{intrinsics::kIdFromType<int64_t>});\n") # pyformat: disable
422    out = io.StringIO()
423    gen_intrinsics._gen_template_parameters_verifier(out, intrinsic, use_type_id=True)
424    self.assertSequenceEqual(out.getvalue(),
425                             "  static_assert(std::tuple{Type0} == "
426                             "std::tuple{intrinsics::kIdFromType<int32_t>} || std::tuple{Type0} == "
427                             "std::tuple{intrinsics::kIdFromType<int64_t>});\n") # pyformat: disable
428
429
430if __name__ == "__main__":
431  unittest.main(verbosity=2)
432