1 // Copyright 2014 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 #ifndef V8_CCTEST_COMPILER_VALUE_HELPER_H_
6 #define V8_CCTEST_COMPILER_VALUE_HELPER_H_
7 
8 #include <stdint.h>
9 
10 #include "src/base/template-utils.h"
11 #include "src/compiler/common-operator.h"
12 #include "src/compiler/node-matchers.h"
13 #include "src/compiler/node.h"
14 #include "src/execution/isolate.h"
15 #include "src/objects/objects.h"
16 #include "test/cctest/cctest.h"
17 
18 namespace v8 {
19 namespace internal {
20 namespace compiler {
21 
22 // A collection of utilities related to numerical and heap values, including
23 // example input values of various types, including int32_t, uint32_t, double,
24 // etc.
25 class ValueHelper {
26  public:
27   Isolate* isolate_;
28 
ValueHelper()29   ValueHelper() : isolate_(CcTest::InitIsolateOnce()) {}
30 
CheckFloat64Constant(double expected,Node * node)31   void CheckFloat64Constant(double expected, Node* node) {
32     CHECK_EQ(IrOpcode::kFloat64Constant, node->opcode());
33     CHECK_EQ(expected, OpParameter<double>(node->op()));
34   }
35 
CheckNumberConstant(double expected,Node * node)36   void CheckNumberConstant(double expected, Node* node) {
37     CHECK_EQ(IrOpcode::kNumberConstant, node->opcode());
38     CHECK_EQ(expected, OpParameter<double>(node->op()));
39   }
40 
CheckInt32Constant(int32_t expected,Node * node)41   void CheckInt32Constant(int32_t expected, Node* node) {
42     CHECK_EQ(IrOpcode::kInt32Constant, node->opcode());
43     CHECK_EQ(expected, OpParameter<int32_t>(node->op()));
44   }
45 
CheckUint32Constant(int32_t expected,Node * node)46   void CheckUint32Constant(int32_t expected, Node* node) {
47     CHECK_EQ(IrOpcode::kInt32Constant, node->opcode());
48     CHECK_EQ(expected, OpParameter<int32_t>(node->op()));
49   }
50 
CheckHeapConstant(HeapObject expected,Node * node)51   void CheckHeapConstant(HeapObject expected, Node* node) {
52     CHECK_EQ(IrOpcode::kHeapConstant, node->opcode());
53     CHECK_EQ(expected, *HeapConstantOf(node->op()));
54   }
55 
56   static constexpr float float32_array[] = {
57       -std::numeric_limits<float>::infinity(),
58       -2.70497e+38f,
59       -1.4698e+37f,
60       -1.22813e+35f,
61       -1.20555e+35f,
62       -1.34584e+34f,
63       -1.0079e+32f,
64       -6.49364e+26f,
65       -3.06077e+25f,
66       -1.46821e+25f,
67       -1.17658e+23f,
68       -1.9617e+22f,
69       -2.7357e+20f,
70       -9223372036854775808.0f,  // INT64_MIN
71       -1.48708e+13f,
72       -1.89633e+12f,
73       -4.66622e+11f,
74       -2.22581e+11f,
75       -1.45381e+10f,
76       -2147483904.0f,  // First float32 after INT32_MIN
77       -2147483648.0f,  // INT32_MIN
78       -2147483520.0f,  // Last float32 before INT32_MIN
79       -1.3956e+09f,
80       -1.32951e+09f,
81       -1.30721e+09f,
82       -1.19756e+09f,
83       -9.26822e+08f,
84       -6.35647e+08f,
85       -4.00037e+08f,
86       -1.81227e+08f,
87       -5.09256e+07f,
88       -964300.0f,
89       -192446.0f,
90       -28455.0f,
91       -27194.0f,
92       -26401.0f,
93       -20575.0f,
94       -17069.0f,
95       -9167.0f,
96       -960.178f,
97       -113.0f,
98       -62.0f,
99       -15.0f,
100       -7.0f,
101       -1.0f,
102       -0.0256635f,
103       -4.60374e-07f,
104       -3.63759e-10f,
105       -4.30175e-14f,
106       -5.27385e-15f,
107       -1.5707963267948966f,
108       -1.48084e-15f,
109       -2.220446049250313e-16f,
110       -1.05755e-19f,
111       -3.2995e-21f,
112       -1.67354e-23f,
113       -1.11885e-23f,
114       -1.78506e-30f,
115       -5.07594e-31f,
116       -3.65799e-31f,
117       -1.43718e-34f,
118       -1.27126e-38f,
119       -0.0f,
120       0.0f,
121       1.17549e-38f,
122       1.56657e-37f,
123       4.08512e-29f,
124       3.31357e-28f,
125       6.25073e-22f,
126       4.1723e-13f,
127       1.44343e-09f,
128       1.5707963267948966f,
129       5.27004e-08f,
130       9.48298e-08f,
131       5.57888e-07f,
132       4.89988e-05f,
133       0.244326f,
134       1.0f,
135       12.4895f,
136       19.0f,
137       47.0f,
138       106.0f,
139       538.324f,
140       564.536f,
141       819.124f,
142       7048.0f,
143       12611.0f,
144       19878.0f,
145       20309.0f,
146       797056.0f,
147       1.77219e+09f,
148       2147483648.0f,  // INT32_MAX + 1
149       4294967296.0f,  // UINT32_MAX + 1
150       1.51116e+11f,
151       4.18193e+13f,
152       3.59167e+16f,
153       9223372036854775808.0f,   // INT64_MAX + 1
154       18446744073709551616.0f,  // UINT64_MAX + 1
155       3.38211e+19f,
156       2.67488e+20f,
157       1.78831e+21f,
158       9.20914e+21f,
159       8.35654e+23f,
160       1.4495e+24f,
161       5.94015e+25f,
162       4.43608e+30f,
163       2.44502e+33f,
164       2.61152e+33f,
165       1.38178e+37f,
166       1.71306e+37f,
167       3.31899e+38f,
168       3.40282e+38f,
169       std::numeric_limits<float>::infinity(),
170       std::numeric_limits<float>::quiet_NaN(),
171       -std::numeric_limits<float>::quiet_NaN()};
172 
float32_vector()173   static constexpr base::Vector<const float> float32_vector() {
174     return base::ArrayVector(float32_array);
175   }
176 
177   static constexpr double float64_array[] = {
178       -2e66,
179       -2.220446049250313e-16,
180       -9223373136366403584.0,
181       -9223372036854775808.0,  // INT64_MIN
182       -2147483649.5,
183       -2147483648.25,
184       -2147483648.0,
185       -2147483647.875,
186       -2147483647.125,
187       -2147483647.0,
188       -999.75,
189       -2e66,
190       -1.75,
191       -1.5707963267948966,
192       -1.0,
193       -0.5,
194       -0.0,
195       0.0,
196       3e-88,
197       0.125,
198       0.25,
199       0.375,
200       0.5,
201       1.0,
202       1.17549e-38,
203       1.56657e-37,
204       1.0000001,
205       1.25,
206       1.5707963267948966,
207       2,
208       3.1e7,
209       5.125,
210       6.25,
211       888,
212       982983.25,
213       2147483647.0,
214       2147483647.375,
215       2147483647.75,
216       2147483648.0,
217       2147483648.25,
218       2147483649.25,
219       9223372036854775808.0,  // INT64_MAX + 1
220       9223373136366403584.0,
221       18446744073709551616.0,  // UINT64_MAX + 1
222       2e66,
223       V8_INFINITY,
224       -V8_INFINITY,
225       std::numeric_limits<double>::quiet_NaN(),
226       -std::numeric_limits<double>::quiet_NaN()};
227 
float64_vector()228   static constexpr base::Vector<const double> float64_vector() {
229     return base::ArrayVector(float64_array);
230   }
231 
232   static constexpr uint32_t uint32_array[] = {
233       0x00000000, 0x00000001, 0xFFFFFFFF, 0x1B09788B, 0x04C5FCE8, 0xCC0DE5BF,
234       // This row is useful for testing lea optimizations on intel.
235       0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000008, 0x00000009,
236       0x273A798E, 0x187937A3, 0xECE3AF83, 0x5495A16B, 0x0B668ECC, 0x11223344,
237       0x0000009E, 0x00000043, 0x0000AF73, 0x0000116B, 0x00658ECC, 0x002B3B4C,
238       0x88776655, 0x70000000, 0x07200000, 0x7FFFFFFF, 0x56123761, 0x7FFFFF00,
239       0x761C4761, 0x80000000, 0x88888888, 0xA0000000, 0xDDDDDDDD, 0xE0000000,
240       0xEEEEEEEE, 0xFFFFFFFD, 0xF0000000, 0x007FFFFF, 0x003FFFFF, 0x001FFFFF,
241       0x000FFFFF, 0x0007FFFF, 0x0003FFFF, 0x0001FFFF, 0x0000FFFF, 0x00007FFF,
242       0x00003FFF, 0x00001FFF, 0x00000FFF, 0x000007FF, 0x000003FF, 0x000001FF,
243       // Bit pattern of a quiet NaN and signaling NaN, with or without
244       // additional payload.
245       0x7FC00000, 0x7F800000, 0x7FFFFFFF, 0x7F876543};
246 
uint32_vector()247   static constexpr base::Vector<const uint32_t> uint32_vector() {
248     return base::ArrayVector(uint32_array);
249   }
250 
int32_vector()251   static base::Vector<const int32_t> int32_vector() {
252     return base::Vector<const int32_t>::cast(uint32_vector());
253   }
254 
255   static constexpr uint64_t uint64_array[] = {
256       0x00000000, 0x00000001, 0xFFFFFFFF, 0x1B09788B, 0x04C5FCE8, 0xCC0DE5BF,
257       0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000008, 0x00000009,
258       0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFD,
259       0x0000000000000000, 0x0000000100000000, 0xFFFFFFFF00000000,
260       0x1B09788B00000000, 0x04C5FCE800000000, 0xCC0DE5BF00000000,
261       0x0000000200000000, 0x0000000300000000, 0x0000000400000000,
262       0x0000000500000000, 0x0000000800000000, 0x0000000900000000,
263       0x273A798E187937A3, 0xECE3AF835495A16B, 0x0B668ECC11223344, 0x0000009E,
264       0x00000043, 0x0000AF73, 0x0000116B, 0x00658ECC, 0x002B3B4C, 0x88776655,
265       0x70000000, 0x07200000, 0x7FFFFFFF, 0x56123761, 0x7FFFFF00,
266       0x761C4761EEEEEEEE, 0x80000000EEEEEEEE, 0x88888888DDDDDDDD,
267       0xA0000000DDDDDDDD, 0xDDDDDDDDAAAAAAAA, 0xE0000000AAAAAAAA,
268       0xEEEEEEEEEEEEEEEE, 0xFFFFFFFDEEEEEEEE, 0xF0000000DDDDDDDD,
269       0x007FFFFFDDDDDDDD, 0x003FFFFFAAAAAAAA, 0x001FFFFFAAAAAAAA, 0x000FFFFF,
270       0x0007FFFF, 0x0003FFFF, 0x0001FFFF, 0x0000FFFF, 0x00007FFF, 0x00003FFF,
271       0x00001FFF, 0x00000FFF, 0x000007FF, 0x000003FF, 0x000001FF,
272       0x00003FFFFFFFFFFF, 0x00001FFFFFFFFFFF, 0x00000FFFFFFFFFFF,
273       0x000007FFFFFFFFFF, 0x000003FFFFFFFFFF, 0x000001FFFFFFFFFF,
274       0x8000008000000000, 0x8000008000000001, 0x8000000000000400,
275       0x8000000000000401, 0x0000000000000020,
276       0x8000000000000000,  // int64_t min
277       0x7FFFFFFFFFFFFFFF,  // int64_t max
278       // Bit pattern of a quiet NaN and signaling NaN, with or without
279       // additional payload.
280       0x7FF8000000000000, 0x7FF0000000000000, 0x7FF8123456789ABC,
281       0x7FF7654321FEDCBA};
282 
uint64_vector()283   static constexpr base::Vector<const uint64_t> uint64_vector() {
284     return base::ArrayVector(uint64_array);
285   }
286 
int64_vector()287   static base::Vector<const int64_t> int64_vector() {
288     return base::Vector<const int64_t>::cast(uint64_vector());
289   }
290 
291   static constexpr int16_t int16_array[] = {
292       0, 1, 2, INT16_MAX - 1, INT16_MAX, INT16_MIN, INT16_MIN + 1, -2, -1};
293 
int16_vector()294   static constexpr base::Vector<const int16_t> int16_vector() {
295     return base::ArrayVector(int16_array);
296   }
297 
uint16_vector()298   static base::Vector<const uint16_t> uint16_vector() {
299     return base::Vector<const uint16_t>::cast(int16_vector());
300   }
301 
302   static constexpr int8_t int8_array[] = {
303       0, 1, 2, INT8_MAX - 1, INT8_MAX, INT8_MIN, INT8_MIN + 1, -2, -1};
304 
int8_vector()305   static constexpr base::Vector<const int8_t> int8_vector() {
306     return base::ArrayVector(int8_array);
307   }
308 
uint8_vector()309   static base::Vector<const uint8_t> uint8_vector() {
310     return base::Vector<const uint8_t>::cast(base::ArrayVector(int8_array));
311   }
312 
313   static constexpr uint32_t ror_array[31] = {
314       1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16,
315       17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
316 
ror_vector()317   static constexpr base::Vector<const uint32_t> ror_vector() {
318     return base::ArrayVector(ror_array);
319   }
320 
321   template <typename T>
322   static inline base::Vector<const T> GetVector();
323 };
324 
325 template <>
GetVector()326 inline base::Vector<const int8_t> ValueHelper::GetVector() {
327   return int8_vector();
328 }
329 
330 template <>
GetVector()331 inline base::Vector<const uint8_t> ValueHelper::GetVector() {
332   return uint8_vector();
333 }
334 
335 template <>
GetVector()336 inline base::Vector<const int16_t> ValueHelper::GetVector() {
337   return int16_vector();
338 }
339 
340 template <>
GetVector()341 inline base::Vector<const uint16_t> ValueHelper::GetVector() {
342   return uint16_vector();
343 }
344 
345 template <>
GetVector()346 inline base::Vector<const int32_t> ValueHelper::GetVector() {
347   return int32_vector();
348 }
349 
350 template <>
GetVector()351 inline base::Vector<const uint32_t> ValueHelper::GetVector() {
352   return uint32_vector();
353 }
354 
355 template <>
GetVector()356 inline base::Vector<const int64_t> ValueHelper::GetVector() {
357   return int64_vector();
358 }
359 
360 template <>
GetVector()361 inline base::Vector<const float> ValueHelper::GetVector() {
362   return float32_vector();
363 }
364 
365 template <>
GetVector()366 inline base::Vector<const double> ValueHelper::GetVector() {
367   return float64_vector();
368 }
369 
370 // Helper macros that can be used in FOR_INT32_INPUTS(i) { ... i ... }
371 #define FOR_INPUTS(ctype, itype, var) \
372   for (ctype var : ::v8::internal::compiler::ValueHelper::itype##_vector())
373 
374 #define FOR_INT32_INPUTS(var) FOR_INPUTS(int32_t, int32, var)
375 #define FOR_UINT32_INPUTS(var) FOR_INPUTS(uint32_t, uint32, var)
376 #define FOR_INT16_INPUTS(var) FOR_INPUTS(int16_t, int16, var)
377 #define FOR_UINT16_INPUTS(var) FOR_INPUTS(uint16_t, uint16, var)
378 #define FOR_INT8_INPUTS(var) FOR_INPUTS(int8_t, int8, var)
379 #define FOR_UINT8_INPUTS(var) FOR_INPUTS(uint8_t, uint8, var)
380 #define FOR_INT64_INPUTS(var) FOR_INPUTS(int64_t, int64, var)
381 #define FOR_UINT64_INPUTS(var) FOR_INPUTS(uint64_t, uint64, var)
382 #define FOR_FLOAT32_INPUTS(var) FOR_INPUTS(float, float32, var)
383 #define FOR_FLOAT64_INPUTS(var) FOR_INPUTS(double, float64, var)
384 
385 #define FOR_INT32_SHIFTS(var) for (int32_t var = 0; var < 32; var++)
386 
387 #define FOR_UINT32_SHIFTS(var) for (uint32_t var = 0; var < 32; var++)
388 
389 template <typename type>
390 struct FloatCompareWrapper {
391   type value;
FloatCompareWrapperFloatCompareWrapper392   explicit FloatCompareWrapper(type x) : value(x) {}
393   bool operator==(FloatCompareWrapper<type> const& other) const {
394     return std::isnan(value)
395                ? std::isnan(other.value)
396                : value == other.value &&
397                      std::signbit(value) == std::signbit(other.value);
398   }
399 };
400 
401 template <typename type>
402 std::ostream& operator<<(std::ostream& out, FloatCompareWrapper<type> wrapper) {
403   uint8_t bytes[sizeof(type)];
404   memcpy(bytes, &wrapper.value, sizeof(type));
405   out << wrapper.value << " (0x";
406   const char* kHexDigits = "0123456789ABCDEF";
407   for (unsigned i = 0; i < sizeof(type); ++i) {
408     out << kHexDigits[bytes[i] >> 4] << kHexDigits[bytes[i] & 15];
409   }
410   return out << ")";
411 }
412 
413 #define CHECK_FLOAT_EQ(lhs, rhs)                                               \
414   do {                                                                         \
415     using FloatWrapper = ::v8::internal::compiler::FloatCompareWrapper<float>; \
416     CHECK_EQ(FloatWrapper(lhs), FloatWrapper(rhs));                            \
417   } while (false)
418 
419 #define CHECK_DOUBLE_EQ(lhs, rhs)                              \
420   do {                                                         \
421     using DoubleWrapper =                                      \
422         ::v8::internal::compiler::FloatCompareWrapper<double>; \
423     CHECK_EQ(DoubleWrapper(lhs), DoubleWrapper(rhs));          \
424   } while (false)
425 
426 }  // namespace compiler
427 }  // namespace internal
428 }  // namespace v8
429 
430 #endif  // V8_CCTEST_COMPILER_VALUE_HELPER_H_
431