Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/coreclr/jit/codegenwasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1883,12 +1883,22 @@ void CodeGen::genCodeForBitCast(GenTreeOp* tree)
case PackTypes(TYP_DOUBLE, TYP_LONG):
ins = INS_f64_reinterpret_i64;
break;

// Same-size bitcasts are no-ops on the wasm value stack. PackTypes normalizes
// TYP_REF/TYP_BYREF to TYP_I_IMPL, so this covers all INT/REF/BYREF combos on wasm32
// and LONG/REF/BYREF on wasm64.
case PackTypes(TYP_INT, TYP_INT):
case PackTypes(TYP_LONG, TYP_LONG):
break;

default:
unreached();
break;
}

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

Expand Down
44 changes: 18 additions & 26 deletions src/coreclr/jit/valuenum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,15 @@ struct FloatTraits
// Notes:
// "Default" NaN value returned by expression 0.0f / 0.0f on x86/x64 has
// different binary representation (0xffc00000) than NaN on
// ARM32/ARM64/LoongArch64 (0x7fc00000).
// ARM32/ARM64/LoongArch64/RISC-V 64/WASM (0x7fc00000).

static float NaN()
{
#if defined(TARGET_XARCH)
unsigned bits = 0xFFC00000u;
#elif defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
#elif defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) || defined(TARGET_WASM)
// WASM uses the canonical NaN payload, matching ARM.
unsigned bits = 0x7FC00000u;
Comment thread
AndyAyersMS marked this conversation as resolved.
#elif defined(TARGET_WASM)
// TODO-WASM: this may prove tricker than it seems since there are two possible "canonical"
// NaN values. We may need to introduce a new "unknown" value to be returned here.
NYI_WASM("FloatTraits::NaN");
unsigned bits = 0;
#else
#error Unsupported or unset target architecture
#endif
Expand All @@ -69,19 +65,15 @@ struct DoubleTraits
// Notes:
// "Default" NaN value returned by expression 0.0 / 0.0 on x86/x64 has
// different binary representation (0xfff8000000000000) than NaN on
// ARM32/ARM64/LoongArch64 (0x7ff8000000000000).
// ARM32/ARM64/LoongArch64/RISC-V 64/WASM (0x7ff8000000000000).

static double NaN()
{
#if defined(TARGET_XARCH)
unsigned long long bits = 0xFFF8000000000000ull;
#elif defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
#elif defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) || defined(TARGET_WASM)
// WASM uses the canonical NaN payload, matching ARM.
unsigned long long bits = 0x7FF8000000000000ull;
Comment thread
AndyAyersMS marked this conversation as resolved.
#elif defined(TARGET_WASM)
// TODO-WASM: this may prove tricker than it seems since there are two possible "canonical"
// NaN values. We may need to introduce a new "unknown" value to be returned here.
NYI_WASM("DoubleTraits::NaN");
unsigned long long bits = 0;
#else
#error Unsupported or unset target architecture
#endif
Expand All @@ -96,7 +88,7 @@ struct DoubleTraits
// FpAdd: Computes value1 + value2
//
// Return Value:
// TFpTraits::NaN() - If target ARM32/ARM64 and result value is NaN
// TFpTraits::NaN() - If target is ARM32/ARM64/LoongArch64/RISC-V 64/WASM and result value is NaN
// value1 + value2 - Otherwise
//
// Notes:
Expand All @@ -105,7 +97,7 @@ struct DoubleTraits
template <typename TFp, typename TFpTraits>
TFp FpAdd(TFp value1, TFp value2)
{
#if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
#if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) || defined(TARGET_WASM)
// If [value1] is negative infinity and [value2] is positive infinity
Comment thread
AndyAyersMS marked this conversation as resolved.
// the result is NaN.
// If [value1] is positive infinity and [value2] is negative infinity
Expand All @@ -123,7 +115,7 @@ TFp FpAdd(TFp value1, TFp value2)
return TFpTraits::NaN();
}
}
#endif // TARGET_ARMARCH || TARGET_LOONGARCH64 || TARGET_RISCV64
#endif // TARGET_ARMARCH || TARGET_LOONGARCH64 || TARGET_RISCV64 || TARGET_WASM

return value1 + value2;
}
Expand All @@ -132,7 +124,7 @@ TFp FpAdd(TFp value1, TFp value2)
// FpSub: Computes value1 - value2
//
// Return Value:
// TFpTraits::NaN() - If target ARM32/ARM64 and result value is NaN
// TFpTraits::NaN() - If target is ARM32/ARM64/LoongArch64/RISC-V 64/WASM and result value is NaN
// value1 - value2 - Otherwise
//
// Notes:
Expand All @@ -141,7 +133,7 @@ TFp FpAdd(TFp value1, TFp value2)
template <typename TFp, typename TFpTraits>
TFp FpSub(TFp value1, TFp value2)
{
#if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
#if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) || defined(TARGET_WASM)
// If [value1] is positive infinity and [value2] is positive infinity
Comment thread
AndyAyersMS marked this conversation as resolved.
// the result is NaN.
// If [value1] is negative infinity and [value2] is negative infinity
Expand All @@ -159,7 +151,7 @@ TFp FpSub(TFp value1, TFp value2)
return TFpTraits::NaN();
}
}
#endif // TARGET_ARMARCH || TARGET_LOONGARCH64 || TARGET_RISCV64
#endif // TARGET_ARMARCH || TARGET_LOONGARCH64 || TARGET_RISCV64 || TARGET_WASM

