1 // 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 
48 using namespace v8::internal;
49 
50 namespace {
51 
Validate(Zone * zone,const char * source,ZoneVector<ExpressionTypeEntry> * types)52 std::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 
TEST(ValidateMinimum)86 TEST(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 
TEST(MissingUseAsm)312 TEST(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 
TEST(WrongUseAsm)327 TEST(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 
TEST(MissingReturnExports)343 TEST(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 
447 namespace {
448 
CheckStdlibShortcuts1(Zone * zone,ZoneVector<ExpressionTypeEntry> & types,size_t & index,int & depth,TypeCache & cache)449 void 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 
CheckStdlibShortcuts2(Zone * zone,ZoneVector<ExpressionTypeEntry> & types,size_t & index,int & depth,TypeCache & cache)480 void 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 
TEST(BareHarness)553 TEST(BareHarness) {
554   CHECK_FUNC_TYPES_BEGIN("function foo() {}") {
555     CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {}
556   }
557   CHECK_FUNC_TYPES_END
558 }
559 
560 
TEST(ReturnVoid)561 TEST(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 
TEST(EmptyBody)579 TEST(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 
TEST(DoesNothing)594 TEST(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 
TEST(ReturnInt32Literal)614 TEST(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 
TEST(ReturnFloat64Literal)632 TEST(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 
TEST(ReturnFloat32Literal)650 TEST(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 
TEST(ReturnFloat64Var)669 TEST(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 
TEST(Addition2)695 TEST(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 
742 TEST_COMPARE_OP(EqOperator, "==")
743 TEST_COMPARE_OP(LtOperator, "<")
744 TEST_COMPARE_OP(LteOperator, "<=")
745 TEST_COMPARE_OP(GtOperator, ">")
746 TEST_COMPARE_OP(GteOperator, ">=")
747 
748 
TEST(NeqOperator)749 TEST(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 
TEST(NotOperator)770 TEST(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 
TEST(InvertOperator)792 TEST(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 
TEST(InvertConversion)815 TEST(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 
TEST(Ternary)841 TEST(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 
893 TEST_INT_BIN_OP(AndOperator, "&")
894 TEST_INT_BIN_OP(OrOperator, "|")
895 TEST_INT_BIN_OP(XorOperator, "^")
896 
897 
TEST(SignedCompare)898 TEST(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 
TEST(SignedCompareConst)931 TEST(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 
TEST(UnsignedCompare)961 TEST(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 
TEST(UnsignedCompareConst0)994 TEST(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 
TEST(UnsignedCompareConst1)1024 TEST(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 
TEST(UnsignedDivide)1055 TEST(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 
TEST(UnsignedFromFloat64)1088 TEST(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 
TEST(AndFloat64)1096 TEST(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 
TEST(TypeMismatchAddInt32Float64)1104 TEST(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 
TEST(TypeMismatchSubInt32Float64)1112 TEST(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 
TEST(TypeMismatchDivInt32Float64)1120 TEST(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 
TEST(TypeMismatchModInt32Float64)1128 TEST(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 
TEST(ModFloat32)1136 TEST(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 
TEST(TernaryMismatchInt32Float64)1144 TEST(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 
TEST(TernaryMismatchIntish)1152 TEST(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 
TEST(TernaryMismatchInt32Float32)1160 TEST(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 
TEST(TernaryBadCondition)1168 TEST(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 
TEST(FroundFloat32)1176 TEST(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 
TEST(Addition4)1196 TEST(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 
TEST(Multiplication2)1229 TEST(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 
TEST(Division4)1237 TEST(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 
TEST(CompareToStringLeft)1245 TEST(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 
TEST(CompareToStringRight)1253 TEST(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 
TEST(CompareMismatchInt32Float64)1261 TEST(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 
TEST(CompareMismatchInt32Uint32)1269 TEST(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 
TEST(CompareMismatchInt32Float32)1277 TEST(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 
TEST(Float64ToInt32)1285 TEST(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 
TEST(Load1)1315 TEST(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 
TEST(LoadDouble)1344 TEST(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 
TEST(Store1)1377 TEST(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 
TEST(StoreFloat)1403 TEST(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 
TEST(Load1Constant)1439 TEST(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 
TEST(FunctionTables)1465 TEST(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 
TEST(BadFunctionTable)1548 TEST(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 
TEST(MissingParameterTypes)1559 TEST(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 
TEST(InvalidTypeAnnotationBinaryOpDiv)1567 TEST(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 
TEST(InvalidTypeAnnotationBinaryOpMul)1575 TEST(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 
TEST(InvalidArgumentCount)1583 TEST(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 
TEST(InvalidTypeAnnotationArity)1591 TEST(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 
TEST(InvalidTypeAnnotationOnlyFround)1599 TEST(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 
TEST(InvalidTypeAnnotation)1607 TEST(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 
TEST(WithStatement)1615 TEST(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 
TEST(NestedFunction)1623 TEST(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 
TEST(UnboundVariable)1631 TEST(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 
TEST(EqStrict)1639 TEST(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 
TEST(NeStrict)1647 TEST(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 
TEST(InstanceOf)1655 TEST(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 
TEST(InOperator)1663 TEST(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 
TEST(LogicalAndOperator)1671 TEST(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 
TEST(LogicalOrOperator)1679 TEST(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 
TEST(BadLiteral)1687 TEST(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 
TEST(MismatchedReturnTypeLiteral)1695 TEST(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 
TEST(MismatchedReturnTypeExpression)1703 TEST(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 
TEST(AssignToFloatishToF64)1712 TEST(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 
TEST(ForeignFunction)1720 TEST(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 
TEST(BadExports)1753 TEST(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 
TEST(NestedHeapAssignment)1768 TEST(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 
TEST(BadArrayAssignment)1776 TEST(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 
TEST(BadStandardFunctionCallOutside)1784 TEST(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 
TEST(BadFunctionCallOutside)1793 TEST(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 
TEST(NestedVariableAssignment)1802 TEST(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 
TEST(NestedAssignmentInHeap)1825 TEST(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 
TEST(NegativeDouble)1854 TEST(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 
TEST(NegativeInteger)1870 TEST(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 
TEST(AbsFunction)1886 TEST(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 
TEST(CeilFloat)1909 TEST(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 
TEST(TypeConsistency)1935 TEST(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 
TEST(SwitchTest)1983 TEST(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 
TEST(BadSwitchRange)2029 TEST(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 
TEST(DuplicateSwitchCase)2037 TEST(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 
TEST(BadSwitchOrder)2045 TEST(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 }
2051