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

Code before:
        case PackTypes(TYP_INT, TYP_DOUBLE):
            ins = isUnsigned ? INS_i32_trunc_sat_f64_u : INS_i32_trunc_sat_f64_s;
            break;
        case PackTypes(TYP_LONG, TYP_FLOAT):
            ins = isUnsigned ? INS_i64_trunc_sat_f32_u : INS_i64_trunc_sat_f32_s;
            break;
        case PackTypes(TYP_LONG, TYP_DOUBLE):
            ins = isUnsigned ? INS_i64_trunc_sat_f64_u : INS_i64_trunc_sat_f64_s;
            break;
        default:
            unreached();
    }

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

void CodeGen::genIntToFloatCast(GenTree* tree)
{
    NYI_WASM("genIntToFloatCast");
}

void CodeGen::genFloatToFloatCast(GenTree* tree)
{
    var_types   toType   = genActualType(tree->TypeGet());
    var_types   fromType = genActualType(tree->AsCast()->CastFromType());
    instruction ins      = INS_none;

    genConsumeRegs(tree->AsCast()->CastOp());

    switch (PackTypes(toType, fromType))
    {
        case PackTypes(TYP_FLOAT, TYP_DOUBLE):
            ins = INS_f32_demote_f64;
            break;
        case PackTypes(TYP_DOUBLE, TYP_FLOAT):
            ins = INS_f64_promote_f32;
            break;
        case PackTypes(TYP_FLOAT, TYP_FLOAT):
        case PackTypes(TYP_DOUBLE, TYP_DOUBLE):
            ins = INS_none;
            break;
        default:
            unreached();
    }

    if (ins != INS_none)
    {
        GetEmitter()->emitIns(ins);
    }
    genProduceReg(tree);

Review comment (suggestion):
```suggestion
    var_types   toType   = tree->TypeGet();
    var_types   fromType = tree->AsCast()->CastOp()->TypeGet();
```

Code after:
}

// ------------------------------------------------------------------------
// PackTypes: Pack two var_types together into a uint32_t

// Arguments:
//    toType - a var_types to pack
//    fromType - a var_types to pack
//
// Return Value:
//    The two types packed together into an integer that can be used as a switch/value,
//    the primary use case being the handling of operations with two-type variants such
//    as casts.
//
static constexpr uint32_t PackTypes(var_types toType, var_types fromType)
{
    if (toType == TYP_BYREF || toType == TYP_REF)
    {
        toType = TYP_I_IMPL;
    }
    if (fromType == TYP_BYREF || fromType == TYP_REF)
    {
        fromType = TYP_I_IMPL;
    }
    const int shift1 = ConstLog2<TYP_COUNT>::value + 1;
    return ((uint32_t)toType) | ((uint32_t)fromType << shift1);
}

//------------------------------------------------------------------------
// genIntToIntCast: Generate code for an integer to integer cast
//
// Arguments:
//    cast - The GT_CAST node for the integer cast operation
//
// Notes:
//    Handles casts to and from small int, int, and long types
//    including proper sign extension and truncation as needed.
//
void CodeGen::genIntToIntCast(GenTreeCast* cast)
{
    if (cast->gtOverflow())
    {
        NYI_WASM("Overflow checks");
    }

    GenIntCastDesc desc(cast);
    var_types      toType     = genActualType(cast->CastToType());
    var_types      fromType   = genActualType(cast->CastOp());
    int            extendSize = desc.ExtendSrcSize();
    instruction    ins        = INS_none;
    assert(fromType == TYP_INT || fromType == TYP_LONG);