diff options
Diffstat (limited to 'src/validator.cc')
-rw-r--r-- | src/validator.cc | 72 |
1 files changed, 60 insertions, 12 deletions
diff --git a/src/validator.cc b/src/validator.cc index 24895bb2..6392f884 100644 --- a/src/validator.cc +++ b/src/validator.cc @@ -76,6 +76,12 @@ class Validator : public ExprVisitor::Delegate { Result OnTableCopyExpr(TableCopyExpr*) override; Result OnElemDropExpr(ElemDropExpr*) override; Result OnTableInitExpr(TableInitExpr*) override; + Result OnTableGetExpr(TableGetExpr*) override; + Result OnTableSetExpr(TableSetExpr*) override; + Result OnTableGrowExpr(TableGrowExpr*) override; + Result OnTableSizeExpr(TableSizeExpr*) override; + Result OnRefNullExpr(RefNullExpr*) override; + Result OnRefIsNullExpr(RefIsNullExpr*) override; Result OnNopExpr(NopExpr*) override; Result OnReturnExpr(ReturnExpr*) override; Result OnReturnCallExpr(ReturnCallExpr*) override; @@ -166,7 +172,7 @@ class Validator : public ExprVisitor::Delegate { const char* desc); void CheckExprList(const Location* loc, const ExprList& exprs); bool CheckHasMemory(const Location* loc, Opcode opcode); - bool CheckHasTable(const Location* loc, Opcode opcode); + bool CheckHasTable(const Location* loc, Opcode opcode, Index index = 0); void CheckHasSharedMemory(const Location* loc, Opcode opcode); void CheckBlockDeclaration(const Location* loc, Opcode opcode, @@ -491,10 +497,10 @@ bool Validator::CheckHasMemory(const Location* loc, Opcode opcode) { return true; } -bool Validator::CheckHasTable(const Location* loc, Opcode opcode) { - if (current_module_->tables.size() == 0) { - PrintError(loc, "%s requires an imported or defined table.", - opcode.GetName()); +bool Validator::CheckHasTable(const Location* loc, Opcode opcode, Index index) { + if (current_module_->tables.size() <= index) { + PrintError(loc, "%s requires table %d to be an imported or defined table.", + opcode.GetName(), index); return false; } @@ -607,9 +613,7 @@ Result Validator::OnCallExpr(CallExpr* expr) { Result Validator::OnCallIndirectExpr(CallIndirectExpr* expr) { expr_loc_ = &expr->loc; - if (current_module_->tables.size() == 0) { - PrintError(&expr->loc, "found call_indirect operator, but no table"); - } + CheckHasTable(&expr->loc, Opcode::CallIndirect, expr->table.index()); CheckFuncSignature(&expr->loc, expr->decl); typechecker_.OnCallIndirect(expr->decl.sig.param_types, expr->decl.sig.result_types); @@ -793,6 +797,46 @@ Result Validator::OnTableInitExpr(TableInitExpr* expr) { return Result::Ok; } +Result Validator::OnTableGetExpr(TableGetExpr* expr) { + expr_loc_ = &expr->loc; + CheckHasTable(&expr->loc, Opcode::TableGet, expr->var.index()); + typechecker_.OnTableGet(expr->var.index()); + return Result::Ok; +} + +Result Validator::OnTableSetExpr(TableSetExpr* expr) { + expr_loc_ = &expr->loc; + CheckHasTable(&expr->loc, Opcode::TableSet, expr->var.index()); + typechecker_.OnTableSet(expr->var.index()); + return Result::Ok; +} + +Result Validator::OnTableGrowExpr(TableGrowExpr* expr) { + expr_loc_ = &expr->loc; + CheckHasTable(&expr->loc, Opcode::TableGrow, expr->var.index()); + typechecker_.OnTableGrow(expr->var.index()); + return Result::Ok; +} + +Result Validator::OnTableSizeExpr(TableSizeExpr* expr) { + expr_loc_ = &expr->loc; + CheckHasTable(&expr->loc, Opcode::TableSize, expr->var.index()); + typechecker_.OnTableSize(expr->var.index()); + return Result::Ok; +} + +Result Validator::OnRefNullExpr(RefNullExpr* expr) { + expr_loc_ = &expr->loc; + typechecker_.OnRefNullExpr(); + return Result::Ok; +} + +Result Validator::OnRefIsNullExpr(RefIsNullExpr* expr) { + expr_loc_ = &expr->loc; + typechecker_.OnRefIsNullExpr(); + return Result::Ok; +} + Result Validator::OnNopExpr(NopExpr* expr) { expr_loc_ = &expr->loc; return Result::Ok; @@ -816,9 +860,7 @@ Result Validator::OnReturnCallExpr(ReturnCallExpr* expr) { Result Validator::OnReturnCallIndirectExpr(ReturnCallIndirectExpr* expr) { expr_loc_ = &expr->loc; - if (current_module_->tables.empty()) { - PrintError(&expr->loc, "found return_call_indirect operator, but no table"); - } + CheckHasTable(&expr->loc, Opcode::ReturnCallIndirect, expr->table.index()); CheckFuncSignature(&expr->loc, expr->decl); typechecker_.OnReturnCallIndirect(expr->decl.sig.param_types, expr->decl.sig.result_types); @@ -1055,7 +1097,7 @@ void Validator::CheckLimits(const Location* loc, } void Validator::CheckTable(const Location* loc, const Table* table) { - if (current_table_index_ == 1) { + if (current_table_index_ == 1 && !options_.features.reference_types_enabled()) { PrintError(loc, "only one table allowed"); } CheckLimits(loc, &table->elem_limits, UINT32_MAX, "elems"); @@ -1063,6 +1105,12 @@ void Validator::CheckTable(const Location* loc, const Table* table) { if (table->elem_limits.is_shared) { PrintError(loc, "tables may not be shared"); } + if (table->elem_type == Type::Anyref && !options_.features.reference_types_enabled()) { + PrintError(loc, "tables must have anyref type"); + } + if (table->elem_type != Type::Anyref && table->elem_type != Type::Anyfunc) { + PrintError(loc, "tables must have anyref or anyfunc type"); + } } void Validator::CheckElemSegments(const Module* module) { |