Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: test/cctest/test-asm-validator.cc

Issue 2071343003: V8. ASM-2-WASM. Validator V2. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: tests function tables and module exports. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« src/wasm/asm-typer.cc ('K') | « src/wasm/asm-types.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 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 <cstring>
6 #include <functional>
7 #include <iostream>
8 #include <memory>
9
5 #include "src/v8.h" 10 #include "src/v8.h"
6 11
12 #include "src/ast/ast-expression-visitor.h"
13 #include "src/ast/ast-value-factory.h"
7 #include "src/ast/ast.h" 14 #include "src/ast/ast.h"
8 #include "src/ast/ast-expression-visitor.h"
9 #include "src/ast/scopes.h" 15 #include "src/ast/scopes.h"
10 #include "src/parsing/parser.h" 16 #include "src/parsing/parser.h"
11 #include "src/parsing/rewriter.h" 17 #include "src/parsing/rewriter.h"
12 #include "src/type-cache.h" 18 #include "src/type-cache.h"
13 #include "src/typing-asm.h" 19 #include "src/typing-asm.h"
20 #include "src/wasm/asm-typer.h"
21 #include "src/wasm/asm-types.h"
14 #include "test/cctest/cctest.h" 22 #include "test/cctest/cctest.h"
23 #include "test/cctest/expression-type-collector-macros.h"
15 #include "test/cctest/expression-type-collector.h" 24 #include "test/cctest/expression-type-collector.h"
16 #include "test/cctest/expression-type-collector-macros.h"
17 25
18 // Macros for function types. 26 // Macros for function types.
19 #define FUNC_FOREIGN_TYPE Bounds(Type::Function(Type::Any(), zone)) 27 #define FUNC_FOREIGN_TYPE Bounds(Type::Function(Type::Any(), zone))
20 #define FUNC_V_TYPE Bounds(Type::Function(Type::Undefined(), zone)) 28 #define FUNC_V_TYPE Bounds(Type::Function(Type::Undefined(), zone))
21 #define FUNC_I_TYPE Bounds(Type::Function(cache.kAsmSigned, zone)) 29 #define FUNC_I_TYPE Bounds(Type::Function(cache.kAsmSigned, zone))
22 #define FUNC_F_TYPE Bounds(Type::Function(cache.kAsmFloat, zone)) 30 #define FUNC_F_TYPE Bounds(Type::Function(cache.kAsmFloat, zone))
23 #define FUNC_D_TYPE Bounds(Type::Function(cache.kAsmDouble, zone)) 31 #define FUNC_D_TYPE Bounds(Type::Function(cache.kAsmDouble, zone))
24 #define FUNC_D2D_TYPE \ 32 #define FUNC_D2D_TYPE \
25 Bounds(Type::Function(cache.kAsmDouble, cache.kAsmDouble, zone)) 33 Bounds(Type::Function(cache.kAsmDouble, cache.kAsmDouble, zone))
26 #define FUNC_N2F_TYPE \ 34 #define FUNC_N2F_TYPE \
(...skipping 12 matching lines...) Expand all
39 #define FUNC_N2N_TYPE \ 47 #define FUNC_N2N_TYPE \
40 Bounds(Type::Function(Type::Number(), Type::Number(), zone)) 48 Bounds(Type::Function(Type::Number(), Type::Number(), zone))
41 49
42 // Macros for array types. 50 // Macros for array types.
43 #define FLOAT64_ARRAY_TYPE Bounds(Type::Array(cache.kAsmDouble, zone)) 51 #define FLOAT64_ARRAY_TYPE Bounds(Type::Array(cache.kAsmDouble, zone))
44 #define FUNC_I2I_ARRAY_TYPE \ 52 #define FUNC_I2I_ARRAY_TYPE \
45 Bounds(Type::Array(Type::Function(cache.kAsmSigned, cache.kAsmInt, zone), \ 53 Bounds(Type::Array(Type::Function(cache.kAsmSigned, cache.kAsmInt, zone), \
46 zone)) 54 zone))
47 55
48 using namespace v8::internal; 56 using namespace v8::internal;
57 namespace iw = i::wasm;
49 58
50 namespace { 59 namespace {
51 60
52 std::string Validate(Zone* zone, const char* source, 61 std::string Validate(Zone* zone, const char* source,
53 ZoneVector<ExpressionTypeEntry>* types) { 62 ZoneVector<ExpressionTypeEntry>* types) {
54 i::Isolate* isolate = CcTest::i_isolate(); 63 i::Isolate* isolate = CcTest::i_isolate();
55 i::Factory* factory = isolate->factory(); 64 i::Factory* factory = isolate->factory();
56 65
57 i::Handle<i::String> source_code = 66 i::Handle<i::String> source_code =
58 factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked(); 67 factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked();
(...skipping 2447 matching lines...) Expand 10 before | Expand all | Expand 10 after
2506 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) { 2515 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) {
2507 CHECK_VAR(x, Bounds(cache.kAsmDouble)); 2516 CHECK_VAR(x, Bounds(cache.kAsmDouble));
2508 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); 2517 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
2509 } 2518 }
2510 } 2519 }
2511 } 2520 }
2512 CHECK_SKIP(); 2521 CHECK_SKIP();
2513 } 2522 }
2514 CHECK_FUNC_TYPES_END 2523 CHECK_FUNC_TYPES_END
2515 } 2524 }
2525
bradnelson 2016/06/24 00:19:03 Maybe put this in test/wasm/test-asm-validator ? T
John 2016/06/24 17:47:58 I left a TODO, for now. I'll move the file before
bradn 2016/06/24 18:57:03 Ok. Yeah better for review.
2526 // -----------------------------------------------------------------------------
2527 // asm.js typer v2.
2528
2529 namespace v8 {
2530 namespace internal {
2531 namespace wasm {
2532
2533 enum ValidationType {
2534 ValidateModule,
2535 ValidateGlobals,
2536 ValidateFunctionTables,
2537 ValidateExport,
2538 };
2539
2540 class AsmTyperHarnessBuilder {
2541 public:
2542 AsmTyperHarnessBuilder(const char* source, ValidationType type)
2543 : source_(source),
2544 validation_type_(type),
2545 handles_(),
2546 zone_(handles_.main_zone()),
2547 isolate_(CcTest::i_isolate()),
2548 ast_value_factory_(zone_, isolate_->heap()->HashSeed()),
2549 factory_(isolate_->factory()),
2550 source_code_(
2551 factory_->NewStringFromUtf8(CStrVector(source)).ToHandleChecked()),
2552 script_(factory_->NewScript(source_code_)) {
2553 ParseInfo info(zone_, script_);
2554 Parser parser(&info);
2555 info.set_global();
2556 info.set_lazy(false);
2557 info.set_allow_lazy_parsing(false);
2558 info.set_toplevel(true);
2559 info.set_ast_value_factory(&ast_value_factory_);
2560 info.set_ast_value_factory_owned(false);
2561
2562 if (!Compiler::ParseAndAnalyze(&info)) {
2563 std::cerr << "Failed to parse:\n" << source_ << "\n";
2564 CHECK(false);
2565 }
2566
2567 outer_scope_ = info.script_scope();
2568 module_ =
2569 info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun();
2570 typer_.reset(new AsmTyper(isolate_, zone_, *script_, module_));
2571 }
2572
2573 struct VariableName {
2574 VariableName(const char* name, VariableMode mode)
2575 : name_(name), mode_(mode) {}
2576 VariableName(const VariableName&) = default;
2577 VariableName& operator=(const VariableName&) = default;
2578
2579 const char* name_;
2580 const VariableMode mode_;
2581 };
2582
2583 AsmTyperHarnessBuilder* WithLocal(VariableName, AsmType*) { return this; }
2584
2585 AsmTyperHarnessBuilder* WithGlobal(VariableName var_name, AsmType* type) {
2586 auto* var = DeclareVariable(var_name);
2587 auto* var_info = new (zone_) AsmTyper::VariableInfo(type);
2588 var_info->set_mutability(AsmTyper::VariableInfo::kMutableGlobal);
2589 CHECK(typer_->AddGlobal(var, var_info));
2590 return this;
2591 }
2592
2593 AsmTyperHarnessBuilder* WithGlobal(
2594 VariableName var_name, std::function<AsmType*(Zone*)> type_creator) {
2595 return WithGlobal(var_name, type_creator(zone_));
2596 }
2597
2598 AsmTyperHarnessBuilder* WithUndefinedGlobal(
2599 VariableName var_name, std::function<AsmType*(Zone*)> type_creator) {
2600 auto* type = type_creator(zone_);
2601 CHECK(type->AsFunctionType() != nullptr ||
2602 type->AsFunctionTableType() != nullptr);
2603 WithGlobal(var_name, type);
2604 auto* var_info = typer_->Lookup(DeclareVariable(var_name));
2605 CHECK(var_info);
2606 var_info->FirstForwardUseIs(nullptr);
2607 return this;
2608 }
2609
2610 AsmTyperHarnessBuilder* WithImport(VariableName var_name,
2611 AsmTyper::StandardMember standard_member) {
2612 auto* var = DeclareVariable(var_name);
2613 AsmTyper::VariableInfo* var_info = nullptr;
2614 auto* stdlib_map = &typer_->stdlib_math_types_;
2615 switch (standard_member) {
2616 case AsmTyper::kHeap:
2617 case AsmTyper::kStdlib:
2618 case AsmTyper::kModule:
2619 case AsmTyper::kNone:
2620 CHECK(false);
2621 case AsmTyper::kFFI:
2622 stdlib_map = nullptr;
2623 var_info = new (zone_) AsmTyper::VariableInfo(AsmType::FFIType(zone_));
2624 var_info->set_mutability(AsmTyper::VariableInfo::kImmutableGlobal);
2625 break;
2626 case AsmTyper::kInfinity:
2627 case AsmTyper::kNaN:
2628 stdlib_map = &typer_->stdlib_types_;
2629 default:
2630 break;
2631 }
2632
2633 if (var_info == nullptr) {
2634 for (auto iter : *stdlib_map) {
2635 if (iter.second->standard_member() == standard_member) {
2636 var_info = iter.second;
2637 break;
2638 }
2639 }
2640
2641 CHECK(var_info != nullptr);
2642 var_info = var_info->Clone(zone_);
2643 }
2644
2645 CHECK(typer_->AddGlobal(var, var_info));
2646 return this;
2647 }
2648
2649 AsmTyperHarnessBuilder* WithStdlib(VariableName var_name) {
2650 auto* var = DeclareVariable(var_name);
2651 auto* var_info = new (zone_) AsmTyper::VariableInfo();
2652 var_info->set_mutability(AsmTyper::VariableInfo::kImmutableGlobal);
2653 var_info->set_standard_member(AsmTyper::kStdlib);
2654 CHECK(typer_->AddGlobal(var, var_info));
2655 return this;
2656 }
2657
2658 AsmTyperHarnessBuilder* WithHeap(VariableName var_name) {
2659 auto* var = DeclareVariable(var_name);
2660 auto* var_info = new (zone_) AsmTyper::VariableInfo();
2661 var_info->set_mutability(AsmTyper::VariableInfo::kImmutableGlobal);
2662 var_info->set_standard_member(AsmTyper::kHeap);
2663 CHECK(typer_->AddGlobal(var, var_info));
2664 return this;
2665 }
2666
2667 AsmTyperHarnessBuilder* WithFFI(VariableName var_name) {
2668 auto* var = DeclareVariable(var_name);
2669 auto* var_info =
2670 new (zone_) AsmTyper::VariableInfo(AsmType::FFIType(zone_));
2671 var_info->set_mutability(AsmTyper::VariableInfo::kImmutableGlobal);
2672 var_info->set_standard_member(AsmTyper::kFFI);
2673 CHECK(typer_->AddGlobal(var, var_info));
2674 return this;
2675 }
2676
2677 bool Succeeds() {
2678 CHECK(validation_type_ == ValidateModule ||
2679 validation_type_ == ValidateGlobals ||
2680 validation_type_ == ValidateFunctionTables ||
2681 validation_type_ == ValidateExport);
2682 if (typer_->Validate()) {
2683 return true;
2684 }
2685
2686 std::cerr << "Asm validation failed: " << typer_->error_message() << "\n";
2687 return false;
2688 }
2689
2690 bool FailsWithMessage(const char* error_message) {
2691 CHECK(validation_type_ == ValidateModule ||
2692 validation_type_ == ValidateGlobals ||
2693 validation_type_ == ValidateFunctionTables ||
2694 validation_type_ == ValidateExport);
2695
2696 if (typer_->Validate()) {
2697 std::cerr << "Asm validation succeeded\n";
2698 return false;
2699 }
2700
2701 if (std::strstr(typer_->error_message(), error_message) == nullptr) {
2702 std::cerr << "Asm validation failed with the wrong error message:\n"
2703 "Expected to contain '"
2704 << error_message << "'\n"
2705 " Actually is '"
2706 << typer_->error_message() << "'\n";
2707 return false;
2708 }
2709
2710 return true;
2711 }
2712
2713 private:
2714 Variable* DeclareVariable(VariableName var_name) {
2715 auto* name_ast_string = ast_value_factory_.GetOneByteString(var_name.name_);
2716 return var_name.mode_ == DYNAMIC_GLOBAL
2717 ? outer_scope_->DeclareDynamicGlobal(name_ast_string)
2718 : module_->scope()->DeclareLocal(name_ast_string, VAR,
2719 kCreatedInitialized,
2720 Variable::NORMAL);
2721 }
2722
2723 std::string source_;
2724 ValidationType validation_type_;
2725 HandleAndZoneScope handles_;
2726 Zone* zone_;
2727 Isolate* isolate_;
2728 AstValueFactory ast_value_factory_;
2729 Factory* factory_;
2730 Handle<String> source_code_;
2731 Handle<Script> script_;
2732
2733 Scope* outer_scope_;
2734 FunctionLiteral* module_;
2735 std::unique_ptr<AsmTyper> typer_;
2736 };
2737
2738 } // namespace wasm
2739 } // namespace internal
2740 } // namespace v8
2741
2742 namespace {
2743
2744 struct ValidationInput {
2745 ValidationInput(const std::string& source, iw::ValidationType type)
2746 : source_(source), type_(type) {}
2747
2748 const std::string source_;
2749 const iw::ValidationType type_;
2750 };
2751
2752 std::unique_ptr<iw::AsmTyperHarnessBuilder> ValidationOf(
2753 ValidationInput input) {
2754 return std::unique_ptr<iw::AsmTyperHarnessBuilder>(
2755 new iw::AsmTyperHarnessBuilder(input.source_.c_str(), input.type_));
2756 }
2757
2758 ValidationInput Module(const char* source) {
2759 return ValidationInput(source, iw::ValidateModule);
2760 }
2761
2762 std::string WrapInFunction(const char* source, bool needs_use_asm) {
2763 if (needs_use_asm) {
2764 return std::string(
2765 "function foo() {\n"
2766 " 'use asm';\n"
2767 " ") +
2768 source +
2769 "\n"
2770 "}";
2771 }
2772
2773 return std::string(
2774 "function foo() {\n"
2775 " ") +
2776 source +
2777 "\n"
2778 "}";
2779 }
2780
2781 ValidationInput Globals(const char* source) {
2782 static const bool kNeedsUseAsm = true;
2783 return ValidationInput(WrapInFunction(source, kNeedsUseAsm),
2784 iw::ValidateGlobals);
2785 }
2786
2787 ValidationInput FunctionTables(const char* source) {
2788 static const bool kNeedsUseAsm = true;
2789 return ValidationInput(WrapInFunction(source, kNeedsUseAsm),
2790 iw::ValidateFunctionTables);
2791 }
2792
2793 ValidationInput Export(const char* source) {
2794 static const bool kNeedsUseAsm = true;
2795 return ValidationInput(WrapInFunction(source, kNeedsUseAsm),
2796 iw::ValidateExport);
2797 }
2798
2799 iw::AsmTyperHarnessBuilder::VariableName Var(const char* name) {
2800 return iw::AsmTyperHarnessBuilder::VariableName(name, VAR);
2801 }
2802
2803 iw::AsmTyperHarnessBuilder::VariableName DynamicGlobal(const char* name) {
2804 return iw::AsmTyperHarnessBuilder::VariableName(name, DYNAMIC_GLOBAL);
2805 }
2806
2807 TEST(MissingUseAsmDirective) {
2808 v8::V8::Initialize();
2809
2810 // We can't test the empty input ("") because the AsmTyperHarnessBuilder will
2811 // CHECK if there's no function in the top-level scope.
2812 const char* kTests[] = {"function module(){}",
2813 "function module(){ use_asm; }",
2814 "function module(){ \"use asm \"; }",
2815 "function module(){ \" use asm \"; }",
2816 "function module(){ \"use Asm\"; }"};
2817
2818 for (size_t ii = 0; ii < arraysize(kTests); ++ii) {
2819 const char* module = kTests[ii];
2820 if (!ValidationOf(Module(module))
2821 ->FailsWithMessage("missing \"use asm\"")) {
2822 std::cerr << "Test:\n" << module;
2823 CHECK(false);
2824 }
2825 }
2826 }
2827
2828 TEST(InvalidModuleSignature) {
2829 v8::V8::Initialize();
2830
2831 const struct {
2832 const char* module;
2833 const char* error_message;
2834 } kTests[] = {
2835 {"function eval(){ \"use asm\"; }",
2836 "Invalid ASM.js identifier in module name"},
2837 {"function arguments(){ \"use asm\"; }",
2838 "Invalid ASM.js identifier in module name"},
2839 {"function module(eval){ \"use asm\"; }",
2840 "Invalid ASM.js identifier in module parameter"},
2841 {"function module(arguments){ \"use asm\"; }",
2842 "Invalid ASM.js identifier in module parameter"},
2843 {"function module(stdlib, eval){ \"use asm\"; }",
2844 "Invalid ASM.js identifier in module parameter"},
2845 {"function module(stdlib, arguments){ \"use asm\"; }",
2846 "Invalid ASM.js identifier in module parameter"},
2847 {"function module(stdlib, foreign, eval){ \"use asm\"; }",
2848 "Invalid ASM.js identifier in module parameter"},
2849 {"function module(stdlib, foreign, arguments){ \"use asm\"; }",
2850 "Invalid ASM.js identifier in module parameter"},
2851 {"function module(stdlib, foreign, heap, eval){ \"use asm\"; }",
2852 "ASM.js modules may not have more than three parameters"},
2853 {"function module(stdlib, foreign, heap, arguments){ \"use asm\"; }",
2854 "ASM.js modules may not have more than three parameters"},
2855 {"function module(module){ \"use asm\"; }",
2856 "Redeclared identifier in module parameter"},
2857 {"function module(stdlib, module){ \"use asm\"; }",
2858 "Redeclared identifier in module parameter"},
2859 {"function module(stdlib, stdlib){ \"use asm\"; }",
2860 "Redeclared identifier in module parameter"},
2861 {"function module(stdlib, foreign, module){ \"use asm\"; }",
2862 "Redeclared identifier in module parameter"},
2863 {"function module(stdlib, foreign, stdlib){ \"use asm\"; }",
2864 "Redeclared identifier in module parameter"},
2865 {"function module(stdlib, foreign, foreign){ \"use asm\"; }",
2866 "Redeclared identifier in module parameter"},
2867 };
2868
2869 for (size_t ii = 0; ii < arraysize(kTests); ++ii) {
2870 const auto* test = kTests + ii;
2871 if (!ValidationOf(Module(test->module))
2872 ->FailsWithMessage(test->error_message)) {
2873 std::cerr << "Test:\n" << test->module;
2874 CHECK(false);
2875 }
2876 }
2877 }
2878
2879 TEST(ErrorsInGlobalVariableDefinition) {
2880 const struct {
2881 const char* decl;
2882 const char* error_message;
2883 } kTests[] = {
2884 {"var v;", "Global variable missing initializer"},
2885 {"var v = uninitialized;", "Invalid global variable initializer"},
2886 {"var v = 'use asm';", "type annotation - forbidden literal"},
2887 {"var v = 4294967296;", " - forbidden literal"},
2888 {"var v = not_fround;", "Invalid global variable initializer"},
2889 {"var v = not_fround(1);", "expected call fround(literal)"},
2890 {"var v = __fround__(1.0);", "expected call fround(literal)"},
2891 {"var v = fround(1.0, 1.0);", "expected call fround(literal)"},
2892 {"var v = fround(not_fround);", "literal argument for call to fround"},
2893 {"var v = fround(1);", "literal argument to be a floating point"},
2894 {"var v = stdlib.nan", "Invalid import"},
2895 {"var v = stdlib.Math.nan", "Invalid import"},
2896 {"var v = stdlib.Mathh.E", "Invalid import"},
2897 {"var v = stdlib.Math", "Invalid import"},
2898 {"var v = Stdlib.Math.E", "Invalid import"},
2899 {"var v = stdlib.Math.E[0]", "Invalid import"},
2900 {"var v = stdlibb.NaN", "Invalid import"},
2901 {"var v = ffi.NaN[0]", "Invalid import"},
2902 {"var v = heap.NaN[0]", "Invalid import"},
2903 {"var v = ffi.foo * 2.0;", "unrecognized annotation"},
2904 {"var v = ffi.foo|1;", "unrecognized annotation"},
2905 {"var v = ffi()|0;", "must import member"},
2906 {"var v = +ffi();", "must import member"},
2907 {"var v = ffi().a|0;", "object lookup failed"},
2908 {"var v = +ffi().a;", "object lookup failed"},
2909 {"var v = sstdlib.a|0;", "object lookup failed"},
2910 {"var v = +sstdlib.a;", "object lookup failed"},
2911 {"var v = stdlib.NaN|0;", "object is not the ffi"},
2912 {"var v = +stdlib.NaN;", "object is not the ffi"},
2913 {"var v = new f()", "Invalid type after new"},
2914 {"var v = new stdli.Uint8Array(heap)", "Unknown stdlib member in heap"},
2915 {"var v = new stdlib.dd(heap)", "Unknown stdlib member in heap"},
2916 {"var v = new stdlib.Math.fround(heap)", "Type is not a heap view type"},
2917 {"var v = new stdlib.Uint8Array(a, b)", "Invalid number of arguments"},
2918 {"var v = new stdlib.Uint8Array(heap())", "should be the module's heap"},
2919 {"var v = new stdlib.Uint8Array(heap_)", "instead of heap parameter"},
2920 {"var v = new stdlib.Uint8Array(ffi)", "should be the module's heap"},
2921 {"var eval = 0;", "in global variable"},
2922 {"var eval = 0.0;", "in global variable"},
2923 {"var eval = fround(0.0);", "in global variable"},
2924 {"var eval = +ffi.a;", "in global variable"},
2925 {"var eval = ffi.a|0;", "in global variable"},
2926 {"var eval = ffi.a;", "in global variable"},
2927 {"var eval = new stdlib.Uint8Array(heap);", "in global variable"},
2928 {"var arguments = 0;", "in global variable"},
2929 {"var arguments = 0.0;", "in global variable"},
2930 {"var arguments = fround(0.0);", "in global variable"},
2931 {"var arguments = +ffi.a;", "in global variable"},
2932 {"var arguments = ffi.a|0;", "in global variable"},
2933 {"var arguments = ffi.a;", "in global variable"},
2934 {"var arguments = new stdlib.Uint8Array(heap);", "in global variable"},
2935 {"var a = 0, a = 0.0;", "Redefined global variable"},
2936 {"var a = 0; var a = 0;", "Redefined global variable"},
2937 {"var a = 0, b = 0; var a = 0;", "Redefined global variable"},
2938 {"var a = 0, b = 0; var b = 0, a = 0.0;", "Redefined global variable"},
2939 };
2940
2941 for (size_t ii = 0; ii < arraysize(kTests); ++ii) {
2942 const auto* test = kTests + ii;
2943 if (!ValidationOf(Globals(test->decl))
2944 ->WithStdlib(DynamicGlobal("stdlib"))
2945 ->WithFFI(DynamicGlobal("ffi"))
2946 ->WithHeap(DynamicGlobal("heap"))
2947 ->WithGlobal(DynamicGlobal("not_fround"), iw::AsmType::Int())
2948 ->WithImport(DynamicGlobal("fround"), iw::AsmTyper::kMathFround)
2949 ->FailsWithMessage(test->error_message)) {
2950 std::cerr << "Test:\n" << test->decl;
2951 CHECK(false);
2952 }
2953 }
2954 }
2955
2956 TEST(ErrorsInFunctionTableDefinition) {
2957 const struct {
2958 const char* tables;
2959 const char* error_message;
2960 } kTests[] = {
2961 {"var a = [a, a, a];", "Invalid length for function pointer table"},
2962 {"var a = [d2s0()];", "must be a function name"},
2963 {"var a = [d2s44];", "Undefined identifier in function pointer"},
2964 {"var a = [fround];", "not be a member of the standard library"},
2965 {"var a = [imul];", "not be a member of the standard library"},
2966 {"var a = [ffi_import];", "must be an ASM.js function"},
2967 {"var a = [dI];", "must be an ASM.js function"},
2968 {"var a = [d2s0, d2s1, d2s0, f2s0];", "mismatch in function pointer"},
2969 {"var eval = [d2s0, d2s1];", "ASM.js identifier in function table name"},
2970 {"var arguments = [d2s0, d2s1];", "ASM.js identifier in function table"},
2971 {"var foo = [d2s0, d2s1];", "Identifier redefined in function table"},
2972 {"var I = [d2s0, d2s1];", "Identifier redefined in function table name"},
2973 {"var d2s = [d2f0, d2f1];", "redeclared as function pointer table"},
2974 {"var d2s_t = [d2s0];", "Function table size mismatch"},
2975 {"var d2s_t = [d2f0, d2sf];", "initializer does not match previous"},
2976 };
2977
2978 auto d2s = [](Zone* zone) -> iw::AsmType* {
2979 auto* ret = iw::AsmType::Function(zone, iw::AsmType::Signed());
2980 ret->AsFunctionType()->AddArgument(iw::AsmType::Double());
2981 return ret;
2982 };
2983
2984 auto d2s_tbl = [](Zone* zone) -> iw::AsmType* {
2985 auto* d2s = iw::AsmType::Function(zone, iw::AsmType::Signed());
2986 d2s->AsFunctionType()->AddArgument(iw::AsmType::Double());
2987
2988 auto* ret = iw::AsmType::FunctionTableType(zone, 2, d2s);
2989 return ret;
2990 };
2991
2992 auto f2s = [](Zone* zone) -> iw::AsmType* {
2993 auto* ret = iw::AsmType::Function(zone, iw::AsmType::Signed());
2994 ret->AsFunctionType()->AddArgument(iw::AsmType::Float());
2995 return ret;
2996 };
2997
2998 auto d2f = [](Zone* zone) -> iw::AsmType* {
2999 auto* ret = iw::AsmType::Function(zone, iw::AsmType::Float());
3000 ret->AsFunctionType()->AddArgument(iw::AsmType::Double());
3001 return ret;
3002 };
3003
3004 for (size_t ii = 0; ii < arraysize(kTests); ++ii) {
3005 const auto* test = kTests + ii;
3006 if (!ValidationOf(FunctionTables(test->tables))
3007 ->WithImport(DynamicGlobal("ffi_import"), iw::AsmTyper::kFFI)
3008 ->WithImport(DynamicGlobal("imul"), iw::AsmTyper::kMathImul)
3009 ->WithImport(DynamicGlobal("E"), iw::AsmTyper::kMathE)
3010 ->WithImport(DynamicGlobal("fround"), iw::AsmTyper::kMathFround)
3011 ->WithImport(DynamicGlobal("floor"), iw::AsmTyper::kMathFround)
3012 ->WithGlobal(DynamicGlobal("d2s0"), d2s)
3013 ->WithGlobal(DynamicGlobal("d2s1"), d2s)
3014 ->WithGlobal(DynamicGlobal("f2s0"), f2s)
3015 ->WithGlobal(DynamicGlobal("f2s1"), f2s)
3016 ->WithGlobal(DynamicGlobal("d2f0"), d2f)
3017 ->WithGlobal(DynamicGlobal("d2f1"), d2f)
3018 ->WithGlobal(DynamicGlobal("dI"), iw::AsmType::Int())
3019 ->WithGlobal(Var("I"), iw::AsmType::Int())
3020 ->WithUndefinedGlobal(Var("d2s"), d2s)
3021 ->WithUndefinedGlobal(Var("d2s_t"), d2s_tbl)
3022 ->FailsWithMessage(test->error_message)) {
3023 std::cerr << "Test:\n" << test->tables;
3024 CHECK(false);
3025 }
3026 }
3027 }
3028
3029 TEST(ErrorsInModuleExport) {
bradnelson 2016/06/24 00:19:03 These tests are great John, definitely a good appr
John 2016/06/24 17:47:58 Acknowledged.
3030 const struct {
3031 const char* module_export;
3032 const char* error_message;
3033 } kTests[] = {
3034 {"", "Missing ASM.js module export"},
3035 {"return;", "Unrecognized expression in ASM.js module export expression"},
3036 {"return d2s_tbl;", "is not an ASM.js function"},
3037 {"return min;", "is not an ASM.js function"},
3038 {"return I;", "is not an ASM.js function"},
3039 {"return {\'a\': d2s_tbl}", "export property is not an ASM.js"},
3040 {"return {\'a\': min}", "export cannot contain standard library"},
3041 {"return {\'a\': f()}", "must be an ASM.js function name"},
3042 {"return {\'a\': f}", "in ASM.js module export property"},
3043 {"function v() { a(); } return {b: d2s}", "Missing definition for forw"},
3044 {"return {b: d2s, \'a\': d2s_tbl}", "export property is not an ASM.js"},
3045 {"return {b: d2s, \'a\': min}", "export cannot contain standard library"},
3046 {"return {b: d2s, \'a\': f()}", "must be an ASM.js function name"},
3047 {"return {b: d2s, \'a\': f}", "in ASM.js module export property"},
3048 };
3049
3050 auto d2s_tbl = [](Zone* zone) -> iw::AsmType* {
3051 auto* d2s = iw::AsmType::Function(zone, iw::AsmType::Signed());
3052 d2s->AsFunctionType()->AddArgument(iw::AsmType::Double());
3053
3054 auto* ret = iw::AsmType::FunctionTableType(zone, 2, d2s);
3055 return ret;
3056 };
3057
3058 auto d2s = [](Zone* zone) -> iw::AsmType* {
3059 auto* ret = iw::AsmType::Function(zone, iw::AsmType::Signed());
3060 ret->AsFunctionType()->AddArgument(iw::AsmType::Double());
3061 return ret;
3062 };
3063
3064 for (size_t ii = 0; ii < arraysize(kTests); ++ii) {
3065 const auto* test = kTests + ii;
3066 if (!ValidationOf(Export(test->module_export))
3067 ->WithGlobal(DynamicGlobal("d2s_tbl"), d2s_tbl)
3068 ->WithGlobal(DynamicGlobal("d2s"), d2s)
3069 ->WithImport(DynamicGlobal("min"), iw::AsmTyper::kMathMin)
3070 ->WithGlobal(DynamicGlobal("I"), iw::AsmType::Int())
3071 ->FailsWithMessage(test->error_message)) {
3072 std::cerr << "Test:\n" << test->module_export;
3073 CHECK(false);
3074 }
3075 }
3076 }
3077
3078 } // namespace
OLDNEW
« src/wasm/asm-typer.cc ('K') | « src/wasm/asm-types.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698