diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 9894611a963450..127e3ec23e8237 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -9917,6 +9917,7 @@ class Compiler void funSetCurrentFunc(unsigned funcIdx); FuncInfoDsc* funGetFunc(unsigned funcIdx); unsigned int funGetFuncIdx(BasicBlock* block); + bool bbIsInSameFunclet(BasicBlock* block1, BasicBlock* block2); // LIVENESS diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 8aad4186d05faf..ecd0a3eeb94024 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -859,6 +859,38 @@ inline unsigned Compiler::funGetFuncIdx(BasicBlock* block) return funcIdx; } +/***************************************************************************** + * Are two blocks physically contained in the same function region (funclet)? + * The main method is region 0. Unlike funGetFuncIdx, this works for an + * arbitrary block (not just a funclet entry), distinguishing a filter + * funclet (FUNC_FILTER) from its filter-handler. Only valid after funclets + * are created. + * + */ +inline bool Compiler::bbIsInSameFunclet(BasicBlock* block1, BasicBlock* block2) +{ + assert(fgFuncletsCreated); + + auto funcRegionOf = [this](BasicBlock* blk) -> unsigned { + if (!blk->hasHndIndex()) + { + return 0; + } + + EHblkDsc* const eh = ehGetDsc(blk->getHndIndex()); + unsigned funcIdx = eh->ebdFuncIndex; + + if (eh->HasFilter() && eh->InFilterRegionBBRange(blk)) + { + // The filter is the funclet immediately preceding its filter-handler. + funcIdx--; + } + + return funcIdx; + }; + + return funcRegionOf(block1) == funcRegionOf(block2); +} #if HAS_FIXED_REGISTER_SET //------------------------------------------------------------------------------ // genRegNumFromMask : Maps a single register mask to a register number. diff --git a/src/coreclr/jit/fgwasm.h b/src/coreclr/jit/fgwasm.h index 5070be0da26f61..2832967bc0bfc3 100644 --- a/src/coreclr/jit/fgwasm.h +++ b/src/coreclr/jit/fgwasm.h @@ -468,7 +468,18 @@ BasicBlockVisit FgWasm::VisitWasmSuccs(Compiler* comp, BasicBlock* block, TFunc // if (acd->acdUsed) { - RETURN_ON_ABORT(func(acd->acdDstBlk)); + // bbThrowIndex / bbInTryRegions are purely lexical tests, so a match can + // name a throw helper that lives in a different function region (funclet) + // than this side-entry -- e.g. a main-method helper for an outer try whose + // handler funclet merely nests inside that try. Attaching it here would pull + // the helper into this funclet's layout, interleaving it with funclet blocks + // and corrupting the emitted wasm. Only attach when the helper and the + // side-entry share the same function region. + // + if (comp->bbIsInSameFunclet(block, acd->acdDstBlk)) + { + RETURN_ON_ABORT(func(acd->acdDstBlk)); + } } } }