diff options
author | Thomas Lively <tlively@google.com> | 2024-04-16 10:43:50 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-16 10:43:50 -0700 |
commit | 359d5aa30ca8349fd38e6968350e7ab4280c1cbb (patch) | |
tree | c2e32021ae74c2dfa706dc4d4ebd4257d19ad2db /test/lit/help/wasm-as.test | |
parent | e29d77848b89846cf3519491fee581b507e3b194 (diff) | |
download | binaryen-359d5aa30ca8349fd38e6968350e7ab4280c1cbb.tar.gz binaryen-359d5aa30ca8349fd38e6968350e7ab4280c1cbb.tar.bz2 binaryen-359d5aa30ca8349fd38e6968350e7ab4280c1cbb.zip |
[Parser] Pop past unreachables where possible (#6489)
We previously would eagerly drop all concretely typed expressions on the stack
when pushing an unreachable instruction. This was semantically correct and
closely modeled the semantics of unreachable instructions, which implicitly drop
the entire stack and start a new polymorphic stack. However, it also meant that
the structure of the parsed IR did not match the structure of the folded input,
which meant that tests involving unreachable children would not parse as
intended, preventing the test from testing the intended behavior.
For example, this wat:
```wasm
(i32.add
(i32.const 0)
(unreachable)
)
```
Would previously parse into this IR:
```wasm
(drop
(i32.const 0)
)
(i32.add
(unreachable)
(unreachable)
)
```
To fix this problem, we need to stop eagerly dropping stack values when
encountering an unreachable instruction so we can still pop expressions pushed
before the unreachable as direct children of later instructions. In the example
above, we need to keep the `i32.const 0` on the stack so it is available to be
popped and become a child of the `i32.add`.
However, the naive solution of simply popping past unreachables would produce
invalid IR in some cases. For example, consider this wat:
```wasm
f32.const 0
unreachable
i32.add
```
The naive solution would parse this wat into this IR:
```wasm
(i32.add
(f32.const 0)
(unreachable)
)
```
But we do not want to parse an `i32.add` with an `f32`-typed child. Neither do
we want to reject this input, since it is a perfectly valid Wasm fragment. In this
case, we actually want the old behavior of dropping the `f32.const` and
replacing it with another `unreachable` as the first child of the `i32.add`.
To both match the input structure where possible and also gracefully fall back
to the old behavior of dropping expressions prior to the unreachable, collect
constraints on the types of each child for each kind of expression and compare
them to the types of available expressions on the stack when an unreachable
instruction will be popped. When the constraints are satisfied, pop expressions
normally, even after popping the unreachable instruction. Otherwise, drop the
instructions that precede the unreachable instruction to ensure we parse valid
IR.
To collect the constraints, add a new `ChildTyper` utility that calls a
different callback for each kind of possible type constraint for each child. In
the future, this utility can be used to simplify the validator as well.
Diffstat (limited to 'test/lit/help/wasm-as.test')
0 files changed, 0 insertions, 0 deletions