Quellcode durchsuchen

truncation bug fixes, clean-up

Nikolay Korovaiko vor 9 Jahren
Ursprung
Commit
05a28df871

+ 7 - 0
lib/Common/Common/NumberUtilities.cpp

@@ -33,6 +33,10 @@ namespace Js
     const uint64 NumberConstants::k_TwoTo63;
     const uint64 NumberConstants::k_NegTwoTo63;
     const uint64 NumberConstants::k_TwoTo64;
+    const uint64 NumberConstants::k_TwoTo31;
+    const uint64 NumberConstants::k_NegTwoTo31;
+    const uint64 NumberConstants::k_TwoTo32;
+
     const uint32 NumberConstants::k_Float32Zero;
     const uint32 NumberConstants::k_Float32PointFive;
     const uint32 NumberConstants::k_Float32NegPointFive;
@@ -43,6 +47,9 @@ namespace Js
     const uint32 NumberConstants::k_Float32NegTwoTo63;
     const uint32 NumberConstants::k_Float32TwoTo64;
     const uint32 NumberConstants::k_Float32NegOne;
+    const uint32 NumberConstants::k_Float32TwoTo31;
+    const uint32 NumberConstants::k_Float32NegTwoTo31;
+    const uint32 NumberConstants::k_Float32TwoTo32;
 #endif
 
     const double NumberConstants::MAX_VALUE = *(double*)(&NumberConstants::k_PosMax);

+ 6 - 0
lib/Common/Common/NumberUtilities.h

@@ -29,6 +29,9 @@ namespace Js
         static const uint64     k_TwoTo63 = 0x43e0000000000000ull;
         static const uint64     k_NegTwoTo63 = 0xc3e0000000000000ull;
         static const uint64     k_TwoTo64 = 0x43f0000000000000ull;
+        static const uint64     k_TwoTo31 = 0x41dfffffffc00000ull;
+        static const uint64     k_NegTwoTo31 = 0xc1e0000000000000ull;
+        static const uint64     k_TwoTo32 = 0x41efffffffe00000ull;
 
         static const uint32     k_Float32Zero      = 0x00000000ul;
         static const uint32     k_Float32PointFive = 0x3F000000ul;
@@ -43,6 +46,9 @@ namespace Js
         static const uint32     k_Float32NegTwoTo63 = 0xdf000000u;
         static const uint32     k_Float32TwoTo64 = 0x5f800000u;
         static const uint32     k_Float32NegOne = 0xbf800000u;
+        static const uint32     k_Float32TwoTo31 = 0x4f000000u;
+        static const uint32     k_Float32NegTwoTo31 = 0xcf000000u;
+        static const uint32     k_Float32TwoTo32 = 0x4f800000u;
 
         static const double     MAX_VALUE;
         static const double     MIN_VALUE;

+ 1 - 1
lib/Runtime/Language/AsmJsUtils.cpp

@@ -235,7 +235,7 @@ namespace Js
                 }
 
                 *(int64*)(argDst) = 0;
-                *(int64*)argDst = intVal;
+                *(int32*)argDst = intVal;
 
                 argDst = argDst + MachPtr;
             }

+ 4 - 4
lib/Runtime/Language/InterpreterHandlerAsmJs.inl

