diff options
Diffstat (limited to 'src/passes/pass.cpp')
-rw-r--r-- | src/passes/pass.cpp | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index 8dcc7e417..570cd8610 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -891,18 +891,48 @@ void PassRunner::runPass(Pass* pass) { void PassRunner::runPassOnFunction(Pass* pass, Function* func) { assert(pass->isFunctionParallel()); + + auto passDebug = getPassDebug(); + + // Add extra validation logic in pass-debug mode 2. The main logic in + // PassRunner::run will work at the module level, and here for a function- + // parallel pass we can do the same at the function level: we can print the + // function before the pass, run the pass on the function, and then if it + // fails to validate we can show an error and print the state right before the + // pass broke it. + // + // Skip nameless passes for this. Anything without a name is an internal + // component of some larger pass, and information about it won't be very + // useful - leave it to the entire module to fail validation in that case. + bool extraFunctionValidation = + passDebug == 2 && options.validate && !pass->name.empty(); + std::stringstream bodyBefore; + if (extraFunctionValidation) { + bodyBefore << *func->body << '\n'; + } + // function-parallel passes get a new instance per function auto instance = std::unique_ptr<Pass>(pass->create()); std::unique_ptr<AfterEffectFunctionChecker> checker; - if (getPassDebug()) { + if (passDebug) { checker = std::unique_ptr<AfterEffectFunctionChecker>( new AfterEffectFunctionChecker(func)); } instance->runOnFunction(this, wasm, func); handleAfterEffects(pass, func); - if (getPassDebug()) { + if (passDebug) { checker->check(); } + + if (extraFunctionValidation) { + if (!WasmValidator().validate(func, *wasm, WasmValidator::Minimal)) { + Fatal() << "Last nested function-parallel pass (" << pass->name + << ") broke validation of function " << func->name + << ". Here is the function body before:\n" + << bodyBefore.str() << "\n\nAnd here it is now:\n" + << *func->body << '\n'; + } + } } void PassRunner::handleAfterEffects(Pass* pass, Function* func) { |