OLD | NEW |
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 793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
804 CHECK(value != nullptr); | 804 CHECK(value != nullptr); |
805 ZoneList<Expression*>* pointers = value->values(); | 805 ZoneList<Expression*>* pointers = value->values(); |
806 | 806 |
807 // The function table size must be n = 2 ** m, for m >= 0; | 807 // The function table size must be n = 2 ** m, for m >= 0; |
808 // TODO(jpp): should this be capped? | 808 // TODO(jpp): should this be capped? |
809 if (!base::bits::IsPowerOfTwo32(pointers->length())) { | 809 if (!base::bits::IsPowerOfTwo32(pointers->length())) { |
810 FAIL(assign, "Invalid length for function pointer table."); | 810 FAIL(assign, "Invalid length for function pointer table."); |
811 } | 811 } |
812 | 812 |
813 AsmType* table_element_type = nullptr; | 813 AsmType* table_element_type = nullptr; |
814 AsmCallableType* callable_type = nullptr; | |
815 for (auto* initializer : *pointers) { | 814 for (auto* initializer : *pointers) { |
816 auto* var_proxy = initializer->AsVariableProxy(); | 815 auto* var_proxy = initializer->AsVariableProxy(); |
817 if (var_proxy == nullptr) { | 816 if (var_proxy == nullptr) { |
818 FAIL(initializer, | 817 FAIL(initializer, |
819 "Function pointer table initializer must be a function name."); | 818 "Function pointer table initializer must be a function name."); |
820 } | 819 } |
821 | 820 |
822 auto* var_info = Lookup(var_proxy->var()); | 821 auto* var_info = Lookup(var_proxy->var()); |
823 if (var_info == nullptr) { | 822 if (var_info == nullptr) { |
824 FAIL(var_proxy, | 823 FAIL(var_proxy, |
825 "Undefined identifier in function pointer table initializer."); | 824 "Undefined identifier in function pointer table initializer."); |
826 } | 825 } |
827 | 826 |
828 if (var_info->standard_member() != kNone) { | 827 if (var_info->standard_member() != kNone) { |
829 FAIL(initializer, | 828 FAIL(initializer, |
830 "Function pointer table must not be a member of the standard " | 829 "Function pointer table must not be a member of the standard " |
831 "library."); | 830 "library."); |
832 } | 831 } |
833 | 832 |
834 auto* initializer_callable = var_info->type()->AsFunctionType(); | 833 auto* initializer_type = var_info->type(); |
835 if (initializer_callable == nullptr) { | 834 if (initializer_type->AsFunctionType() == nullptr) { |
836 FAIL(initializer, | 835 FAIL(initializer, |
837 "Function pointer table initializer must be an asm.js function."); | 836 "Function pointer table initializer must be an asm.js function."); |
838 } | 837 } |
839 | 838 |
840 DCHECK(var_info->type()->AsFFIType() == nullptr); | 839 DCHECK(var_info->type()->AsFFIType() == nullptr); |
841 DCHECK(var_info->type()->AsFunctionTableType() == nullptr); | 840 DCHECK(var_info->type()->AsFunctionTableType() == nullptr); |
842 | 841 |
843 if (callable_type == nullptr) { | 842 if (table_element_type == nullptr) { |
844 table_element_type = var_info->type(); | 843 table_element_type = initializer_type; |
845 callable_type = initializer_callable; | 844 } else if (!initializer_type->IsA(table_element_type)) { |
846 } else if (callable_type->ValidateCall(initializer_callable->ReturnType(), | |
847 initializer_callable->Arguments()) == | |
848 AsmType::None()) { | |
849 FAIL(initializer, "Type mismatch in function pointer table initializer."); | 845 FAIL(initializer, "Type mismatch in function pointer table initializer."); |
850 } | 846 } |
851 } | 847 } |
852 | 848 |
853 auto* target_info = Lookup(target_variable); | 849 auto* target_info = Lookup(target_variable); |
854 if (target_info == nullptr) { | 850 if (target_info == nullptr) { |
855 // Function pointer tables are the last entities to be validates, so this is | 851 // Function pointer tables are the last entities to be validates, so this is |
856 // unlikely to happen: only unreferenced function tables will not already | 852 // unlikely to happen: only unreferenced function tables will not already |
857 // have an entry in the global scope. | 853 // have an entry in the global scope. |
858 target_info = new (zone_) VariableInfo(AsmType::FunctionTableType( | 854 target_info = new (zone_) VariableInfo(AsmType::FunctionTableType( |
(...skipping 16 matching lines...) Expand all Loading... |
875 } | 871 } |
876 | 872 |
877 if (!target_info->missing_definition()) { | 873 if (!target_info->missing_definition()) { |
878 FAIL(assign, "Identifier redefined (function table name)."); | 874 FAIL(assign, "Identifier redefined (function table name)."); |
879 } | 875 } |
880 | 876 |
881 if (target_info_table->length() != pointers->length()) { | 877 if (target_info_table->length() != pointers->length()) { |
882 FAIL(assign, "Function table size mismatch."); | 878 FAIL(assign, "Function table size mismatch."); |
883 } | 879 } |
884 | 880 |
885 auto* function_type = callable_type->AsFunctionType(); | 881 DCHECK(target_info_table->signature()->AsFunctionType()); |
886 if (target_info_table->ValidateCall(function_type->ReturnType(), | 882 if (!table_element_type->IsA(target_info_table->signature())) { |
887 function_type->Arguments()) == | |
888 AsmType::None()) { | |
889 FAIL(assign, "Function table initializer does not match previous type."); | 883 FAIL(assign, "Function table initializer does not match previous type."); |
890 } | 884 } |
891 | 885 |
892 target_info->MarkDefined(); | 886 target_info->MarkDefined(); |
893 DCHECK(target_info->type() != AsmType::None()); | 887 DCHECK(target_info->type() != AsmType::None()); |
894 SetTypeOf(value, target_info->type()); | 888 SetTypeOf(value, target_info->type()); |
895 | 889 |
896 return target_info->type(); | 890 return target_info->type(); |
897 } | 891 } |
898 | 892 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1043 | 1037 |
1044 auto* fun_type = AsmType::Function(zone_, return_type_); | 1038 auto* fun_type = AsmType::Function(zone_, return_type_); |
1045 auto* fun_type_as_function = fun_type->AsFunctionType(); | 1039 auto* fun_type_as_function = fun_type->AsFunctionType(); |
1046 for (auto* param_type : parameter_types) { | 1040 for (auto* param_type : parameter_types) { |
1047 fun_type_as_function->AddArgument(param_type); | 1041 fun_type_as_function->AddArgument(param_type); |
1048 } | 1042 } |
1049 | 1043 |
1050 auto* fun_var = fun_decl_proxy->var(); | 1044 auto* fun_var = fun_decl_proxy->var(); |
1051 auto* fun_info = new (zone_) VariableInfo(fun_type); | 1045 auto* fun_info = new (zone_) VariableInfo(fun_type); |
1052 fun_info->set_mutability(VariableInfo::kImmutableGlobal); | 1046 fun_info->set_mutability(VariableInfo::kImmutableGlobal); |
1053 auto* old_fun_type = Lookup(fun_var); | 1047 auto* old_fun_info = Lookup(fun_var); |
1054 if (old_fun_type == nullptr) { | 1048 if (old_fun_info == nullptr) { |
1055 if (!ValidAsmIdentifier(fun_var->name())) { | 1049 if (!ValidAsmIdentifier(fun_var->name())) { |
1056 FAIL(fun_decl_proxy, "Invalid asm.js identifier in function name."); | 1050 FAIL(fun_decl_proxy, "Invalid asm.js identifier in function name."); |
1057 } | 1051 } |
1058 if (!AddGlobal(fun_var, fun_info)) { | 1052 if (!AddGlobal(fun_var, fun_info)) { |
1059 DCHECK(false); | 1053 DCHECK(false); |
1060 FAIL(fun_decl, "Redeclared global identifier."); | 1054 FAIL(fun_decl, "Redeclared global identifier."); |
1061 } | 1055 } |
1062 | 1056 |
1063 SetTypeOf(fun, fun_type); | 1057 SetTypeOf(fun, fun_type); |
1064 return fun_type; | 1058 return fun_type; |
1065 } | 1059 } |
1066 | 1060 |
1067 // Not necessarily an error -- fun_decl might have been used before being | 1061 // Not necessarily an error -- fun_decl might have been used before being |
1068 // defined. If that's the case, then the type in the global environment must | 1062 // defined. If that's the case, then the type in the global environment must |
1069 // be the same as the type inferred by the parameter/return type annotations. | 1063 // be the same as the type inferred by the parameter/return type annotations. |
1070 auto* old_fun_callable = old_fun_type->type()->AsCallableType(); | 1064 auto* old_fun_type = old_fun_info->type(); |
1071 if (old_fun_callable == nullptr) { | 1065 if (old_fun_type->AsFunctionType() == nullptr) { |
1072 FAIL(fun_decl, "Identifier redefined as function."); | 1066 FAIL(fun_decl, "Identifier redefined as function."); |
1073 } | 1067 } |
1074 | 1068 |
1075 if (!old_fun_type->missing_definition()) { | 1069 if (!old_fun_info->missing_definition()) { |
1076 FAIL(fun_decl, "Identifier redefined (function name)."); | 1070 FAIL(fun_decl, "Identifier redefined (function name)."); |
1077 } | 1071 } |
1078 | 1072 |
1079 if (old_fun_callable->ValidateCall(fun_type_as_function->ReturnType(), | 1073 if (!fun_type->IsA(old_fun_type)) { |
1080 fun_type_as_function->Arguments()) == | |
1081 AsmType::None()) { | |
1082 FAIL(fun_decl, "Signature mismatch when defining function."); | 1074 FAIL(fun_decl, "Signature mismatch when defining function."); |
1083 } | 1075 } |
1084 | 1076 |
1085 old_fun_type->MarkDefined(); | 1077 old_fun_info->MarkDefined(); |
1086 SetTypeOf(fun, fun_type); | 1078 SetTypeOf(fun, fun_type); |
1087 | 1079 |
1088 return fun_type; | 1080 return fun_type; |
1089 } | 1081 } |
1090 | 1082 |
1091 // 6.5 ValidateStatement | 1083 // 6.5 ValidateStatement |
1092 AsmType* AsmTyper::ValidateStatement(Statement* statement) { | 1084 AsmType* AsmTyper::ValidateStatement(Statement* statement) { |
1093 switch (statement->node_type()) { | 1085 switch (statement->node_type()) { |
1094 default: | 1086 default: |
1095 FAIL(statement, "Statement type invalid for asm.js."); | 1087 FAIL(statement, "Statement type invalid for asm.js."); |
(...skipping 1533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2629 return true; | 2621 return true; |
2630 } | 2622 } |
2631 | 2623 |
2632 *error_message = typer.error_message(); | 2624 *error_message = typer.error_message(); |
2633 return false; | 2625 return false; |
2634 } | 2626 } |
2635 | 2627 |
2636 } // namespace wasm | 2628 } // namespace wasm |
2637 } // namespace internal | 2629 } // namespace internal |
2638 } // namespace v8 | 2630 } // namespace v8 |
OLD | NEW |