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 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 if (target_info != nullptr) { | 755 if (target_info != nullptr) { |
756 FAIL(target, "Redefined global variable."); | 756 FAIL(target, "Redefined global variable."); |
757 } | 757 } |
758 | 758 |
759 auto* value = assign->value(); | 759 auto* value = assign->value(); |
760 // Not all types of assignment are allowed by asm.js. See | 760 // Not all types of assignment are allowed by asm.js. See |
761 // 5.5 Global Variable Type Annotations. | 761 // 5.5 Global Variable Type Annotations. |
762 bool global_variable = false; | 762 bool global_variable = false; |
763 if (value->IsLiteral() || value->IsCall()) { | 763 if (value->IsLiteral() || value->IsCall()) { |
764 AsmType* type = nullptr; | 764 AsmType* type = nullptr; |
765 RECURSE(type = VariableTypeAnnotations(value, true)); | 765 VariableInfo::Mutability mutability; |
| 766 if (target_variable->mode() == CONST) { |
| 767 mutability = VariableInfo::kConstGlobal; |
| 768 } else { |
| 769 mutability = VariableInfo::kMutableGlobal; |
| 770 } |
| 771 RECURSE(type = VariableTypeAnnotations(value, mutability)); |
766 target_info = new (zone_) VariableInfo(type); | 772 target_info = new (zone_) VariableInfo(type); |
767 target_info->set_mutability(VariableInfo::kMutableGlobal); | 773 target_info->set_mutability(mutability); |
768 global_variable = true; | 774 global_variable = true; |
769 } else if (value->IsProperty()) { | 775 } else if (value->IsProperty()) { |
770 target_info = ImportLookup(value->AsProperty()); | 776 target_info = ImportLookup(value->AsProperty()); |
771 if (target_info == nullptr) { | 777 if (target_info == nullptr) { |
772 FAIL(assign, "Invalid import."); | 778 FAIL(assign, "Invalid import."); |
773 } | 779 } |
774 CHECK(target_info->mutability() == VariableInfo::kImmutableGlobal); | 780 CHECK(target_info->mutability() == VariableInfo::kImmutableGlobal); |
775 if (target_info->IsFFI()) { | 781 if (target_info->IsFFI()) { |
776 // create a new target info that represents a foreign variable. | 782 // create a new target info that represents a foreign variable. |
777 target_info = new (zone_) VariableInfo(ffi_type_); | 783 target_info = new (zone_) VariableInfo(ffi_type_); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
821 } | 827 } |
822 | 828 |
823 // Create a new target info that represents the foreign import. | 829 // Create a new target info that represents the foreign import. |
824 target_info = new (zone_) VariableInfo(import_type); | 830 target_info = new (zone_) VariableInfo(import_type); |
825 target_info->set_mutability(VariableInfo::kMutableGlobal); | 831 target_info->set_mutability(VariableInfo::kMutableGlobal); |
826 } else if (value->IsCallNew()) { | 832 } else if (value->IsCallNew()) { |
827 AsmType* type = nullptr; | 833 AsmType* type = nullptr; |
828 RECURSE(type = NewHeapView(value->AsCallNew())); | 834 RECURSE(type = NewHeapView(value->AsCallNew())); |
829 target_info = new (zone_) VariableInfo(type); | 835 target_info = new (zone_) VariableInfo(type); |
830 target_info->set_mutability(VariableInfo::kImmutableGlobal); | 836 target_info->set_mutability(VariableInfo::kImmutableGlobal); |
| 837 } else if (auto* proxy = value->AsVariableProxy()) { |
| 838 auto* var_info = Lookup(proxy->var()); |
| 839 |
| 840 if (var_info == nullptr) { |
| 841 FAIL(value, "Undeclared identifier in global initializer"); |
| 842 } |
| 843 |
| 844 if (var_info->mutability() != VariableInfo::kConstGlobal) { |
| 845 FAIL(value, "Identifier used to initialize a global must be a const"); |
| 846 } |
| 847 |
| 848 target_info = new (zone_) VariableInfo(var_info->type()); |
| 849 if (target_variable->mode() == CONST) { |
| 850 target_info->set_mutability(VariableInfo::kConstGlobal); |
| 851 } else { |
| 852 target_info->set_mutability(VariableInfo::kMutableGlobal); |
| 853 } |
831 } | 854 } |
832 | 855 |
833 if (target_info == nullptr) { | 856 if (target_info == nullptr) { |
834 FAIL(assign, "Invalid global variable initializer."); | 857 FAIL(assign, "Invalid global variable initializer."); |
835 } | 858 } |
836 | 859 |
837 if (!ValidAsmIdentifier(target_variable->name())) { | 860 if (!ValidAsmIdentifier(target_variable->name())) { |
838 FAIL(target, "Invalid asm.js identifier in global variable."); | 861 FAIL(target, "Invalid asm.js identifier in global variable."); |
839 } | 862 } |
840 | 863 |
(...skipping 1836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2677 // return; | 2700 // return; |
2678 // | 2701 // |
2679 // into | 2702 // into |
2680 // | 2703 // |
2681 // return undefined | 2704 // return undefined |
2682 return AsmType::Void(); | 2705 return AsmType::Void(); |
2683 } | 2706 } |
2684 FAIL(statement, "Invalid literal in return statement."); | 2707 FAIL(statement, "Invalid literal in return statement."); |
2685 } | 2708 } |
2686 | 2709 |
| 2710 if (auto* proxy = ret_expr->AsVariableProxy()) { |
| 2711 auto* var_info = Lookup(proxy->var()); |
| 2712 |
| 2713 if (var_info == nullptr) { |
| 2714 FAIL(statement, "Undeclared identifier in return statement."); |
| 2715 } |
| 2716 |
| 2717 if (var_info->mutability() != VariableInfo::kConstGlobal) { |
| 2718 FAIL(statement, "Identifier in return statement is not const."); |
| 2719 } |
| 2720 |
| 2721 return var_info->type(); |
| 2722 } |
| 2723 |
2687 FAIL(statement, "Invalid return type expression."); | 2724 FAIL(statement, "Invalid return type expression."); |
2688 } | 2725 } |
2689 | 2726 |
2690 // 5.4 VariableTypeAnnotations | 2727 // 5.4 VariableTypeAnnotations |
2691 // Also used for 5.5 GlobalVariableTypeAnnotations | 2728 // Also used for 5.5 GlobalVariableTypeAnnotations |
2692 AsmType* AsmTyper::VariableTypeAnnotations(Expression* initializer, | 2729 AsmType* AsmTyper::VariableTypeAnnotations( |
2693 bool global) { | 2730 Expression* initializer, VariableInfo::Mutability mutability_type) { |
2694 if (auto* literal = initializer->AsLiteral()) { | 2731 if (auto* literal = initializer->AsLiteral()) { |
2695 if (literal->raw_value()->ContainsDot()) { | 2732 if (literal->raw_value()->ContainsDot()) { |
2696 SetTypeOf(initializer, AsmType::Double()); | 2733 SetTypeOf(initializer, AsmType::Double()); |
2697 return AsmType::Double(); | 2734 return AsmType::Double(); |
2698 } | 2735 } |
2699 int32_t i32; | 2736 int32_t i32; |
2700 uint32_t u32; | 2737 uint32_t u32; |
| 2738 |
| 2739 AsmType* initializer_type = nullptr; |
2701 if (literal->value()->ToUint32(&u32)) { | 2740 if (literal->value()->ToUint32(&u32)) { |
2702 if (u32 > LargestFixNum) { | 2741 if (u32 > LargestFixNum) { |
2703 SetTypeOf(initializer, AsmType::Unsigned()); | 2742 initializer_type = AsmType::Unsigned(); |
| 2743 SetTypeOf(initializer, initializer_type); |
2704 } else { | 2744 } else { |
2705 SetTypeOf(initializer, AsmType::FixNum()); | 2745 initializer_type = AsmType::FixNum(); |
| 2746 SetTypeOf(initializer, initializer_type); |
| 2747 initializer_type = AsmType::Signed(); |
2706 } | 2748 } |
2707 } else if (literal->value()->ToInt32(&i32)) { | 2749 } else if (literal->value()->ToInt32(&i32)) { |
2708 SetTypeOf(initializer, AsmType::Signed()); | 2750 initializer_type = AsmType::Signed(); |
| 2751 SetTypeOf(initializer, initializer_type); |
2709 } else { | 2752 } else { |
2710 FAIL(initializer, "Invalid type annotation - forbidden literal."); | 2753 FAIL(initializer, "Invalid type annotation - forbidden literal."); |
2711 } | 2754 } |
2712 return AsmType::Int(); | 2755 if (mutability_type != VariableInfo::kConstGlobal) { |
| 2756 return AsmType::Int(); |
| 2757 } |
| 2758 return initializer_type; |
| 2759 } |
| 2760 |
| 2761 if (auto* proxy = initializer->AsVariableProxy()) { |
| 2762 auto* var_info = Lookup(proxy->var()); |
| 2763 |
| 2764 if (var_info == nullptr) { |
| 2765 FAIL(initializer, |
| 2766 "Undeclared identifier in variable declaration initializer."); |
| 2767 } |
| 2768 |
| 2769 if (var_info->mutability() != VariableInfo::kConstGlobal) { |
| 2770 FAIL(initializer, |
| 2771 "Identifier in variable declaration initializer must be const."); |
| 2772 } |
| 2773 |
| 2774 SetTypeOf(initializer, var_info->type()); |
| 2775 return var_info->type(); |
2713 } | 2776 } |
2714 | 2777 |
2715 auto* call = initializer->AsCall(); | 2778 auto* call = initializer->AsCall(); |
2716 if (call == nullptr) { | 2779 if (call == nullptr) { |
2717 FAIL(initializer, | 2780 FAIL(initializer, |
2718 "Invalid variable initialization - it should be a literal, or " | 2781 "Invalid variable initialization - it should be a literal, const, or " |
2719 "fround(literal)."); | 2782 "fround(literal)."); |
2720 } | 2783 } |
2721 | 2784 |
2722 if (!IsCallToFround(call)) { | 2785 if (!IsCallToFround(call)) { |
2723 FAIL(initializer, | 2786 FAIL(initializer, |
2724 "Invalid float coercion - expected call fround(literal)."); | 2787 "Invalid float coercion - expected call fround(literal)."); |
2725 } | 2788 } |
2726 | 2789 |
2727 auto* src_expr = call->arguments()->at(0)->AsLiteral(); | 2790 auto* src_expr = call->arguments()->at(0)->AsLiteral(); |
2728 if (src_expr == nullptr) { | 2791 if (src_expr == nullptr) { |
2729 FAIL(initializer, | 2792 FAIL(initializer, |
2730 "Invalid float type annotation - expected literal argument for call " | 2793 "Invalid float type annotation - expected literal argument for call " |
2731 "to fround."); | 2794 "to fround."); |
2732 } | 2795 } |
2733 | 2796 |
2734 // Float constants must contain dots in local, but not in globals. | 2797 // Float constants must contain dots in local, but not in globals. |
2735 if (!global) { | 2798 if (mutability_type == VariableInfo::kLocal) { |
2736 if (!src_expr->raw_value()->ContainsDot()) { | 2799 if (!src_expr->raw_value()->ContainsDot()) { |
2737 FAIL(initializer, | 2800 FAIL(initializer, |
2738 "Invalid float type annotation - expected literal argument to be a " | 2801 "Invalid float type annotation - expected literal argument to be a " |
2739 "floating point literal."); | 2802 "floating point literal."); |
2740 } | 2803 } |
2741 } | 2804 } |
2742 | 2805 |
2743 return AsmType::Float(); | 2806 return AsmType::Float(); |
2744 } | 2807 } |
2745 | 2808 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2795 return true; | 2858 return true; |
2796 } | 2859 } |
2797 | 2860 |
2798 *error_message = typer.error_message(); | 2861 *error_message = typer.error_message(); |
2799 return false; | 2862 return false; |
2800 } | 2863 } |
2801 | 2864 |
2802 } // namespace wasm | 2865 } // namespace wasm |
2803 } // namespace internal | 2866 } // namespace internal |
2804 } // namespace v8 | 2867 } // namespace v8 |
OLD | NEW |