diff --git a/src/coreclr/interpreter/compiler.cpp b/src/coreclr/interpreter/compiler.cpp index da590da2f9856a..cae549411e4540 100644 --- a/src/coreclr/interpreter/compiler.cpp +++ b/src/coreclr/interpreter/compiler.cpp @@ -1097,13 +1097,21 @@ void InterpCompiler::EmitCode() getEHinfo(m_methodInfo, i, &clause); for (InterpBasicBlock *bb = m_pEntryBB; bb != NULL; bb = bb->pNextBB) { + if (bb->isLeaveChainIsland && clause.HandlerOffset == (uint32_t)bb->ilOffset) + { + // Leave chain islands are not part of any EH clause, but their IL offset may be + continue; + } + if (clause.HandlerOffset <= (uint32_t)bb->ilOffset && (clause.HandlerOffset + clause.HandlerLength) > (uint32_t)bb->ilOffset) { + INTERP_DUMP("BB %d with ilOffset %x overlaps EH clause %d (handler)\n", bb->index, bb->ilOffset, i); bb->overlappingEHClauseCount++; } if (clause.Flags == CORINFO_EH_CLAUSE_FILTER && clause.FilterOffset <= (uint32_t)bb->ilOffset && clause.HandlerOffset > (uint32_t)bb->ilOffset) { + INTERP_DUMP("BB %d with ilOffset %x overlaps EH clause %d (filter)\n", bb->index, bb->ilOffset, i); bb->overlappingEHClauseCount++; } } @@ -1569,6 +1577,7 @@ void InterpCompiler::GetNativeRangeForClause(uint32_t startILOffset, uint32_t en assert(pStartBB != NULL); InterpBasicBlock* pEndBB = pStartBB; + for (InterpBasicBlock* pBB = pStartBB->pNextBB; (pBB != NULL) && ((uint32_t)pBB->ilOffset < endILOffset); pBB = pBB->pNextBB) { if (pBB->overlappingEHClauseCount == pStartBB->overlappingEHClauseCount) @@ -1682,6 +1691,18 @@ void InterpCompiler::BuildEHInfo() m_compHnd->setEHcount(nativeEHCount); unsigned int nativeEHIndex = 0; + +#ifdef DEBUG + INTERP_DUMP(" BB overlapping EH clause counts:\n"); + if (t_interpDump) + { + for (InterpBasicBlock* pBB = GetBB(0); (pBB != NULL); pBB = pBB->pNextBB) + { + INTERP_DUMP("BB:%d has overlappingEHClauseCount=%d and ilOffset=%x\n", pBB->index, pBB->overlappingEHClauseCount, pBB->ilOffset); + } + } +#endif + for (unsigned int i = 0; i < getEHcount(m_methodInfo); i++) { CORINFO_EH_CLAUSE clause; @@ -2272,8 +2293,9 @@ void InterpCompiler::CreateLeaveChainIslandBasicBlocks(CORINFO_METHOD_INFO* meth if (pLeaveChainIslandBB == NULL) { - pLeaveChainIslandBB = AllocBB(clause.HandlerOffset + clause.HandlerLength); + pLeaveChainIslandBB = AllocBB(clause.HandlerOffset); pLeaveChainIslandBB->pLeaveTargetBB = pLeaveTargetBB; + pLeaveChainIslandBB->isLeaveChainIsland = true; *ppLastBBNext = pLeaveChainIslandBB; } diff --git a/src/coreclr/interpreter/compiler.h b/src/coreclr/interpreter/compiler.h index af4f20e74bd075..6a380a103d5bc6 100644 --- a/src/coreclr/interpreter/compiler.h +++ b/src/coreclr/interpreter/compiler.h @@ -335,6 +335,9 @@ struct InterpBasicBlock // Valid only for BBs of call islands. It is set to true if it is a finally call island, false if is is a catch leave island. bool isFinallyCallIsland; + // Is a leave chain island basic block + bool isLeaveChainIsland; + // If this basic block is a catch or filter funclet entry, this is the index of the variable // that holds the exception object. int clauseVarIndex; @@ -366,6 +369,7 @@ struct InterpBasicBlock clauseType = BBClauseNone; isFilterOrCatchFuncletEntry = false; isFinallyCallIsland = false; + isLeaveChainIsland = false; clauseVarIndex = -1; overlappingEHClauseCount = 0; enclosingTryBlockCount = -1;