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

Code before:
        // We must consume the operands in the proper execution order,
        // so that liveness is updated appropriately.
        genConsumeAddress(addr);
        genConsumeRegs(data);

        var_types   type = tree->TypeGet();
        instruction ins  = ins_Store(type);

        // TODO-WASM: Memory barriers

        GetEmitter()->emitIns_I(ins, emitActualTypeSize(type), 0);
    }

    genUpdateLife(tree);
}

//---------------------------------------------------------------------
// genPutArgReg - generate code for a T_PUTARG_REG node
//
// Arguments
//    tree - the GT_PUTARG_REG node
//
// Return value:
//    None
//
void CodeGen::genPutArgReg(GenTreeOp* tree)
{
    assert(tree->OperIs(GT_PUTARG_REG));

    var_types targetType = tree->TypeGet();
    regNumber targetReg  = tree->GetRegNum();

    assert(targetType != TYP_STRUCT);

    GenTree* op1 = tree->gtOp1;
    genConsumeReg(op1);

    GetEmitter()->emitIns_I(INS_local_get, emitTypeSize(tree), WasmRegToIndex(op1->GetRegNum()));
    GetEmitter()->emitIns_I(INS_local_set, emitTypeSize(tree), WasmRegToIndex(targetReg));

    genProduceReg(tree);
}

//------------------------------------------------------------------------
// genCall: Produce code for a GT_CALL node
//
void CodeGen::genCall(GenTreeCall* call)
{
    // Insert a null check on "this" pointer if asked.
    if (call->NeedsNullCheck())
    {

Review comment (suggestion):
I think this just needs the `genConsumerReg` and `genProduceReg` parts and no code emission. If an argument is passed "in a register" we really mean it is passed on the Wasm stack.

Code after:
    // tee.local $temp2
    // ... exception checks (using $temp1 and $temp2; will introduce flow)
    // div/mod op

    if (!varTypeIsFloating(treeNode->TypeGet()))
    {
        ExceptionSetFlags exSetFlags = treeNode->OperExceptions(compiler);

        // TODO-WASM:(AnyVal / 0) => DivideByZeroException
        //
        if ((exSetFlags & ExceptionSetFlags::DivideByZeroException) != ExceptionSetFlags::None)
        {
        }

        // TODO-WASM: (MinInt / -1) => ArithmeticException
        //
        if ((exSetFlags & ExceptionSetFlags::ArithmeticException) != ExceptionSetFlags::None)
        {
        }
    }

    instruction ins;
    switch (PackOperAndType(treeNode->OperGet(), treeNode->TypeGet()))
    {
        case PackOperAndType(GT_DIV, TYP_INT):
            ins = INS_i32_div_s;
            break;
        case PackOperAndType(GT_DIV, TYP_LONG):
            ins = INS_i64_div_s;
            break;
        case PackOperAndType(GT_DIV, TYP_FLOAT):
            ins = INS_f32_div;
            break;
        case PackOperAndType(GT_DIV, TYP_DOUBLE):
            ins = INS_f64_div;
            break;

        case PackOperAndType(GT_UDIV, TYP_INT):
            ins = INS_i32_div_u;
            break;
        case PackOperAndType(GT_UDIV, TYP_LONG):
            ins = INS_i64_div_u;
            break;

        case PackOperAndType(GT_MOD, TYP_INT):
            ins = INS_i32_rem_s;
            break;
        case PackOperAndType(GT_MOD, TYP_LONG):
            ins = INS_i64_rem_s;
            break;