summaryrefslogtreecommitdiff
path: root/src/validator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/validator.cc')
-rw-r--r--src/validator.cc146
1 files changed, 71 insertions, 75 deletions
diff --git a/src/validator.cc b/src/validator.cc
index a1afab1e..8ec4cb51 100644
--- a/src/validator.cc
+++ b/src/validator.cc
@@ -55,11 +55,6 @@ class Validator {
};
};
- struct TryContext {
- const TryExpr* try_ = nullptr;
- const Catch* catch_ = nullptr;
- };
-
void WABT_PRINTF_FORMAT(3, 4)
PrintError(const Location* loc, const char* fmt, ...);
void OnTypecheckerError(const char* msg);
@@ -134,8 +129,8 @@ class Validator {
void CheckExport(const Location* loc, const Export* export_);
void CheckDuplicateExportBindings(const Module* module);
- const TypeVector* CheckInvoke(const Action* action);
- Result CheckGet(const Action* action, Type* out_type);
+ const TypeVector* CheckInvoke(const InvokeAction* action);
+ Result CheckGet(const GetAction* action, Type* out_type);
ActionResult CheckAction(const Action* action);
void CheckAssertReturnNanCommand(const Action* action);
void CheckCommand(const Command* command);
@@ -157,7 +152,6 @@ class Validator {
// Cached for access by OnTypecheckerError.
const Location* expr_loc_ = nullptr;
Result result_ = Result::Ok;
- std::vector<TryContext> try_contexts_;
};
Validator::Validator(ErrorHandler* error_handler,
@@ -419,16 +413,16 @@ void Validator::CheckBlockSig(const Location* loc,
void Validator::CheckExpr(const Expr* expr) {
expr_loc_ = &expr->loc;
- switch (expr->type) {
+ switch (expr->type()) {
case ExprType::Binary:
typechecker_.OnBinary(cast<BinaryExpr>(expr)->opcode);
break;
case ExprType::Block: {
auto block_expr = cast<BlockExpr>(expr);
- CheckBlockSig(&block_expr->loc, Opcode::Block, &block_expr->block->sig);
- typechecker_.OnBlock(&block_expr->block->sig);
- CheckExprList(&block_expr->loc, block_expr->block->exprs);
+ CheckBlockSig(&block_expr->loc, Opcode::Block, &block_expr->block.sig);
+ typechecker_.OnBlock(&block_expr->block.sig);
+ CheckExprList(&block_expr->loc, block_expr->block.exprs);
typechecker_.OnEnd();
break;
}
@@ -444,7 +438,7 @@ void Validator::CheckExpr(const Expr* expr) {
case ExprType::BrTable: {
auto br_table_expr = cast<BrTableExpr>(expr);
typechecker_.BeginBrTable();
- for (Var& var : *br_table_expr->targets) {
+ for (const Var& var : br_table_expr->targets) {
typechecker_.OnBrTableTarget(var.index());
}
typechecker_.OnBrTableTarget(br_table_expr->default_target.index());
@@ -507,9 +501,9 @@ void Validator::CheckExpr(const Expr* expr) {
case ExprType::If: {
auto if_expr = cast<IfExpr>(expr);
- CheckBlockSig(&if_expr->loc, Opcode::If, &if_expr->true_->sig);
- typechecker_.OnIf(&if_expr->true_->sig);
- CheckExprList(&if_expr->loc, if_expr->true_->exprs);
+ CheckBlockSig(&if_expr->loc, Opcode::If, &if_expr->true_.sig);
+ typechecker_.OnIf(&if_expr->true_.sig);
+ CheckExprList(&if_expr->loc, if_expr->true_.exprs);
if (!if_expr->false_.empty()) {
typechecker_.OnElse();
CheckExprList(&if_expr->loc, if_expr->false_);
@@ -529,9 +523,9 @@ void Validator::CheckExpr(const Expr* expr) {
case ExprType::Loop: {
auto loop_expr = cast<LoopExpr>(expr);
- CheckBlockSig(&loop_expr->loc, Opcode::Loop, &loop_expr->block->sig);
- typechecker_.OnLoop(&loop_expr->block->sig);
- CheckExprList(&loop_expr->loc, loop_expr->block->exprs);
+ CheckBlockSig(&loop_expr->loc, Opcode::Loop, &loop_expr->block.sig);
+ typechecker_.OnLoop(&loop_expr->block.sig);
+ CheckExprList(&loop_expr->loc, loop_expr->block.exprs);
typechecker_.OnEnd();
break;
}
@@ -589,34 +583,29 @@ void Validator::CheckExpr(const Expr* expr) {
case ExprType::TryBlock: {
auto try_expr = cast<TryExpr>(expr);
- TryContext context;
- context.try_ = try_expr;
- try_contexts_.push_back(context);
- CheckBlockSig(&try_expr->loc, Opcode::Try, &try_expr->block->sig);
+ CheckBlockSig(&try_expr->loc, Opcode::Try, &try_expr->block.sig);
- typechecker_.OnTryBlock(&try_expr->block->sig);
- CheckExprList(&try_expr->loc, try_expr->block->exprs);
+ typechecker_.OnTryBlock(&try_expr->block.sig);
+ CheckExprList(&try_expr->loc, try_expr->block.exprs);
if (try_expr->catches.empty())
PrintError(&try_expr->loc, "TryBlock: doesn't have any catch clauses");
bool found_catch_all = false;
- for (const Catch* catch_ : try_expr->catches) {
- try_contexts_.back().catch_ = catch_;
- typechecker_.OnCatchBlock(&try_expr->block->sig);
- if (catch_->IsCatchAll()) {
+ for (const Catch& catch_ : try_expr->catches) {
+ typechecker_.OnCatchBlock(&try_expr->block.sig);
+ if (catch_.IsCatchAll()) {
found_catch_all = true;
} else {
if (found_catch_all)
- PrintError(&catch_->loc, "Appears after catch all block");
+ PrintError(&catch_.loc, "Appears after catch all block");
const Exception* except = nullptr;
- if (Succeeded(CheckExceptVar(&catch_->var, &except))) {
+ if (Succeeded(CheckExceptVar(&catch_.var, &except))) {
typechecker_.OnCatch(&except->sig);
}
}
- CheckExprList(&catch_->loc, catch_->exprs);
+ CheckExprList(&catch_.loc, catch_.exprs);
}
typechecker_.OnEnd();
- try_contexts_.pop_back();
break;
}
@@ -681,7 +670,7 @@ void Validator::CheckConstInitExpr(const Location* loc,
const Expr* expr = &exprs.front();
loc = &expr->loc;
- switch (expr->type) {
+ switch (expr->type()) {
case ExprType::Const:
type = cast<ConstExpr>(expr)->const_.type;
break;
@@ -754,17 +743,17 @@ void Validator::CheckTable(const Location* loc, const Table* table) {
void Validator::CheckElemSegments(const Module* module) {
for (const ModuleField& field : module->fields) {
if (auto elem_segment_field = dyn_cast<ElemSegmentModuleField>(&field)) {
- ElemSegment* elem_segment = elem_segment_field->elem_segment;
+ auto&& elem_segment = elem_segment_field->elem_segment;
const Table* table;
- if (!Succeeded(CheckTableVar(&elem_segment->table_var, &table)))
+ if (!Succeeded(CheckTableVar(&elem_segment.table_var, &table)))
continue;
- for (const Var& var : elem_segment->vars) {
+ for (const Var& var : elem_segment.vars) {
if (!Succeeded(CheckFuncVar(&var, nullptr)))
continue;
}
- CheckConstInitExpr(&field.loc, elem_segment->offset, Type::I32,
+ CheckConstInitExpr(&field.loc, elem_segment.offset, Type::I32,
"elem segment offset");
}
}
@@ -779,42 +768,50 @@ void Validator::CheckMemory(const Location* loc, const Memory* memory) {
void Validator::CheckDataSegments(const Module* module) {
for (const ModuleField& field : module->fields) {
if (auto data_segment_field = dyn_cast<DataSegmentModuleField>(&field)) {
- DataSegment* data_segment = data_segment_field->data_segment;
+ auto&& data_segment = data_segment_field->data_segment;
const Memory* memory;
- if (!Succeeded(CheckMemoryVar(&data_segment->memory_var, &memory)))
+ if (!Succeeded(CheckMemoryVar(&data_segment.memory_var, &memory)))
continue;
- CheckConstInitExpr(&field.loc, data_segment->offset, Type::I32,
+ CheckConstInitExpr(&field.loc, data_segment.offset, Type::I32,
"data segment offset");
}
}
}
void Validator::CheckImport(const Location* loc, const Import* import) {
- switch (import->kind) {
+ switch (import->kind()) {
case ExternalKind::Except:
++current_except_index_;
- CheckExcept(loc, import->except);
+ CheckExcept(loc, &cast<ExceptionImport>(import)->except);
break;
- case ExternalKind::Func:
- if (import->func->decl.has_func_type)
- CheckFuncTypeVar(&import->func->decl.type_var, nullptr);
+
+ case ExternalKind::Func: {
+ auto* func_import = cast<FuncImport>(import);
+ if (func_import->func.decl.has_func_type)
+ CheckFuncTypeVar(&func_import->func.decl.type_var, nullptr);
break;
+ }
+
case ExternalKind::Table:
- CheckTable(loc, import->table);
+ CheckTable(loc, &cast<TableImport>(import)->table);
++current_table_index_;
break;
+
case ExternalKind::Memory:
- CheckMemory(loc, import->memory);
+ CheckMemory(loc, &cast<MemoryImport>(import)->memory);
++current_memory_index_;
break;
- case ExternalKind::Global:
- if (import->global->mutable_) {
+
+ case ExternalKind::Global: {
+ auto* global_import = cast<GlobalImport>(import);
+ if (global_import->global.mutable_) {
PrintError(loc, "mutable globals cannot be imported");
}
++num_imported_globals_;
++current_global_index_;
break;
+ }
}
}
@@ -866,31 +863,31 @@ Result Validator::CheckModule(const Module* module) {
current_except_index_ = 0;
for (const ModuleField& field : module->fields) {
- switch (field.type) {
+ switch (field.type()) {
case ModuleFieldType::Except:
++current_except_index_;
- CheckExcept(&field.loc, cast<ExceptionModuleField>(&field)->except);
+ CheckExcept(&field.loc, &cast<ExceptionModuleField>(&field)->except);
break;
case ModuleFieldType::Func:
- CheckFunc(&field.loc, cast<FuncModuleField>(&field)->func);
+ CheckFunc(&field.loc, &cast<FuncModuleField>(&field)->func);
break;
case ModuleFieldType::Global:
- CheckGlobal(&field.loc, cast<GlobalModuleField>(&field)->global);
+ CheckGlobal(&field.loc, &cast<GlobalModuleField>(&field)->global);
current_global_index_++;
break;
case ModuleFieldType::Import:
- CheckImport(&field.loc, cast<ImportModuleField>(&field)->import);
+ CheckImport(&field.loc, cast<ImportModuleField>(&field)->import.get());
break;
case ModuleFieldType::Export:
- CheckExport(&field.loc, cast<ExportModuleField>(&field)->export_);
+ CheckExport(&field.loc, &cast<ExportModuleField>(&field)->export_);
break;
case ModuleFieldType::Table:
- CheckTable(&field.loc, cast<TableModuleField>(&field)->table);
+ CheckTable(&field.loc, &cast<TableModuleField>(&field)->table);
current_table_index_++;
break;
@@ -899,7 +896,7 @@ Result Validator::CheckModule(const Module* module) {
break;
case ModuleFieldType::Memory:
- CheckMemory(&field.loc, cast<MemoryModuleField>(&field)->memory);
+ CheckMemory(&field.loc, &cast<MemoryModuleField>(&field)->memory);
current_memory_index_++;
break;
@@ -942,8 +939,7 @@ Result Validator::CheckModule(const Module* 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.
-const TypeVector* Validator::CheckInvoke(const Action* action) {
- const ActionInvoke* invoke = action->invoke;
+const TypeVector* Validator::CheckInvoke(const InvokeAction* action) {
const Module* module = script_->GetModule(action->module_var);
if (!module) {
PrintError(&action->loc, "unknown module");
@@ -963,7 +959,7 @@ const TypeVector* Validator::CheckInvoke(const Action* action) {
return nullptr;
}
- size_t actual_args = invoke->args.size();
+ size_t actual_args = action->args.size();
size_t expected_args = func->GetNumParams();
if (expected_args != actual_args) {
PrintError(&action->loc, "too %s parameters to function. got %" PRIzd
@@ -973,7 +969,7 @@ const TypeVector* Validator::CheckInvoke(const Action* action) {
return nullptr;
}
for (size_t i = 0; i < actual_args; ++i) {
- const Const* const_ = &invoke->args[i];
+ const Const* const_ = &action->args[i];
CheckTypeIndex(&const_->loc, const_->type, func->GetParamType(i), "invoke",
i, "argument");
}
@@ -981,7 +977,7 @@ const TypeVector* Validator::CheckInvoke(const Action* action) {
return &func->decl.sig.result_types;
}
-Result Validator::CheckGet(const Action* action, Type* out_type) {
+Result Validator::CheckGet(const GetAction* action, Type* out_type) {
const Module* module = script_->GetModule(action->module_var);
if (!module) {
PrintError(&action->loc, "unknown module");
@@ -1035,15 +1031,15 @@ Validator::ActionResult Validator::CheckAction(const Action* action) {
ActionResult result;
ZeroMemory(result);
- switch (action->type) {
+ switch (action->type()) {
case ActionType::Invoke:
- result.types = CheckInvoke(action);
+ result.types = CheckInvoke(cast<InvokeAction>(action));
result.kind =
result.types ? ActionResult::Kind::Types : ActionResult::Kind::Error;
break;
case ActionType::Get:
- if (Succeeded(CheckGet(action, &result.type)))
+ if (Succeeded(CheckGet(cast<GetAction>(action), &result.type)))
result.kind = ActionResult::Kind::Type;
else
result.kind = ActionResult::Kind::Error;
@@ -1078,12 +1074,12 @@ void Validator::CheckAssertReturnNanCommand(const Action* action) {
void Validator::CheckCommand(const Command* command) {
switch (command->type) {
case CommandType::Module:
- CheckModule(cast<ModuleCommand>(command)->module);
+ CheckModule(&cast<ModuleCommand>(command)->module);
break;
case CommandType::Action:
// Ignore result type.
- CheckAction(cast<ActionCommand>(command)->action);
+ CheckAction(cast<ActionCommand>(command)->action.get());
break;
case CommandType::Register:
@@ -1096,17 +1092,17 @@ void Validator::CheckCommand(const Command* command) {
case CommandType::AssertReturn: {
auto* assert_return_command = cast<AssertReturnCommand>(command);
- const Action* action = assert_return_command->action;
+ const Action* action = assert_return_command->action.get();
ActionResult result = CheckAction(action);
switch (result.kind) {
case ActionResult::Kind::Types:
CheckConstTypes(&action->loc, *result.types,
- *assert_return_command->expected, "action");
+ assert_return_command->expected, "action");
break;
case ActionResult::Kind::Type:
CheckConstType(&action->loc, result.type,
- *assert_return_command->expected, "action");
+ assert_return_command->expected, "action");
break;
case ActionResult::Kind::Error:
@@ -1118,21 +1114,21 @@ void Validator::CheckCommand(const Command* command) {
case CommandType::AssertReturnCanonicalNan:
CheckAssertReturnNanCommand(
- cast<AssertReturnCanonicalNanCommand>(command)->action);
+ cast<AssertReturnCanonicalNanCommand>(command)->action.get());
break;
case CommandType::AssertReturnArithmeticNan:
CheckAssertReturnNanCommand(
- cast<AssertReturnArithmeticNanCommand>(command)->action);
+ cast<AssertReturnArithmeticNanCommand>(command)->action.get());
break;
case CommandType::AssertTrap:
// ignore result type.
- CheckAction(cast<AssertTrapCommand>(command)->action);
+ CheckAction(cast<AssertTrapCommand>(command)->action.get());
break;
case CommandType::AssertExhaustion:
// ignore result type.
- CheckAction(cast<AssertExhaustionCommand>(command)->action);
+ CheckAction(cast<AssertExhaustionCommand>(command)->action.get());
break;
}
}