You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
--i64-to-i32-lowering rewrites the type of a return_call_indirect to (func (result unreachable)), even in a module with no i64 at all, so writing a binary aborts and writing text produces a module that does not parse.
I expected the call to keep (type $t): the input is valid (wasm-opt without the pass accepts it), there is nothing to lower, and the pass only rejects return calls with i64 results (with a clean Fatal), so other return calls look meant to be supported.
Found at commit 93d6e9d and still reproduces at 207bbae. A release build aborts the same way (SIGABRT) on binary output; with text output it exits 0 and writes the invalid module above. The validator does not report anything before writing.
Looks like visitGenericCall in src/passes/I64ToI32Lowering.cpp passes curr->type as the results when the call does not return i64, and for a return call that is unreachable, so visitCallIndirect builds Signature(Type(params), unreachable) as the new heap type; using the lowered curr->heapType.getSignature().results would avoid it.
Found with an LLM-based testing tool; I used Claude to reduce it and look for the cause.
I'd like to pick this up. The fix I have in mind is in visitGenericCall in src/passes/I64ToI32Lowering.cpp: when the call does not return i64, take the results from the call's signature instead of curr->type, so a return_call_indirect keeps its original type instead of getting (func (result unreachable)). I'll add a lit test under test/lit/passes with the module from the report and open a PR, unless someone is already on it.
Activity
akshat-lakhera commentedon Oct 25, 2026
I'd like to pick this up. The fix I have in mind is in visitGenericCall in src/passes/I64ToI32Lowering.cpp: when the call does not return i64, take the results from the call's signature instead of curr->type, so a return_call_indirect keeps its original type instead of getting (func (result unreachable)). I'll add a lit test under test/lit/passes with the module from the report and open a PR, unless someone is already on it.
cc @tlively @kripken