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 callerThe 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
rethrowWe correctly handle this in the first normal try placement phase
(placeTryMarker function), but failed to handle this in this
fixUnwindMismatches.