@@ -231,10 +231,10 @@ EXDEF2_WMS( D1toD1Mem        , Trunc_Db         , Wasm::WasmMath::Trunc<double>
 EXDEF2_WMS( D1toD1Mem        , Nearest_Db       , Wasm::WasmMath::Nearest<double>                    )
 EXDEF2_WMS( VtoI1Mem         , CurrentMemory_Int, OP_GetMemorySize                                   )
 EXDEF2    ( EMPTYASMJS       , Unreachable_Void , OP_Unreachable                                     )
-EXDEF2_WMS( D1toI1Mem        , Conv_Check_DTI   , (OP_TruncWithCheck<int,INT_MIN,INT_MAX>)           )
-EXDEF2_WMS( F1toI1Mem        , Conv_Check_FTI   , (OP_TruncWithCheck<int,INT_MIN,INT_MAX>)           )
-EXDEF2_WMS( D1toI1Mem        , Conv_Check_DTU   , (OP_TruncWithCheck<uint,0,UINT_MAX>)               )
-EXDEF2_WMS( F1toI1Mem        , Conv_Check_FTU   , (OP_TruncWithCheck<uint,0,UINT_MAX>)               )
+EXDEF2_WMS( D1toI1Ctx        , Conv_Check_DTI   , JavascriptConversion::F64TOI32                     )
+EXDEF2_WMS( F1toI1Ctx        , Conv_Check_FTI   , JavascriptConversion::F32TOI32                     )
+EXDEF2_WMS( D1toI1Ctx        , Conv_Check_DTU   , JavascriptConversion::F64TOU32                     )
+EXDEF2_WMS( F1toI1Ctx        , Conv_Check_FTU   , JavascriptConversion::F32TOU32                     )
 EXDEF2_WMS( F1toL1Ctx        , Conv_Check_FTL   , JavascriptConversion::F32TOI64                     )
 EXDEF2_WMS( F1toL1Ctx        , Conv_Check_FTUL  , JavascriptConversion::F32TOU64                     )
 EXDEF2_WMS( D1toL1Ctx        , Conv_Check_DTL   , JavascriptConversion::F64TOI64                     )

+ 18 - 0
lib/Runtime/Language/InterpreterProcessOpCodeAsmJs.h

@@ -418,6 +418,15 @@ if (switchProfileMode) \
                                                                 }
 #define PROCESS_C1toI1(name, func) PROCESS_C1toI1_COMMON(name, func,)
 
+#define PROCESS_F1toI1Ctx_COMMON(name, func, suffix) \
+    case OpCodeAsmJs::name: \
+                                                                { \
+        PROCESS_READ_LAYOUT_ASMJS(name, Int1Float1, suffix); \
+        SetRegRawInt( playout->I0, func(GetRegRawFloat(playout->F1),scriptContext)); \
+        break; \
+                                                                }
+#define PROCESS_F1toI1Ctx(name, func) PROCESS_F1toI1Ctx_COMMON(name, func,)
+
 #define PROCESS_F1toL1Ctx_COMMON(name, func, suffix) \
     case OpCodeAsmJs::name: \
                                                                 { \
@@ -427,6 +436,15 @@ if (switchProfileMode) \
                                                                 }
 #define PROCESS_F1toL1Ctx(name, func) PROCESS_F1toL1Ctx_COMMON(name, func,)
 
+#define PROCESS_D1toI1Ctx_COMMON(name, func, suffix) \
+    case OpCodeAsmJs::name: \
+                                                                { \
+        PROCESS_READ_LAYOUT_ASMJS(name,Int1Double1, suffix); \
+        SetRegRawInt( playout->I0, func(GetRegRawDouble(playout->D1),scriptContext)); \
+        break; \
+                                                                }
+#define PROCESS_D1toI1Ctx(name, func) PROCESS_D1toI1Ctx_COMMON(name, func,)
+
 #define PROCESS_D1toL1Ctx_COMMON(name, func, suffix) \
     case OpCodeAsmJs::name: \
                                                                 { \

+ 0 - 13
lib/Runtime/Language/InterpreterStackFrame.cpp

@@ -8014,19 +8014,6 @@ const byte * InterpreterStackFrame::OP_ProfiledLoopBodyStart(const byte * ip)
         JavascriptError::ThrowUnreachable(scriptContext);
     }
 
-    template <typename T, T MIN, T MAX>
-    int InterpreterStackFrame::OP_TruncWithCheck(double val)
-    {
-        //min, max are converted to double
-        //and min <= val <= max is tested
-        if (!Wasm::WasmMath::IsInValidRange<T, MIN, MAX>(val))
-        {
-            JavascriptError::ThrowError(scriptContext, VBSERR_Overflow);
-        }
-
-        return (int) ((T) val);
-    }
-
     template <class T>
     void InterpreterStackFrame::OP_SimdLdArrGeneric(const unaligned T* playout)
     {

+ 0 - 1
lib/Runtime/Language/InterpreterStackFrame.h

@@ -187,7 +187,6 @@ namespace Js
         void ValidateRegValue(Var value, bool allowStackVar = false, bool allowStackVarOnDisabledStackNestedFunc = true) const;
         int OP_GetMemorySize();
         void OP_Unreachable();
-        template < typename T, T MIN, T MAX> int OP_TruncWithCheck(double val);
         template <typename T> using AsmJsMathPtr = T(*)(T a, T b);
         template <typename T, AsmJsMathPtr<T> func, T MIN> static T OP_DivOverflow(T a, T b, ScriptContext* scriptContext);
         template <typename T, AsmJsMathPtr<T> func> static T OP_DivRemCheck(T a, T b, ScriptContext* scriptContext);

+ 60 - 4
lib/Runtime/Language/JavascriptConversion.cpp

@@ -1525,9 +1525,59 @@ CommonNumber:
         return ToString(ToPrimitive(aValue, JavascriptHint::None, scriptContext), scriptContext);
     }
 
