summaryrefslogtreecommitdiff
path: root/src/validator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/validator.cc')
-rw-r--r--src/validator.cc196
1 files changed, 95 insertions, 101 deletions
diff --git a/src/validator.cc b/src/validator.cc
index d2062f8e..02c83e4d 100644
--- a/src/validator.cc
+++ b/src/validator.cc
@@ -47,20 +47,29 @@ struct ActionResult {
};
struct Context {
- SourceErrorHandler* error_handler;
- AstLexer* lexer;
- const Script* script;
- const Module* current_module;
- const Func* current_func;
- int current_table_index;
- int current_memory_index;
- int current_global_index;
- int num_imported_globals;
+ WABT_DISALLOW_COPY_AND_ASSIGN(Context);
+ Context(SourceErrorHandler*, AstLexer*, const Script*);
+
+ SourceErrorHandler* error_handler = nullptr;
+ AstLexer* lexer = nullptr;
+ const Script* script = nullptr;
+ const Module* current_module = nullptr;
+ const Func* current_func = nullptr;
+ int current_table_index = 0;
+ int current_memory_index = 0;
+ int current_global_index = 0;
+ int num_imported_globals = 0;
TypeChecker typechecker;
- const Location* expr_loc; /* Cached for access by on_typechecker_error */
- Result result;
+ /* Cached for access by on_typechecker_error */
+ const Location* expr_loc = nullptr;
+ Result result = Result::Ok;
};
+Context::Context(SourceErrorHandler* error_handler,
+ AstLexer* lexer,
+ const Script* script)
+ : error_handler(error_handler), lexer(lexer), script(script) {}
+
} // namespace
static void WABT_PRINTF_FORMAT(3, 4)
@@ -107,13 +116,13 @@ static Result check_func_var(Context* ctx,
const Var* var,
const Func** out_func) {
int index;
- if (WABT_FAILED(check_var(ctx, ctx->current_module->funcs.size, var,
+ if (WABT_FAILED(check_var(ctx, ctx->current_module->funcs.size(), var,
"function", &index))) {
return Result::Error;
}
if (out_func)
- *out_func = ctx->current_module->funcs.data[index];
+ *out_func = ctx->current_module->funcs[index];
return Result::Ok;
}
@@ -122,13 +131,13 @@ static Result check_global_var(Context* ctx,
const Global** out_global,
int* out_global_index) {
int index;
- if (WABT_FAILED(check_var(ctx, ctx->current_module->globals.size, var,
+ if (WABT_FAILED(check_var(ctx, ctx->current_module->globals.size(), var,
"global", &index))) {
return Result::Error;
}
if (out_global)
- *out_global = ctx->current_module->globals.data[index];
+ *out_global = ctx->current_module->globals[index];
if (out_global_index)
*out_global_index = index;
return Result::Ok;
@@ -145,13 +154,13 @@ static Result check_func_type_var(Context* ctx,
const Var* var,
const FuncType** out_func_type) {
int index;
- if (WABT_FAILED(check_var(ctx, ctx->current_module->func_types.size, var,
+ if (WABT_FAILED(check_var(ctx, ctx->current_module->func_types.size(), var,
"function type", &index))) {
return Result::Error;
}
if (out_func_type)
- *out_func_type = ctx->current_module->func_types.data[index];
+ *out_func_type = ctx->current_module->func_types[index];
return Result::Ok;
}
@@ -159,13 +168,13 @@ static Result check_table_var(Context* ctx,
const Var* var,
const Table** out_table) {
int index;
- if (WABT_FAILED(check_var(ctx, ctx->current_module->tables.size, var, "table",
- &index))) {
+ if (WABT_FAILED(check_var(ctx, ctx->current_module->tables.size(), var,
+ "table", &index))) {
return Result::Error;
}
if (out_table)
- *out_table = ctx->current_module->tables.data[index];
+ *out_table = ctx->current_module->tables[index];
return Result::Ok;
}
@@ -173,13 +182,13 @@ static Result check_memory_var(Context* ctx,
const Var* var,
const Memory** out_memory) {
int index;
- if (WABT_FAILED(check_var(ctx, ctx->current_module->memories.size, var,
+ if (WABT_FAILED(check_var(ctx, ctx->current_module->memories.size(), var,
"memory", &index))) {
return Result::Error;
}
if (out_memory)
- *out_memory = ctx->current_module->memories.data[index];
+ *out_memory = ctx->current_module->memories[index];
return Result::Ok;
}
@@ -193,7 +202,7 @@ 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.data[index - num_params];
+ *out_type = ctx->current_func->local_types[index - num_params];
}
}
return Result::Ok;
@@ -264,47 +273,45 @@ static void check_type_index(Context* ctx,
static void check_types(Context* ctx,
const Location* loc,
- const TypeVector* actual,
- const TypeVector* expected,
+ 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->data[i], expected->data[i], desc, i,
- 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);
}
} else {
print_error(ctx, loc, "expected %" PRIzd " %ss, got %" PRIzd,
- expected->size, index_kind, actual->size);
+ expected.size(), index_kind, actual.size());
}
}
static void check_const_types(Context* ctx,
const Location* loc,
- const TypeVector* actual,
- const ConstVector* expected,
+ 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->data[i], expected->data[i].type, desc,
- i, "result");
+ 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");
}
} else {
print_error(ctx, loc, "expected %" PRIzd " results, got %" PRIzd,
- expected->size, actual->size);
+ expected.size(), actual.size());
}
}
static void check_const_type(Context* ctx,
const Location* loc,
Type actual,
- const ConstVector* expected,
+ const ConstVector& expected,
const char* desc) {
TypeVector actual_types;
- WABT_ZERO_MEMORY(actual_types);
- actual_types.size = actual == Type::Void ? 0 : 1;
- actual_types.data = &actual;
- check_const_types(ctx, loc, &actual_types, expected, desc);
+ if (actual != Type::Void)
+ actual_types.push_back(actual);
+ check_const_types(ctx, loc, actual_types, expected, desc);
}
static void check_assert_return_nan_type(Context* ctx,
@@ -331,7 +338,7 @@ static void check_expr_list(Context* ctx,
}
static void check_has_memory(Context* ctx, const Location* loc, Opcode opcode) {
- if (ctx->current_module->memories.size == 0) {
+ if (ctx->current_module->memories.size() == 0) {
print_error(ctx, loc, "%s requires an imported or defined memory.",
get_opcode_name(opcode));
}
@@ -346,8 +353,8 @@ static void check_expr(Context* ctx, const Expr* expr) {
break;
case ExprType::Block:
- typechecker_on_block(&ctx->typechecker, &expr->block.sig);
- check_expr_list(ctx, &expr->loc, expr->block.first);
+ typechecker_on_block(&ctx->typechecker, &expr->block->sig);
+ check_expr_list(ctx, &expr->loc, expr->block->first);
typechecker_on_end(&ctx->typechecker);
break;
@@ -361,9 +368,8 @@ static void check_expr(Context* ctx, const Expr* expr) {
case ExprType::BrTable: {
typechecker_begin_br_table(&ctx->typechecker);
- for (size_t i = 0; i < expr->br_table.targets.size; ++i) {
- typechecker_on_br_table_target(&ctx->typechecker,
- expr->br_table.targets.data[i].index);
+ for (Var& var: *expr->br_table.targets) {
+ typechecker_on_br_table_target(&ctx->typechecker, var.index);
}
typechecker_on_br_table_target(&ctx->typechecker,
expr->br_table.default_target.index);
@@ -382,7 +388,7 @@ static void check_expr(Context* ctx, const Expr* expr) {
case ExprType::CallIndirect: {
const FuncType* func_type;
- if (ctx->current_module->tables.size == 0) {
+ if (ctx->current_module->tables.size() == 0) {
print_error(ctx, &expr->loc,
"found call_indirect operator, but no table");
}
@@ -429,8 +435,8 @@ static void check_expr(Context* ctx, const Expr* expr) {
break;
case ExprType::If:
- typechecker_on_if(&ctx->typechecker, &expr->if_.true_.sig);
- check_expr_list(ctx, &expr->loc, expr->if_.true_.first);
+ typechecker_on_if(&ctx->typechecker, &expr->if_.true_->sig);
+ check_expr_list(ctx, &expr->loc, expr->if_.true_->first);
if (expr->if_.false_) {
typechecker_on_else(&ctx->typechecker);
check_expr_list(ctx, &expr->loc, expr->if_.false_);
@@ -447,8 +453,8 @@ static void check_expr(Context* ctx, const Expr* expr) {
break;
case ExprType::Loop:
- typechecker_on_loop(&ctx->typechecker, &expr->loop.sig);
- check_expr_list(ctx, &expr->loc, expr->loop.first);
+ typechecker_on_loop(&ctx->typechecker, &expr->loop->sig);
+ check_expr_list(ctx, &expr->loc, expr->loop->first);
typechecker_on_end(&ctx->typechecker);
break;
@@ -506,12 +512,12 @@ static void check_expr(Context* ctx, const Expr* expr) {
static void check_func_signature_matches_func_type(Context* ctx,
const Location* loc,
- const FuncSignature* sig,
+ const FuncSignature& sig,
const FuncType* func_type) {
- check_types(ctx, loc, &sig->result_types, &func_type->sig.result_types,
+ 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");
+ check_types(ctx, loc, sig.param_types, func_type->sig.param_types, "function",
+ "argument");
}
static void check_func(Context* ctx, const Location* loc, const Func* func) {
@@ -525,7 +531,7 @@ static void check_func(Context* ctx, const Location* loc, const Func* func) {
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,
+ check_func_signature_matches_func_type(ctx, loc, func->decl.sig,
func_type);
}
}
@@ -642,14 +648,13 @@ static void check_elem_segments(Context* ctx, const Module* module) {
if (field->type != ModuleFieldType::ElemSegment)
continue;
- ElemSegment* elem_segment = &field->elem_segment;
+ ElemSegment* elem_segment = field->elem_segment;
const Table* table;
if (!WABT_SUCCEEDED(check_table_var(ctx, &elem_segment->table_var, &table)))
continue;
- for (size_t i = 0; i < elem_segment->vars.size; ++i) {
- if (!WABT_SUCCEEDED(
- check_func_var(ctx, &elem_segment->vars.data[i], nullptr)))
+ for (const Var& var: elem_segment->vars) {
+ if (!WABT_SUCCEEDED(check_func_var(ctx, &var, nullptr)))
continue;
}
@@ -671,7 +676,7 @@ static void check_data_segments(Context* ctx, const Module* module) {
if (field->type != ModuleFieldType::DataSegment)
continue;
- DataSegment* data_segment = &field->data_segment;
+ DataSegment* data_segment = field->data_segment;
const Memory* memory;
if (!WABT_SUCCEEDED(
check_memory_var(ctx, &data_segment->memory_var, &memory)))
@@ -691,15 +696,15 @@ static void check_import(Context* ctx,
check_func_type_var(ctx, &import->func->decl.type_var, nullptr);
break;
case ExternalKind::Table:
- check_table(ctx, loc, &import->table);
+ check_table(ctx, loc, import->table);
ctx->current_table_index++;
break;
case ExternalKind::Memory:
- check_memory(ctx, loc, &import->memory);
+ check_memory(ctx, loc, import->memory);
ctx->current_memory_index++;
break;
case ExternalKind::Global:
- if (import->global.mutable_) {
+ if (import->global->mutable_) {
print_error(ctx, loc, "mutable globals cannot be imported");
}
ctx->num_imported_globals++;
@@ -765,7 +770,7 @@ static void check_module(Context* ctx, const Module* module) {
break;
case ModuleFieldType::Global:
- check_global(ctx, &field->loc, &field->global);
+ check_global(ctx, &field->loc, field->global);
ctx->current_global_index++;
break;
@@ -774,11 +779,11 @@ static void check_module(Context* ctx, const Module* module) {
break;
case ModuleFieldType::Export:
- check_export(ctx, &field->export_);
+ check_export(ctx, field->export_);
break;
case ModuleFieldType::Table:
- check_table(ctx, &field->loc, &field->table);
+ check_table(ctx, &field->loc, field->table);
ctx->current_table_index++;
break;
@@ -787,7 +792,7 @@ static void check_module(Context* ctx, const Module* module) {
break;
case ModuleFieldType::Memory:
- check_memory(ctx, &field->loc, &field->memory);
+ check_memory(ctx, &field->loc, field->memory);
ctx->current_memory_index++;
break;
@@ -830,18 +835,18 @@ static void check_module(Context* ctx, const Module* module) {
* 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) {
- const ActionInvoke* invoke = &action->invoke;
+ const ActionInvoke* invoke = action->invoke;
const Module* module = get_module_by_var(ctx->script, &action->module_var);
if (!module) {
print_error(ctx, &action->loc, "unknown module");
return nullptr;
}
- Export* export_ = get_export_by_name(module, &invoke->name);
+ 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(invoke->name));
+ WABT_PRINTF_STRING_SLICE_ARG(action->name));
return nullptr;
}
@@ -851,7 +856,7 @@ static const TypeVector* check_invoke(Context* ctx, const Action* action) {
return nullptr;
}
- size_t actual_args = invoke->args.size;
+ 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
@@ -861,7 +866,7 @@ static const TypeVector* check_invoke(Context* ctx, const Action* action) {
return nullptr;
}
for (size_t i = 0; i < actual_args; ++i) {
- Const* const_ = &invoke->args.data[i];
+ const Const* const_ = &invoke->args[i];
check_type_index(ctx, &const_->loc, const_->type, get_param_type(func, i),
"invoke", i, "argument");
}
@@ -870,18 +875,17 @@ static const TypeVector* check_invoke(Context* ctx, const Action* action) {
}
static Result check_get(Context* ctx, const Action* action, Type* out_type) {
- const ActionGet* get = &action->get;
const Module* module = get_module_by_var(ctx->script, &action->module_var);
if (!module) {
print_error(ctx, &action->loc, "unknown module");
return Result::Error;
}
- Export* export_ = get_export_by_name(module, &get->name);
+ 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(get->name));
+ WABT_PRINTF_STRING_SLICE_ARG(action->name));
return Result::Error;
}
@@ -925,7 +929,7 @@ static void check_command(Context* ctx, const Command* command) {
case CommandType::Action:
/* ignore result type */
- check_action(ctx, &command->action);
+ check_action(ctx, command->action);
break;
case CommandType::Register:
@@ -938,17 +942,17 @@ static void check_command(Context* ctx, const Command* command) {
break;
case CommandType::AssertReturn: {
- const Action* action = &command->assert_return.action;
+ const Action* action = command->assert_return.action;
ActionResult result = check_action(ctx, action);
switch (result.kind) {
case ActionResultKind::Types:
- check_const_types(ctx, &action->loc, result.types,
- &command->assert_return.expected, "action");
+ check_const_types(ctx, &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");
+ *command->assert_return.expected, "action");
break;
case ActionResultKind::Error:
@@ -959,7 +963,7 @@ static void check_command(Context* ctx, const Command* command) {
}
case CommandType::AssertReturnNan: {
- const Action* action = &command->assert_return_nan.action;
+ const Action* action = command->assert_return_nan.action;
ActionResult result = check_action(ctx, action);
/* a valid result type will either be f32 or f64; convert a TYPES result
@@ -967,12 +971,12 @@ static void check_command(Context* ctx, const Command* command) {
* used to specify a type that should not be checked (because an earlier
* error occurred). */
if (result.kind == ActionResultKind::Types) {
- if (result.types->size == 1) {
+ if (result.types->size() == 1) {
result.kind = ActionResultKind::Type;
- result.type = result.types->data[0];
+ result.type = (*result.types)[0];
} else {
print_error(ctx, &action->loc, "expected 1 result, got %" PRIzd,
- result.types->size);
+ result.types->size());
result.type = Type::Any;
}
}
@@ -985,33 +989,23 @@ static void check_command(Context* ctx, const Command* command) {
case CommandType::AssertTrap:
case CommandType::AssertExhaustion:
/* ignore result type */
- check_action(ctx, &command->assert_trap.action);
+ check_action(ctx, command->assert_trap.action);
break;
}
}
-static void destroy_context(Context* ctx) {
- destroy_typechecker(&ctx->typechecker);
-}
-
Result validate_script(AstLexer* lexer,
const struct Script* script,
SourceErrorHandler* error_handler) {
- Context ctx;
- WABT_ZERO_MEMORY(ctx);
- ctx.lexer = lexer;
- ctx.error_handler = error_handler;
- ctx.result = Result::Ok;
- ctx.script = script;
+ Context ctx(error_handler, lexer, script);
TypeCheckerErrorHandler tc_error_handler;
tc_error_handler.on_error = on_typechecker_error;
tc_error_handler.user_data = &ctx;
ctx.typechecker.error_handler = &tc_error_handler;
- for (size_t i = 0; i < script->commands.size; ++i)
- check_command(&ctx, &script->commands.data[i]);
- destroy_context(&ctx);
+ for (const std::unique_ptr<Command>& command : script->commands)
+ check_command(&ctx, command.get());
return ctx.result;
}