Wasm should support floating point operations.
authorkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 24 Oct 2016 21:44:34 +0000 (21:44 +0000)
committerkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 24 Oct 2016 21:44:34 +0000 (21:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163770

Reviewed by Michael Saboff.

JSTests:

Add appropriate b3op names for floating point wasm bytecodes, where they exist.
Also, fix some WASM => Wasm in WasmOps.h generator script that I missed
the first time I made the change.

* wasm/generate-wasmops-header.js:
(const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.template.typename.Int.inline.bool.isValidOpType): Deleted.
(const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.enum.BinaryOpType): Deleted.
(const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.enum.UnaryOpType): Deleted.
(const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.enum.LoadOpType): Deleted.
(const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.enum.StoreOpType): Deleted.
(const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.undef.CREATE_ENUM_VALUE.inline.bool.isControlOp): Deleted.
* wasm/wasm.json:

Source/JavaScriptCore:

Since we now have a Double => Float Trunc in B3, we can now support calls in Wasm
that take floating point arguments. This patch also enables most of the Wasm
floating point operations, as the associated B3 opcode has been linked via wasm.json.
If there is no direct mapping to a B3 opcode the Wasm is not yet implemented. This
patch also fixes a bug in calls where the arguments would be reversed.

* testWasm.cpp:
(cast):
(invoke):
(boxf):
(boxd):
(runWasmTests):
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::createJSWrapper):
* wasm/WasmCallingConvention.h:
(JSC::Wasm::CallingConvention::loadArguments):
(JSC::Wasm::CallingConvention::setupCall):
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser<Context>::parseExpression):
(JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression):
* wasm/WasmOps.h:

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

JSTests/ChangeLog
JSTests/wasm/generate-wasmops-header.js
JSTests/wasm/wasm.json
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/testWasm.cpp
Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
Source/JavaScriptCore/wasm/WasmCallingConvention.h
Source/JavaScriptCore/wasm/WasmFunctionParser.h
Source/JavaScriptCore/wasm/WasmOps.h

index 8a9a89d..ad60031 100644 (file)
@@ -1,3 +1,23 @@
+2016-10-24  Keith Miller  <keith_miller@apple.com>
+
+        Wasm should support floating point operations.
+        https://bugs.webkit.org/show_bug.cgi?id=163770
+
+        Reviewed by Michael Saboff.
+
+        Add appropriate b3op names for floating point wasm bytecodes, where they exist.
+        Also, fix some WASM => Wasm in WasmOps.h generator script that I missed
+        the first time I made the change.
+
+        * wasm/generate-wasmops-header.js:
+        (const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.template.typename.Int.inline.bool.isValidOpType): Deleted.
+        (const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.enum.BinaryOpType): Deleted.
+        (const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.enum.UnaryOpType): Deleted.
+        (const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.enum.LoadOpType): Deleted.
+        (const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.enum.StoreOpType): Deleted.
+        (const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.undef.CREATE_ENUM_VALUE.inline.bool.isControlOp): Deleted.
+        * wasm/wasm.json:
+
 2016-10-21  Saam Barati  <sbarati@apple.com>
 
         SpeculativeJIT::compileTryGetById needs to pass in NeedsToSpill along both the cell speculation and untyped speculation path
index b9a4252..dd0d772 100644 (file)
@@ -1,4 +1,4 @@
-// Use the JSON description of WebAssembly to generate the JavaScriptCore's WASMOps.h.
+// Use the JSON description of WebAssembly to generate the JavaScriptCore's WasmOps.h.
 
 const jsonFile = 'wasm.json';
 const wasm = JSON.parse(read(jsonFile));
@@ -90,7 +90,7 @@ const template = `/*
 
 #include <cstdint>
 
-namespace JSC { namespace WASM {
+namespace JSC { namespace Wasm {
 
 ${defines}
 
@@ -147,7 +147,7 @@ inline bool isControlOp(OpType op)
     return false;
 }
 
-} } // namespace JSC::WASM
+} } // namespace JSC::Wasm
 
 #endif // ENABLE(WEBASSEMBLY)
 `;
index a8239d1..c400a62 100644 (file)
         "i64.ctz":             { "category": "arithmetic", "value": 115, "return": ["i64"],      "parameter": ["i64"],                  "immediate": []                         },
         "i64.popcnt":          { "category": "arithmetic", "value": 116, "return": ["i64"],      "parameter": ["i64"],                  "immediate": []                         },
         "i64.eqz":             { "category": "comparison", "value": 186, "return": ["bool"],     "parameter": ["i64"],                  "immediate": []                         },
