summaryrefslogtreecommitdiff
path: root/src/wasm-validator.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm-validator.h')
-rw-r--r--src/wasm-validator.h186
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