Chromium Code Reviews| 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 // Emscipten. | |
|
Mircea Trofin
2017/01/26 07:47:27
Emscripten
bradn
2017/01/26 07:50:42
Done.
| |
| 2810 if (auto* cond = ret_expr->AsConditional()) { | |
| 2811 AsmType* a; | |
|
Mircea Trofin
2017/01/26 07:47:27
init a and b?
bradn
2017/01/26 07:50:42
Done.
| |
| 2812 AsmType* b; | |
| 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 |