-        "f32.add":             { "category": "arithmetic", "value": 117, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": []                         },
-        "f32.sub":             { "category": "arithmetic", "value": 118, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": []                         },
-        "f32.mul":             { "category": "arithmetic", "value": 119, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": []                         },
-        "f32.div":             { "category": "arithmetic", "value": 120, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": []                         },
+        "f32.add":             { "category": "arithmetic", "value": 117, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Add"          },
+        "f32.sub":             { "category": "arithmetic", "value": 118, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Sub"          },
+        "f32.mul":             { "category": "arithmetic", "value": 119, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Mul"          },
+        "f32.div":             { "category": "arithmetic", "value": 120, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Div"          },
         "f32.min":             { "category": "arithmetic", "value": 121, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": []                         },
         "f32.max":             { "category": "arithmetic", "value": 122, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": []                         },
-        "f32.abs":             { "category": "arithmetic", "value": 123, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "f32.abs":             { "category": "arithmetic", "value": 123, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Abs"          },
         "f32.neg":             { "category": "arithmetic", "value": 124, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
         "f32.copysign":        { "category": "arithmetic", "value": 125, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
-        "f32.ceil":            { "category": "arithmetic", "value": 126, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
-        "f32.floor":           { "category": "arithmetic", "value": 127, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "f32.ceil":            { "category": "arithmetic", "value": 126, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Ceil"         },
+        "f32.floor":           { "category": "arithmetic", "value": 127, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Floor"        },
         "f32.trunc":           { "category": "arithmetic", "value": 128, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
         "f32.nearest":         { "category": "arithmetic", "value": 129, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
         "f32.sqrt":            { "category": "arithmetic", "value": 130, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
-        "f32.eq":              { "category": "comparison", "value": 131, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": []                         },
-        "f32.ne":              { "category": "comparison", "value": 132, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": []                         },
-        "f32.lt":              { "category": "comparison", "value": 133, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": []                         },
-        "f32.le":              { "category": "comparison", "value": 134, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": []                         },
-        "f32.gt":              { "category": "comparison", "value": 135, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": []                         },
-        "f32.ge":              { "category": "comparison", "value": 136, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": []                         },
-        "f64.add":             { "category": "arithmetic", "value": 137, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": []                         },
-        "f64.sub":             { "category": "arithmetic", "value": 138, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": []                         },
-        "f64.mul":             { "category": "arithmetic", "value": 139, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": []                         },
-        "f64.div":             { "category": "arithmetic", "value": 140, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": []                         },
+        "f32.eq":              { "category": "comparison", "value": 131, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Equal"        },
+        "f32.ne":              { "category": "comparison", "value": 132, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "NotEqual"     },
+        "f32.lt":              { "category": "comparison", "value": 133, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "LessThan"     },
+        "f32.le":              { "category": "comparison", "value": 134, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "LessEqual"    },
+        "f32.gt":              { "category": "comparison", "value": 135, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "GreaterThan"  },
+        "f32.ge":              { "category": "comparison", "value": 136, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "GreaterEqual" },
+        "f64.add":             { "category": "arithmetic", "value": 137, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Add"          },
+        "f64.sub":             { "category": "arithmetic", "value": 138, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Sub"          },
+        "f64.mul":             { "category": "arithmetic", "value": 139, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Mul"          },
+        "f64.div":             { "category": "arithmetic", "value": 140, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Div"          },
         "f64.min":             { "category": "arithmetic", "value": 141, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": []                         },
         "f64.max":             { "category": "arithmetic", "value": 142, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": []                         },
-        "f64.abs":             { "category": "arithmetic", "value": 143, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "f64.abs":             { "category": "arithmetic", "value": 143, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Abs"          },
         "f64.neg":             { "category": "arithmetic", "value": 144, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
         "f64.copysign":        { "category": "arithmetic", "value": 145, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
-        "f64.ceil":            { "category": "arithmetic", "value": 146, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
-        "f64.floor":           { "category": "arithmetic", "value": 147, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "f64.ceil":            { "category": "arithmetic", "value": 146, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Ceil"         },
+        "f64.floor":           { "category": "arithmetic", "value": 147, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Floor"        },
         "f64.trunc":           { "category": "arithmetic", "value": 148, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
         "f64.nearest":         { "category": "arithmetic", "value": 149, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
         "f64.sqrt":            { "category": "arithmetic", "value": 150, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
-        "f64.eq":              { "category": "comparison", "value": 151, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": []                         },
-        "f64.ne":              { "category": "comparison", "value": 152, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": []                         },
-        "f64.lt":              { "category": "comparison", "value": 153, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": []                         },
-        "f64.le":              { "category": "comparison", "value": 154, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": []                         },
-        "f64.gt":              { "category": "comparison", "value": 155, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": []                         },
-        "f64.ge":              { "category": "comparison", "value": 156, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": []                         },
+        "f64.eq":              { "category": "comparison", "value": 151, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Equal"        },
+        "f64.ne":              { "category": "comparison", "value": 152, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "NotEqual"     },
+        "f64.lt":              { "category": "comparison", "value": 153, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "LessThan"     },
+        "f64.le":              { "category": "comparison", "value": 154, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "LessEqual"    },
+        "f64.gt":              { "category": "comparison", "value": 155, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "GreaterThan"  },
+        "f64.ge":              { "category": "comparison", "value": 156, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "GreaterEqual" },
         "i32.trunc_s/f32":     { "category": "conversion", "value": 157, "return": ["i32"],      "parameter": ["f32"],                  "immediate": []                         },
         "i32.trunc_s/f64":     { "category": "conversion", "value": 158, "return": ["i32"],      "parameter": ["f64"],                  "immediate": []                         },
         "i32.trunc_u/f32":     { "category": "conversion", "value": 159, "return": ["i32"],      "parameter": ["f32"],                  "immediate": []                         },
index 04fdab1..eaa20b6 100644 (file)
@@ -1,3 +1,32 @@
+2016-10-24  Keith Miller  <keith_miller@apple.com>
+
+        Wasm should support floating point operations.
+        https://bugs.webkit.org/show_bug.cgi?id=163770
+
+        Reviewed by Michael Saboff.
+
+        Since we now have a Double => Float Trunc in B3, we can now support calls in Wasm
+        that take floating point arguments. This patch also enables most of the Wasm
+        floating point operations, as the associated B3 opcode has been linked via wasm.json.
+        If there is no direct mapping to a B3 opcode the Wasm is not yet implemented. This
+        patch also fixes a bug in calls where the arguments would be reversed.
+
+        * testWasm.cpp:
+        (cast):
+        (invoke):
+        (boxf):
+        (boxd):
+        (runWasmTests):
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::createJSWrapper):
+        * wasm/WasmCallingConvention.h:
+        (JSC::Wasm::CallingConvention::loadArguments):
+        (JSC::Wasm::CallingConvention::setupCall):
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser<Context>::parseExpression):
+        (JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression):
+        * wasm/WasmOps.h:
+
 2016-10-24  Mark Lam  <mark.lam@apple.com>
 
         Dumping of op_negate bytecode is broken.
index 1813207..a91be33 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "config.h"
 
+#include "B3Common.h"
 #include "B3Compilation.h"
 #include "InitializeThreading.h"
 #include "JSCJSValueInlines.h"
@@ -96,6 +97,8 @@ StaticLock crashLock;
         CRASH(); \
     } while (false)
 
+#define CHECK(x) CHECK_EQ(x, true)
+
 #define FOR_EACH_UNSIGNED_LEB_TEST(macro) \
     /* Simple tests that use all the bits in the array */ \
     macro(({ 0x07 }), 0, true, 0x7lu, 1lu) \
@@ -208,6 +211,24 @@ using namespace Wasm;
 using namespace B3;
 
 template<typename T>
+T cast(EncodedJSValue value)
+{
+    return static_cast<T>(value);
+}
+
+template<>
+double cast(EncodedJSValue value)
+{
+    return bitwise_cast<double>(value);
+}
+
+template<>
+float cast(EncodedJSValue value)
+{
+    return bitwise_cast<float>(static_cast<int>(value));
+}
+
+template<typename T>
 T invoke(MacroAssemblerCodePtr ptr, std::initializer_list<JSValue> args)
 {
     JSValue firstArgument;
@@ -224,8 +245,7 @@ T invoke(MacroAssemblerCodePtr ptr, std::initializer_list<JSValue> args)
     ProtoCallFrame protoCallFrame;
     protoCallFrame.init(nullptr, nullptr, firstArgument, argCount, remainingArguments);
 
-    // This won't work for floating point values but we don't have those yet.
-    return static_cast<T>(vmEntryToWasm(ptr.executableAddress(), vm, &protoCallFrame));
+    return cast<T>(vmEntryToWasm(ptr.executableAddress(), vm, &protoCallFrame));
 }
 
 template<typename T>
@@ -239,9 +259,78 @@ inline JSValue box(uint64_t value)
     return JSValue::decode(value);
 }
 
+inline JSValue boxf(float value)
+{
+    return box(bitwise_cast<uint32_t>(value));
+}
+
+inline JSValue boxd(double value)
+{
+    return box(bitwise_cast<uint64_t>(value));
+}
+
 // For now we inline the test files.
 static void runWasmTests()
 {
+
+    {
+        // Generated from:
+        //    (module
+        //     (func $f32-sub (export "f32-sub") (param f32) (param f32) (result f32) (return (f32.sub (get_local 0) (get_local 1))))
+        //     (func (export "indirect-f32-sub") (param f32) (param f32) (result f32) (return (call $f32-sub (get_local 0) (get_local 1))))
+        //     )
+        Vector<uint8_t> vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x02, 0x03, 0x03, 0x01, 0x03, 0x03, 0x83, 0x80, 0x80, 0x80, 0x00, 0x02, 0x00, 0x00, 0x07, 0x9e,
+            0x80, 0x80, 0x80, 0x00, 0x02, 0x07, 0x66, 0x33, 0x32, 0x2d, 0x73, 0x75, 0x62, 0x00, 0x00, 0x10,
+            0x69, 0x6e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x2d, 0x66, 0x33, 0x32, 0x2d, 0x73, 0x75, 0x62,
+            0x00, 0x01, 0x0a, 0x9c, 0x80, 0x80, 0x80, 0x00, 0x02, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14,
+            0x00, 0x14, 0x01, 0x76, 0x09, 0x0f, 0x89, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01,
+            0x16, 0x00, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 2 || !plan.result[0] || !plan.result[1]) {
+            dataLogLn("Module failed to compile correctly.");
+            CRASH();
+        }
+
+        // Test this doesn't crash.
+        CHECK(isIdentical(invoke<float>(*plan.result[1]->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
+        CHECK(isIdentical(invoke<float>(*plan.result[1]->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));
+        CHECK(isIdentical(invoke<float>(*plan.result[0]->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
+        CHECK(isIdentical(invoke<float>(*plan.result[0]->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));
+    }
+
+    {
+        // Generated from:
+        //    (module
+        //     (func $f32-add (export "f32-add") (param f32) (param f32) (result f32) (return (f32.add (get_local 0) (get_local 1))))
+        //     (func (export "indirect-f32-add") (param f32) (param f32) (result f32) (return (call $f32-add (get_local 0) (get_local 1))))
+        //     )
+        Vector<uint8_t> vector = {
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x02, 0x03, 0x03, 0x01, 0x03, 0x03, 0x83, 0x80, 0x80, 0x80, 0x00, 0x02, 0x00, 0x00, 0x07, 0x9e,
+            0x80, 0x80, 0x80, 0x00, 0x02, 0x07, 0x66, 0x33, 0x32, 0x2d, 0x61, 0x64, 0x64, 0x00, 0x00, 0x10,
+            0x69, 0x6e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x2d, 0x66, 0x33, 0x32, 0x2d, 0x61, 0x64, 0x64,
+            0x00, 0x01, 0x0a, 0x9c, 0x80, 0x80, 0x80, 0x00, 0x02, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14,
+            0x00, 0x14, 0x01, 0x75, 0x09, 0x0f, 0x89, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01,
+            0x16, 0x00, 0x09, 0x0f
+        };
+
+        Plan plan(*vm, vector);
+        if (plan.result.size() != 2 || !plan.result[0] || !plan.result[1]) {
+            dataLogLn("Module failed to compile correctly.");
+            CRASH();
+        }
+
+        // Test this doesn't crash.
+        CHECK(isIdentical(invoke<float>(*plan.result[1]->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
+        CHECK(isIdentical(invoke<float>(*plan.result[1]->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));
+        CHECK(isIdentical(invoke<float>(*plan.result[0]->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
+        CHECK(isIdentical(invoke<float>(*plan.result[0]->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));
+    }
+
     {
         // Generated from:
         //    (module
index 5359d30..1417792 100644 (file)
@@ -697,10 +697,19 @@ static std::unique_ptr<Compilation> createJSWrapper(VM& vm, const Signature* sig
     });
 
     // Return the result, if needed.
-    if (signature->returnType != Void)
-        block->appendNewControlValue(proc, B3::Return, Origin(), result);
-    else
+    switch (signature->returnType) {
+    case Void:
         block->appendNewControlValue(proc, B3::Return, Origin());
+        break;
+    case F32:
+    case F64:
+        result = block->appendNew<Value>(proc, BitwiseCast, Origin(), result);
+        FALLTHROUGH;
+    case I32:
+    case I64:
+        block->appendNewControlValue(proc, B3::Return, Origin(), result);
+        break;
+    }
 
     return std::make_unique<Compilation>(vm, proc);
 }
index 7442e71..5589363 100644 (file)
@@ -98,10 +98,8 @@ public:
             B3::ValueRep rep = marshallArgument(type, gpArgumentCount, fpArgumentCount, stackOffset);
             if (rep.isReg()) {
                 argument = block->appendNew<B3::ArgumentRegValue>(proc, origin, rep.reg());
-                if (type == B3::Int32)
+                if (type == B3::Int32 || type == B3::Float)
                     argument = block->appendNew<B3::Value>(proc, B3::Trunc, origin, argument);
-                // FIXME: How do I get a float from a FPR? We don't support floating points yet so it's not a big deal... yet.
-                // see: https://bugs.webkit.org/show_bug.cgi?id=163770
             } else {
                 ASSERT(rep.isStackArgument());
                 B3::Value* address = block->appendNew<B3::Value>(proc, B3::Add, origin, framePointer,
@@ -134,10 +132,18 @@ public:
         patchpoint->appendVector(constrainedArguments);
         patchpointFunctor(patchpoint);
 
-        if (returnType == B3::Void)
+        switch (returnType) {
+        case B3::Void:
             return nullptr;
-
-        patchpoint->resultConstraint = B3::ValueRep::reg(GPRInfo::returnValueGPR);
+        case B3::Float:
+        case B3::Double:
+            patchpoint->resultConstraint = B3::ValueRep::reg(FPRInfo::returnValueFPR);
+            break;
+        case B3::Int32:
+        case B3::Int64:
+            patchpoint->resultConstraint = B3::ValueRep::reg(GPRInfo::returnValueGPR);
+            break;
+        }
         return patchpoint;
     }
 
index 0bce7e3..a0d5b3d 100644 (file)
@@ -190,6 +190,7 @@ bool FunctionParser<Context>::parseExpression(OpType op)
         return m_context.store(static_cast<StoreOpType>(op), pointer, value, offset);
     }
 
+    case OpType::F32Const:
     case OpType::I32Const: {
         uint32_t constant;
         if (!parseVarUInt32(constant))
@@ -198,6 +199,7 @@ bool FunctionParser<Context>::parseExpression(OpType op)
         return true;
     }
 
+    case OpType::F64Const:
     case OpType::I64Const: {
         uint64_t constant;
         if (!parseVarUInt64(constant))
@@ -236,9 +238,15 @@ bool FunctionParser<Context>::parseExpression(OpType op)
 
         const FunctionInformation& info = m_functions[functionIndex];
 
+        if (info.signature->arguments.size() > m_expressionStack.size())
+            return false;
+
+        size_t firstArgumentIndex = m_expressionStack.size() - info.signature->arguments.size();
         Vector<ExpressionType> args;
-        for (unsigned i = 0; i < info.signature->arguments.size(); ++i)
-            args.append(m_expressionStack.takeLast());
+        args.reserveInitialCapacity(info.signature->arguments.size());
+        for (unsigned i = firstArgumentIndex; i < m_expressionStack.size(); ++i)
+            args.append(m_expressionStack[i]);
+        m_expressionStack.shrink(firstArgumentIndex);
 
         ExpressionType result = Context::emptyExpression;
         if (!m_context.addCall(functionIndex, info, args, result))
@@ -318,8 +326,6 @@ bool FunctionParser<Context>::parseExpression(OpType op)
     case OpType::BrTable:
     case OpType::Nop:
     case OpType::Drop:
-    case OpType::F32Const:
-    case OpType::F64Const:
     case OpType::TeeLocal:
     case OpType::GetGlobal:
     case OpType::SetGlobal:
@@ -374,7 +380,10 @@ bool FunctionParser<Context>::parseUnreachableExpression(OpType op)
 
     // one immediate cases
     case OpType::Return:
+    case OpType::F32Const:
     case OpType::I32Const:
+    case OpType::F64Const:
+    case OpType::I64Const:
     case OpType::SetLocal:
     case OpType::GetLocal: {
         uint32_t unused;
index 3cd9ee7..fd38ffe 100644 (file)
@@ -68,19 +68,19 @@ namespace JSC { namespace Wasm {
     macro(I64Clz, 0x72, Clz) \
     macro(I64Ctz, 0x73, Oops) \
     macro(I64Popcnt, 0x74, Oops) \
-    macro(F32Abs, 0x7b, Oops) \
+    macro(F32Abs, 0x7b, Abs) \
     macro(F32Neg, 0x7c, Oops) \
     macro(F32Copysign, 0x7d, Oops) \
-    macro(F32Ceil, 0x7e, Oops) \
-    macro(F32Floor, 0x7f, Oops) \
+    macro(F32Ceil, 0x7e, Ceil) \
+    macro(F32Floor, 0x7f, Floor) \
     macro(F32Trunc, 0x80, Oops) \
     macro(F32Nearest, 0x81, Oops) \
     macro(F32Sqrt, 0x82, Oops) \
-    macro(F64Abs, 0x8f, Oops) \
+    macro(F64Abs, 0x8f, Abs) \
     macro(F64Neg, 0x90, Oops) \
     macro(F64Copysign, 0x91, Oops) \
-    macro(F64Ceil, 0x92, Oops) \
-    macro(F64Floor, 0x93, Oops) \
+    macro(F64Ceil, 0x92, Ceil) \
+    macro(F64Floor, 0x93, Floor) \
     macro(F64Trunc, 0x94, Oops) \
     macro(F64Nearest, 0x95, Oops) \
     macro(F64Sqrt, 0x96, Oops)
@@ -136,30 +136,30 @@ namespace JSC { namespace Wasm {
     macro(I64GeS, 0x6f, GreaterEqual) \
     macro(I64GtU, 0x70, Above) \
     macro(I64GeU, 0x71, AboveEqual) \
-    macro(F32Add, 0x75, Oops) \
-    macro(F32Sub, 0x76, Oops) \
-    macro(F32Mul, 0x77, Oops) \
-    macro(F32Div, 0x78, Oops) \
+    macro(F32Add, 0x75, Add) \
+    macro(F32Sub, 0x76, Sub) \
+    macro(F32Mul, 0x77, Mul) \
+    macro(F32Div, 0x78, Div) \
     macro(F32Min, 0x79, Oops) \
     macro(F32Max, 0x7a, Oops) \
-    macro(F32Eq, 0x83, Oops) \
-    macro(F32Ne, 0x84, Oops) \
-    macro(F32Lt, 0x85, Oops) \
-    macro(F32Le, 0x86, Oops) \
-    macro(F32Gt, 0x87, Oops) \
-    macro(F32Ge, 0x88, Oops) \
-    macro(F64Add, 0x89, Oops) \
-    macro(F64Sub, 0x8a, Oops) \
-    macro(F64Mul, 0x8b, Oops) \
-    macro(F64Div, 0x8c, Oops) \
+    macro(F32Eq, 0x83, Equal) \
+    macro(F32Ne, 0x84, NotEqual) \
+    macro(F32Lt, 0x85, LessThan) \
+    macro(F32Le, 0x86, LessEqual) \
+    macro(F32Gt, 0x87, GreaterThan) \
+    macro(F32Ge, 0x88, GreaterEqual) \
+    macro(F64Add, 0x89, Add) \
+    macro(F64Sub, 0x8a, Sub) \
+    macro(F64Mul, 0x8b, Mul) \
+    macro(F64Div, 0x8c, Div) \
     macro(F64Min, 0x8d, Oops) \
     macro(F64Max, 0x8e, Oops) \
-    macro(F64Eq, 0x97, Oops) \
-    macro(F64Ne, 0x98, Oops) \
-    macro(F64Lt, 0x99, Oops) \
-    macro(F64Le, 0x9a, Oops) \
-    macro(F64Gt, 0x9b, Oops) \
-    macro(F64Ge, 0x9c, Oops)
+    macro(F64Eq, 0x97, Equal) \
+    macro(F64Ne, 0x98, NotEqual) \
+    macro(F64Lt, 0x99, LessThan) \
+    macro(F64Le, 0x9a, LessEqual) \
+    macro(F64Gt, 0x9b, GreaterThan) \
+    macro(F64Ge, 0x9c, GreaterEqual)
 
 #define FOR_EACH_WASM_MEMORY_LOAD_OP(macro) \
     macro(I32Load8S, 0x20, Oops) \