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

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: fix 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 } 720 }
721 721
722 722
723 void AsmTyper::VisitYield(Yield* expr) { 723 void AsmTyper::VisitYield(Yield* expr) {
724 FAIL(expr, "yield expression encountered"); 724 FAIL(expr, "yield expression encountered");
725 } 725 }
726 726
727 727
728 void AsmTyper::VisitThrow(Throw* expr) { 728 void AsmTyper::VisitThrow(Throw* expr) {
729 FAIL(expr, "throw statement encountered"); 729 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"); 769 // FAIL(right, "call mask must be integer");
770 // } 770 // }
771 // RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned, 771 // RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned,
772 // "call mask expected to be integer")); 772 // "call mask expected to be integer"));
773 // if (static_cast<size_t>(right->raw_value()->AsNumber()) != size - 1) { 773 // if (static_cast<size_t>(right->raw_value()->AsNumber()) != size - 1) {
774 // FAIL(right, "call mask must match function table"); 774 // FAIL(right, "call mask must match function table");
775 // } 775 // }
776 // bin->set_bounds(Bounds(cache_.kAsmSigned)); 776 // bin->set_bounds(Bounds(cache_.kAsmSigned));
777 RECURSE(VisitWithExpectation(expr->key(), cache_.kAsmSigned, 777 RECURSE(VisitWithExpectation(expr->key(), cache_.kAsmSigned,
778 "must be integer")); 778 "must be integer"));
779 IntersectResult(expr, type); 779 RECURSE(IntersectResult(expr, type));
780 } else { 780 } else {
781 Literal* literal = expr->key()->AsLiteral(); 781 Literal* literal = expr->key()->AsLiteral();
782 if (literal) { 782 if (literal) {
783 RECURSE(VisitWithExpectation(literal, cache_.kAsmSigned, 783 RECURSE(VisitWithExpectation(literal, cache_.kAsmSigned,
784 "array index expected to be integer")); 784 "array index expected to be integer"));
785 } else { 785 } else {
786 int expected_shift = ElementShiftSize(type); 786 int expected_shift = ElementShiftSize(type);
787 if (expected_shift == 0) { 787 if (expected_shift == 0) {
788 RECURSE(Visit(expr->key())); 788 RECURSE(Visit(expr->key()));
789 } else { 789 } else {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
828 } 828 }
829 intish_ = 0; 829 intish_ = 0;
830 } else { 830 } else {
831 UNREACHABLE(); 831 UNREACHABLE();
832 } 832 }
833 if (assigning) { 833 if (assigning) {
834 if (!assignment_type->Is(result_type)) { 834 if (!assignment_type->Is(result_type)) {
835 FAIL(expr, "illegal type in assignment"); 835 FAIL(expr, "illegal type in assignment");
836 } 836 }
837 } else { 837 } else {
838 IntersectResult(expr, expected_type_); 838 RECURSE(IntersectResult(expr, expected_type_));
839 IntersectResult(expr, result_type); 839 RECURSE(IntersectResult(expr, result_type));
840 } 840 }
841 } 841 }
842 } 842 }
843 843
844 844
845 bool AsmTyper::IsStdlibObject(Expression* expr) { 845 bool AsmTyper::IsStdlibObject(Expression* expr) {
846 VariableProxy* proxy = expr->AsVariableProxy(); 846 VariableProxy* proxy = expr->AsVariableProxy();
847 if (proxy == nullptr) { 847 if (proxy == nullptr) {
848 return false; 848 return false;
849 } 849 }
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
1027 if (!computed_type_->Is(cache_.kAsmSigned) && 1027 if (!computed_type_->Is(cache_.kAsmSigned) &&
1028 !computed_type_->Is(cache_.kAsmFixnum) && 1028 !computed_type_->Is(cache_.kAsmFixnum) &&
1029 !computed_type_->Is(cache_.kAsmDouble)) { 1029 !computed_type_->Is(cache_.kAsmDouble)) {
1030 FAIL(arg, 1030 FAIL(arg,
1031 "foreign call argument expected to be int, double, or fixnum"); 1031 "foreign call argument expected to be int, double, or fixnum");
1032 } 1032 }
1033 } 1033 }
1034 intish_ = 0; 1034 intish_ = 0;
1035 bounds_.set(expr->expression(), 1035 bounds_.set(expr->expression(),
1036 Bounds(Type::Function(Type::Any(), zone()))); 1036 Bounds(Type::Function(Type::Any(), zone())));
1037 IntersectResult(expr, expected_type); 1037 RECURSE(IntersectResult(expr, expected_type));
1038 } else { 1038 } else {
1039 if (fun_type->Arity() != args->length()) { 1039 if (fun_type->Arity() != args->length()) {
1040 FAIL(expr, "call with wrong arity"); 1040 FAIL(expr, "call with wrong arity");
1041 } 1041 }
1042 for (int i = 0; i < args->length(); ++i) { 1042 for (int i = 0; i < args->length(); ++i) {
1043 Expression* arg = args->at(i); 1043 Expression* arg = args->at(i);
1044 RECURSE(VisitWithExpectation( 1044 RECURSE(VisitWithExpectation(
1045 arg, fun_type->Parameter(i), 1045 arg, fun_type->Parameter(i),
1046 "call argument expected to match callee parameter")); 1046 "call argument expected to match callee parameter"));
1047 if (standard_member != kNone && standard_member != kMathFround && 1047 if (standard_member != kNone && standard_member != kMathFround &&
1048 i == 0) { 1048 i == 0) {
1049 result_type = computed_type_; 1049 result_type = computed_type_;
1050 } 1050 }
1051 } 1051 }
1052 RECURSE(CheckPolymorphicStdlibArguments(standard_member, args)); 1052 RECURSE(CheckPolymorphicStdlibArguments(standard_member, args));
1053 intish_ = 0; 1053 intish_ = 0;
1054 IntersectResult(expr, result_type); 1054 RECURSE(IntersectResult(expr, result_type));
1055 } 1055 }
1056 } else { 1056 } else {
1057 FAIL(expr, "invalid callee"); 1057 FAIL(expr, "invalid callee");
1058 } 1058 }
1059 } 1059 }
1060 1060
1061 1061
1062 void AsmTyper::VisitCallNew(CallNew* expr) { 1062 void AsmTyper::VisitCallNew(CallNew* expr) {
1063 if (in_function_) { 1063 if (in_function_) {
1064 FAIL(expr, "new not allowed in module function"); 1064 FAIL(expr, "new not allowed in module function");
1065 } 1065 }
1066 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), 1066 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(),
1067 "expected stdlib function")); 1067 "expected stdlib function"));
1068 if (computed_type_->IsFunction()) { 1068 if (computed_type_->IsFunction()) {
1069 FunctionType* fun_type = computed_type_->AsFunction(); 1069 FunctionType* fun_type = computed_type_->AsFunction();
1070 ZoneList<Expression*>* args = expr->arguments(); 1070 ZoneList<Expression*>* args = expr->arguments();
1071 if (fun_type->Arity() != args->length()) 1071 if (fun_type->Arity() != args->length())
1072 FAIL(expr, "call with wrong arity"); 1072 FAIL(expr, "call with wrong arity");
1073 for (int i = 0; i < args->length(); ++i) { 1073 for (int i = 0; i < args->length(); ++i) {
1074 Expression* arg = args->at(i); 1074 Expression* arg = args->at(i);
1075 RECURSE(VisitWithExpectation( 1075 RECURSE(VisitWithExpectation(
1076 arg, fun_type->Parameter(i), 1076 arg, fun_type->Parameter(i),
1077 "constructor argument expected to match callee parameter")); 1077 "constructor argument expected to match callee parameter"));
1078 } 1078 }
1079 IntersectResult(expr, fun_type->Result()); 1079 RECURSE(IntersectResult(expr, fun_type->Result()));
1080 return; 1080 return;
1081 } 1081 }
1082 1082
1083 FAIL(expr, "ill-typed new operator"); 1083 FAIL(expr, "ill-typed new operator");
1084 } 1084 }
1085 1085
1086 1086
1087 void AsmTyper::VisitCallRuntime(CallRuntime* expr) { 1087 void AsmTyper::VisitCallRuntime(CallRuntime* expr) {
1088 FAIL(expr, "runtime call not allowed"); 1088 FAIL(expr, "runtime call not allowed");
1089 } 1089 }
1090 1090
1091 1091
1092 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) { 1092 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) {
1093 if (!in_function_) { 1093 if (!in_function_) {
1094 FAIL(expr, "unary operator inside module body"); 1094 FAIL(expr, "unary operator inside module body");
1095 } 1095 }
1096 switch (expr->op()) { 1096 switch (expr->op()) {
1097 case Token::NOT: // Used to encode != and !== 1097 case Token::NOT: // Used to encode != and !==
1098 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt, 1098 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt,
1099 "operand expected to be integer")); 1099 "operand expected to be integer"));
1100 IntersectResult(expr, cache_.kAsmSigned); 1100 RECURSE(IntersectResult(expr, cache_.kAsmSigned));
1101 return; 1101 return;
1102 case Token::DELETE: 1102 case Token::DELETE:
1103 FAIL(expr, "delete operator encountered"); 1103 FAIL(expr, "delete operator encountered");
1104 case Token::VOID: 1104 case Token::VOID:
1105 FAIL(expr, "void operator encountered"); 1105 FAIL(expr, "void operator encountered");
1106 case Token::TYPEOF: 1106 case Token::TYPEOF:
1107 FAIL(expr, "typeof operator encountered"); 1107 FAIL(expr, "typeof operator encountered");
1108 default: 1108 default:
1109 UNREACHABLE(); 1109 UNREACHABLE();
1110 } 1110 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 left_type = right_type; 1149 left_type = right_type;
1150 } 1150 }
1151 if (right_type->Is(cache_.kAsmFixnum) && left_type->Is(cache_.kAsmInt)) { 1151 if (right_type->Is(cache_.kAsmFixnum) && left_type->Is(cache_.kAsmInt)) {
1152 right_type = left_type; 1152 right_type = left_type;
1153 } 1153 }
1154 if (!conversion) { 1154 if (!conversion) {
1155 if (!left_type->Is(cache_.kAsmIntQ) || !right_type->Is(cache_.kAsmIntQ)) { 1155 if (!left_type->Is(cache_.kAsmIntQ) || !right_type->Is(cache_.kAsmIntQ)) {
1156 FAIL(expr, "ill-typed bitwise operation"); 1156 FAIL(expr, "ill-typed bitwise operation");
1157 } 1157 }
1158 } 1158 }
1159 IntersectResult(expr, result_type); 1159 RECURSE(IntersectResult(expr, result_type));
1160 } 1160 }
1161 1161
1162 1162
1163 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { 1163 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
1164 if (!in_function_) { 1164 if (!in_function_) {
1165 if (expr->op() != Token::BIT_OR && expr->op() != Token::MUL) { 1165 if (expr->op() != Token::BIT_OR && expr->op() != Token::MUL) {
1166 FAIL(expr, "illegal binary operator inside module body"); 1166 FAIL(expr, "illegal binary operator inside module body");
1167 } 1167 }
1168 if (!(expr->left()->IsProperty() || expr->left()->IsVariableProxy()) || 1168 if (!(expr->left()->IsProperty() || expr->left()->IsVariableProxy()) ||
1169 !expr->right()->IsLiteral()) { 1169 !expr->right()->IsLiteral()) {
(...skipping 11 matching lines...) Expand all
1181 FAIL(expr, "illegal double annotation value"); 1181 FAIL(expr, "illegal double annotation value");
1182 } 1182 }
1183 } 1183 }
1184 } 1184 }
1185 switch (expr->op()) { 1185 switch (expr->op()) {
1186 case Token::COMMA: { 1186 case Token::COMMA: {
1187 RECURSE(VisitWithExpectation(expr->left(), Type::Any(), 1187 RECURSE(VisitWithExpectation(expr->left(), Type::Any(),
1188 "left comma operand expected to be any")); 1188 "left comma operand expected to be any"));
1189 RECURSE(VisitWithExpectation(expr->right(), Type::Any(), 1189 RECURSE(VisitWithExpectation(expr->right(), Type::Any(),
1190 "right comma operand expected to be any")); 1190 "right comma operand expected to be any"));
1191 IntersectResult(expr, computed_type_); 1191 RECURSE(IntersectResult(expr, computed_type_));
1192 return; 1192 return;
1193 } 1193 }
1194 case Token::OR: 1194 case Token::OR:
1195 case Token::AND: 1195 case Token::AND:
1196 FAIL(expr, "illegal logical operator"); 1196 FAIL(expr, "illegal logical operator");
1197 case Token::BIT_OR: { 1197 case Token::BIT_OR: {
1198 // BIT_OR allows Any since it is used as a type coercion. 1198 // BIT_OR allows Any since it is used as a type coercion.
1199 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ, 1199 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ,
1200 cache_.kAsmSigned, true)); 1200 cache_.kAsmSigned, true));
1201 if (expr->left()->IsCall() && expr->op() == Token::BIT_OR && 1201 if (expr->left()->IsCall() && expr->op() == Token::BIT_OR &&
1202 Type::Number()->Is(bounds_.get(expr->left()).upper)) { 1202 Type::Number()->Is(bounds_.get(expr->left()).upper)) {
1203 // Force the return types of foreign functions. 1203 // Force the return types of foreign functions.
1204 bounds_.set(expr->left(), Bounds(cache_.kAsmSigned)); 1204 bounds_.set(expr->left(), Bounds(cache_.kAsmSigned));
1205 } 1205 }
1206 if (in_function_ && 1206 if (in_function_ &&
1207 !bounds_.get(expr->left()).upper->Is(cache_.kAsmIntQ)) { 1207 !bounds_.get(expr->left()).upper->Is(cache_.kAsmIntQ)) {
1208 FAIL(expr->left(), "intish required"); 1208 FAIL(expr->left(), "intish required");
1209 } 1209 }
1210 return; 1210 return;
1211 } 1211 }
1212 case Token::BIT_XOR: { 1212 case Token::BIT_XOR: {
1213 // Handle booleans specially to handle de-sugared ! 1213 // Handle booleans specially to handle de-sugared !
1214 Literal* left = expr->left()->AsLiteral(); 1214 Literal* left = expr->left()->AsLiteral();
1215 if (left && left->value()->IsBoolean()) { 1215 if (left && left->value()->IsBoolean()) {
1216 if (left->ToBooleanIsTrue()) { 1216 if (left->ToBooleanIsTrue()) {
1217 bounds_.set(left, Bounds(cache_.kSingletonOne)); 1217 bounds_.set(left, Bounds(cache_.kSingletonOne));
1218 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmIntQ, 1218 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmIntQ,
1219 "not operator expects an integer")); 1219 "not operator expects an integer"));
1220 IntersectResult(expr, cache_.kAsmSigned); 1220 RECURSE(IntersectResult(expr, cache_.kAsmSigned));
1221 return; 1221 return;
1222 } else { 1222 } else {
1223 FAIL(left, "unexpected false"); 1223 FAIL(left, "unexpected false");
1224 } 1224 }
1225 } 1225 }
1226 // BIT_XOR allows Any since it is used as a type coercion (via ~~). 1226 // BIT_XOR allows Any since it is used as a type coercion (via ~~).
1227 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ, 1227 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ,
1228 cache_.kAsmSigned, true)); 1228 cache_.kAsmSigned, true));
1229 return; 1229 return;
1230 } 1230 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1272 FAIL(expr, "intish not allowed in multiply"); 1272 FAIL(expr, "intish not allowed in multiply");
1273 } 1273 }
1274 } else { 1274 } else {
1275 FAIL(expr, "multiply must be by an integer literal"); 1275 FAIL(expr, "multiply must be by an integer literal");
1276 } 1276 }
1277 i = abs(i); 1277 i = abs(i);
1278 if (i >= (1 << 20)) { 1278 if (i >= (1 << 20)) {
1279 FAIL(expr, "multiply must be by value in -2^20 < n < 2^20"); 1279 FAIL(expr, "multiply must be by value in -2^20 < n < 2^20");
1280 } 1280 }
1281 intish_ = i; 1281 intish_ = i;
1282 IntersectResult(expr, cache_.kAsmInt); 1282 RECURSE(IntersectResult(expr, cache_.kAsmInt));
1283 return; 1283 return;
1284 } else { 1284 } else {
1285 intish_ = left_intish + right_intish + 1; 1285 intish_ = left_intish + right_intish + 1;
1286 if (expr->op() == Token::ADD || expr->op() == Token::SUB) { 1286 if (expr->op() == Token::ADD || expr->op() == Token::SUB) {
1287 if (intish_ > kMaxUncombinedAdditiveSteps) { 1287 if (intish_ > kMaxUncombinedAdditiveSteps) {
1288 FAIL(expr, "too many consecutive additive ops"); 1288 FAIL(expr, "too many consecutive additive ops");
1289 } 1289 }
1290 } else { 1290 } else {
1291 if (intish_ > kMaxUncombinedMultiplicativeSteps) { 1291 if (intish_ > kMaxUncombinedMultiplicativeSteps) {
1292 FAIL(expr, "too many consecutive multiplicative ops"); 1292 FAIL(expr, "too many consecutive multiplicative ops");
1293 } 1293 }
1294 } 1294 }
1295 IntersectResult(expr, cache_.kAsmInt); 1295 RECURSE(IntersectResult(expr, cache_.kAsmInt));
1296 return; 1296 return;
1297 } 1297 }
1298 } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() && 1298 } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() &&
1299 right_type->Is(cache_.kAsmDouble) && 1299 right_type->Is(cache_.kAsmDouble) &&
1300 expr->right()->AsLiteral()->raw_value()->ContainsDot() && 1300 expr->right()->AsLiteral()->raw_value()->ContainsDot() &&
1301 expr->right()->AsLiteral()->raw_value()->AsNumber() == 1.0) { 1301 expr->right()->AsLiteral()->raw_value()->AsNumber() == 1.0) {
1302 // For unary +, expressed as x * 1.0 1302 // For unary +, expressed as x * 1.0
1303 if (expr->left()->IsCall() && 1303 if (expr->left()->IsCall() &&
1304 Type::Number()->Is(bounds_.get(expr->left()).upper)) { 1304 Type::Number()->Is(bounds_.get(expr->left()).upper)) {
1305 // Force the return types of foreign functions. 1305 // Force the return types of foreign functions.
1306 bounds_.set(expr->left(), Bounds(cache_.kAsmDouble)); 1306 bounds_.set(expr->left(), Bounds(cache_.kAsmDouble));
1307 left_type = bounds_.get(expr->left()).upper; 1307 left_type = bounds_.get(expr->left()).upper;
1308 } 1308 }
1309 if (!(expr->left()->IsProperty() && 1309 if (!(expr->left()->IsProperty() &&
1310 Type::Number()->Is(bounds_.get(expr->left()).upper))) { 1310 Type::Number()->Is(bounds_.get(expr->left()).upper))) {
1311 if (!left_type->Is(cache_.kAsmSigned) && 1311 if (!left_type->Is(cache_.kAsmSigned) &&
1312 !left_type->Is(cache_.kAsmUnsigned) && 1312 !left_type->Is(cache_.kAsmUnsigned) &&
1313 !left_type->Is(cache_.kAsmFixnum) && 1313 !left_type->Is(cache_.kAsmFixnum) &&
1314 !left_type->Is(cache_.kAsmFloatQ) && 1314 !left_type->Is(cache_.kAsmFloatQ) &&
1315 !left_type->Is(cache_.kAsmDoubleQ)) { 1315 !left_type->Is(cache_.kAsmDoubleQ)) {
1316 FAIL( 1316 FAIL(
1317 expr->left(), 1317 expr->left(),
1318 "unary + only allowed on signed, unsigned, float?, or double?"); 1318 "unary + only allowed on signed, unsigned, float?, or double?");
1319 } 1319 }
1320 } 1320 }
1321 IntersectResult(expr, cache_.kAsmDouble); 1321 RECURSE(IntersectResult(expr, cache_.kAsmDouble));
1322 return; 1322 return;
1323 } else if (expr->op() == Token::MUL && left_type->Is(cache_.kAsmDouble) && 1323 } else if (expr->op() == Token::MUL && left_type->Is(cache_.kAsmDouble) &&
1324 expr->right()->IsLiteral() && 1324 expr->right()->IsLiteral() &&
1325 !expr->right()->AsLiteral()->raw_value()->ContainsDot() && 1325 !expr->right()->AsLiteral()->raw_value()->ContainsDot() &&
1326 expr->right()->AsLiteral()->raw_value()->AsNumber() == -1.0) { 1326 expr->right()->AsLiteral()->raw_value()->AsNumber() == -1.0) {
1327 // For unary -, expressed as x * -1 1327 // For unary -, expressed as x * -1
1328 bounds_.set(expr->right(), Bounds(cache_.kAsmDouble)); 1328 bounds_.set(expr->right(), Bounds(cache_.kAsmDouble));
1329 IntersectResult(expr, cache_.kAsmDouble); 1329 RECURSE(IntersectResult(expr, cache_.kAsmDouble));
1330 return; 1330 return;
1331 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) { 1331 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) {
1332 if (left_intish != 0 || right_intish != 0) { 1332 if (left_intish != 0 || right_intish != 0) {
1333 FAIL(expr, "float operation before required fround"); 1333 FAIL(expr, "float operation before required fround");
1334 } 1334 }
1335 IntersectResult(expr, cache_.kAsmFloat); 1335 RECURSE(IntersectResult(expr, cache_.kAsmFloat));
1336 intish_ = 1; 1336 intish_ = 1;
1337 return; 1337 return;
1338 } else if (type->Is(cache_.kAsmDouble)) { 1338 } else if (type->Is(cache_.kAsmDouble)) {
1339 IntersectResult(expr, cache_.kAsmDouble); 1339 RECURSE(IntersectResult(expr, cache_.kAsmDouble));
1340 return; 1340 return;
1341 } else { 1341 } else {
1342 FAIL(expr, "ill-typed arithmetic operation"); 1342 FAIL(expr, "ill-typed arithmetic operation");
1343 } 1343 }
1344 } 1344 }
1345 default: 1345 default:
1346 UNREACHABLE(); 1346 UNREACHABLE();
1347 } 1347 }
1348 } 1348 }
1349 1349
(...skipping 21 matching lines...) Expand all
1371 "right comparison operand expected to be number")); 1371 "right comparison operand expected to be number"));
1372 Type* right_type = computed_type_; 1372 Type* right_type = computed_type_;
1373 if (!right_type->Is(cache_.kAsmComparable)) { 1373 if (!right_type->Is(cache_.kAsmComparable)) {
1374 FAIL(expr->right(), "bad type on right side of comparison"); 1374 FAIL(expr->right(), "bad type on right side of comparison");
1375 } 1375 }
1376 1376
1377 if (!left_type->Is(right_type) && !right_type->Is(left_type)) { 1377 if (!left_type->Is(right_type) && !right_type->Is(left_type)) {
1378 FAIL(expr, "left and right side of comparison must match"); 1378 FAIL(expr, "left and right side of comparison must match");
1379 } 1379 }
1380 1380
1381 IntersectResult(expr, cache_.kAsmSigned); 1381 RECURSE(IntersectResult(expr, cache_.kAsmSigned));
1382 } 1382 }
1383 1383
1384 1384
1385 void AsmTyper::VisitThisFunction(ThisFunction* expr) { 1385 void AsmTyper::VisitThisFunction(ThisFunction* expr) {
1386 FAIL(expr, "this function not allowed"); 1386 FAIL(expr, "this function not allowed");
1387 } 1387 }
1388 1388
1389 1389
1390 void AsmTyper::VisitDeclarations(ZoneList<Declaration*>* decls) { 1390 void AsmTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
1391 for (int i = 0; i < decls->length(); ++i) { 1391 for (int i = 0; i < decls->length(); ++i) {
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
1591 1591
1592 void AsmTyper::SetResult(Expression* expr, Type* type) { 1592 void AsmTyper::SetResult(Expression* expr, Type* type) {
1593 computed_type_ = type; 1593 computed_type_ = type;
1594 bounds_.set(expr, Bounds(computed_type_)); 1594 bounds_.set(expr, Bounds(computed_type_));
1595 } 1595 }
1596 1596
1597 1597
1598 void AsmTyper::IntersectResult(Expression* expr, Type* type) { 1598 void AsmTyper::IntersectResult(Expression* expr, Type* type) {
1599 computed_type_ = type; 1599 computed_type_ = type;
1600 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); 1600 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
1601 if (Type::Representation(bounded_type, zone())->Is(Type::None())) {
1602 #ifdef DEBUG
1603 PrintF("Computed type: ");
1604 computed_type_->Print();
1605 PrintF("Expected type: ");
1606 expected_type_->Print();
1607 #endif
1608 FAIL(expr, "type mismatch");
1609 }
1601 bounds_.set(expr, Bounds(bounded_type)); 1610 bounds_.set(expr, Bounds(bounded_type));
1602 } 1611 }
1603 1612
1604 1613
1605 void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type, 1614 void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type,
1606 const char* msg) { 1615 const char* msg) {
1607 Type* save = expected_type_; 1616 Type* save = expected_type_;
1608 expected_type_ = expected_type; 1617 expected_type_ = expected_type;
1609 RECURSE(Visit(expr)); 1618 RECURSE(Visit(expr));
1610 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); 1619 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
1611 if (bounded_type->Is(Type::None())) { 1620 if (Type::Representation(bounded_type, zone())->Is(Type::None())) {
1612 #ifdef DEBUG 1621 #ifdef DEBUG
1613 PrintF("Computed type: "); 1622 PrintF("Computed type: ");
1614 computed_type_->Print(); 1623 computed_type_->Print();
1615 PrintF("Expected type: "); 1624 PrintF("Expected type: ");
1616 expected_type_->Print(); 1625 expected_type_->Print();
1617 #endif 1626 #endif
1618 FAIL(expr, msg); 1627 FAIL(expr, msg);
1619 } 1628 }
1620 expected_type_ = save; 1629 expected_type_ = save;
1621 } 1630 }
1622 1631
1623 1632
1624 void AsmTyper::VisitRewritableExpression(RewritableExpression* expr) { 1633 void AsmTyper::VisitRewritableExpression(RewritableExpression* expr) {
1625 RECURSE(Visit(expr->expression())); 1634 RECURSE(Visit(expr->expression()));
1626 } 1635 }
1627 1636
1628 1637
1629 } // namespace internal 1638 } // namespace internal
1630 } // namespace v8 1639 } // 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