OLD | NEW |
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 18 matching lines...) Expand all Loading... |
29 | 29 |
30 | 30 |
31 #define RECURSE(call) \ | 31 #define RECURSE(call) \ |
32 do { \ | 32 do { \ |
33 DCHECK(!HasStackOverflow()); \ | 33 DCHECK(!HasStackOverflow()); \ |
34 call; \ | 34 call; \ |
35 if (HasStackOverflow()) return; \ | 35 if (HasStackOverflow()) return; \ |
36 if (!valid_) return; \ | 36 if (!valid_) return; \ |
37 } while (false) | 37 } while (false) |
38 | 38 |
| 39 |
39 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, | 40 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, |
40 FunctionLiteral* root) | 41 FunctionLiteral* root) |
41 : zone_(zone), | 42 : zone_(zone), |
42 isolate_(isolate), | 43 isolate_(isolate), |
43 script_(script), | 44 script_(script), |
44 root_(root), | 45 root_(root), |
45 valid_(true), | 46 valid_(true), |
46 allow_simd_(false), | 47 allow_simd_(false), |
47 property_info_(NULL), | 48 property_info_(NULL), |
48 intish_(0), | 49 intish_(0), |
49 stdlib_types_(zone), | 50 stdlib_types_(zone), |
50 stdlib_heap_types_(zone), | 51 stdlib_heap_types_(zone), |
51 stdlib_math_types_(zone), | 52 stdlib_math_types_(zone), |
52 #define V(NAME, Name, name, lane_count, lane_type) \ | 53 #define V(NAME, Name, name, lane_count, lane_type) \ |
53 stdlib_simd_##name##_types_(zone), | 54 stdlib_simd_##name##_types_(zone), |
54 SIMD128_TYPES(V) | 55 SIMD128_TYPES(V) |
55 #undef V | 56 #undef V |
56 global_variable_type_(HashMap::PointersMatch, | 57 global_variable_type_(HashMap::PointersMatch, |
57 ZoneHashMap::kDefaultHashMapCapacity, | 58 ZoneHashMap::kDefaultHashMapCapacity, |
58 ZoneAllocationPolicy(zone)), | 59 ZoneAllocationPolicy(zone)), |
59 local_variable_type_(HashMap::PointersMatch, | 60 local_variable_type_(HashMap::PointersMatch, |
60 ZoneHashMap::kDefaultHashMapCapacity, | 61 ZoneHashMap::kDefaultHashMapCapacity, |
61 ZoneAllocationPolicy(zone)), | 62 ZoneAllocationPolicy(zone)), |
62 in_function_(false), | 63 in_function_(false), |
63 building_function_tables_(false), | 64 building_function_tables_(false), |
64 visiting_exports_(false), | |
65 cache_(TypeCache::Get()) { | 65 cache_(TypeCache::Get()) { |
66 InitializeAstVisitor(isolate); | 66 InitializeAstVisitor(isolate); |
67 InitializeStdlib(); | 67 InitializeStdlib(); |
68 } | 68 } |
69 | 69 |
70 | 70 |
71 bool AsmTyper::Validate() { | 71 bool AsmTyper::Validate() { |
72 VisitAsmModule(root_); | 72 VisitAsmModule(root_); |
73 return valid_ && !HasStackOverflow(); | 73 return valid_ && !HasStackOverflow(); |
74 } | 74 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 if (decl != NULL) { | 128 if (decl != NULL) { |
129 RECURSE( | 129 RECURSE( |
130 VisitWithExpectation(decl->fun(), Type::Any(zone()), "UNREACHABLE")); | 130 VisitWithExpectation(decl->fun(), Type::Any(zone()), "UNREACHABLE")); |
131 if (!computed_type_->IsFunction()) { | 131 if (!computed_type_->IsFunction()) { |
132 FAIL(decl->fun(), "function literal expected to be a function"); | 132 FAIL(decl->fun(), "function literal expected to be a function"); |
133 } | 133 } |
134 } | 134 } |
135 } | 135 } |
136 | 136 |
137 // Validate exports. | 137 // Validate exports. |
138 visiting_exports_ = true; | |
139 ReturnStatement* stmt = fun->body()->last()->AsReturnStatement(); | 138 ReturnStatement* stmt = fun->body()->last()->AsReturnStatement(); |
140 if (stmt == nullptr) { | 139 if (stmt == nullptr) { |
141 FAIL(fun->body()->last(), "last statement in module is not a return"); | 140 FAIL(fun->body()->last(), "last statement in module is not a return"); |
142 } | 141 } |
143 RECURSE(VisitWithExpectation(stmt->expression(), Type::Object(), | 142 RECURSE(VisitWithExpectation(stmt->expression(), Type::Object(), |
144 "expected object export")); | 143 "expected object export")); |
145 } | 144 } |
146 | 145 |
147 | 146 |
148 void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) { | 147 void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) { |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 FAIL(stmt, "try statement encountered"); | 482 FAIL(stmt, "try statement encountered"); |
484 } | 483 } |
485 | 484 |
486 | 485 |
487 void AsmTyper::VisitDebuggerStatement(DebuggerStatement* stmt) { | 486 void AsmTyper::VisitDebuggerStatement(DebuggerStatement* stmt) { |
488 FAIL(stmt, "debugger statement encountered"); | 487 FAIL(stmt, "debugger statement encountered"); |
489 } | 488 } |
490 | 489 |
491 | 490 |
492 void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) { | 491 void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 492 Scope* scope = expr->scope(); |
| 493 DCHECK(scope->is_function_scope()); |
493 if (in_function_) { | 494 if (in_function_) { |
494 FAIL(expr, "invalid nested function"); | 495 FAIL(expr, "invalid nested function"); |
495 } | 496 } |
496 Scope* scope = expr->scope(); | |
497 DCHECK(scope->is_function_scope()); | |
498 | 497 |
499 if (!expr->bounds().upper->IsFunction()) { | 498 if (!expr->bounds().upper->IsFunction()) { |
500 FAIL(expr, "invalid function literal"); | 499 FAIL(expr, "invalid function literal"); |
501 } | 500 } |
502 | 501 |
503 Type::FunctionType* type = expr->bounds().upper->AsFunction(); | 502 Type::FunctionType* type = expr->bounds().upper->AsFunction(); |
504 Type* save_return_type = return_type_; | 503 Type* save_return_type = return_type_; |
505 return_type_ = type->Result(); | 504 return_type_ = type->Result(); |
506 in_function_ = true; | 505 in_function_ = true; |
507 local_variable_type_.Clear(); | 506 local_variable_type_.Clear(); |
508 RECURSE(VisitDeclarations(scope->declarations())); | 507 RECURSE(VisitDeclarations(scope->declarations())); |
509 RECURSE(VisitStatements(expr->body())); | 508 RECURSE(VisitStatements(expr->body())); |
510 in_function_ = false; | 509 in_function_ = false; |
511 return_type_ = save_return_type; | 510 return_type_ = save_return_type; |
512 IntersectResult(expr, type); | 511 IntersectResult(expr, type); |
513 } | 512 } |
514 | 513 |
515 | 514 |
516 void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 515 void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
517 FAIL(expr, "function info literal encountered"); | 516 FAIL(expr, "function info literal encountered"); |
518 } | 517 } |
519 | 518 |
520 | 519 |
521 void AsmTyper::VisitDoExpression(DoExpression* expr) { | 520 void AsmTyper::VisitDoExpression(DoExpression* expr) { |
522 FAIL(expr, "do-expression encountered"); | 521 FAIL(expr, "do-expression encountered"); |
523 } | 522 } |
524 | 523 |
525 | 524 |
526 void AsmTyper::VisitConditional(Conditional* expr) { | 525 void AsmTyper::VisitConditional(Conditional* expr) { |
527 if (!in_function_) { | |
528 FAIL(expr, "ternary operator inside module body"); | |
529 } | |
530 RECURSE(VisitWithExpectation(expr->condition(), Type::Number(), | 526 RECURSE(VisitWithExpectation(expr->condition(), Type::Number(), |
531 "condition expected to be integer")); | 527 "condition expected to be integer")); |
532 if (!computed_type_->Is(cache_.kAsmInt)) { | 528 if (!computed_type_->Is(cache_.kAsmInt)) { |
533 FAIL(expr->condition(), "condition must be of type int"); | 529 FAIL(expr->condition(), "condition must be of type int"); |
534 } | 530 } |
535 | 531 |
536 RECURSE(VisitWithExpectation( | 532 RECURSE(VisitWithExpectation( |
537 expr->then_expression(), expected_type_, | 533 expr->then_expression(), expected_type_, |
538 "conditional then branch type mismatch with enclosing expression")); | 534 "conditional then branch type mismatch with enclosing expression")); |
539 Type* then_type = StorageType(computed_type_); | 535 Type* then_type = StorageType(computed_type_); |
(...skipping 11 matching lines...) Expand all Loading... |
551 | 547 |
552 if (!then_type->Is(else_type) || !else_type->Is(then_type)) { | 548 if (!then_type->Is(else_type) || !else_type->Is(then_type)) { |
553 FAIL(expr, "then and else expressions in ? must have the same type"); | 549 FAIL(expr, "then and else expressions in ? must have the same type"); |
554 } | 550 } |
555 | 551 |
556 IntersectResult(expr, then_type); | 552 IntersectResult(expr, then_type); |
557 } | 553 } |
558 | 554 |
559 | 555 |
560 void AsmTyper::VisitVariableProxy(VariableProxy* expr) { | 556 void AsmTyper::VisitVariableProxy(VariableProxy* expr) { |
561 VisitVariableProxy(expr, false); | |
562 } | |
563 | |
564 void AsmTyper::VisitVariableProxy(VariableProxy* expr, bool assignment) { | |
565 Variable* var = expr->var(); | 557 Variable* var = expr->var(); |
566 VariableInfo* info = GetVariableInfo(var, false); | 558 VariableInfo* info = GetVariableInfo(var, false); |
567 if (!assignment && !in_function_ && !building_function_tables_ && | |
568 !visiting_exports_) { | |
569 if (var->location() != VariableLocation::PARAMETER || var->index() >= 3) { | |
570 FAIL(expr, "illegal variable reference in module body"); | |
571 } | |
572 } | |
573 if (info == NULL || info->type == NULL) { | 559 if (info == NULL || info->type == NULL) { |
574 if (var->mode() == TEMPORARY) { | 560 if (var->mode() == TEMPORARY) { |
575 SetType(var, Type::Any(zone())); | 561 SetType(var, Type::Any(zone())); |
576 info = GetVariableInfo(var, false); | 562 info = GetVariableInfo(var, false); |
577 } else { | 563 } else { |
578 FAIL(expr, "unbound variable"); | 564 FAIL(expr, "unbound variable"); |
579 } | 565 } |
580 } | 566 } |
581 if (property_info_ != NULL) { | 567 if (property_info_ != NULL) { |
582 SetVariableInfo(var, property_info_); | 568 SetVariableInfo(var, property_info_); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
682 } | 668 } |
683 if (expr->is_compound()) FAIL(expr, "compound assignment encountered"); | 669 if (expr->is_compound()) FAIL(expr, "compound assignment encountered"); |
684 Type* type = expected_type_; | 670 Type* type = expected_type_; |
685 RECURSE(VisitWithExpectation( | 671 RECURSE(VisitWithExpectation( |
686 expr->value(), type, "assignment value expected to match surrounding")); | 672 expr->value(), type, "assignment value expected to match surrounding")); |
687 Type* target_type = StorageType(computed_type_); | 673 Type* target_type = StorageType(computed_type_); |
688 if (intish_ != 0) { | 674 if (intish_ != 0) { |
689 FAIL(expr, "intish or floatish assignment"); | 675 FAIL(expr, "intish or floatish assignment"); |
690 } | 676 } |
691 if (expr->target()->IsVariableProxy()) { | 677 if (expr->target()->IsVariableProxy()) { |
692 expected_type_ = target_type; | 678 RECURSE(VisitWithExpectation(expr->target(), target_type, |
693 VisitVariableProxy(expr->target()->AsVariableProxy(), true); | 679 "assignment target expected to match value")); |
694 } else if (expr->target()->IsProperty()) { | 680 } else if (expr->target()->IsProperty()) { |
695 Property* property = expr->target()->AsProperty(); | 681 Property* property = expr->target()->AsProperty(); |
696 RECURSE(VisitWithExpectation(property->obj(), Type::Any(), | 682 RECURSE(VisitWithExpectation(property->obj(), Type::Any(), |
697 "bad propety object")); | 683 "bad propety object")); |
698 if (!computed_type_->IsArray()) { | 684 if (!computed_type_->IsArray()) { |
699 FAIL(property->obj(), "array expected"); | 685 FAIL(property->obj(), "array expected"); |
700 } | 686 } |
701 VisitHeapAccess(property, true, target_type); | 687 VisitHeapAccess(property, true, target_type); |
702 } | 688 } |
703 IntersectResult(expr, target_type); | 689 IntersectResult(expr, target_type); |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
919 SetResult(expr, expected_type_); | 905 SetResult(expr, expected_type_); |
920 return; | 906 return; |
921 } | 907 } |
922 } | 908 } |
923 | 909 |
924 FAIL(expr, "invalid property access"); | 910 FAIL(expr, "invalid property access"); |
925 } | 911 } |
926 | 912 |
927 | 913 |
928 void AsmTyper::VisitCall(Call* expr) { | 914 void AsmTyper::VisitCall(Call* expr) { |
929 Type* expected_type = expected_type_; | |
930 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), | 915 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), |
931 "callee expected to be any")); | 916 "callee expected to be any")); |
932 StandardMember standard_member = kNone; | 917 StandardMember standard_member = kNone; |
933 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 918 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
934 if (proxy) { | 919 if (proxy) { |
935 standard_member = VariableAsStandardMember(proxy->var()); | 920 standard_member = VariableAsStandardMember(proxy->var()); |
936 } | 921 } |
937 if (!in_function_ && (proxy == NULL || standard_member != kMathFround)) { | 922 if (!in_function_ && (proxy == NULL || standard_member != kMathFround)) { |
938 FAIL(expr, "calls forbidden outside function bodies"); | 923 FAIL(expr, "calls forbidden outside function bodies"); |
939 } | 924 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
982 } | 967 } |
983 intish_ = 0; | 968 intish_ = 0; |
984 IntersectResult(expr, result_type); | 969 IntersectResult(expr, result_type); |
985 } else if (computed_type_->Is(Type::Any())) { | 970 } else if (computed_type_->Is(Type::Any())) { |
986 // For foreign calls. | 971 // For foreign calls. |
987 ZoneList<Expression*>* args = expr->arguments(); | 972 ZoneList<Expression*>* args = expr->arguments(); |
988 for (int i = 0; i < args->length(); ++i) { | 973 for (int i = 0; i < args->length(); ++i) { |
989 Expression* arg = args->at(i); | 974 Expression* arg = args->at(i); |
990 RECURSE(VisitWithExpectation(arg, Type::Any(), | 975 RECURSE(VisitWithExpectation(arg, Type::Any(), |
991 "foreign call argument expected to be any")); | 976 "foreign call argument expected to be any")); |
992 // Checking for asm extern types explicitly, as the type system | |
993 // doesn't correctly check their inheritance relationship. | |
994 if (!computed_type_->Is(cache_.kAsmSigned) && | |
995 !computed_type_->Is(cache_.kAsmFixnum) && | |
996 !computed_type_->Is(cache_.kAsmDouble)) { | |
997 FAIL(arg, | |
998 "foreign call argument expected to be int, double, or fixnum"); | |
999 } | |
1000 } | 977 } |
1001 intish_ = kMaxUncombinedAdditiveSteps; | 978 intish_ = kMaxUncombinedAdditiveSteps; |
1002 IntersectResult(expr, expected_type); | 979 IntersectResult(expr, Type::Number()); |
1003 } else { | 980 } else { |
1004 FAIL(expr, "invalid callee"); | 981 FAIL(expr, "invalid callee"); |
1005 } | 982 } |
1006 } | 983 } |
1007 | 984 |
1008 | 985 |
1009 void AsmTyper::VisitCallNew(CallNew* expr) { | 986 void AsmTyper::VisitCallNew(CallNew* expr) { |
1010 if (in_function_) { | 987 if (in_function_) { |
1011 FAIL(expr, "new not allowed in module function"); | 988 FAIL(expr, "new not allowed in module function"); |
1012 } | 989 } |
(...skipping 17 matching lines...) Expand all Loading... |
1030 FAIL(expr, "ill-typed new operator"); | 1007 FAIL(expr, "ill-typed new operator"); |
1031 } | 1008 } |
1032 | 1009 |
1033 | 1010 |
1034 void AsmTyper::VisitCallRuntime(CallRuntime* expr) { | 1011 void AsmTyper::VisitCallRuntime(CallRuntime* expr) { |
1035 // Allow runtime calls for now. | 1012 // Allow runtime calls for now. |
1036 } | 1013 } |
1037 | 1014 |
1038 | 1015 |
1039 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) { | 1016 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) { |
1040 if (!in_function_) { | |
1041 FAIL(expr, "unary operator inside module body"); | |
1042 } | |
1043 switch (expr->op()) { | 1017 switch (expr->op()) { |
1044 case Token::NOT: // Used to encode != and !== | 1018 case Token::NOT: // Used to encode != and !== |
1045 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt, | 1019 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt, |
1046 "operand expected to be integer")); | 1020 "operand expected to be integer")); |
1047 IntersectResult(expr, cache_.kAsmSigned); | 1021 IntersectResult(expr, cache_.kAsmSigned); |
1048 return; | 1022 return; |
1049 case Token::DELETE: | 1023 case Token::DELETE: |
1050 FAIL(expr, "delete operator encountered"); | 1024 FAIL(expr, "delete operator encountered"); |
1051 case Token::VOID: | 1025 case Token::VOID: |
1052 FAIL(expr, "void operator encountered"); | 1026 FAIL(expr, "void operator encountered"); |
1053 case Token::TYPEOF: | 1027 case Token::TYPEOF: |
1054 FAIL(expr, "typeof operator encountered"); | 1028 FAIL(expr, "typeof operator encountered"); |
1055 default: | 1029 default: |
1056 UNREACHABLE(); | 1030 UNREACHABLE(); |
1057 } | 1031 } |
1058 } | 1032 } |
1059 | 1033 |
1060 | 1034 |
1061 void AsmTyper::VisitCountOperation(CountOperation* expr) { | 1035 void AsmTyper::VisitCountOperation(CountOperation* expr) { |
1062 FAIL(expr, "increment or decrement operator encountered"); | 1036 FAIL(expr, "increment or decrement operator encountered"); |
1063 } | 1037 } |
1064 | 1038 |
1065 | 1039 |
1066 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr, | 1040 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr, |
1067 Type* left_expected, | 1041 Type* left_expected, |
1068 Type* right_expected, | 1042 Type* right_expected, |
1069 Type* result_type, bool conversion) { | 1043 Type* result_type, bool conversion) { |
1070 RECURSE(VisitWithExpectation(expr->left(), Type::Number(zone()), | 1044 RECURSE(VisitWithExpectation(expr->left(), Type::Number(), |
1071 "left bitwise operand expected to be a number")); | 1045 "left bitwise operand expected to be a number")); |
1072 int left_intish = intish_; | 1046 int left_intish = intish_; |
1073 Type* left_type = computed_type_; | 1047 Type* left_type = computed_type_; |
1074 if (!left_type->Is(left_expected)) { | 1048 if (!left_type->Is(left_expected)) { |
1075 FAIL(expr->left(), "left bitwise operand expected to be an integer"); | 1049 FAIL(expr->left(), "left bitwise operand expected to be an integer"); |
1076 } | 1050 } |
1077 if (left_intish > kMaxUncombinedAdditiveSteps) { | 1051 if (left_intish > kMaxUncombinedAdditiveSteps) { |
1078 FAIL(expr->left(), "too many consecutive additive ops"); | 1052 FAIL(expr->left(), "too many consecutive additive ops"); |
1079 } | 1053 } |
1080 | 1054 |
(...skipping 20 matching lines...) Expand all Loading... |
1101 if (!conversion) { | 1075 if (!conversion) { |
1102 if (!left_type->Is(right_type) || !right_type->Is(left_type)) { | 1076 if (!left_type->Is(right_type) || !right_type->Is(left_type)) { |
1103 FAIL(expr, "ill-typed bitwise operation"); | 1077 FAIL(expr, "ill-typed bitwise operation"); |
1104 } | 1078 } |
1105 } | 1079 } |
1106 IntersectResult(expr, result_type); | 1080 IntersectResult(expr, result_type); |
1107 } | 1081 } |
1108 | 1082 |
1109 | 1083 |
1110 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { | 1084 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { |
1111 if (!in_function_) { | |
1112 if (expr->op() != Token::BIT_OR && expr->op() != Token::MUL) { | |
1113 FAIL(expr, "illegal binary operator inside module body"); | |
1114 } | |
1115 if (!(expr->left()->IsProperty() || expr->left()->IsVariableProxy()) || | |
1116 !expr->right()->IsLiteral()) { | |
1117 FAIL(expr, "illegal computation inside module body"); | |
1118 } | |
1119 } | |
1120 switch (expr->op()) { | 1085 switch (expr->op()) { |
1121 case Token::COMMA: { | 1086 case Token::COMMA: { |
1122 RECURSE(VisitWithExpectation(expr->left(), Type::Any(), | 1087 RECURSE(VisitWithExpectation(expr->left(), Type::Any(), |
1123 "left comma operand expected to be any")); | 1088 "left comma operand expected to be any")); |
1124 RECURSE(VisitWithExpectation(expr->right(), Type::Any(), | 1089 RECURSE(VisitWithExpectation(expr->right(), Type::Any(), |
1125 "right comma operand expected to be any")); | 1090 "right comma operand expected to be any")); |
1126 IntersectResult(expr, computed_type_); | 1091 IntersectResult(expr, computed_type_); |
1127 return; | 1092 return; |
1128 } | 1093 } |
1129 case Token::OR: | 1094 case Token::OR: |
1130 case Token::AND: | 1095 case Token::AND: |
1131 FAIL(expr, "illegal logical operator"); | 1096 FAIL(expr, "illegal logical operator"); |
1132 case Token::BIT_OR: { | 1097 case Token::BIT_OR: { |
1133 // BIT_OR allows Any since it is used as a type coercion. | 1098 // BIT_OR allows Any since it is used as a type coercion. |
1134 VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmInt, | 1099 VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmInt, |
1135 cache_.kAsmSigned, true); | 1100 cache_.kAsmSigned, true); |
1136 if (expr->left()->IsCall() && expr->op() == Token::BIT_OR) { | |
1137 IntersectResult(expr->left(), cache_.kAsmSigned); | |
1138 } | |
1139 return; | 1101 return; |
1140 } | 1102 } |
1141 case Token::BIT_XOR: { | 1103 case Token::BIT_XOR: { |
1142 // Handle booleans specially to handle de-sugared ! | 1104 // Handle booleans specially to handle de-sugared ! |
1143 Literal* left = expr->left()->AsLiteral(); | 1105 Literal* left = expr->left()->AsLiteral(); |
1144 if (left && left->value()->IsBoolean()) { | 1106 if (left && left->value()->IsBoolean()) { |
1145 if (left->ToBooleanIsTrue()) { | 1107 if (left->ToBooleanIsTrue()) { |
1146 left->set_bounds(Bounds(cache_.kSingletonOne)); | 1108 left->set_bounds(Bounds(cache_.kSingletonOne)); |
1147 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmInt, | 1109 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmInt, |
1148 "not operator expects an integer")); | 1110 "not operator expects an integer")); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1215 if (intish_ > kMaxUncombinedMultiplicativeSteps) { | 1177 if (intish_ > kMaxUncombinedMultiplicativeSteps) { |
1216 FAIL(expr, "too many consecutive multiplicative ops"); | 1178 FAIL(expr, "too many consecutive multiplicative ops"); |
1217 } | 1179 } |
1218 } | 1180 } |
1219 IntersectResult(expr, cache_.kAsmInt); | 1181 IntersectResult(expr, cache_.kAsmInt); |
1220 return; | 1182 return; |
1221 } | 1183 } |
1222 } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() && | 1184 } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() && |
1223 right_type->Is(cache_.kAsmDouble)) { | 1185 right_type->Is(cache_.kAsmDouble)) { |
1224 // For unary +, expressed as x * 1.0 | 1186 // For unary +, expressed as x * 1.0 |
1225 if (expr->left()->IsCall() && expr->op() == Token::MUL) { | |
1226 IntersectResult(expr->left(), cache_.kAsmDouble); | |
1227 } | |
1228 IntersectResult(expr, cache_.kAsmDouble); | 1187 IntersectResult(expr, cache_.kAsmDouble); |
1229 return; | 1188 return; |
1230 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) { | 1189 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) { |
1231 if (left_intish != 0 || right_intish != 0) { | 1190 if (left_intish != 0 || right_intish != 0) { |
1232 FAIL(expr, "float operation before required fround"); | 1191 FAIL(expr, "float operation before required fround"); |
1233 } | 1192 } |
1234 IntersectResult(expr, cache_.kAsmFloat); | 1193 IntersectResult(expr, cache_.kAsmFloat); |
1235 intish_ = 1; | 1194 intish_ = 1; |
1236 return; | 1195 return; |
1237 } else if (type->Is(cache_.kAsmDouble)) { | 1196 } else if (type->Is(cache_.kAsmDouble)) { |
1238 IntersectResult(expr, cache_.kAsmDouble); | 1197 IntersectResult(expr, cache_.kAsmDouble); |
1239 return; | 1198 return; |
1240 } else { | 1199 } else { |
1241 FAIL(expr, "ill-typed arithmetic operation"); | 1200 FAIL(expr, "ill-typed arithmetic operation"); |
1242 } | 1201 } |
1243 } | 1202 } |
1244 default: | 1203 default: |
1245 UNREACHABLE(); | 1204 UNREACHABLE(); |
1246 } | 1205 } |
1247 } | 1206 } |
1248 | 1207 |
1249 | 1208 |
1250 void AsmTyper::VisitCompareOperation(CompareOperation* expr) { | 1209 void AsmTyper::VisitCompareOperation(CompareOperation* expr) { |
1251 if (!in_function_) { | |
1252 FAIL(expr, "comparison inside module body"); | |
1253 } | |
1254 Token::Value op = expr->op(); | 1210 Token::Value op = expr->op(); |
1255 if (op != Token::EQ && op != Token::NE && op != Token::LT && | 1211 if (op != Token::EQ && op != Token::NE && op != Token::LT && |
1256 op != Token::LTE && op != Token::GT && op != Token::GTE) { | 1212 op != Token::LTE && op != Token::GT && op != Token::GTE) { |
1257 FAIL(expr, "illegal comparison operator"); | 1213 FAIL(expr, "illegal comparison operator"); |
1258 } | 1214 } |
1259 | 1215 |
1260 RECURSE( | 1216 RECURSE( |
1261 VisitWithExpectation(expr->left(), Type::Number(), | 1217 VisitWithExpectation(expr->left(), Type::Number(), |
1262 "left comparison operand expected to be number")); | 1218 "left comparison operand expected to be number")); |
1263 Type* left_type = computed_type_; | 1219 Type* left_type = computed_type_; |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1530 | 1486 |
1531 | 1487 |
1532 void AsmTyper::VisitRewritableAssignmentExpression( | 1488 void AsmTyper::VisitRewritableAssignmentExpression( |
1533 RewritableAssignmentExpression* expr) { | 1489 RewritableAssignmentExpression* expr) { |
1534 RECURSE(Visit(expr->expression())); | 1490 RECURSE(Visit(expr->expression())); |
1535 } | 1491 } |
1536 | 1492 |
1537 | 1493 |
1538 } // namespace internal | 1494 } // namespace internal |
1539 } // namespace v8 | 1495 } // namespace v8 |
OLD | NEW |