WebAssembly / binaryen

Optimizer and compiler/toolchain library for WebAssembly
Apache License 2.0
7.51k stars 746 forks source link

Invalid non-nullable local binary emitting related to unreachability #5599

Open kripken opened 1 year ago

kripken commented 1 year ago
(module
 (func $test (param $ref (ref struct)) 
  (local $local (ref struct))
  (drop
   (block (result i32)
    (local.set $local
     (unreachable)       ;; this causes validation of the later local.get to fail
     ;; (local.get $ref) ;; this would be ok
    )
    (i32.const 0)
   )
  )
  (drop
   (local.get $local)
  )
 )
)

bin/wasm-as -all --nominal wat -o wasm emits a binary that V8 complains about, uninitialized non-defaultable local. Binaryen does accept the binary as valid, oddly. Also oddly, replacing the unreachable with something reachable fixes it in V8.

I think Binaryen thinks this validates since the unnamed block is not emitted in the binary format, so the local.set dominates the local.get. But perhaps unreachability makes us behave differently somehow?

tlively commented 1 year ago

We won't emit the local.set $local instruction into the binary, but we will emit the local.get $local, so it makes sense that V8 would complain about this. Replacing the unreachable with something reachable will cause us to emit the local.set, which fixes the problem.

We should update our domination calculation to take into account the fact that unreachable sets won't be emitted.