class Validator : public ExprVisitor::Delegate { public:
Validator(Errors*, const Module* module, const ValidateOptions& options);
Result CheckModule();
Result OnBinaryExpr(BinaryExpr*) override;
Result BeginBlockExpr(BlockExpr*) override;
Result EndBlockExpr(BlockExpr*) override;
Result OnBrExpr(BrExpr*) override;
Result OnBrIfExpr(BrIfExpr*) override;
Result OnBrTableExpr(BrTableExpr*) override;
Result OnCallExpr(CallExpr*) override;
Result OnCallIndirectExpr(CallIndirectExpr*) override;
Result OnCallRefExpr(CallRefExpr*) override;
Result OnCodeMetadataExpr(CodeMetadataExpr*) override;
Result OnCompareExpr(CompareExpr*) override;
Result OnConstExpr(ConstExpr*) override;
Result OnConvertExpr(ConvertExpr*) override;
Result OnDropExpr(DropExpr*) override;
Result OnGlobalGetExpr(GlobalGetExpr*) override;
Result OnGlobalSetExpr(GlobalSetExpr*) override;
Result BeginIfExpr(IfExpr*) override;
Result AfterIfTrueExpr(IfExpr*) override;
Result EndIfExpr(IfExpr*) override;
Result OnLoadExpr(LoadExpr*) override;
Result OnLocalGetExpr(LocalGetExpr*) override;
Result OnLocalSetExpr(LocalSetExpr*) override;
Result OnLocalTeeExpr(LocalTeeExpr*) override;
Result BeginLoopExpr(LoopExpr*) override;
Result EndLoopExpr(LoopExpr*) override;
Result OnMemoryCopyExpr(MemoryCopyExpr*) override;
Result OnDataDropExpr(DataDropExpr*) override;
Result OnMemoryFillExpr(MemoryFillExpr*) override;
Result OnMemoryGrowExpr(MemoryGrowExpr*) override;
Result OnMemoryInitExpr(MemoryInitExpr*) override;
Result OnMemorySizeExpr(MemorySizeExpr*) override;
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 OnTableFillExpr(TableFillExpr*) override;
Result OnRefFuncExpr(RefFuncExpr*) override;
Result OnRefNullExpr(RefNullExpr*) override;
Result OnRefIsNullExpr(RefIsNullExpr*) override;
Result OnNopExpr(NopExpr*) override;
Result OnReturnExpr(ReturnExpr*) override;
Result OnReturnCallExpr(ReturnCallExpr*) override;
Result OnReturnCallIndirectExpr(ReturnCallIndirectExpr*) override;
Result OnSelectExpr(SelectExpr*) override;
Result OnStoreExpr(StoreExpr*) override;
Result OnUnaryExpr(UnaryExpr*) override;
Result OnUnreachableExpr(UnreachableExpr*) override;
Result BeginTryExpr(TryExpr*) override;
Result OnCatchExpr(TryExpr*, Catch*) override;
Result OnDelegateExpr(TryExpr*) override;
Result EndTryExpr(TryExpr*) override;
Result OnThrowExpr(ThrowExpr*) override;
Result OnRethrowExpr(RethrowExpr*) override;
Result OnAtomicWaitExpr(AtomicWaitExpr*) override;
Result OnAtomicFenceExpr(AtomicFenceExpr*) override;
Result OnAtomicNotifyExpr(AtomicNotifyExpr*) override;
Result OnAtomicLoadExpr(AtomicLoadExpr*) override;
Result OnAtomicStoreExpr(AtomicStoreExpr*) override;
Result OnAtomicRmwExpr(AtomicRmwExpr*) override;
Result OnAtomicRmwCmpxchgExpr(AtomicRmwCmpxchgExpr*) override;
Result OnTernaryExpr(TernaryExpr*) override;
Result OnSimdLaneOpExpr(SimdLaneOpExpr*) override;
Result OnSimdLoadLaneExpr(SimdLoadLaneExpr*) override;
Result OnSimdStoreLaneExpr(SimdStoreLaneExpr*) override;
Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) override;
Result OnLoadSplatExpr(LoadSplatExpr*) override;
Result OnLoadZeroExpr(LoadZeroExpr*) override;
private:
Type GetDeclarationType(const FuncDeclaration&);
Var GetFuncTypeIndex(const Location&, const FuncDeclaration&);
void ScriptValidator::CheckExpectation(const Location* loc, const TypeVector& result_types, const ConstVector& expected, constchar* desc) { // Here we take the concrete expected output types verify those actains // the types that are the result of the action.
TypeVector actual_types; for (auto ex : expected) {
actual_types.push_back(ex.type());
}
CheckResultTypes(loc, actual_types, result_types, desc);
}
case ExternalKind::Global: { auto&& global = cast<GlobalImport>(f->import.get())->global;
result_ |= validator_.OnGlobalImport(field.loc, global.type,
global.mutable_); break;
}
case ExternalKind::Tag: { auto&& tag = cast<TagImport>(f->import.get())->tag;
result_ |= validator_.OnTag(field.loc,
GetFuncTypeIndex(field.loc, tag.decl)); break;
}
}
}
}
// Func section. for (const ModuleField& field : module->fields) { if (auto* f = dyn_cast<FuncModuleField>(&field)) {
result_ |= validator_.OnFunction(
field.loc, GetFuncTypeIndex(field.loc, f->func.decl));
}
}
// Table section. for (const ModuleField& field : module->fields) { if (auto* f = dyn_cast<TableModuleField>(&field)) {
result_ |= validator_.OnTable(field.loc, f->table.elem_type,
f->table.elem_limits);
}
}
// Memory section. for (const ModuleField& field : module->fields) { if (auto* f = dyn_cast<MemoryModuleField>(&field)) {
result_ |= validator_.OnMemory(field.loc, f->memory.page_limits,
f->memory.page_size);
}
}
// Global section. for (const ModuleField& field : module->fields) { if (auto* f = dyn_cast<GlobalModuleField>(&field)) {
result_ |=
validator_.OnGlobal(field.loc, f->global.type, f->global.mutable_);
// Tag section. for (const ModuleField& field : module->fields) { if (auto* f = dyn_cast<TagModuleField>(&field)) {
result_ |=
validator_.OnTag(field.loc, GetFuncTypeIndex(field.loc, f->tag.decl));
}
}
// Export section. for (const ModuleField& field : module->fields) { if (auto* f = dyn_cast<ExportModuleField>(&field)) {
result_ |= validator_.OnExport(field.loc, f->export_.kind, f->export_.var,
f->export_.name);
}
}
// Start section. for (const ModuleField& field : module->fields) { if (auto* f = dyn_cast<StartModuleField>(&field)) {
result_ |= validator_.OnStart(field.loc, f->start);
}
}
// Elem segment section. for (const ModuleField& field : module->fields) { if (auto* f = dyn_cast<ElemSegmentModuleField>(&field)) {
result_ |= validator_.OnElemSegment(field.loc, f->elem_segment.table_var,
f->elem_segment.kind);
// Data segment section. for (const ModuleField& field : module->fields) { if (auto* f = dyn_cast<DataSegmentModuleField>(&field)) {
result_ |= validator_.OnDataSegment(field.loc, f->data_segment.memory_var,
f->data_segment.kind);
// 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* ScriptValidator::CheckInvoke(const InvokeAction* action) { const Module* module = script_->GetModule(action->module_var); if (!module) {
PrintError(&action->loc, "unknown module"); return nullptr;
}
const Export* export_ = module->GetExport(action->name); if (!export_) {
PrintError(&action->loc, "unknown function export \"%s\"",
action->name.c_str()); return nullptr;
}
const Func* func = module->GetFunc(export_->var); if (!func) { // This error will have already been reported, just skip it. return nullptr;
}
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 ", expected %" PRIzd,
actual_args > expected_args ? "many" : "few", actual_args,
expected_args); return nullptr;
} for (size_t i = 0; i < actual_args; ++i) { constConst* const_ = &action->args[i];
CheckTypeIndex(&const_->loc, const_->type(), func->GetParamType(i), "invoke", i, "argument");
}
const Export* export_ = module->GetExport(action->name); if (!export_) {
PrintError(&action->loc, "unknown global export \"%s\"",
action->name.c_str()); return Result::Error;
}
const Global* global = module->GetGlobal(export_->var); if (!global) { // This error will have already been reported, just skip it. return Result::Error;
}
case CommandType::Action: // Ignore result type.
CheckAction(cast<ActionCommand>(command)->action.get()); break;
case CommandType::Register: case CommandType::AssertMalformed: case CommandType::AssertInvalid: case CommandType::AssertUnlinkable: case CommandType::AssertUninstantiable: // Ignore. break;
case ActionResult::Kind::Type:
CheckExpectationTypes(&action->loc, {result.type}, expected, "action"); break;
case ActionResult::Kind::Error: // Error occurred, don't do any further checks. break;
} break;
}
case CommandType::AssertTrap: // ignore result type.
CheckAction(cast<AssertTrapCommand>(command)->action.get()); break; case CommandType::AssertExhaustion: // ignore result type.
CheckAction(cast<AssertExhaustionCommand>(command)->action.get()); break; case CommandType::AssertException: // ignore result type.
CheckAction(cast<AssertExceptionCommand>(command)->action.get()); break;
}
}
Result ScriptValidator::CheckScript() { for (const std::unique_ptr<Command>& command : script_->commands)
CheckCommand(command.get()); return result_;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.