Add wasm int to floating point opcodes
authorkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 Dec 2016 22:00:23 +0000 (22:00 +0000)
committerkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 Dec 2016 22:00:23 +0000 (22:00 +0000)
https://bugs.webkit.org/show_bug.cgi?id=165252

Reviewed by Geoffrey Garen.

JSTests:

Add tests for Wasm integral to floating point conversion opcodes.

* wasm/function-tests/int-to-floating-point.js: Added.
* wasm/wasm.json:

Source/JavaScriptCore:

This patch adds support for the Wasm integral type => floating point
type conversion opcodes. Most of these were already supported by B3
however there was no support for uint64 to float/double. Unfortunately,
AFAIK x86_64 does not have a single instruction that performs this
conversion. Since there is a signed conversion instruction on x86 we
use that for all uint64s that don't have the top bit set. If they do have
the top bit set we need to divide by 2 (rounding up) then convert the number
with the signed conversion then double the result.

* assembler/MacroAssemblerX86_64.h:
(JSC::MacroAssemblerX86_64::convertUInt64ToDouble):
(JSC::MacroAssemblerX86_64::convertUInt64ToFloat):
* jsc.cpp:
(valueWithTypeOfWasmValue):
(box):
(functionTestWasmModuleFunctions):
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::addOp<F64ConvertUI64>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::F32ConvertUI64>):
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser<Context>::parseExpression):
* wasm/wasm.json:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@209204 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JSTests/ChangeLog
JSTests/wasm/function-tests/int-to-floating-point.js [new file with mode: 0644]
JSTests/wasm/wasm.json
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
Source/JavaScriptCore/wasm/WasmFunctionParser.h
Source/JavaScriptCore/wasm/wasm.json

index 783c306..0aaef97 100644 (file)
@@ -1,3 +1,15 @@
+2016-12-01  Keith Miller  <keith_miller@apple.com>
+
+        Add wasm int to floating point opcodes
+        https://bugs.webkit.org/show_bug.cgi?id=165252
+
+        Reviewed by Geoffrey Garen.
+
+        Add tests for Wasm integral to floating point conversion opcodes.
+
+        * wasm/function-tests/int-to-floating-point.js: Added.
+        * wasm/wasm.json:
+
 2016-12-01  Geoffrey Garen  <ggaren@apple.com>
 
         Land a test case for <rdar://problem/27889416>
