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