diff options
-rwxr-xr-x | check.py | 31 | ||||
-rw-r--r-- | src/wasm-binary.h | 18 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 22 | ||||
-rw-r--r-- | test/elided-br.wasm | bin | 0 -> 33 bytes | |||
-rw-r--r-- | test/elided-br.wasm.fromBinary | 9 |
5 files changed, 62 insertions, 18 deletions
@@ -39,6 +39,19 @@ if options.interpreter: print '[ using wasm interpreter at "%s" ]' % options.interpreter assert os.path.exists(options.interpreter), 'interpreter not found' +# run a check with BINARYEN_PASS_DEBUG set, to do full validation +def with_pass_debug(check): + old_pass_debug = os.environ.get('BINARYEN_PASS_DEBUG') + try: + os.environ['BINARYEN_PASS_DEBUG'] = '1' + check() + finally: + if old_pass_debug is not None: + os.environ['BINARYEN_PASS_DEBUG'] = old_pass_debug + else: + if 'BINARYEN_PASS_DEBUG' in os.environ: + del os.environ['BINARYEN_PASS_DEBUG'] + # tests def run_help_tests(): @@ -99,17 +112,10 @@ def run_wasm_opt_tests(): debugged = run_command(cmd + ['--debug'], stderr=subprocess.PIPE) fail_if_not_contained(actual, debugged) # also check pass-debug mode - old_pass_debug = os.environ.get('BINARYEN_PASS_DEBUG') - try: - os.environ['BINARYEN_PASS_DEBUG'] = '1' + def check(): pass_debug = run_command(cmd) fail_if_not_identical(curr, pass_debug) - finally: - if old_pass_debug is not None: - os.environ['BINARYEN_PASS_DEBUG'] = old_pass_debug - else: - if 'BINARYEN_PASS_DEBUG' in os.environ: - del os.environ['BINARYEN_PASS_DEBUG'] + with_pass_debug(check) expected_file = os.path.join(options.binaryen_test, 'passes', base + ('.bin' if binary else '') + '.txt') @@ -167,9 +173,14 @@ def run_wasm_dis_tests(): if os.path.isfile(t + '.map'): cmd += ['--source-map', t + '.map'] actual = run_command(cmd) - fail_if_not_identical_to_file(actual, t + '.fromBinary') + # also verify there are no validation errors + def check(): + cmd = WASM_OPT + [t] + actual = run_command(cmd) + with_pass_debug(check) + def run_wasm_merge_tests(): print '\n[ checking wasm-merge... ]\n' diff --git a/src/wasm-binary.h b/src/wasm-binary.h index b8eb86d31..4b4a37888 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -895,8 +895,22 @@ public: std::vector<Expression*> expressionStack; - bool definitelyUnreachable; // set when we know code is definitely unreachable. this helps parse - // stacky wasm code, which can be unsuitable for our IR when unreachable + // set when we know code is unreachable in the sense of the wasm spec: we are in a block + // and after an unreachable element. + // this helps parse stacky wasm code, which can be unsuitable for our IR when unreachable. + bool unreachableInTheWasmSense; + + // set when the current code being processed will not be emitted in the output, which is the + // case when it is literally unreachable, for example, + // (block $a + // (unreachable) + // (block $b + // ;; code here is reachable in the wasm sense, even though $b as a whole is not + // (unreachable) + // ;; code here is unreachable in the wasm sense + // ) + // ) + bool willBeIgnored; BinaryConsts::ASTNodes lastSeparator = BinaryConsts::End; diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index f70f74c56..e0c75badc 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1753,6 +1753,7 @@ void WasmBinaryBuilder::readFunctions() { if (debug) std::cerr << "processing function: " << i << std::endl; nextLabel = 0; useDebugLocation = false; + willBeIgnored = false; // process body assert(breakTargetNames.size() == 0); assert(breakStack.empty()); @@ -1957,7 +1958,7 @@ void WasmBinaryBuilder::readGlobals() { void WasmBinaryBuilder::processExpressions() { if (debug) std::cerr << "== processExpressions" << std::endl; - definitelyUnreachable = false; + unreachableInTheWasmSense = false; while (1) { Expression* curr; auto ret = readExpression(curr); @@ -1996,19 +1997,24 @@ void WasmBinaryBuilder::skipUnreachableCode() { // unreachable, and we can ignore anything after it. things after it may pop, // we want to undo that auto savedStack = expressionStack; + // note we are entering unreachable code, and note what the state as before so + // we can restore it + auto before = willBeIgnored; + willBeIgnored = true; // clear the stack. nothing should be popped from there anyhow, just stuff // can be pushed and then popped. Popping past the top of the stack will // result in uneachables being returned expressionStack.clear(); while (1) { - // set the definitelyUnreachable flag each time, as sub-blocks may set and unset it - definitelyUnreachable = true; + // set the unreachableInTheWasmSense flag each time, as sub-blocks may set and unset it + unreachableInTheWasmSense = true; Expression* curr; auto ret = readExpression(curr); if (!curr) { if (debug) std::cerr << "== skipUnreachableCode finished" << std::endl; lastSeparator = ret; - definitelyUnreachable = false; + unreachableInTheWasmSense = false; + willBeIgnored = before; expressionStack = savedStack; return; } @@ -2019,7 +2025,7 @@ void WasmBinaryBuilder::skipUnreachableCode() { Expression* WasmBinaryBuilder::popExpression() { if (debug) std::cerr << "== popExpression" << std::endl; if (expressionStack.empty()) { - if (definitelyUnreachable) { + if (unreachableInTheWasmSense) { // in unreachable code, trying to pop past the polymorphic stack // area results in receiving unreachables if (debug) std::cerr << "== popping unreachable from polymorphic stack" << std::endl; @@ -2460,7 +2466,11 @@ WasmBinaryBuilder::BreakTarget WasmBinaryBuilder::getBreakTarget(int32_t offset) } if (debug) std::cerr << "breaktarget "<< breakStack[index].name << " arity " << breakStack[index].arity << std::endl; auto& ret = breakStack[index]; - breakTargetNames.insert(ret.name); + // if the break is in literally unreachable code, then we will not emit it anyhow, + // so do not note that the target has breaks to it + if (!willBeIgnored) { + breakTargetNames.insert(ret.name); + } return ret; } diff --git a/test/elided-br.wasm b/test/elided-br.wasm Binary files differnew file mode 100644 index 000000000..71034a449 --- /dev/null +++ b/test/elided-br.wasm diff --git a/test/elided-br.wasm.fromBinary b/test/elided-br.wasm.fromBinary new file mode 100644 index 000000000..c248ded7d --- /dev/null +++ b/test/elided-br.wasm.fromBinary @@ -0,0 +1,9 @@ +(module + (type $0 (func)) + (func $0 (; 0 ;) (type $0) + (block $label$1 + (unreachable) + ) + ) +) + |