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