Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: src/typing-asm.cc

Issue 2011873002: [wasm] Check that type intersections don't yield empty. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/mjsunit/wasm/asm-wasm.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/typing-asm.h" 5 #include "src/typing-asm.h"
6 6
7 #include <limits> 7 #include <limits>
8 8
9 #include "src/v8.h" 9 #include "src/v8.h"
10 10
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 501
502 Type* type = bounds_.get(expr).upper; 502 Type* type = bounds_.get(expr).upper;
503 Type* save_return_type = return_type_; 503 Type* save_return_type = return_type_;
504 return_type_ = type->AsFunction()->Result(); 504 return_type_ = type->AsFunction()->Result();
505 in_function_ = true; 505 in_function_ = true;
506 local_variable_type_.Clear(); 506 local_variable_type_.Clear();
507 RECURSE(VisitDeclarations(scope->declarations())); 507 RECURSE(VisitDeclarations(scope->declarations()));
508 RECURSE(VisitStatements(expr->body())); 508 RECURSE(VisitStatements(expr->body()));
509 in_function_ = false; 509 in_function_ = false;
510 return_type_ = save_return_type; 510 return_type_ = save_return_type;
511 IntersectResult(expr, type); 511 RECURSE(IntersectResult(expr, type));
512 } 512 }
513 513
514 514
515 void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { 515 void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
516 FAIL(expr, "function info literal encountered"); 516 FAIL(expr, "function info literal encountered");
517 } 517 }
518 518
519 519
520 void AsmTyper::VisitDoExpression(DoExpression* expr) { 520 void AsmTyper::VisitDoExpression(DoExpression* expr) {
521 FAIL(expr, "do-expression encountered"); 521 FAIL(expr, "do-expression encountered");
(...skipping 23 matching lines...) Expand all
545 "conditional else branch type mismatch with enclosing expression")); 545 "conditional else branch type mismatch with enclosing expression"));
546 Type* else_type = StorageType(computed_type_); 546 Type* else_type = StorageType(computed_type_);
547 if (intish_ != 0 || !else_type->Is(cache_.kAsmComparable)) { 547 if (intish_ != 0 || !else_type->Is(cache_.kAsmComparable)) {
548 FAIL(expr->else_expression(), "invalid type in ? else expression"); 548 FAIL(expr->else_expression(), "invalid type in ? else expression");
549 } 549 }
550 550
551 if (!then_type->Is(else_type) || !else_type->Is(then_type)) { 551 if (!then_type->Is(else_type) || !else_type->Is(then_type)) {
552 FAIL(expr, "then and else expressions in ? must have the same type"); 552 FAIL(expr, "then and else expressions in ? must have the same type");
553 } 553 }
554 554
555 IntersectResult(expr, then_type); 555 RECURSE(IntersectResult(expr, then_type));
556 } 556 }
557 557
558 558
559 void AsmTyper::VisitVariableProxy(VariableProxy* expr) { 559 void AsmTyper::VisitVariableProxy(VariableProxy* expr) {
560 Variable* var = expr->var(); 560 Variable* var = expr->var();
561 VariableInfo* info = GetVariableInfo(var); 561 VariableInfo* info = GetVariableInfo(var);
562 if (!in_function_ && !building_function_tables_ && !visiting_exports_) { 562 if (!in_function_ && !building_function_tables_ && !visiting_exports_) {
563 if (var->location() != VariableLocation::PARAMETER || var->index() >= 3) { 563 if (var->location() != VariableLocation::PARAMETER || var->index() >= 3) {
564 FAIL(expr, "illegal variable reference in module body"); 564 FAIL(expr, "illegal variable reference in module body");
565 } 565 }
566 } 566 }
567 if (info == nullptr || info->type == nullptr) { 567 if (info == nullptr || info->type == nullptr) {
568 if (var->mode() == TEMPORARY) { 568 if (var->mode() == TEMPORARY) {
569 SetType(var, Type::Any()); 569 SetType(var, Type::Any());
570 info = GetVariableInfo(var); 570 info = GetVariableInfo(var);
571 } else { 571 } else {
572 FAIL(expr, "unbound variable"); 572 FAIL(expr, "unbound variable");
573 } 573 }
574 } 574 }
575 if (property_info_ != nullptr) { 575 if (property_info_ != nullptr) {
576 SetVariableInfo(var, property_info_); 576 SetVariableInfo(var, property_info_);
577 property_info_ = nullptr; 577 property_info_ = nullptr;
578 } 578 }
579 Type* type = Type::Intersect(info->type, expected_type_, zone()); 579 Type* type = Type::Intersect(info->type, expected_type_, zone());
580 if (type->Is(cache_.kAsmInt)) type = cache_.kAsmInt; 580 if (type->Is(cache_.kAsmInt)) type = cache_.kAsmInt;
581 intish_ = 0; 581 intish_ = 0;
582 IntersectResult(expr, type); 582 RECURSE(IntersectResult(expr, type));
583 } 583 }
584 584
585 void AsmTyper::VisitLiteral(Literal* expr, bool is_return) { 585 void AsmTyper::VisitLiteral(Literal* expr, bool is_return) {
586 intish_ = 0; 586 intish_ = 0;
587 Handle<Object> value = expr->value(); 587 Handle<Object> value = expr->value();
588 if (value->IsNumber()) { 588 if (value->IsNumber()) {
589 int32_t i; 589 int32_t i;
590 uint32_t u; 590 uint32_t u;
591 if (expr->raw_value()->ContainsDot()) { 591 if (expr->raw_value()->ContainsDot()) {
592 IntersectResult(expr, cache_.kAsmDouble); 592 RECURSE(IntersectResult(expr, cache_.kAsmDouble));
593 } else if (!is_return && value->ToUint32(&u)) { 593 } else if (!is_return && value->ToUint32(&u)) {
594 if (u <= 0x7fffffff) { 594 if (u <= 0x7fffffff) {
595 IntersectResult(expr, cache_.kAsmFixnum); 595 RECURSE(IntersectResult(expr, cache_.kAsmFixnum));
596 } else { 596 } else {
597 IntersectResult(expr, cache_.kAsmUnsigned); 597 RECURSE(IntersectResult(expr, cache_.kAsmUnsigned));
598 } 598 }
599 } else if (value->ToInt32(&i)) { 599 } else if (value->ToInt32(&i)) {
600 IntersectResult(expr, cache_.kAsmSigned); 600 RECURSE(IntersectResult(expr, cache_.kAsmSigned));
601 } else { 601 } else {
602 FAIL(expr, "illegal number"); 602 FAIL(expr, "illegal number");
603 } 603 }
604 } else if (!is_return && value->IsString()) { 604 } else if (!is_return && value->IsString()) {
605 IntersectResult(expr, Type::String()); 605 RECURSE(IntersectResult(expr, Type::String()));
606 } else if (value->IsUndefined()) { 606 } else if (value->IsUndefined()) {
607 IntersectResult(expr, Type::Undefined()); 607 RECURSE(IntersectResult(expr, Type::Undefined()));
608 } else { 608 } else {
609 FAIL(expr, "illegal literal"); 609 FAIL(expr, "illegal literal");
610 } 610 }
611 } 611 }
612 612
613 613
614 void AsmTyper::VisitLiteral(Literal* expr) { VisitLiteral(expr, false); } 614 void AsmTyper::VisitLiteral(Literal* expr) { VisitLiteral(expr, false); }
615 615
616 616
617 void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) { 617 void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
618 FAIL(expr, "regular expression encountered"); 618 FAIL(expr, "regular expression encountered");
619 } 619 }
620 620
621 621
622 void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) { 622 void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) {
623 if (in_function_) { 623 if (in_function_) {
624 FAIL(expr, "object literal in function"); 624 FAIL(expr, "object literal in function");
625 } 625 }
626 // Allowed for asm module's export declaration. 626 // Allowed for asm module's export declaration.
627 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); 627 ZoneList<ObjectLiteralProperty*>* props = expr->properties();
628 for (int i = 0; i < props->length(); ++i) { 628 for (int i = 0; i < props->length(); ++i) {
629 ObjectLiteralProperty* prop = props->at(i); 629 ObjectLiteralProperty* prop = props->at(i);
630 RECURSE(VisitWithExpectation(prop->value(), Type::Any(), 630 RECURSE(VisitWithExpectation(prop->value(), Type::Any(),
631 "object property expected to be a function")); 631 "object property expected to be a function"));
632 if (!computed_type_->IsFunction()) { 632 if (!computed_type_->IsFunction()) {
633 FAIL(prop->value(), "non-function in function table"); 633 FAIL(prop->value(), "non-function in function table");
634 } 634 }
635 } 635 }
636 IntersectResult(expr, Type::Object()); 636 RECURSE(IntersectResult(expr, Type::Object()));
637 } 637 }
638 638
639 639
640 void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) { 640 void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) {
641 if (in_function_) { 641 if (in_function_) {
642 FAIL(expr, "array literal inside a function"); 642 FAIL(expr, "array literal inside a function");
643 } 643 }
644 // Allowed for function tables. 644 // Allowed for function tables.
645 ZoneList<Expression*>* values = expr->values(); 645 ZoneList<Expression*>* values = expr->values();
646 Type* elem_type = Type::None(); 646 Type* elem_type = Type::None();
647 for (int i = 0; i < values->length(); ++i) { 647 for (int i = 0; i < values->length(); ++i) {
648 Expression* value = values->at(i); 648 Expression* value = values->at(i);
649 RECURSE(VisitWithExpectation(value, Type::Any(), "UNREACHABLE")); 649 RECURSE(VisitWithExpectation(value, Type::Any(), "UNREACHABLE"));
650 if (!computed_type_->IsFunction()) { 650 if (!computed_type_->IsFunction()) {
651 FAIL(value, "array component expected to be a function"); 651 FAIL(value, "array component expected to be a function");
652 } 652 }
653 elem_type = Type::Union(elem_type, computed_type_, zone()); 653 elem_type = Type::Union(elem_type, computed_type_, zone());
654 } 654 }
655 array_size_ = values->length(); 655 array_size_ = values->length();
656 IntersectResult(expr, Type::Array(elem_type, zone())); 656 RECURSE(IntersectResult(expr, Type::Array(elem_type, zone())));
657 } 657 }
658 658
659 659
660 void AsmTyper::VisitAssignment(Assignment* expr) { 660 void AsmTyper::VisitAssignment(Assignment* expr) {
661 // Handle function tables and everything else in different passes. 661 // Handle function tables and everything else in different passes.
662 if (!in_function_) { 662 if (!in_function_) {
663 if (expr->value()->IsArrayLiteral()) { 663 if (expr->value()->IsArrayLiteral()) {
664 if (!building_function_tables_) { 664 if (!building_function_tables_) {
665 return; 665 return;
666 } 666 }
(...skipping 27 matching lines...) Expand all
694 } 694 }
695 } 695 }
696 if (property_info_ != nullptr) { 696 if (property_info_ != nullptr) {
697 SetVariableInfo(var, property_info_); 697 SetVariableInfo(var, property_info_);
698 property_info_ = nullptr; 698 property_info_ = nullptr;
699 } 699 }
700 Type* type = Type::Intersect(info->type, expected_type_, zone()); 700 Type* type = Type::Intersect(info->type, expected_type_, zone());
701 if (type->Is(cache_.kAsmInt)) type = cache_.kAsmInt; 701 if (type->Is(cache_.kAsmInt)) type = cache_.kAsmInt;
702 info->type = type; 702 info->type = type;
703 intish_ = 0; 703 intish_ = 0;
704 IntersectResult(proxy, type); 704 RECURSE(IntersectResult(proxy, type));
705 } else if (expr->target()->IsProperty()) { 705 } else if (expr->target()->IsProperty()) {
706 // Assignment to a property: should be a heap assignment {H[x] = y}. 706 // Assignment to a property: should be a heap assignment {H[x] = y}.
707 int32_t value_intish = intish_; 707 int32_t value_intish = intish_;
708 Property* property = expr->target()->AsProperty(); 708 Property* property = expr->target()->AsProperty();
709 RECURSE(VisitWithExpectation(property->obj(), Type::Any(), 709 RECURSE(VisitWithExpectation(property->obj(), Type::Any(),
710 "bad propety object")); 710 "bad propety object"));
711 if (!computed_type_->IsArray()) { 711 if (!computed_type_->IsArray()) {
712 FAIL(property->obj(), "array expected"); 712 FAIL(property->obj(), "array expected");
713 } 713 }
714 if (value_intish != 0 && computed_type_->Is(cache_.kFloat64Array)) { 714 if (value_intish != 0 && computed_type_->Is(cache_.kFloat64Array)) {
715 FAIL(expr, "floatish assignment to double array"); 715 FAIL(expr, "floatish assignment to double array");
716 } 716 }
717 VisitHeapAccess(property, true, target_type); 717 VisitHeapAccess(property, true, target_type);
718 } 718 }
719 IntersectResult(expr, target_type); 719 RECURSE(IntersectResult(expr, target_type));
720 if (bounds_.get(expr).upper->Is(Type::None())) {
ahaas 2016/05/25 10:09:11 You could just write DCHECK(bounds_.get(expr).uppe
bradn 2016/05/25 16:26:49 Done.
721 DCHECK(false);
722 }
720 } 723 }
721 724
722 725
723 void AsmTyper::VisitYield(Yield* expr) { 726 void AsmTyper::VisitYield(Yield* expr) {
724 FAIL(expr, "yield expression encountered"); 727 FAIL(expr, "yield expression encountered");
725 } 728 }
726 729
727 730
728 void AsmTyper::VisitThrow(Throw* expr) { 731 void AsmTyper::VisitThrow(Throw* expr) {
729 FAIL(expr, "throw statement encountered"); 732 FAIL(expr, "throw statement encountered");
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
769 // FAIL(right, "call mask must be integer"); 772 // FAIL(right, "call mask must be integer");
770 // } 773 // }
771 // RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned, 774 // RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned,
772 // "call mask expected to be integer")); 775 // "call mask expected to be integer"));
773 // if (static_cast<size_t>(right->raw_value()->AsNumber()) != size - 1) { 776 // if (static_cast<size_t>(right->raw_value()->AsNumber()) != size - 1) {
774 // FAIL(right, "call mask must match function table"); 777 // FAIL(right, "call mask must match function table");
775 // } 778 // }
776 // bin->set_bounds(Bounds(cache_.kAsmSigned)); 779 // bin->set_bounds(Bounds(cache_.kAsmSigned));
777 RECURSE(VisitWithExpectation(expr->key(), cache_.kAsmSigned, 780 RECURSE(VisitWithExpectation(expr->key(), cache_.kAsmSigned,
778 "must be integer")); 781 "must be integer"));
779 IntersectResult(expr, type); 782 RECURSE(IntersectResult(expr, type));
780 } else { 783 } else {
781 Literal* literal = expr->key()->AsLiteral(); 784 Literal* literal = expr->key()->AsLiteral();
782 if (literal) { 785 if (literal) {
783 RECURSE(VisitWithExpectation(literal, cache_.kAsmSigned, 786 RECURSE(VisitWithExpectation(literal, cache_.kAsmSigned,
784 "array index expected to be integer")); 787 "array index expected to be integer"));
785 } else { 788 } else {
786 int expected_shift = ElementShiftSize(type); 789 int expected_shift = ElementShiftSize(type);
787 if (expected_shift == 0) { 790 if (expected_shift == 0) {
788 RECURSE(Visit(expr->key())); 791 RECURSE(Visit(expr->key()));
789 } else { 792 } else {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
828 } 831 }
829 intish_ = 0; 832 intish_ = 0;
830 } else { 833 } else {
831 UNREACHABLE(); 834 UNREACHABLE();
832 } 835 }
833 if (assigning) { 836 if (assigning) {
834 if (!assignment_type->Is(result_type)) { 837 if (!assignment_type->Is(result_type)) {
835 FAIL(expr, "illegal type in assignment"); 838 FAIL(expr, "illegal type in assignment");
836 } 839 }
837 } else { 840 } else {
838 IntersectResult(expr, expected_type_); 841 RECURSE(IntersectResult(expr, expected_type_));
839 IntersectResult(expr, result_type); 842 RECURSE(IntersectResult(expr, result_type));
840 } 843 }
841 } 844 }
842 } 845 }
843 846
844 847
845 bool AsmTyper::IsStdlibObject(Expression* expr) { 848 bool AsmTyper::IsStdlibObject(Expression* expr) {
846 VariableProxy* proxy = expr->AsVariableProxy(); 849 VariableProxy* proxy = expr->AsVariableProxy();
847 if (proxy == nullptr) { 850 if (proxy == nullptr) {
848 return false; 851 return false;
849 } 852 }
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
1027 if (!computed_type_->Is(cache_.kAsmSigned) && 1030 if (!computed_type_->Is(cache_.kAsmSigned) &&
1028 !computed_type_->Is(cache_.kAsmFixnum) && 1031 !computed_type_->Is(cache_.kAsmFixnum) &&
1029 !computed_type_->Is(cache_.kAsmDouble)) { 1032 !computed_type_->Is(cache_.kAsmDouble)) {
1030 FAIL(arg, 1033 FAIL(arg,
1031 "foreign call argument expected to be int, double, or fixnum"); 1034 "foreign call argument expected to be int, double, or fixnum");
1032 } 1035 }
1033 } 1036 }
1034 intish_ = 0; 1037 intish_ = 0;
1035 bounds_.set(expr->expression(), 1038 bounds_.set(expr->expression(),
1036 Bounds(Type::Function(Type::Any(), zone()))); 1039 Bounds(Type::Function(Type::Any(), zone())));
1037 IntersectResult(expr, expected_type); 1040 RECURSE(IntersectResult(expr, expected_type));
1038 } else { 1041 } else {
1039 if (fun_type->Arity() != args->length()) { 1042 if (fun_type->Arity() != args->length()) {
1040 FAIL(expr, "call with wrong arity"); 1043 FAIL(expr, "call with wrong arity");
1041 } 1044 }
1042 for (int i = 0; i < args->length(); ++i) { 1045 for (int i = 0; i < args->length(); ++i) {
1043 Expression* arg = args->at(i); 1046 Expression* arg = args->at(i);
1044 RECURSE(VisitWithExpectation( 1047 RECURSE(VisitWithExpectation(
1045 arg, fun_type->Parameter(i), 1048 arg, fun_type->Parameter(i),
1046 "call argument expected to match callee parameter")); 1049 "call argument expected to match callee parameter"));
1047 if (standard_member != kNone && standard_member != kMathFround && 1050 if (standard_member != kNone && standard_member != kMathFround &&
1048 i == 0) { 1051 i == 0) {
1049 result_type = computed_type_; 1052 result_type = computed_type_;
1050 } 1053 }
1051 } 1054 }
1052 RECURSE(CheckPolymorphicStdlibArguments(standard_member, args)); 1055 RECURSE(CheckPolymorphicStdlibArguments(standard_member, args));
1053 intish_ = 0; 1056 intish_ = 0;
1054 IntersectResult(expr, result_type); 1057 RECURSE(IntersectResult(expr, result_type));
1055 } 1058 }
1056 } else { 1059 } else {
1057 FAIL(expr, "invalid callee"); 1060 FAIL(expr, "invalid callee");
1058 } 1061 }
1059 } 1062 }
1060 1063
1061 1064
1062 void AsmTyper::VisitCallNew(CallNew* expr) { 1065 void AsmTyper::VisitCallNew(CallNew* expr) {
1063 if (in_function_) { 1066 if (in_function_) {
1064 FAIL(expr, "new not allowed in module function"); 1067 FAIL(expr, "new not allowed in module function");
1065 } 1068 }
1066 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), 1069 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(),
1067 "expected stdlib function")); 1070 "expected stdlib function"));
1068 if (computed_type_->IsFunction()) { 1071 if (computed_type_->IsFunction()) {
1069 FunctionType* fun_type = computed_type_->AsFunction(); 1072 FunctionType* fun_type = computed_type_->AsFunction();
1070 ZoneList<Expression*>* args = expr->arguments(); 1073 ZoneList<Expression*>* args = expr->arguments();
1071 if (fun_type->Arity() != args->length()) 1074 if (fun_type->Arity() != args->length())
1072 FAIL(expr, "call with wrong arity"); 1075 FAIL(expr, "call with wrong arity");
1073 for (int i = 0; i < args->length(); ++i) { 1076 for (int i = 0; i < args->length(); ++i) {
1074 Expression* arg = args->at(i); 1077 Expression* arg = args->at(i);
1075 RECURSE(VisitWithExpectation( 1078 RECURSE(VisitWithExpectation(
1076 arg, fun_type->Parameter(i), 1079 arg, fun_type->Parameter(i),
1077 "constructor argument expected to match callee parameter")); 1080 "constructor argument expected to match callee parameter"));
1078 } 1081 }
1079 IntersectResult(expr, fun_type->Result()); 1082 RECURSE(IntersectResult(expr, fun_type->Result()));
1080 return; 1083 return;
1081 } 1084 }
1082 1085
1083 FAIL(expr, "ill-typed new operator"); 1086 FAIL(expr, "ill-typed new operator");
1084 } 1087 }
1085 1088
1086 1089
1087 void AsmTyper::VisitCallRuntime(CallRuntime* expr) { 1090 void AsmTyper::VisitCallRuntime(CallRuntime* expr) {
1088 FAIL(expr, "runtime call not allowed"); 1091 FAIL(expr, "runtime call not allowed");
1089 } 1092 }
1090 1093
1091 1094
1092 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) { 1095 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) {
1093 if (!in_function_) { 1096 if (!in_function_) {
1094 FAIL(expr, "unary operator inside module body"); 1097 FAIL(expr, "unary operator inside module body");
1095 } 1098 }
1096 switch (expr->op()) { 1099 switch (expr->op()) {
1097 case Token::NOT: // Used to encode != and !== 1100 case Token::NOT: // Used to encode != and !==
1098 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt, 1101 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt,
1099 "operand expected to be integer")); 1102 "operand expected to be integer"));
1100 IntersectResult(expr, cache_.kAsmSigned); 1103 RECURSE(IntersectResult(expr, cache_.kAsmSigned));
1101 return; 1104 return;
1102 case Token::DELETE: 1105 case Token::DELETE:
1103 FAIL(expr, "delete operator encountered"); 1106 FAIL(expr, "delete operator encountered");
1104 case Token::VOID: 1107 case Token::VOID:
1105 FAIL(expr, "void operator encountered"); 1108 FAIL(expr, "void operator encountered");
1106 case Token::TYPEOF: 1109 case Token::TYPEOF:
1107 FAIL(expr, "typeof operator encountered"); 1110 FAIL(expr, "typeof operator encountered");
1108 default: 1111 default:
1109 UNREACHABLE(); 1112 UNREACHABLE();
1110 } 1113 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 left_type = right_type; 1152 left_type = right_type;
1150 } 1153 }
1151 if (right_type->Is(cache_.kAsmFixnum) && left_type->Is(cache_.kAsmInt)) { 1154 if (right_type->Is(cache_.kAsmFixnum) && left_type->Is(cache_.kAsmInt)) {
1152 right_type = left_type; 1155 right_type = left_type;
1153 } 1156 }
1154 if (!conversion) { 1157 if (!conversion) {
1155 if (!left_type->Is(cache_.kAsmIntQ) || !right_type->Is(cache_.kAsmIntQ)) { 1158 if (!left_type->Is(cache_.kAsmIntQ) || !right_type->Is(cache_.kAsmIntQ)) {
1156 FAIL(expr, "ill-typed bitwise operation"); 1159 FAIL(expr, "ill-typed bitwise operation");
1157 } 1160 }
1158 } 1161 }
1159 IntersectResult(expr, result_type); 1162 RECURSE(IntersectResult(expr, result_type));
1160 } 1163 }
1161 1164
1162 1165
1163 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { 1166 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
1164 if (!in_function_) { 1167 if (!in_function_) {
1165 if (expr->op() != Token::BIT_OR && expr->op() != Token::MUL) { 1168 if (expr->op() != Token::BIT_OR && expr->op() != Token::MUL) {
1166 FAIL(expr, "illegal binary operator inside module body"); 1169 FAIL(expr, "illegal binary operator inside module body");
1167 } 1170 }
1168 if (!(expr->left()->IsProperty() || expr->left()->IsVariableProxy()) || 1171 if (!(expr->left()->IsProperty() || expr->left()->IsVariableProxy()) ||
1169 !expr->right()->IsLiteral()) { 1172 !expr->right()->IsLiteral()) {
(...skipping 11 matching lines...) Expand all
1181 FAIL(expr, "illegal double annotation value"); 1184 FAIL(expr, "illegal double annotation value");
1182 } 1185 }
1183 } 1186 }
1184 } 1187 }
1185 switch (expr->op()) { 1188 switch (expr->op()) {
1186 case Token::COMMA: { 1189 case Token::COMMA: {
1187 RECURSE(VisitWithExpectation(expr->left(), Type::Any(), 1190 RECURSE(VisitWithExpectation(expr->left(), Type::Any(),
1188 "left comma operand expected to be any")); 1191 "left comma operand expected to be any"));
1189 RECURSE(VisitWithExpectation(expr->right(), Type::Any(), 1192 RECURSE(VisitWithExpectation(expr->right(), Type::Any(),
1190 "right comma operand expected to be any")); 1193 "right comma operand expected to be any"));
1191 IntersectResult(expr, computed_type_); 1194 RECURSE(IntersectResult(expr, computed_type_));
1192 return; 1195 return;
1193 } 1196 }
1194 case Token::OR: 1197 case Token::OR:
1195 case Token::AND: 1198 case Token::AND:
1196 FAIL(expr, "illegal logical operator"); 1199 FAIL(expr, "illegal logical operator");
1197 case Token::BIT_OR: { 1200 case Token::BIT_OR: {
1198 // BIT_OR allows Any since it is used as a type coercion. 1201 // BIT_OR allows Any since it is used as a type coercion.
1199 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ, 1202 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ,
1200 cache_.kAsmSigned, true)); 1203 cache_.kAsmSigned, true));
1201 if (expr->left()->IsCall() && expr->op() == Token::BIT_OR && 1204 if (expr->left()->IsCall() && expr->op() == Token::BIT_OR &&
1202 Type::Number()->Is(bounds_.get(expr->left()).upper)) { 1205 Type::Number()->Is(bounds_.get(expr->left()).upper)) {
1203 // Force the return types of foreign functions. 1206 // Force the return types of foreign functions.
1204 bounds_.set(expr->left(), Bounds(cache_.kAsmSigned)); 1207 bounds_.set(expr->left(), Bounds(cache_.kAsmSigned));
1205 } 1208 }
1206 if (in_function_ && 1209 if (in_function_ &&
1207 !bounds_.get(expr->left()).upper->Is(cache_.kAsmIntQ)) { 1210 !bounds_.get(expr->left()).upper->Is(cache_.kAsmIntQ)) {
1208 FAIL(expr->left(), "intish required"); 1211 FAIL(expr->left(), "intish required");
1209 } 1212 }
1210 return; 1213 return;
1211 } 1214 }
1212 case Token::BIT_XOR: { 1215 case Token::BIT_XOR: {
1213 // Handle booleans specially to handle de-sugared ! 1216 // Handle booleans specially to handle de-sugared !
1214 Literal* left = expr->left()->AsLiteral(); 1217 Literal* left = expr->left()->AsLiteral();
1215 if (left && left->value()->IsBoolean()) { 1218 if (left && left->value()->IsBoolean()) {
1216 if (left->ToBooleanIsTrue()) { 1219 if (left->ToBooleanIsTrue()) {
1217 bounds_.set(left, Bounds(cache_.kSingletonOne)); 1220 bounds_.set(left, Bounds(cache_.kSingletonOne));
1218 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmIntQ, 1221 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmIntQ,
1219 "not operator expects an integer")); 1222 "not operator expects an integer"));
1220 IntersectResult(expr, cache_.kAsmSigned); 1223 RECURSE(IntersectResult(expr, cache_.kAsmSigned));
1221 return; 1224 return;
1222 } else { 1225 } else {
1223 FAIL(left, "unexpected false"); 1226 FAIL(left, "unexpected false");
1224 } 1227 }
1225 } 1228 }
1226 // BIT_XOR allows Any since it is used as a type coercion (via ~~). 1229 // BIT_XOR allows Any since it is used as a type coercion (via ~~).
1227 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ, 1230 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ,
1228 cache_.kAsmSigned, true)); 1231 cache_.kAsmSigned, true));
1229 return; 1232 return;
1230 } 1233 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1272 FAIL(expr, "intish not allowed in multiply"); 1275 FAIL(expr, "intish not allowed in multiply");
1273 } 1276 }
1274 } else { 1277 } else {
1275 FAIL(expr, "multiply must be by an integer literal"); 1278 FAIL(expr, "multiply must be by an integer literal");
1276 } 1279 }
1277 i = abs(i); 1280 i = abs(i);
1278 if (i >= (1 << 20)) { 1281 if (i >= (1 << 20)) {
1279 FAIL(expr, "multiply must be by value in -2^20 < n < 2^20"); 1282 FAIL(expr, "multiply must be by value in -2^20 < n < 2^20");
1280 } 1283 }
1281 intish_ = i; 1284 intish_ = i;
1282 IntersectResult(expr, cache_.kAsmInt); 1285 RECURSE(IntersectResult(expr, cache_.kAsmInt));
1283 return; 1286 return;
1284 } else { 1287 } else {
1285 intish_ = left_intish + right_intish + 1; 1288 intish_ = left_intish + right_intish + 1;
1286 if (expr->op() == Token::ADD || expr->op() == Token::SUB) { 1289 if (expr->op() == Token::ADD || expr->op() == Token::SUB) {
1287 if (intish_ > kMaxUncombinedAdditiveSteps) { 1290 if (intish_ > kMaxUncombinedAdditiveSteps) {
1288 FAIL(expr, "too many consecutive additive ops"); 1291 FAIL(expr, "too many consecutive additive ops");
1289 } 1292 }
1290 } else { 1293 } else {
1291 if (intish_ > kMaxUncombinedMultiplicativeSteps) { 1294 if (intish_ > kMaxUncombinedMultiplicativeSteps) {
1292 FAIL(expr, "too many consecutive multiplicative ops"); 1295 FAIL(expr, "too many consecutive multiplicative ops");
1293 } 1296 }
1294 } 1297 }
1295 IntersectResult(expr, cache_.kAsmInt); 1298 RECURSE(IntersectResult(expr, cache_.kAsmInt));
1296 return; 1299 return;
1297 } 1300 }
1298 } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() && 1301 } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() &&
1299 right_type->Is(cache_.kAsmDouble) && 1302 right_type->Is(cache_.kAsmDouble) &&
1300 expr->right()->AsLiteral()->raw_value()->ContainsDot() && 1303 expr->right()->AsLiteral()->raw_value()->ContainsDot() &&
1301 expr->right()->AsLiteral()->raw_value()->AsNumber() == 1.0) { 1304 expr->right()->AsLiteral()->raw_value()->AsNumber() == 1.0) {
1302 // For unary +, expressed as x * 1.0 1305 // For unary +, expressed as x * 1.0
1303 if (expr->left()->IsCall() && 1306 if (expr->left()->IsCall() &&
1304 Type::Number()->Is(bounds_.get(expr->left()).upper)) { 1307 Type::Number()->Is(bounds_.get(expr->left()).upper)) {
1305 // Force the return types of foreign functions. 1308 // Force the return types of foreign functions.
1306 bounds_.set(expr->left(), Bounds(cache_.kAsmDouble)); 1309 bounds_.set(expr->left(), Bounds(cache_.kAsmDouble));
1307 left_type = bounds_.get(expr->left()).upper; 1310 left_type = bounds_.get(expr->left()).upper;
1308 } 1311 }
1309 if (!(expr->left()->IsProperty() && 1312 if (!(expr->left()->IsProperty() &&
1310 Type::Number()->Is(bounds_.get(expr->left()).upper))) { 1313 Type::Number()->Is(bounds_.get(expr->left()).upper))) {
1311 if (!left_type->Is(cache_.kAsmSigned) && 1314 if (!left_type->Is(cache_.kAsmSigned) &&
1312 !left_type->Is(cache_.kAsmUnsigned) && 1315 !left_type->Is(cache_.kAsmUnsigned) &&
1313 !left_type->Is(cache_.kAsmFixnum) && 1316 !left_type->Is(cache_.kAsmFixnum) &&
1314 !left_type->Is(cache_.kAsmFloatQ) && 1317 !left_type->Is(cache_.kAsmFloatQ) &&
1315 !left_type->Is(cache_.kAsmDoubleQ)) { 1318 !left_type->Is(cache_.kAsmDoubleQ)) {
1316 FAIL( 1319 FAIL(
1317 expr->left(), 1320 expr->left(),
1318 "unary + only allowed on signed, unsigned, float?, or double?"); 1321 "unary + only allowed on signed, unsigned, float?, or double?");
1319 } 1322 }
1320 } 1323 }
1321 IntersectResult(expr, cache_.kAsmDouble); 1324 RECURSE(IntersectResult(expr, cache_.kAsmDouble));
1322 return; 1325 return;
1323 } else if (expr->op() == Token::MUL && left_type->Is(cache_.kAsmDouble) && 1326 } else if (expr->op() == Token::MUL && left_type->Is(cache_.kAsmDouble) &&
1324 expr->right()->IsLiteral() && 1327 expr->right()->IsLiteral() &&
1325 !expr->right()->AsLiteral()->raw_value()->ContainsDot() && 1328 !expr->right()->AsLiteral()->raw_value()->ContainsDot() &&
1326 expr->right()->AsLiteral()->raw_value()->AsNumber() == -1.0) { 1329 expr->right()->AsLiteral()->raw_value()->AsNumber() == -1.0) {
1327 // For unary -, expressed as x * -1 1330 // For unary -, expressed as x * -1
1328 bounds_.set(expr->right(), Bounds(cache_.kAsmDouble)); 1331 bounds_.set(expr->right(), Bounds(cache_.kAsmDouble));
1329 IntersectResult(expr, cache_.kAsmDouble); 1332 RECURSE(IntersectResult(expr, cache_.kAsmDouble));
1330 return; 1333 return;
1331 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) { 1334 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) {
1332 if (left_intish != 0 || right_intish != 0) { 1335 if (left_intish != 0 || right_intish != 0) {
1333 FAIL(expr, "float operation before required fround"); 1336 FAIL(expr, "float operation before required fround");
1334 } 1337 }
1335 IntersectResult(expr, cache_.kAsmFloat); 1338 RECURSE(IntersectResult(expr, cache_.kAsmFloat));
1336 intish_ = 1; 1339 intish_ = 1;
1337 return; 1340 return;
1338 } else if (type->Is(cache_.kAsmDouble)) { 1341 } else if (type->Is(cache_.kAsmDouble)) {
1339 IntersectResult(expr, cache_.kAsmDouble); 1342 RECURSE(IntersectResult(expr, cache_.kAsmDouble));
1340 return; 1343 return;
1341 } else { 1344 } else {
1342 FAIL(expr, "ill-typed arithmetic operation"); 1345 FAIL(expr, "ill-typed arithmetic operation");
1343 } 1346 }
1344 } 1347 }
1345 default: 1348 default:
1346 UNREACHABLE(); 1349 UNREACHABLE();
1347 } 1350 }
1348 } 1351 }
1349 1352
(...skipping 21 matching lines...) Expand all
1371 "right comparison operand expected to be number")); 1374 "right comparison operand expected to be number"));
1372 Type* right_type = computed_type_; 1375 Type* right_type = computed_type_;
1373 if (!right_type->Is(cache_.kAsmComparable)) { 1376 if (!right_type->Is(cache_.kAsmComparable)) {
1374 FAIL(expr->right(), "bad type on right side of comparison"); 1377 FAIL(expr->right(), "bad type on right side of comparison");
1375 } 1378 }
1376 1379
1377 if (!left_type->Is(right_type) && !right_type->Is(left_type)) { 1380 if (!left_type->Is(right_type) && !right_type->Is(left_type)) {
1378 FAIL(expr, "left and right side of comparison must match"); 1381 FAIL(expr, "left and right side of comparison must match");
1379 } 1382 }
1380 1383
1381 IntersectResult(expr, cache_.kAsmSigned); 1384 RECURSE(IntersectResult(expr, cache_.kAsmSigned));
1382 } 1385 }
1383 1386
1384 1387
1385 void AsmTyper::VisitThisFunction(ThisFunction* expr) { 1388 void AsmTyper::VisitThisFunction(ThisFunction* expr) {
1386 FAIL(expr, "this function not allowed"); 1389 FAIL(expr, "this function not allowed");
1387 } 1390 }
1388 1391
1389 1392
1390 void AsmTyper::VisitDeclarations(ZoneList<Declaration*>* decls) { 1393 void AsmTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
1391 for (int i = 0; i < decls->length(); ++i) { 1394 for (int i = 0; i < decls->length(); ++i) {
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
1591 1594
1592 void AsmTyper::SetResult(Expression* expr, Type* type) { 1595 void AsmTyper::SetResult(Expression* expr, Type* type) {
1593 computed_type_ = type; 1596 computed_type_ = type;
1594 bounds_.set(expr, Bounds(computed_type_)); 1597 bounds_.set(expr, Bounds(computed_type_));
1595 } 1598 }
1596 1599
1597 1600
1598 void AsmTyper::IntersectResult(Expression* expr, Type* type) { 1601 void AsmTyper::IntersectResult(Expression* expr, Type* type) {
1599 computed_type_ = type; 1602 computed_type_ = type;
1600 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); 1603 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
1604 if (bounded_type->Is(Type::None())) {
1605 #ifdef DEBUG
1606 PrintF("Computed type: ");
1607 computed_type_->Print();
1608 PrintF("Expected type: ");
1609 expected_type_->Print();
1610 #endif
1611 FAIL(expr, "type mismatch");
1612 }
1601 bounds_.set(expr, Bounds(bounded_type)); 1613 bounds_.set(expr, Bounds(bounded_type));
1602 } 1614 }
1603 1615
1604 1616
1605 void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type, 1617 void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type,
1606 const char* msg) { 1618 const char* msg) {
1607 Type* save = expected_type_; 1619 Type* save = expected_type_;
1608 expected_type_ = expected_type; 1620 expected_type_ = expected_type;
1609 RECURSE(Visit(expr)); 1621 RECURSE(Visit(expr));
1610 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); 1622 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
(...skipping 10 matching lines...) Expand all
1621 } 1633 }
1622 1634
1623 1635
1624 void AsmTyper::VisitRewritableExpression(RewritableExpression* expr) { 1636 void AsmTyper::VisitRewritableExpression(RewritableExpression* expr) {
1625 RECURSE(Visit(expr->expression())); 1637 RECURSE(Visit(expr->expression()));
1626 } 1638 }
1627 1639
1628 1640
1629 } // namespace internal 1641 } // namespace internal
1630 } // namespace v8 1642 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/wasm/asm-wasm.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698