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

Side by Side Diff: src/asmjs/asm-typer.cc

Issue 2134333003: V8. ASM-2-WASM. Migrates asm-wasm-builder to the new asm-typer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: addresses comments. Created 4 years, 5 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 | « src/asmjs/asm-typer.h ('k') | src/asmjs/asm-types.h » ('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 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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/asmjs/asm-typer.h" 5 #include "src/asmjs/asm-typer.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <string> 8 #include <string>
9 9
10 #include "src/v8.h" 10 #include "src/v8.h"
(...skipping 30 matching lines...) Expand all
41 } \ 41 } \
42 \ 42 \
43 if (result == AsmType::None()) { \ 43 if (result == AsmType::None()) { \
44 return AsmType::None(); \ 44 return AsmType::None(); \
45 } \ 45 } \
46 } while (false) 46 } while (false)
47 47
48 namespace v8 { 48 namespace v8 {
49 namespace internal { 49 namespace internal {
50 namespace wasm { 50 namespace wasm {
51 namespace {
52 static const uint32_t LargestFixNum = std::numeric_limits<int32_t>::max();
53 } // namespace
51 54
52 using v8::internal::AstNode; 55 using v8::internal::AstNode;
53 using v8::internal::GetCurrentStackPosition; 56 using v8::internal::GetCurrentStackPosition;
54 57
55 // ---------------------------------------------------------------------------- 58 // ----------------------------------------------------------------------------
56 // Implementation of AsmTyper::FlattenedStatements 59 // Implementation of AsmTyper::FlattenedStatements
57 60
58 AsmTyper::FlattenedStatements::FlattenedStatements(Zone* zone, 61 AsmTyper::FlattenedStatements::FlattenedStatements(Zone* zone,
59 ZoneList<Statement*>* s) 62 ZoneList<Statement*>* s)
60 : context_stack_(zone) { 63 : context_stack_(zone) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 forward_definitions_(zone), 118 forward_definitions_(zone),
116 stdlib_types_(zone), 119 stdlib_types_(zone),
117 stdlib_math_types_(zone), 120 stdlib_math_types_(zone),
118 global_scope_(ZoneHashMap::PointersMatch, 121 global_scope_(ZoneHashMap::PointersMatch,
119 ZoneHashMap::kDefaultHashMapCapacity, 122 ZoneHashMap::kDefaultHashMapCapacity,
120 ZoneAllocationPolicy(zone)), 123 ZoneAllocationPolicy(zone)),
121 local_scope_(ZoneHashMap::PointersMatch, 124 local_scope_(ZoneHashMap::PointersMatch,
122 ZoneHashMap::kDefaultHashMapCapacity, 125 ZoneHashMap::kDefaultHashMapCapacity,
123 ZoneAllocationPolicy(zone)), 126 ZoneAllocationPolicy(zone)),
124 stack_limit_(isolate->stack_guard()->real_climit()), 127 stack_limit_(isolate->stack_guard()->real_climit()),
125 node_types_(zone_) { 128 node_types_(zone_),
129 fround_type_(AsmType::FroundType(zone_)) {
126 InitializeStdlib(); 130 InitializeStdlib();
127 module_info_.set_standard_member(kModule); 131 module_info_.set_standard_member(kModule);
128 } 132 }
129 133
130 namespace { 134 namespace {
131 bool ValidAsmIdentifier(Handle<String> name) { 135 bool ValidAsmIdentifier(Handle<String> name) {
132 static const char* kInvalidAsmNames[] = {"eval", "arguments"}; 136 static const char* kInvalidAsmNames[] = {"eval", "arguments"};
133 137
134 for (size_t ii = 0; ii < arraysize(kInvalidAsmNames); ++ii) { 138 for (size_t ii = 0; ii < arraysize(kInvalidAsmNames); ++ii) {
135 if (strcmp(name->ToCString().get(), kInvalidAsmNames[ii]) == 0) { 139 if (strcmp(name->ToCString().get(), kInvalidAsmNames[ii]) == 0) {
(...skipping 22 matching lines...) Expand all
158 auto* s = AsmType::Signed(); 162 auto* s = AsmType::Signed();
159 auto* s2s = AsmType::Function(zone_, s); 163 auto* s2s = AsmType::Function(zone_, s);
160 s2s->AsFunctionType()->AddArgument(s); 164 s2s->AsFunctionType()->AddArgument(s);
161 165
162 auto* i = AsmType::Int(); 166 auto* i = AsmType::Int();
163 auto* ii2s = AsmType::Function(zone_, s); 167 auto* ii2s = AsmType::Function(zone_, s);
164 ii2s->AsFunctionType()->AddArgument(i); 168 ii2s->AsFunctionType()->AddArgument(i);
165 ii2s->AsFunctionType()->AddArgument(i); 169 ii2s->AsFunctionType()->AddArgument(i);
166 170
167 auto* minmax_d = AsmType::MinMaxType(zone_, d, d); 171 auto* minmax_d = AsmType::MinMaxType(zone_, d, d);
172 // *VIOLATION* The float variant is not part of the spec, but firefox accepts
173 // it.
174 auto* minmax_f = AsmType::MinMaxType(zone_, f, f);
168 auto* minmax_i = AsmType::MinMaxType(zone_, s, i); 175 auto* minmax_i = AsmType::MinMaxType(zone_, s, i);
169 auto* minmax = AsmType::OverloadedFunction(zone_); 176 auto* minmax = AsmType::OverloadedFunction(zone_);
170 minmax->AsOverloadedFunctionType()->AddOverload(minmax_i); 177 minmax->AsOverloadedFunctionType()->AddOverload(minmax_i);
178 minmax->AsOverloadedFunctionType()->AddOverload(minmax_f);
171 minmax->AsOverloadedFunctionType()->AddOverload(minmax_d); 179 minmax->AsOverloadedFunctionType()->AddOverload(minmax_d);
172 180
173 auto* fround = AsmType::FroundType(zone_); 181 auto* fround = fround_type_;
174 182
175 auto* abs = AsmType::OverloadedFunction(zone_); 183 auto* abs = AsmType::OverloadedFunction(zone_);
176 abs->AsOverloadedFunctionType()->AddOverload(s2s); 184 abs->AsOverloadedFunctionType()->AddOverload(s2s);
177 abs->AsOverloadedFunctionType()->AddOverload(dq2d); 185 abs->AsOverloadedFunctionType()->AddOverload(dq2d);
178 abs->AsOverloadedFunctionType()->AddOverload(fq2f); 186 abs->AsOverloadedFunctionType()->AddOverload(fq2f);
179 187
180 auto* ceil = AsmType::OverloadedFunction(zone_); 188 auto* ceil = AsmType::OverloadedFunction(zone_);
181 ceil->AsOverloadedFunctionType()->AddOverload(dq2d); 189 ceil->AsOverloadedFunctionType()->AddOverload(dq2d);
182 ceil->AsOverloadedFunctionType()->AddOverload(fq2f); 190 ceil->AsOverloadedFunctionType()->AddOverload(fq2f);
183 191
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 if (entry->value != nullptr) { 363 if (entry->value != nullptr) {
356 return false; 364 return false;
357 } 365 }
358 366
359 entry->value = info; 367 entry->value = info;
360 return true; 368 return true;
361 } 369 }
362 370
363 void AsmTyper::SetTypeOf(AstNode* node, AsmType* type) { 371 void AsmTyper::SetTypeOf(AstNode* node, AsmType* type) {
364 DCHECK_NE(type, AsmType::None()); 372 DCHECK_NE(type, AsmType::None());
365 auto** node_type = &node_types_[node]; 373 DCHECK(node_types_.find(node) == node_types_.end());
366 DCHECK(*node_type == nullptr); 374 node_types_.insert(std::make_pair(node, type));
367 *node_type = type;
368 } 375 }
369 376
370 AsmType* AsmTyper::TypeOf(AstNode* node) const { 377 AsmType* AsmTyper::TypeOf(AstNode* node) const {
371 auto node_type_iter = node_types_.find(node); 378 auto node_type_iter = node_types_.find(node);
372 if (node_type_iter == node_types_.end()) { 379 if (node_type_iter != node_types_.end()) {
373 return AsmType::None(); 380 return node_type_iter->second;
374 } 381 }
375 return node_type_iter->second; 382
383 // Sometimes literal nodes are not added to the node_type_ map simply because
384 // their are not visited with ValidateExpression().
385 if (auto* literal = node->AsLiteral()) {
386 if (literal->raw_value()->ContainsDot()) {
387 return AsmType::Double();
388 }
389 uint32_t u;
390 if (literal->value()->ToUint32(&u)) {
391 if (u > LargestFixNum) {
392 return AsmType::Unsigned();
393 }
394 return AsmType::FixNum();
395 }
396 int32_t i;
397 if (literal->value()->ToInt32(&i)) {
398 return AsmType::Signed();
399 }
400 }
401
402 return AsmType::None();
376 } 403 }
377 404
378 AsmTyper::StandardMember AsmTyper::VariableAsStandardMember(Variable* var) { 405 AsmTyper::StandardMember AsmTyper::VariableAsStandardMember(Variable* var) {
379 auto* var_info = Lookup(var); 406 auto* var_info = Lookup(var);
380 if (var_info == nullptr) { 407 if (var_info == nullptr) {
381 return kNone; 408 return kNone;
382 } 409 }
383 return var_info->standard_member(); 410 return var_info->standard_member();
384 } 411 }
385 412
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 auto* target_variable = target->AsVariableProxy()->var(); 627 auto* target_variable = target->AsVariableProxy()->var();
601 auto* target_info = Lookup(target_variable); 628 auto* target_info = Lookup(target_variable);
602 629
603 if (target_info != nullptr) { 630 if (target_info != nullptr) {
604 FAIL(target, "Redefined global variable."); 631 FAIL(target, "Redefined global variable.");
605 } 632 }
606 633
607 auto* value = assign->value(); 634 auto* value = assign->value();
608 // Not all types of assignment are allowed by asm.js. See 635 // Not all types of assignment are allowed by asm.js. See
609 // 5.5 Global Variable Type Annotations. 636 // 5.5 Global Variable Type Annotations.
637 bool global_variable = false;
610 if (value->IsLiteral() || value->IsCall()) { 638 if (value->IsLiteral() || value->IsCall()) {
611 AsmType* type = nullptr; 639 AsmType* type = nullptr;
612 RECURSE(type = VariableTypeAnnotations(value)); 640 RECURSE(type = VariableTypeAnnotations(value));
613 target_info = new (zone_) VariableInfo(type); 641 target_info = new (zone_) VariableInfo(type);
614 target_info->set_mutability(VariableInfo::kMutableGlobal); 642 target_info->set_mutability(VariableInfo::kMutableGlobal);
643 global_variable = true;
615 } else if (value->IsProperty()) { 644 } else if (value->IsProperty()) {
616 target_info = ImportLookup(value->AsProperty()); 645 target_info = ImportLookup(value->AsProperty());
617 if (target_info == nullptr) { 646 if (target_info == nullptr) {
618 FAIL(assign, "Invalid import."); 647 FAIL(assign, "Invalid import.");
619 } 648 }
620 CHECK(target_info->mutability() == VariableInfo::kImmutableGlobal); 649 CHECK(target_info->mutability() == VariableInfo::kImmutableGlobal);
621 if (!target_info->IsFFI()) { 650 if (!target_info->IsFFI()) {
622 target_info = target_info->Clone(zone_); 651 target_info = target_info->Clone(zone_);
623 } else { 652 } else {
624 // create a new target info that represents a foreign variable. 653 // create a new target info that represents a foreign variable.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 711
683 if (!ValidAsmIdentifier(target_variable->name())) { 712 if (!ValidAsmIdentifier(target_variable->name())) {
684 FAIL(target, "Invalid asm.js identifier in global variable."); 713 FAIL(target, "Invalid asm.js identifier in global variable.");
685 } 714 }
686 715
687 if (!AddGlobal(target_variable, target_info)) { 716 if (!AddGlobal(target_variable, target_info)) {
688 FAIL(assign, "Redeclared global identifier."); 717 FAIL(assign, "Redeclared global identifier.");
689 } 718 }
690 719
691 DCHECK(target_info->type() != AsmType::None()); 720 DCHECK(target_info->type() != AsmType::None());
721 if (!global_variable) {
722 // Global variables have their types set in VariableTypeAnnotations.
723 SetTypeOf(value, target_info->type());
724 }
725 SetTypeOf(assign, target_info->type());
726 SetTypeOf(target, target_info->type());
692 return target_info->type(); 727 return target_info->type();
693 } 728 }
694 729
695 // 6.2 ValidateExport 730 // 6.2 ValidateExport
696 AsmType* AsmTyper::ExportType(VariableProxy* fun_export) { 731 AsmType* AsmTyper::ExportType(VariableProxy* fun_export) {
697 auto* fun_info = Lookup(fun_export->var()); 732 auto* fun_info = Lookup(fun_export->var());
698 if (fun_info == nullptr) { 733 if (fun_info == nullptr) {
699 FAIL(fun_export, "Undefined identifier in asm.js module export."); 734 FAIL(fun_export, "Undefined identifier in asm.js module export.");
700 } 735 }
701 736
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 target_info = new (zone_) VariableInfo(AsmType::FunctionTableType( 858 target_info = new (zone_) VariableInfo(AsmType::FunctionTableType(
824 zone_, pointers->length(), table_element_type)); 859 zone_, pointers->length(), table_element_type));
825 target_info->set_mutability(VariableInfo::kImmutableGlobal); 860 target_info->set_mutability(VariableInfo::kImmutableGlobal);
826 if (!ValidAsmIdentifier(target_variable->name())) { 861 if (!ValidAsmIdentifier(target_variable->name())) {
827 FAIL(target, "Invalid asm.js identifier in function table name."); 862 FAIL(target, "Invalid asm.js identifier in function table name.");
828 } 863 }
829 if (!AddGlobal(target_variable, target_info)) { 864 if (!AddGlobal(target_variable, target_info)) {
830 DCHECK(false); 865 DCHECK(false);
831 FAIL(assign, "Redeclared global identifier in function table name."); 866 FAIL(assign, "Redeclared global identifier in function table name.");
832 } 867 }
868 SetTypeOf(value, target_info->type());
833 return target_info->type(); 869 return target_info->type();
834 } 870 }
835 871
836 auto* target_info_table = target_info->type()->AsFunctionTableType(); 872 auto* target_info_table = target_info->type()->AsFunctionTableType();
837 if (target_info_table == nullptr) { 873 if (target_info_table == nullptr) {
838 FAIL(assign, "Identifier redefined as function pointer table."); 874 FAIL(assign, "Identifier redefined as function pointer table.");
839 } 875 }
840 876
841 if (!target_info->missing_definition()) { 877 if (!target_info->missing_definition()) {
842 FAIL(assign, "Identifier redefined (function table name)."); 878 FAIL(assign, "Identifier redefined (function table name).");
843 } 879 }
844 880
845 if (target_info_table->length() != pointers->length()) { 881 if (target_info_table->length() != pointers->length()) {
846 FAIL(assign, "Function table size mismatch."); 882 FAIL(assign, "Function table size mismatch.");
847 } 883 }
848 884
849 auto* function_type = callable_type->AsFunctionType(); 885 auto* function_type = callable_type->AsFunctionType();
850 if (target_info_table->ValidateCall(function_type->ReturnType(), 886 if (target_info_table->ValidateCall(function_type->ReturnType(),
851 function_type->Arguments()) == 887 function_type->Arguments()) ==
852 AsmType::None()) { 888 AsmType::None()) {
853 FAIL(assign, "Function table initializer does not match previous type."); 889 FAIL(assign, "Function table initializer does not match previous type.");
854 } 890 }
855 891
856 target_info->MarkDefined(); 892 target_info->MarkDefined();
857 DCHECK(target_info->type() == AsmType::None()); 893 DCHECK(target_info->type() != AsmType::None());
858 SetTypeOf(value, target_info->type()); 894 SetTypeOf(value, target_info->type());
859 895
860 return target_info->type(); 896 return target_info->type();
861 } 897 }
862 898
863 // 6.4 ValidateFunction 899 // 6.4 ValidateFunction
864 AsmType* AsmTyper::ValidateFunction(FunctionDeclaration* fun_decl) { 900 AsmType* AsmTyper::ValidateFunction(FunctionDeclaration* fun_decl) {
865 FunctionScope _(this); 901 FunctionScope _(this);
866 902
867 // Extract parameter types. 903 // Extract parameter types.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
909 auto* param_info = new (zone_) VariableInfo(type); 945 auto* param_info = new (zone_) VariableInfo(type);
910 param_info->set_mutability(VariableInfo::kLocal); 946 param_info->set_mutability(VariableInfo::kLocal);
911 if (!ValidAsmIdentifier(proxy->name())) { 947 if (!ValidAsmIdentifier(proxy->name())) {
912 FAIL(proxy, "Invalid asm.js identifier in parameter name."); 948 FAIL(proxy, "Invalid asm.js identifier in parameter name.");
913 } 949 }
914 950
915 if (!AddLocal(param, param_info)) { 951 if (!AddLocal(param, param_info)) {
916 FAIL(proxy, "Redeclared parameter."); 952 FAIL(proxy, "Redeclared parameter.");
917 } 953 }
918 parameter_types.push_back(type); 954 parameter_types.push_back(type);
955 SetTypeOf(proxy, type);
956 SetTypeOf(expr, type);
919 } 957 }
920 958
921 if (annotated_parameters != fun->parameter_count()) { 959 if (annotated_parameters != fun->parameter_count()) {
922 FAIL(fun_decl, "Incorrect parameter type annotations."); 960 FAIL(fun_decl, "Incorrect parameter type annotations.");
923 } 961 }
924 962
925 // 5.3 Function type annotations 963 // 5.3 Function type annotations
926 // * locals 964 // * locals
927 for (; current; current = iter.Next()) { 965 for (; current; current = iter.Next()) {
928 auto* initializer = ExtractInitializerExpression(current); 966 auto* initializer = ExtractInitializerExpression(current);
(...skipping 16 matching lines...) Expand all
945 RECURSE(type = VariableTypeAnnotations(initializer->value())); 983 RECURSE(type = VariableTypeAnnotations(initializer->value()));
946 auto* local_info = new (zone_) VariableInfo(type); 984 auto* local_info = new (zone_) VariableInfo(type);
947 local_info->set_mutability(VariableInfo::kLocal); 985 local_info->set_mutability(VariableInfo::kLocal);
948 if (!ValidAsmIdentifier(local->name())) { 986 if (!ValidAsmIdentifier(local->name())) {
949 FAIL(local, "Invalid asm.js identifier in local variable."); 987 FAIL(local, "Invalid asm.js identifier in local variable.");
950 } 988 }
951 989
952 if (!AddLocal(local->var(), local_info)) { 990 if (!AddLocal(local->var(), local_info)) {
953 FAIL(initializer, "Redeclared local."); 991 FAIL(initializer, "Redeclared local.");
954 } 992 }
993
994 SetTypeOf(local, type);
995 SetTypeOf(initializer, type);
955 } 996 }
956 997
957 // 5.2 Return Type Annotations 998 // 5.2 Return Type Annotations
958 // *VIOLATION* we peel blocks to find the last statement in the asm module 999 // *VIOLATION* we peel blocks to find the last statement in the asm module
959 // because the parser may introduce synthetic blocks. 1000 // because the parser may introduce synthetic blocks.
960 ZoneList<Statement*>* statements = fun->body(); 1001 ZoneList<Statement*>* statements = fun->body();
961 1002
962 do { 1003 do {
963 if (statements->length() == 0) { 1004 if (statements->length() == 0) {
964 return_type_ = AsmType::Void(); 1005 return_type_ = AsmType::Void();
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1011 fun_info->set_mutability(VariableInfo::kImmutableGlobal); 1052 fun_info->set_mutability(VariableInfo::kImmutableGlobal);
1012 auto* old_fun_type = Lookup(fun_var); 1053 auto* old_fun_type = Lookup(fun_var);
1013 if (old_fun_type == nullptr) { 1054 if (old_fun_type == nullptr) {
1014 if (!ValidAsmIdentifier(fun_var->name())) { 1055 if (!ValidAsmIdentifier(fun_var->name())) {
1015 FAIL(fun_decl_proxy, "Invalid asm.js identifier in function name."); 1056 FAIL(fun_decl_proxy, "Invalid asm.js identifier in function name.");
1016 } 1057 }
1017 if (!AddGlobal(fun_var, fun_info)) { 1058 if (!AddGlobal(fun_var, fun_info)) {
1018 DCHECK(false); 1059 DCHECK(false);
1019 FAIL(fun_decl, "Redeclared global identifier."); 1060 FAIL(fun_decl, "Redeclared global identifier.");
1020 } 1061 }
1062
1063 SetTypeOf(fun, fun_type);
1021 return fun_type; 1064 return fun_type;
1022 } 1065 }
1023 1066
1024 // Not necessarily an error -- fun_decl might have been used before being 1067 // Not necessarily an error -- fun_decl might have been used before being
1025 // defined. If that's the case, then the type in the global environment must 1068 // defined. If that's the case, then the type in the global environment must
1026 // be the same as the type inferred by the parameter/return type annotations. 1069 // be the same as the type inferred by the parameter/return type annotations.
1027 auto* old_fun_callable = old_fun_type->type()->AsCallableType(); 1070 auto* old_fun_callable = old_fun_type->type()->AsCallableType();
1028 if (old_fun_callable == nullptr) { 1071 if (old_fun_callable == nullptr) {
1029 FAIL(fun_decl, "Identifier redefined as function."); 1072 FAIL(fun_decl, "Identifier redefined as function.");
1030 } 1073 }
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1214 } 1257 }
1215 1258
1216 bool has_default = false; 1259 bool has_default = false;
1217 1260
1218 ZoneSet<int32_t> cases_seen(zone_); 1261 ZoneSet<int32_t> cases_seen(zone_);
1219 for (auto* a_case : *stmt->cases()) { 1262 for (auto* a_case : *stmt->cases()) {
1220 if (a_case->is_default()) { 1263 if (a_case->is_default()) {
1221 CHECK(!has_default); 1264 CHECK(!has_default);
1222 RECURSE(ValidateDefault(a_case)); 1265 RECURSE(ValidateDefault(a_case));
1223 has_default = true; 1266 has_default = true;
1267 continue;
1224 } 1268 }
1225 1269
1226 int32_t case_lbl; 1270 int32_t case_lbl;
1227 RECURSE(ValidateCase(a_case, &case_lbl)); 1271 RECURSE(ValidateCase(a_case, &case_lbl));
1228 auto case_lbl_pos = cases_seen.find(case_lbl); 1272 auto case_lbl_pos = cases_seen.find(case_lbl);
1229 if (case_lbl_pos != cases_seen.end() && *case_lbl_pos == case_lbl) { 1273 if (case_lbl_pos != cases_seen.end() && *case_lbl_pos == case_lbl) {
1230 FAIL(a_case, "Duplicated case label."); 1274 FAIL(a_case, "Duplicated case label.");
1231 } 1275 }
1232 cases_seen.insert(case_lbl); 1276 cases_seen.insert(case_lbl);
1233 } 1277 }
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1357 // *VIOLATION* The parser replaces uses of +x with x*1.0. 1401 // *VIOLATION* The parser replaces uses of +x with x*1.0.
1358 if (binop->op() != Token::MUL) { 1402 if (binop->op() != Token::MUL) {
1359 return false; 1403 return false;
1360 } 1404 }
1361 1405
1362 auto* right_as_literal = binop->right()->AsLiteral(); 1406 auto* right_as_literal = binop->right()->AsLiteral();
1363 if (right_as_literal == nullptr) { 1407 if (right_as_literal == nullptr) {
1364 return false; 1408 return false;
1365 } 1409 }
1366 1410
1367 return right_as_literal->raw_value()->ContainsDot() && 1411 return !right_as_literal->raw_value()->ContainsDot() &&
1368 right_as_literal->raw_value()->AsNumber() == -1.0; 1412 right_as_literal->raw_value()->AsNumber() == -1.0;
1369 } 1413 }
1370 } // namespace 1414 } // namespace
1371 1415
1372 AsmType* AsmTyper::ValidateBinaryOperation(BinaryOperation* expr) { 1416 AsmType* AsmTyper::ValidateBinaryOperation(BinaryOperation* expr) {
1373 #define UNOP_OVERLOAD(Src, Dest) \ 1417 #define UNOP_OVERLOAD(Src, Dest) \
1374 do { \ 1418 do { \
1375 if (left_type->IsA(AsmType::Src())) { \ 1419 if (left_type->IsA(AsmType::Src())) { \
1376 return AsmType::Dest(); \ 1420 return AsmType::Dest(); \
1377 } \ 1421 } \
1378 } while (0) 1422 } while (0)
1379 1423
1380 switch (expr->op()) { 1424 switch (expr->op()) {
1381 default: 1425 default:
1382 FAIL(expr, "Invalid asm.js binary expression."); 1426 FAIL(expr, "Invalid asm.js binary expression.");
1383 case Token::COMMA: 1427 case Token::COMMA:
1384 return ValidateCommaExpression(expr); 1428 return ValidateCommaExpression(expr);
1385 case Token::MUL: 1429 case Token::MUL:
1386 if (IsDoubleAnnotation(expr)) { 1430 if (IsDoubleAnnotation(expr)) {
1387 // *VIOLATION* We can't be 100% sure this really IS a unary + in the asm 1431 // *VIOLATION* We can't be 100% sure this really IS a unary + in the asm
1388 // source so we have to be lenient, and treat this as a unary +. 1432 // source so we have to be lenient, and treat this as a unary +.
1389 if (auto* Call = expr->left()->AsCall()) { 1433 if (auto* Call = expr->left()->AsCall()) {
1390 return ValidateCall(AsmType::Double(), Call); 1434 return ValidateCall(AsmType::Double(), Call);
1391 } 1435 }
1392 AsmType* left_type; 1436 AsmType* left_type;
1393 RECURSE(left_type = ValidateExpression(expr->left())); 1437 RECURSE(left_type = ValidateExpression(expr->left()));
1438 SetTypeOf(expr->right(), AsmType::Double());
1394 UNOP_OVERLOAD(Signed, Double); 1439 UNOP_OVERLOAD(Signed, Double);
1395 UNOP_OVERLOAD(Unsigned, Double); 1440 UNOP_OVERLOAD(Unsigned, Double);
1396 UNOP_OVERLOAD(DoubleQ, Double); 1441 UNOP_OVERLOAD(DoubleQ, Double);
1397 UNOP_OVERLOAD(FloatQ, Double); 1442 UNOP_OVERLOAD(FloatQ, Double);
1398 FAIL(expr, "Invalid type for conversion to double."); 1443 FAIL(expr, "Invalid type for conversion to double.");
1399 } 1444 }
1400 1445
1401 if (IsUnaryMinus(expr)) { 1446 if (IsUnaryMinus(expr)) {
1402 // *VIOLATION* the parser converts -x to x * -1.0. 1447 // *VIOLATION* the parser converts -x to x * -1.0.
1403 AsmType* left_type; 1448 AsmType* left_type;
1404 RECURSE(left_type = ValidateExpression(expr->left())); 1449 RECURSE(left_type = ValidateExpression(expr->left()));
1450 SetTypeOf(expr->right(), left_type);
1405 UNOP_OVERLOAD(Int, Intish); 1451 UNOP_OVERLOAD(Int, Intish);
1406 UNOP_OVERLOAD(DoubleQ, Double); 1452 UNOP_OVERLOAD(DoubleQ, Double);
1407 UNOP_OVERLOAD(FloatQ, Floatish); 1453 UNOP_OVERLOAD(FloatQ, Floatish);
1408 FAIL(expr, "Invalid type for unary -."); 1454 FAIL(expr, "Invalid type for unary -.");
1409 } 1455 }
1410 // FALTHROUGH 1456 // FALTHROUGH
1411 case Token::DIV: 1457 case Token::DIV:
1412 case Token::MOD: 1458 case Token::MOD:
1413 return ValidateMultiplicativeExpression(expr); 1459 return ValidateMultiplicativeExpression(expr);
1414 case Token::ADD: 1460 case Token::ADD:
1415 case Token::SUB: { 1461 case Token::SUB: {
1416 static const uint32_t kInitialIntishCount = 0; 1462 static const uint32_t kInitialIntishCount = 0;
1417 return ValidateAdditiveExpression(expr, kInitialIntishCount); 1463 return ValidateAdditiveExpression(expr, kInitialIntishCount);
1418 } 1464 }
1419 case Token::SAR: 1465 case Token::SAR:
1420 case Token::SHL: 1466 case Token::SHL:
1421 case Token::SHR: 1467 case Token::SHR:
1422 return ValidateShiftExpression(expr); 1468 return ValidateShiftExpression(expr);
1423 case Token::BIT_AND: 1469 case Token::BIT_AND:
1424 return ValidateBitwiseANDExpression(expr); 1470 return ValidateBitwiseANDExpression(expr);
1425 case Token::BIT_XOR: 1471 case Token::BIT_XOR:
1426 if (IsNegate(expr)) { 1472 if (IsNegate(expr)) {
1427 auto* left = expr->left(); 1473 auto* left = expr->left();
1428 auto* left_as_binop = left->AsBinaryOperation(); 1474 auto* left_as_binop = left->AsBinaryOperation();
1429 1475
1430 if (left_as_binop != nullptr && IsNegate(left_as_binop)) { 1476 if (left_as_binop != nullptr && IsNegate(left_as_binop)) {
1431 // This is the special ~~ operator. 1477 // This is the special ~~ operator.
1432 AsmType* left_type; 1478 AsmType* left_type;
1433 RECURSE(left_type = ValidateExpression(left_as_binop->left())); 1479 RECURSE(left_type = ValidateExpression(left_as_binop->left()));
1480 SetTypeOf(left_as_binop->right(), AsmType::FixNum());
1481 SetTypeOf(left_as_binop, AsmType::Signed());
1482 SetTypeOf(expr->right(), AsmType::FixNum());
1434 UNOP_OVERLOAD(Double, Signed); 1483 UNOP_OVERLOAD(Double, Signed);
1435 UNOP_OVERLOAD(FloatQ, Signed); 1484 UNOP_OVERLOAD(FloatQ, Signed);
1436 FAIL(left_as_binop, "Invalid type for conversion to signed."); 1485 FAIL(left_as_binop, "Invalid type for conversion to signed.");
1437 } 1486 }
1438 1487
1439 AsmType* left_type; 1488 AsmType* left_type;
1440 RECURSE(left_type = ValidateExpression(left)); 1489 RECURSE(left_type = ValidateExpression(left));
1441 UNOP_OVERLOAD(Intish, Signed); 1490 UNOP_OVERLOAD(Intish, Signed);
1442 FAIL(left, "Invalid type for ~."); 1491 FAIL(left, "Invalid type for ~.");
1443 } 1492 }
1444 1493
1445 return ValidateBitwiseXORExpression(expr); 1494 return ValidateBitwiseXORExpression(expr);
1446 case Token::BIT_OR: 1495 case Token::BIT_OR:
1447 return ValidateBitwiseORExpression(expr); 1496 return ValidateBitwiseORExpression(expr);
1448 } 1497 }
1449 #undef UNOP_OVERLOAD 1498 #undef UNOP_OVERLOAD
1450 UNREACHABLE(); 1499 UNREACHABLE();
1451 } 1500 }
1452 1501
1453 // 6.8.1 Expression 1502 // 6.8.1 Expression
1454 AsmType* AsmTyper::ValidateCommaExpression(BinaryOperation* comma) { 1503 AsmType* AsmTyper::ValidateCommaExpression(BinaryOperation* comma) {
1455 // The AST looks like: 1504 // The AST looks like:
1456 // (expr COMMA (expr COMMA (expr COMMA (... )))) 1505 // (expr COMMA (expr COMMA (expr COMMA (... ))))
1457 1506
1458 auto* left = comma->left(); 1507 auto* left = comma->left();
1459 auto* left_as_binop = left->AsBinaryOperation(); 1508 if (auto* left_as_call = left->AsCall()) {
1460 if (left_as_binop && left_as_binop->op() == Token::COMMA) { 1509 RECURSE(ValidateCall(AsmType::Void(), left_as_call));
1461 ValidateCommaExpression(left_as_binop);
1462 } else if (auto* left_as_call = left->AsCall()) {
1463 ValidateCall(AsmType::Void(), left_as_call);
1464 } else { 1510 } else {
1465 ValidateExpression(left); 1511 RECURSE(ValidateExpression(left));
1466 } 1512 }
1467 1513
1468 auto* right = comma->right(); 1514 auto* right = comma->right();
1469 auto* right_as_binop = right->AsBinaryOperation(); 1515 AsmType* right_type = nullptr;
1470 if (right_as_binop && right_as_binop->op() == Token::COMMA) { 1516 if (auto* right_as_call = right->AsCall()) {
1471 return ValidateCommaExpression(right_as_binop); 1517 RECURSE(right_type = ValidateCall(AsmType::Void(), right_as_call));
1472 } else { 1518 } else {
1473 return ValidateExpression(right); 1519 RECURSE(right_type = ValidateExpression(right));
1474 } 1520 }
1475 1521
1476 UNREACHABLE(); 1522 return right_type;
1477 } 1523 }
1478 1524
1479 // 6.8.2 NumericLiteral 1525 // 6.8.2 NumericLiteral
1480 AsmType* AsmTyper::ValidateNumericLiteral(Literal* literal) { 1526 AsmType* AsmTyper::ValidateNumericLiteral(Literal* literal) {
1481 // *VIOLATION* asm.js does not allow the use of undefined, but our parser 1527 // *VIOLATION* asm.js does not allow the use of undefined, but our parser
1482 // inserts them, so we have to handle them. 1528 // inserts them, so we have to handle them.
1483 if (literal->IsUndefinedLiteral()) { 1529 if (literal->IsUndefinedLiteral()) {
1484 return AsmType::Void(); 1530 return AsmType::Void();
1485 } 1531 }
1486 1532
1487 if (literal->raw_value()->ContainsDot()) { 1533 if (literal->raw_value()->ContainsDot()) {
1488 return AsmType::Double(); 1534 return AsmType::Double();
1489 } 1535 }
1490 1536
1491 uint32_t value; 1537 uint32_t value;
1492 if (!literal->value()->ToUint32(&value)) { 1538 if (!literal->value()->ToUint32(&value)) {
1493 int32_t value; 1539 int32_t value;
1494 if (!literal->value()->ToInt32(&value)) { 1540 if (!literal->value()->ToInt32(&value)) {
1495 FAIL(literal, "Integer literal is out of range."); 1541 FAIL(literal, "Integer literal is out of range.");
1496 } 1542 }
1497 // *VIOLATION* Not really a violation, but rather a different in the 1543 // *VIOLATION* Not really a violation, but rather a different in the
1498 // validation. The spec handles -NumericLiteral in ValidateUnaryExpression, 1544 // validation. The spec handles -NumericLiteral in ValidateUnaryExpression,
1499 // but V8's AST represents the negative literals as Literals. 1545 // but V8's AST represents the negative literals as Literals.
1500 return AsmType::Signed(); 1546 return AsmType::Signed();
1501 } 1547 }
1502 1548
1503 static const uint32_t LargestFixNum = std::numeric_limits<int32_t>::max();
1504 if (value <= LargestFixNum) { 1549 if (value <= LargestFixNum) {
1505 return AsmType::FixNum(); 1550 return AsmType::FixNum();
1506 } 1551 }
1507 1552
1508 return AsmType::Unsigned(); 1553 return AsmType::Unsigned();
1509 } 1554 }
1510 1555
1511 // 6.8.3 Identifier 1556 // 6.8.3 Identifier
1512 AsmType* AsmTyper::ValidateIdentifier(VariableProxy* proxy) { 1557 AsmType* AsmTyper::ValidateIdentifier(VariableProxy* proxy) {
1513 auto* proxy_info = Lookup(proxy->var()); 1558 auto* proxy_info = Lookup(proxy->var());
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1580 1625
1581 return value_type; 1626 return value_type;
1582 } 1627 }
1583 1628
1584 if (auto* target_as_property = assignment->target()->AsProperty()) { 1629 if (auto* target_as_property = assignment->target()->AsProperty()) {
1585 AsmType* allowed_store_types; 1630 AsmType* allowed_store_types;
1586 RECURSE(allowed_store_types = 1631 RECURSE(allowed_store_types =
1587 ValidateHeapAccess(target_as_property, StoreToHeap)); 1632 ValidateHeapAccess(target_as_property, StoreToHeap));
1588 1633
1589 // TODO(jpp): Change FloatishDoubleQ and FloatQDoubleQ so that they are base 1634 // TODO(jpp): Change FloatishDoubleQ and FloatQDoubleQ so that they are base
1590 // classes for Floatish, DoubleQ, and FloatQ, and then invert this if so 1635 // classes for Floatish, DoubleQ, and FloatQ.
1591 // that it reads more naturally as 1636 if (allowed_store_types == AsmType::FloatishDoubleQ()) {
1592 // 1637 if (!value_type->IsA(AsmType::Floatish()) &&
1593 // if (!value_type->IsA(allowed_store_types)) 1638 !value_type->IsA(AsmType::DoubleQ())) {
1594 if (allowed_store_types == AsmType::FloatishDoubleQ() || 1639 FAIL(assignment, "Type mismatch in heap assignment.");
1595 allowed_store_types == AsmType::FloatQDoubleQ()) { 1640 }
1596 if (!allowed_store_types->IsA(value_type)) { 1641 } else if (allowed_store_types == AsmType::FloatQDoubleQ()) {
1642 if (!value_type->IsA(AsmType::FloatQ()) &&
1643 !value_type->IsA(AsmType::DoubleQ())) {
1597 FAIL(assignment, "Type mismatch in heap assignment."); 1644 FAIL(assignment, "Type mismatch in heap assignment.");
1598 } 1645 }
1599 } else { 1646 } else {
1600 if (!value_type->IsA(allowed_store_types)) { 1647 if (!value_type->IsA(allowed_store_types)) {
1601 FAIL(assignment, "Type mismatch in heap assignment."); 1648 FAIL(assignment, "Type mismatch in heap assignment.");
1602 } 1649 }
1603 } 1650 }
1604 1651
1605 return value_type; 1652 return value_type;
1606 } 1653 }
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1771 auto* left = binop->left(); 1818 auto* left = binop->left();
1772 auto* left_as_binop = left->AsBinaryOperation(); 1819 auto* left_as_binop = left->AsBinaryOperation();
1773 AsmType* left_type; 1820 AsmType* left_type;
1774 1821
1775 // TODO(jpp): maybe use an iterative approach instead of the recursion to 1822 // TODO(jpp): maybe use an iterative approach instead of the recursion to
1776 // ValidateAdditiveExpression. 1823 // ValidateAdditiveExpression.
1777 if (left_as_binop != nullptr && (left_as_binop->op() == Token::ADD || 1824 if (left_as_binop != nullptr && (left_as_binop->op() == Token::ADD ||
1778 left_as_binop->op() == Token::SUB)) { 1825 left_as_binop->op() == Token::SUB)) {
1779 RECURSE(left_type = 1826 RECURSE(left_type =
1780 ValidateAdditiveExpression(left_as_binop, intish_count + 1)); 1827 ValidateAdditiveExpression(left_as_binop, intish_count + 1));
1828 SetTypeOf(left_as_binop, left_type);
1781 } else { 1829 } else {
1782 RECURSE(left_type = ValidateExpression(left)); 1830 RECURSE(left_type = ValidateExpression(left));
1783 } 1831 }
1784 1832
1785 auto* right = binop->right(); 1833 auto* right = binop->right();
1786 auto* right_as_binop = right->AsBinaryOperation(); 1834 auto* right_as_binop = right->AsBinaryOperation();
1787 AsmType* right_type; 1835 AsmType* right_type;
1788 1836
1789 if (right_as_binop != nullptr && (right_as_binop->op() == Token::ADD || 1837 if (right_as_binop != nullptr && (right_as_binop->op() == Token::ADD ||
1790 right_as_binop->op() == Token::SUB)) { 1838 right_as_binop->op() == Token::SUB)) {
1791 RECURSE(right_type = 1839 RECURSE(right_type =
1792 ValidateAdditiveExpression(right_as_binop, intish_count + 1)); 1840 ValidateAdditiveExpression(right_as_binop, intish_count + 1));
1841 SetTypeOf(right_as_binop, right_type);
1793 } else { 1842 } else {
1794 RECURSE(right_type = ValidateExpression(right)); 1843 RECURSE(right_type = ValidateExpression(right));
1795 } 1844 }
1796 1845
1797 if (left_type->IsA(AsmType::FloatQ()) && right_type->IsA(AsmType::FloatQ())) { 1846 if (left_type->IsA(AsmType::FloatQ()) && right_type->IsA(AsmType::FloatQ())) {
1798 return AsmType::Floatish(); 1847 return AsmType::Floatish();
1799 } 1848 }
1800 1849
1801 if (left_type->IsA(AsmType::Int()) && right_type->IsA(AsmType::Int())) { 1850 if (left_type->IsA(AsmType::Int()) && right_type->IsA(AsmType::Int())) {
1802 if (intish_count == 0) { 1851 if (intish_count == 0) {
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
2077 if (as_literal->raw_value()->ContainsDot()) { 2126 if (as_literal->raw_value()->ContainsDot()) {
2078 return false; 2127 return false;
2079 } 2128 }
2080 2129
2081 if (!as_literal->value()->ToUint32(value)) { 2130 if (!as_literal->value()->ToUint32(value)) {
2082 return false; 2131 return false;
2083 } 2132 }
2084 2133
2085 return base::bits::IsPowerOfTwo32(1 + *value); 2134 return base::bits::IsPowerOfTwo32(1 + *value);
2086 } 2135 }
2087
2088 // TODO(jpp): Add a AsmType::ValidateCall is poorly designed. It can only handle
2089 // function declarations, not invocations. CheckInvocationOf temporarily works
2090 // around this limitation by converting each actual in actuals to a parameter
2091 // type before invoking prototype->ValidateCall. This is the wrong behavior for
2092 // FFIs (we need to pass Signed integers to FFIs, not Ints), so that case is
2093 // handled separately.
2094 bool CheckInvocationOf(AsmCallableType* prototype, AsmType* return_type,
2095 ZoneVector<AsmType*>* actuals) {
2096 if (auto* ffi = prototype->AsFFIType()) {
2097 return ffi->ValidateCall(return_type, *actuals) != AsmType::None();
2098 }
2099
2100 for (size_t ii = 0; ii < actuals->size(); ++ii) {
2101 (*actuals)[ii] = (*actuals)[ii]->ToParameterType();
2102 }
2103 return prototype->ValidateCall(return_type, *actuals) != AsmType::None();
2104 }
2105
2106 } // namespace 2136 } // namespace
2107 2137
2108 AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) { 2138 AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) {
2109 AsmType* float_coercion_type; 2139 AsmType* float_coercion_type;
2110 RECURSE(float_coercion_type = ValidateFloatCoercion(call)); 2140 RECURSE(float_coercion_type = ValidateFloatCoercion(call));
2111 if (float_coercion_type == AsmType::Float()) { 2141 if (float_coercion_type == AsmType::Float()) {
2112 return AsmType::Float(); 2142 SetTypeOf(call, AsmType::Float());
2143 return return_type;
2113 } 2144 }
2114 2145
2115 // TODO(jpp): we should be able to reuse the args vector's storage space. 2146 // TODO(jpp): we should be able to reuse the args vector's storage space.
2116 ZoneVector<AsmType*> args(zone_); 2147 ZoneVector<AsmType*> args(zone_);
2117 args.reserve(call->arguments()->length()); 2148 args.reserve(call->arguments()->length());
2118 2149
2119 for (auto* arg : *call->arguments()) { 2150 for (auto* arg : *call->arguments()) {
2120 AsmType* arg_type; 2151 AsmType* arg_type;
2121 RECURSE(arg_type = ValidateExpression(arg)); 2152 RECURSE(arg_type = ValidateExpression(arg));
2122 args.emplace_back(arg_type); 2153 args.emplace_back(arg_type);
(...skipping 18 matching lines...) Expand all
2141 fun_info->set_mutability(VariableInfo::kImmutableGlobal); 2172 fun_info->set_mutability(VariableInfo::kImmutableGlobal);
2142 AddForwardReference(call_var_proxy, fun_info); 2173 AddForwardReference(call_var_proxy, fun_info);
2143 if (!ValidAsmIdentifier(call_var_proxy->name())) { 2174 if (!ValidAsmIdentifier(call_var_proxy->name())) {
2144 FAIL(call_var_proxy, 2175 FAIL(call_var_proxy,
2145 "Invalid asm.js identifier in (forward) function name."); 2176 "Invalid asm.js identifier in (forward) function name.");
2146 } 2177 }
2147 if (!AddGlobal(call_var_proxy->var(), fun_info)) { 2178 if (!AddGlobal(call_var_proxy->var(), fun_info)) {
2148 DCHECK(false); 2179 DCHECK(false);
2149 FAIL(call, "Redeclared global identifier."); 2180 FAIL(call, "Redeclared global identifier.");
2150 } 2181 }
2182 SetTypeOf(call_var_proxy, reinterpret_cast<AsmType*>(call_type));
2183 SetTypeOf(call, return_type);
2151 return return_type; 2184 return return_type;
2152 } 2185 }
2153 2186
2154 auto* callee_type = call_var_info->type()->AsCallableType(); 2187 auto* callee_type = call_var_info->type()->AsCallableType();
2155 if (callee_type == nullptr) { 2188 if (callee_type == nullptr) {
2156 FAIL(call, "Calling something that's not a function."); 2189 FAIL(call, "Calling something that's not a function.");
2157 } 2190 }
2158 2191
2159 if (callee_type->AsFFIType() != nullptr && 2192 if (callee_type->AsFFIType() != nullptr &&
2160 return_type == AsmType::Float()) { 2193 return_type == AsmType::Float()) {
2161 FAIL(call, "Foreign functions can't return float."); 2194 FAIL(call, "Foreign functions can't return float.");
2162 } 2195 }
2163 2196
2164 if (!CheckInvocationOf(callee_type, return_type, &args)) { 2197 if (!callee_type->CanBeInvokedWith(return_type, args)) {
2165 FAIL(call, "Function invocation does not match function type."); 2198 FAIL(call, "Function invocation does not match function type.");
2166 } 2199 }
2167 2200
2201 SetTypeOf(call_var_proxy, call_var_info->type());
2202 SetTypeOf(call, return_type);
2168 return return_type; 2203 return return_type;
2169 } 2204 }
2170 2205
2171 // identifier[expr & n](Expression...) 2206 // identifier[expr & n](Expression...)
2172 if (auto* call_property = call_expr->AsProperty()) { 2207 if (auto* call_property = call_expr->AsProperty()) {
2173 auto* index = call_property->key()->AsBinaryOperation(); 2208 auto* index = call_property->key()->AsBinaryOperation();
2174 if (index == nullptr || index->op() != Token::BIT_AND) { 2209 if (index == nullptr || index->op() != Token::BIT_AND) {
2175 FAIL(call_property->key(), 2210 FAIL(call_property->key(),
2176 "Indirect call index must be in the expr & mask form."); 2211 "Indirect call index must be in the expr & mask form.");
2177 } 2212 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2214 fun_info->set_mutability(VariableInfo::kImmutableGlobal); 2249 fun_info->set_mutability(VariableInfo::kImmutableGlobal);
2215 AddForwardReference(name_var, fun_info); 2250 AddForwardReference(name_var, fun_info);
2216 if (!ValidAsmIdentifier(name_var->name())) { 2251 if (!ValidAsmIdentifier(name_var->name())) {
2217 FAIL(name_var, 2252 FAIL(name_var,
2218 "Invalid asm.js identifier in (forward) function table name."); 2253 "Invalid asm.js identifier in (forward) function table name.");
2219 } 2254 }
2220 if (!AddGlobal(name_var->var(), fun_info)) { 2255 if (!AddGlobal(name_var->var(), fun_info)) {
2221 DCHECK(false); 2256 DCHECK(false);
2222 FAIL(call, "Redeclared global identifier."); 2257 FAIL(call, "Redeclared global identifier.");
2223 } 2258 }
2259 SetTypeOf(call_property, reinterpret_cast<AsmType*>(call_type));
2260 SetTypeOf(call, return_type);
2224 return return_type; 2261 return return_type;
2225 } 2262 }
2226 2263
2227 auto* previous_type = name_info->type()->AsFunctionTableType(); 2264 auto* previous_type = name_info->type()->AsFunctionTableType();
2228 if (previous_type == nullptr) { 2265 if (previous_type == nullptr) {
2229 FAIL(call, "Identifier does not name a function table."); 2266 FAIL(call, "Identifier does not name a function table.");
2230 } 2267 }
2231 2268
2232 if (table_length != previous_type->length()) { 2269 if (table_length != previous_type->length()) {
2233 FAIL(call, "Function table size does not match expected size."); 2270 FAIL(call, "Function table size does not match expected size.");
2234 } 2271 }
2235 2272
2236 auto* previous_type_signature = 2273 auto* previous_type_signature =
2237 previous_type->signature()->AsFunctionType(); 2274 previous_type->signature()->AsFunctionType();
2238 DCHECK(previous_type_signature != nullptr); 2275 DCHECK(previous_type_signature != nullptr);
2239 if (!CheckInvocationOf(previous_type_signature, return_type, &args)) { 2276 if (!previous_type_signature->CanBeInvokedWith(return_type, args)) {
2277 // TODO(jpp): better error messages.
2240 FAIL(call, 2278 FAIL(call,
2241 "Function pointer table signature does not match previous " 2279 "Function pointer table signature does not match previous "
2242 "signature."); 2280 "signature.");
2243 } 2281 }
2244 2282
2283 SetTypeOf(call_property, previous_type->signature());
2284 SetTypeOf(call, return_type);
2245 return return_type; 2285 return return_type;
2246 } 2286 }
2247 2287
2248 FAIL(call, "Invalid call."); 2288 FAIL(call, "Invalid call.");
2249 } 2289 }
2250 2290
2251 // 6.10 ValidateHeapAccess 2291 // 6.10 ValidateHeapAccess
2252 namespace { 2292 namespace {
2253 bool ExtractHeapAccessShift(Expression* expr, uint32_t* value) { 2293 bool ExtractHeapAccessShift(Expression* expr, uint32_t* value) {
2254 auto* as_literal = expr->AsLiteral(); 2294 auto* as_literal = expr->AsLiteral();
(...skipping 18 matching lines...) Expand all
2273 2313
2274 auto* obj_info = Lookup(obj->var()); 2314 auto* obj_info = Lookup(obj->var());
2275 if (obj_info == nullptr) { 2315 if (obj_info == nullptr) {
2276 FAIL(heap, "Undeclared identifier in heap access."); 2316 FAIL(heap, "Undeclared identifier in heap access.");
2277 } 2317 }
2278 2318
2279 auto* obj_type = obj_info->type(); 2319 auto* obj_type = obj_info->type();
2280 if (!obj_type->IsA(AsmType::Heap())) { 2320 if (!obj_type->IsA(AsmType::Heap())) {
2281 FAIL(heap, "Identifier does not represent a heap view."); 2321 FAIL(heap, "Identifier does not represent a heap view.");
2282 } 2322 }
2323 SetTypeOf(obj, obj_type);
2283 2324
2284 if (auto* key_as_literal = heap->key()->AsLiteral()) { 2325 if (auto* key_as_literal = heap->key()->AsLiteral()) {
2285 if (key_as_literal->raw_value()->ContainsDot()) { 2326 if (key_as_literal->raw_value()->ContainsDot()) {
2286 FAIL(key_as_literal, "Heap access index must be intish."); 2327 FAIL(key_as_literal, "Heap access index must be intish.");
2287 } 2328 }
2288 2329
2289 uint32_t _; 2330 uint32_t _;
2290 if (!key_as_literal->value()->ToUint32(&_)) { 2331 if (!key_as_literal->value()->ToUint32(&_)) {
2291 FAIL(key_as_literal, 2332 FAIL(key_as_literal,
2292 "Heap access index must be a 32-bit unsigned integer."); 2333 "Heap access index must be a 32-bit unsigned integer.");
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
2364 if (auto* arg_as_call = arg->AsCall()) { 2405 if (auto* arg_as_call = arg->AsCall()) {
2365 RECURSE(ValidateCall(AsmType::Float(), arg_as_call)); 2406 RECURSE(ValidateCall(AsmType::Float(), arg_as_call));
2366 return AsmType::Float(); 2407 return AsmType::Float();
2367 } 2408 }
2368 2409
2369 // 2. fround is used for converting to float. 2410 // 2. fround is used for converting to float.
2370 AsmType* arg_type; 2411 AsmType* arg_type;
2371 RECURSE(arg_type = ValidateExpression(arg)); 2412 RECURSE(arg_type = ValidateExpression(arg));
2372 if (arg_type->IsA(AsmType::Floatish()) || arg_type->IsA(AsmType::DoubleQ()) || 2413 if (arg_type->IsA(AsmType::Floatish()) || arg_type->IsA(AsmType::DoubleQ()) ||
2373 arg_type->IsA(AsmType::Signed()) || arg_type->IsA(AsmType::Unsigned())) { 2414 arg_type->IsA(AsmType::Signed()) || arg_type->IsA(AsmType::Unsigned())) {
2415 SetTypeOf(call->expression(), fround_type_);
2374 return AsmType::Float(); 2416 return AsmType::Float();
2375 } 2417 }
2376 2418
2377 FAIL(call, "Invalid argument type to fround."); 2419 FAIL(call, "Invalid argument type to fround.");
2378 } 2420 }
2379 2421
2380 // 5.1 ParameterTypeAnnotations 2422 // 5.1 ParameterTypeAnnotations
2381 AsmType* AsmTyper::ParameterTypeAnnotations(Variable* parameter, 2423 AsmType* AsmTyper::ParameterTypeAnnotations(Variable* parameter,
2382 Expression* annotation) { 2424 Expression* annotation) {
2383 if (auto* binop = annotation->AsBinaryOperation()) { 2425 if (auto* binop = annotation->AsBinaryOperation()) {
2384 // Must be: 2426 // Must be:
2385 // * x|0 2427 // * x|0
2386 // * x*1 (*VIOLATION* i.e.,, +x) 2428 // * x*1 (*VIOLATION* i.e.,, +x)
2387 auto* left = binop->left()->AsVariableProxy(); 2429 auto* left = binop->left()->AsVariableProxy();
2388 if (left == nullptr) { 2430 if (left == nullptr) {
2389 FAIL( 2431 FAIL(
2390 binop->left(), 2432 binop->left(),
2391 "Invalid parameter type annotation - should annotate an identifier."); 2433 "Invalid parameter type annotation - should annotate an identifier.");
2392 } 2434 }
2393 if (left->var() != parameter) { 2435 if (left->var() != parameter) {
2394 FAIL(binop->left(), 2436 FAIL(binop->left(),
2395 "Invalid parameter type annotation - should annotate a parameter."); 2437 "Invalid parameter type annotation - should annotate a parameter.");
2396 } 2438 }
2397 if (IsDoubleAnnotation(binop)) { 2439 if (IsDoubleAnnotation(binop)) {
2440 SetTypeOf(left, AsmType::Double());
2398 return AsmType::Double(); 2441 return AsmType::Double();
2399 } 2442 }
2400 if (IsIntAnnotation(binop)) { 2443 if (IsIntAnnotation(binop)) {
2444 SetTypeOf(left, AsmType::Int());
2401 return AsmType::Int(); 2445 return AsmType::Int();
2402 } 2446 }
2403 FAIL(binop, "Invalid parameter type annotation."); 2447 FAIL(binop, "Invalid parameter type annotation.");
2404 } 2448 }
2405 2449
2406 auto* call = annotation->AsCall(); 2450 auto* call = annotation->AsCall();
2407 if (call == nullptr) { 2451 if (call == nullptr) {
2408 FAIL( 2452 FAIL(
2409 annotation, 2453 annotation,
2410 "Invalid float parameter type annotation - must be fround(parameter)."); 2454 "Invalid float parameter type annotation - must be fround(parameter).");
(...skipping 10 matching lines...) Expand all
2421 "Invalid float parameter type annotation - argument to fround is not " 2465 "Invalid float parameter type annotation - argument to fround is not "
2422 "an identifier."); 2466 "an identifier.");
2423 } 2467 }
2424 2468
2425 if (src_expr->var() != parameter) { 2469 if (src_expr->var() != parameter) {
2426 FAIL(annotation, 2470 FAIL(annotation,
2427 "Invalid float parameter type annotation - argument to fround is not " 2471 "Invalid float parameter type annotation - argument to fround is not "
2428 "a parameter."); 2472 "a parameter.");
2429 } 2473 }
2430 2474
2475 SetTypeOf(src_expr, AsmType::Float());
2431 return AsmType::Float(); 2476 return AsmType::Float();
2432 } 2477 }
2433 2478
2434 // 5.2 ReturnTypeAnnotations 2479 // 5.2 ReturnTypeAnnotations
2435 AsmType* AsmTyper::ReturnTypeAnnotations(ReturnStatement* statement) { 2480 AsmType* AsmTyper::ReturnTypeAnnotations(ReturnStatement* statement) {
2436 if (statement == nullptr) { 2481 if (statement == nullptr) {
2437 return AsmType::Void(); 2482 return AsmType::Void();
2438 } 2483 }
2439 2484
2440 auto* ret_expr = statement->expression(); 2485 auto* ret_expr = statement->expression();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2478 } 2523 }
2479 2524
2480 FAIL(statement, "Invalid return type expression."); 2525 FAIL(statement, "Invalid return type expression.");
2481 } 2526 }
2482 2527
2483 // 5.4 VariableTypeAnnotations 2528 // 5.4 VariableTypeAnnotations
2484 // Also used for 5.5 GlobalVariableTypeAnnotations 2529 // Also used for 5.5 GlobalVariableTypeAnnotations
2485 AsmType* AsmTyper::VariableTypeAnnotations(Expression* initializer) { 2530 AsmType* AsmTyper::VariableTypeAnnotations(Expression* initializer) {
2486 if (auto* literal = initializer->AsLiteral()) { 2531 if (auto* literal = initializer->AsLiteral()) {
2487 if (literal->raw_value()->ContainsDot()) { 2532 if (literal->raw_value()->ContainsDot()) {
2533 SetTypeOf(initializer, AsmType::Double());
2488 return AsmType::Double(); 2534 return AsmType::Double();
2489 } 2535 }
2490 int32_t i32; 2536 int32_t i32;
2491 uint32_t u32; 2537 uint32_t u32;
2492 if (literal->value()->ToInt32(&i32) || literal->value()->ToUint32(&u32)) { 2538 if (literal->value()->ToUint32(&u32)) {
2493 return AsmType::Int(); 2539 if (u32 > LargestFixNum) {
2540 SetTypeOf(initializer, AsmType::Unsigned());
2541 } else {
2542 SetTypeOf(initializer, AsmType::FixNum());
2543 }
2544 } else if (literal->value()->ToInt32(&i32)) {
2545 SetTypeOf(initializer, AsmType::Signed());
2546 } else {
2547 FAIL(initializer, "Invalid type annotation - forbidden literal.");
2494 } 2548 }
2495 FAIL(initializer, "Invalid type annotation - forbidden literal."); 2549 return AsmType::Int();
2496 } 2550 }
2497 2551
2498 auto* call = initializer->AsCall(); 2552 auto* call = initializer->AsCall();
2499 DCHECK(call != nullptr);
2500 if (call == nullptr) { 2553 if (call == nullptr) {
2501 FAIL(initializer, 2554 FAIL(initializer,
2502 "Invalid variable initialization - it should be a literal, or " 2555 "Invalid variable initialization - it should be a literal, or "
2503 "fround(literal)."); 2556 "fround(literal).");
2504 } 2557 }
2505 2558
2506 if (!IsCallToFround(call)) { 2559 if (!IsCallToFround(call)) {
2507 FAIL(initializer, 2560 FAIL(initializer,
2508 "Invalid float coercion - expected call fround(literal)."); 2561 "Invalid float coercion - expected call fround(literal).");
2509 } 2562 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2576 return true; 2629 return true;
2577 } 2630 }
2578 2631
2579 *error_message = typer.error_message(); 2632 *error_message = typer.error_message();
2580 return false; 2633 return false;
2581 } 2634 }
2582 2635
2583 } // namespace wasm 2636 } // namespace wasm
2584 } // namespace internal 2637 } // namespace internal
2585 } // namespace v8 2638 } // namespace v8
OLDNEW
« no previous file with comments | « src/asmjs/asm-typer.h ('k') | src/asmjs/asm-types.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698