summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/validator.cc889
1 files changed, 460 insertions, 429 deletions
diff --git a/src/validator.cc b/src/validator.cc
index d9179ba5..16a1f7ca 100644
--- a/src/validator.cc
+++ b/src/validator.cc
@@ -30,62 +30,141 @@ namespace wabt {
namespace {
-enum class ActionResultKind {
- Error,
- Types,
- Type,
-};
-
-struct ActionResult {
- ActionResultKind kind;
- union {
- const TypeVector* types;
- Type type;
+class Validator {
+ public:
+ WABT_DISALLOW_COPY_AND_ASSIGN(Validator);
+ Validator(SourceErrorHandler*, WastLexer*, const Script*);
+
+ Result CheckScript(const Script* script);
+
+ private:
+ struct ActionResult {
+ enum class Kind {
+ Error,
+ Types,
+ Type,
+ } kind;
+
+ union {
+ const TypeVector* types;
+ Type type;
+ };
};
-};
-
-struct Context {
- WABT_DISALLOW_COPY_AND_ASSIGN(Context);
- Context(SourceErrorHandler*, WastLexer*, const Script*);
+ void WABT_PRINTF_FORMAT(3, 4)
+ PrintError(const Location* loc, const char* fmt, ...);
void OnTypecheckerError(const char* msg);
-
- SourceErrorHandler* error_handler = nullptr;
- WastLexer* lexer = nullptr;
- const Script* script = nullptr;
- const Module* current_module = nullptr;
- const Func* current_func = nullptr;
- Index current_table_index = 0;
- Index current_memory_index = 0;
- Index current_global_index = 0;
- Index num_imported_globals = 0;
- TypeChecker typechecker;
+ Result CheckVar(Index max_index,
+ const Var* var,
+ const char* desc,
+ Index* out_index);
+ Result CheckFuncVar(const Var* var, const Func** out_func);
+ Result CheckGlobalVar(const Var* var,
+ const Global** out_global,
+ Index* out_global_index);
+ Type GetGlobalVarTypeOrAny(const Var* var);
+ Result CheckFuncTypeVar(const Var* var, const FuncType** out_func_type);
+ Result CheckTableVar(const Var* var, const Table** out_table);
+ Result CheckMemoryVar(const Var* var, const Memory** out_memory);
+ Result CheckLocalVar(const Var* var, Type* out_type);
+ Type GetLocalVarTypeOrAny(const Var* var);
+ void CheckAlign(const Location* loc,
+ Address alignment,
+ Address natural_alignment);
+ void CheckOffset(const Location* loc, uint64_t offset);
+ void CheckType(const Location* loc,
+ Type actual,
+ Type expected,
+ const char* desc);
+ void CheckTypeIndex(const Location* loc,
+ Type actual,
+ Type expected,
+ const char* desc,
+ Index index,
+ const char* index_kind);
+ void CheckTypes(const Location* loc,
+ const TypeVector& actual,
+ const TypeVector& expected,
+ const char* desc,
+ const char* index_kind);
+ void CheckConstTypes(const Location* loc,
+ const TypeVector& actual,
+ const ConstVector& expected,
+ const char* desc);
+ void CheckConstType(const Location* loc,
+ Type actual,
+ const ConstVector& expected,
+ const char* desc);
+ void CheckAssertReturnNanType(const Location* loc,
+ Type actual,
+ const char* desc);
+ void CheckExprList(const Location* loc, const Expr* first);
+ void CheckHasMemory(const Location* loc, Opcode opcode);
+ void CheckExpr(const Expr* expr);
+ void CheckFuncSignatureMatchesFuncType(const Location* loc,
+ const FuncSignature& sig,
+ const FuncType* func_type);
+ void CheckFunc(const Location* loc, const Func* func);
+ void PrintConstExprError(const Location* loc, const char* desc);
+ void CheckConstInitExpr(const Location* loc,
+ const Expr* expr,
+ Type expected_type,
+ const char* desc);
+ void CheckGlobal(const Location* loc, const Global* global);
+ void CheckLimits(const Location* loc,
+ const Limits* limits,
+ uint64_t absolute_max,
+ const char* desc);
+ void CheckTable(const Location* loc, const Table* table);
+ void CheckElemSegments(const Module* module);
+ void CheckMemory(const Location* loc, const Memory* memory);
+ void CheckDataSegments(const Module* module);
+ void CheckImport(const Location* loc, const Import* import);
+ void CheckExport(const Export* export_);
+
+ void OnDuplicateBinding(const BindingHash::value_type& a,
+ const BindingHash::value_type& b);
+ void CheckDuplicateExportBindings(const Module* module);
+ void CheckModule(const Module* module);
+ const TypeVector* CheckInvoke(const Action* action);
+ Result CheckGet(const Action* action, Type* out_type);
+ ActionResult CheckAction(const Action* action);
+ void CheckAssertReturnNanCommand(const Action* action);
+ void CheckCommand(const Command* command);
+
+ SourceErrorHandler* error_handler_ = nullptr;
+ WastLexer* lexer_ = nullptr;
+ const Script* script_ = nullptr;
+ const Module* current_module_ = nullptr;
+ const Func* current_func_ = nullptr;
+ Index current_table_index_ = 0;
+ Index current_memory_index_ = 0;
+ Index current_global_index_ = 0;
+ Index num_imported_globals_ = 0;
+ TypeChecker typechecker_;
// Cached for access by OnTypecheckerError.
- const Location* expr_loc = nullptr;
- Result result = Result::Ok;
+ const Location* expr_loc_ = nullptr;
+ Result result_ = Result::Ok;
};
-Context::Context(SourceErrorHandler* error_handler,
- WastLexer* lexer,
- const Script* script)
- : error_handler(error_handler), lexer(lexer), script(script) {
- typechecker.set_error_callback(
+Validator::Validator(SourceErrorHandler* error_handler,
+ WastLexer* lexer,
+ const Script* script)
+ : error_handler_(error_handler), lexer_(lexer), script_(script) {
+ typechecker_.set_error_callback(
[this](const char* msg) { OnTypecheckerError(msg); });
}
-} // namespace
-
-static void WABT_PRINTF_FORMAT(3, 4)
- print_error(Context* ctx, const Location* loc, const char* fmt, ...) {
- ctx->result = Result::Error;
+void Validator::PrintError(const Location* loc, const char* fmt, ...) {
+ result_ = Result::Error;
va_list args;
va_start(args, fmt);
- wast_format_error(ctx->error_handler, loc, ctx->lexer, fmt, args);
+ wast_format_error(error_handler_, loc, lexer_, fmt, args);
va_end(args);
}
-void Context::OnTypecheckerError(const char* msg) {
- print_error(this, expr_loc, "%s", msg);
+void Validator::OnTypecheckerError(const char* msg) {
+ PrintError(expr_loc_, "%s", msg);
}
static bool is_power_of_two(uint32_t x) {
@@ -98,104 +177,95 @@ static Address get_opcode_natural_alignment(Opcode opcode) {
return memory_size;
}
-static Result check_var(Context* ctx,
- Index max_index,
- const Var* var,
- const char* desc,
- Index* out_index) {
+Result Validator::CheckVar(Index max_index,
+ const Var* var,
+ const char* desc,
+ Index* out_index) {
assert(var->type == VarType::Index);
if (var->index < max_index) {
if (out_index)
*out_index = var->index;
return Result::Ok;
}
- print_error(ctx, &var->loc, "%s variable out of range (max %" PRIindex ")",
- desc, max_index);
+ PrintError(&var->loc, "%s variable out of range (max %" PRIindex ")", desc,
+ max_index);
return Result::Error;
}
-static Result check_func_var(Context* ctx,
- const Var* var,
- const Func** out_func) {
+Result Validator::CheckFuncVar(const Var* var, const Func** out_func) {
Index index;
- if (WABT_FAILED(check_var(ctx, ctx->current_module->funcs.size(), var,
- "function", &index))) {
+ if (WABT_FAILED(
+ CheckVar(current_module_->funcs.size(), var, "function", &index))) {
return Result::Error;
}
if (out_func)
- *out_func = ctx->current_module->funcs[index];
+ *out_func = current_module_->funcs[index];
return Result::Ok;
}
-static Result check_global_var(Context* ctx,
- const Var* var,
- const Global** out_global,
- Index* out_global_index) {
+Result Validator::CheckGlobalVar(const Var* var,
+ const Global** out_global,
+ Index* out_global_index) {
Index index;
- if (WABT_FAILED(check_var(ctx, ctx->current_module->globals.size(), var,
- "global", &index))) {
+ if (WABT_FAILED(
+ CheckVar(current_module_->globals.size(), var, "global", &index))) {
return Result::Error;
}
if (out_global)
- *out_global = ctx->current_module->globals[index];
+ *out_global = current_module_->globals[index];
if (out_global_index)
*out_global_index = index;
return Result::Ok;
}
-static Type get_global_var_type_or_any(Context* ctx, const Var* var) {
+Type Validator::GetGlobalVarTypeOrAny(const Var* var) {
const Global* global;
- if (WABT_SUCCEEDED(check_global_var(ctx, var, &global, nullptr)))
+ if (WABT_SUCCEEDED(CheckGlobalVar(var, &global, nullptr)))
return global->type;
return Type::Any;
}
-static Result check_func_type_var(Context* ctx,
- const Var* var,
- const FuncType** out_func_type) {
+Result Validator::CheckFuncTypeVar(const Var* var,
+ const FuncType** out_func_type) {
Index index;
- if (WABT_FAILED(check_var(ctx, ctx->current_module->func_types.size(), var,
- "function type", &index))) {
+ if (WABT_FAILED(CheckVar(current_module_->func_types.size(), var,
+ "function type", &index))) {
return Result::Error;
}
if (out_func_type)
- *out_func_type = ctx->current_module->func_types[index];
+ *out_func_type = current_module_->func_types[index];
return Result::Ok;
}
-static Result check_table_var(Context* ctx,
- const Var* var,
- const Table** out_table) {
+Result Validator::CheckTableVar(const Var* var, const Table** out_table) {
Index index;
- if (WABT_FAILED(check_var(ctx, ctx->current_module->tables.size(), var,
- "table", &index))) {
+ if (WABT_FAILED(
+ CheckVar(current_module_->tables.size(), var, "table", &index))) {
return Result::Error;
}
if (out_table)
- *out_table = ctx->current_module->tables[index];
+ *out_table = current_module_->tables[index];
return Result::Ok;
}
-static Result check_memory_var(Context* ctx,
- const Var* var,
- const Memory** out_memory) {
+Result Validator::CheckMemoryVar(const Var* var, const Memory** out_memory) {
Index index;
- if (WABT_FAILED(check_var(ctx, ctx->current_module->memories.size(), var,
- "memory", &index))) {
+ if (WABT_FAILED(
+ CheckVar(current_module_->memories.size(), var, "memory", &index))) {
return Result::Error;
}
if (out_memory)
- *out_memory = ctx->current_module->memories[index];
+ *out_memory = current_module_->memories[index];
return Result::Ok;
}
-static Result check_local_var(Context* ctx, const Var* var, Type* out_type) {
- const Func* func = ctx->current_func;
+Result Validator::CheckLocalVar(const Var* var, Type* out_type) {
+ const Func* func = current_func_;
Index max_index = get_num_params_and_locals(func);
Index index = get_local_index_by_var(func, var);
if (index < max_index) {
@@ -204,359 +274,334 @@ static Result check_local_var(Context* ctx, const Var* var, Type* out_type) {
if (index < num_params) {
*out_type = get_param_type(func, index);
} else {
- *out_type = ctx->current_func->local_types[index - num_params];
+ *out_type = current_func_->local_types[index - num_params];
}
}
return Result::Ok;
}
if (var->type == VarType::Name) {
- print_error(ctx, &var->loc,
- "undefined local variable \"" PRIstringslice "\"",
- WABT_PRINTF_STRING_SLICE_ARG(var->name));
+ PrintError(&var->loc, "undefined local variable \"" PRIstringslice "\"",
+ WABT_PRINTF_STRING_SLICE_ARG(var->name));
} else {
- print_error(ctx, &var->loc,
- "local variable out of range (max %" PRIindex ")", max_index);
+ PrintError(&var->loc, "local variable out of range (max %" PRIindex ")",
+ max_index);
}
return Result::Error;
}
-static Type get_local_var_type_or_any(Context* ctx, const Var* var) {
+Type Validator::GetLocalVarTypeOrAny(const Var* var) {
Type type = Type::Any;
- check_local_var(ctx, var, &type);
+ CheckLocalVar(var, &type);
return type;
}
-static void check_align(Context* ctx,
- const Location* loc,
- Address alignment,
- Address natural_alignment) {
+void Validator::CheckAlign(const Location* loc,
+ Address alignment,
+ Address natural_alignment) {
if (alignment != WABT_USE_NATURAL_ALIGNMENT) {
if (!is_power_of_two(alignment))
- print_error(ctx, loc, "alignment must be power-of-two");
+ PrintError(loc, "alignment must be power-of-two");
if (alignment > natural_alignment) {
- print_error(ctx, loc,
- "alignment must not be larger than natural alignment (%u)",
- natural_alignment);
+ PrintError(loc,
+ "alignment must not be larger than natural alignment (%u)",
+ natural_alignment);
}
}
}
-static void check_offset(Context* ctx, const Location* loc, uint64_t offset) {
+void Validator::CheckOffset(const Location* loc, uint64_t offset) {
if (offset > UINT32_MAX) {
- print_error(ctx, loc, "offset must be less than or equal to 0xffffffff");
+ PrintError(loc, "offset must be less than or equal to 0xffffffff");
}
}
-static void check_type(Context* ctx,
- const Location* loc,
- Type actual,
- Type expected,
- const char* desc) {
+void Validator::CheckType(const Location* loc,
+ Type actual,
+ Type expected,
+ const char* desc) {
if (expected != actual) {
- print_error(ctx, loc, "type mismatch at %s. got %s, expected %s", desc,
- get_type_name(actual), get_type_name(expected));
+ PrintError(loc, "type mismatch at %s. got %s, expected %s", desc,
+ get_type_name(actual), get_type_name(expected));
}
}
-static void check_type_index(Context* ctx,
- const Location* loc,
- Type actual,
- Type expected,
- const char* desc,
- Index index,
- const char* index_kind) {
+void Validator::CheckTypeIndex(const Location* loc,
+ Type actual,
+ Type expected,
+ const char* desc,
+ Index index,
+ const char* index_kind) {
if (expected != actual && expected != Type::Any && actual != Type::Any) {
- print_error(ctx, loc,
- "type mismatch for %s %" PRIindex " of %s. got %s, expected %s",
- index_kind, index, desc, get_type_name(actual),
- get_type_name(expected));
+ PrintError(loc,
+ "type mismatch for %s %" PRIindex " of %s. got %s, expected %s",
+ index_kind, index, desc, get_type_name(actual),
+ get_type_name(expected));
}
}
-static void check_types(Context* ctx,
- const Location* loc,
- const TypeVector& actual,
- const TypeVector& expected,
- const char* desc,
- const char* index_kind) {
+void Validator::CheckTypes(const Location* loc,
+ const TypeVector& actual,
+ const TypeVector& expected,
+ const char* desc,
+ const char* index_kind) {
if (actual.size() == expected.size()) {
for (size_t i = 0; i < actual.size(); ++i) {
- check_type_index(ctx, loc, actual[i], expected[i], desc, i, index_kind);
+ CheckTypeIndex(loc, actual[i], expected[i], desc, i, index_kind);
}
} else {
- print_error(ctx, loc, "expected %" PRIzd " %ss, got %" PRIzd,
- expected.size(), index_kind, actual.size());
+ PrintError(loc, "expected %" PRIzd " %ss, got %" PRIzd, expected.size(),
+ index_kind, actual.size());
}
}
-static void check_const_types(Context* ctx,
- const Location* loc,
- const TypeVector& actual,
- const ConstVector& expected,
- const char* desc) {
+void Validator::CheckConstTypes(const Location* loc,
+ const TypeVector& actual,
+ const ConstVector& expected,
+ const char* desc) {
if (actual.size() == expected.size()) {
for (size_t i = 0; i < actual.size(); ++i) {
- check_type_index(ctx, loc, actual[i], expected[i].type, desc, i,
- "result");
+ CheckTypeIndex(loc, actual[i], expected[i].type, desc, i, "result");
}
} else {
- print_error(ctx, loc, "expected %" PRIzd " results, got %" PRIzd,
- expected.size(), actual.size());
+ PrintError(loc, "expected %" PRIzd " results, got %" PRIzd, expected.size(),
+ actual.size());
}
}
-static void check_const_type(Context* ctx,
- const Location* loc,
- Type actual,
- const ConstVector& expected,
- const char* desc) {
+void Validator::CheckConstType(const Location* loc,
+ Type actual,
+ const ConstVector& expected,
+ const char* desc) {
TypeVector actual_types;
if (actual != Type::Void)
actual_types.push_back(actual);
- check_const_types(ctx, loc, actual_types, expected, desc);
+ CheckConstTypes(loc, actual_types, expected, desc);
}
-static void check_assert_return_nan_type(Context* ctx,
- const Location* loc,
+void Validator::CheckAssertReturnNanType(const Location* loc,
Type actual,
const char* desc) {
- /* when using assert_return_nan, the result can be either a f32 or f64 type
- * so we special case it here. */
+ // When using assert_return_nan, the result can be either a f32 or f64 type
+ // so we special case it here.
if (actual != Type::F32 && actual != Type::F64) {
- print_error(ctx, loc, "type mismatch at %s. got %s, expected f32 or f64",
- desc, get_type_name(actual));
+ PrintError(loc, "type mismatch at %s. got %s, expected f32 or f64", desc,
+ get_type_name(actual));
}
}
-static void check_expr(Context* ctx, const Expr* expr);
-
-static void check_expr_list(Context* ctx,
- const Location* loc,
- const Expr* first) {
+void Validator::CheckExprList(const Location* loc, const Expr* first) {
if (first) {
for (const Expr* expr = first; expr; expr = expr->next)
- check_expr(ctx, expr);
+ CheckExpr(expr);
}
}
-static void check_has_memory(Context* ctx, const Location* loc, Opcode opcode) {
- if (ctx->current_module->memories.size() == 0) {
- print_error(ctx, loc, "%s requires an imported or defined memory.",
- get_opcode_name(opcode));
+void Validator::CheckHasMemory(const Location* loc, Opcode opcode) {
+ if (current_module_->memories.size() == 0) {
+ PrintError(loc, "%s requires an imported or defined memory.",
+ get_opcode_name(opcode));
}
}
-static void check_expr(Context* ctx, const Expr* expr) {
- ctx->expr_loc = &expr->loc;
+void Validator::CheckExpr(const Expr* expr) {
+ expr_loc_ = &expr->loc;
switch (expr->type) {
case ExprType::Binary:
- ctx->typechecker.OnBinary(expr->binary.opcode);
+ typechecker_.OnBinary(expr->binary.opcode);
break;
case ExprType::Block:
- ctx->typechecker.OnBlock(&expr->block->sig);
- check_expr_list(ctx, &expr->loc, expr->block->first);
- ctx->typechecker.OnEnd();
+ typechecker_.OnBlock(&expr->block->sig);
+ CheckExprList(&expr->loc, expr->block->first);
+ typechecker_.OnEnd();
break;
case ExprType::Br:
- ctx->typechecker.OnBr(expr->br.var.index);
+ typechecker_.OnBr(expr->br.var.index);
break;
case ExprType::BrIf:
- ctx->typechecker.OnBrIf(expr->br_if.var.index);
+ typechecker_.OnBrIf(expr->br_if.var.index);
break;
case ExprType::BrTable: {
- ctx->typechecker.BeginBrTable();
- for (Var& var: *expr->br_table.targets) {
- ctx->typechecker.OnBrTableTarget(var.index);
+ typechecker_.BeginBrTable();
+ for (Var& var : *expr->br_table.targets) {
+ typechecker_.OnBrTableTarget(var.index);
}
- ctx->typechecker.OnBrTableTarget(expr->br_table.default_target.index);
- ctx->typechecker.EndBrTable();
+ typechecker_.OnBrTableTarget(expr->br_table.default_target.index);
+ typechecker_.EndBrTable();
break;
}
case ExprType::Call: {
const Func* callee;
- if (WABT_SUCCEEDED(check_func_var(ctx, &expr->call.var, &callee))) {
- ctx->typechecker.OnCall(&callee->decl.sig.param_types,
- &callee->decl.sig.result_types);
+ if (WABT_SUCCEEDED(CheckFuncVar(&expr->call.var, &callee))) {
+ typechecker_.OnCall(&callee->decl.sig.param_types,
+ &callee->decl.sig.result_types);
}
break;
}
case ExprType::CallIndirect: {
const FuncType* func_type;
- if (ctx->current_module->tables.size() == 0) {
- print_error(ctx, &expr->loc,
- "found call_indirect operator, but no table");
+ if (current_module_->tables.size() == 0) {
+ PrintError(&expr->loc, "found call_indirect operator, but no table");
}
if (WABT_SUCCEEDED(
- check_func_type_var(ctx, &expr->call_indirect.var, &func_type))) {
- ctx->typechecker.OnCallIndirect(&func_type->sig.param_types,
- &func_type->sig.result_types);
+ CheckFuncTypeVar(&expr->call_indirect.var, &func_type))) {
+ typechecker_.OnCallIndirect(&func_type->sig.param_types,
+ &func_type->sig.result_types);
}
break;
}
case ExprType::Compare:
- ctx->typechecker.OnCompare(expr->compare.opcode);
+ typechecker_.OnCompare(expr->compare.opcode);
break;
case ExprType::Const:
- ctx->typechecker.OnConst(expr->const_.type);
+ typechecker_.OnConst(expr->const_.type);
break;
case ExprType::Convert:
- ctx->typechecker.OnConvert(expr->convert.opcode);
+ typechecker_.OnConvert(expr->convert.opcode);
break;
case ExprType::Drop:
- ctx->typechecker.OnDrop();
+ typechecker_.OnDrop();
break;
case ExprType::GetGlobal:
- ctx->typechecker.OnGetGlobal(
- get_global_var_type_or_any(ctx, &expr->get_global.var));
+ typechecker_.OnGetGlobal(GetGlobalVarTypeOrAny(&expr->get_global.var));
break;
case ExprType::GetLocal:
- ctx->typechecker.OnGetLocal(
- get_local_var_type_or_any(ctx, &expr->get_local.var));
+ typechecker_.OnGetLocal(GetLocalVarTypeOrAny(&expr->get_local.var));
break;
case ExprType::GrowMemory:
- check_has_memory(ctx, &expr->loc, Opcode::GrowMemory);
- ctx->typechecker.OnGrowMemory();
+ CheckHasMemory(&expr->loc, Opcode::GrowMemory);
+ typechecker_.OnGrowMemory();
break;
case ExprType::If:
- ctx->typechecker.OnIf(&expr->if_.true_->sig);
- check_expr_list(ctx, &expr->loc, expr->if_.true_->first);
+ typechecker_.OnIf(&expr->if_.true_->sig);
+ CheckExprList(&expr->loc, expr->if_.true_->first);
if (expr->if_.false_) {
- ctx->typechecker.OnElse();
- check_expr_list(ctx, &expr->loc, expr->if_.false_);
+ typechecker_.OnElse();
+ CheckExprList(&expr->loc, expr->if_.false_);
}
- ctx->typechecker.OnEnd();
+ typechecker_.OnEnd();
break;
case ExprType::Load:
- check_has_memory(ctx, &expr->loc, expr->load.opcode);
- check_align(ctx, &expr->loc, expr->load.align,
- get_opcode_natural_alignment(expr->load.opcode));
- check_offset(ctx, &expr->loc, expr->load.offset);
- ctx->typechecker.OnLoad(expr->load.opcode);
+ CheckHasMemory(&expr->loc, expr->load.opcode);
+ CheckAlign(&expr->loc, expr->load.align,
+ get_opcode_natural_alignment(expr->load.opcode));
+ CheckOffset(&expr->loc, expr->load.offset);
+ typechecker_.OnLoad(expr->load.opcode);
break;
case ExprType::Loop:
- ctx->typechecker.OnLoop(&expr->loop->sig);
- check_expr_list(ctx, &expr->loc, expr->loop->first);
- ctx->typechecker.OnEnd();
+ typechecker_.OnLoop(&expr->loop->sig);
+ CheckExprList(&expr->loc, expr->loop->first);
+ typechecker_.OnEnd();
break;
case ExprType::CurrentMemory:
- check_has_memory(ctx, &expr->loc, Opcode::CurrentMemory);
- ctx->typechecker.OnCurrentMemory();
+ CheckHasMemory(&expr->loc, Opcode::CurrentMemory);
+ typechecker_.OnCurrentMemory();
break;
case ExprType::Nop:
break;
case ExprType::Return:
- ctx->typechecker.OnReturn();
+ typechecker_.OnReturn();
break;
case ExprType::Select:
- ctx->typechecker.OnSelect();
+ typechecker_.OnSelect();
break;
case ExprType::SetGlobal:
- ctx->typechecker.OnSetGlobal(
- get_global_var_type_or_any(ctx, &expr->set_global.var));
+ typechecker_.OnSetGlobal(GetGlobalVarTypeOrAny(&expr->set_global.var));
break;
case ExprType::SetLocal:
- ctx->typechecker.OnSetLocal(
- get_local_var_type_or_any(ctx, &expr->set_local.var));
+ typechecker_.OnSetLocal(GetLocalVarTypeOrAny(&expr->set_local.var));
break;
case ExprType::Store:
- check_has_memory(ctx, &expr->loc, expr->store.opcode);
- check_align(ctx, &expr->loc, expr->store.align,
- get_opcode_natural_alignment(expr->store.opcode));
- check_offset(ctx, &expr->loc, expr->store.offset);
- ctx->typechecker.OnStore(expr->store.opcode);
+ CheckHasMemory(&expr->loc, expr->store.opcode);
+ CheckAlign(&expr->loc, expr->store.align,
+ get_opcode_natural_alignment(expr->store.opcode));
+ CheckOffset(&expr->loc, expr->store.offset);
+ typechecker_.OnStore(expr->store.opcode);
break;
case ExprType::TeeLocal:
- ctx->typechecker.OnTeeLocal(
- get_local_var_type_or_any(ctx, &expr->tee_local.var));
+ typechecker_.OnTeeLocal(GetLocalVarTypeOrAny(&expr->tee_local.var));
break;
case ExprType::Unary:
- ctx->typechecker.OnUnary(expr->unary.opcode);
+ typechecker_.OnUnary(expr->unary.opcode);
break;
case ExprType::Unreachable:
- ctx->typechecker.OnUnreachable();
+ typechecker_.OnUnreachable();
break;
}
}
-static void check_func_signature_matches_func_type(Context* ctx,
- const Location* loc,
- const FuncSignature& sig,
- const FuncType* func_type) {
- check_types(ctx, loc, sig.result_types, func_type->sig.result_types,
- "function", "result");
- check_types(ctx, loc, sig.param_types, func_type->sig.param_types, "function",
- "argument");
+void Validator::CheckFuncSignatureMatchesFuncType(const Location* loc,
+ const FuncSignature& sig,
+ const FuncType* func_type) {
+ CheckTypes(loc, sig.result_types, func_type->sig.result_types, "function",
+ "result");
+ CheckTypes(loc, sig.param_types, func_type->sig.param_types, "function",
+ "argument");
}
-static void check_func(Context* ctx, const Location* loc, const Func* func) {
- ctx->current_func = func;
+void Validator::CheckFunc(const Location* loc, const Func* func) {
+ current_func_ = func;
if (get_num_results(func) > 1) {
- print_error(ctx, loc, "multiple result values not currently supported.");
- /* don't run any other checks, the won't test the result_type properly */
+ PrintError(loc, "multiple result values not currently supported.");
+ // Don't run any other checks, the won't test the result_type properly.
return;
}
if (decl_has_func_type(&func->decl)) {
const FuncType* func_type;
- if (WABT_SUCCEEDED(
- check_func_type_var(ctx, &func->decl.type_var, &func_type))) {
- check_func_signature_matches_func_type(ctx, loc, func->decl.sig,
- func_type);
+ if (WABT_SUCCEEDED(CheckFuncTypeVar(&func->decl.type_var, &func_type))) {
+ CheckFuncSignatureMatchesFuncType(loc, func->decl.sig, func_type);
}
}
- ctx->expr_loc = loc;
- ctx->typechecker.BeginFunction(&func->decl.sig.result_types);
- check_expr_list(ctx, loc, func->first_expr);
- ctx->typechecker.EndFunction();
- ctx->current_func = nullptr;
+ expr_loc_ = loc;
+ typechecker_.BeginFunction(&func->decl.sig.result_types);
+ CheckExprList(loc, func->first_expr);
+ typechecker_.EndFunction();
+ current_func_ = nullptr;
}
-static void print_const_expr_error(Context* ctx,
- const Location* loc,
- const char* desc) {
- print_error(ctx, loc,
- "invalid %s, must be a constant expression; either *.const or "
- "get_global.",
- desc);
+void Validator::PrintConstExprError(const Location* loc, const char* desc) {
+ PrintError(loc,
+ "invalid %s, must be a constant expression; either *.const or "
+ "get_global.",
+ desc);
}
-static void check_const_init_expr(Context* ctx,
- const Location* loc,
- const Expr* expr,
- Type expected_type,
- const char* desc) {
+void Validator::CheckConstInitExpr(const Location* loc,
+ const Expr* expr,
+ Type expected_type,
+ const char* desc) {
Type type = Type::Void;
if (expr) {
if (expr->next) {
- print_const_expr_error(ctx, loc, desc);
+ PrintConstExprError(loc, desc);
return;
}
@@ -568,165 +613,149 @@ static void check_const_init_expr(Context* ctx,
case ExprType::GetGlobal: {
const Global* ref_global = nullptr;
Index ref_global_index;
- if (WABT_FAILED(check_global_var(ctx, &expr->get_global.var,
- &ref_global, &ref_global_index))) {
+ if (WABT_FAILED(CheckGlobalVar(&expr->get_global.var, &ref_global,
+ &ref_global_index))) {
return;
}
type = ref_global->type;
- /* globals can only reference previously defined, internal globals */
- if (ref_global_index >= ctx->current_global_index) {
- print_error(ctx, loc,
- "initializer expression can only reference a previously "
- "defined global");
- } else if (ref_global_index >= ctx->num_imported_globals) {
- print_error(
- ctx, loc,
+ if (ref_global_index >= num_imported_globals_) {
+ PrintError(
+ loc,
"initializer expression can only reference an imported global");
}
if (ref_global->mutable_) {
- print_error(
- ctx, loc,
- "initializer expression cannot reference a mutable global");
+ PrintError(
+ loc, "initializer expression cannot reference a mutable global");
}
break;
}
default:
- print_const_expr_error(ctx, loc, desc);
+ PrintConstExprError(loc, desc);
return;
}
}
- check_type(ctx, expr ? &expr->loc : loc, type, expected_type, desc);
+ CheckType(expr ? &expr->loc : loc, type, expected_type, desc);
}
-static void check_global(Context* ctx,
- const Location* loc,
- const Global* global) {
- check_const_init_expr(ctx, loc, global->init_expr, global->type,
- "global initializer expression");
+void Validator::CheckGlobal(const Location* loc, const Global* global) {
+ CheckConstInitExpr(loc, global->init_expr, global->type,
+ "global initializer expression");
}
-static void check_limits(Context* ctx,
- const Location* loc,
- const Limits* limits,
- uint64_t absolute_max,
- const char* desc) {
+void Validator::CheckLimits(const Location* loc,
+ const Limits* limits,
+ uint64_t absolute_max,
+ const char* desc) {
if (limits->initial > absolute_max) {
- print_error(ctx, loc, "initial %s (%" PRIu64 ") must be <= (%" PRIu64 ")",
- desc, limits->initial, absolute_max);
+ PrintError(loc, "initial %s (%" PRIu64 ") must be <= (%" PRIu64 ")", desc,
+ limits->initial, absolute_max);
}
if (limits->has_max) {
if (limits->max > absolute_max) {
- print_error(ctx, loc, "max %s (%" PRIu64 ") must be <= (%" PRIu64 ")",
- desc, limits->max, absolute_max);
+ PrintError(loc, "max %s (%" PRIu64 ") must be <= (%" PRIu64 ")", desc,
+ limits->max, absolute_max);
}
if (limits->max < limits->initial) {
- print_error(ctx, loc,
- "max %s (%" PRIu64 ") must be >= initial %s (%" PRIu64 ")",
- desc, limits->max, desc, limits->initial);
+ PrintError(loc,
+ "max %s (%" PRIu64 ") must be >= initial %s (%" PRIu64 ")",
+ desc, limits->max, desc, limits->initial);
}
}
}
-static void check_table(Context* ctx, const Location* loc, const Table* table) {
- if (ctx->current_table_index == 1)
- print_error(ctx, loc, "only one table allowed");
- check_limits(ctx, loc, &table->elem_limits, UINT32_MAX, "elems");
+void Validator::CheckTable(const Location* loc, const Table* table) {
+ if (current_table_index_ == 1)
+ PrintError(loc, "only one table allowed");
+ CheckLimits(loc, &table->elem_limits, UINT32_MAX, "elems");
}
-static void check_elem_segments(Context* ctx, const Module* module) {
+void Validator::CheckElemSegments(const Module* module) {
for (ModuleField* field = module->first_field; field; field = field->next) {
if (field->type != ModuleFieldType::ElemSegment)
continue;
ElemSegment* elem_segment = field->elem_segment;
const Table* table;
- if (!WABT_SUCCEEDED(check_table_var(ctx, &elem_segment->table_var, &table)))
+ if (!WABT_SUCCEEDED(CheckTableVar(&elem_segment->table_var, &table)))
continue;
- for (const Var& var: elem_segment->vars) {
- if (!WABT_SUCCEEDED(check_func_var(ctx, &var, nullptr)))
+ for (const Var& var : elem_segment->vars) {
+ if (!WABT_SUCCEEDED(CheckFuncVar(&var, nullptr)))
continue;
}
- check_const_init_expr(ctx, &field->loc, elem_segment->offset, Type::I32,
- "elem segment offset");
+ CheckConstInitExpr(&field->loc, elem_segment->offset, Type::I32,
+ "elem segment offset");
}
}
-static void check_memory(Context* ctx,
- const Location* loc,
- const Memory* memory) {
- if (ctx->current_memory_index == 1)
- print_error(ctx, loc, "only one memory block allowed");
- check_limits(ctx, loc, &memory->page_limits, WABT_MAX_PAGES, "pages");
+void Validator::CheckMemory(const Location* loc, const Memory* memory) {
+ if (current_memory_index_ == 1)
+ PrintError(loc, "only one memory block allowed");
+ CheckLimits(loc, &memory->page_limits, WABT_MAX_PAGES, "pages");
}
-static void check_data_segments(Context* ctx, const Module* module) {
+void Validator::CheckDataSegments(const Module* module) {
for (ModuleField* field = module->first_field; field; field = field->next) {
if (field->type != ModuleFieldType::DataSegment)
continue;
DataSegment* data_segment = field->data_segment;
const Memory* memory;
- if (!WABT_SUCCEEDED(
- check_memory_var(ctx, &data_segment->memory_var, &memory)))
+ if (!WABT_SUCCEEDED(CheckMemoryVar(&data_segment->memory_var, &memory)))
continue;
- check_const_init_expr(ctx, &field->loc, data_segment->offset, Type::I32,
- "data segment offset");
+ CheckConstInitExpr(&field->loc, data_segment->offset, Type::I32,
+ "data segment offset");
}
}
-static void check_import(Context* ctx,
- const Location* loc,
- const Import* import) {
+void Validator::CheckImport(const Location* loc, const Import* import) {
switch (import->kind) {
case ExternalKind::Func:
if (decl_has_func_type(&import->func->decl))
- check_func_type_var(ctx, &import->func->decl.type_var, nullptr);
+ CheckFuncTypeVar(&import->func->decl.type_var, nullptr);
break;
case ExternalKind::Table:
- check_table(ctx, loc, import->table);
- ctx->current_table_index++;
+ CheckTable(loc, import->table);
+ current_table_index_++;
break;
case ExternalKind::Memory:
- check_memory(ctx, loc, import->memory);
- ctx->current_memory_index++;
+ CheckMemory(loc, import->memory);
+ current_memory_index_++;
break;
case ExternalKind::Global:
if (import->global->mutable_) {
- print_error(ctx, loc, "mutable globals cannot be imported");
+ PrintError(loc, "mutable globals cannot be imported");
}
- ctx->num_imported_globals++;
- ctx->current_global_index++;
+ num_imported_globals_++;
+ current_global_index_++;
break;
}
}
-static void check_export(Context* ctx, const Export* export_) {
+void Validator::CheckExport(const Export* export_) {
switch (export_->kind) {
case ExternalKind::Func:
- check_func_var(ctx, &export_->var, nullptr);
+ CheckFuncVar(&export_->var, nullptr);
break;
case ExternalKind::Table:
- check_table_var(ctx, &export_->var, nullptr);
+ CheckTableVar(&export_->var, nullptr);
break;
case ExternalKind::Memory:
- check_memory_var(ctx, &export_->var, nullptr);
+ CheckMemoryVar(&export_->var, nullptr);
break;
case ExternalKind::Global: {
const Global* global;
- if (WABT_SUCCEEDED(
- check_global_var(ctx, &export_->var, &global, nullptr))) {
+ if (WABT_SUCCEEDED(CheckGlobalVar(&export_->var, &global, nullptr))) {
if (global->mutable_) {
- print_error(ctx, &export_->var.loc,
- "mutable globals cannot be exported");
+ PrintError(&export_->var.loc, "mutable globals cannot be exported");
}
}
break;
@@ -734,66 +763,68 @@ static void check_export(Context* ctx, const Export* export_) {
}
}
-static void on_duplicate_binding(const BindingHash::value_type& a,
- const BindingHash::value_type& b,
- void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- /* choose the location that is later in the file */
+void Validator::OnDuplicateBinding(const BindingHash::value_type& a,
+ const BindingHash::value_type& b) {
+ // Choose the location that is later in the file.
const Location& a_loc = a.second.loc;
const Location& b_loc = b.second.loc;
const Location& loc = a_loc.line > b_loc.line ? a_loc : b_loc;
- print_error(ctx, &loc, "redefinition of export \"%s\"", a.first.c_str());
+ PrintError(&loc, "redefinition of export \"%s\"", a.first.c_str());
}
-static void check_duplicate_export_bindings(Context* ctx,
- const Module* module) {
- module->export_bindings.find_duplicates(on_duplicate_binding, ctx);
+void Validator::CheckDuplicateExportBindings(const Module* module) {
+ module->export_bindings.find_duplicates(
+ [](const BindingHash::value_type& a, const BindingHash::value_type& b,
+ void* user_data) {
+ static_cast<Validator*>(user_data)->OnDuplicateBinding(a, b);
+ },
+ this);
}
-static void check_module(Context* ctx, const Module* module) {
+void Validator::CheckModule(const Module* module) {
bool seen_start = false;
- ctx->current_module = module;
- ctx->current_table_index = 0;
- ctx->current_memory_index = 0;
- ctx->current_global_index = 0;
- ctx->num_imported_globals = 0;
+ current_module_ = module;
+ current_table_index_ = 0;
+ current_memory_index_ = 0;
+ current_global_index_ = 0;
+ num_imported_globals_ = 0;
for (ModuleField* field = module->first_field; field; field = field->next) {
switch (field->type) {
case ModuleFieldType::Func:
- check_func(ctx, &field->loc, field->func);
+ CheckFunc(&field->loc, field->func);
break;
case ModuleFieldType::Global:
- check_global(ctx, &field->loc, field->global);
- ctx->current_global_index++;
+ CheckGlobal(&field->loc, field->global);
+ current_global_index_++;
break;
case ModuleFieldType::Import:
- check_import(ctx, &field->loc, field->import);
+ CheckImport(&field->loc, field->import);
break;
case ModuleFieldType::Export:
- check_export(ctx, field->export_);
+ CheckExport(field->export_);
break;
case ModuleFieldType::Table:
- check_table(ctx, &field->loc, field->table);
- ctx->current_table_index++;
+ CheckTable(&field->loc, field->table);
+ current_table_index_++;
break;
case ModuleFieldType::ElemSegment:
- /* checked below */
+ // Checked below.
break;
case ModuleFieldType::Memory:
- check_memory(ctx, &field->loc, field->memory);
- ctx->current_memory_index++;
+ CheckMemory(&field->loc, field->memory);
+ current_memory_index_++;
break;
case ModuleFieldType::DataSegment:
- /* checked below */
+ // Checked below.
break;
case ModuleFieldType::FuncType:
@@ -801,19 +832,18 @@ static void check_module(Context* ctx, const Module* module) {
case ModuleFieldType::Start: {
if (seen_start) {
- print_error(ctx, &field->loc, "only one start function allowed");
+ PrintError(&field->loc, "only one start function allowed");
}
const Func* start_func = nullptr;
- check_func_var(ctx, &field->start, &start_func);
+ CheckFuncVar(&field->start, &start_func);
if (start_func) {
if (get_num_params(start_func) != 0) {
- print_error(ctx, &field->loc, "start function must be nullary");
+ PrintError(&field->loc, "start function must be nullary");
}
if (get_num_results(start_func) != 0) {
- print_error(ctx, &field->loc,
- "start function must not return anything");
+ PrintError(&field->loc, "start function must not return anything");
}
}
seen_start = true;
@@ -822,72 +852,70 @@ static void check_module(Context* ctx, const Module* module) {
}
}
- check_elem_segments(ctx, module);
- check_data_segments(ctx, module);
- check_duplicate_export_bindings(ctx, module);
+ CheckElemSegments(module);
+ CheckDataSegments(module);
+ CheckDuplicateExportBindings(module);
}
-/* returns the result type of the invoked function, checked by the caller;
- * returning nullptr means that another error occured first, so the result type
- * should be ignored. */
-static const TypeVector* check_invoke(Context* ctx, const Action* action) {
+// Returns the result type of the invoked function, checked by the caller;
+// returning nullptr means that another error occured first, so the result type
+// should be ignored.
+const TypeVector* Validator::CheckInvoke(const Action* action) {
const ActionInvoke* invoke = action->invoke;
- const Module* module = get_module_by_var(ctx->script, &action->module_var);
+ const Module* module = get_module_by_var(script_, &action->module_var);
if (!module) {
- print_error(ctx, &action->loc, "unknown module");
+ PrintError(&action->loc, "unknown module");
return nullptr;
}
Export* export_ = get_export_by_name(module, &action->name);
if (!export_) {
- print_error(ctx, &action->loc,
- "unknown function export \"" PRIstringslice "\"",
- WABT_PRINTF_STRING_SLICE_ARG(action->name));
+ PrintError(&action->loc, "unknown function export \"" PRIstringslice "\"",
+ WABT_PRINTF_STRING_SLICE_ARG(action->name));
return nullptr;
}
Func* func = get_func_by_var(module, &export_->var);
if (!func) {
- /* this error will have already been reported, just skip it */
+ // This error will have already been reported, just skip it.
return nullptr;
}
size_t actual_args = invoke->args.size();
size_t expected_args = get_num_params(func);
if (expected_args != actual_args) {
- print_error(ctx, &action->loc, "too %s parameters to function. got %" PRIzd
- ", expected %" PRIzd,
- actual_args > expected_args ? "many" : "few", actual_args,
- expected_args);
+ PrintError(&action->loc, "too %s parameters to function. got %" PRIzd
+ ", expected %" PRIzd,
+ actual_args > expected_args ? "many" : "few", actual_args,
+ expected_args);
return nullptr;
}
for (size_t i = 0; i < actual_args; ++i) {
const Const* const_ = &invoke->args[i];
- check_type_index(ctx, &const_->loc, const_->type, get_param_type(func, i),
- "invoke", i, "argument");
+ CheckTypeIndex(&const_->loc, const_->type, get_param_type(func, i),
+ "invoke", i, "argument");
}
return &func->decl.sig.result_types;
}
-static Result check_get(Context* ctx, const Action* action, Type* out_type) {
- const Module* module = get_module_by_var(ctx->script, &action->module_var);
+Result Validator::CheckGet(const Action* action, Type* out_type) {
+ const Module* module = get_module_by_var(script_, &action->module_var);
if (!module) {
- print_error(ctx, &action->loc, "unknown module");
+ PrintError(&action->loc, "unknown module");
return Result::Error;
}
Export* export_ = get_export_by_name(module, &action->name);
if (!export_) {
- print_error(ctx, &action->loc,
- "unknown global export \"" PRIstringslice "\"",
- WABT_PRINTF_STRING_SLICE_ARG(action->name));
+ PrintError(&action->loc, "unknown global export \"" PRIstringslice "\"",
+ WABT_PRINTF_STRING_SLICE_ARG(action->name));
return Result::Error;
}
Global* global = get_global_by_var(module, &export_->var);
if (!global) {
- /* this error will have already been reported, just skip it */
+ // This error will have already been reported, just skip it.
return Result::Error;
}
@@ -895,60 +923,59 @@ static Result check_get(Context* ctx, const Action* action, Type* out_type) {
return Result::Ok;
}
-static ActionResult check_action(Context* ctx, const Action* action) {
+Validator::ActionResult Validator::CheckAction(const Action* action) {
ActionResult result;
WABT_ZERO_MEMORY(result);
switch (action->type) {
case ActionType::Invoke:
- result.types = check_invoke(ctx, action);
+ result.types = CheckInvoke(action);
result.kind =
- result.types ? ActionResultKind::Types : ActionResultKind::Error;
+ result.types ? ActionResult::Kind::Types : ActionResult::Kind::Error;
break;
case ActionType::Get:
- if (WABT_SUCCEEDED(check_get(ctx, action, &result.type)))
- result.kind = ActionResultKind::Type;
+ if (WABT_SUCCEEDED(CheckGet(action, &result.type)))
+ result.kind = ActionResult::Kind::Type;
else
- result.kind = ActionResultKind::Error;
+ result.kind = ActionResult::Kind::Error;
break;
}
return result;
}
-static void check_assert_return_nan_command(Context* ctx,
- const Action* action) {
- ActionResult result = check_action(ctx, action);
+void Validator::CheckAssertReturnNanCommand(const Action* action) {
+ ActionResult result = CheckAction(action);
- /* a valid result type will either be f32 or f64; convert a TYPES result
- * into a TYPE result, so it is easier to check below. Type::Any is
- * used to specify a type that should not be checked (because an earlier
- * error occurred). */
- if (result.kind == ActionResultKind::Types) {
+ // A valid result type will either be f32 or f64; convert a Types result into
+ // a Type result, so it is easier to check below. Type::Any is used to
+ // specify a type that should not be checked (because an earlier error
+ // occurred).
+ if (result.kind == ActionResult::Kind::Types) {
if (result.types->size() == 1) {
- result.kind = ActionResultKind::Type;
+ result.kind = ActionResult::Kind::Type;
result.type = (*result.types)[0];
} else {
- print_error(ctx, &action->loc, "expected 1 result, got %" PRIzd,
- result.types->size());
+ PrintError(&action->loc, "expected 1 result, got %" PRIzd,
+ result.types->size());
result.type = Type::Any;
}
}
- if (result.kind == ActionResultKind::Type && result.type != Type::Any)
- check_assert_return_nan_type(ctx, &action->loc, result.type, "action");
+ if (result.kind == ActionResult::Kind::Type && result.type != Type::Any)
+ CheckAssertReturnNanType(&action->loc, result.type, "action");
}
-static void check_command(Context* ctx, const Command* command) {
+void Validator::CheckCommand(const Command* command) {
switch (command->type) {
case CommandType::Module:
- check_module(ctx, command->module);
+ CheckModule(command->module);
break;
case CommandType::Action:
- /* ignore result type */
- check_action(ctx, command->action);
+ // Ignore result type.
+ CheckAction(command->action);
break;
case CommandType::Register:
@@ -957,56 +984,60 @@ static void check_command(Context* ctx, const Command* command) {
case CommandType::AssertInvalidNonBinary:
case CommandType::AssertUnlinkable:
case CommandType::AssertUninstantiable:
- /* ignore */
+ // Ignore.
break;
case CommandType::AssertReturn: {
const Action* action = command->assert_return.action;
- ActionResult result = check_action(ctx, action);
+ ActionResult result = CheckAction(action);
switch (result.kind) {
- case ActionResultKind::Types:
- check_const_types(ctx, &action->loc, *result.types,
- *command->assert_return.expected, "action");
+ case ActionResult::Kind::Types:
+ CheckConstTypes(&action->loc, *result.types,
+ *command->assert_return.expected, "action");
break;
- case ActionResultKind::Type:
- check_const_type(ctx, &action->loc, result.type,
- *command->assert_return.expected, "action");
+ case ActionResult::Kind::Type:
+ CheckConstType(&action->loc, result.type,
+ *command->assert_return.expected, "action");
break;
- case ActionResultKind::Error:
- /* error occurred, don't do any further checks */
+ case ActionResult::Kind::Error:
+ // Error occurred, don't do any further checks.
break;
}
break;
}
case CommandType::AssertReturnCanonicalNan:
- check_assert_return_nan_command(
- ctx, command->assert_return_canonical_nan.action);
+ CheckAssertReturnNanCommand(command->assert_return_canonical_nan.action);
break;
case CommandType::AssertReturnArithmeticNan:
- check_assert_return_nan_command(
- ctx, command->assert_return_arithmetic_nan.action);
+ CheckAssertReturnNanCommand(command->assert_return_arithmetic_nan.action);
break;
case CommandType::AssertTrap:
case CommandType::AssertExhaustion:
- /* ignore result type */
- check_action(ctx, command->assert_trap.action);
+ // ignore result type.
+ CheckAction(command->assert_trap.action);
break;
}
}
+Result Validator::CheckScript(const Script* script) {
+ for (const std::unique_ptr<Command>& command : script->commands)
+ CheckCommand(command.get());
+ return result_;
+}
+
+} // namespace
+
Result validate_script(WastLexer* lexer,
- const struct Script* script,
+ const Script* script,
SourceErrorHandler* error_handler) {
- Context ctx(error_handler, lexer, script);
+ Validator validator(error_handler, lexer, script);
- for (const std::unique_ptr<Command>& command : script->commands)
- check_command(&ctx, command.get());
- return ctx.result;
+ return validator.CheckScript(script);
}
} // namespace wabt