binaryen
binaryen copied to clipboard
Failure with optimize
I'm generating some working WebAssembly code that fails if I try to run the default optimization passes. The code uses WASM GC, and there are no warnings or errors on validation.
What makes me think it might be a bug is that wasm-opt
works fine on the un-optimized WASM file I write.
The error message is:
/workspace/srcdir/binaryen/src/passes/LocalCSE.cpp:305:
void wasm::{anonymous}::Scanner::visitExpression(wasm::Expression*): Assertion `childOriginalRequests > 0' failed.
Any hints on how to debug this? I'm not sure how to produce a minimum working example. The code in question is shown in the examples here.
If you have a wasm-opt
command that hits that assertion, reducing it to a minimal testcase should be easy with wasm-reduce
, https://github.com/WebAssembly/binaryen/wiki/Fuzzing#reducing
Basically, assuming wasm-opt -all -O2
hits that error, then
bin/wasm-reduce start.wasm "--command=bin/wasm-opt -all -O2 test.wasm" -t test.wasm -w work.wasm
I haven't found a case where wasm-opt
fails. It only fails when calling BinaryenModuleOptimize(mod)
with the C API.
Perhaps you can save the module before optimization and do a reduction on a small program that loads it and calls BinaryenModuleOptimize
? wasm-reduce
can be run on any program that reads a wasm file.
I tried writing the small program to load a file and then run BinaryenModuleOptimize
. I couldn't get that to fail. I can't reproduce the error after reading from a file. Not sure what to try next.
As a workaround, I can write and read the wasm file, optimize, then rewrite it. That's better than shelling out to wasm-opt
. Also, BinaryenModuleOptimize
doesn't fail if I set the following:
BinaryenSetShrinkLevel(0)
BinaryenSetOptimizeLevel(2)
Another option for debugging here is to set BINARYEN_PASS_DEBUG=3
in the environment. That will write out a file after each pass. The last pass before that failure should then fail if you run wasm-opt THAT_FILE.wasm --local-cse
, that is, running the next pass where you saw the error should continue from that step, and error.
If none of this works for you, if you can provide a reasonably small testcase in any form I can look into it.
I didn't have luck with BINARYEN_PASS_DEBUG
. I could not reproduce the crash with wasm-opt
with any file saved.
I am still not able to get you a great reproducer. I found an interesting work-around. This crashes:
BinaryenModuleValidate(ctx.mod)
BinaryenSetShrinkLevel(1)
BinaryenSetOptimizeLevel(3)
BinaryenModuleOptimize(ctx.mod)
Using a two-step optimization, the following doesn't crash:
BinaryenModuleValidate(ctx.mod)
BinaryenSetShrinkLevel(0)
BinaryenSetOptimizeLevel(2)
BinaryenModuleOptimize(ctx.mod)
BinaryenSetShrinkLevel(1)
BinaryenSetOptimizeLevel(3)
BinaryenModuleOptimize(ctx.mod)
I tried adding instrumentation for my code generation to produce more vanilla C-type Binaryen, but I failed at that. Any time I write anything out and read it back in or try wasm-opt
, it doesn't crash.
local-cse
crashes if I run it right away.
BinaryenModuleValidate(ctx.mod)
BinaryenModuleRunPasses(ctx.mod, ["local-cse"], 1)
It doesn't crash if I run other stuff first:
BinaryenModuleValidate(ctx.mod)
BinaryenSetShrinkLevel(0)
BinaryenSetOptimizeLevel(2)
BinaryenModuleOptimize(ctx.mod)
BinaryenModuleRunPasses(ctx.mod, ["local-cse"], 1)
I don't know what to try next. Unless someone wants to try out Julia, I haven't come up with a good reproducer. In Julia, the code to reproduce is pretty small.
Sounds like running local-cse
is the simplest way to crash it. What happens if you print the module before that, then load that text in wasm-opt text.wat --local-cse
? (if the issue is related to unreachable code, writing to binary would remove that code and hide the bug, but not text, so there's a chance this will help)
If that doesn't work, that text + a full stack trace (from gdb, that is, the full path to that visitExpression
that crashes) might be enough for me to see something curious, if we're lucky (but it would be far better if the crash reproduces on the text).
(I unfortunately don't know anything about Julia, so it would probably take much longer for me to try to get that set up to reproduce the problem that way, but if nothing else works out that's an option too... :smile: )