return value1 - value2;
}
Expand All @@ -168,7 +160,7 @@ TFp FpSub(TFp value1, TFp value2)
// FpMul: Computes value1 * value2
//
// Return Value:
// TFpTraits::NaN() - If target ARM32/ARM64 and result value is NaN
// TFpTraits::NaN() - If target is ARM32/ARM64/LoongArch64/RISC-V 64/WASM and result value is NaN
// value1 * value2 - Otherwise
//
// Notes:
Expand All @@ -177,7 +169,7 @@ TFp FpSub(TFp value1, TFp value2)
template <typename TFp, typename TFpTraits>
TFp FpMul(TFp value1, TFp value2)
{
#if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
#if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) || defined(TARGET_WASM)
// From the ECMA standard:
Comment thread
AndyAyersMS marked this conversation as resolved.
//
// If [value1] is zero and [value2] is infinity
Expand All @@ -193,7 +185,7 @@ TFp FpMul(TFp value1, TFp value2)
{
return TFpTraits::NaN();
}
#endif // TARGET_ARMARCH || TARGET_LOONGARCH64 || TARGET_RISCV64
#endif // TARGET_ARMARCH || TARGET_LOONGARCH64 || TARGET_RISCV64 || TARGET_WASM

return value1 * value2;
}
Expand All @@ -202,7 +194,7 @@ TFp FpMul(TFp value1, TFp value2)
// FpDiv: Computes value1 / value2
//
// Return Value:
// TFpTraits::NaN() - If target ARM32/ARM64 and result value is NaN
// TFpTraits::NaN() - If target is ARM32/ARM64/LoongArch64/RISC-V 64/WASM and result value is NaN
// value1 / value2 - Otherwise
//
// Notes:
Expand All @@ -211,7 +203,7 @@ TFp FpMul(TFp value1, TFp value2)
template <typename TFp, typename TFpTraits>
TFp FpDiv(TFp dividend, TFp divisor)
{
#if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
#if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) || defined(TARGET_WASM)
// From the ECMA standard:
Comment thread
AndyAyersMS marked this conversation as resolved.
//
// If [dividend] is zero and [divisor] is zero
Expand All @@ -228,7 +220,7 @@ TFp FpDiv(TFp dividend, TFp divisor)
{
return TFpTraits::NaN();
}
#endif // TARGET_ARMARCH || TARGET_LOONGARCH64 || TARGET_RISCV64
#endif // TARGET_ARMARCH || TARGET_LOONGARCH64 || TARGET_RISCV64 || TARGET_WASM

return dividend / divisor;
}
Expand Down
Loading