Repository: dotnet/runtime
File: src/coreclr/jit/codegenwasm.cpp (C++)

Code before:
// genCodeForNullCheck - generate code for a GT_NULLCHECK node
//
// Arguments:
//    tree - the GT_NULLCHECK node
//
void CodeGen::genCodeForNullCheck(GenTreeIndir* tree)
{
    genConsumeAddress(tree->Addr());

    // TODO-WASM: refactor once we have implemented other cases invoking throw helpers
    if (m_compiler->fgUseThrowHelperBlocks())
    {
        Compiler::AddCodeDsc* const add = m_compiler->fgGetExcptnTarget(SCK_NULL_CHECK, m_compiler->compCurBB);
        assert(add != nullptr);
        assert(add->acdUsed);
        GetEmitter()->emitIns_I(INS_I_const, EA_PTRSIZE, m_compiler->compMaxUncheckedOffsetForNullObject);
        GetEmitter()->emitIns(INS_I_le_u);
        inst_JMP(EJ_jmpif, add->acdDstBlk);
    }
    else
    {
        GetEmitter()->emitIns_I(INS_I_const, EA_PTRSIZE, m_compiler->compMaxUncheckedOffsetForNullObject);
        GetEmitter()->emitIns(INS_I_le_u);
        GetEmitter()->emitIns(INS_if);
        genEmitHelperCall(m_compiler->acdHelper(SCK_NULL_CHECK), 0, EA_UNKNOWN);
        GetEmitter()->emitIns(INS_unreachable);
        GetEmitter()->emitIns(INS_end);
    }
}

//------------------------------------------------------------------------
// genRangeCheck - generate code for a GT_BOUNDS_CHECK node
//
// Arguments:
//    tree - the GT_BOUNDS_CHECK node
//
void CodeGen::genRangeCheck(GenTree* tree)
{
    assert(tree->OperIs(GT_BOUNDS_CHECK));
    genConsumeOperands(tree->AsOp());

    if (m_compiler->fgUseThrowHelperBlocks())
    {
        Compiler::AddCodeDsc* const add = m_compiler->fgGetExcptnTarget(SCK_RNGCHK_FAIL, m_compiler->compCurBB);
        assert(add != nullptr);
        assert(add->acdUsed);

        GetEmitter()->emitIns(INS_I_ge_u);
        inst_JMP(EJ_jmpif, add->acdDstBlk);
    }
    else

Review comment (refactor):
Why do we need `unreachable` here? It should only be needed if the throw helper returns something (in which case we should really fix that instead).

Code after:
// genJumpToThrowHlpBlk - generate code to invoke a throw helper call
//
// Arguments:
//    codeKind -- kind of throw helper call needed
//
// Notes:
//    On entry the predicate for the throw helper is the only item on the Wasm stack.
//    An exception is thrown if the predicate is true.
//
void CodeGen::genJumpToThrowHlpBlk(SpecialCodeKind codeKind)
{
    if (m_compiler->fgUseThrowHelperBlocks())
    {
        Compiler::AddCodeDsc* const add = m_compiler->fgGetExcptnTarget(codeKind, m_compiler->compCurBB);
        assert(add != nullptr);
        assert(add->acdUsed);
        inst_JMP(EJ_jmpif, add->acdDstBlk);
    }
    else
    {
        GetEmitter()->emitIns(INS_if);
        // Throw helper arity is (i (sp)) -> (void).
        // Push SP here as the arg for the call.
        GetEmitter()->emitIns_I(INS_local_get, EA_PTRSIZE, WasmRegToIndex(GetStackPointerReg()));
        genEmitHelperCall(m_compiler->acdHelper(codeKind), 0, EA_UNKNOWN);
        GetEmitter()->emitIns(INS_end);
    }
}

//---------------------------------------------------------------------
// genCodeForNullCheck - generate code for a GT_NULLCHECK node
//
// Arguments:
//    tree - the GT_NULLCHECK node
//
void CodeGen::genCodeForNullCheck(GenTreeIndir* tree)
{
    genConsumeAddress(tree->Addr());
    GetEmitter()->emitIns_I(INS_I_const, EA_PTRSIZE, m_compiler->compMaxUncheckedOffsetForNullObject);
    GetEmitter()->emitIns(INS_I_le_u);
    genJumpToThrowHlpBlk(SCK_NULL_CHECK);
}

//------------------------------------------------------------------------
// genRangeCheck - generate code for a GT_BOUNDS_CHECK node
//
// Arguments:
//    tree - the GT_BOUNDS_CHECK node
//
// Notes:
//    Incoming stack args are index; length (tos).