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 <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <memory> | 9 #include <memory> |
10 #include <string> | 10 #include <string> |
(...skipping 1207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1218 | 1218 |
1219 do { | 1219 do { |
1220 if (statements->length() == 0) { | 1220 if (statements->length() == 0) { |
1221 return_type_ = AsmType::Void(); | 1221 return_type_ = AsmType::Void(); |
1222 } else { | 1222 } else { |
1223 auto* last_statement = statements->last(); | 1223 auto* last_statement = statements->last(); |
1224 auto* as_block = last_statement->AsBlock(); | 1224 auto* as_block = last_statement->AsBlock(); |
1225 if (as_block != nullptr) { | 1225 if (as_block != nullptr) { |
1226 statements = as_block->statements(); | 1226 statements = as_block->statements(); |
1227 } else { | 1227 } else { |
1228 // We don't check whether AsReturnStatement() below returns non-null -- | 1228 if (auto* ret_statement = last_statement->AsReturnStatement()) { |
1229 // we leave that to the ReturnTypeAnnotations method. | 1229 RECURSE(return_type_ = |
1230 RECURSE(return_type_ = | 1230 ReturnTypeAnnotations(ret_statement->expression())); |
1231 ReturnTypeAnnotations(last_statement->AsReturnStatement())); | 1231 } else { |
| 1232 return_type_ = AsmType::Void(); |
| 1233 } |
1232 } | 1234 } |
1233 } | 1235 } |
1234 } while (return_type_ == AsmType::None()); | 1236 } while (return_type_ == AsmType::None()); |
1235 | 1237 |
1236 DCHECK(return_type_->IsReturnType()); | 1238 DCHECK(return_type_->IsReturnType()); |
1237 | 1239 |
1238 for (Declaration* decl : *fun->scope()->declarations()) { | 1240 for (Declaration* decl : *fun->scope()->declarations()) { |
1239 auto* var_decl = decl->AsVariableDeclaration(); | 1241 auto* var_decl = decl->AsVariableDeclaration(); |
1240 if (var_decl == nullptr) { | 1242 if (var_decl == nullptr) { |
1241 FAIL(decl, "Functions may only define inner variables."); | 1243 FAIL(decl, "Functions may only define inner variables."); |
(...skipping 1498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2740 FAIL(annotation, | 2742 FAIL(annotation, |
2741 "Invalid float parameter type annotation - argument to fround is not " | 2743 "Invalid float parameter type annotation - argument to fround is not " |
2742 "a parameter."); | 2744 "a parameter."); |
2743 } | 2745 } |
2744 | 2746 |
2745 SetTypeOf(src_expr, AsmType::Float()); | 2747 SetTypeOf(src_expr, AsmType::Float()); |
2746 return AsmType::Float(); | 2748 return AsmType::Float(); |
2747 } | 2749 } |
2748 | 2750 |
2749 // 5.2 ReturnTypeAnnotations | 2751 // 5.2 ReturnTypeAnnotations |
2750 AsmType* AsmTyper::ReturnTypeAnnotations(ReturnStatement* statement) { | 2752 AsmType* AsmTyper::ReturnTypeAnnotations(Expression* ret_expr) { |
2751 if (statement == nullptr) { | 2753 DCHECK_NOT_NULL(ret_expr); |
2752 return AsmType::Void(); | |
2753 } | |
2754 | |
2755 auto* ret_expr = statement->expression(); | |
2756 if (ret_expr == nullptr) { | |
2757 return AsmType::Void(); | |
2758 } | |
2759 | 2754 |
2760 if (auto* binop = ret_expr->AsBinaryOperation()) { | 2755 if (auto* binop = ret_expr->AsBinaryOperation()) { |
2761 if (IsDoubleAnnotation(binop)) { | 2756 if (IsDoubleAnnotation(binop)) { |
2762 return AsmType::Double(); | 2757 return AsmType::Double(); |
2763 } else if (IsIntAnnotation(binop)) { | 2758 } else if (IsIntAnnotation(binop)) { |
2764 return AsmType::Signed(); | 2759 return AsmType::Signed(); |
2765 } | 2760 } |
2766 FAIL(statement, "Invalid return type annotation."); | 2761 FAIL(ret_expr, "Invalid return type annotation."); |
2767 } | 2762 } |
2768 | 2763 |
2769 if (auto* call = ret_expr->AsCall()) { | 2764 if (auto* call = ret_expr->AsCall()) { |
2770 if (IsCallToFround(call)) { | 2765 if (IsCallToFround(call)) { |
2771 return AsmType::Float(); | 2766 return AsmType::Float(); |
2772 } | 2767 } |
2773 FAIL(statement, "Invalid function call in return statement."); | 2768 FAIL(ret_expr, "Invalid function call in return statement."); |
2774 } | 2769 } |
2775 | 2770 |
2776 if (auto* literal = ret_expr->AsLiteral()) { | 2771 if (auto* literal = ret_expr->AsLiteral()) { |
2777 int32_t _; | 2772 int32_t _; |
2778 if (IsLiteralDouble(literal)) { | 2773 if (IsLiteralDouble(literal)) { |
2779 return AsmType::Double(); | 2774 return AsmType::Double(); |
2780 } else if (IsLiteralInt(literal) && literal->value()->ToInt32(&_)) { | 2775 } else if (IsLiteralInt(literal) && literal->value()->ToInt32(&_)) { |
2781 return AsmType::Signed(); | 2776 return AsmType::Signed(); |
2782 } else if (literal->IsUndefinedLiteral()) { | 2777 } else if (literal->IsUndefinedLiteral()) { |
2783 // *VIOLATION* The parser changes | 2778 // *VIOLATION* The parser changes |
2784 // | 2779 // |
2785 // return; | 2780 // return; |
2786 // | 2781 // |
2787 // into | 2782 // into |
2788 // | 2783 // |
2789 // return undefined | 2784 // return undefined |
2790 return AsmType::Void(); | 2785 return AsmType::Void(); |
2791 } | 2786 } |
2792 FAIL(statement, "Invalid literal in return statement."); | 2787 FAIL(ret_expr, "Invalid literal in return statement."); |
2793 } | 2788 } |
2794 | 2789 |
2795 if (auto* proxy = ret_expr->AsVariableProxy()) { | 2790 if (auto* proxy = ret_expr->AsVariableProxy()) { |
2796 auto* var_info = Lookup(proxy->var()); | 2791 auto* var_info = Lookup(proxy->var()); |
2797 | 2792 |
2798 if (var_info == nullptr) { | 2793 if (var_info == nullptr) { |
2799 FAIL(statement, "Undeclared identifier in return statement."); | 2794 FAIL(ret_expr, "Undeclared identifier in return statement."); |
2800 } | 2795 } |
2801 | 2796 |
2802 if (var_info->mutability() != VariableInfo::kConstGlobal) { | 2797 if (var_info->mutability() != VariableInfo::kConstGlobal) { |
2803 FAIL(statement, "Identifier in return statement is not const."); | 2798 FAIL(ret_expr, "Identifier in return statement is not const."); |
2804 } | 2799 } |
2805 | 2800 |
2806 if (!var_info->type()->IsReturnType()) { | 2801 if (!var_info->type()->IsReturnType()) { |
2807 FAIL(statement, "Constant in return must be signed, float, or double."); | 2802 FAIL(ret_expr, "Constant in return must be signed, float, or double."); |
2808 } | 2803 } |
2809 | 2804 |
2810 return var_info->type(); | 2805 return var_info->type(); |
2811 } | 2806 } |
2812 | 2807 |
2813 FAIL(statement, "Invalid return type expression."); | 2808 // NOTE: This is not strictly valid asm.js, but is emitted by some versions of |
| 2809 // Emscripten. |
| 2810 if (auto* cond = ret_expr->AsConditional()) { |
| 2811 AsmType* a = AsmType::None(); |
| 2812 AsmType* b = AsmType::None(); |
| 2813 RECURSE(a = ReturnTypeAnnotations(cond->then_expression())); |
| 2814 if (a->IsA(AsmType::None())) { |
| 2815 return a; |
| 2816 } |
| 2817 RECURSE(b = ReturnTypeAnnotations(cond->else_expression())); |
| 2818 if (b->IsA(AsmType::None())) { |
| 2819 return b; |
| 2820 } |
| 2821 if (a->IsExactly(b)) { |
| 2822 return a; |
| 2823 } |
| 2824 } |
| 2825 |
| 2826 FAIL(ret_expr, "Invalid return type expression."); |
2814 } | 2827 } |
2815 | 2828 |
2816 // 5.4 VariableTypeAnnotations | 2829 // 5.4 VariableTypeAnnotations |
2817 // Also used for 5.5 GlobalVariableTypeAnnotations | 2830 // Also used for 5.5 GlobalVariableTypeAnnotations |
2818 AsmType* AsmTyper::VariableTypeAnnotations( | 2831 AsmType* AsmTyper::VariableTypeAnnotations( |
2819 Expression* initializer, VariableInfo::Mutability mutability_type) { | 2832 Expression* initializer, VariableInfo::Mutability mutability_type) { |
2820 if (auto* literal = initializer->AsLiteral()) { | 2833 if (auto* literal = initializer->AsLiteral()) { |
2821 if (IsLiteralDouble(literal)) { | 2834 if (IsLiteralDouble(literal)) { |
2822 SetTypeOf(initializer, AsmType::Double()); | 2835 SetTypeOf(initializer, AsmType::Double()); |
2823 return AsmType::Double(); | 2836 return AsmType::Double(); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2940 "Heap view creation parameter should be the module's heap parameter."); | 2953 "Heap view creation parameter should be the module's heap parameter."); |
2941 } | 2954 } |
2942 | 2955 |
2943 DCHECK(heap_view_info->type()->IsA(AsmType::Heap())); | 2956 DCHECK(heap_view_info->type()->IsA(AsmType::Heap())); |
2944 return heap_view_info->type(); | 2957 return heap_view_info->type(); |
2945 } | 2958 } |
2946 | 2959 |
2947 } // namespace wasm | 2960 } // namespace wasm |
2948 } // namespace internal | 2961 } // namespace internal |
2949 } // namespace v8 | 2962 } // namespace v8 |
OLD | NEW |