Skip to content

Fix #8785: StackEntry wasm stack type invariants and unreachable parser regressions - #8978

Open
ANAMASGARD wants to merge 7 commits into
WebAssembly:mainfrom
ANAMASGARD:fix/parser-validation-stack-underflow
Open

Fix #8785: StackEntry wasm stack type invariants and unreachable parser regressions#8978
ANAMASGARD wants to merge 7 commits into
WebAssembly:mainfrom
ANAMASGARD:fix/parser-validation-stack-underflow

Conversation

@ANAMASGARD

Copy link
Copy Markdown

Fixes parser/IRBuilder regressions from tracking Wasm operand-stack effects separately via StackEntry::wasmStackType (#8785).

  • Introduce wasmStackType on the IRBuilder expression stack and keep it in sync with Wasm stack semantics (unreachable barriers vs ordinary void instructions).
  • Fix unreachable operand popping for GC/array stores, struct.new, try/return_call, and related control-flow edge cases.
  • Drop non-final concrete stack entries when building typed multi-expression blocks.
  • Treat unreachable-typed void control flow as poppable where baseline did (fixes -S pipe roundtrip, e.g. array-multibyte).
  • Update ~93 lit -S expectations: output shape changes (extra block/drop/unreachable nesting), not semantic IR changes.

Test plan

  • build-clang/bin/binaryen-unittests — 379/379
  • build-clang/bin/binaryen-lit test/lit -j 2 — 982/986 (only 4 pre-existing d8/fuzz_shell*.wast failures; need v8)
  • Targeted validation tests: test/lit/validation/unreachable-*.wast
  • Hard failures cleared: array-multibyte, wat-kitchen-sink, remove-unused-brs_enable-multivalue, wasm-split/split-module-items

Track Wasm operand-stack effects separately from Binaryen IR types via
StackEntry::wasmStackType. Key fixes:
- Sync wasmStackType to none when dropping unreachable predecessors
- Guard finishScope tuple repackaging when hoist is empty
- Mask deeper stack values under unreachable in hoistLastValue

Adds validation tests for unreachable void-block drop, multivalue tuple
parsing, and related edge cases.
Extend pushControlFlow/finishScope handling so void unreachable fallthrough
control flow and return_call inside try remain parseable in concrete-result
functions, while preserving WebAssembly#8785 rejection of (block (unreachable)) (drop).

Allow void unreachable fallthrough blocks to satisfy concrete operand pops
(e.g. if/br_if conditions). Skip struct.get field typing when the ref is
unreachable. Add focused validation regressions for try/return_call and
concrete block ends.

Lit ledger: /tmp/binaryen-lit-ledger/report.md
Track void stack entries skipped in unreachable scopes so operand
popping can match concrete values below (gufa struct.new) while still
synthesizing unreachable operands when types mismatch (br_table index).
Treat wasm unreachable instructions (wasmStackType none but expr type
unreachable) as polymorphic stack values in hoistLastValue,
checkNeedsUnreachableFallback, and pop. Drop non-final concrete stack
entries when building typed multi-expression blocks.

Fixes array-multibyte parser failure and wasm-split validator errors.
Adds unreachable-array-store-value-valid.wast regression test.
When wasmStackType is none but a void block retains expr->type
unreachable, treat it as a poppable stack entry. Fixes -S pipe
roundtrip on array-multibyte and drop(block) reparse paths.
The parser now distinguishes unreachable barriers from ordinary void
entries, which changes block/drop/unreachable nesting in -S output
across many tests. Also fixes scratch-local-roundtrip RTRIP checks
and updates two validation tests to match baseline parse behavior.
@ANAMASGARD
ANAMASGARD requested a review from a team as a code owner August 7, 2026 06:37
@ANAMASGARD
ANAMASGARD requested review from aheejin and removed request for a team August 7, 2026 06:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant