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 |