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