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 // At least one type was expanded. | |
151 EXPECT_GT(total_types, 0); | |
152 | |
153 // Each value type is unique. | |
154 EXPECT_EQ(total_types, seen_types.size()); | |
155 | |
156 // Each number is unique. | |
157 EXPECT_EQ(total_types, seen_numbers.size()); | |
158 } | |
159 | |
160 TEST_F(AsmTypeTest, SaneParentsMap) { | |
161 // This test ensures our parents map contains all the parents types that are | |
162 // specified in the types' declaration. It does not report bogus inheritance. | |
163 | |
164 // Handy-dandy lambda for counting bits. Code borrowed from stack overflow. | |
165 auto NumberOfSetBits = [](uintptr_t parent_mask) -> uint32_t { | |
166 uint32_t parent_mask32 = static_cast<uint32_t>(parent_mask); | |
167 CHECK_EQ(parent_mask, parent_mask32); | |
168 parent_mask32 = parent_mask32 - ((parent_mask32 >> 1) & 0x55555555); | |
169 parent_mask32 = | |
170 (parent_mask32 & 0x33333333) + ((parent_mask32 >> 2) & 0x33333333); | |
171 return (((parent_mask32 + (parent_mask32 >> 4)) & 0x0F0F0F0F) * | |
172 0x01010101) >> | |
173 24; | |
174 }; | |
175 | |
176 #define V(CamelName, string_name, number, parent_types) \ | |
177 do { \ | |
178 const uintptr_t parents = \ | |
179 reinterpret_cast<uintptr_t>(Type::CamelName()) & ~(1 << (number)); \ | |
180 EXPECT_EQ(NumberOfSetBits(parents), \ | |
181 1 + ParentsOf(Type::CamelName()).size()) \ | |
182 << Type::CamelName()->Name() << ", parents " \ | |
183 << reinterpret_cast<void*>(parents) << ", type " \ | |
184 << static_cast<void*>(Type::CamelName()); \ | |
185 } while (0); | |
186 FOR_EACH_ASM_VALUE_TYPE_LIST(V) | |
187 #undef V | |
188 } | |
189 | |
190 TEST_F(AsmTypeTest, Names) { | |
191 #define V(CamelName, string_name, number, parent_types) \ | |
192 do { \ | |
193 EXPECT_THAT(Type::CamelName()->Name(), StrEq(string_name)); \ | |
194 } while (0); | |
195 FOR_EACH_ASM_VALUE_TYPE_LIST(V) | |
196 #undef V | |
197 | |
198 EXPECT_THAT(Function(Type::Int)(Type::Double, Type::Float)->Name(), | |
199 StrEq("(double, float) -> int")); | |
200 | |
201 EXPECT_THAT(Overload(Function(Type::Int)(Type::Double, Type::Float), | |
202 Function(Type::Int)(Type::Int)) | |
203 ->Name(), | |
204 StrEq("(double, float) -> int /\\ (int) -> int")); | |
205 | |
206 EXPECT_THAT(Type::FroundType(zone(), Type::Int())->Name(), | |
207 StrEq("(int) -> float")); | |
208 EXPECT_THAT(Type::FroundType(zone(), Type::Floatish())->Name(), | |
209 StrEq("(floatish) -> float")); | |
210 EXPECT_THAT(Type::FroundType(zone(), Type::DoubleQ())->Name(), | |
211 StrEq("(double?) -> float")); | |
212 | |
213 EXPECT_THAT(Type::MinMaxType(zone(), Type::Int())->Name(), | |
214 StrEq("(int, int...) -> int")); | |
215 EXPECT_THAT(Type::MinMaxType(zone(), Type::Floatish())->Name(), | |
216 StrEq("(floatish, floatish...) -> floatish")); | |
217 EXPECT_THAT(Type::MinMaxType(zone(), Type::DoubleQ())->Name(), | |
218 StrEq("(double?, double?...) -> double?")); | |
219 } | |
220 | |
221 TEST_F(AsmTypeTest, IsExactly) { | |
222 Type* test_types[] = { | |
223 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), | |
224 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) | |
225 #undef CREATE | |
226 Function(Type::Int)(Type::Double), | |
227 Function(Type::Int)(Type::DoubleQ), | |
228 Overload(Function(Type::Int)(Type::Double)), | |
229 Function(Type::Int)(Type::Int, Type::Int), | |
ahaas
2016/06/13 16:27:03
If you duplicate the line "Function(Type::Int)(Typ
John
2016/06/13 17:32:27
Yes, because (as I mentioned before) function type
| |
230 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), | |
231 Type::FroundType(zone(), Type::Int()), | |
232 }; | |
233 | |
234 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { | |
235 for (size_t jj = 0; jj < arraysize(test_types); ++jj) { | |
236 EXPECT_EQ(ii == jj, test_types[ii]->IsExactly(test_types[jj])) | |
237 << test_types[ii]->Name() | |
238 << ((ii == jj) ? " is not exactly " : " is exactly ") | |
239 << test_types[jj]->Name(); | |
240 } | |
241 } | |
242 } | |
243 | |
244 TEST_F(AsmTypeTest, IsA) { | |
245 Type* test_types[] = { | |
246 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), | |
247 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) | |
248 #undef CREATE | |
249 Function(Type::Int)(Type::Double), | |
250 Function(Type::Int)(Type::DoubleQ), | |
251 Overload(Function(Type::Int)(Type::Double)), | |
252 Function(Type::Int)(Type::Int, Type::Int), | |
253 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), | |
254 Type::FroundType(zone(), Type::Int()), | |
255 }; | |
256 | |
257 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { | |
258 for (size_t jj = 0; jj < arraysize(test_types); ++jj) { | |
259 const bool Expected = | |
260 (ii == jj) || ParentsOf(test_types[ii]).count(test_types[jj]) != 0; | |
261 EXPECT_EQ(Expected, test_types[ii]->IsA(test_types[jj])) | |
262 << test_types[ii]->Name() << (Expected ? " is not a " : " is a ") | |
263 << test_types[jj]->Name(); | |
264 } | |
265 } | |
266 } | |
267 | |
268 TEST_F(AsmTypeTest, ValidateCall) { | |
269 auto* min_max_int = Type::MinMaxType(zone(), Type::Int()); | |
270 auto* i2i = Function(Type::Int)(Type::Int); | |
271 auto* ii2i = Function(Type::Int)(Type::Int, Type::Int); | |
272 auto* iii2i = Function(Type::Int)(Type::Int, Type::Int, Type::Int); | |
273 auto* iiii2i = | |
274 Function(Type::Int)(Type::Int, Type::Int, Type::Int, Type::Int); | |
275 | |
276 EXPECT_EQ(Type::Int(), | |
277 min_max_int->AsCallableType()->ValidateCall(min_max_int)); | |
278 EXPECT_EQ(Type::Int(), min_max_int->AsCallableType()->ValidateCall(ii2i)); | |
279 EXPECT_EQ(Type::Int(), min_max_int->AsCallableType()->ValidateCall(iii2i)); | |
280 EXPECT_EQ(Type::Int(), min_max_int->AsCallableType()->ValidateCall(iiii2i)); | |
281 EXPECT_EQ(Type::None(), min_max_int->AsCallableType()->ValidateCall(i2i)); | |
282 | |
283 auto* min_max_double = Type::MinMaxType(zone(), Type::Double()); | |
284 auto* d2d = Function(Type::Double)(Type::Double); | |
285 auto* dd2d = Function(Type::Double)(Type::Double, Type::Double); | |
286 auto* ddd2d = | |
287 Function(Type::Double)(Type::Double, Type::Double, Type::Double); | |
288 auto* dddd2d = Function(Type::Double)(Type::Double, Type::Double, | |
289 Type::Double, Type::Double); | |
290 EXPECT_EQ(Type::Double(), | |
291 min_max_double->AsCallableType()->ValidateCall(min_max_double)); | |
292 EXPECT_EQ(Type::Double(), | |
293 min_max_double->AsCallableType()->ValidateCall(dd2d)); | |
294 EXPECT_EQ(Type::Double(), | |
295 min_max_double->AsCallableType()->ValidateCall(ddd2d)); | |
296 EXPECT_EQ(Type::Double(), | |
297 min_max_double->AsCallableType()->ValidateCall(dddd2d)); | |
298 EXPECT_EQ(Type::None(), min_max_double->AsCallableType()->ValidateCall(d2d)); | |
299 | |
300 auto* min_max = Overload(min_max_int, min_max_double); | |
301 EXPECT_EQ(Type::None(), min_max->AsCallableType()->ValidateCall(min_max)); | |
302 EXPECT_EQ(Type::None(), min_max->AsCallableType()->ValidateCall(i2i)); | |
303 EXPECT_EQ(Type::None(), min_max->AsCallableType()->ValidateCall(d2d)); | |
304 EXPECT_EQ(Type::Int(), min_max->AsCallableType()->ValidateCall(min_max_int)); | |
305 EXPECT_EQ(Type::Int(), min_max->AsCallableType()->ValidateCall(ii2i)); | |
306 EXPECT_EQ(Type::Int(), min_max->AsCallableType()->ValidateCall(iii2i)); | |
307 EXPECT_EQ(Type::Int(), min_max->AsCallableType()->ValidateCall(iiii2i)); | |
308 EXPECT_EQ(Type::Double(), | |
309 min_max->AsCallableType()->ValidateCall(min_max_double)); | |
310 EXPECT_EQ(Type::Double(), min_max->AsCallableType()->ValidateCall(dd2d)); | |
311 EXPECT_EQ(Type::Double(), min_max->AsCallableType()->ValidateCall(ddd2d)); | |
312 EXPECT_EQ(Type::Double(), min_max->AsCallableType()->ValidateCall(dddd2d)); | |
313 | |
314 auto* fround_floatish = Type::FroundType(zone(), Type::Floatish()); | |
315 auto* fround_floatq = Type::FroundType(zone(), Type::FloatQ()); | |
316 auto* fround_float = Type::FroundType(zone(), Type::Float()); | |
317 auto* fround_doubleq = Type::FroundType(zone(), Type::DoubleQ()); | |
318 auto* fround_double = Type::FroundType(zone(), Type::Double()); | |
319 auto* fround_signed = Type::FroundType(zone(), Type::Signed()); | |
320 auto* fround_unsigned = Type::FroundType(zone(), Type::Unsigned()); | |
321 auto* fround_fixnum = Type::FroundType(zone(), Type::FixNum()); | |
322 auto* fround = | |
323 Overload(fround_floatish, fround_floatq, fround_float, fround_doubleq, | |
324 fround_double, fround_signed, fround_unsigned, fround_fixnum); | |
325 | |
326 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( | |
327 Function(Type::Float)(Type::Floatish))); | |
328 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( | |
329 Function(Type::Float)(Type::FloatQ))); | |
330 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( | |
331 Function(Type::Float)(Type::Float))); | |
332 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( | |
333 Function(Type::Float)(Type::DoubleQ))); | |
334 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( | |
335 Function(Type::Float)(Type::Double))); | |
336 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( | |
337 Function(Type::Float)(Type::Signed))); | |
338 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( | |
339 Function(Type::Float)(Type::Unsigned))); | |
340 EXPECT_EQ(Type::Float(), fround->AsCallableType()->ValidateCall( | |
341 Function(Type::Float)(Type::FixNum))); | |
342 | |
343 auto* idf2v = Function(Type::Void)(Type::Int, Type::Double, Type::Float); | |
344 auto* i2d = Function(Type::Double)(Type::Int); | |
345 auto* i2f = Function(Type::Float)(Type::Int); | |
346 auto* fi2d = Function(Type::Double)(Type::Float, Type::Int); | |
347 auto* idif2i = | |
348 Function(Type::Int)(Type::Int, Type::Double, Type::Int, Type::Float); | |
349 auto* overload = Overload(idf2v, i2f, /*i2d missing, */ fi2d, idif2i); | |
350 EXPECT_EQ(Type::Void(), overload->AsCallableType()->ValidateCall(idf2v)); | |
351 EXPECT_EQ(Type::Float(), overload->AsCallableType()->ValidateCall(i2f)); | |
352 EXPECT_EQ(Type::Double(), overload->AsCallableType()->ValidateCall(fi2d)); | |
353 EXPECT_EQ(Type::Int(), overload->AsCallableType()->ValidateCall(idif2i)); | |
354 EXPECT_EQ(Type::None(), overload->AsCallableType()->ValidateCall(i2d)); | |
355 EXPECT_EQ(Type::None(), i2f->AsCallableType()->ValidateCall(i2d)); | |
356 } | |
357 | |
358 TEST_F(AsmTypeTest, IsReturnType) { | |
359 Type* test_types[] = { | |
360 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), | |
361 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) | |
362 #undef CREATE | |
363 Function(Type::Int)(Type::Double), | |
364 Function(Type::Int)(Type::DoubleQ), | |
365 Overload(Function(Type::Int)(Type::Double)), | |
366 Function(Type::Int)(Type::Int, Type::Int), | |
367 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), | |
368 Type::FroundType(zone(), Type::Int()), | |
369 }; | |
370 | |
371 std::unordered_set<Type*> return_types{ | |
372 Type::Double(), Type::Signed(), Type::Float(), Type::Void(), | |
373 }; | |
374 | |
375 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { | |
376 const bool IsReturnType = return_types.count(test_types[ii]); | |
377 EXPECT_EQ(IsReturnType, test_types[ii]->IsReturnType()) | |
378 << test_types[ii]->Name() | |
379 << (IsReturnType ? " is not a return type" : " is a return type"); | |
380 } | |
381 } | |
382 | |
383 TEST_F(AsmTypeTest, IsParameterType) { | |
384 Type* test_types[] = { | |
385 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), | |
386 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) | |
387 #undef CREATE | |
388 Function(Type::Int)(Type::Double), | |
389 Function(Type::Int)(Type::DoubleQ), | |
390 Overload(Function(Type::Int)(Type::Double)), | |
391 Function(Type::Int)(Type::Int, Type::Int), | |
392 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), | |
393 Type::FroundType(zone(), Type::Int()), | |
394 }; | |
395 | |
396 std::unordered_set<Type*> parameter_types{ | |
397 Type::Double(), Type::Int(), Type::Float(), | |
398 }; | |
399 | |
400 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { | |
401 const bool IsParameterType = parameter_types.count(test_types[ii]); | |
402 EXPECT_EQ(IsParameterType, test_types[ii]->IsParameterType()) | |
403 << test_types[ii]->Name() | |
404 << (IsParameterType ? " is not a parameter type" | |
405 : " is a parameter type"); | |
406 } | |
407 } | |
408 | |
409 TEST_F(AsmTypeTest, IsComparableType) { | |
410 Type* test_types[] = { | |
411 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), | |
412 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) | |
413 #undef CREATE | |
414 Function(Type::Int)(Type::Double), | |
415 Function(Type::Int)(Type::DoubleQ), | |
416 Overload(Function(Type::Int)(Type::Double)), | |
417 Function(Type::Int)(Type::Int, Type::Int), | |
418 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), | |
419 Type::FroundType(zone(), Type::Int()), | |
420 }; | |
421 | |
422 std::unordered_set<Type*> comparable_types{ | |
423 Type::Double(), Type::Signed(), Type::Unsigned(), Type::Float(), | |
424 }; | |
425 | |
426 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { | |
427 const bool IsComparableType = comparable_types.count(test_types[ii]); | |
428 EXPECT_EQ(IsComparableType, test_types[ii]->IsComparableType()) | |
429 << test_types[ii]->Name() | |
430 << (IsComparableType ? " is not a comparable type" | |
431 : " is a comparable type"); | |
432 } | |
433 } | |
434 | |
435 TEST_F(AsmTypeTest, ElementSizeInBytes) { | |
436 Type* test_types[] = { | |
437 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), | |
438 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) | |
439 #undef CREATE | |
440 Function(Type::Int)(Type::Double), | |
441 Function(Type::Int)(Type::DoubleQ), | |
442 Overload(Function(Type::Int)(Type::Double)), | |
443 Function(Type::Int)(Type::Int, Type::Int), | |
444 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), | |
445 Type::FroundType(zone(), Type::Int()), | |
446 }; | |
447 | |
448 auto ElementSizeInBytesForType = [](Type* type) -> int32_t { | |
449 if (type == Type::Int8Array() || type == Type::Uint8Array()) { | |
450 return 1; | |
451 } | |
452 if (type == Type::Int16Array() || type == Type::Uint16Array()) { | |
453 return 2; | |
454 } | |
455 if (type == Type::Int32Array() || type == Type::Uint32Array() || | |
456 type == Type::Float32Array()) { | |
457 return 4; | |
458 } | |
459 if (type == Type::Float64Array()) { | |
460 return 8; | |
461 } | |
462 return -1; | |
463 }; | |
464 | |
465 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { | |
466 EXPECT_EQ(ElementSizeInBytesForType(test_types[ii]), | |
467 test_types[ii]->ElementSizeInBytes()); | |
468 } | |
469 } | |
470 | |
471 TEST_F(AsmTypeTest, LoadType) { | |
472 Type* test_types[] = { | |
473 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), | |
474 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) | |
475 #undef CREATE | |
476 Function(Type::Int)(Type::Double), | |
477 Function(Type::Int)(Type::DoubleQ), | |
478 Overload(Function(Type::Int)(Type::Double)), | |
479 Function(Type::Int)(Type::Int, Type::Int), | |
480 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), | |
481 Type::FroundType(zone(), Type::Int()), | |
482 }; | |
483 | |
484 auto LoadTypeForType = [](Type* type) -> Type* { | |
485 if (type == Type::Int8Array() || type == Type::Uint8Array() || | |
486 type == Type::Int16Array() || type == Type::Uint16Array() || | |
487 type == Type::Int32Array() || type == Type::Uint32Array()) { | |
488 return Type::Intish(); | |
489 } | |
490 | |
491 if (type == Type::Float32Array()) { | |
492 return Type::FloatQ(); | |
493 } | |
494 | |
495 if (type == Type::Float64Array()) { | |
496 return Type::DoubleQ(); | |
497 } | |
498 | |
499 return Type::None(); | |
500 }; | |
501 | |
502 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { | |
503 EXPECT_EQ(LoadTypeForType(test_types[ii]), test_types[ii]->LoadType()); | |
504 } | |
505 } | |
506 | |
507 TEST_F(AsmTypeTest, StoreType) { | |
508 Type* test_types[] = { | |
509 #define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(), | |
510 FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE) | |
511 #undef CREATE | |
512 Function(Type::Int)(Type::Double), | |
513 Function(Type::Int)(Type::DoubleQ), | |
514 Overload(Function(Type::Int)(Type::Double)), | |
515 Function(Type::Int)(Type::Int, Type::Int), | |
516 Type::MinMaxType(zone(), Type::Int()), Function(Type::Int)(Type::Float), | |
517 Type::FroundType(zone(), Type::Int()), | |
518 }; | |
519 | |
520 auto StoreTypeForType = [](Type* type) -> Type* { | |
521 if (type == Type::Int8Array() || type == Type::Uint8Array() || | |
522 type == Type::Int16Array() || type == Type::Uint16Array() || | |
523 type == Type::Int32Array() || type == Type::Uint32Array()) { | |
524 return Type::Intish(); | |
525 } | |
526 | |
527 if (type == Type::Float32Array()) { | |
528 return Type::FloatishDoubleQ(); | |
529 } | |
530 | |
531 if (type == Type::Float64Array()) { | |
532 return Type::FloatQDoubleQ(); | |
533 } | |
534 | |
535 return Type::None(); | |
536 }; | |
537 | |
538 for (size_t ii = 0; ii < arraysize(test_types); ++ii) { | |
539 EXPECT_EQ(StoreTypeForType(test_types[ii]), test_types[ii]->StoreType()) | |
540 << test_types[ii]->Name(); | |
541 } | |
542 } | |
543 | |
544 } // namespace | |
545 } // namespace wasm | |
546 } // namespace internal | |
547 } // namespace v8 | |
OLD | NEW |