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.
8 #include "src/ast-expression-visitor.h"
9 #include "src/parser.h"
10 #include "src/rewriter.h"
11 #include "src/scopes.h"
12 #include "src/typing-asm.h"
13 #include "src/zone-type-cache.h"
14 #include "test/cctest/cctest.h"
15 #include "test/cctest/expression-type-collector.h"
16 #include "test/cctest/expression-type-collector-macros.h"
18 // Macros for function types.
19 #define FUNC_V_TYPE Bounds(Type::Function(Type::Undefined(), zone))
20 #define FUNC_I_TYPE Bounds(Type::Function(cache.kInt32, zone))
21 #define FUNC_F_TYPE Bounds(Type::Function(cache.kFloat32, zone))
22 #define FUNC_D_TYPE Bounds(Type::Function(cache.kFloat64, zone))
23 #define FUNC_D2D_TYPE \
24 Bounds(Type::Function(cache.kFloat64, cache.kFloat64, zone))
25 #define FUNC_N2F_TYPE \
26 Bounds(Type::Function(cache.kFloat32, Type::Number(), zone))
27 #define FUNC_I2I_TYPE Bounds(Type::Function(cache.kInt32, cache.kInt32, zone))
28 #define FUNC_II2D_TYPE \
29 Bounds(Type::Function(cache.kFloat64, cache.kInt32, cache.kInt32, zone))
30 #define FUNC_II2I_TYPE \
31 Bounds(Type::Function(cache.kInt32, cache.kInt32, cache.kInt32, zone))
32 #define FUNC_DD2D_TYPE \
33 Bounds(Type::Function(cache.kFloat64, cache.kFloat64, cache.kFloat64, zone))
34 #define FUNC_N2N_TYPE \
35 Bounds(Type::Function(Type::Number(), Type::Number(), zone))
37 // Macros for array types.
38 #define FLOAT64_ARRAY_TYPE Bounds(Type::Array(cache.kFloat64, zone))
39 #define FUNC_I2I_ARRAY_TYPE \
40 Bounds(Type::Array(Type::Function(cache.kInt32, cache.kInt32, zone), zone))
42 using namespace v8::internal;
46 std::string Validate(Zone* zone, const char* source,
47 ZoneVector<ExpressionTypeEntry>* types) {
48 i::Isolate* isolate = CcTest::i_isolate();
49 i::Factory* factory = isolate->factory();
51 i::Handle<i::String> source_code =
52 factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked();
54 i::Handle<i::Script> script = factory->NewScript(source_code);
56 i::ParseInfo info(zone, script);
57 i::Parser parser(&info);
58 parser.set_allow_harmony_arrow_functions(true);
59 parser.set_allow_harmony_sloppy(true);
62 info.set_allow_lazy_parsing(false);
63 info.set_toplevel(true);
65 CHECK(i::Compiler::ParseAndAnalyze(&info));
67 FunctionLiteral* root =
68 info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun();
69 AsmTyper typer(isolate, zone, *script, root);
70 if (typer.Validate()) {
71 ExpressionTypeCollector(isolate, zone, root, types).Run();
74 return typer.error_message();
80 TEST(ValidateMinimum) {
81 const char test_function[] =
82 "function GeometricMean(stdlib, foreign, buffer) {\n"
85 " var exp = stdlib.Math.exp;\n"
86 " var log = stdlib.Math.log;\n"
87 " var values = new stdlib.Float64Array(buffer);\n"
89 " function logSum(start, end) {\n"
93 " var sum = 0.0, p = 0, q = 0;\n"
95 " // asm.js forces byte addressing of the heap by requiring shifting "
97 " for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {\n"
98 " sum = sum + +log(values[p>>3]);\n"
104 " function geometricMean(start, end) {\n"
105 " start = start|0;\n"
108 " return +exp(+logSum(start, end) / +((end - start)|0));\n"
111 " return { geometricMean: geometricMean };\n"
114 v8::V8::Initialize();
115 HandleAndZoneScope handles;
116 Zone* zone = handles.main_zone();
117 ZoneVector<ExpressionTypeEntry> types(zone);
118 CHECK_EQ("", Validate(zone, test_function, &types));
123 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
125 CHECK_EXPR(FunctionLiteral, FUNC_II2D_TYPE) {
126 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
127 CHECK_VAR(start, Bounds(cache.kInt32));
128 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
129 CHECK_VAR(start, Bounds(cache.kInt32));
130 CHECK_EXPR(Literal, Bounds(cache.kInt32));
133 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
134 CHECK_VAR(end, Bounds(cache.kInt32));
135 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
136 CHECK_VAR(end, Bounds(cache.kInt32));
137 CHECK_EXPR(Literal, Bounds(cache.kInt32));
140 CHECK_EXPR(Assignment, Bounds(cache.kFloat64)) {
141 CHECK_VAR(sum, Bounds(cache.kFloat64));
142 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
144 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
145 CHECK_VAR(p, Bounds(cache.kInt32));
146 CHECK_EXPR(Literal, Bounds(cache.kInt32));
148 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
149 CHECK_VAR(q, Bounds(cache.kInt32));
150 CHECK_EXPR(Literal, Bounds(cache.kInt32));
152 // for (p = start << 3, q = end << 3;
153 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
154 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
155 CHECK_VAR(p, Bounds(cache.kInt32));
156 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
157 CHECK_VAR(start, Bounds(cache.kInt32));
158 CHECK_EXPR(Literal, Bounds(cache.kInt32));
161 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
162 CHECK_VAR(q, Bounds(cache.kInt32));
163 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
164 CHECK_VAR(end, Bounds(cache.kInt32));
165 CHECK_EXPR(Literal, Bounds(cache.kInt32));
170 CHECK_EXPR(CompareOperation, Bounds(cache.kInt32)) {
171 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
172 CHECK_VAR(p, Bounds(cache.kInt32));
173 CHECK_EXPR(Literal, Bounds(cache.kInt32));
175 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
176 CHECK_VAR(q, Bounds(cache.kInt32));
177 CHECK_EXPR(Literal, Bounds(cache.kInt32));
180 // p = (p + 8)|0) {\n"
181 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
182 CHECK_VAR(p, Bounds(cache.kInt32));
183 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
184 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
185 CHECK_VAR(p, Bounds(cache.kInt32));
186 CHECK_EXPR(Literal, Bounds(cache.kInt32));
188 CHECK_EXPR(Literal, Bounds(cache.kInt32));
191 // sum = sum + +log(values[p>>3]);
192 CHECK_EXPR(Assignment, Bounds(cache.kFloat64)) {
193 CHECK_VAR(sum, Bounds(cache.kFloat64));
194 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
195 CHECK_VAR(sum, Bounds(cache.kFloat64));
196 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
197 CHECK_EXPR(Call, Bounds(cache.kFloat64)) {
198 CHECK_VAR(log, FUNC_D2D_TYPE);
199 CHECK_EXPR(Property, Bounds(cache.kFloat64)) {
200 CHECK_VAR(values, FLOAT64_ARRAY_TYPE);
201 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
202 CHECK_VAR(p, Bounds(cache.kInt32));
203 CHECK_EXPR(Literal, Bounds(cache.kInt32));
207 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
212 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
213 CHECK_VAR(sum, Bounds(cache.kFloat64));
214 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
217 // function geometricMean
218 CHECK_EXPR(FunctionLiteral, FUNC_II2D_TYPE) {
219 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
220 CHECK_VAR(start, Bounds(cache.kInt32));
221 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
222 CHECK_VAR(start, Bounds(cache.kInt32));
223 CHECK_EXPR(Literal, Bounds(cache.kInt32));
226 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
227 CHECK_VAR(end, Bounds(cache.kInt32));
228 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
229 CHECK_VAR(end, Bounds(cache.kInt32));
230 CHECK_EXPR(Literal, Bounds(cache.kInt32));
233 // return +exp(+logSum(start, end) / +((end - start)|0));
234 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
235 CHECK_EXPR(Call, Bounds(cache.kFloat64)) {
236 CHECK_VAR(exp, FUNC_D2D_TYPE);
237 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
238 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
239 CHECK_EXPR(Call, Bounds(cache.kFloat64)) {
240 CHECK_VAR(logSum, FUNC_II2D_TYPE);
241 CHECK_VAR(start, Bounds(cache.kInt32));
242 CHECK_VAR(end, Bounds(cache.kInt32));
244 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
246 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
247 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
248 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
249 CHECK_VAR(end, Bounds(cache.kInt32));
250 CHECK_VAR(start, Bounds(cache.kInt32));
252 CHECK_EXPR(Literal, Bounds(cache.kInt32));
254 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
258 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
262 CHECK_EXPR(Literal, Bounds(Type::String()));
263 // var exp = stdlib.Math.exp;
264 CHECK_EXPR(Assignment, FUNC_D2D_TYPE) {
265 CHECK_VAR(exp, FUNC_D2D_TYPE);
266 CHECK_EXPR(Property, FUNC_D2D_TYPE) {
267 CHECK_EXPR(Property, Bounds::Unbounded()) {
268 CHECK_VAR(stdlib, Bounds::Unbounded());
269 CHECK_EXPR(Literal, Bounds::Unbounded());
271 CHECK_EXPR(Literal, Bounds::Unbounded());
274 // var log = stdlib.Math.log;
275 CHECK_EXPR(Assignment, FUNC_D2D_TYPE) {
276 CHECK_VAR(log, FUNC_D2D_TYPE);
277 CHECK_EXPR(Property, FUNC_D2D_TYPE) {
278 CHECK_EXPR(Property, Bounds::Unbounded()) {
279 CHECK_VAR(stdlib, Bounds::Unbounded());
280 CHECK_EXPR(Literal, Bounds::Unbounded());
282 CHECK_EXPR(Literal, Bounds::Unbounded());
285 // var values = new stdlib.Float64Array(buffer);
286 CHECK_EXPR(Assignment, FLOAT64_ARRAY_TYPE) {
287 CHECK_VAR(values, FLOAT64_ARRAY_TYPE);
288 CHECK_EXPR(CallNew, FLOAT64_ARRAY_TYPE) {
289 CHECK_EXPR(Property, Bounds::Unbounded()) {
290 CHECK_VAR(stdlib, Bounds::Unbounded());
291 CHECK_EXPR(Literal, Bounds::Unbounded());
293 CHECK_VAR(buffer, Bounds::Unbounded());
296 // return { geometricMean: geometricMean };
297 CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) {
298 CHECK_VAR(geometricMean, FUNC_II2D_TYPE);
306 #define HARNESS_STDLIB() \
307 "var Infinity = stdlib.Infinity;\n" \
308 "var NaN = stdlib.NaN;\n" \
309 "var acos = stdlib.Math.acos;\n" \
310 "var asin = stdlib.Math.asin;\n" \
311 "var atan = stdlib.Math.atan;\n" \
312 "var cos = stdlib.Math.cos;\n" \
313 "var sin = stdlib.Math.sin;\n" \
314 "var tan = stdlib.Math.tan;\n" \
315 "var exp = stdlib.Math.exp;\n" \
316 "var log = stdlib.Math.log;\n" \
317 "var ceil = stdlib.Math.ceil;\n" \
318 "var floor = stdlib.Math.floor;\n" \
319 "var sqrt = stdlib.Math.sqrt;\n" \
320 "var min = stdlib.Math.min;\n" \
321 "var max = stdlib.Math.max;\n" \
322 "var atan2 = stdlib.Math.atan2;\n" \
323 "var pow = stdlib.Math.pow;\n" \
324 "var abs = stdlib.Math.abs;\n" \
325 "var imul = stdlib.Math.imul;\n" \
326 "var fround = stdlib.Math.fround;\n" \
327 "var E = stdlib.Math.E;\n" \
328 "var LN10 = stdlib.Math.LN10;\n" \
329 "var LN2 = stdlib.Math.LN2;\n" \
330 "var LOG2E = stdlib.Math.LOG2E;\n" \
331 "var LOG10E = stdlib.Math.LOG10E;\n" \
332 "var PI = stdlib.Math.PI;\n" \
333 "var SQRT1_2 = stdlib.Math.SQRT1_2;\n" \
334 "var SQRT2 = stdlib.Math.SQRT2;\n"
337 #define HARNESS_HEAP() \
338 "var u8 = new stdlib.Uint8Array(buffer);\n" \
339 "var i8 = new stdlib.Int8Array(buffer);\n" \
340 "var u16 = new stdlib.Uint16Array(buffer);\n" \
341 "var i16 = new stdlib.Int16Array(buffer);\n" \
342 "var u32 = new stdlib.Uint32Array(buffer);\n" \
343 "var i32 = new stdlib.Int32Array(buffer);\n" \
344 "var f32 = new stdlib.Float32Array(buffer);\n" \
345 "var f64 = new stdlib.Float64Array(buffer);\n"
348 #define HARNESS_PREAMBLE() \
349 const char test_function[] = \
350 "function Module(stdlib, foreign, buffer) {\n" \
351 "\"use asm\";\n" HARNESS_STDLIB() HARNESS_HEAP()
354 #define HARNESS_POSTAMBLE() \
355 "return { foo: foo };\n" \
359 #define CHECK_VAR_MATH_SHORTCUT(name, type) \
360 CHECK_EXPR(Assignment, type) { \
361 CHECK_VAR(name, type); \
362 CHECK_EXPR(Property, type) { \
363 CHECK_EXPR(Property, Bounds::Unbounded()) { \
364 CHECK_VAR(stdlib, Bounds::Unbounded()); \
365 CHECK_EXPR(Literal, Bounds::Unbounded()); \
367 CHECK_EXPR(Literal, Bounds::Unbounded()); \
372 #define CHECK_VAR_SHORTCUT(name, type) \
373 CHECK_EXPR(Assignment, type) { \
374 CHECK_VAR(name, type); \
375 CHECK_EXPR(Property, type) { \
376 CHECK_VAR(stdlib, Bounds::Unbounded()); \
377 CHECK_EXPR(Literal, Bounds::Unbounded()); \
382 #define CHECK_VAR_NEW_SHORTCUT(name, type) \
383 CHECK_EXPR(Assignment, type) { \
384 CHECK_VAR(name, type); \
385 CHECK_EXPR(CallNew, type) { \
386 CHECK_EXPR(Property, Bounds::Unbounded()) { \
387 CHECK_VAR(stdlib, Bounds::Unbounded()); \
388 CHECK_EXPR(Literal, Bounds::Unbounded()); \
390 CHECK_VAR(buffer, Bounds::Unbounded()); \
397 void CheckStdlibShortcuts(Zone* zone, ZoneVector<ExpressionTypeEntry>& types,
398 size_t& index, int& depth, ZoneTypeCache& cache) {
399 // var exp = stdlib.*; (D * 12)
400 CHECK_VAR_SHORTCUT(Infinity, Bounds(cache.kFloat64));
401 CHECK_VAR_SHORTCUT(NaN, Bounds(cache.kFloat64));
402 // var x = stdlib.Math.x; D2D
403 CHECK_VAR_MATH_SHORTCUT(acos, FUNC_D2D_TYPE);
404 CHECK_VAR_MATH_SHORTCUT(asin, FUNC_D2D_TYPE);
405 CHECK_VAR_MATH_SHORTCUT(atan, FUNC_D2D_TYPE);
406 CHECK_VAR_MATH_SHORTCUT(cos, FUNC_D2D_TYPE);
407 CHECK_VAR_MATH_SHORTCUT(sin, FUNC_D2D_TYPE);
408 CHECK_VAR_MATH_SHORTCUT(tan, FUNC_D2D_TYPE);
409 CHECK_VAR_MATH_SHORTCUT(exp, FUNC_D2D_TYPE);
410 CHECK_VAR_MATH_SHORTCUT(log, FUNC_D2D_TYPE);
411 CHECK_VAR_MATH_SHORTCUT(ceil, FUNC_D2D_TYPE);
412 CHECK_VAR_MATH_SHORTCUT(floor, FUNC_D2D_TYPE);
413 CHECK_VAR_MATH_SHORTCUT(sqrt, FUNC_D2D_TYPE);
414 // var exp = stdlib.Math.*; (DD2D * 12)
415 CHECK_VAR_MATH_SHORTCUT(min, FUNC_DD2D_TYPE);
416 CHECK_VAR_MATH_SHORTCUT(max, FUNC_DD2D_TYPE);
417 CHECK_VAR_MATH_SHORTCUT(atan2, FUNC_DD2D_TYPE);
418 CHECK_VAR_MATH_SHORTCUT(pow, FUNC_DD2D_TYPE);
420 CHECK_VAR_MATH_SHORTCUT(abs, FUNC_N2N_TYPE);
421 CHECK_VAR_MATH_SHORTCUT(imul, FUNC_II2I_TYPE);
422 CHECK_VAR_MATH_SHORTCUT(fround, FUNC_N2F_TYPE);
423 // var exp = stdlib.Math.*; (D * 12)
424 CHECK_VAR_MATH_SHORTCUT(E, Bounds(cache.kFloat64));
425 CHECK_VAR_MATH_SHORTCUT(LN10, Bounds(cache.kFloat64));
426 CHECK_VAR_MATH_SHORTCUT(LN2, Bounds(cache.kFloat64));
427 CHECK_VAR_MATH_SHORTCUT(LOG2E, Bounds(cache.kFloat64));
428 CHECK_VAR_MATH_SHORTCUT(LOG10E, Bounds(cache.kFloat64));
429 CHECK_VAR_MATH_SHORTCUT(PI, Bounds(cache.kFloat64));
430 CHECK_VAR_MATH_SHORTCUT(SQRT1_2, Bounds(cache.kFloat64));
431 CHECK_VAR_MATH_SHORTCUT(SQRT2, Bounds(cache.kFloat64));
432 // var values = new stdlib.*Array(buffer);
433 CHECK_VAR_NEW_SHORTCUT(u8, Bounds(cache.kUint8Array));
434 CHECK_VAR_NEW_SHORTCUT(i8, Bounds(cache.kInt8Array));
435 CHECK_VAR_NEW_SHORTCUT(u16, Bounds(cache.kUint16Array));
436 CHECK_VAR_NEW_SHORTCUT(i16, Bounds(cache.kInt16Array));
437 CHECK_VAR_NEW_SHORTCUT(u32, Bounds(cache.kUint32Array));
438 CHECK_VAR_NEW_SHORTCUT(i32, Bounds(cache.kInt32Array));
439 CHECK_VAR_NEW_SHORTCUT(f32, Bounds(cache.kFloat32Array));
440 CHECK_VAR_NEW_SHORTCUT(f64, Bounds(cache.kFloat64Array));
445 #define CHECK_FUNC_TYPES_BEGIN(func) \
447 func "\n" HARNESS_POSTAMBLE(); \
449 v8::V8::Initialize(); \
450 HandleAndZoneScope handles; \
451 Zone* zone = handles.main_zone(); \
452 ZoneVector<ExpressionTypeEntry> types(zone); \
453 CHECK_EQ("", Validate(zone, test_function, &types)); \
454 ZoneTypeCache cache; \
456 CHECK_TYPES_BEGIN { \
458 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
459 #define CHECK_FUNC_TYPES_END_1() \
461 CHECK_EXPR(Literal, Bounds(Type::String())); \
462 /* stdlib shortcuts. */ \
463 CheckStdlibShortcuts(zone, types, index, depth, cache);
466 #define CHECK_FUNC_TYPES_END_2() \
467 /* return { foo: foo }; */ \
468 CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) { \
469 CHECK_VAR(foo, FUNC_V_TYPE); \
476 #define CHECK_FUNC_TYPES_END \
477 CHECK_FUNC_TYPES_END_1(); \
478 CHECK_FUNC_TYPES_END_2();
481 #define CHECK_FUNC_ERROR(func, message) \
483 func "\n" HARNESS_POSTAMBLE(); \
485 v8::V8::Initialize(); \
486 HandleAndZoneScope handles; \
487 Zone* zone = handles.main_zone(); \
488 ZoneVector<ExpressionTypeEntry> types(zone); \
489 CHECK_EQ(message, Validate(zone, test_function, &types));
493 CHECK_FUNC_TYPES_BEGIN("function foo() {}") {
494 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {}
501 CHECK_FUNC_TYPES_BEGIN(
502 "function bar() { return; }\n"
503 "function foo() { bar(); }") {
504 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
506 CHECK_EXPR(Literal, Bounds(Type::Undefined()));
508 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
509 CHECK_EXPR(Call, Bounds(Type::Undefined())) {
510 CHECK_VAR(bar, FUNC_V_TYPE);
518 TEST(ReturnInt32Literal) {
519 CHECK_FUNC_TYPES_BEGIN(
520 "function bar() { return 1; }\n"
521 "function foo() { bar(); }") {
522 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
524 CHECK_EXPR(Literal, Bounds(cache.kInt32));
526 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
527 CHECK_EXPR(Call, Bounds(cache.kInt32)) { CHECK_VAR(bar, FUNC_I_TYPE); }
534 TEST(ReturnFloat64Literal) {
535 CHECK_FUNC_TYPES_BEGIN(
536 "function bar() { return 1.0; }\n"
537 "function foo() { bar(); }") {
538 CHECK_EXPR(FunctionLiteral, FUNC_D_TYPE) {
540 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
542 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
543 CHECK_EXPR(Call, Bounds(cache.kFloat64)) { CHECK_VAR(bar, FUNC_D_TYPE); }
550 TEST(ReturnFloat32Literal) {
551 CHECK_FUNC_TYPES_BEGIN(
552 "function bar() { return fround(1.0); }\n"
553 "function foo() { bar(); }") {
554 CHECK_EXPR(FunctionLiteral, FUNC_F_TYPE) {
555 // return fround(1.0);
556 CHECK_EXPR(Call, Bounds(cache.kFloat32)) {
557 CHECK_VAR(fround, FUNC_N2F_TYPE);
558 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
561 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
562 CHECK_EXPR(Call, Bounds(cache.kFloat32)) { CHECK_VAR(bar, FUNC_F_TYPE); }
569 TEST(ReturnFloat64Var) {
570 CHECK_FUNC_TYPES_BEGIN(
571 "function bar() { var x = 1.0; return +x; }\n"
572 "function foo() { bar(); }") {
573 CHECK_EXPR(FunctionLiteral, FUNC_D_TYPE) {
575 CHECK_EXPR(Assignment, Bounds(cache.kFloat64)) {
576 CHECK_VAR(x, Bounds(cache.kFloat64));
577 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
580 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
581 CHECK_VAR(x, Bounds(cache.kFloat64));
582 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
585 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
586 CHECK_EXPR(Call, Bounds(cache.kFloat64)) { CHECK_VAR(bar, FUNC_D_TYPE); }
594 CHECK_FUNC_TYPES_BEGIN(
595 "function bar() { var x = 1; var y = 2; return (x+y)|0; }\n"
596 "function foo() { bar(); }") {
597 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
598 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
599 CHECK_VAR(x, Bounds(cache.kInt32));
600 CHECK_EXPR(Literal, Bounds(cache.kInt32));
602 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
603 CHECK_VAR(y, Bounds(cache.kInt32));
604 CHECK_EXPR(Literal, Bounds(cache.kInt32));
606 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
607 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
608 CHECK_VAR(x, Bounds(cache.kInt32));
609 CHECK_VAR(y, Bounds(cache.kInt32));
611 CHECK_EXPR(Literal, Bounds(cache.kInt32));
621 CHECK_FUNC_TYPES_BEGIN(
622 "function bar() { var x = 1; var y = 2; return (x+y+x+y)|0; }\n"
623 "function foo() { bar(); }") {
624 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
625 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
626 CHECK_VAR(x, Bounds(cache.kInt32));
627 CHECK_EXPR(Literal, Bounds(cache.kInt32));
629 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
630 CHECK_VAR(y, Bounds(cache.kInt32));
631 CHECK_EXPR(Literal, Bounds(cache.kInt32));
633 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
634 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
635 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
636 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
637 CHECK_VAR(x, Bounds(cache.kInt32));
638 CHECK_VAR(y, Bounds(cache.kInt32));
640 CHECK_VAR(x, Bounds(cache.kInt32));
642 CHECK_VAR(y, Bounds(cache.kInt32));
644 CHECK_EXPR(Literal, Bounds(cache.kInt32));
653 TEST(Multiplication2) {
655 "function bar() { var x = 1; var y = 2; return (x*y)|0; }\n"
656 "function foo() { bar(); }",
657 "asm: line 39: direct integer multiply forbidden\n");
663 "function bar() { var x = 1; var y = 2; return (x/y/x/y)|0; }\n"
664 "function foo() { bar(); }",
665 "asm: line 39: too many consecutive multiplicative ops\n");
670 CHECK_FUNC_TYPES_BEGIN(
671 "function bar() { var x = 1; var y = i8[x>>0]|0; }\n"
672 "function foo() { bar(); }") {
673 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
674 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
675 CHECK_VAR(x, Bounds(cache.kInt32));
676 CHECK_EXPR(Literal, Bounds(cache.kInt32));
678 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
679 CHECK_VAR(y, Bounds(cache.kInt32));
680 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
681 CHECK_EXPR(Property, Bounds(cache.kInt8)) {
682 CHECK_VAR(i8, Bounds(cache.kInt8Array));
683 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
684 CHECK_VAR(x, Bounds(cache.kInt32));
685 CHECK_EXPR(Literal, Bounds(cache.kInt32));
688 CHECK_EXPR(Literal, Bounds(cache.kInt32));
698 TEST(FunctionTables) {
699 CHECK_FUNC_TYPES_BEGIN(
700 "function func1(x) { x = x | 0; return (x * 5) | 0; }\n"
701 "function func2(x) { x = x | 0; return (x * 25) | 0; }\n"
702 "var table1 = [func1, func2];\n"
703 "function bar(x, y) { x = x | 0; y = y | 0;\n"
704 " return table1[x & 1](y)|0; }\n"
705 "function foo() { bar(1, 2); }") {
706 CHECK_EXPR(FunctionLiteral, FUNC_I2I_TYPE) {
707 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
708 CHECK_VAR(x, Bounds(cache.kInt32));
709 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
710 CHECK_VAR(x, Bounds(cache.kInt32));
711 CHECK_EXPR(Literal, Bounds(cache.kInt32));
714 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
715 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
716 CHECK_VAR(x, Bounds(cache.kInt32));
717 CHECK_EXPR(Literal, Bounds(cache.kInt32));
719 CHECK_EXPR(Literal, Bounds(cache.kInt32));
722 CHECK_EXPR(FunctionLiteral, FUNC_I2I_TYPE) {
723 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
724 CHECK_VAR(x, Bounds(cache.kInt32));
725 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
726 CHECK_VAR(x, Bounds(cache.kInt32));
727 CHECK_EXPR(Literal, Bounds(cache.kInt32));
730 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
731 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
732 CHECK_VAR(x, Bounds(cache.kInt32));
733 CHECK_EXPR(Literal, Bounds(cache.kInt32));
735 CHECK_EXPR(Literal, Bounds(cache.kInt32));
738 CHECK_EXPR(FunctionLiteral, FUNC_II2I_TYPE) {
739 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
740 CHECK_VAR(x, Bounds(cache.kInt32));
741 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
742 CHECK_VAR(x, Bounds(cache.kInt32));
743 CHECK_EXPR(Literal, Bounds(cache.kInt32));
746 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
747 CHECK_VAR(y, Bounds(cache.kInt32));
748 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
749 CHECK_VAR(y, Bounds(cache.kInt32));
750 CHECK_EXPR(Literal, Bounds(cache.kInt32));
753 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
754 CHECK_EXPR(Call, Bounds(cache.kInt32)) {
755 CHECK_EXPR(Property, FUNC_I2I_TYPE) {
756 CHECK_VAR(table1, FUNC_I2I_ARRAY_TYPE);
757 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
758 CHECK_VAR(x, Bounds(cache.kInt32));
759 CHECK_EXPR(Literal, Bounds(cache.kInt32));
762 CHECK_VAR(y, Bounds(cache.kInt32));
764 CHECK_EXPR(Literal, Bounds(cache.kInt32));
769 CHECK_FUNC_TYPES_END_1();
770 CHECK_EXPR(Assignment, FUNC_I2I_ARRAY_TYPE) {
771 CHECK_VAR(table1, FUNC_I2I_ARRAY_TYPE);
772 CHECK_EXPR(ArrayLiteral, FUNC_I2I_ARRAY_TYPE) {
773 CHECK_VAR(func1, FUNC_I2I_TYPE);
774 CHECK_VAR(func2, FUNC_I2I_TYPE);
777 CHECK_FUNC_TYPES_END_2();
781 TEST(BadFunctionTable) {
783 "function func1(x) { x = x | 0; return (x * 5) | 0; }\n"
784 "var table1 = [func1, 1];\n"
785 "function bar(x, y) { x = x | 0; y = y | 0;\n"
786 " return table1[x & 1](y)|0; }\n"
787 "function foo() { bar(1, 2); }",
788 "asm: line 40: array component expected to be a function\n");
792 TEST(MissingParameterTypes) {
794 "function bar(x) { var y = 1; }\n"
795 "function foo() { bar(2); }",
796 "asm: line 39: missing parameter type annotations\n");
800 TEST(InvalidTypeAnnotationBinaryOpDiv) {
802 "function bar(x) { x = x / 4; }\n"
803 "function foo() { bar(2); }",
804 "asm: line 39: invalid type annotation on binary op\n");
808 TEST(InvalidTypeAnnotationBinaryOpMul) {
810 "function bar(x) { x = x * 4.0; }\n"
811 "function foo() { bar(2); }",
812 "asm: line 39: invalid type annotation on binary op\n");
816 TEST(InvalidArgumentCount) {
818 "function bar(x) { return fround(4, 5); }\n"
819 "function foo() { bar(); }",
820 "asm: line 39: invalid argument count calling fround\n");
824 TEST(InvalidTypeAnnotationArity) {
826 "function bar(x) { x = max(x); }\n"
827 "function foo() { bar(3); }",
828 "asm: line 39: only fround allowed on expression annotations\n");
832 TEST(InvalidTypeAnnotationOnlyFround) {
834 "function bar(x) { x = sin(x); }\n"
835 "function foo() { bar(3); }",
836 "asm: line 39: only fround allowed on expression annotations\n");
840 TEST(InvalidTypeAnnotation) {
842 "function bar(x) { x = (x+x)(x); }\n"
843 "function foo() { bar(3); }",
844 "asm: line 39: invalid type annotation\n");
848 TEST(WithStatement) {
850 "function bar() { var x = 0; with (x) { x = x + 1; } }\n"
851 "function foo() { bar(); }",
852 "asm: line 39: bad with statement\n");
856 TEST(NestedFunction) {
858 "function bar() { function x() { return 1; } }\n"
859 "function foo() { bar(); }",
860 "asm: line 39: function declared inside another\n");
864 TEST(UnboundVariable) {
866 "function bar() { var x = y; }\n"
867 "function foo() { bar(); }",
868 "asm: line 39: unbound variable\n");
872 TEST(ForeignFunction) {
873 CHECK_FUNC_TYPES_BEGIN(
874 "var baz = foreign.baz;\n"
875 "function bar() { return baz(1, 2)|0; }\n"
876 "function foo() { bar(); }") {
877 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
878 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
879 CHECK_EXPR(Call, Bounds(Type::Number(zone))) {
880 CHECK_VAR(baz, Bounds(Type::Any()));
881 CHECK_EXPR(Literal, Bounds(cache.kInt32));
882 CHECK_EXPR(Literal, Bounds(cache.kInt32));
884 CHECK_EXPR(Literal, Bounds(cache.kInt32));
887 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
888 CHECK_EXPR(Call, Bounds(cache.kInt32)) { CHECK_VAR(bar, FUNC_I_TYPE); }
891 CHECK_FUNC_TYPES_END_1()
892 CHECK_EXPR(Assignment, Bounds(Type::Any())) {
893 CHECK_VAR(baz, Bounds(Type::Any()));
894 CHECK_EXPR(Property, Bounds(Type::Any())) {
895 CHECK_VAR(foreign, Bounds::Unbounded());
896 CHECK_EXPR(Literal, Bounds::Unbounded());
899 CHECK_FUNC_TYPES_END_2()
905 "function foo() {};\n"
906 "return {foo: foo, bar: 1};"
909 v8::V8::Initialize();
910 HandleAndZoneScope handles;
911 Zone* zone = handles.main_zone();
912 ZoneVector<ExpressionTypeEntry> types(zone);
913 CHECK_EQ("asm: line 40: non-function in function table\n",
914 Validate(zone, test_function, &types));