diff options
Diffstat (limited to 'src/validator.cc')
-rw-r--r-- | src/validator.cc | 146 |
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; } } |