+    int32 JavascriptConversion::F32TOI32(float src, ScriptContext * ctx)
+    {
+        if (Wasm::WasmMath::isInRange<float, uint32, NumberConstants::k_Float32TwoTo31, NumberConstants::k_Float32NegZero, NumberConstants::k_Float32NegTwoTo31,
+            &Wasm::WasmMath::LessThan<uint32>, &Wasm::WasmMath::LessOrEqual<uint32>>(src) &&
+            !Wasm::WasmMath::isNaN<float>(src))
+        {
+            return (int32)src;
+        }
+
+        JavascriptError::ThrowError(ctx, VBSERR_Overflow);
+    }
+
+    uint32 JavascriptConversion::F32TOU32(float src, ScriptContext * ctx)
+    {
+        if (Wasm::WasmMath::isInRange<float, uint32, NumberConstants::k_Float32TwoTo32, NumberConstants::k_Float32NegZero, NumberConstants::k_Float32NegOne,
+            &Wasm::WasmMath::LessThan<uint32>, &Wasm::WasmMath::LessThan<uint32>>(src) &&
+            !Wasm::WasmMath::isNaN<float>(src))
+        {
+            return (uint32)src;
+        }
+
+        JavascriptError::ThrowError(ctx, VBSERR_Overflow);
+    }
+
+    int32 JavascriptConversion::F64TOI32(double src, ScriptContext * ctx)
+    {
+        if (Wasm::WasmMath::isInRange<double, uint64, NumberConstants::k_TwoTo31, NumberConstants::k_NegZero, NumberConstants::k_NegTwoTo31,
+            &Wasm::WasmMath::LessOrEqual<uint64>, &Wasm::WasmMath::LessOrEqual<uint64>>(src) &&
+            !Wasm::WasmMath::isNaN<double>(src))
+        {
+            return (int32)src;
+        }
+
+        JavascriptError::ThrowError(ctx, VBSERR_Overflow);
+    }
+
+    uint32 JavascriptConversion::F64TOU32(double src, ScriptContext * ctx)
+    {
+        if (Wasm::WasmMath::isInRange<double, uint64, NumberConstants::k_TwoTo32, NumberConstants::k_NegZero, NumberConstants::k_NegOne,
+            &Wasm::WasmMath::LessOrEqual<uint64>, &Wasm::WasmMath::LessThan<uint64>>(src)
+            && !Wasm::WasmMath::isNaN<double>(src))
+        {
+            return (uint32)src;
+        }
+
+        JavascriptError::ThrowError(ctx, VBSERR_Overflow);
+    }
+
     int64 JavascriptConversion::F32TOI64(float src, ScriptContext * ctx)
     {
-        if (Wasm::WasmMath::isInRangeInclusive<float, uint32, NumberConstants::k_Float32TwoTo63, NumberConstants::k_Float32NegZero, NumberConstants::k_Float32NegTwoTo63>(src) && !Wasm::WasmMath::isNaN<float>(src))
+        if (Wasm::WasmMath::isInRange<float, uint32, NumberConstants::k_Float32TwoTo63, NumberConstants::k_Float32NegZero, NumberConstants::k_Float32NegTwoTo63,
+            &Wasm::WasmMath::LessThan<uint32>, &Wasm::WasmMath::LessOrEqual<uint32>>(src) &&
+            !Wasm::WasmMath::isNaN<float>(src))
         {
             return (int64)src;
         }
@@ -1537,7 +1587,9 @@ CommonNumber:
 
     uint64 JavascriptConversion::F32TOU64(float src, ScriptContext * ctx)
     {
-        if (Wasm::WasmMath::isInRange<float, uint32, NumberConstants::k_Float32TwoTo64, NumberConstants::k_Float32NegZero, NumberConstants::k_Float32NegOne>(src) && !Wasm::WasmMath::isNaN<float>(src))
+        if (Wasm::WasmMath::isInRange<float, uint32, NumberConstants::k_Float32TwoTo64, NumberConstants::k_Float32NegZero, NumberConstants::k_Float32NegOne,
+            &Wasm::WasmMath::LessThan<uint32>, &Wasm::WasmMath::LessThan<uint32>>(src) &&
+            !Wasm::WasmMath::isNaN<float>(src))
         {
             return (uint64)src;
         }
@@ -1547,7 +1599,9 @@ CommonNumber:
 
     int64 JavascriptConversion::F64TOI64(double src, ScriptContext * ctx)
     {
-        if (Wasm::WasmMath::isInRangeInclusive<double, uint64, NumberConstants::k_TwoTo63, NumberConstants::k_NegZero, NumberConstants::k_NegTwoTo63>(src) && !Wasm::WasmMath::isNaN<double>(src))
+        if (Wasm::WasmMath::isInRange<double, uint64, NumberConstants::k_TwoTo63, NumberConstants::k_NegZero, NumberConstants::k_NegTwoTo63,
+            &Wasm::WasmMath::LessThan<uint64>, &Wasm::WasmMath::LessOrEqual<uint64>>(src) &&
+            !Wasm::WasmMath::isNaN<double>(src))
         {
             return (int64)src;
         }
@@ -1557,7 +1611,9 @@ CommonNumber:
 
     uint64 JavascriptConversion::F64TOU64(double src, ScriptContext * ctx)
     {
-        if (Wasm::WasmMath::isInRange<double, uint64, NumberConstants::k_TwoTo64, NumberConstants::k_NegZero, NumberConstants::k_NegOne>(src) && !Wasm::WasmMath::isNaN<double>(src))
+        if (Wasm::WasmMath::isInRange<double, uint64, NumberConstants::k_TwoTo64, NumberConstants::k_NegZero, NumberConstants::k_NegOne,
+            &Wasm::WasmMath::LessThan<uint64>, &Wasm::WasmMath::LessThan<uint64>>(src) &&
+            !Wasm::WasmMath::isNaN<double>(src))
         {
             return (uint64)src;
         }

+ 5 - 0
lib/Runtime/Language/JavascriptConversion.h

@@ -72,6 +72,11 @@ namespace Js {
         static uint64 F32TOU64(float src, ScriptContext * ctx);
         static int64 F64TOI64(double src, ScriptContext * ctx);
         static uint64 F64TOU64(double src, ScriptContext * ctx);
+        static int32 F32TOI32(float src, ScriptContext * ctx);
+        static uint32 F32TOU32(float src, ScriptContext * ctx);
+        static int32 F64TOI32(double src, ScriptContext * ctx);
+        static uint32 F64TOU32(double src, ScriptContext * ctx);
+
     private:
         static BOOL ToInt32Finite(double value, int32* result);
         template<bool zero>

+ 4 - 3
lib/Runtime/Math/WasmMath.h

@@ -24,9 +24,10 @@ public:
     template<typename T> static T Clz(T value);
     template<typename T> static T Rol(T aLeft, T aRight);
     template<typename T> static T Ror(T aLeft, T aRight);
-    template <typename T, T MIN, T MAX> static bool IsInValidRange(double aLeft);
-    template <typename STYPE, typename UTYPE, UTYPE MAX, UTYPE NEG_ZERO, UTYPE NEG_ONE> static bool isInRange(STYPE srcVal);
-    template <typename STYPE, typename UTYPE, UTYPE MAX, UTYPE NEG_ZERO, UTYPE NEG_ONE> static bool isInRangeInclusive(STYPE srcVal);
+    template <typename T> bool static LessThan(T aLeft, T aRight);
+    template <typename T> bool static LessOrEqual(T aLeft, T aRight);
+    template <typename T> using CmpPtr = bool(*)(T a, T b);
+    template <typename STYPE, typename UTYPE, UTYPE MAX, UTYPE NEG_ZERO, UTYPE NEG_ONE, CmpPtr<UTYPE> CMP1, CmpPtr<UTYPE> CMP2> static bool isInRange(STYPE srcVal);
     template <typename STYPE> static bool isNaN(STYPE src);
 };
 

+ 17 - 9
lib/Runtime/Math/WasmMath.inl

@@ -139,20 +139,28 @@ inline bool WasmMath::IsInValidRange(double aLeft)
     return (aLeft >= (double) MIN && aLeft <= (double) MAX);
 }
 
-template <typename STYPE, typename UTYPE, UTYPE MAX, UTYPE NEG_ZERO, UTYPE NEG_ONE> bool  WasmMath::isInRange(STYPE srcVal)
+template <typename T> bool WasmMath::LessThan(T aLeft, T aRight)
 {
-    Assert(sizeof(STYPE) == sizeof(UTYPE));
-    UTYPE val;
-    memcpy(&val, &srcVal, sizeof(STYPE));
-    return (val < MAX) || (val >= NEG_ZERO && val < NEG_ONE);
+    return aLeft < aRight;
+}
+
+template <typename T> bool WasmMath::LessOrEqual(T aLeft, T aRight)
+{
+    return aLeft <= aRight;
 }
 
-template <typename STYPE, typename UTYPE, UTYPE MAX, UTYPE NEG_ZERO, UTYPE NEG_ONE> bool  WasmMath::isInRangeInclusive(STYPE srcVal)
+template <typename STYPE,
+    typename UTYPE,
+    UTYPE MAX,
+    UTYPE NEG_ZERO,
+    UTYPE NEG_ONE,
+    WasmMath::CmpPtr<UTYPE> CMP1,
+    WasmMath::CmpPtr<UTYPE> CMP2>
+bool WasmMath::isInRange(STYPE srcVal)
 {
     Assert(sizeof(STYPE) == sizeof(UTYPE));
-    UTYPE val;
-    memcpy(&val, &srcVal, sizeof(STYPE));
-    return (val < MAX) || (val >= NEG_ZERO && val <= NEG_ONE);
+    UTYPE val = *reinterpret_cast<UTYPE*> (&srcVal);
+    return (CMP1(val, MAX)) || (val >= NEG_ZERO && CMP2(val, NEG_ONE));
 }
 
 template <typename STYPE> bool  WasmMath::isNaN(STYPE src)

+ 33 - 2
test/wasm/trunc.js

@@ -27,7 +27,39 @@ let ffi = {};
 let wasm = readbuffer("trunc.wasm");
 let exports = Wasm.instantiateModule(new Uint8Array(wasm), ffi).exports;
 
-//i64 div/rem
+//i32
+check("Overflow","exports.i32_trunc_u_f64",Number.NaN);
+check("Overflow","exports.i32_trunc_s_f64",Number.NaN);
+check("Overflow","exports.i32_trunc_u_f32",Number.NaN);
+check("Overflow","exports.i32_trunc_s_f32",Number.NaN);
+
+check(-1,"exports.i32_trunc_u_f64",4294967295.0);
+check("Overflow","exports.i32_trunc_u_f64",4294967296.0);
+check(0,"exports.i32_trunc_u_f64",0.0);
+//check(0,"exports.i32_trunc_u_f64",0.7); BUG!!! Needs to be fixed!
+check("Overflow","exports.i32_trunc_u_f64",-1);
+
+check(2147483647,"exports.i32_trunc_s_f64",2147483647.0);
+check("Overflow","exports.i32_trunc_s_f64",2147483648.0); 
+
+check(-2147483648,"exports.i32_trunc_s_f64",-2147483648.0);
+check("Overflow","exports.i32_trunc_s_f64",-2147483649.0);
+
+check(-256,"exports.i32_trunc_u_f32",4294967040.0);
+check("Overflow","exports.i32_trunc_u_f32",4294967296.0);
+
+check(2147483520,"exports.i32_trunc_s_f32",2147483520.0);
+check("Overflow","exports.i32_trunc_s_f32",2147483647.0);
+
+check(-2147483520,"exports.i32_trunc_s_f32",-2147483520.0);
+check("Overflow","exports.i32_trunc_s_f32",-2147483800.0);
+
+//i64
+check("Overflow","exports.i64_trunc_u_f64",Number.NaN);
+check("Overflow","exports.i64_trunc_s_f64",Number.NaN);
+check("Overflow","exports.i64_trunc_u_f32",Number.NaN);
+check("Overflow","exports.i64_trunc_s_f32",Number.NaN);
+
 check(1,"exports.test1");
 check("Overflow","exports.test2");
 check(1,"exports.test3");
@@ -50,7 +82,6 @@ check("Overflow","exports.test16");
 check(1,"exports.test17");
 check("Overflow","exports.test18");
 
-
 if(passed)
 {
     print("Passed");

BIN
test/wasm/trunc.wasm


+ 35 - 7
test/wasm/trunc.wast

@@ -4,11 +4,39 @@
 ;;-------------------------------------------------------------------------------------------------------
 
 (module
-    (func (export "i64_div_s_by_two") (param $x i64) (result i64)
-        (i64.div_s (get_local $x) (i64.const 2))
-    )
-    (func (export "i64_div_s_over") (result i64)
-        (i64.div_s (i64.const 0x8000000000000000  ) (i64.const 0xffffffffffffffff))
-    )
-    (func (export "rem_s177") (result i64) (i64.rem_s (i64.const 0x7fffffffffffffff) (i64.const -1)))
+  (func (export "i32_trunc_s_f32") (param $x f32) (result i32) (i32.trunc_s/f32 (get_local $x)))
+  (func (export "i32_trunc_u_f32") (param $x f32) (result i32) (i32.trunc_u/f32 (get_local $x)))
+  (func (export "i32_trunc_s_f64") (param $x f64) (result i32) (i32.trunc_s/f64 (get_local $x)))
+  (func (export "i32_trunc_u_f64") (param $x f64) (result i32) (i32.trunc_u/f64 (get_local $x)))
+  (func (export "i64_trunc_s_f32") (param $x f32) (result i64) (i64.trunc_s/f32 (get_local $x)))
+  (func (export "i64_trunc_u_f32") (param $x f32) (result i64) (i64.trunc_u/f32 (get_local $x)))
+  (func (export "i64_trunc_s_f64") (param $x f64) (result i64) (i64.trunc_s/f64 (get_local $x)))
+  (func (export "i64_trunc_u_f64") (param $x f64) (result i64) (i64.trunc_u/f64 (get_local $x)))
+  ;;
+  (func(export "test1") (result i32) (i64.eq (i64.trunc_u/f64 (f64.const 18446744073709549568.0))  (i64.const 0xfffffffffffff800)))
+  (func(export "test2") (result i32) (i64.eq (i64.trunc_u/f64 (f64.const 18446744073709550592.0))  (i64.const 0))) ;; overflow
+  ;;
+  (func(export "test3") (result i32) (i64.eq (i64.trunc_u/f64 (f64.const 0.0))  (i64.const 0)))
+  (func(export "test4") (result i32) (i64.eq (i64.trunc_u/f64 (f64.const 0.5))  (i64.const 0)))
+  (func(export "test5") (result i32) (i64.eq (i64.trunc_u/f64 (f64.const -1))  (i64.const 0)))
+  ;;
+  (func(export "test6") (result i32) (i64.eq (i64.trunc_s/f64 (f64.const 9223372036854774784))  (i64.const 9223372036854774784)))
+  (func(export "test7") (result i32) (i64.eq (i64.trunc_s/f64 (f64.const 9223372036854775296))  (i64.const 0))) ;; overflow
+  ;;
+  (func(export "test8") (result i32) (i64.eq (i64.trunc_s/f64 (f64.const -9223372036854775808.0))  (i64.const -9223372036854775808)))
+  (func(export "test9") (result i32) (i64.eq (i64.trunc_s/f64 (f64.const -36893488147419103232.0))  (i64.const 0))) ;; overflow
+  ;;
+  (func(export "test10") (result i32) (i64.eq (i64.trunc_u/f32 (f32.const 4294967040.0))  (i64.const 4294967040)))
+  (func(export "test11") (result i32) (i64.eq (i64.trunc_u/f32 (f32.const 18446744073709550592.0))  (i64.const 0))) ;; overflow
+  ;;
+  (func(export "test12") (result i32) (i64.eq (i64.trunc_u/f32 (f32.const 0.0))  (i64.const 0)))
+  (func(export "test13") (result i32) (i64.eq (i64.trunc_u/f32 (f32.const 0.5))  (i64.const 0)))
+  (func(export "test14") (result i32) (i64.eq (i64.trunc_u/f32 (f32.const -1))  (i64.const 0))) ;; overflow
+  ;;
+  (func(export "test15") (result i32) (i64.eq (i64.trunc_s/f32 (f32.const 2147483520.0))  (i64.const 2147483520)))
+  (func(export "test16") (result i32) (i64.eq (i64.trunc_s/f32 (f32.const 9223372036854775296.0))  (i64.const 2147483584))) ;; overflow
+  ;;
+  (func(export "test17") (result i32) (i64.eq (i64.trunc_s/f32 (f32.const 2147483520.0))  (i64.const 2147483520)))
+  (func(export "test18") (result i32) (i64.eq (i64.trunc_s/f32 (f32.const 18446744073709551616.0))  (i64.const 0))) ;; overflow
 )
+