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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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