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

Code before:
{
    // Insert a null check on "this" pointer if asked.
    if (call->NeedsNullCheck())
    {
        // TODO-WASM: Ensure that when the this-arg is pushed onto the stack earlier, we perform the null check there.
        // Once that's done this NYI can go away.
        NYI_WASM("this ptr null check in genCall");
    }

    // TODO-WASM: Handle "fast tail calls" here if we decide to implement them.

    genCallInstruction(call);

    // TODO-WASM: Disabled in WASM currently. Not sure if we need it
    // genDefinePendingCallLabel(call);

    var_types returnType = call->TypeGet();
    if (returnType != TYP_VOID)
    {
        if (call->HasMultiRegRetVal())
        {
            NYI_WASM("multi-reg return values");
        }

        genProduceReg(call);
    }
}

//------------------------------------------------------------------------
// genCallInstruction - Generate instructions necessary to transfer control to the call.
//
// Arguments:
//    call - the GT_CALL node
//
void CodeGen::genCallInstruction(GenTreeCall* call)
{
    // Determine return value size(s).
    const ReturnTypeDesc* pRetTypeDesc = call->GetReturnTypeDesc();
    EmitCallParams        params;

    // unused values are of no interest to GC.
    if (!call->IsUnusedValue())
    {
        if (call->HasMultiRegRetVal())
        {
            NYI_WASM("multi-reg return values");
        }
        else
        {
            assert(!call->TypeIs(TYP_STRUCT));


Review comment (suggestion):
```suggestion
    assert(!call->IsTailCall());

    genCallInstruction(call);
    genProduceReg(call);
```
I suspect the logic that skips `genProduceReg` for `VOID` calls is not entirely sound either, but in a way that's 'mostly fine' (the reason it should nominally be needed is because calls can induce liveness changes with return buffer locals).

`genDefinePendingCallLabel` is used to implement `GT_LABEL` and things that rely on the return address being available, so, not going to be needed for WASM.

Code after:
        case PackOperAndType(GT_MOD, TYP_LONG):
            ins = INS_i64_rem_s;
            break;

        case PackOperAndType(GT_UMOD, TYP_INT):
            ins = INS_i32_rem_u;
            break;
        case PackOperAndType(GT_UMOD, TYP_LONG):
            ins = INS_i64_rem_u;
            break;

        default:
            ins = INS_none;
            NYI_WASM("genCodeForDivMod");
            break;
    }

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

//------------------------------------------------------------------------
// genCodeForConstant: Generate code for an integer or floating point constant
//
// Arguments:
//    treeNode - The constant.
//
void CodeGen::genCodeForConstant(GenTree* treeNode)
{
    instruction    ins  = INS_none;
    cnsval_ssize_t bits = 0;
    var_types      type = treeNode->TypeIs(TYP_REF, TYP_BYREF) ? TYP_I_IMPL : treeNode->TypeGet();
    static_assert(sizeof(cnsval_ssize_t) >= sizeof(double));

    GenTreeIntConCommon* icon = nullptr;
    if ((type == TYP_INT) || (type == TYP_LONG))
    {
        icon = treeNode->AsIntConCommon();
        if (icon->ImmedValNeedsReloc(compiler))
        {
            // WASM-TODO: Generate reloc for this handle
            ins  = INS_I_const;
            bits = 0;
        }
        else
        {
            bits = icon->IntegralValue();
        }
    }

    if (ins == INS_none)