diff options
Diffstat (limited to 'src/wasm-validator.h')
-rw-r--r-- | src/wasm-validator.h | 186 |
1 files changed, 4 insertions, 182 deletions
diff --git a/src/wasm-validator.h b/src/wasm-validator.h index ceaaee890..250779b91 100644 --- a/src/wasm-validator.h +++ b/src/wasm-validator.h @@ -33,6 +33,8 @@ // about function B not existing yet, but we would care // if e.g. inside function A an i32.add receives an i64). // +// * quiet: Whether to log errors verbosely. +// #ifndef wasm_wasm_validator_h #define wasm_wasm_validator_h @@ -46,188 +48,8 @@ namespace wasm { -// Print anything that can be streamed to an ostream -template <typename T, - typename std::enable_if< - !std::is_base_of<Expression, typename std::remove_pointer<T>::type>::value - >::type* = nullptr> -inline std::ostream& printModuleComponent(T curr, std::ostream& stream) { - stream << curr << std::endl; - return stream; -} -// Extra overload for Expressions, to print type info too -inline std::ostream& printModuleComponent(Expression* curr, std::ostream& stream) { - WasmPrinter::printExpression(curr, stream, false, true) << std::endl; - return stream; -} - -struct WasmValidator : public PostWalker<WasmValidator> { - bool valid = true; - - // what to validate, see comment up top - bool validateWeb = false; - bool validateGlobally = true; - - bool quiet = false; // whether to log errors verbosely - - struct BreakInfo { - WasmType type; - Index arity; - BreakInfo() {} - BreakInfo(WasmType type, Index arity) : type(type), arity(arity) {} - }; - - std::map<Name, Expression*> breakTargets; - std::map<Expression*, BreakInfo> breakInfos; - - WasmType returnType = unreachable; // type used in returns - - std::set<Name> labelNames; // Binaryen IR requires that label names must be unique - IR generators must ensure that - - std::unordered_set<Expression*> seenExpressions; // expressions must not appear twice - - void noteLabelName(Name name); - -public: - // TODO: If we want the validator to be part of libwasm rather than libpasses, then - // Using PassRunner::getPassDebug causes a circular dependence. We should fix that, - // perhaps by moving some of the pass infrastructure into libsupport. - bool validate(Module& module, bool validateWeb_ = false, bool validateGlobally_ = true) { - validateWeb = validateWeb_; - validateGlobally = validateGlobally_; - // wasm logic validation - walkModule(&module); - // validate additional internal IR details when in pass-debug mode - if (PassRunner::getPassDebug()) { - validateBinaryenIR(module); - } - // print if an error occurred - if (!valid && !quiet) { - WasmPrinter::printModule(&module, std::cerr); - } - return valid; - } - - // visitors - - static void visitPreBlock(WasmValidator* self, Expression** currp) { - auto* curr = (*currp)->cast<Block>(); - if (curr->name.is()) self->breakTargets[curr->name] = curr; - } - - void visitBlock(Block *curr); - - static void visitPreLoop(WasmValidator* self, Expression** currp) { - auto* curr = (*currp)->cast<Loop>(); - if (curr->name.is()) self->breakTargets[curr->name] = curr; - } - - void visitLoop(Loop *curr); - void visitIf(If *curr); - - // override scan to add a pre and a post check task to all nodes - static void scan(WasmValidator* self, Expression** currp) { - PostWalker<WasmValidator>::scan(self, currp); - - auto* curr = *currp; - if (curr->is<Block>()) self->pushTask(visitPreBlock, currp); - if (curr->is<Loop>()) self->pushTask(visitPreLoop, currp); - } - - void noteBreak(Name name, Expression* value, Expression* curr); - void visitBreak(Break *curr); - void visitSwitch(Switch *curr); - void visitCall(Call *curr); - void visitCallImport(CallImport *curr); - void visitCallIndirect(CallIndirect *curr); - void visitGetLocal(GetLocal* curr); - void visitSetLocal(SetLocal *curr); - void visitLoad(Load *curr); - void visitStore(Store *curr); - void visitAtomicRMW(AtomicRMW *curr); - void visitAtomicCmpxchg(AtomicCmpxchg *curr); - void visitAtomicWait(AtomicWait *curr); - void visitAtomicWake(AtomicWake *curr); - void visitBinary(Binary *curr); - void visitUnary(Unary *curr); - void visitSelect(Select* curr); - void visitDrop(Drop* curr); - void visitReturn(Return* curr); - void visitHost(Host* curr); - void visitImport(Import* curr); - void visitExport(Export* curr); - void visitGlobal(Global* curr); - void visitFunction(Function *curr); - - void visitMemory(Memory *curr); - void visitTable(Table* curr); - void visitModule(Module *curr); - - void doWalkFunction(Function* func) { - PostWalker<WasmValidator>::doWalkFunction(func); - } - - // helpers - private: - template <typename T, typename S> - std::ostream& fail(S text, T curr); - std::ostream& printFailureHeader(); - - template<typename T> - bool shouldBeTrue(bool result, T curr, const char* text) { - if (!result) { - fail("unexpected false: " + std::string(text), curr); - return false; - } - return result; - } - template<typename T> - bool shouldBeFalse(bool result, T curr, const char* text) { - if (result) { - fail("unexpected true: " + std::string(text), curr); - return false; - } - return result; - } - - template<typename T, typename S> - bool shouldBeEqual(S left, S right, T curr, const char* text) { - if (left != right) { - std::ostringstream ss; - ss << left << " != " << right << ": " << text; - fail(ss.str(), curr); - return false; - } - return true; - } - - template<typename T, typename S> - bool shouldBeEqualOrFirstIsUnreachable(S left, S right, T curr, const char* text) { - if (left != unreachable && left != right) { - std::ostringstream ss; - ss << left << " != " << right << ": " << text; - fail(ss.str(), curr); - return false; - } - return true; - } - - template<typename T, typename S> - bool shouldBeUnequal(S left, S right, T curr, const char* text) { - if (left == right) { - std::ostringstream ss; - ss << left << " == " << right << ": " << text; - fail(ss.str(), curr); - return false; - } - return true; - } - - void shouldBeIntOrUnreachable(WasmType ty, Expression* curr, const char* text); - void validateAlignment(size_t align, WasmType type, Index bytes, bool isAtomic, - Expression* curr); - void validateMemBytes(uint8_t bytes, WasmType type, Expression* curr); - void validateBinaryenIR(Module& wasm); +struct WasmValidator { + bool validate(Module& module, bool validateWeb = false, bool validateGlobally = true, bool quiet = false); }; } // namespace wasm |