Asyncify does not support unwinding from functions returning non-nullable values
Hi,
While testing some wasm-opt options for Wasocaml, I found the following assertion failure:
$ wasm-opt -O3 --enable-gc --enable-tail-call --enable-reference-types --enable-multivalue --enable-exception-handling a.out.wasm -o a.out.optimised.wasm --asyncify
wasm-opt: ~/dev/cpp/binaryen/src/ir/literal-utils.h:35: wasm::Expression* wasm::LiteralUtils::makeZero(wasm::Type, wasm::Module&): Assertion `canMakeZero(type)' failed.
zsh: IOT instruction wasm-opt -O3 --enable-gc --enable-tail-call --enable-reference-types -o
I'm on a recent version:
$ wasm-opt version 119 (version_119-55-g7e1413902)
It works without --asyncify.
The binary file is attached, I don't have the text version sorry. I uploaded it as a .jpeg otherwise GitHub won't let me do it: .
Thanks!
This may be the same issue as #6989, as Asyncify uses Flatten internally. If not, please upload the file as an archive and I can take a look.
Here is an archive: asyncify.zip. I'm not sure it's related but it probably is.
Thanks. This is a real Asyncify issue, it turns out. Reduced testcase:
(module
(import "a" "b" (func $import))
(func $0 (result (ref i31))
(call $import)
(unreachable)
)
)
The result of the function is non-nullable. Asyncify works by returning twice, that is, when we pause, we flow out of the function from the pause point, and when we resume we flow back to that point and then continue normally. But the first return must return a value, even if the outside will ignore it, and there is no non-nullable value we can emit. makeZero can't make a null for it, and makeUnreachable would just trap.
We should probably document this as a limitation of Asyncify, with the workaround that function returns must be nullable in functions that unwind, unless I'm missing something.