In CFGStackify, fixUnwindMismatches function fixes unwind destination
mismatches created by try marker placement. For example,
try ... call @qux ;; This should throw to the caller! catch ... end
When call @qux is supposed to throw to the caller, it is possible that
it is wrapped inside a catch so in case it throws it ends up unwinding
there incorrectly. (Also it is possible call @qux is supposed to
unwind to another catch within the same function.)
To fix this, we wrap this inner call @qux with a nested
try-catch-end sequence, and within the nested catch body, branch
to the right destination:
block $l0 try ... try ;; new nested try call @qux catch ;; new nested catch local.set n ;; store exnref to a local br $l0 end catch ... end end local.get n ;; retrieve exnref back rethrow ;; rethrow to the caller
The previous algorithm placed the nested try right before the call.
But it is possible that there are stackified instructions before the
call from which the call takes arguments.
try ... i32.const 5 call @qux ;; This should throw to the caller! catch ... end
In this case we have to place try before those stackified
instructions.
block $l0 try ... try ;; this should go *before* 'i32.const 5' i32.const 5 call @qux catch local.set n br $l0 end catch ... end end local.get n rethrow
We correctly handle this in the first normal try placement phase
(placeTryMarker function), but failed to handle this in this
fixUnwindMismatches.