OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "src/wasm/asm-types.h" |
| 6 |
| 7 #include <unordered_map> |
| 8 #include <unordered_set> |
| 9 |
| 10 #include "src/base/macros.h" |
| 11 #include "test/unittests/test-utils.h" |
| 12 #include "testing/gmock/include/gmock/gmock.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 |
| 15 namespace v8 { |
| 16 namespace internal { |
| 17 namespace wasm { |
| 18 namespace { |
| 19 |
| 20 using ::testing::StrEq; |
| 21 |
| 22 class AsmTypeTest : public TestWithZone { |
| 23 public: |
| 24 using Type = AsmType; |
| 25 |
| 26 AsmTypeTest() |
| 27 : parents_({ |
| 28 {Type::Uint8Array(), {Type::Heap()}}, |
| 29 {Type::Int8Array(), {Type::Heap()}}, |
| 30 {Type::Uint16Array(), {Type::Heap()}}, |
| 31 {Type::Int16Array(), {Type::Heap()}}, |
| 32 {Type::Uint32Array(), {Type::Heap()}}, |
| 33 {Type::Int32Array(), {Type::Heap()}}, |
| 34 {Type::Float32Array(), {Type::Heap()}}, |
| 35 {Type::Float64Array(), {Type::Heap()}}, |
| 36 {Type::FloatishDoubleQ(), {Type::Floatish(), Type::DoubleQ()}}, |
| 37 {Type::FloatQDoubleQ(), |
| 38 {Type::FloatQ(), Type::Floatish(), Type::DoubleQ()}}, |
| 39 {Type::Float(), {Type::FloatQ(), Type::Floatish()}}, |
| 40 {Type::FloatQ(), {Type::Floatish()}}, |
| 41 {Type::FixNum(), |
| 42 {Type::Signed(), Type::Extern(), Type::Unsigned(), Type::Int(), |
| 43 Type::Intish()}}, |
| 44 {Type::Unsigned(), {Type::Int(), Type::Intish()}}, |
| 45 {Type::Signed(), {Type::Extern(), Type::Int(), Type::Intish()}}, |
| 46 {Type::Int(), {Type::Intish()}}, |
| 47 {Type::Double(), {Type::DoubleQ(), Type::Extern()}}, |
| 48 }) {} |
| 49 |
| 50 protected: |
| 51 std::unordered_set<Type*> ParentsOf(Type* derived) const { |
| 52 const auto parents_iter = parents_.find(derived); |
| 53 if (parents_iter == parents_.end()) { |
| 54 return std::unordered_set<Type*>(); |
| 55 } |
| 56 return parents_iter->second; |
| 57 } |
| 58 |
| 59 class FunctionTypeBuilder { |
| 60 public: |
| 61 FunctionTypeBuilder(FunctionTypeBuilder&& b) |
| 62 : function_type_(b.function_type_) { |
| 63 b.function_type_ = nullptr; |
| 64 } |
| 65 |
| 66 FunctionTypeBuilder& operator=(FunctionTypeBuilder&& b) { |
| 67 if (this != &b) { |
| 68 function_type_ = b.function_type_; |
| 69 b.function_type_ = nullptr; |
| 70 } |
| 71 return *this; |
| 72 } |
| 73 |
| 74 FunctionTypeBuilder(Zone* zone, Type* return_type) |
| 75 : function_type_(Type::Function(zone, return_type)) {} |
| 76 |
| 77 private: |
| 78 static void AddAllArguments(AsmFunctionType*) {} |
| 79 |
| 80 template <typename Arg, typename... Others> |
| 81 static void AddAllArguments(AsmFunctionType* function_type, Arg* arg, |
| 82 Others... others) { |
| 83 CHECK(function_type != nullptr); |
| 84 function_type->AddArgument((*arg)()); |
| 85 AddAllArguments(function_type, others...); |
| 86 } |
| 87 |
| 88 public: |
| 89 template <typename... Args> |
| 90 Type* operator()(Args... args) { |
| 91 Type* ret = function_type_; |
| 92 function_type_ = nullptr; |
| 93 AddAllArguments(ret->AsFunctionType(), args...); |
| 94 return ret; |
| 95 } |
| 96 |
| 97 private: |
| 98 Type* function_type_; |
| 99 }; |
| 100 |
| 101 FunctionTypeBuilder Function(Type* (*return_type)()) { |
| 102 return FunctionTypeBuilder(zone(), (*return_type)()); |
| 103 } |
| 104 |
| 105 template <typename... Overloads> |
| 106 Type* Overload(Overloads... overloads) { |
| 107 auto* ret = Type::OverloadedFunction(zone()); |
| 108 AddAllOverloads(ret->AsOverloadedFunctionType(), overloads...); |
| 109 return ret; |
| 110 } |
| 111 |
| 112 private: |
| 113 static void AddAllOverloads(AsmOverloadedFunctionType*) {} |
| 114 |
| 115 template <typename Overload, typename... Others> |
| 116 static void AddAllOverloads(AsmOverloadedFunctionType* function, |
| 117 Overload* overload, Others... others) { |
| 118 CHECK(function != nullptr); |
| 119 function->AddOverload(overload); |
| 120 AddAllOverloads(function, others...); |
| 121 } |
| 122 |
| 123 const std::unordered_map<Type*, std::unordered_set<Type*>> parents_; |
| 124 }; |
| 125 |
| 126 // AsmValueTypeParents expose the bitmasks for the parents for each value type |
| 127 // in asm's type system. It inherits from AsmValueType so that the kAsm<Foo> |
| 128 // members are available when expanding the FOR_EACH_ASM_VALUE_TYPE_LIST macro. |
| 129 class AsmValueTypeParents : private AsmValueType { |
| 130 public: |
| 131 enum : uint32_t { |
| 132 #define V(CamelName, string_name, number, parent_types) \ |
| 133 CamelName = parent_types, |
| 134 FOR_EACH_ASM_VALUE_TYPE_LIST(V) |
| 135 #undef V |
| 136 }; |
| 137 |
| 138 private: |
| 139 DISALLOW_IMPLICIT_CONSTRUCTORS(AsmValueTypeParents); |
| 140 }; |
| 141 |
| 142 TEST_F(AsmTypeTest, ValidateBits) { |
| 143 // Generic validation tests for the bits in the type system's type |
| 144 // definitions. |
| 145 |
| 146 std::unordered_set<Type*> seen_types; |
| 147 std::unordered_set<uint32_t> seen_numbers; |
| 148 uint32_t total_types = 0; |
| 149 #define V(CamelName, string_name, number, parent_types) \ |
| 150 do { \ |
| 151 ++total_types; \ |
| 152 seen_types.insert(Type::CamelName()); \ |
| 153 seen_numbers.insert(number); \ |
| 154 /* Every ASM type must have a valid number. */ \ |
| 155 EXPECT_NE(0, number) << Type::CamelName()->Name(); \ |
| 156 /* Inheritance cycles - unlikely, but we're paranoid and check for it */ \ |
| 157 /* anyways.*/ \ |
| 158 EXPECT_EQ(0, (1 << (number)) & AsmValueTypeParents::CamelName); \ |
| 159 } while (0); |
| 160 FOR_EACH_ASM_VALUE_TYPE_LIST(V) |
| 161 #undef V |
| 162 |
| 163 // At least one type was expanded. |
| 164 EXPECT_GT(total_types, 0u); |
| 165 |
| 166 // Each value type is unique. |
| 167 EXPECT_EQ(total_types, seen_types.size()); |
| 168 |
| 169 // Each number is unique. |
| 170 EXPECT_EQ(total_types, seen_numbers.size()); |
| 171 } |
| 172 |
| 173 TEST_F(AsmTypeTest, SaneParentsMap) { |
| 174 // This test ensures our parents map contains all the parents types that are |
| 175 // specified in the types' declaration. It does not report bogus inheritance. |
| 176 |
| 177 // Handy-dandy lambda for counting bits. Code borrowed from stack overflow. |
| 178 auto NumberOfSetBits = [](uintptr_t parent_mask) -> uint32_t { |
| 179 uint32_t parent_mask32 = static_cast<uint32_t>(parent_mask); |
| 180 CHECK_EQ(parent_mask, parent_mask32); |
| 181 parent_mask32 = parent_mask32 - ((parent_mask32 >> 1) & 0x55555555); |
| 182 parent_mask32 = |
| 183 (parent_mask32 & 0x33333333) + ((parent_mask32 >> 2) & 0x33333333); |
| 184 return (((parent_mask32 + (parent_mask32 >> 4)) & 0x0F0F0F0F) * |
| 185 0x01010101) >> |
| 186 24; |
| 187 }; |
| 188 |
| 189 #define V(CamelName, string_name, number, parent_types) \ |
| 190 do { \ |
| 191 const uintptr_t parents = \ |
| 192 reinterpret_cast<uintptr_t>(Type::CamelName()) & ~(1 << (number)); \ |
| 193 EXPECT_EQ(NumberOfSetBits(parents), \ |
| 194 1 + ParentsOf(Type::CamelName()).size()) \ |
| 195 << Type::CamelName()->Name() << ", parents " \ |
| 196 << reinterpret_cast<void*>(parents) << ", type " \ |
| 197 << static_cast<void*>(Type::CamelName()); \ |
| 198 } while (0); |
| 199 FOR_EACH_ASM_VALUE_TYPE_LIST(V) |
| 200 #undef V |
| 201 } |
| 202 |
| 203 TEST_F(AsmTypeTest, Names) { |
| 204 #define V(CamelName, string_name, number, parent_types) \ |
| 205 do { \ |
| 206 EXPECT_THAT(Type::CamelName()->Name(), StrEq(string_name)); \ |
| 207 } while (0); |
| 208 FOR_EACH_ASM_VALUE_TYPE_LIST(V) |
| 209 #undef V |
| 210 |
| 211 EXPECT_THAT(Function(Type::Int)(Type::Double, Type::Float)->Name(), |
| 212 StrEq("(double, float) -> int")); |
| 213 |
| 214 EXPECT_THAT(Overload(Function(Type::Int)(Type::Double, Type::Float), |
| 215 Function(Type::Int)(Type::Int)) |
| 216 ->Name(), |
| 217 StrEq("(double, float) -> int /\\ (int) -> int")); |
| 218 |
| 219 EXPECT_THAT(Type::FroundType(zone(), Type::Int())->Name(), |
| 220 StrEq("(int) -> float")); |
| 221 EXPECT_THAT(Type::FroundType(zone(), Type::Floatish())->Name(), |
| 222 StrEq("(floatish) -> float")); |
| 223 EXPECT_THAT(Type::FroundType(zone(), Type::DoubleQ())->Name(), |
| 224 StrEq("(double?) -> float")); |
| 225 |
| 226 EXPECT_THAT(Type::MinMaxType(zone(), Type::Int())->Name(), |
| 227 StrEq("(int, int...) -> int")); |
| 228 EXPECT_THAT(Type::MinMaxType(zone(), Type::Floatish())->Name(), |
| 229 StrEq("(floatish, floatish...) -> floatish")); |
| 230 EXPECT_THAT(Type::MinMaxType(zone(), Type::DoubleQ())->Name(), |
| 231 StrEq("(double?, double?...) -> double?")); |
| 232 } |
| 233 |
| 234 TEST_F(AsmTypeTest, IsExactly) { |
| 235 Type* test_types[] = { |
| 236 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), |
| 237 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) |
| 238 #undef CREATE |
| 239 Function(Type::Int)(Type::Double), |
| 240 Function(Type::Int)(Type::DoubleQ), |
| 241 Overload(Function(Type::Int)(Type::Double)), |
| 242 Function(Type::Int)(Type::Int, Type::Int), |
| 243 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), |
| 244 Type::FroundType(zone(), Type::Int()), |
| 245 }; |
| 246 |
| 247 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { |
| 248 for (size_t jj = 0; jj < arraysize(test_types); ++jj) { |
| 249 EXPECT_EQ(ii == jj, test_types[ii]->IsExactly(test_types[jj])) |
| 250 << test_types[ii]->Name() |
| 251 << ((ii == jj) ? " is not exactly " : " is exactly ") |
| 252 << test_types[jj]->Name(); |
| 253 } |
| 254 } |
| 255 } |
| 256 |
| 257 TEST_F(AsmTypeTest, IsA) { |
| 258 Type* test_types[] = { |
| 259 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), |
| 260 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) |
| 261 #undef CREATE |
| 262 Function(Type::Int)(Type::Double), |
| 263 Function(Type::Int)(Type::DoubleQ), |
| 264 Overload(Function(Type::Int)(Type::Double)), |
| 265 Function(Type::Int)(Type::Int, Type::Int), |
| 266 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), |
| 267 Type::FroundType(zone(), Type::Int()), |
| 268 }; |
| 269 |
| 270 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { |
| 271 for (size_t jj = 0; jj < arraysize(test_types); ++jj) { |
| 272 const bool Expected = |
| 273 (ii == jj) || ParentsOf(test_types[ii]).count(test_types[jj]) != 0; |
| 274 EXPECT_EQ(Expected, test_types[ii]->IsA(test_types[jj])) |
| 275 << test_types[ii]->Name() << (Expected ? " is not a " : " is a ") |
| 276 << test_types[jj]->Name(); |
| 277 } |
| 278 } |
| 279 } |
| 280 |
| 281 TEST_F(AsmTypeTest, ValidateCall) { |
| 282 auto* min_max_int = Type::MinMaxType(zone(), Type::Int()); |
| 283 auto* i2i = Function(Type::Int)(Type::Int); |
| 284 auto* ii2i = Function(Type::Int)(Type::Int, Type::Int); |
| 285 auto* iii2i = Function(Type::Int)(Type::Int, Type::Int, Type::Int); |
| 286 auto* iiii2i = |
| 287 Function(Type::Int)(Type::Int, Type::Int, Type::Int, Type::Int); |
| 288 |
| 289 EXPECT_EQ(Type::Int(), |
| 290 min_max_int->AsCallableType()->ValidateCall(min_max_int)); |
| 291 EXPECT_EQ(Type::Int(), min_max_int->AsCallableType()->ValidateCall(ii2i)); |
| 292 EXPECT_EQ(Type::Int(), min_max_int->AsCallableType()->ValidateCall(iii2i)); |
| 293 EXPECT_EQ(Type::Int(), min_max_int->AsCallableType()->ValidateCall(iiii2i)); |
| 294 EXPECT_EQ(Type::None(), min_max_int->AsCallableType()->ValidateCall(i2i)); |
| 295 |
| 296 auto* min_max_double = Type::MinMaxType(zone(), Type::Double()); |
| 297 auto* d2d = Function(Type::Double)(Type::Double); |
| 298 auto* dd2d = Function(Type::Double)(Type::Double, Type::Double); |
| 299 auto* ddd2d = |
| 300 Function(Type::Double)(Type::Double, Type::Double, Type::Double); |
| 301 auto* dddd2d = Function(Type::Double)(Type::Double, Type::Double, |
| 302 Type::Double, Type::Double); |
| 303 EXPECT_EQ(Type::Double(), |
| 304 min_max_double->AsCallableType()->ValidateCall(min_max_double)); |
| 305 EXPECT_EQ(Type::Double(), |
| 306 min_max_double->AsCallableType()->ValidateCall(dd2d)); |
| 307 EXPECT_EQ(Type::Double(), |
| 308 min_max_double->AsCallableType()->ValidateCall(ddd2d)); |
| 309 EXPECT_EQ(Type::Double(), |
| 310 min_max_double->AsCallableType()->ValidateCall(dddd2d)); |
| 311 EXPECT_EQ(Type::None(), min_max_double->AsCallableType()->ValidateCall(d2d)); |
| 312 |
| 313 auto* min_max = Overload(min_max_int, min_max_double); |
| 314 EXPECT_EQ(Type::None(), min_max->AsCallableType()->ValidateCall(min_max)); |
| 315 EXPECT_EQ(Type::None(), min_max->AsCallableType()->ValidateCall(i2i)); |
| 316 EXPECT_EQ(Type::None(), min_max->AsCallableType()->ValidateCall(d2d)); |
| 317 EXPECT_EQ(Type::Int(), min_max->AsCallableType()->ValidateCall(min_max_int)); |
| 318 EXPECT_EQ(Type::Int(), min_max->AsCallableType()->ValidateCall(ii2i)); |
| 319 EXPECT_EQ(Type::Int(), min_max->AsCallableType()->ValidateCall(iii2i)); |
| 320 EXPECT_EQ(Type::Int(), min_max->AsCallableType()->ValidateCall(iiii2i)); |
| 321 EXPECT_EQ(Type::Double(), |
| 322 min_max->AsCallableType()->ValidateCall(min_max_double)); |
| 323 EXPECT_EQ(Type::Double(), min_max->AsCallableType()->ValidateCall(dd2d)); |
| 324 EXPECT_EQ(Type::Double(), min_max->AsCallableType()->ValidateCall(ddd2d)); |
| 325 EXPECT_EQ(Type::Double(), min_max->AsCallableType()->ValidateCall(dddd2d)); |
| 326 |
| 327 auto* fround_floatish = Type::FroundType(zone(), Type::Floatish()); |
| 328 auto* fround_floatq = Type::FroundType(zone(), Type::FloatQ()); |
| 329 auto* fround_float = Type::FroundType(zone(), Type::Float()); |
| 330 auto* fround_doubleq = Type::FroundType(zone(), Type::DoubleQ()); |
| 331 auto* fround_double = Type::FroundType(zone(), Type::Double()); |
| 332 auto* fround_signed = Type::FroundType(zone(), Type::Signed()); |
| 333 auto* fround_unsigned = Type::FroundType(zone(), Type::Unsigned()); |
| 334 auto* fround_fixnum = Type::FroundType(zone(), Type::FixNum()); |
| 335 auto* fround = |
| 336 Overload(fround_floatish, fround_floatq, fround_float, fround_doubleq, |
| 337 fround_double, fround_signed, fround_unsigned, fround_fixnum); |
| 338 |
| 339 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( |
| 340 Function(Type::Float)(Type::Floatish))); |
| 341 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( |
| 342 Function(Type::Float)(Type::FloatQ))); |
| 343 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( |
| 344 Function(Type::Float)(Type::Float))); |
| 345 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( |
| 346 Function(Type::Float)(Type::DoubleQ))); |
| 347 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( |
| 348 Function(Type::Float)(Type::Double))); |
| 349 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( |
| 350 Function(Type::Float)(Type::Signed))); |
| 351 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( |
| 352 Function(Type::Float)(Type::Unsigned))); |
| 353 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( |
| 354 Function(Type::Float)(Type::FixNum))); |
| 355 |
| 356 auto* idf2v = Function(Type::Void)(Type::Int, Type::Double, Type::Float); |
| 357 auto* i2d = Function(Type::Double)(Type::Int); |
| 358 auto* i2f = Function(Type::Float)(Type::Int); |
| 359 auto* fi2d = Function(Type::Double)(Type::Float, Type::Int); |
| 360 auto* idif2i = |
| 361 Function(Type::Int)(Type::Int, Type::Double, Type::Int, Type::Float); |
| 362 auto* overload = Overload(idf2v, i2f, /*i2d missing, */ fi2d, idif2i); |
| 363 EXPECT_EQ(Type::Void(), overload->AsCallableType()->ValidateCall(idf2v)); |
| 364 EXPECT_EQ(Type::Float(), overload->AsCallableType()->ValidateCall(i2f)); |
| 365 EXPECT_EQ(Type::Double(), overload->AsCallableType()->ValidateCall(fi2d)); |
| 366 EXPECT_EQ(Type::Int(), overload->AsCallableType()->ValidateCall(idif2i)); |
| 367 EXPECT_EQ(Type::None(), overload->AsCallableType()->ValidateCall(i2d)); |
| 368 EXPECT_EQ(Type::None(), i2f->AsCallableType()->ValidateCall(i2d)); |
| 369 } |
| 370 |
| 371 TEST_F(AsmTypeTest, IsReturnType) { |
| 372 Type* test_types[] = { |
| 373 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), |
| 374 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) |
| 375 #undef CREATE |
| 376 Function(Type::Int)(Type::Double), |
| 377 Function(Type::Int)(Type::DoubleQ), |
| 378 Overload(Function(Type::Int)(Type::Double)), |
| 379 Function(Type::Int)(Type::Int, Type::Int), |
| 380 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), |
| 381 Type::FroundType(zone(), Type::Int()), |
| 382 }; |
| 383 |
| 384 std::unordered_set<Type*> return_types{ |
| 385 Type::Double(), Type::Signed(), Type::Float(), Type::Void(), |
| 386 }; |
| 387 |
| 388 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { |
| 389 const bool IsReturnType = return_types.count(test_types[ii]); |
| 390 EXPECT_EQ(IsReturnType, test_types[ii]->IsReturnType()) |
| 391 << test_types[ii]->Name() |
| 392 << (IsReturnType ? " is not a return type" : " is a return type"); |
| 393 } |
| 394 } |
| 395 |
| 396 TEST_F(AsmTypeTest, IsParameterType) { |
| 397 Type* test_types[] = { |
| 398 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), |
| 399 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) |
| 400 #undef CREATE |
| 401 Function(Type::Int)(Type::Double), |
| 402 Function(Type::Int)(Type::DoubleQ), |
| 403 Overload(Function(Type::Int)(Type::Double)), |
| 404 Function(Type::Int)(Type::Int, Type::Int), |
| 405 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), |
| 406 Type::FroundType(zone(), Type::Int()), |
| 407 }; |
| 408 |
| 409 std::unordered_set<Type*> parameter_types{ |
| 410 Type::Double(), Type::Int(), Type::Float(), |
| 411 }; |
| 412 |
| 413 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { |
| 414 const bool IsParameterType = parameter_types.count(test_types[ii]); |
| 415 EXPECT_EQ(IsParameterType, test_types[ii]->IsParameterType()) |
| 416 << test_types[ii]->Name() |
| 417 << (IsParameterType ? " is not a parameter type" |
| 418 : " is a parameter type"); |
| 419 } |
| 420 } |
| 421 |
| 422 TEST_F(AsmTypeTest, IsComparableType) { |
| 423 Type* test_types[] = { |
| 424 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), |
| 425 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) |
| 426 #undef CREATE |
| 427 Function(Type::Int)(Type::Double), |
| 428 Function(Type::Int)(Type::DoubleQ), |
| 429 Overload(Function(Type::Int)(Type::Double)), |
| 430 Function(Type::Int)(Type::Int, Type::Int), |
| 431 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), |
| 432 Type::FroundType(zone(), Type::Int()), |
| 433 }; |
| 434 |
| 435 std::unordered_set<Type*> comparable_types{ |
| 436 Type::Double(), Type::Signed(), Type::Unsigned(), Type::Float(), |
| 437 }; |
| 438 |
| 439 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { |
| 440 const bool IsComparableType = comparable_types.count(test_types[ii]); |
| 441 EXPECT_EQ(IsComparableType, test_types[ii]->IsComparableType()) |
| 442 << test_types[ii]->Name() |
| 443 << (IsComparableType ? " is not a comparable type" |
| 444 : " is a comparable type"); |
| 445 } |
| 446 } |
| 447 |
| 448 TEST_F(AsmTypeTest, ElementSizeInBytes) { |
| 449 Type* test_types[] = { |
| 450 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), |
| 451 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) |
| 452 #undef CREATE |
| 453 Function(Type::Int)(Type::Double), |
| 454 Function(Type::Int)(Type::DoubleQ), |
| 455 Overload(Function(Type::Int)(Type::Double)), |
| 456 Function(Type::Int)(Type::Int, Type::Int), |
| 457 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), |
| 458 Type::FroundType(zone(), Type::Int()), |
| 459 }; |
| 460 |
| 461 auto ElementSizeInBytesForType = [](Type* type) -> int32_t { |
| 462 if (type == Type::Int8Array() || type == Type::Uint8Array()) { |
| 463 return 1; |
| 464 } |
| 465 if (type == Type::Int16Array() || type == Type::Uint16Array()) { |
| 466 return 2; |
| 467 } |
| 468 if (type == Type::Int32Array() || type == Type::Uint32Array() || |
| 469 type == Type::Float32Array()) { |
| 470 return 4; |
| 471 } |
| 472 if (type == Type::Float64Array()) { |
| 473 return 8; |
| 474 } |
| 475 return -1; |
| 476 }; |
| 477 |
| 478 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { |
| 479 EXPECT_EQ(ElementSizeInBytesForType(test_types[ii]), |
| 480 test_types[ii]->ElementSizeInBytes()); |
| 481 } |
| 482 } |
| 483 |
| 484 TEST_F(AsmTypeTest, LoadType) { |
| 485 Type* test_types[] = { |
| 486 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), |
| 487 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) |
| 488 #undef CREATE |
| 489 Function(Type::Int)(Type::Double), |
| 490 Function(Type::Int)(Type::DoubleQ), |
| 491 Overload(Function(Type::Int)(Type::Double)), |
| 492 Function(Type::Int)(Type::Int, Type::Int), |
| 493 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), |
| 494 Type::FroundType(zone(), Type::Int()), |
| 495 }; |
| 496 |
| 497 auto LoadTypeForType = [](Type* type) -> Type* { |
| 498 if (type == Type::Int8Array() || type == Type::Uint8Array() || |
| 499 type == Type::Int16Array() || type == Type::Uint16Array() || |
| 500 type == Type::Int32Array() || type == Type::Uint32Array()) { |
| 501 return Type::Intish(); |
| 502 } |
| 503 |
| 504 if (type == Type::Float32Array()) { |
| 505 return Type::FloatQ(); |
| 506 } |
| 507 |
| 508 if (type == Type::Float64Array()) { |
| 509 return Type::DoubleQ(); |
| 510 } |
| 511 |
| 512 return Type::None(); |
| 513 }; |
| 514 |
| 515 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { |
| 516 EXPECT_EQ(LoadTypeForType(test_types[ii]), test_types[ii]->LoadType()); |
| 517 } |
| 518 } |
| 519 |
| 520 TEST_F(AsmTypeTest, StoreType) { |
| 521 Type* test_types[] = { |
| 522 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), |
| 523 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) |
| 524 #undef CREATE |
| 525 Function(Type::Int)(Type::Double), |
| 526 Function(Type::Int)(Type::DoubleQ), |
| 527 Overload(Function(Type::Int)(Type::Double)), |
| 528 Function(Type::Int)(Type::Int, Type::Int), |
| 529 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), |
| 530 Type::FroundType(zone(), Type::Int()), |
| 531 }; |
| 532 |
| 533 auto StoreTypeForType = [](Type* type) -> Type* { |
| 534 if (type == Type::Int8Array() || type == Type::Uint8Array() || |
| 535 type == Type::Int16Array() || type == Type::Uint16Array() || |
| 536 type == Type::Int32Array() || type == Type::Uint32Array()) { |
| 537 return Type::Intish(); |
| 538 } |
| 539 |
| 540 if (type == Type::Float32Array()) { |
| 541 return Type::FloatishDoubleQ(); |
| 542 } |
| 543 |
| 544 if (type == Type::Float64Array()) { |
| 545 return Type::FloatQDoubleQ(); |
| 546 } |
| 547 |
| 548 return Type::None(); |
| 549 }; |
| 550 |
| 551 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { |
| 552 EXPECT_EQ(StoreTypeForType(test_types[ii]), test_types[ii]->StoreType()) |
| 553 << test_types[ii]->Name(); |
| 554 } |
| 555 } |
| 556 |
| 557 } // namespace |
| 558 } // namespace wasm |
| 559 } // namespace internal |
| 560 } // namespace v8 |
OLD | NEW |