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/compiler/common-operator.h"
11 #include "src/compiler/node.h"
12 #include "src/compiler/node-matchers.h"
13 #include "src/isolate.h"
14 #include "src/objects.h"
15 #include "test/cctest/cctest.h"
16
17 namespace v8 {
18 namespace internal {
19 namespace compiler {
20
21 // A collection of utilities related to numerical and heap values, including
22 // example input values of various types, including int32_t, uint32_t, double,
23 // etc.
24 class ValueHelper {
25 public:
26 Isolate* isolate_;
27
ValueHelper()28 ValueHelper() : isolate_(CcTest::InitIsolateOnce()) {}
29
CheckFloat64Constant(double expected,Node * node)30 void CheckFloat64Constant(double expected, Node* node) {
31 CHECK_EQ(IrOpcode::kFloat64Constant, node->opcode());
32 CHECK_EQ(expected, OpParameter<double>(node));
33 }
34
CheckNumberConstant(double expected,Node * node)35 void CheckNumberConstant(double expected, Node* node) {
36 CHECK_EQ(IrOpcode::kNumberConstant, node->opcode());
37 CHECK_EQ(expected, OpParameter<double>(node));
38 }
39
CheckInt32Constant(int32_t expected,Node * node)40 void CheckInt32Constant(int32_t expected, Node* node) {
41 CHECK_EQ(IrOpcode::kInt32Constant, node->opcode());
42 CHECK_EQ(expected, OpParameter<int32_t>(node));
43 }
44
CheckUint32Constant(int32_t expected,Node * node)45 void CheckUint32Constant(int32_t expected, Node* node) {
46 CHECK_EQ(IrOpcode::kInt32Constant, node->opcode());
47 CHECK_EQ(expected, OpParameter<int32_t>(node));
48 }
49
CheckHeapConstant(HeapObject * expected,Node * node)50 void CheckHeapConstant(HeapObject* expected, Node* node) {
51 CHECK_EQ(IrOpcode::kHeapConstant, node->opcode());
52 CHECK_EQ(expected, *OpParameter<Handle<HeapObject>>(node));
53 }
54
CheckTrue(Node * node)55 void CheckTrue(Node* node) {
56 CheckHeapConstant(isolate_->heap()->true_value(), node);
57 }
58
CheckFalse(Node * node)59 void CheckFalse(Node* node) {
60 CheckHeapConstant(isolate_->heap()->false_value(), node);
61 }
62
float32_vector()63 static std::vector<float> float32_vector() {
64 static const float nan = std::numeric_limits<float>::quiet_NaN();
65 static const float kValues[] = {
66 -std::numeric_limits<float>::infinity(),
67 -2.70497e+38f,
68 -1.4698e+37f,
69 -1.22813e+35f,
70 -1.20555e+35f,
71 -1.34584e+34f,
72 -1.0079e+32f,
73 -6.49364e+26f,
74 -3.06077e+25f,
75 -1.46821e+25f,
76 -1.17658e+23f,
77 -1.9617e+22f,
78 -2.7357e+20f,
79 -9223372036854775808.0f, // INT64_MIN
80 -1.48708e+13f,
81 -1.89633e+12f,
82 -4.66622e+11f,
83 -2.22581e+11f,
84 -1.45381e+10f,
85 -1.3956e+09f,
86 -1.32951e+09f,
87 -1.30721e+09f,
88 -1.19756e+09f,
89 -9.26822e+08f,
90 -6.35647e+08f,
91 -4.00037e+08f,
92 -1.81227e+08f,
93 -5.09256e+07f,
94 -964300.0f,
95 -192446.0f,
96 -28455.0f,
97 -27194.0f,
98 -26401.0f,
99 -20575.0f,
100 -17069.0f,
101 -9167.0f,
102 -960.178f,
103 -113.0f,
104 -62.0f,
105 -15.0f,
106 -7.0f,
107 -1.0f,
108 -0.0256635f,
109 -4.60374e-07f,
110 -3.63759e-10f,
111 -4.30175e-14f,
112 -5.27385e-15f,
113 -1.5707963267948966f,
114 -1.48084e-15f,
115 -2.220446049250313e-16f,
116 -1.05755e-19f,
117 -3.2995e-21f,
118 -1.67354e-23f,
119 -1.11885e-23f,
120 -1.78506e-30f,
121 -5.07594e-31f,
122 -3.65799e-31f,
123 -1.43718e-34f,
124 -1.27126e-38f,
125 -0.0f,
126 0.0f,
127 1.17549e-38f,
128 1.56657e-37f,
129 4.08512e-29f,
130 3.31357e-28f,
131 6.25073e-22f,
132 4.1723e-13f,
133 1.44343e-09f,
134 1.5707963267948966f,
135 5.27004e-08f,
136 9.48298e-08f,
137 5.57888e-07f,
138 4.89988e-05f,
139 0.244326f,
140 1.0f,
141 12.4895f,
142 19.0f,
143 47.0f,
144 106.0f,
145 538.324f,
146 564.536f,
147 819.124f,
148 7048.0f,
149 12611.0f,
150 19878.0f,
151 20309.0f,
152 797056.0f,
153 1.77219e+09f,
154 1.51116e+11f,
155 4.18193e+13f,
156 3.59167e+16f,
157 9223372036854775807.0f, // INT64_MAX
158 18446744073709551615.0f, // UINT64_MAX
159 3.38211e+19f,
160 2.67488e+20f,
161 1.78831e+21f,
162 9.20914e+21f,
163 8.35654e+23f,
164 1.4495e+24f,
165 5.94015e+25f,
166 4.43608e+30f,
167 2.44502e+33f,
168 2.61152e+33f,
169 1.38178e+37f,
170 1.71306e+37f,
171 3.31899e+38f,
172 3.40282e+38f,
173 std::numeric_limits<float>::infinity(),
174 nan,
175 -nan,
176 };
177 return std::vector<float>(&kValues[0], &kValues[arraysize(kValues)]);
178 }
179
float64_vector()180 static std::vector<double> float64_vector() {
181 static const double nan = std::numeric_limits<double>::quiet_NaN();
182 static const double values[] = {-2e66,
183 -2.220446049250313e-16,
184 -9223373136366403584.0,
185 -9223372036854775808.0, // INT64_MIN
186 -2147483649.5,
187 -2147483648.25,
188 -2147483648.0,
189 -2147483647.875,
190 -2147483647.125,
191 -2147483647.0,
192 -999.75,
193 -2e66,
194 -1.75,
195 -1.5707963267948966,
196 -1.0,
197 -0.5,
198 -0.0,
199 0.0,
200 3e-88,
201 0.125,
202 0.25,
203 0.375,
204 0.5,
205 1.0,
206 1.17549e-38,
207 1.56657e-37,
208 1.0000001,
209 1.25,
210 1.5707963267948966,
211 2,
212 3.1e7,
213 5.125,
214 6.25,
215 888,
216 982983.25,
217 2147483647.0,
218 2147483647.375,
219 2147483647.75,
220 2147483648.0,
221 2147483648.25,
222 2147483649.25,
223 9223372036854775807.0, // INT64_MAX
224 9223373136366403584.0,
225 18446744073709551615.0, // UINT64_MAX
226 2e66,
227 V8_INFINITY,
228 -V8_INFINITY,
229 -nan,
230 nan};
231 return std::vector<double>(&values[0], &values[arraysize(values)]);
232 }
233
int32_vector()234 static const std::vector<int32_t> int32_vector() {
235 std::vector<uint32_t> values = uint32_vector();
236 return std::vector<int32_t>(values.begin(), values.end());
237 }
238
uint32_vector()239 static const std::vector<uint32_t> uint32_vector() {
240 static const uint32_t kValues[] = {
241 0x00000000, 0x00000001, 0xffffffff, 0x1b09788b, 0x04c5fce8, 0xcc0de5bf,
242 // This row is useful for testing lea optimizations on intel.
243 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000008, 0x00000009,
244 0x273a798e, 0x187937a3, 0xece3af83, 0x5495a16b, 0x0b668ecc, 0x11223344,
245 0x0000009e, 0x00000043, 0x0000af73, 0x0000116b, 0x00658ecc, 0x002b3b4c,
246 0x88776655, 0x70000000, 0x07200000, 0x7fffffff, 0x56123761, 0x7fffff00,
247 0x761c4761, 0x80000000, 0x88888888, 0xa0000000, 0xdddddddd, 0xe0000000,
248 0xeeeeeeee, 0xfffffffd, 0xf0000000, 0x007fffff, 0x003fffff, 0x001fffff,
249 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff, 0x0000ffff, 0x00007fff,
250 0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff};
251 return std::vector<uint32_t>(&kValues[0], &kValues[arraysize(kValues)]);
252 }
253
int64_vector()254 static const std::vector<int64_t> int64_vector() {
255 std::vector<uint64_t> values = uint64_vector();
256 return std::vector<int64_t>(values.begin(), values.end());
257 }
258
uint64_vector()259 static const std::vector<uint64_t> uint64_vector() {
260 static const uint64_t kValues[] = {
261 0x00000000, 0x00000001, 0xffffffff,
262 0x1b09788b, 0x04c5fce8, 0xcc0de5bf,
263 0x00000002, 0x00000003, 0x00000004,
264 0x00000005, 0x00000008, 0x00000009,
265 0xffffffffffffffff, 0xfffffffffffffffe, 0xfffffffffffffffd,
266 0x0000000000000000, 0x0000000100000000, 0xffffffff00000000,
267 0x1b09788b00000000, 0x04c5fce800000000, 0xcc0de5bf00000000,
268 0x0000000200000000, 0x0000000300000000, 0x0000000400000000,
269 0x0000000500000000, 0x0000000800000000, 0x0000000900000000,
270 0x273a798e187937a3, 0xece3af835495a16b, 0x0b668ecc11223344,
271 0x0000009e, 0x00000043, 0x0000af73,
272 0x0000116b, 0x00658ecc, 0x002b3b4c,
273 0x88776655, 0x70000000, 0x07200000,
274 0x7fffffff, 0x56123761, 0x7fffff00,
275 0x761c4761eeeeeeee, 0x80000000eeeeeeee, 0x88888888dddddddd,
276 0xa0000000dddddddd, 0xddddddddaaaaaaaa, 0xe0000000aaaaaaaa,
277 0xeeeeeeeeeeeeeeee, 0xfffffffdeeeeeeee, 0xf0000000dddddddd,
278 0x007fffffdddddddd, 0x003fffffaaaaaaaa, 0x001fffffaaaaaaaa,
279 0x000fffff, 0x0007ffff, 0x0003ffff,
280 0x0001ffff, 0x0000ffff, 0x00007fff,
281 0x00003fff, 0x00001fff, 0x00000fff,
282 0x000007ff, 0x000003ff, 0x000001ff,
283 0x00003fffffffffff, 0x00001fffffffffff, 0x00000fffffffffff,
284 0x000007ffffffffff, 0x000003ffffffffff, 0x000001ffffffffff,
285 0x8000008000000000, 0x8000008000000001, 0x8000000000000400,
286 0x8000000000000401, 0x0000000000000020};
287 return std::vector<uint64_t>(&kValues[0], &kValues[arraysize(kValues)]);
288 }
289
290 static const std::vector<double> nan_vector(size_t limit = 0) {
291 static const double nan = std::numeric_limits<double>::quiet_NaN();
292 static const double values[] = {-nan, -V8_INFINITY * -0.0,
293 -V8_INFINITY * 0.0, V8_INFINITY * -0.0,
294 V8_INFINITY * 0.0, nan};
295 return std::vector<double>(&values[0], &values[arraysize(values)]);
296 }
297
ror_vector()298 static const std::vector<uint32_t> ror_vector() {
299 static const uint32_t kValues[31] = {
300 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
301 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
302 return std::vector<uint32_t>(&kValues[0], &kValues[arraysize(kValues)]);
303 }
304 };
305
306 // Helper macros that can be used in FOR_INT32_INPUTS(i) { ... *i ... }
307 // Watch out, these macros aren't hygenic; they pollute your scope. Thanks STL.
308 #define FOR_INPUTS(ctype, itype, var) \
309 std::vector<ctype> var##_vec = ValueHelper::itype##_vector(); \
310 for (std::vector<ctype>::iterator var = var##_vec.begin(); \
311 var != var##_vec.end(); ++var)
312
313 #define FOR_INT32_INPUTS(var) FOR_INPUTS(int32_t, int32, var)
314 #define FOR_UINT32_INPUTS(var) FOR_INPUTS(uint32_t, uint32, var)
315 #define FOR_INT64_INPUTS(var) FOR_INPUTS(int64_t, int64, var)
316 #define FOR_UINT64_INPUTS(var) FOR_INPUTS(uint64_t, uint64, var)
317 #define FOR_FLOAT32_INPUTS(var) FOR_INPUTS(float, float32, var)
318 #define FOR_FLOAT64_INPUTS(var) FOR_INPUTS(double, float64, var)
319
320 #define FOR_INT32_SHIFTS(var) for (int32_t var = 0; var < 32; var++)
321
322 #define FOR_UINT32_SHIFTS(var) for (uint32_t var = 0; var < 32; var++)
323
324 // TODO(bmeurer): Drop this crap once we switch to GTest/Gmock.
CheckFloatEq(volatile float x,volatile float y)325 static inline void CheckFloatEq(volatile float x, volatile float y) {
326 if (std::isnan(x)) {
327 CHECK(std::isnan(y));
328 } else {
329 CHECK_EQ(x, y);
330 }
331 }
332
333 #define CHECK_FLOAT_EQ(lhs, rhs) \
334 do { \
335 volatile float tmp = lhs; \
336 CheckFloatEq(tmp, rhs); \
337 } while (0)
338
CheckDoubleEq(volatile double x,volatile double y)339 static inline void CheckDoubleEq(volatile double x, volatile double y) {
340 if (std::isnan(x)) {
341 CHECK(std::isnan(y));
342 } else {
343 CHECK_EQ(x, y);
344 }
345 }
346
347 #define CHECK_DOUBLE_EQ(lhs, rhs) \
348 do { \
349 volatile double tmp = lhs; \
350 CheckDoubleEq(tmp, rhs); \
351 } while (0)
352
353 } // namespace compiler
354 } // namespace internal
355 } // namespace v8
356
357 #endif // V8_CCTEST_COMPILER_VALUE_HELPER_H_
358