BasicBlock* const leaveBlock = currentBlock->bbNext;
BasicBlock* const postTryFinallyBlock = leaveBlock->bbJumpDest;
+ JITDUMP("Modifying callfinally BB%02u leave BB%02u finally BB%02u continuation BB%02u\n",
+ currentBlock->bbNum, leaveBlock->bbNum, firstBlock->bbNum, postTryFinallyBlock->bbNum);
+ JITDUMP("so that BB%02u jumps to BB%02u; then remove BB%02u\n", currentBlock->bbNum,
+ postTryFinallyBlock->bbNum, leaveBlock->bbNum);
+
noway_assert(leaveBlock->bbJumpKind == BBJ_ALWAYS);
currentBlock->bbJumpDest = postTryFinallyBlock;
currentBlock = nextBlock;
}
+ JITDUMP("Remove now-unreachable handler BB%02u\n", firstBlock->bbNum);
+
// Handler block should now be unreferenced, since the only
// explicit references to it were in call finallys.
firstBlock->bbRefs = 0;
for (BasicBlock* block = lastTryBlock; block != beforeTryBlock; block = block->bbPrev)
{
#if FEATURE_EH_CALLFINALLY_THUNKS
- // Look for blocks that are always jumps to a call finally
- // pair that targets our finally.
- if (block->bbJumpKind != BBJ_ALWAYS)
+ // Blocks that transfer control to callfinallies are usually
+ // BBJ_ALWAYS blocks, but the last block of a try may fall
+ // through to a callfinally.
+ BasicBlock* jumpDest = nullptr;
+
+ if ((block->bbJumpKind == BBJ_NONE) && (block == lastTryBlock))
{
- continue;
+ jumpDest = block->bbNext;
+ }
+ else if (block->bbJumpKind == BBJ_ALWAYS)
+ {
+ jumpDest = block->bbJumpDest;
}
- BasicBlock* const jumpDest = block->bbJumpDest;
+ if (jumpDest == nullptr)
+ {
+ continue;
+ }
+ // The jumpDest must be a callfinally that in turn invokes the
+ // finally of interest.
if (!jumpDest->isBBCallAlwaysPair() || (jumpDest->bbJumpDest != firstBlock))
{
continue;