Skip to content
Closed
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ class CodeGen final : public CodeGenInterface
void genEmitBeginBlock(WasmValueType blockType = WasmValueType::Invalid);
void genEmitEndBlock();
void genEmitFunctionEnd(bool emitTerminalUnreachable = true);
bool genIsLastBlockOfCurrentFunc(BasicBlock* block);
#endif

void genEmitStartBlock(BasicBlock* block);
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,7 @@ void CodeGen::genEmitEndBlock(BasicBlock* block)
// At function/funclet end, close open intervals and emit `end`
// (we've already emitted the terminating `unreachable` above).
//
if (block->IsLast() || m_compiler->bbIsFuncletBeg(block->Next()))
if (genIsLastBlockOfCurrentFunc(block))
{
genEmitFunctionEnd(/* emitTerminalUnreachable */ false);
}
Expand Down Expand Up @@ -910,7 +910,7 @@ void CodeGen::genEmitEndBlock(BasicBlock* block)
// (e.g., backedge of an infinite loop), close any still-open
// wasm intervals and emit the function-body terminator.
//
if (block->IsLast() || m_compiler->bbIsFuncletBeg(block->Next()))
if (genIsLastBlockOfCurrentFunc(block))
{
genEmitFunctionEnd();
}
Expand Down
36 changes: 34 additions & 2 deletions src/coreclr/jit/codegenwasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,35 @@ void CodeGen::genFuncletProlog(BasicBlock* block)
}
}

//------------------------------------------------------------------------
// genIsLastBlockOfCurrentFunc: determine whether `block` is the last block of the
// wasm function or funclet currently being generated -- i.e. the block after
// which the function body's terminal `end` opcode must be emitted.
//
// Arguments:
// block - the block being generated
//
// Return Value:
// true if `block` is the current func/funclet's last block.
//
// Notes:
// A wasm function body is structurally required to end in `end`, even when its
// last block is a no-return call (e.g. a throw-helper tail). `block->Next()`
// walks the GLOBAL block order (bbNext), in which a funclet's last block can be
// followed by an interspersed root throw-helper block (`fgIsThrowHlpBlk`, no
// handler index) that is not a funclet begin, so `bbIsFuncletBeg(block->Next())`
// fails to recognize the funclet boundary. Codegen iterates per-funclet
// (`genCodeForFunclet` over `funcInfo->Blocks()`), so also compare against the
// current func/funclet's authoritative last block (`FuncInfoDsc::GetLastBlock`:
// `ebdHndLast` for handlers, `BBFilterLast` for filters, and
// `fgLastBBInMainFunction` for the root).
//
bool CodeGen::genIsLastBlockOfCurrentFunc(BasicBlock* block)
{
return block->IsLast() || m_compiler->bbIsFuncletBeg(block->Next()) ||
(block == m_compiler->funCurrentFunc()->GetLastBlock(m_compiler));
}

//------------------------------------------------------------------------
// genFuncletEpilog: codegen for funclet epilogs.
//
Expand All @@ -479,7 +508,10 @@ void CodeGen::genFuncletProlog(BasicBlock* block)
//
void CodeGen::genFuncletEpilog(BasicBlock* block)
{
if (block->IsLast() || m_compiler->bbIsFuncletBeg(block->Next()))
// Emit the function-body terminator (`end`) when this epilog block is the last
// block of the funclet; otherwise emit `return` to unwind to the caller.
//
if (genIsLastBlockOfCurrentFunc(block))
{
instGen(INS_end);
}
Expand Down Expand Up @@ -3781,7 +3813,7 @@ void CodeGen::genCallFinally(BasicBlock* block)
// A retless BBJ_CALLFINALLY can be the last block of a wasm function/funclet;
// every wasm function body must end with `end`.
//
if (block->IsLast() || m_compiler->bbIsFuncletBeg(block->Next()))
if (genIsLastBlockOfCurrentFunc(block))
{
GetEmitter()->emitIns(INS_end);
}
Expand Down
Loading