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

Unified 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 side-by-side diff with in-line comments
Download patch
« src/wasm/asm-typer.cc ('K') | « src/wasm/asm-types.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/test-asm-validator.cc
diff --git a/test/cctest/test-asm-validator.cc b/test/cctest/test-asm-validator.cc
index 39d490e7a931761924ac310a62635d51145383b2..8d5a505f65cc9dc52046b8f9da45948da794ad8e 100644
--- a/test/cctest/test-asm-validator.cc
+++ b/test/cctest/test-asm-validator.cc
@@ -2,18 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <cstring>
+#include <functional>
+#include <iostream>
+#include <memory>
+
#include "src/v8.h"
-#include "src/ast/ast.h"
#include "src/ast/ast-expression-visitor.h"
+#include "src/ast/ast-value-factory.h"
+#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/parsing/parser.h"
#include "src/parsing/rewriter.h"
#include "src/type-cache.h"
#include "src/typing-asm.h"
+#include "src/wasm/asm-typer.h"
+#include "src/wasm/asm-types.h"
#include "test/cctest/cctest.h"
-#include "test/cctest/expression-type-collector.h"
#include "test/cctest/expression-type-collector-macros.h"
+#include "test/cctest/expression-type-collector.h"
// Macros for function types.
#define FUNC_FOREIGN_TYPE Bounds(Type::Function(Type::Any(), zone))
@@ -46,6 +54,7 @@
zone))
using namespace v8::internal;
+namespace iw = i::wasm;
namespace {
@@ -2513,3 +2522,557 @@ TEST(NegateDouble) {
}
CHECK_FUNC_TYPES_END
}
+
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.
+// -----------------------------------------------------------------------------
+// asm.js typer v2.
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+enum ValidationType {
+ ValidateModule,
+ ValidateGlobals,
+ ValidateFunctionTables,
+ ValidateExport,
+};
+
+class AsmTyperHarnessBuilder {
+ public:
+ AsmTyperHarnessBuilder(const char* source, ValidationType type)
+ : source_(source),
+ validation_type_(type),
+ handles_(),
+ zone_(handles_.main_zone()),
+ isolate_(CcTest::i_isolate()),
+ ast_value_factory_(zone_, isolate_->heap()->HashSeed()),
+ factory_(isolate_->factory()),
+ source_code_(
+ factory_->NewStringFromUtf8(CStrVector(source)).ToHandleChecked()),
+ script_(factory_->NewScript(source_code_)) {
+ ParseInfo info(zone_, script_);
+ Parser parser(&info);
+ info.set_global();
+ info.set_lazy(false);
+ info.set_allow_lazy_parsing(false);
+ info.set_toplevel(true);
+ info.set_ast_value_factory(&ast_value_factory_);
+ info.set_ast_value_factory_owned(false);
+
+ if (!Compiler::ParseAndAnalyze(&info)) {
+ std::cerr << "Failed to parse:\n" << source_ << "\n";
+ CHECK(false);
+ }
+
+ outer_scope_ = info.script_scope();
+ module_ =
+ info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun();
+ typer_.reset(new AsmTyper(isolate_, zone_, *script_, module_));
+ }
+
+ struct VariableName {
+ VariableName(const char* name, VariableMode mode)
+ : name_(name), mode_(mode) {}
+ VariableName(const VariableName&) = default;
+ VariableName& operator=(const VariableName&) = default;
+
+ const char* name_;
+ const VariableMode mode_;
+ };
+
+ AsmTyperHarnessBuilder* WithLocal(VariableName, AsmType*) { return this; }
+
+ AsmTyperHarnessBuilder* WithGlobal(VariableName var_name, AsmType* type) {
+ auto* var = DeclareVariable(var_name);
+ auto* var_info = new (zone_) AsmTyper::VariableInfo(type);
+ var_info->set_mutability(AsmTyper::VariableInfo::kMutableGlobal);
+ CHECK(typer_->AddGlobal(var, var_info));
+ return this;
+ }
+
+ AsmTyperHarnessBuilder* WithGlobal(
+ VariableName var_name, std::function<AsmType*(Zone*)> type_creator) {
+ return WithGlobal(var_name, type_creator(zone_));
+ }
+
+ AsmTyperHarnessBuilder* WithUndefinedGlobal(
+ VariableName var_name, std::function<AsmType*(Zone*)> type_creator) {
+ auto* type = type_creator(zone_);
+ CHECK(type->AsFunctionType() != nullptr ||
+ type->AsFunctionTableType() != nullptr);
+ WithGlobal(var_name, type);
+ auto* var_info = typer_->Lookup(DeclareVariable(var_name));
+ CHECK(var_info);
+ var_info->FirstForwardUseIs(nullptr);
+ return this;
+ }
+
+ AsmTyperHarnessBuilder* WithImport(VariableName var_name,
+ AsmTyper::StandardMember standard_member) {
+ auto* var = DeclareVariable(var_name);
+ AsmTyper::VariableInfo* var_info = nullptr;
+ auto* stdlib_map = &typer_->stdlib_math_types_;
+ switch (standard_member) {
+ case AsmTyper::kHeap:
+ case AsmTyper::kStdlib:
+ case AsmTyper::kModule:
+ case AsmTyper::kNone:
+ CHECK(false);
+ case AsmTyper::kFFI:
+ stdlib_map = nullptr;
+ var_info = new (zone_) AsmTyper::VariableInfo(AsmType::FFIType(zone_));
+ var_info->set_mutability(AsmTyper::VariableInfo::kImmutableGlobal);
+ break;
+ case AsmTyper::kInfinity:
+ case AsmTyper::kNaN:
+ stdlib_map = &typer_->stdlib_types_;
+ default:
+ break;
+ }
+
+ if (var_info == nullptr) {
+ for (auto iter : *stdlib_map) {
+ if (iter.second->standard_member() == standard_member) {
+ var_info = iter.second;
+ break;
+ }
+ }
+
+ CHECK(var_info != nullptr);
+ var_info = var_info->Clone(zone_);
+ }
+
+ CHECK(typer_->AddGlobal(var, var_info));
+ return this;
+ }
+
+ AsmTyperHarnessBuilder* WithStdlib(VariableName var_name) {
+ auto* var = DeclareVariable(var_name);
+ auto* var_info = new (zone_) AsmTyper::VariableInfo();
+ var_info->set_mutability(AsmTyper::VariableInfo::kImmutableGlobal);
+ var_info->set_standard_member(AsmTyper::kStdlib);
+ CHECK(typer_->AddGlobal(var, var_info));
+ return this;
+ }
+
+ AsmTyperHarnessBuilder* WithHeap(VariableName var_name) {
+ auto* var = DeclareVariable(var_name);
+ auto* var_info = new (zone_) AsmTyper::VariableInfo();
+ var_info->set_mutability(AsmTyper::VariableInfo::kImmutableGlobal);
+ var_info->set_standard_member(AsmTyper::kHeap);
+ CHECK(typer_->AddGlobal(var, var_info));
+ return this;
+ }
+
+ AsmTyperHarnessBuilder* WithFFI(VariableName var_name) {
+ auto* var = DeclareVariable(var_name);
+ auto* var_info =
+ new (zone_) AsmTyper::VariableInfo(AsmType::FFIType(zone_));
+ var_info->set_mutability(AsmTyper::VariableInfo::kImmutableGlobal);
+ var_info->set_standard_member(AsmTyper::kFFI);
+ CHECK(typer_->AddGlobal(var, var_info));
+ return this;
+ }
+
+ bool Succeeds() {
+ CHECK(validation_type_ == ValidateModule ||
+ validation_type_ == ValidateGlobals ||
+ validation_type_ == ValidateFunctionTables ||
+ validation_type_ == ValidateExport);
+ if (typer_->Validate()) {
+ return true;
+ }
+
+ std::cerr << "Asm validation failed: " << typer_->error_message() << "\n";
+ return false;
+ }
+
+ bool FailsWithMessage(const char* error_message) {
+ CHECK(validation_type_ == ValidateModule ||
+ validation_type_ == ValidateGlobals ||
+ validation_type_ == ValidateFunctionTables ||
+ validation_type_ == ValidateExport);
+
+ if (typer_->Validate()) {
+ std::cerr << "Asm validation succeeded\n";
+ return false;
+ }
+
+ if (std::strstr(typer_->error_message(), error_message) == nullptr) {
+ std::cerr << "Asm validation failed with the wrong error message:\n"
+ "Expected to contain '"
+ << error_message << "'\n"
+ " Actually is '"
+ << typer_->error_message() << "'\n";
+ return false;
+ }
+
+ return true;
+ }
+
+ private:
+ Variable* DeclareVariable(VariableName var_name) {
+ auto* name_ast_string = ast_value_factory_.GetOneByteString(var_name.name_);
+ return var_name.mode_ == DYNAMIC_GLOBAL
+ ? outer_scope_->DeclareDynamicGlobal(name_ast_string)
+ : module_->scope()->DeclareLocal(name_ast_string, VAR,
+ kCreatedInitialized,
+ Variable::NORMAL);
+ }
+
+ std::string source_;
+ ValidationType validation_type_;
+ HandleAndZoneScope handles_;
+ Zone* zone_;
+ Isolate* isolate_;
+ AstValueFactory ast_value_factory_;
+ Factory* factory_;
+ Handle<String> source_code_;
+ Handle<Script> script_;
+
+ Scope* outer_scope_;
+ FunctionLiteral* module_;
+ std::unique_ptr<AsmTyper> typer_;
+};
+
+} // namespace wasm
+} // namespace internal
+} // namespace v8
+
+namespace {
+
+struct ValidationInput {
+ ValidationInput(const std::string& source, iw::ValidationType type)
+ : source_(source), type_(type) {}
+
+ const std::string source_;
+ const iw::ValidationType type_;
+};
+
+std::unique_ptr<iw::AsmTyperHarnessBuilder> ValidationOf(
+ ValidationInput input) {
+ return std::unique_ptr<iw::AsmTyperHarnessBuilder>(
+ new iw::AsmTyperHarnessBuilder(input.source_.c_str(), input.type_));
+}
+
+ValidationInput Module(const char* source) {
+ return ValidationInput(source, iw::ValidateModule);
+}
+
+std::string WrapInFunction(const char* source, bool needs_use_asm) {
+ if (needs_use_asm) {
+ return std::string(
+ "function foo() {\n"
+ " 'use asm';\n"
+ " ") +
+ source +
+ "\n"
+ "}";
+ }
+
+ return std::string(
+ "function foo() {\n"
+ " ") +
+ source +
+ "\n"
+ "}";
+}
+
+ValidationInput Globals(const char* source) {
+ static const bool kNeedsUseAsm = true;
+ return ValidationInput(WrapInFunction(source, kNeedsUseAsm),
+ iw::ValidateGlobals);
+}
+
+ValidationInput FunctionTables(const char* source) {
+ static const bool kNeedsUseAsm = true;
+ return ValidationInput(WrapInFunction(source, kNeedsUseAsm),
+ iw::ValidateFunctionTables);
+}
+
+ValidationInput Export(const char* source) {
+ static const bool kNeedsUseAsm = true;
+ return ValidationInput(WrapInFunction(source, kNeedsUseAsm),
+ iw::ValidateExport);
+}
+
+iw::AsmTyperHarnessBuilder::VariableName Var(const char* name) {
+ return iw::AsmTyperHarnessBuilder::VariableName(name, VAR);
+}
+
+iw::AsmTyperHarnessBuilder::VariableName DynamicGlobal(const char* name) {
+ return iw::AsmTyperHarnessBuilder::VariableName(name, DYNAMIC_GLOBAL);
+}
+
+TEST(MissingUseAsmDirective) {
+ v8::V8::Initialize();
+
+ // We can't test the empty input ("") because the AsmTyperHarnessBuilder will
+ // CHECK if there's no function in the top-level scope.
+ const char* kTests[] = {"function module(){}",
+ "function module(){ use_asm; }",
+ "function module(){ \"use asm \"; }",
+ "function module(){ \" use asm \"; }",
+ "function module(){ \"use Asm\"; }"};
+
+ for (size_t ii = 0; ii < arraysize(kTests); ++ii) {
+ const char* module = kTests[ii];
+ if (!ValidationOf(Module(module))
+ ->FailsWithMessage("missing \"use asm\"")) {
+ std::cerr << "Test:\n" << module;
+ CHECK(false);
+ }
+ }
+}
+
+TEST(InvalidModuleSignature) {
+ v8::V8::Initialize();
+
+ const struct {
+ const char* module;
+ const char* error_message;
+ } kTests[] = {
+ {"function eval(){ \"use asm\"; }",
+ "Invalid ASM.js identifier in module name"},
+ {"function arguments(){ \"use asm\"; }",
+ "Invalid ASM.js identifier in module name"},
+ {"function module(eval){ \"use asm\"; }",
+ "Invalid ASM.js identifier in module parameter"},
+ {"function module(arguments){ \"use asm\"; }",
+ "Invalid ASM.js identifier in module parameter"},
+ {"function module(stdlib, eval){ \"use asm\"; }",
+ "Invalid ASM.js identifier in module parameter"},
+ {"function module(stdlib, arguments){ \"use asm\"; }",
+ "Invalid ASM.js identifier in module parameter"},
+ {"function module(stdlib, foreign, eval){ \"use asm\"; }",
+ "Invalid ASM.js identifier in module parameter"},
+ {"function module(stdlib, foreign, arguments){ \"use asm\"; }",
+ "Invalid ASM.js identifier in module parameter"},
+ {"function module(stdlib, foreign, heap, eval){ \"use asm\"; }",
+ "ASM.js modules may not have more than three parameters"},
+ {"function module(stdlib, foreign, heap, arguments){ \"use asm\"; }",
+ "ASM.js modules may not have more than three parameters"},
+ {"function module(module){ \"use asm\"; }",
+ "Redeclared identifier in module parameter"},
+ {"function module(stdlib, module){ \"use asm\"; }",
+ "Redeclared identifier in module parameter"},
+ {"function module(stdlib, stdlib){ \"use asm\"; }",
+ "Redeclared identifier in module parameter"},
+ {"function module(stdlib, foreign, module){ \"use asm\"; }",
+ "Redeclared identifier in module parameter"},
+ {"function module(stdlib, foreign, stdlib){ \"use asm\"; }",
+ "Redeclared identifier in module parameter"},
+ {"function module(stdlib, foreign, foreign){ \"use asm\"; }",
+ "Redeclared identifier in module parameter"},
+ };
+
+ for (size_t ii = 0; ii < arraysize(kTests); ++ii) {
+ const auto* test = kTests + ii;
+ if (!ValidationOf(Module(test->module))
+ ->FailsWithMessage(test->error_message)) {
+ std::cerr << "Test:\n" << test->module;
+ CHECK(false);
+ }
+ }
+}
+
+TEST(ErrorsInGlobalVariableDefinition) {
+ const struct {
+ const char* decl;
+ const char* error_message;
+ } kTests[] = {
+ {"var v;", "Global variable missing initializer"},
+ {"var v = uninitialized;", "Invalid global variable initializer"},
+ {"var v = 'use asm';", "type annotation - forbidden literal"},
+ {"var v = 4294967296;", " - forbidden literal"},
+ {"var v = not_fround;", "Invalid global variable initializer"},
+ {"var v = not_fround(1);", "expected call fround(literal)"},
+ {"var v = __fround__(1.0);", "expected call fround(literal)"},
+ {"var v = fround(1.0, 1.0);", "expected call fround(literal)"},
+ {"var v = fround(not_fround);", "literal argument for call to fround"},
+ {"var v = fround(1);", "literal argument to be a floating point"},
+ {"var v = stdlib.nan", "Invalid import"},
+ {"var v = stdlib.Math.nan", "Invalid import"},
+ {"var v = stdlib.Mathh.E", "Invalid import"},
+ {"var v = stdlib.Math", "Invalid import"},
+ {"var v = Stdlib.Math.E", "Invalid import"},
+ {"var v = stdlib.Math.E[0]", "Invalid import"},
+ {"var v = stdlibb.NaN", "Invalid import"},
+ {"var v = ffi.NaN[0]", "Invalid import"},
+ {"var v = heap.NaN[0]", "Invalid import"},
+ {"var v = ffi.foo * 2.0;", "unrecognized annotation"},
+ {"var v = ffi.foo|1;", "unrecognized annotation"},
+ {"var v = ffi()|0;", "must import member"},
+ {"var v = +ffi();", "must import member"},
+ {"var v = ffi().a|0;", "object lookup failed"},
+ {"var v = +ffi().a;", "object lookup failed"},
+ {"var v = sstdlib.a|0;", "object lookup failed"},
+ {"var v = +sstdlib.a;", "object lookup failed"},
+ {"var v = stdlib.NaN|0;", "object is not the ffi"},
+ {"var v = +stdlib.NaN;", "object is not the ffi"},
+ {"var v = new f()", "Invalid type after new"},
+ {"var v = new stdli.Uint8Array(heap)", "Unknown stdlib member in heap"},
+ {"var v = new stdlib.dd(heap)", "Unknown stdlib member in heap"},
+ {"var v = new stdlib.Math.fround(heap)", "Type is not a heap view type"},
+ {"var v = new stdlib.Uint8Array(a, b)", "Invalid number of arguments"},
+ {"var v = new stdlib.Uint8Array(heap())", "should be the module's heap"},
+ {"var v = new stdlib.Uint8Array(heap_)", "instead of heap parameter"},
+ {"var v = new stdlib.Uint8Array(ffi)", "should be the module's heap"},
+ {"var eval = 0;", "in global variable"},
+ {"var eval = 0.0;", "in global variable"},
+ {"var eval = fround(0.0);", "in global variable"},
+ {"var eval = +ffi.a;", "in global variable"},
+ {"var eval = ffi.a|0;", "in global variable"},
+ {"var eval = ffi.a;", "in global variable"},
+ {"var eval = new stdlib.Uint8Array(heap);", "in global variable"},
+ {"var arguments = 0;", "in global variable"},
+ {"var arguments = 0.0;", "in global variable"},
+ {"var arguments = fround(0.0);", "in global variable"},
+ {"var arguments = +ffi.a;", "in global variable"},
+ {"var arguments = ffi.a|0;", "in global variable"},
+ {"var arguments = ffi.a;", "in global variable"},
+ {"var arguments = new stdlib.Uint8Array(heap);", "in global variable"},
+ {"var a = 0, a = 0.0;", "Redefined global variable"},
+ {"var a = 0; var a = 0;", "Redefined global variable"},
+ {"var a = 0, b = 0; var a = 0;", "Redefined global variable"},
+ {"var a = 0, b = 0; var b = 0, a = 0.0;", "Redefined global variable"},
+ };
+
+ for (size_t ii = 0; ii < arraysize(kTests); ++ii) {
+ const auto* test = kTests + ii;
+ if (!ValidationOf(Globals(test->decl))
+ ->WithStdlib(DynamicGlobal("stdlib"))
+ ->WithFFI(DynamicGlobal("ffi"))
+ ->WithHeap(DynamicGlobal("heap"))
+ ->WithGlobal(DynamicGlobal("not_fround"), iw::AsmType::Int())
+ ->WithImport(DynamicGlobal("fround"), iw::AsmTyper::kMathFround)
+ ->FailsWithMessage(test->error_message)) {
+ std::cerr << "Test:\n" << test->decl;
+ CHECK(false);
+ }
+ }
+}
+
+TEST(ErrorsInFunctionTableDefinition) {
+ const struct {
+ const char* tables;
+ const char* error_message;
+ } kTests[] = {
+ {"var a = [a, a, a];", "Invalid length for function pointer table"},
+ {"var a = [d2s0()];", "must be a function name"},
+ {"var a = [d2s44];", "Undefined identifier in function pointer"},
+ {"var a = [fround];", "not be a member of the standard library"},
+ {"var a = [imul];", "not be a member of the standard library"},
+ {"var a = [ffi_import];", "must be an ASM.js function"},
+ {"var a = [dI];", "must be an ASM.js function"},
+ {"var a = [d2s0, d2s1, d2s0, f2s0];", "mismatch in function pointer"},
+ {"var eval = [d2s0, d2s1];", "ASM.js identifier in function table name"},
+ {"var arguments = [d2s0, d2s1];", "ASM.js identifier in function table"},
+ {"var foo = [d2s0, d2s1];", "Identifier redefined in function table"},
+ {"var I = [d2s0, d2s1];", "Identifier redefined in function table name"},
+ {"var d2s = [d2f0, d2f1];", "redeclared as function pointer table"},
+ {"var d2s_t = [d2s0];", "Function table size mismatch"},
+ {"var d2s_t = [d2f0, d2sf];", "initializer does not match previous"},
+ };
+
+ auto d2s = [](Zone* zone) -> iw::AsmType* {
+ auto* ret = iw::AsmType::Function(zone, iw::AsmType::Signed());
+ ret->AsFunctionType()->AddArgument(iw::AsmType::Double());
+ return ret;
+ };
+
+ auto d2s_tbl = [](Zone* zone) -> iw::AsmType* {
+ auto* d2s = iw::AsmType::Function(zone, iw::AsmType::Signed());
+ d2s->AsFunctionType()->AddArgument(iw::AsmType::Double());
+
+ auto* ret = iw::AsmType::FunctionTableType(zone, 2, d2s);
+ return ret;
+ };
+
+ auto f2s = [](Zone* zone) -> iw::AsmType* {
+ auto* ret = iw::AsmType::Function(zone, iw::AsmType::Signed());
+ ret->AsFunctionType()->AddArgument(iw::AsmType::Float());
+ return ret;
+ };
+
+ auto d2f = [](Zone* zone) -> iw::AsmType* {
+ auto* ret = iw::AsmType::Function(zone, iw::AsmType::Float());
+ ret->AsFunctionType()->AddArgument(iw::AsmType::Double());
+ return ret;
+ };
+
+ for (size_t ii = 0; ii < arraysize(kTests); ++ii) {
+ const auto* test = kTests + ii;
+ if (!ValidationOf(FunctionTables(test->tables))
+ ->WithImport(DynamicGlobal("ffi_import"), iw::AsmTyper::kFFI)
+ ->WithImport(DynamicGlobal("imul"), iw::AsmTyper::kMathImul)
+ ->WithImport(DynamicGlobal("E"), iw::AsmTyper::kMathE)
+ ->WithImport(DynamicGlobal("fround"), iw::AsmTyper::kMathFround)
+ ->WithImport(DynamicGlobal("floor"), iw::AsmTyper::kMathFround)
+ ->WithGlobal(DynamicGlobal("d2s0"), d2s)
+ ->WithGlobal(DynamicGlobal("d2s1"), d2s)
+ ->WithGlobal(DynamicGlobal("f2s0"), f2s)
+ ->WithGlobal(DynamicGlobal("f2s1"), f2s)
+ ->WithGlobal(DynamicGlobal("d2f0"), d2f)
+ ->WithGlobal(DynamicGlobal("d2f1"), d2f)
+ ->WithGlobal(DynamicGlobal("dI"), iw::AsmType::Int())
+ ->WithGlobal(Var("I"), iw::AsmType::Int())
+ ->WithUndefinedGlobal(Var("d2s"), d2s)
+ ->WithUndefinedGlobal(Var("d2s_t"), d2s_tbl)
+ ->FailsWithMessage(test->error_message)) {
+ std::cerr << "Test:\n" << test->tables;
+ CHECK(false);
+ }
+ }
+}
+
+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.
+ const struct {
+ const char* module_export;
+ const char* error_message;
+ } kTests[] = {
+ {"", "Missing ASM.js module export"},
+ {"return;", "Unrecognized expression in ASM.js module export expression"},
+ {"return d2s_tbl;", "is not an ASM.js function"},
+ {"return min;", "is not an ASM.js function"},
+ {"return I;", "is not an ASM.js function"},
+ {"return {\'a\': d2s_tbl}", "export property is not an ASM.js"},
+ {"return {\'a\': min}", "export cannot contain standard library"},
+ {"return {\'a\': f()}", "must be an ASM.js function name"},
+ {"return {\'a\': f}", "in ASM.js module export property"},
+ {"function v() { a(); } return {b: d2s}", "Missing definition for forw"},
+ {"return {b: d2s, \'a\': d2s_tbl}", "export property is not an ASM.js"},
+ {"return {b: d2s, \'a\': min}", "export cannot contain standard library"},
+ {"return {b: d2s, \'a\': f()}", "must be an ASM.js function name"},
+ {"return {b: d2s, \'a\': f}", "in ASM.js module export property"},
+ };
+
+ auto d2s_tbl = [](Zone* zone) -> iw::AsmType* {
+ auto* d2s = iw::AsmType::Function(zone, iw::AsmType::Signed());
+ d2s->AsFunctionType()->AddArgument(iw::AsmType::Double());
+
+ auto* ret = iw::AsmType::FunctionTableType(zone, 2, d2s);
+ return ret;
+ };
+
+ auto d2s = [](Zone* zone) -> iw::AsmType* {
+ auto* ret = iw::AsmType::Function(zone, iw::AsmType::Signed());
+ ret->AsFunctionType()->AddArgument(iw::AsmType::Double());
+ return ret;
+ };
+
+ for (size_t ii = 0; ii < arraysize(kTests); ++ii) {
+ const auto* test = kTests + ii;
+ if (!ValidationOf(Export(test->module_export))
+ ->WithGlobal(DynamicGlobal("d2s_tbl"), d2s_tbl)
+ ->WithGlobal(DynamicGlobal("d2s"), d2s)
+ ->WithImport(DynamicGlobal("min"), iw::AsmTyper::kMathMin)
+ ->WithGlobal(DynamicGlobal("I"), iw::AsmType::Int())
+ ->FailsWithMessage(test->error_message)) {
+ std::cerr << "Test:\n" << test->module_export;
+ CHECK(false);
+ }
+ }
+}
+
+} // namespace
« 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