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

Code before:
        case PackOperAndType(GT_NEG, TYP_DOUBLE):
            ins = INS_f64_neg;
            break;

        default:
            unreached();
            break;
    }

    GetEmitter()->emitIns(ins);
    genProduceReg(tree);
}

//---------------------------------------------------------------------
// 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)

Review comment (suggestion):
There is a `TODO` above about consolidating the pattern, and I think I see what the contract should be for the WASM version of: `genJumpToThrowHlpBlk`: the caller pushes the condition, on the value stack, the callee emits either the `br_if` or the `if` pattern.

Code after:
        case PackOperAndType(GT_NEG, TYP_DOUBLE):
            ins = INS_f64_neg;
            break;

        default:
            unreached();
            break;
    }

    GetEmitter()->emitIns(ins);
    genProduceReg(tree);
}

//---------------------------------------------------------------------
// 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)
{