blob: fae75008c70c06892aea0f8909afea1a94995973 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2015 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/v8.h"
6
7#include "src/ast/ast.h"
8#include "src/ast/ast-expression-visitor.h"
9#include "src/ast/scopes.h"
10#include "src/parsing/parser.h"
11#include "src/parsing/rewriter.h"
12#include "src/type-cache.h"
13#include "src/typing-asm.h"
14#include "test/cctest/cctest.h"
15#include "test/cctest/expression-type-collector.h"
16#include "test/cctest/expression-type-collector-macros.h"
17
18// Macros for function types.
19#define FUNC_V_TYPE Bounds(Type::Function(Type::Undefined(zone), zone))
20#define FUNC_I_TYPE Bounds(Type::Function(cache.kAsmSigned, zone))
21#define FUNC_F_TYPE Bounds(Type::Function(cache.kAsmFloat, zone))
22#define FUNC_D_TYPE Bounds(Type::Function(cache.kAsmDouble, zone))
23#define FUNC_D2D_TYPE \
24 Bounds(Type::Function(cache.kAsmDouble, cache.kAsmDouble, zone))
25#define FUNC_N2F_TYPE \
26 Bounds(Type::Function(cache.kAsmFloat, Type::Number(zone), zone))
27#define FUNC_I2I_TYPE \
28 Bounds(Type::Function(cache.kAsmSigned, cache.kAsmInt, zone))
29#define FUNC_II2D_TYPE \
30 Bounds(Type::Function(cache.kAsmDouble, cache.kAsmInt, cache.kAsmInt, zone))
31#define FUNC_II2I_TYPE \
32 Bounds(Type::Function(cache.kAsmSigned, cache.kAsmInt, cache.kAsmInt, zone))
33#define FUNC_DD2D_TYPE \
34 Bounds(Type::Function(cache.kAsmDouble, cache.kAsmDouble, cache.kAsmDouble, \
35 zone))
36#define FUNC_NN2N_TYPE \
37 Bounds(Type::Function(Type::Number(zone), Type::Number(zone), \
38 Type::Number(zone), zone))
39#define FUNC_N2N_TYPE \
40 Bounds(Type::Function(Type::Number(zone), Type::Number(zone), zone))
41
42// Macros for array types.
43#define FLOAT64_ARRAY_TYPE Bounds(Type::Array(cache.kAsmDouble, zone))
44#define FUNC_I2I_ARRAY_TYPE \
45 Bounds(Type::Array(Type::Function(cache.kAsmSigned, cache.kAsmInt, zone), \
46 zone))
47
48using namespace v8::internal;
49
50namespace {
51
52std::string Validate(Zone* zone, const char* source,
53 ZoneVector<ExpressionTypeEntry>* types) {
54 i::Isolate* isolate = CcTest::i_isolate();
55 i::Factory* factory = isolate->factory();
56
57 i::Handle<i::String> source_code =
58 factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked();
59
60 i::Handle<i::Script> script = factory->NewScript(source_code);
61
62 i::ParseInfo info(zone, script);
63 i::Parser parser(&info);
64 parser.set_allow_harmony_sloppy(true);
65 info.set_global();
66 info.set_lazy(false);
67 info.set_allow_lazy_parsing(false);
68 info.set_toplevel(true);
69
70 CHECK(i::Compiler::ParseAndAnalyze(&info));
71
72 FunctionLiteral* root =
73 info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun();
74 AsmTyper typer(isolate, zone, *script, root);
75 if (typer.Validate()) {
76 ExpressionTypeCollector(isolate, root, types).Run();
77 return "";
78 } else {
79 return typer.error_message();
80 }
81}
82
83} // namespace
84
85
86TEST(ValidateMinimum) {
87 const char test_function[] =
88 "function GeometricMean(stdlib, foreign, buffer) {\n"
89 " \"use asm\";\n"
90 "\n"
91 " var exp = stdlib.Math.exp;\n"
92 " var log = stdlib.Math.log;\n"
93 " var values = new stdlib.Float64Array(buffer);\n"
94 "\n"
95 " function logSum(start, end) {\n"
96 " start = start|0;\n"
97 " end = end|0;\n"
98 "\n"
99 " var sum = 0.0, p = 0, q = 0;\n"
100 "\n"
101 " // asm.js forces byte addressing of the heap by requiring shifting "
102 "by 3\n"
103 " for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {\n"
104 " sum = sum + +log(values[p>>3]);\n"
105 " }\n"
106 "\n"
107 " return +sum;\n"
108 " }\n"
109 "\n"
110 " function geometricMean(start, end) {\n"
111 " start = start|0;\n"
112 " end = end|0;\n"
113 "\n"
114 " return +exp(+logSum(start, end) / +((end - start)|0));\n"
115 " }\n"
116 "\n"
117 " return { geometricMean: geometricMean };\n"
118 "}\n";
119
120 v8::V8::Initialize();
121 HandleAndZoneScope handles;
122 Zone* zone = handles.main_zone();
123 ZoneVector<ExpressionTypeEntry> types(zone);
124 CHECK_EQ("", Validate(zone, test_function, &types));
125 TypeCache cache;
126
127 CHECK_TYPES_BEGIN {
128 // Module.
129 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
130 // function logSum
131 CHECK_EXPR(FunctionLiteral, FUNC_II2D_TYPE) {
132 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
133 CHECK_VAR(start, Bounds(cache.kAsmInt));
134 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
135 CHECK_VAR(start, Bounds(cache.kAsmInt));
136 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
137 }
138 }
139 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
140 CHECK_VAR(end, Bounds(cache.kAsmInt));
141 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
142 CHECK_VAR(end, Bounds(cache.kAsmInt));
143 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
144 }
145 }
146 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) {
147 CHECK_VAR(sum, Bounds(cache.kAsmDouble));
148 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
149 }
150 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
151 CHECK_VAR(p, Bounds(cache.kAsmInt));
152 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
153 }
154 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
155 CHECK_VAR(q, Bounds(cache.kAsmInt));
156 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
157 }
158 // for (p = start << 3, q = end << 3;
159 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) {
160 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
161 CHECK_VAR(p, Bounds(cache.kAsmInt));
162 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
163 CHECK_VAR(start, Bounds(cache.kAsmInt));
164 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
165 }
166 }
167 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
168 CHECK_VAR(q, Bounds(cache.kAsmInt));
169 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
170 CHECK_VAR(end, Bounds(cache.kAsmInt));
171 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
172 }
173 }
174 }
175 // (p|0) < (q|0);
176 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) {
177 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
178 CHECK_VAR(p, Bounds(cache.kAsmInt));
179 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
180 }
181 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
182 CHECK_VAR(q, Bounds(cache.kAsmInt));
183 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
184 }
185 }
186 // p = (p + 8)|0) {\n"
187 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
188 CHECK_VAR(p, Bounds(cache.kAsmInt));
189 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
190 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) {
191 CHECK_VAR(p, Bounds(cache.kAsmInt));
192 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
193 }
194 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
195 }
196 }
197 // sum = sum + +log(values[p>>3]);
198 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) {
199 CHECK_VAR(sum, Bounds(cache.kAsmDouble));
200 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) {
201 CHECK_VAR(sum, Bounds(cache.kAsmDouble));
202 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) {
203 CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) {
204 CHECK_VAR(log, FUNC_D2D_TYPE);
205 CHECK_EXPR(Property, Bounds(cache.kAsmDouble)) {
206 CHECK_VAR(values, FLOAT64_ARRAY_TYPE);
207 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
208 CHECK_VAR(p, Bounds(cache.kAsmSigned));
209 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
210 }
211 }
212 }
213 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
214 }
215 }
216 }
217 // return +sum;
218 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) {
219 CHECK_VAR(sum, Bounds(cache.kAsmDouble));
220 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
221 }
222 }
223 // function geometricMean
224 CHECK_EXPR(FunctionLiteral, FUNC_II2D_TYPE) {
225 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
226 CHECK_VAR(start, Bounds(cache.kAsmInt));
227 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
228 CHECK_VAR(start, Bounds(cache.kAsmInt));
229 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
230 }
231 }
232 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
233 CHECK_VAR(end, Bounds(cache.kAsmInt));
234 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
235 CHECK_VAR(end, Bounds(cache.kAsmInt));
236 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
237 }
238 }
239 // return +exp(+logSum(start, end) / +((end - start)|0));
240 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) {
241 CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) {
242 CHECK_VAR(exp, FUNC_D2D_TYPE);
243 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) {
244 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) {
245 CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) {
246 CHECK_VAR(logSum, FUNC_II2D_TYPE);
247 CHECK_VAR(start, Bounds(cache.kAsmInt));
248 CHECK_VAR(end, Bounds(cache.kAsmInt));
249 }
250 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
251 }
252 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) {
253 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
254 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) {
255 CHECK_VAR(end, Bounds(cache.kAsmInt));
256 CHECK_VAR(start, Bounds(cache.kAsmInt));
257 }
258 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
259 }
260 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
261 }
262 }
263 }
264 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
265 }
266 }
267 // "use asm";
268 CHECK_EXPR(Literal, Bounds(Type::String(zone)));
269 // var exp = stdlib.Math.exp;
270 CHECK_EXPR(Assignment, FUNC_D2D_TYPE) {
271 CHECK_VAR(exp, FUNC_D2D_TYPE);
272 CHECK_EXPR(Property, FUNC_D2D_TYPE) {
273 CHECK_EXPR(Property, Bounds::Unbounded()) {
274 CHECK_VAR(stdlib, Bounds::Unbounded());
275 CHECK_EXPR(Literal, Bounds::Unbounded());
276 }
277 CHECK_EXPR(Literal, Bounds::Unbounded());
278 }
279 }
280 // var log = stdlib.Math.log;
281 CHECK_EXPR(Assignment, FUNC_D2D_TYPE) {
282 CHECK_VAR(log, FUNC_D2D_TYPE);
283 CHECK_EXPR(Property, FUNC_D2D_TYPE) {
284 CHECK_EXPR(Property, Bounds::Unbounded()) {
285 CHECK_VAR(stdlib, Bounds::Unbounded());
286 CHECK_EXPR(Literal, Bounds::Unbounded());
287 }
288 CHECK_EXPR(Literal, Bounds::Unbounded());
289 }
290 }
291 // var values = new stdlib.Float64Array(buffer);
292 CHECK_EXPR(Assignment, FLOAT64_ARRAY_TYPE) {
293 CHECK_VAR(values, FLOAT64_ARRAY_TYPE);
294 CHECK_EXPR(CallNew, FLOAT64_ARRAY_TYPE) {
295 CHECK_EXPR(Property, Bounds::Unbounded()) {
296 CHECK_VAR(stdlib, Bounds::Unbounded());
297 CHECK_EXPR(Literal, Bounds::Unbounded());
298 }
299 CHECK_VAR(buffer, Bounds::Unbounded());
300 }
301 }
302 // return { geometricMean: geometricMean };
303 CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) {
304 CHECK_VAR(geometricMean, FUNC_II2D_TYPE);
305 }
306 }
307 }
308 CHECK_TYPES_END
309}
310
311
312TEST(MissingUseAsm) {
313 const char test_function[] =
314 "function foo() {\n"
315 " function bar() {}\n"
316 " return { bar: bar };\n"
317 "}\n";
318 v8::V8::Initialize();
319 HandleAndZoneScope handles;
320 Zone* zone = handles.main_zone();
321 ZoneVector<ExpressionTypeEntry> types(zone);
322 CHECK_EQ("asm: line 1: missing \"use asm\"\n",
323 Validate(zone, test_function, &types));
324}
325
326
327TEST(WrongUseAsm) {
328 const char test_function[] =
329 "function foo() {\n"
330 " \"use wasm\"\n"
331 " function bar() {}\n"
332 " return { bar: bar };\n"
333 "}\n";
334 v8::V8::Initialize();
335 HandleAndZoneScope handles;
336 Zone* zone = handles.main_zone();
337 ZoneVector<ExpressionTypeEntry> types(zone);
338 CHECK_EQ("asm: line 1: missing \"use asm\"\n",
339 Validate(zone, test_function, &types));
340}
341
342
343TEST(MissingReturnExports) {
344 const char test_function[] =
345 "function foo() {\n"
346 " \"use asm\"\n"
347 " function bar() {}\n"
348 "}\n";
349 v8::V8::Initialize();
350 HandleAndZoneScope handles;
351 Zone* zone = handles.main_zone();
352 ZoneVector<ExpressionTypeEntry> types(zone);
353 CHECK_EQ("asm: line 2: last statement in module is not a return\n",
354 Validate(zone, test_function, &types));
355}
356
357
358#define HARNESS_STDLIB() \
359 "var Infinity = stdlib.Infinity;\n" \
360 "var NaN = stdlib.NaN;\n" \
361 "var acos = stdlib.Math.acos;\n" \
362 "var asin = stdlib.Math.asin;\n" \
363 "var atan = stdlib.Math.atan;\n" \
364 "var cos = stdlib.Math.cos;\n" \
365 "var sin = stdlib.Math.sin;\n" \
366 "var tan = stdlib.Math.tan;\n" \
367 "var exp = stdlib.Math.exp;\n" \
368 "var log = stdlib.Math.log;\n" \
369 "var ceil = stdlib.Math.ceil;\n" \
370 "var floor = stdlib.Math.floor;\n" \
371 "var sqrt = stdlib.Math.sqrt;\n" \
372 "var min = stdlib.Math.min;\n" \
373 "var max = stdlib.Math.max;\n" \
374 "var atan2 = stdlib.Math.atan2;\n" \
375 "var pow = stdlib.Math.pow;\n" \
376 "var abs = stdlib.Math.abs;\n" \
377 "var imul = stdlib.Math.imul;\n" \
378 "var fround = stdlib.Math.fround;\n" \
379 "var E = stdlib.Math.E;\n" \
380 "var LN10 = stdlib.Math.LN10;\n" \
381 "var LN2 = stdlib.Math.LN2;\n" \
382 "var LOG2E = stdlib.Math.LOG2E;\n" \
383 "var LOG10E = stdlib.Math.LOG10E;\n" \
384 "var PI = stdlib.Math.PI;\n" \
385 "var SQRT1_2 = stdlib.Math.SQRT1_2;\n" \
386 "var SQRT2 = stdlib.Math.SQRT2;\n"
387
388
389#define HARNESS_HEAP() \
390 "var u8 = new stdlib.Uint8Array(buffer);\n" \
391 "var i8 = new stdlib.Int8Array(buffer);\n" \
392 "var u16 = new stdlib.Uint16Array(buffer);\n" \
393 "var i16 = new stdlib.Int16Array(buffer);\n" \
394 "var u32 = new stdlib.Uint32Array(buffer);\n" \
395 "var i32 = new stdlib.Int32Array(buffer);\n" \
396 "var f32 = new stdlib.Float32Array(buffer);\n" \
397 "var f64 = new stdlib.Float64Array(buffer);\n"
398
399
400#define HARNESS_PREAMBLE() \
401 const char test_function[] = \
402 "function Module(stdlib, foreign, buffer) {\n" \
403 "\"use asm\";\n" HARNESS_STDLIB() HARNESS_HEAP()
404
405
406#define HARNESS_POSTAMBLE() \
407 "return { foo: foo };\n" \
408 "}\n";
409
410
411#define CHECK_VAR_MATH_SHORTCUT(name, type) \
412 CHECK_EXPR(Assignment, type) { \
413 CHECK_VAR(name, type); \
414 CHECK_EXPR(Property, type) { \
415 CHECK_EXPR(Property, Bounds::Unbounded()) { \
416 CHECK_VAR(stdlib, Bounds::Unbounded()); \
417 CHECK_EXPR(Literal, Bounds::Unbounded()); \
418 } \
419 CHECK_EXPR(Literal, Bounds::Unbounded()); \
420 } \
421 }
422
423
424#define CHECK_VAR_SHORTCUT(name, type) \
425 CHECK_EXPR(Assignment, type) { \
426 CHECK_VAR(name, type); \
427 CHECK_EXPR(Property, type) { \
428 CHECK_VAR(stdlib, Bounds::Unbounded()); \
429 CHECK_EXPR(Literal, Bounds::Unbounded()); \
430 } \
431 }
432
433
434#define CHECK_VAR_NEW_SHORTCUT(name, type) \
435 CHECK_EXPR(Assignment, type) { \
436 CHECK_VAR(name, type); \
437 CHECK_EXPR(CallNew, type) { \
438 CHECK_EXPR(Property, Bounds::Unbounded()) { \
439 CHECK_VAR(stdlib, Bounds::Unbounded()); \
440 CHECK_EXPR(Literal, Bounds::Unbounded()); \
441 } \
442 CHECK_VAR(buffer, Bounds::Unbounded()); \
443 } \
444 }
445
446
447namespace {
448
449void CheckStdlibShortcuts1(Zone* zone, ZoneVector<ExpressionTypeEntry>& types,
450 size_t& index, int& depth, TypeCache& cache) {
451 // var exp = stdlib.*;
452 CHECK_VAR_SHORTCUT(Infinity, Bounds(cache.kAsmDouble));
453 CHECK_VAR_SHORTCUT(NaN, Bounds(cache.kAsmDouble));
454 // var x = stdlib.Math.x;
455 CHECK_VAR_MATH_SHORTCUT(acos, FUNC_D2D_TYPE);
456 CHECK_VAR_MATH_SHORTCUT(asin, FUNC_D2D_TYPE);
457 CHECK_VAR_MATH_SHORTCUT(atan, FUNC_D2D_TYPE);
458 CHECK_VAR_MATH_SHORTCUT(cos, FUNC_D2D_TYPE);
459 CHECK_VAR_MATH_SHORTCUT(sin, FUNC_D2D_TYPE);
460 CHECK_VAR_MATH_SHORTCUT(tan, FUNC_D2D_TYPE);
461 CHECK_VAR_MATH_SHORTCUT(exp, FUNC_D2D_TYPE);
462 CHECK_VAR_MATH_SHORTCUT(log, FUNC_D2D_TYPE);
463
464 CHECK_VAR_MATH_SHORTCUT(ceil, FUNC_N2N_TYPE);
465 CHECK_VAR_MATH_SHORTCUT(floor, FUNC_N2N_TYPE);
466 CHECK_VAR_MATH_SHORTCUT(sqrt, FUNC_N2N_TYPE);
467
468 CHECK_VAR_MATH_SHORTCUT(min, FUNC_NN2N_TYPE);
469 CHECK_VAR_MATH_SHORTCUT(max, FUNC_NN2N_TYPE);
470
471 CHECK_VAR_MATH_SHORTCUT(atan2, FUNC_DD2D_TYPE);
472 CHECK_VAR_MATH_SHORTCUT(pow, FUNC_DD2D_TYPE);
473
474 CHECK_VAR_MATH_SHORTCUT(abs, FUNC_N2N_TYPE);
475 CHECK_VAR_MATH_SHORTCUT(imul, FUNC_II2I_TYPE);
476 CHECK_VAR_MATH_SHORTCUT(fround, FUNC_N2F_TYPE);
477}
478
479
480void CheckStdlibShortcuts2(Zone* zone, ZoneVector<ExpressionTypeEntry>& types,
481 size_t& index, int& depth, TypeCache& cache) {
482 // var exp = stdlib.Math.*; (D * 12)
483 CHECK_VAR_MATH_SHORTCUT(E, Bounds(cache.kAsmDouble));
484 CHECK_VAR_MATH_SHORTCUT(LN10, Bounds(cache.kAsmDouble));
485 CHECK_VAR_MATH_SHORTCUT(LN2, Bounds(cache.kAsmDouble));
486 CHECK_VAR_MATH_SHORTCUT(LOG2E, Bounds(cache.kAsmDouble));
487 CHECK_VAR_MATH_SHORTCUT(LOG10E, Bounds(cache.kAsmDouble));
488 CHECK_VAR_MATH_SHORTCUT(PI, Bounds(cache.kAsmDouble));
489 CHECK_VAR_MATH_SHORTCUT(SQRT1_2, Bounds(cache.kAsmDouble));
490 CHECK_VAR_MATH_SHORTCUT(SQRT2, Bounds(cache.kAsmDouble));
491 // var values = new stdlib.*Array(buffer);
492 CHECK_VAR_NEW_SHORTCUT(u8, Bounds(cache.kUint8Array));
493 CHECK_VAR_NEW_SHORTCUT(i8, Bounds(cache.kInt8Array));
494 CHECK_VAR_NEW_SHORTCUT(u16, Bounds(cache.kUint16Array));
495 CHECK_VAR_NEW_SHORTCUT(i16, Bounds(cache.kInt16Array));
496 CHECK_VAR_NEW_SHORTCUT(u32, Bounds(cache.kUint32Array));
497 CHECK_VAR_NEW_SHORTCUT(i32, Bounds(cache.kInt32Array));
498 CHECK_VAR_NEW_SHORTCUT(f32, Bounds(cache.kFloat32Array));
499 CHECK_VAR_NEW_SHORTCUT(f64, Bounds(cache.kFloat64Array));
500}
501
502} // namespace
503
504
505#define CHECK_FUNC_TYPES_BEGIN(func) \
506 HARNESS_PREAMBLE() \
507 func "\n" HARNESS_POSTAMBLE(); \
508 \
509 v8::V8::Initialize(); \
510 HandleAndZoneScope handles; \
511 Zone* zone = handles.main_zone(); \
512 ZoneVector<ExpressionTypeEntry> types(zone); \
513 CHECK_EQ("", Validate(zone, test_function, &types)); \
514 TypeCache cache; \
515 \
516 CHECK_TYPES_BEGIN { \
517 /* Module. */ \
518 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
519#define CHECK_FUNC_TYPES_END_1() \
520 /* "use asm"; */ \
521 CHECK_EXPR(Literal, Bounds(Type::String(zone))); \
522 /* stdlib shortcuts. */ \
523 CheckStdlibShortcuts1(zone, types, index, depth, cache); \
524 CheckStdlibShortcuts2(zone, types, index, depth, cache);
525
526
527#define CHECK_FUNC_TYPES_END_2() \
528 /* return { foo: foo }; */ \
529 CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) { \
530 CHECK_VAR(foo, FUNC_V_TYPE); \
531 } \
532 } \
533 } \
534 CHECK_TYPES_END
535
536
537#define CHECK_FUNC_TYPES_END \
538 CHECK_FUNC_TYPES_END_1(); \
539 CHECK_FUNC_TYPES_END_2();
540
541
542#define CHECK_FUNC_ERROR(func, message) \
543 HARNESS_PREAMBLE() \
544 func "\n" HARNESS_POSTAMBLE(); \
545 \
546 v8::V8::Initialize(); \
547 HandleAndZoneScope handles; \
548 Zone* zone = handles.main_zone(); \
549 ZoneVector<ExpressionTypeEntry> types(zone); \
550 CHECK_EQ(message, Validate(zone, test_function, &types));
551
552
553TEST(BareHarness) {
554 CHECK_FUNC_TYPES_BEGIN("function foo() {}") {
555 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {}
556 }
557 CHECK_FUNC_TYPES_END
558}
559
560
561TEST(ReturnVoid) {
562 CHECK_FUNC_TYPES_BEGIN(
563 "function bar() { return; }\n"
564 "function foo() { bar(); }") {
565 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
566 // return undefined;
567 CHECK_EXPR(Literal, Bounds(Type::Undefined(zone)));
568 }
569 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
570 CHECK_EXPR(Call, Bounds(Type::Undefined(zone))) {
571 CHECK_VAR(bar, FUNC_V_TYPE);
572 }
573 }
574 }
575 CHECK_FUNC_TYPES_END
576}
577
578
579TEST(EmptyBody) {
580 CHECK_FUNC_TYPES_BEGIN(
581 "function bar() { }\n"
582 "function foo() { bar(); }") {
583 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE);
584 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
585 CHECK_EXPR(Call, Bounds(Type::Undefined(zone))) {
586 CHECK_VAR(bar, FUNC_V_TYPE);
587 }
588 }
589 }
590 CHECK_FUNC_TYPES_END
591}
592
593
594TEST(DoesNothing) {
595 CHECK_FUNC_TYPES_BEGIN(
596 "function bar() { var x = 1.0; }\n"
597 "function foo() { bar(); }") {
598 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
599 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) {
600 CHECK_VAR(x, Bounds(cache.kAsmDouble));
601 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
602 }
603 }
604 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
605 CHECK_EXPR(Call, Bounds(Type::Undefined(zone))) {
606 CHECK_VAR(bar, FUNC_V_TYPE);
607 }
608 }
609 }
610 CHECK_FUNC_TYPES_END
611}
612
613
614TEST(ReturnInt32Literal) {
615 CHECK_FUNC_TYPES_BEGIN(
616 "function bar() { return 1; }\n"
617 "function foo() { bar(); }") {
618 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
619 // return 1;
620 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned));
621 }
622 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
623 CHECK_EXPR(Call, Bounds(cache.kAsmSigned)) {
624 CHECK_VAR(bar, FUNC_I_TYPE);
625 }
626 }
627 }
628 CHECK_FUNC_TYPES_END
629}
630
631
632TEST(ReturnFloat64Literal) {
633 CHECK_FUNC_TYPES_BEGIN(
634 "function bar() { return 1.0; }\n"
635 "function foo() { bar(); }") {
636 CHECK_EXPR(FunctionLiteral, FUNC_D_TYPE) {
637 // return 1.0;
638 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
639 }
640 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
641 CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) {
642 CHECK_VAR(bar, FUNC_D_TYPE);
643 }
644 }
645 }
646 CHECK_FUNC_TYPES_END
647}
648
649
650TEST(ReturnFloat32Literal) {
651 CHECK_FUNC_TYPES_BEGIN(
652 "function bar() { return fround(1.0); }\n"
653 "function foo() { bar(); }") {
654 CHECK_EXPR(FunctionLiteral, FUNC_F_TYPE) {
655 // return fround(1.0);
656 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) {
657 CHECK_VAR(fround, FUNC_N2F_TYPE);
658 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
659 }
660 }
661 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
662 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { CHECK_VAR(bar, FUNC_F_TYPE); }
663 }
664 }
665 CHECK_FUNC_TYPES_END
666}
667
668
669TEST(ReturnFloat64Var) {
670 CHECK_FUNC_TYPES_BEGIN(
671 "function bar() { var x = 1.0; return +x; }\n"
672 "function foo() { bar(); }") {
673 CHECK_EXPR(FunctionLiteral, FUNC_D_TYPE) {
674 // return 1.0;
675 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) {
676 CHECK_VAR(x, Bounds(cache.kAsmDouble));
677 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
678 }
679 // return 1.0;
680 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) {
681 CHECK_VAR(x, Bounds(cache.kAsmDouble));
682 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
683 }
684 }
685 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
686 CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) {
687 CHECK_VAR(bar, FUNC_D_TYPE);
688 }
689 }
690 }
691 CHECK_FUNC_TYPES_END
692}
693
694
695TEST(Addition2) {
696 CHECK_FUNC_TYPES_BEGIN(
697 "function bar() { var x = 1; var y = 2; return (x+y)|0; }\n"
698 "function foo() { bar(); }") {
699 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
700 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
701 CHECK_VAR(x, Bounds(cache.kAsmInt));
702 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
703 }
704 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
705 CHECK_VAR(y, Bounds(cache.kAsmInt));
706 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
707 }
708 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
709 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) {
710 CHECK_VAR(x, Bounds(cache.kAsmInt));
711 CHECK_VAR(y, Bounds(cache.kAsmInt));
712 }
713 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
714 }
715 }
716 CHECK_SKIP();
717 }
718 CHECK_FUNC_TYPES_END
719}
720
721
722#define TEST_COMPARE_OP(name, op) \
723 TEST(name) { \
724 CHECK_FUNC_TYPES_BEGIN("function bar() { return (0 " op \
725 " 0)|0; }\n" \
726 "function foo() { bar(); }") { \
727 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { \
728 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { \
729 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) { \
730 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); \
731 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); \
732 } \
733 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); \
734 } \
735 } \
736 CHECK_SKIP(); \
737 } \
738 CHECK_FUNC_TYPES_END \
739 }
740
741
742TEST_COMPARE_OP(EqOperator, "==")
743TEST_COMPARE_OP(LtOperator, "<")
744TEST_COMPARE_OP(LteOperator, "<=")
745TEST_COMPARE_OP(GtOperator, ">")
746TEST_COMPARE_OP(GteOperator, ">=")
747
748
749TEST(NeqOperator) {
750 CHECK_FUNC_TYPES_BEGIN(
751 "function bar() { return (0 != 0)|0; }\n"
752 "function foo() { bar(); }") {
753 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
754 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
755 CHECK_EXPR(UnaryOperation, Bounds(cache.kAsmSigned)) {
756 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) {
757 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
758 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
759 }
760 }
761 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
762 }
763 }
764 CHECK_SKIP();
765 }
766 CHECK_FUNC_TYPES_END
767}
768
769
770TEST(NotOperator) {
771 CHECK_FUNC_TYPES_BEGIN(
772 "function bar() { var x = 0; return (!x)|0; }\n"
773 "function foo() { bar(); }") {
774 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
775 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
776 CHECK_VAR(x, Bounds(cache.kAsmInt));
777 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
778 }
779 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
780 CHECK_EXPR(UnaryOperation, Bounds(cache.kAsmSigned)) {
781 CHECK_VAR(x, Bounds(cache.kAsmInt));
782 }
783 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
784 }
785 }
786 CHECK_SKIP();
787 }
788 CHECK_FUNC_TYPES_END
789}
790
791
792TEST(InvertOperator) {
793 CHECK_FUNC_TYPES_BEGIN(
794 "function bar() { var x = 0; return (~x)|0; }\n"
795 "function foo() { bar(); }") {
796 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
797 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
798 CHECK_VAR(x, Bounds(cache.kAsmInt));
799 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
800 }
801 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
802 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
803 CHECK_VAR(x, Bounds(cache.kAsmInt));
804 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned));
805 }
806 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
807 }
808 }
809 CHECK_SKIP();
810 }
811 CHECK_FUNC_TYPES_END
812}
813
814
815TEST(InvertConversion) {
816 CHECK_FUNC_TYPES_BEGIN(
817 "function bar() { var x = 0.0; return (~~x)|0; }\n"
818 "function foo() { bar(); }") {
819 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
820 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) {
821 CHECK_VAR(x, Bounds(cache.kAsmDouble));
822 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
823 }
824 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
825 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
826 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
827 CHECK_VAR(x, Bounds(cache.kAsmDouble));
828 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned));
829 }
830 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned));
831 }
832 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
833 }
834 }
835 CHECK_SKIP();
836 }
837 CHECK_FUNC_TYPES_END
838}
839
840
841TEST(Ternary) {
842 CHECK_FUNC_TYPES_BEGIN(
843 "function bar() { var x = 1; var y = 1; return (x?y:5)|0; }\n"
844 "function foo() { bar(); }") {
845 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
846 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
847 CHECK_VAR(x, Bounds(cache.kAsmInt));
848 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
849 }
850 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
851 CHECK_VAR(y, Bounds(cache.kAsmInt));
852 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
853 }
854 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
855 CHECK_EXPR(Conditional, Bounds(cache.kAsmInt)) {
856 CHECK_VAR(x, Bounds(cache.kAsmInt));
857 CHECK_VAR(y, Bounds(cache.kAsmInt));
858 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
859 }
860 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
861 }
862 }
863 CHECK_SKIP();
864 }
865 CHECK_FUNC_TYPES_END
866}
867
868
869#define TEST_INT_BIN_OP(name, op) \
870 TEST(name) { \
871 CHECK_FUNC_TYPES_BEGIN("function bar() { var x = 0; return (x " op \
872 " 123)|0; }\n" \
873 "function foo() { bar(); }") { \
874 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { \
875 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { \
876 CHECK_VAR(x, Bounds(cache.kAsmInt)); \
877 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); \
878 } \
879 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { \
880 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { \
881 CHECK_VAR(x, Bounds(cache.kAsmInt)); \
882 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); \
883 } \
884 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); \
885 } \
886 } \
887 CHECK_SKIP(); \
888 } \
889 CHECK_FUNC_TYPES_END \
890 }
891
892
893TEST_INT_BIN_OP(AndOperator, "&")
894TEST_INT_BIN_OP(OrOperator, "|")
895TEST_INT_BIN_OP(XorOperator, "^")
896
897
898TEST(SignedCompare) {
899 CHECK_FUNC_TYPES_BEGIN(
900 "function bar() { var x = 1; var y = 1; return ((x|0) < (y|0))|0; }\n"
901 "function foo() { bar(); }") {
902 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
903 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
904 CHECK_VAR(x, Bounds(cache.kAsmInt));
905 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
906 }
907 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
908 CHECK_VAR(y, Bounds(cache.kAsmInt));
909 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
910 }
911 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
912 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) {
913 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
914 CHECK_VAR(x, Bounds(cache.kAsmInt));
915 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
916 }
917 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
918 CHECK_VAR(y, Bounds(cache.kAsmInt));
919 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
920 }
921 }
922 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
923 }
924 }
925 CHECK_SKIP();
926 }
927 CHECK_FUNC_TYPES_END
928}
929
930
931TEST(SignedCompareConst) {
932 CHECK_FUNC_TYPES_BEGIN(
933 "function bar() { var x = 1; var y = 1; return ((x|0) < (1<<31))|0; }\n"
934 "function foo() { bar(); }") {
935 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
936 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
937 CHECK_VAR(x, Bounds(cache.kAsmInt));
938 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
939 }
940 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
941 CHECK_VAR(y, Bounds(cache.kAsmInt));
942 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
943 }
944 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
945 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) {
946 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
947 CHECK_VAR(x, Bounds(cache.kAsmInt));
948 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
949 }
950 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned));
951 }
952 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
953 }
954 }
955 CHECK_SKIP();
956 }
957 CHECK_FUNC_TYPES_END
958}
959
960
961TEST(UnsignedCompare) {
962 CHECK_FUNC_TYPES_BEGIN(
963 "function bar() { var x = 1; var y = 1; return ((x>>>0) < (y>>>0))|0; }\n"
964 "function foo() { bar(); }") {
965 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
966 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
967 CHECK_VAR(x, Bounds(cache.kAsmInt));
968 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
969 }
970 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
971 CHECK_VAR(y, Bounds(cache.kAsmInt));
972 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
973 }
974 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
975 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) {
976 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) {
977 CHECK_VAR(x, Bounds(cache.kAsmInt));
978 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
979 }
980 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) {
981 CHECK_VAR(y, Bounds(cache.kAsmInt));
982 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
983 }
984 }
985 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
986 }
987 }
988 CHECK_SKIP();
989 }
990 CHECK_FUNC_TYPES_END
991}
992
993
994TEST(UnsignedCompareConst0) {
995 CHECK_FUNC_TYPES_BEGIN(
996 "function bar() { var x = 1; var y = 1; return ((x>>>0) < (0>>>0))|0; }\n"
997 "function foo() { bar(); }") {
998 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
999 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1000 CHECK_VAR(x, Bounds(cache.kAsmInt));
1001 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1002 }
1003 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1004 CHECK_VAR(y, Bounds(cache.kAsmInt));
1005 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1006 }
1007 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1008 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) {
1009 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) {
1010 CHECK_VAR(x, Bounds(cache.kAsmInt));
1011 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1012 }
1013 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1014 }
1015 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1016 }
1017 }
1018 CHECK_SKIP();
1019 }
1020 CHECK_FUNC_TYPES_END
1021}
1022
1023
1024TEST(UnsignedCompareConst1) {
1025 CHECK_FUNC_TYPES_BEGIN(
1026 "function bar() { var x = 1; var y = 1; return ((x>>>0) < "
1027 "(0xffffffff>>>0))|0; }\n"
1028 "function foo() { bar(); }") {
1029 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
1030 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1031 CHECK_VAR(x, Bounds(cache.kAsmInt));
1032 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1033 }
1034 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1035 CHECK_VAR(y, Bounds(cache.kAsmInt));
1036 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1037 }
1038 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1039 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) {
1040 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) {
1041 CHECK_VAR(x, Bounds(cache.kAsmInt));
1042 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1043 }
1044 CHECK_EXPR(Literal, Bounds(cache.kAsmUnsigned));
1045 }
1046 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1047 }
1048 }
1049 CHECK_SKIP();
1050 }
1051 CHECK_FUNC_TYPES_END
1052}
1053
1054
1055TEST(UnsignedDivide) {
1056 CHECK_FUNC_TYPES_BEGIN(
1057 "function bar() { var x = 1; var y = 1; return ((x>>>0) / (y>>>0))|0; }\n"
1058 "function foo() { bar(); }") {
1059 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
1060 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1061 CHECK_VAR(x, Bounds(cache.kAsmInt));
1062 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1063 }
1064 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1065 CHECK_VAR(y, Bounds(cache.kAsmInt));
1066 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1067 }
1068 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1069 CHECK_EXPR(BinaryOperation, Bounds(Type::None(zone), Type::Any(zone))) {
1070 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) {
1071 CHECK_VAR(x, Bounds(cache.kAsmInt));
1072 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1073 }
1074 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) {
1075 CHECK_VAR(y, Bounds(cache.kAsmInt));
1076 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1077 }
1078 }
1079 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1080 }
1081 }
1082 CHECK_SKIP();
1083 }
1084 CHECK_FUNC_TYPES_END
1085}
1086
1087
1088TEST(UnsignedFromFloat64) {
1089 CHECK_FUNC_ERROR(
1090 "function bar() { var x = 1.0; return (x>>>0)|0; }\n"
1091 "function foo() { bar(); }",
1092 "asm: line 39: left bitwise operand expected to be an integer\n");
1093}
1094
1095
1096TEST(AndFloat64) {
1097 CHECK_FUNC_ERROR(
1098 "function bar() { var x = 1.0; return (x&0)|0; }\n"
1099 "function foo() { bar(); }",
1100 "asm: line 39: left bitwise operand expected to be an integer\n");
1101}
1102
1103
1104TEST(TypeMismatchAddInt32Float64) {
1105 CHECK_FUNC_ERROR(
1106 "function bar() { var x = 1.0; var y = 0; return (x + y)|0; }\n"
1107 "function foo() { bar(); }",
1108 "asm: line 39: ill-typed arithmetic operation\n");
1109}
1110
1111
1112TEST(TypeMismatchSubInt32Float64) {
1113 CHECK_FUNC_ERROR(
1114 "function bar() { var x = 1.0; var y = 0; return (x - y)|0; }\n"
1115 "function foo() { bar(); }",
1116 "asm: line 39: ill-typed arithmetic operation\n");
1117}
1118
1119
1120TEST(TypeMismatchDivInt32Float64) {
1121 CHECK_FUNC_ERROR(
1122 "function bar() { var x = 1.0; var y = 0; return (x / y)|0; }\n"
1123 "function foo() { bar(); }",
1124 "asm: line 39: ill-typed arithmetic operation\n");
1125}
1126
1127
1128TEST(TypeMismatchModInt32Float64) {
1129 CHECK_FUNC_ERROR(
1130 "function bar() { var x = 1.0; var y = 0; return (x % y)|0; }\n"
1131 "function foo() { bar(); }",
1132 "asm: line 39: ill-typed arithmetic operation\n");
1133}
1134
1135
1136TEST(ModFloat32) {
1137 CHECK_FUNC_ERROR(
1138 "function bar() { var x = fround(1.0); return (x % x)|0; }\n"
1139 "function foo() { bar(); }",
1140 "asm: line 39: ill-typed arithmetic operation\n");
1141}
1142
1143
1144TEST(TernaryMismatchInt32Float64) {
1145 CHECK_FUNC_ERROR(
1146 "function bar() { var x = 1; var y = 0.0; return (1 ? x : y)|0; }\n"
1147 "function foo() { bar(); }",
1148 "asm: line 39: then and else expressions in ? must have the same type\n");
1149}
1150
1151
1152TEST(TernaryMismatchIntish) {
1153 CHECK_FUNC_ERROR(
1154 "function bar() { var x = 1; var y = 0; return (1 ? x + x : y)|0; }\n"
1155 "function foo() { bar(); }",
1156 "asm: line 39: invalid type in ? then expression\n");
1157}
1158
1159
1160TEST(TernaryMismatchInt32Float32) {
1161 CHECK_FUNC_ERROR(
1162 "function bar() { var x = 1; var y = 2; return (x?fround(y):x)|0; }\n"
1163 "function foo() { bar(); }",
1164 "asm: line 39: then and else expressions in ? must have the same type\n");
1165}
1166
1167
1168TEST(TernaryBadCondition) {
1169 CHECK_FUNC_ERROR(
1170 "function bar() { var x = 1; var y = 2.0; return (y?x:1)|0; }\n"
1171 "function foo() { bar(); }",
1172 "asm: line 39: condition must be of type int\n");
1173}
1174
1175
1176TEST(FroundFloat32) {
1177 CHECK_FUNC_TYPES_BEGIN(
1178 "function bar() { var x = 1; return fround(x); }\n"
1179 "function foo() { bar(); }") {
1180 CHECK_EXPR(FunctionLiteral, FUNC_F_TYPE) {
1181 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1182 CHECK_VAR(x, Bounds(cache.kAsmInt));
1183 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1184 }
1185 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) {
1186 CHECK_VAR(fround, FUNC_N2F_TYPE);
1187 CHECK_VAR(x, Bounds(cache.kAsmInt));
1188 }
1189 }
1190 CHECK_SKIP();
1191 }
1192 CHECK_FUNC_TYPES_END
1193}
1194
1195
1196TEST(Addition4) {
1197 CHECK_FUNC_TYPES_BEGIN(
1198 "function bar() { var x = 1; var y = 2; return (x+y+x+y)|0; }\n"
1199 "function foo() { bar(); }") {
1200 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
1201 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1202 CHECK_VAR(x, Bounds(cache.kAsmInt));
1203 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1204 }
1205 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1206 CHECK_VAR(y, Bounds(cache.kAsmInt));
1207 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1208 }
1209 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1210 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) {
1211 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) {
1212 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) {
1213 CHECK_VAR(x, Bounds(cache.kAsmInt));
1214 CHECK_VAR(y, Bounds(cache.kAsmInt));
1215 }
1216 CHECK_VAR(x, Bounds(cache.kAsmInt));
1217 }
1218 CHECK_VAR(y, Bounds(cache.kAsmInt));
1219 }
1220 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1221 }
1222 }
1223 CHECK_SKIP();
1224 }
1225 CHECK_FUNC_TYPES_END
1226}
1227
1228
1229TEST(Multiplication2) {
1230 CHECK_FUNC_ERROR(
1231 "function bar() { var x = 1; var y = 2; return (x*y)|0; }\n"
1232 "function foo() { bar(); }",
1233 "asm: line 39: direct integer multiply forbidden\n");
1234}
1235
1236
1237TEST(Division4) {
1238 CHECK_FUNC_ERROR(
1239 "function bar() { var x = 1; var y = 2; return (x/y/x/y)|0; }\n"
1240 "function foo() { bar(); }",
1241 "asm: line 39: too many consecutive multiplicative ops\n");
1242}
1243
1244
1245TEST(CompareToStringLeft) {
1246 CHECK_FUNC_ERROR(
1247 "function bar() { var x = 1; return ('hi' > x)|0; }\n"
1248 "function foo() { bar(); }",
1249 "asm: line 39: bad type on left side of comparison\n");
1250}
1251
1252
1253TEST(CompareToStringRight) {
1254 CHECK_FUNC_ERROR(
1255 "function bar() { var x = 1; return (x < 'hi')|0; }\n"
1256 "function foo() { bar(); }",
1257 "asm: line 39: bad type on right side of comparison\n");
1258}
1259
1260
1261TEST(CompareMismatchInt32Float64) {
1262 CHECK_FUNC_ERROR(
1263 "function bar() { var x = 1; var y = 2.0; return (x < y)|0; }\n"
1264 "function foo() { bar(); }",
1265 "asm: line 39: left and right side of comparison must match\n");
1266}
1267
1268
1269TEST(CompareMismatchInt32Uint32) {
1270 CHECK_FUNC_ERROR(
1271 "function bar() { var x = 1; var y = 2; return ((x|0) < (y>>>0))|0; }\n"
1272 "function foo() { bar(); }",
1273 "asm: line 39: left and right side of comparison must match\n");
1274}
1275
1276
1277TEST(CompareMismatchInt32Float32) {
1278 CHECK_FUNC_ERROR(
1279 "function bar() { var x = 1; var y = 2; return (x < fround(y))|0; }\n"
1280 "function foo() { bar(); }",
1281 "asm: line 39: left and right side of comparison must match\n");
1282}
1283
1284
1285TEST(Float64ToInt32) {
1286 CHECK_FUNC_TYPES_BEGIN(
1287 "function bar() { var x = 1; var y = 0.0; x = ~~y; }\n"
1288 "function foo() { bar(); }") {
1289 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
1290 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1291 CHECK_VAR(x, Bounds(cache.kAsmInt));
1292 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1293 }
1294 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) {
1295 CHECK_VAR(y, Bounds(cache.kAsmDouble));
1296 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
1297 }
1298 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1299 CHECK_VAR(x, Bounds(cache.kAsmInt));
1300 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1301 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1302 CHECK_VAR(y, Bounds(cache.kAsmDouble));
1303 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned));
1304 }
1305 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned));
1306 }
1307 }
1308 }
1309 CHECK_SKIP();
1310 }
1311 CHECK_FUNC_TYPES_END
1312}
1313
1314
1315TEST(Load1) {
1316 CHECK_FUNC_TYPES_BEGIN(
1317 "function bar() { var x = 1; var y = i8[x>>0]|0; }\n"
1318 "function foo() { bar(); }") {
1319 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
1320 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1321 CHECK_VAR(x, Bounds(cache.kAsmInt));
1322 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1323 }
1324 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1325 CHECK_VAR(y, Bounds(cache.kAsmInt));
1326 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1327 CHECK_EXPR(Property, Bounds(cache.kAsmInt)) {
1328 CHECK_VAR(i8, Bounds(cache.kInt8Array));
1329 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1330 CHECK_VAR(x, Bounds(cache.kAsmSigned));
1331 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1332 }
1333 }
1334 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1335 }
1336 }
1337 }
1338 CHECK_SKIP();
1339 }
1340 CHECK_FUNC_TYPES_END
1341}
1342
1343
1344TEST(LoadDouble) {
1345 CHECK_FUNC_TYPES_BEGIN(
1346 "function bar() { var x = 1; var y = 0.0; y = +f64[x>>3]; }\n"
1347 "function foo() { bar(); }") {
1348 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
1349 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1350 CHECK_VAR(x, Bounds(cache.kAsmInt));
1351 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1352 }
1353 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) {
1354 CHECK_VAR(y, Bounds(cache.kAsmDouble));
1355 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
1356 }
1357 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) {
1358 CHECK_VAR(y, Bounds(cache.kAsmDouble));
1359 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) {
1360 CHECK_EXPR(Property, Bounds(cache.kAsmDouble)) {
1361 CHECK_VAR(f64, Bounds(cache.kFloat64Array));
1362 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1363 CHECK_VAR(x, Bounds(cache.kAsmSigned));
1364 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1365 }
1366 }
1367 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
1368 }
1369 }
1370 }
1371 CHECK_SKIP();
1372 }
1373 CHECK_FUNC_TYPES_END
1374}
1375
1376
1377TEST(Store1) {
1378 CHECK_FUNC_TYPES_BEGIN(
1379 "function bar() { var x = 1; i8[x>>0] = 0; }\n"
1380 "function foo() { bar(); }") {
1381 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
1382 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1383 CHECK_VAR(x, Bounds(cache.kAsmInt));
1384 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1385 }
1386 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1387 CHECK_EXPR(Property, Bounds::Unbounded()) {
1388 CHECK_VAR(i8, Bounds(cache.kInt8Array));
1389 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1390 CHECK_VAR(x, Bounds(cache.kAsmSigned));
1391 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1392 }
1393 }
1394 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1395 }
1396 }
1397 CHECK_SKIP();
1398 }
1399 CHECK_FUNC_TYPES_END
1400}
1401
1402
1403TEST(StoreFloat) {
1404 CHECK_FUNC_TYPES_BEGIN(
1405 "function bar() { var x = fround(1.0); "
1406 "f32[0] = fround(x + fround(1.0)); }\n"
1407 "function foo() { bar(); }") {
1408 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
1409 CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) {
1410 CHECK_VAR(x, Bounds(cache.kAsmFloat));
1411 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) {
1412 CHECK_VAR(fround, FUNC_N2F_TYPE);
1413 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
1414 }
1415 }
1416 CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) {
1417 CHECK_EXPR(Property, Bounds::Unbounded()) {
1418 CHECK_VAR(f32, Bounds(cache.kFloat32Array));
1419 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1420 }
1421 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) {
1422 CHECK_VAR(fround, FUNC_N2F_TYPE);
1423 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmFloat)) {
1424 CHECK_VAR(x, Bounds(cache.kAsmFloat));
1425 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) {
1426 CHECK_VAR(fround, FUNC_N2F_TYPE);
1427 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
1428 }
1429 }
1430 }
1431 }
1432 }
1433 CHECK_SKIP();
1434 }
1435 CHECK_FUNC_TYPES_END
1436}
1437
1438
1439TEST(Load1Constant) {
1440 CHECK_FUNC_TYPES_BEGIN(
1441 "function bar() { var x = 1; var y = i8[5]|0; }\n"
1442 "function foo() { bar(); }") {
1443 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
1444 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1445 CHECK_VAR(x, Bounds(cache.kAsmInt));
1446 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1447 }
1448 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1449 CHECK_VAR(y, Bounds(cache.kAsmInt));
1450 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1451 CHECK_EXPR(Property, Bounds(cache.kAsmInt)) {
1452 CHECK_VAR(i8, Bounds(cache.kInt8Array));
1453 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1454 }
1455 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1456 }
1457 }
1458 }
1459 CHECK_SKIP();
1460 }
1461 CHECK_FUNC_TYPES_END
1462}
1463
1464
1465TEST(FunctionTables) {
1466 CHECK_FUNC_TYPES_BEGIN(
1467 "function func1(x) { x = x | 0; return (x * 5) | 0; }\n"
1468 "function func2(x) { x = x | 0; return (x * 25) | 0; }\n"
1469 "var table1 = [func1, func2];\n"
1470 "function bar(x, y) { x = x | 0; y = y | 0;\n"
1471 " return table1[x & 1](y)|0; }\n"
1472 "function foo() { bar(1, 2); }") {
1473 CHECK_EXPR(FunctionLiteral, FUNC_I2I_TYPE) {
1474 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1475 CHECK_VAR(x, Bounds(cache.kAsmInt));
1476 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1477 CHECK_VAR(x, Bounds(cache.kAsmInt));
1478 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1479 }
1480 }
1481 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1482 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) {
1483 CHECK_VAR(x, Bounds(cache.kAsmInt));
1484 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1485 }
1486 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1487 }
1488 }
1489 CHECK_EXPR(FunctionLiteral, FUNC_I2I_TYPE) {
1490 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1491 CHECK_VAR(x, Bounds(cache.kAsmInt));
1492 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1493 CHECK_VAR(x, Bounds(cache.kAsmInt));
1494 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1495 }
1496 }
1497 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1498 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) {
1499 CHECK_VAR(x, Bounds(cache.kAsmInt));
1500 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1501 }
1502 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1503 }
1504 }
1505 CHECK_EXPR(FunctionLiteral, FUNC_II2I_TYPE) {
1506 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1507 CHECK_VAR(x, Bounds(cache.kAsmInt));
1508 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1509 CHECK_VAR(x, Bounds(cache.kAsmInt));
1510 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1511 }
1512 }
1513 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1514 CHECK_VAR(y, Bounds(cache.kAsmInt));
1515 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1516 CHECK_VAR(y, Bounds(cache.kAsmInt));
1517 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1518 }
1519 }
1520 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1521 CHECK_EXPR(Call, Bounds(cache.kAsmSigned)) {
1522 CHECK_EXPR(Property, FUNC_I2I_TYPE) {
1523 CHECK_VAR(table1, FUNC_I2I_ARRAY_TYPE);
1524 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1525 CHECK_VAR(x, Bounds(cache.kAsmSigned));
1526 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1527 }
1528 }
1529 CHECK_VAR(y, Bounds(cache.kAsmInt));
1530 }
1531 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1532 }
1533 }
1534 CHECK_SKIP();
1535 }
1536 CHECK_FUNC_TYPES_END_1();
1537 CHECK_EXPR(Assignment, FUNC_I2I_ARRAY_TYPE) {
1538 CHECK_VAR(table1, FUNC_I2I_ARRAY_TYPE);
1539 CHECK_EXPR(ArrayLiteral, FUNC_I2I_ARRAY_TYPE) {
1540 CHECK_VAR(func1, FUNC_I2I_TYPE);
1541 CHECK_VAR(func2, FUNC_I2I_TYPE);
1542 }
1543 }
1544 CHECK_FUNC_TYPES_END_2();
1545}
1546
1547
1548TEST(BadFunctionTable) {
1549 CHECK_FUNC_ERROR(
1550 "function func1(x) { x = x | 0; return (x * 5) | 0; }\n"
1551 "var table1 = [func1, 1];\n"
1552 "function bar(x, y) { x = x | 0; y = y | 0;\n"
1553 " return table1[x & 1](y)|0; }\n"
1554 "function foo() { bar(1, 2); }",
1555 "asm: line 40: array component expected to be a function\n");
1556}
1557
1558
1559TEST(MissingParameterTypes) {
1560 CHECK_FUNC_ERROR(
1561 "function bar(x) { var y = 1; }\n"
1562 "function foo() { bar(2); }",
1563 "asm: line 39: missing parameter type annotations\n");
1564}
1565
1566
1567TEST(InvalidTypeAnnotationBinaryOpDiv) {
1568 CHECK_FUNC_ERROR(
1569 "function bar(x) { x = x / 4; }\n"
1570 "function foo() { bar(2); }",
1571 "asm: line 39: invalid type annotation on binary op\n");
1572}
1573
1574
1575TEST(InvalidTypeAnnotationBinaryOpMul) {
1576 CHECK_FUNC_ERROR(
1577 "function bar(x) { x = x * 4.0; }\n"
1578 "function foo() { bar(2); }",
1579 "asm: line 39: invalid type annotation on binary op\n");
1580}
1581
1582
1583TEST(InvalidArgumentCount) {
1584 CHECK_FUNC_ERROR(
1585 "function bar(x) { return fround(4, 5); }\n"
1586 "function foo() { bar(); }",
1587 "asm: line 39: invalid argument count calling function\n");
1588}
1589
1590
1591TEST(InvalidTypeAnnotationArity) {
1592 CHECK_FUNC_ERROR(
1593 "function bar(x) { x = max(x); }\n"
1594 "function foo() { bar(3); }",
1595 "asm: line 39: only fround allowed on expression annotations\n");
1596}
1597
1598
1599TEST(InvalidTypeAnnotationOnlyFround) {
1600 CHECK_FUNC_ERROR(
1601 "function bar(x) { x = sin(x); }\n"
1602 "function foo() { bar(3); }",
1603 "asm: line 39: only fround allowed on expression annotations\n");
1604}
1605
1606
1607TEST(InvalidTypeAnnotation) {
1608 CHECK_FUNC_ERROR(
1609 "function bar(x) { x = (x+x)(x); }\n"
1610 "function foo() { bar(3); }",
1611 "asm: line 39: invalid type annotation\n");
1612}
1613
1614
1615TEST(WithStatement) {
1616 CHECK_FUNC_ERROR(
1617 "function bar() { var x = 0; with (x) { x = x + 1; } }\n"
1618 "function foo() { bar(); }",
1619 "asm: line 39: bad with statement\n");
1620}
1621
1622
1623TEST(NestedFunction) {
1624 CHECK_FUNC_ERROR(
1625 "function bar() { function x() { return 1; } }\n"
1626 "function foo() { bar(); }",
1627 "asm: line 39: function declared inside another\n");
1628}
1629
1630
1631TEST(UnboundVariable) {
1632 CHECK_FUNC_ERROR(
1633 "function bar() { var x = y; }\n"
1634 "function foo() { bar(); }",
1635 "asm: line 39: unbound variable\n");
1636}
1637
1638
1639TEST(EqStrict) {
1640 CHECK_FUNC_ERROR(
1641 "function bar() { return (0 === 0)|0; }\n"
1642 "function foo() { bar(); }",
1643 "asm: line 39: illegal comparison operator\n");
1644}
1645
1646
1647TEST(NeStrict) {
1648 CHECK_FUNC_ERROR(
1649 "function bar() { return (0 !== 0)|0; }\n"
1650 "function foo() { bar(); }",
1651 "asm: line 39: illegal comparison operator\n");
1652}
1653
1654
1655TEST(InstanceOf) {
1656 CHECK_FUNC_ERROR(
1657 "function bar() { return (0 instanceof 0)|0; }\n"
1658 "function foo() { bar(); }",
1659 "asm: line 39: illegal comparison operator\n");
1660}
1661
1662
1663TEST(InOperator) {
1664 CHECK_FUNC_ERROR(
1665 "function bar() { return (0 in 0)|0; }\n"
1666 "function foo() { bar(); }",
1667 "asm: line 39: illegal comparison operator\n");
1668}
1669
1670
1671TEST(LogicalAndOperator) {
1672 CHECK_FUNC_ERROR(
1673 "function bar() { return (0 && 0)|0; }\n"
1674 "function foo() { bar(); }",
1675 "asm: line 39: illegal logical operator\n");
1676}
1677
1678
1679TEST(LogicalOrOperator) {
1680 CHECK_FUNC_ERROR(
1681 "function bar() { return (0 || 0)|0; }\n"
1682 "function foo() { bar(); }",
1683 "asm: line 39: illegal logical operator\n");
1684}
1685
1686
1687TEST(BadLiteral) {
1688 CHECK_FUNC_ERROR(
1689 "function bar() { return true | 0; }\n"
1690 "function foo() { bar(); }",
1691 "asm: line 39: illegal literal\n");
1692}
1693
1694
1695TEST(MismatchedReturnTypeLiteral) {
1696 CHECK_FUNC_ERROR(
1697 "function bar() { if(1) { return 1; } return 1.0; }\n"
1698 "function foo() { bar(); }",
1699 "asm: line 39: return type does not match function signature\n");
1700}
1701
1702
1703TEST(MismatchedReturnTypeExpression) {
1704 CHECK_FUNC_ERROR(
1705 "function bar() {\n"
1706 " var x = 1; var y = 1.0; if(1) { return x; } return +y; }\n"
1707 "function foo() { bar(); }",
1708 "asm: line 40: return type does not match function signature\n");
1709}
1710
1711
1712TEST(AssignToFloatishToF64) {
1713 CHECK_FUNC_ERROR(
1714 "function bar() { var v = fround(1.0); f32[0] = v + fround(1.0); }\n"
1715 "function foo() { bar(); }",
1716 "asm: line 39: intish or floatish assignment\n");
1717}
1718
1719
1720TEST(ForeignFunction) {
1721 CHECK_FUNC_TYPES_BEGIN(
1722 "var baz = foreign.baz;\n"
1723 "function bar() { return baz(1, 2)|0; }\n"
1724 "function foo() { bar(); }") {
1725 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
1726 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1727 CHECK_EXPR(Call, Bounds(Type::Number(zone))) {
1728 CHECK_VAR(baz, Bounds(Type::Any(zone)));
1729 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1730 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1731 }
1732 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1733 }
1734 }
1735 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
1736 CHECK_EXPR(Call, Bounds(cache.kAsmSigned)) {
1737 CHECK_VAR(bar, FUNC_I_TYPE);
1738 }
1739 }
1740 }
1741 CHECK_FUNC_TYPES_END_1()
1742 CHECK_EXPR(Assignment, Bounds(Type::Any(zone))) {
1743 CHECK_VAR(baz, Bounds(Type::Any(zone)));
1744 CHECK_EXPR(Property, Bounds(Type::Any(zone))) {
1745 CHECK_VAR(foreign, Bounds::Unbounded());
1746 CHECK_EXPR(Literal, Bounds::Unbounded());
1747 }
1748 }
1749 CHECK_FUNC_TYPES_END_2()
1750}
1751
1752
1753TEST(BadExports) {
1754 HARNESS_PREAMBLE()
1755 "function foo() {};\n"
1756 "return {foo: foo, bar: 1};"
1757 "}\n";
1758
1759 v8::V8::Initialize();
1760 HandleAndZoneScope handles;
1761 Zone* zone = handles.main_zone();
1762 ZoneVector<ExpressionTypeEntry> types(zone);
1763 CHECK_EQ("asm: line 40: non-function in function table\n",
1764 Validate(zone, test_function, &types));
1765}
1766
1767
1768TEST(NestedHeapAssignment) {
1769 CHECK_FUNC_ERROR(
1770 "function bar() { var x = 0; i8[x = 1] = 2; }\n"
1771 "function foo() { bar(); }",
1772 "asm: line 39: expected >> in heap access\n");
1773}
1774
1775
1776TEST(BadArrayAssignment) {
1777 CHECK_FUNC_ERROR(
1778 "function bar() { i8[0] = 0.0; }\n"
1779 "function foo() { bar(); }",
1780 "asm: line 39: illegal type in assignment\n");
1781}
1782
1783
1784TEST(BadStandardFunctionCallOutside) {
1785 CHECK_FUNC_ERROR(
1786 "var s0 = sin(0);\n"
1787 "function bar() { }\n"
1788 "function foo() { bar(); }",
1789 "asm: line 39: calls forbidden outside function bodies\n");
1790}
1791
1792
1793TEST(BadFunctionCallOutside) {
1794 CHECK_FUNC_ERROR(
1795 "function bar() { return 0.0; }\n"
1796 "var s0 = bar(0);\n"
1797 "function foo() { bar(); }",
1798 "asm: line 40: calls forbidden outside function bodies\n");
1799}
1800
1801
1802TEST(NestedVariableAssignment) {
1803 CHECK_FUNC_TYPES_BEGIN(
1804 "function bar() { var x = 0; x = x = 4; }\n"
1805 "function foo() { bar(); }") {
1806 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
1807 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1808 CHECK_VAR(x, Bounds(cache.kAsmInt));
1809 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1810 }
1811 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1812 CHECK_VAR(x, Bounds(cache.kAsmInt));
1813 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1814 CHECK_VAR(x, Bounds(cache.kAsmInt));
1815 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1816 }
1817 }
1818 }
1819 CHECK_SKIP();
1820 }
1821 CHECK_FUNC_TYPES_END
1822}
1823
1824
1825TEST(NestedAssignmentInHeap) {
1826 CHECK_FUNC_TYPES_BEGIN(
1827 "function bar() { var x = 0; i8[(x = 1) >> 0] = 2; }\n"
1828 "function foo() { bar(); }") {
1829 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
1830 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1831 CHECK_VAR(x, Bounds(cache.kAsmInt));
1832 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1833 }
1834 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1835 CHECK_EXPR(Property, Bounds::Unbounded()) {
1836 CHECK_VAR(i8, Bounds(cache.kInt8Array));
1837 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1838 CHECK_EXPR(Assignment, Bounds(cache.kAsmSigned)) {
1839 CHECK_VAR(x, Bounds(cache.kAsmInt));
1840 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1841 }
1842 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1843 }
1844 }
1845 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
1846 }
1847 }
1848 CHECK_SKIP();
1849 }
1850 CHECK_FUNC_TYPES_END
1851}
1852
1853
1854TEST(NegativeDouble) {
1855 CHECK_FUNC_TYPES_BEGIN(
1856 "function bar() { var x = -123.2; }\n"
1857 "function foo() { bar(); }") {
1858 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
1859 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) {
1860 CHECK_VAR(x, Bounds(cache.kAsmDouble));
1861 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
1862 }
1863 }
1864 CHECK_SKIP();
1865 }
1866 CHECK_FUNC_TYPES_END
1867}
1868
1869
1870TEST(NegativeInteger) {
1871 CHECK_FUNC_TYPES_BEGIN(
1872 "function bar() { var x = -123; }\n"
1873 "function foo() { bar(); }") {
1874 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
1875 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1876 CHECK_VAR(x, Bounds(cache.kAsmInt));
1877 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned));
1878 }
1879 }
1880 CHECK_SKIP();
1881 }
1882 CHECK_FUNC_TYPES_END
1883}
1884
1885
1886TEST(AbsFunction) {
1887 CHECK_FUNC_TYPES_BEGIN(
1888 "function bar() { var x = -123.0; x = abs(x); }\n"
1889 "function foo() { bar(); }") {
1890 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
1891 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) {
1892 CHECK_VAR(x, Bounds(cache.kAsmDouble));
1893 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
1894 }
1895 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) {
1896 CHECK_VAR(x, Bounds(cache.kAsmDouble));
1897 CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) {
1898 CHECK_VAR(abs, FUNC_N2N_TYPE);
1899 CHECK_VAR(x, Bounds(cache.kAsmDouble));
1900 }
1901 }
1902 }
1903 CHECK_SKIP();
1904 }
1905 CHECK_FUNC_TYPES_END
1906}
1907
1908
1909TEST(CeilFloat) {
1910 CHECK_FUNC_TYPES_BEGIN(
1911 "function bar() { var x = fround(3.1); x = ceil(x); }\n"
1912 "function foo() { bar(); }") {
1913 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
1914 CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) {
1915 CHECK_VAR(x, Bounds(cache.kAsmFloat));
1916 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) {
1917 CHECK_VAR(fround, FUNC_N2F_TYPE);
1918 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
1919 }
1920 }
1921 CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) {
1922 CHECK_VAR(x, Bounds(cache.kAsmFloat));
1923 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) {
1924 CHECK_VAR(ceil, FUNC_N2N_TYPE);
1925 CHECK_VAR(x, Bounds(cache.kAsmFloat));
1926 }
1927 }
1928 }
1929 CHECK_SKIP();
1930 }
1931 CHECK_FUNC_TYPES_END
1932}
1933
1934
1935TEST(TypeConsistency) {
1936 v8::V8::Initialize();
1937 TypeCache cache;
1938 // Check the consistency of each of the main Asm.js types.
1939 CHECK(cache.kAsmFixnum->Is(cache.kAsmFixnum));
1940 CHECK(cache.kAsmFixnum->Is(cache.kAsmSigned));
1941 CHECK(cache.kAsmFixnum->Is(cache.kAsmUnsigned));
1942 CHECK(cache.kAsmFixnum->Is(cache.kAsmInt));
1943 CHECK(!cache.kAsmFixnum->Is(cache.kAsmFloat));
1944 CHECK(!cache.kAsmFixnum->Is(cache.kAsmDouble));
1945
1946 CHECK(cache.kAsmSigned->Is(cache.kAsmSigned));
1947 CHECK(cache.kAsmSigned->Is(cache.kAsmInt));
1948 CHECK(!cache.kAsmSigned->Is(cache.kAsmFixnum));
1949 CHECK(!cache.kAsmSigned->Is(cache.kAsmUnsigned));
1950 CHECK(!cache.kAsmSigned->Is(cache.kAsmFloat));
1951 CHECK(!cache.kAsmSigned->Is(cache.kAsmDouble));
1952
1953 CHECK(cache.kAsmUnsigned->Is(cache.kAsmUnsigned));
1954 CHECK(cache.kAsmUnsigned->Is(cache.kAsmInt));
1955 CHECK(!cache.kAsmUnsigned->Is(cache.kAsmSigned));
1956 CHECK(!cache.kAsmUnsigned->Is(cache.kAsmFixnum));
1957 CHECK(!cache.kAsmUnsigned->Is(cache.kAsmFloat));
1958 CHECK(!cache.kAsmUnsigned->Is(cache.kAsmDouble));
1959
1960 CHECK(cache.kAsmInt->Is(cache.kAsmInt));
1961 CHECK(!cache.kAsmInt->Is(cache.kAsmUnsigned));
1962 CHECK(!cache.kAsmInt->Is(cache.kAsmSigned));
1963 CHECK(!cache.kAsmInt->Is(cache.kAsmFixnum));
1964 CHECK(!cache.kAsmInt->Is(cache.kAsmFloat));
1965 CHECK(!cache.kAsmInt->Is(cache.kAsmDouble));
1966
1967 CHECK(cache.kAsmFloat->Is(cache.kAsmFloat));
1968 CHECK(!cache.kAsmFloat->Is(cache.kAsmInt));
1969 CHECK(!cache.kAsmFloat->Is(cache.kAsmUnsigned));
1970 CHECK(!cache.kAsmFloat->Is(cache.kAsmSigned));
1971 CHECK(!cache.kAsmFloat->Is(cache.kAsmFixnum));
1972 CHECK(!cache.kAsmFloat->Is(cache.kAsmDouble));
1973
1974 CHECK(cache.kAsmDouble->Is(cache.kAsmDouble));
1975 CHECK(!cache.kAsmDouble->Is(cache.kAsmInt));
1976 CHECK(!cache.kAsmDouble->Is(cache.kAsmUnsigned));
1977 CHECK(!cache.kAsmDouble->Is(cache.kAsmSigned));
1978 CHECK(!cache.kAsmDouble->Is(cache.kAsmFixnum));
1979 CHECK(!cache.kAsmDouble->Is(cache.kAsmFloat));
1980}
1981
1982
1983TEST(SwitchTest) {
1984 CHECK_FUNC_TYPES_BEGIN(
1985 "function switcher(x) {\n"
1986 " x = x|0;\n"
1987 " switch (x|0) {\n"
1988 " case 1: return 23;\n"
1989 " case 2: return 43;\n"
1990 " default: return 66;\n"
1991 " }\n"
1992 " return 0;\n"
1993 "}\n"
1994 "function foo() { switcher(1); }") {
1995 CHECK_EXPR(FunctionLiteral, FUNC_I2I_TYPE) {
1996 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
1997 CHECK_VAR(x, Bounds(cache.kAsmInt));
1998 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
1999 CHECK_VAR(x, Bounds(cache.kAsmInt));
2000 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
2001 }
2002 }
2003 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
2004 CHECK_VAR(.switch_tag, Bounds(cache.kAsmInt));
2005 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
2006 CHECK_VAR(x, Bounds(cache.kAsmInt));
2007 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
2008 }
2009 }
2010 CHECK_EXPR(Literal, Bounds(Type::Undefined(zone)));
2011 CHECK_VAR(.switch_tag, Bounds(cache.kAsmSigned));
2012 // case 1: return 23;
2013 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
2014 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned));
2015 // case 2: return 43;
2016 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
2017 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned));
2018 // default: return 66;
2019 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned));
2020 // return 0;
2021 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned));
2022 }
2023 CHECK_SKIP();
2024 }
2025 CHECK_FUNC_TYPES_END
2026}
2027
2028
2029TEST(BadSwitchRange) {
2030 CHECK_FUNC_ERROR(
2031 "function bar() { switch (1) { case -1: case 0x7fffffff: } }\n"
2032 "function foo() { bar(); }",
2033 "asm: line 39: case range too large\n");
2034}
2035
2036
2037TEST(DuplicateSwitchCase) {
2038 CHECK_FUNC_ERROR(
2039 "function bar() { switch (1) { case 0: case 0: } }\n"
2040 "function foo() { bar(); }",
2041 "asm: line 39: duplicate case value\n");
2042}
2043
2044
2045TEST(BadSwitchOrder) {
2046 CHECK_FUNC_ERROR(
2047 "function bar() { switch (1) { default: case 0: } }\n"
2048 "function foo() { bar(); }",
2049 "asm: line 39: default case out of order\n");
2050}