Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/coreclr/jit/fgdiagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2740,6 +2740,52 @@ void Compiler::fgDebugCheckBBlist(bool checkBBNum /* = false */, bool checkBBRef
assert(block->getTryIndex() < compHndBBtabCount);
}

// A branch or fall-through to a BBJ_CALLFINALLY block must come from the `try` region associated
// with the finally block the BBJ_CALLFINALLY is targeting. There is one special case: if the
// BBJ_CALLFINALLY is the first block of a `try`, then its predecessor can be outside the `try`:
// either a branch or fall-through to the first block.
//
// Note that this IR condition is a choice. It naturally occurs when importing EH constructs.
// This condition prevents flow optimizations from skipping blocks in a `try` and branching
// directly to the BBJ_CALLFINALLY. Relaxing this constraint would require careful thinking about
// the implications, such as data flow optimizations.
//
// Don't depend on predecessors list for the check.
for (BasicBlock* const succBlock : block->Succs())
{
if (succBlock->bbJumpKind == BBJ_CALLFINALLY)
{
BasicBlock* finallyBlock = succBlock->bbJumpDest;
assert(finallyBlock->hasHndIndex());
unsigned finallyIndex = finallyBlock->getHndIndex();

// Now make sure the block branching to the BBJ_CALLFINALLY is in the correct region. The branch
// to the BBJ_CALLFINALLY can come from the try region of the finally block, or from a more nested
// try region, e.g.:
// try {
// try {
// LEAVE L_OUTER; // this becomes a branch to a BBJ_CALLFINALLY in an outer try region
// // (in the FEATURE_EH_CALLFINALLY_THUNKS case)
// } catch {
// }
// } finally {
// }
// L_OUTER:
//
EHblkDsc* ehDsc = ehGetDsc(finallyIndex);
if (ehDsc->ebdTryBeg == succBlock)
{
// The BBJ_CALLFINALLY is the first block of it's `try` region. Don't check the predecessor.
// Note that this case won't occur in the FEATURE_EH_CALLFINALLY_THUNKS case, since the
// BBJ_CALLFINALLY in that case won't exist in the `try` region of the `finallyIndex`.
}
else
{
assert(bbInTryRegions(finallyIndex, block));
}
}
}

/* Check if BBF_RUN_RARELY is set that we have bbWeight of zero */
if (block->isRunRarely())
{
Expand Down