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 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; |
|
bradnelson
2016/10/19 21:52:07
Maybe a comment linking to the errata?
John
2016/10/20 15:13:22
Done (in asm-typer.h)
| |
| 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"); | |
|
bradnelson
2016/10/19 21:52:07
period like the others?
John
2016/10/20 15:13:22
Done.
| |
| 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 |