diff --git a/JSTests/wasm/function-tests/int-to-floating-point.js b/JSTests/wasm/function-tests/int-to-floating-point.js
new file mode 100644 (file)
index 0000000..c1633b8
--- /dev/null
@@ -0,0 +1,135 @@
+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.setChecked(false);
+b.Type().End()
+    .Function().End()
+    .Code()
+
+    .Function({ params: ["i64"], ret: "f32" }, [])
+    .GetLocal(0)
+    .F32ConvertUI64()
+    .End()
+
+    .Function({ params: ["i64"], ret: "f32" }, [])
+    .GetLocal(0)
+    .F32ConvertSI64()
+    .End()
+
+    .Function({ params: ["i32"], ret: "f32" }, [])
+    .GetLocal(0)
+    .F32ConvertUI32()
+    .End()
+
+    .Function({ params: ["i32"], ret: "f32" }, [])
+    .GetLocal(0)
+    .F32ConvertSI32()
+    .End()
+
+    .Function({ params: ["i64"], ret: "f64" }, [])
+    .GetLocal(0)
+    .F64ConvertUI64()
+    .End()
+
+    .Function({ params: ["i64"], ret: "f64" }, [])
+    .GetLocal(0)
+    .F64ConvertSI64()
+    .End()
+
+    .Function({ params: ["i32"], ret: "f64" }, [])
+    .GetLocal(0)
+    .F64ConvertUI32()
+    .End()
+
+    .Function({ params: ["i32"], ret: "f64" }, [])
+    .GetLocal(0)
+    .F64ConvertSI32()
+    .End()
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 8,
+                        [[{ type: "f32", value: 1.0 }, [{ type: "i64", value: "1" }]],
+                         [{ type: "f32", value: 0.0 }, [{ type: "i64", value: "0" }]],
+                         [{ type: "f32", value: 9223372036854775807 }, [{type: "i64", value: "9223372036854775807" }]],
+                         [{ type: "f32", value: 9223372036854775808 }, [{type: "i64", value: "-9223372036854775808" }]],
+                         [{ type: "f32", value: 18446744073709551616.0 }, [{ type: "i64", value: "0xffffffffffffffff" }]],
+                         // Test rounding directions.
+                         [{ type: "f32", value: 16777216.0 }, [{ type: "i64", value: "16777217" }]],
+                         [{ type: "f32", value: 16777220.0 }, [{ type: "i64", value: "16777219" }]]
+                        ],
+
+                        [[{ type: "f32", value: 1.0 }, [{ type: "i64", value: "1" }]],
+                         [{ type: "f32", value: -1.0}, [{ type: "i64", value: "-1" }]],
+                         [{ type: "f32", value: 0.0}, [{ type: "i64", value: "0" }]],
+                         [{ type: "f32", value: 9223372036854775807}, [{ type: "i64", value: "9223372036854775807" }]],
+                         [{ type: "f32", value: -9223372036854775808}, [{ type: "i64", value: "-9223372036854775808" }]],
+                         [{ type: "f32", value: 314159275180032.0}, [{ type: "i64", value: "314159265358979" }]],
+                         // Test rounding directions.
+                         [{ type: "f32", value: 16777216.0}, [{ type: "i64", value: "16777217" }]],
+                         [{ type: "f32", value: -16777216.0}, [{ type: "i64", value: "-16777217" }]],
+                         [{ type: "f32", value: 16777220.0}, [{ type: "i64", value: "16777219" }]],
+                         [{ type: "f32", value: -16777220.0}, [{ type: "i64", value: "-16777219" }]]
+                        ],
+
+                        [[{ type: "f32", value: 1.0 }, [{ type: "i32", value: 1 }]],
+                         [{ type: "f32", value: 0.0 }, [{ type: "i32", value: 0 }]],
+                         [{ type: "f32", value: 2147483648 }, [{ type: "i32", value: 2147483647 }]],
+                         [{ type: "f32", value: 2147483648 }, [{ type: "i32", value: -2147483648 }]],
+                         [{ type: "f32", value: 305419904.0 }, [{ type: "i32", value: 0x12345678 }]],
+                         [{ type: "f32", value: 4294967296.0 }, [{ type: "i32", value: -1 }]],
+                         // Test rounding directions.
+                         [{ type: "f32", value: 16777220.0 }, [{ type: "i32", value: 16777219 }]]
+                        ],
+
+                        [[{ type: "f32", value: 1.0 }, [{ type: "i32", value: 1 }]],
+                         [{ type: "f32", value: -1.0 }, [{ type: "i32", value: -1 }]],
+                         [{ type: "f32", value: 0.0 }, [{ type: "i32", value: 0 }]],
+                         [{ type: "f32", value: 2147483648 }, [{ type: "i32", value: 2147483647 }]],
+                         [{ type: "f32", value: -2147483648 }, [{ type: "i32", value: -2147483648 }]],
+                         [{ type: "f32", value: 1234567936.0 }, [{ type: "i32", value: 1234567890 }]],
+                         // Test rounding directions.
+                         [{ type: "f32", value: 16777216.0 }, [{ type: "i32", value: 16777217 }]],
+                         [{ type: "f32", value: -16777216.0 }, [{ type: "i32", value: -16777217 }]],
+                         [{ type: "f32", value: 16777220.0 }, [{ type: "i32", value: 16777219 }]],
+                         [{ type: "f32", value: -16777220.0 }, [{ type: "i32", value: -16777219 }]]
+                        ],
+
+                        [[{ type: "f64", value: 1.0 }, [{ type: "i64", value: "1" }]],
+                         [{ type: "f64", value: 0.0 }, [{ type: "i64", value: "0" }]],
+                         [{ type: "f64", value: 9223372036854775807 }, [{ type: "i64", value: "9223372036854775807" }]],
+                         [{ type: "f64", value: 9223372036854775808 }, [{ type: "i64", value: "-9223372036854775808" }]],
+                         [{ type: "f64", value: 18446744073709551616.0 }, [{ type: "i64", value: "0xffffffffffffffff" }]],
+                         // Test rounding directions.
+                         [{ type: "f64", value: 9007199254740992 }, [{ type: "i64", value: "9007199254740993" }]],
+                         [{ type: "f64", value: 9007199254740996 }, [{ type: "i64", value: "9007199254740995" }]]
+                        ],
+
+                        [[{ type: "f64", value: 1.0 }, [{ type: "i64", value: "1" }]],
+                         [{ type: "f64", value: -1.0 }, [{ type: "i64", value: "-1" }]],
+                         [{ type: "f64", value: 0.0 }, [{ type: "i64", value: "0" }]],
+                         [{ type: "f64", value: 9223372036854775807 }, [{ type: "i64", value: "9223372036854775807" }]],
+                         [{ type: "f64", value: -9223372036854775808 }, [{ type: "i64", value: "-9223372036854775808" }]],
+                         [{ type: "f64", value: 4669201609102990 }, [{ type: "i64", value: "4669201609102990" }]],
+                         // Test rounding directions.
+                         [{ type: "f64", value: 9007199254740992 }, [{ type: "i64", value: "9007199254740993" }]],
+                         [{ type: "f64", value: -9007199254740992 }, [{ type: "i64", value: "-9007199254740993" }]],
+                         [{ type: "f64", value: 9007199254740996 }, [{ type: "i64", value: "9007199254740995" }]],
+                         [{ type: "f64", value: -9007199254740996 }, [{ type: "i64", value: "-9007199254740995" }]]
+                        ],
+
+                        [[{ type: "f64", value: 1.0 }, [{ type: "i32", value: 1 }]],
+                         [{ type: "f64", value: 0.0 }, [{ type: "i32", value: 0 }]],
+                         [{ type: "f64", value: 2147483647 }, [{ type: "i32", value: 2147483647 }]],
+                         [{ type: "f64", value: 2147483648 }, [{ type: "i32", value: -2147483648 }]],
+                         [{ type: "f64", value: 4294967295.0 }, [{ type: "i32", value: -1 }]]
+                        ],
+
+                        [[{ type: "f64", value: 1.0 }, [{ type: "i32", value: 1 }]],
+                         [{ type: "f64", value: -1.0 }, [{ type: "i32", value: -1 }]],
+                         [{ type: "f64", value: 0.0 }, [{ type: "i32", value: 0 }]],
+                         [{ type: "f64", value: 2147483647 }, [{ type: "i32", value: 2147483647 }]],
+                         [{ type: "f64", value: -2147483648 }, [{ type: "i32", value: -2147483648 }]],
+                         [{ type: "f64", value: 987654321 }, [{ type: "i32", value: 987654321 }]]
+                        ]
+                       );
index 34878ea..87b23d1 100644 (file)
         "i64.trunc_u/f64":     { "category": "conversion", "value": 177, "return": ["i64"],      "parameter": ["f64"],                  "immediate": []                         },
         "i64.extend_s/i32":    { "category": "conversion", "value": 172, "return": ["i64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "SExt32"       },
         "i64.extend_u/i32":    { "category": "conversion", "value": 173, "return": ["i64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "ZExt32"       },
-        "f32.convert_s/i32":   { "category": "conversion", "value": 178, "return": ["f32"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f32.convert_u/i32":   { "category": "conversion", "value": 179, "return": ["f32"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f32.convert_s/i64":   { "category": "conversion", "value": 180, "return": ["f32"],      "parameter": ["i64"],                  "immediate": []                         },
+        "f32.convert_s/i32":   { "category": "conversion", "value": 178, "return": ["f32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "IToF"         },
+        "f32.convert_u/i32":   { "category": "conversion", "value": 179, "return": ["f32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "IToF(ZExt32(@0))" },
+        "f32.convert_s/i64":   { "category": "conversion", "value": 180, "return": ["f32"],      "parameter": ["i64"],                  "immediate": [], "b3op": "IToF"         },
         "f32.convert_u/i64":   { "category": "conversion", "value": 181, "return": ["f32"],      "parameter": ["i64"],                  "immediate": []                         },
         "f32.demote/f64":      { "category": "conversion", "value": 182, "return": ["f32"],      "parameter": ["f64"],                  "immediate": [], "b3op": "DoubleToFloat"},
         "f32.reinterpret/i32": { "category": "conversion", "value": 190, "return": ["f32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "BitwiseCast"  },
-        "f64.convert_s/i32":   { "category": "conversion", "value": 183, "return": ["f64"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f64.convert_u/i32":   { "category": "conversion", "value": 184, "return": ["f64"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f64.convert_s/i64":   { "category": "conversion", "value": 185, "return": ["f64"],      "parameter": ["i64"],                  "immediate": []                         },
+        "f64.convert_s/i32":   { "category": "conversion", "value": 183, "return": ["f64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "IToD"         },
+        "f64.convert_u/i32":   { "category": "conversion", "value": 184, "return": ["f64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "IToD(ZExt32(@0))" },
+        "f64.convert_s/i64":   { "category": "conversion", "value": 185, "return": ["f64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "IToD"         },
         "f64.convert_u/i64":   { "category": "conversion", "value": 186, "return": ["f64"],      "parameter": ["i64"],                  "immediate": []                         },
         "f64.promote/f32":     { "category": "conversion", "value": 187, "return": ["f64"],      "parameter": ["f32"],                  "immediate": [], "b3op": "FloatToDouble"},
         "f64.reinterpret/i64": { "category": "conversion", "value": 191, "return": ["f64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "BitwiseCast"  },
index e864992..cdff18f 100644 (file)
@@ -1,3 +1,33 @@
+2016-12-01  Keith Miller  <keith_miller@apple.com>
+
+        Add wasm int to floating point opcodes
+        https://bugs.webkit.org/show_bug.cgi?id=165252
+
+        Reviewed by Geoffrey Garen.
+
+        This patch adds support for the Wasm integral type => floating point
+        type conversion opcodes. Most of these were already supported by B3
+        however there was no support for uint64 to float/double. Unfortunately,
+        AFAIK x86_64 does not have a single instruction that performs this
+        conversion. Since there is a signed conversion instruction on x86 we
+        use that for all uint64s that don't have the top bit set. If they do have
+        the top bit set we need to divide by 2 (rounding up) then convert the number
+        with the signed conversion then double the result.
+
+        * assembler/MacroAssemblerX86_64.h:
+        (JSC::MacroAssemblerX86_64::convertUInt64ToDouble):
+        (JSC::MacroAssemblerX86_64::convertUInt64ToFloat):
+        * jsc.cpp:
+        (valueWithTypeOfWasmValue):
+        (box):
+        (functionTestWasmModuleFunctions):
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::addOp<F64ConvertUI64>):
+        (JSC::Wasm::B3IRGenerator::addOp<OpType::F32ConvertUI64>):
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser<Context>::parseExpression):
+        * wasm/wasm.json:
+
 2016-12-01  Geoffrey Garen  <ggaren@apple.com>
 
         Renamed EvalCodeCache => DirectEvalCodeCache
index e38057b..ec15adc 100644 (file)
@@ -1682,7 +1682,17 @@ public:
     {
         m_assembler.scvtf<32, 64>(dest, src);
     }
-    
+
+    void convertUInt64ToDouble(RegisterID src, FPRegisterID dest)
+    {
+        m_assembler.ucvtf<64, 64>(dest, src);
+    }
+
+    void convertUInt64ToFloat(RegisterID src, FPRegisterID dest)
+    {
+        m_assembler.ucvtf<32, 64>(dest, src);
+    }
+
     void divDouble(FPRegisterID src, FPRegisterID dest)
     {
         divDouble(dest, src, dest);
index c9bc078..67308de 100644 (file)
@@ -1305,6 +1305,47 @@ public:
         m_assembler.cvtsi2ssq_mr(src.offset, src.base, dest);
     }
 
+    // One of scratch or scratch2 may be the same as src
+    void convertUInt64ToDouble(RegisterID src, FPRegisterID dest, RegisterID scratch)
+    {
+        RegisterID scratch2 = scratchRegister();
+
+        m_assembler.testq_rr(src, src);
+        AssemblerLabel signBitSet = m_assembler.jCC(x86Condition(Signed));
+        m_assembler.cvtsi2sdq_rr(src, dest);
+        AssemblerLabel done = m_assembler.jmp();
+        m_assembler.linkJump(signBitSet, m_assembler.label());
+        if (scratch != src)
+            m_assembler.movq_rr(src, scratch);
+        m_assembler.movq_rr(src, scratch2);
+        m_assembler.shrq_i8r(1, scratch);
+        m_assembler.andq_ir(1, scratch2);
+        m_assembler.orq_rr(scratch, scratch2);
+        m_assembler.cvtsi2sdq_rr(scratch2, dest);
+        m_assembler.addsd_rr(dest, dest);
+        m_assembler.linkJump(done, m_assembler.label());
+    }
+
+    // One of scratch or scratch2 may be the same as src
+    void convertUInt64ToFloat(RegisterID src, FPRegisterID dest, RegisterID scratch)
+    {
+        RegisterID scratch2 = scratchRegister();
+        m_assembler.testq_rr(src, src);
+        AssemblerLabel signBitSet = m_assembler.jCC(x86Condition(Signed));
+        m_assembler.cvtsi2ssq_rr(src, dest);
+        AssemblerLabel done = m_assembler.jmp();
+        m_assembler.linkJump(signBitSet, m_assembler.label());
+        if (scratch != src)
+            m_assembler.movq_rr(src, scratch);
+        m_assembler.movq_rr(src, scratch2);
+        m_assembler.shrq_i8r(1, scratch);
+        m_assembler.andq_ir(1, scratch2);
+        m_assembler.orq_rr(scratch, scratch2);
+        m_assembler.cvtsi2ssq_rr(scratch2, dest);
+        m_assembler.addss_rr(dest, dest);
+        m_assembler.linkJump(done, m_assembler.label());
+    }
+
     static bool supportsFloatingPoint() { return true; }
     static bool supportsFloatingPointTruncate() { return true; }
     static bool supportsFloatingPointSqrt() { return true; }
index 434e4ea..6db5c11 100644 (file)
@@ -75,6 +75,7 @@
 #include <string.h>
 #include <thread>
 #include <type_traits>
+#include <wtf/CommaPrinter.h>
 #include <wtf/CurrentTime.h>
 #include <wtf/MainThread.h>
 #include <wtf/NeverDestroyed.h>
@@ -2495,6 +2496,18 @@ EncodedJSValue JSC_HOST_CALL functionMaxArguments(ExecState*)
 
 #if ENABLE(WEBASSEMBLY)
 
+static CString valueWithTypeOfWasmValue(ExecState* exec, VM& vm, JSValue value, JSValue wasmValue)
+{
+    JSString* type = jsCast<JSString*>(wasmValue.get(exec, makeIdentifier(vm, "type")));
+
+    const String& typeString = type->value(exec);
+    if (typeString == "i64" || typeString == "i32")
+        return toCString(typeString, " ", RawPointer(bitwise_cast<void*>(value)));
+    if (typeString == "f32")
+        return toCString(typeString, " hex: ", RawPointer(bitwise_cast<void*>(value)), ", float: ", bitwise_cast<float>(static_cast<uint32_t>(JSValue::encode(value))));
+    return toCString(typeString, " hex: ", RawPointer(bitwise_cast<void*>(value)), ", double: ", bitwise_cast<double>(value));
+}
+
 static JSValue box(ExecState* exec, VM& vm, JSValue wasmValue)
 {
     JSString* type = jsCast<JSString*>(wasmValue.get(exec, makeIdentifier(vm, "type")));
@@ -2502,9 +2515,14 @@ static JSValue box(ExecState* exec, VM& vm, JSValue wasmValue)
 
     const String& typeString = type->value(exec);
     if (typeString == "i64") {
-        RELEASE_ASSERT(value.isString());
         int64_t result;
-        RELEASE_ASSERT(sscanf(bitwise_cast<const char*>(jsCast<JSString*>(value)->value(exec).characters8()), "%lld", &result) != EOF);
+        const char* str = toCString(jsCast<JSString*>(value)->value(exec)).data();
+        int scanResult;
+        if (std::strlen(str) > 2 && str[0] == '0' && str[1] == 'x')
+            scanResult = sscanf(str, "%llx", &result);
+        else
+            scanResult = sscanf(str, "%lld", &result);
+        RELEASE_ASSERT(scanResult != EOF);
         return JSValue::decode(result);
     }
     RELEASE_ASSERT(value.isNumber());
@@ -2582,7 +2600,13 @@ static EncodedJSValue JSC_HOST_CALL functionTestWasmModuleFunctions(ExecState* e
             JSValue callResult = callWasmFunction(&vm, *plan.compiledFunction(i)->jsEntryPoint, boxedArgs);
             JSValue expected = box(exec, vm, result);
             if (callResult != expected) {
-                WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, toCString(" (callResult == ", RawPointer(bitwise_cast<void*>(callResult)), ", expected == ", RawPointer(bitwise_cast<void*>(expected)), ")").data());
+                dataLog("Arguments: ");
+                CommaPrinter comma(", ");
+                for (unsigned argIndex = 0; argIndex < arguments->length(); ++argIndex)
+                    dataLog(comma, valueWithTypeOfWasmValue(exec, vm, boxedArgs[argIndex], arguments->getIndexQuickly(argIndex)));
+                dataLogLn();
+
+                WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, toCString(" (callResult == ", valueWithTypeOfWasmValue(exec, vm, callResult, result), ", expected == ", valueWithTypeOfWasmValue(exec, vm, expected, result), ")").data());
                 CRASH();
             }
         }
index fd07c45..3d98a62 100644 (file)
@@ -760,6 +760,48 @@ std::unique_ptr<FunctionCompilation> parseAndCompile(VM& vm, const uint8_t* func
     return result;
 }
 
+// Custom wasm ops. These are the ones too messy to do in wasm.json.
+
+template<>
+bool B3IRGenerator::addOp<F64ConvertUI64>(ExpressionType arg, ExpressionType& result)
+{
+    PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Float, Origin());
+    if (isX86())
+        patchpoint->numGPScratchRegisters = 1;
+    patchpoint->append(ConstrainedValue(arg, ValueRep::WarmAny));
+    patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+        AllowMacroScratchRegisterUsage allowScratch(jit);
+#if CPU(X86_64)
+        jit.convertUInt64ToDouble(params[1].gpr(), params[0].fpr(), params.gpScratch(0));
+#else
+        jit.convertUInt64ToDouble(params[1].gpr(), params[0].fpr());
+#endif
+    });
+    patchpoint->effects = Effects::none();
+    result = patchpoint;
+    return true;
+}
+
+template<>
+bool B3IRGenerator::addOp<OpType::F32ConvertUI64>(ExpressionType arg, ExpressionType& result)
+{
+    PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Float, Origin());
+    if (isX86())
+        patchpoint->numGPScratchRegisters = 1;
+    patchpoint->append(ConstrainedValue(arg, ValueRep::WarmAny));
+    patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+        AllowMacroScratchRegisterUsage allowScratch(jit);
+#if CPU(X86_64)
+        jit.convertUInt64ToFloat(params[1].gpr(), params[0].fpr(), params.gpScratch(0));
+#else
+        jit.convertUInt64ToFloat(params[1].gpr(), params[0].fpr());
+#endif
+    });
+    patchpoint->effects = Effects::none();
+    result = patchpoint;
+    return true;
+}
+
 } } // namespace JSC::Wasm
 
 #include "WasmB3IRGeneratorInlines.h"
index 4ee1b5f..bea73cc 100644 (file)
@@ -211,6 +211,8 @@ bool FunctionParser<Context>::parseExpression(OpType op)
     FOR_EACH_WASM_SIMPLE_BINARY_OP(CREATE_CASE)
 #undef CREATE_CASE
 
+    case OpType::F32ConvertUI64: return unaryCase<OpType::F32ConvertUI64>();
+    case OpType::F64ConvertUI64: return unaryCase<OpType::F64ConvertUI64>();
 #define CREATE_CASE(name, id, b3op, inc) case OpType::name: return unaryCase<OpType::name>();
     FOR_EACH_WASM_SIMPLE_UNARY_OP(CREATE_CASE)
 #undef CREATE_CASE
index 34878ea..87b23d1 100644 (file)
         "i64.trunc_u/f64":     { "category": "conversion", "value": 177, "return": ["i64"],      "parameter": ["f64"],                  "immediate": []                         },
         "i64.extend_s/i32":    { "category": "conversion", "value": 172, "return": ["i64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "SExt32"       },
         "i64.extend_u/i32":    { "category": "conversion", "value": 173, "return": ["i64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "ZExt32"       },
-        "f32.convert_s/i32":   { "category": "conversion", "value": 178, "return": ["f32"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f32.convert_u/i32":   { "category": "conversion", "value": 179, "return": ["f32"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f32.convert_s/i64":   { "category": "conversion", "value": 180, "return": ["f32"],      "parameter": ["i64"],                  "immediate": []                         },
+        "f32.convert_s/i32":   { "category": "conversion", "value": 178, "return": ["f32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "IToF"         },
+        "f32.convert_u/i32":   { "category": "conversion", "value": 179, "return": ["f32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "IToF(ZExt32(@0))" },
+        "f32.convert_s/i64":   { "category": "conversion", "value": 180, "return": ["f32"],      "parameter": ["i64"],                  "immediate": [], "b3op": "IToF"         },
         "f32.convert_u/i64":   { "category": "conversion", "value": 181, "return": ["f32"],      "parameter": ["i64"],                  "immediate": []                         },
         "f32.demote/f64":      { "category": "conversion", "value": 182, "return": ["f32"],      "parameter": ["f64"],                  "immediate": [], "b3op": "DoubleToFloat"},
         "f32.reinterpret/i32": { "category": "conversion", "value": 190, "return": ["f32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "BitwiseCast"  },
-        "f64.convert_s/i32":   { "category": "conversion", "value": 183, "return": ["f64"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f64.convert_u/i32":   { "category": "conversion", "value": 184, "return": ["f64"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f64.convert_s/i64":   { "category": "conversion", "value": 185, "return": ["f64"],      "parameter": ["i64"],                  "immediate": []                         },
+        "f64.convert_s/i32":   { "category": "conversion", "value": 183, "return": ["f64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "IToD"         },
+        "f64.convert_u/i32":   { "category": "conversion", "value": 184, "return": ["f64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "IToD(ZExt32(@0))" },
+        "f64.convert_s/i64":   { "category": "conversion", "value": 185, "return": ["f64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "IToD"         },
         "f64.convert_u/i64":   { "category": "conversion", "value": 186, "return": ["f64"],      "parameter": ["i64"],                  "immediate": []                         },
         "f64.promote/f32":     { "category": "conversion", "value": 187, "return": ["f64"],      "parameter": ["f32"],                  "immediate": [], "b3op": "FloatToDouble"},
         "f64.reinterpret/i64": { "category": "conversion", "value": 191, "return": ["f64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "BitwiseCast"  },