Update WASM towards 0xc
authorkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 19 Sep 2016 20:39:55 +0000 (20:39 +0000)
committerkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 19 Sep 2016 20:39:55 +0000 (20:39 +0000)
https://bugs.webkit.org/show_bug.cgi?id=162067

Reviewed by Geoffrey Garen.

This patch updates some of the core parts of the WASM frontend to the 0xc standard.
First, it changes the section names from strings to bytecodes. It also adds support
for inline block signatures. This is a change from the old version that used to have
each branch indicate the arity. Finally, this patch updates all the tests and deletes
a duplicate test.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* testWASM.cpp:
(runWASMTests):
* wasm/WASMB3IRGenerator.cpp:
* wasm/WASMFormat.h:
* wasm/WASMFunctionParser.h:
(JSC::WASM::FunctionParser<Context>::FunctionParser):
(JSC::WASM::FunctionParser<Context>::parseBlock):
(JSC::WASM::FunctionParser<Context>::parseExpression):
* wasm/WASMModuleParser.cpp:
(JSC::WASM::ModuleParser::parse):
* wasm/WASMSections.cpp: Removed.
(JSC::WASM::Sections::lookup): Deleted.
* wasm/WASMSections.h:
(JSC::WASM::Sections::validateOrder):

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

Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/testWASM.cpp
Source/JavaScriptCore/wasm/WASMB3IRGenerator.cpp
Source/JavaScriptCore/wasm/WASMFormat.h
Source/JavaScriptCore/wasm/WASMFunctionParser.h
Source/JavaScriptCore/wasm/WASMModuleParser.cpp
Source/JavaScriptCore/wasm/WASMSections.cpp [deleted file]
Source/JavaScriptCore/wasm/WASMSections.h

index f17ed63..979e0f1 100644 (file)
@@ -854,7 +854,6 @@ set(JavaScriptCore_SOURCES
     wasm/WASMCallingConvention.cpp
     wasm/WASMModuleParser.cpp
     wasm/WASMPlan.cpp
-    wasm/WASMSections.cpp
 
     yarr/RegularExpression.cpp
     yarr/YarrCanonicalizeUCS2.cpp
index cd3bc62..3fed20d 100644 (file)
@@ -1,3 +1,33 @@
+2016-09-19  Keith Miller  <keith_miller@apple.com>
+
+        Update WASM towards 0xc
+        https://bugs.webkit.org/show_bug.cgi?id=162067
+
+        Reviewed by Geoffrey Garen.
+
+        This patch updates some of the core parts of the WASM frontend to the 0xc standard.
+        First, it changes the section names from strings to bytecodes. It also adds support
+        for inline block signatures. This is a change from the old version that used to have
+        each branch indicate the arity. Finally, this patch updates all the tests and deletes
+        a duplicate test.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * testWASM.cpp:
+        (runWASMTests):
+        * wasm/WASMB3IRGenerator.cpp:
+        * wasm/WASMFormat.h:
+        * wasm/WASMFunctionParser.h:
+        (JSC::WASM::FunctionParser<Context>::FunctionParser):
+        (JSC::WASM::FunctionParser<Context>::parseBlock):
+        (JSC::WASM::FunctionParser<Context>::parseExpression):
+        * wasm/WASMModuleParser.cpp:
+        (JSC::WASM::ModuleParser::parse):
+        * wasm/WASMSections.cpp: Removed.
+        (JSC::WASM::Sections::lookup): Deleted.
+        * wasm/WASMSections.h:
+        (JSC::WASM::Sections::validateOrder):
+
 2016-09-19  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         [JSC] Use is_cell_with_type for @isRegExpObject, @isMap, and @isSet
index 2c5ec1c..6fc35b2 100644 (file)
                539EB0811D55608A00C82EF7 /* testWASM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 539EB0711D553DF800C82EF7 /* testWASM.cpp */; };
                539FB8BA1C99DA7C00940FA1 /* JSArrayInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 539FB8B91C99DA7C00940FA1 /* JSArrayInlines.h */; };
                53F40E851D58F9770099A1B6 /* WASMSections.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E841D58F9770099A1B6 /* WASMSections.h */; };
-               53F40E871D58F9D60099A1B6 /* WASMSections.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53F40E861D58F9D60099A1B6 /* WASMSections.cpp */; };
                53F40E8B1D5901BB0099A1B6 /* WASMFunctionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E8A1D5901BB0099A1B6 /* WASMFunctionParser.h */; };
                53F40E8D1D5901F20099A1B6 /* WASMParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E8C1D5901F20099A1B6 /* WASMParser.h */; };
                53F40E8F1D5902820099A1B6 /* WASMB3IRGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53F40E8E1D5902820099A1B6 /* WASMB3IRGenerator.cpp */; };
                539FB8B91C99DA7C00940FA1 /* JSArrayInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSArrayInlines.h; sourceTree = "<group>"; };
                53F256E11B87E28000B4B768 /* JSTypedArrayViewPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArrayViewPrototype.cpp; sourceTree = "<group>"; };
                53F40E841D58F9770099A1B6 /* WASMSections.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMSections.h; sourceTree = "<group>"; };
-               53F40E861D58F9D60099A1B6 /* WASMSections.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WASMSections.cpp; sourceTree = "<group>"; };
                53F40E8A1D5901BB0099A1B6 /* WASMFunctionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMFunctionParser.h; sourceTree = "<group>"; };
                53F40E8C1D5901F20099A1B6 /* WASMParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMParser.h; sourceTree = "<group>"; };
                53F40E8E1D5902820099A1B6 /* WASMB3IRGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WASMB3IRGenerator.cpp; sourceTree = "<group>"; };
                                531374BE1D5CE95000AF7A0B /* WASMPlan.cpp */,
                                531374BC1D5CE67600AF7A0B /* WASMPlan.h */,
                                53F40E8C1D5901F20099A1B6 /* WASMParser.h */,
-                               53F40E861D58F9D60099A1B6 /* WASMSections.cpp */,
                                53F40E841D58F9770099A1B6 /* WASMSections.h */,
                        );
                        path = wasm;
                                0FBE0F7216C1DB030082C5E8 /* DFGCPSRethreadingPhase.cpp in Sources */,
                                A7D89CF517A0B8CC00773AD8 /* DFGCriticalEdgeBreakingPhase.cpp in Sources */,
                                0F6183291C45BF070072450B /* AirCCallingConvention.cpp in Sources */,
-                               53F40E871D58F9D60099A1B6 /* WASMSections.cpp in Sources */,
                                0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */,
                                0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */,
                                0F338E121BF0276C0013C88F /* B3OpaqueByproducts.cpp in Sources */,
index ca40896..d9ed91f 100644 (file)
@@ -243,7 +243,7 @@ static void runWASMTests()
     {
         // Generated from:
         //    (module
-        //     (func "dumb-eq" (param $x i32) (param $y i32) (result i32)
+        //     (func (export "dumb-eq") (param $x i32) (param $y i32) (result i32)
         //      (if (i32.eq (get_local $x) (get_local $y))
         //       (then (br 0))
         //       (else (return (i32.const 1))))
@@ -251,13 +251,11 @@ static void runWASMTests()
         //      )
         //     )
         Vector<uint8_t> vector = {
-            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x87, 0x80, 0x80,
-            0x00, 0x01, 0x40, 0x02, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
-            0x6e, 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x91, 0x80,
-            0x80, 0x00, 0x01, 0x00, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
-            0x68, 0x61, 0x6e, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x97, 0x80, 0x80, 0x00, 0x01, 0x92, 0x80, 0x80,
-            0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x03, 0x10, 0x00, 0x09, 0x01, 0x04, 0x10, 0x01, 0x09,
-            0x01, 0x0f, 0x0f
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8b, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x07, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x65, 0x71, 0x00, 0x00, 0x0a, 0x99,
+            0x80, 0x80, 0x80, 0x00, 0x01, 0x93, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x4d,
+            0x03, 0x00, 0x06, 0x00, 0x04, 0x10, 0x01, 0x09, 0x0f, 0x10, 0x00, 0x09, 0x0f
         };
 
         Plan plan(*vm, vector);
@@ -280,7 +278,7 @@ static void runWASMTests()
     {
         // Generated from:
         //    (module
-        //     (func "dumb-less-than" (param $x i32) (param $y i32) (result i32)
+        //     (func (export "dumb-less-than") (param $x i32) (param $y i32) (result i32)
         //      (loop
         //       (if (i32.eq (get_local $x) (get_local $y))
         //        (then (return (i32.const 0)))
@@ -292,14 +290,13 @@ static void runWASMTests()
         //      )
         //     )
         Vector<uint8_t> vector = {
-            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x87, 0x80, 0x80,
-            0x00, 0x01, 0x40, 0x02, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
-            0x6e, 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x91, 0x80,
-            0x80, 0x00, 0x01, 0x00, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
-            0x68, 0x61, 0x6e, 0x04, 0x63, 0x6f, 0x64, 0x65, 0xaa, 0x80, 0x80, 0x00, 0x01, 0xa5, 0x80, 0x80,
-            0x00, 0x00, 0x02, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x03, 0x10, 0x00, 0x09, 0x01, 0x04, 0x14, 0x00,
-            0x10, 0x00, 0x4d, 0x03, 0x10, 0x01, 0x09, 0x01, 0x0f, 0x0f, 0x14, 0x00, 0x10, 0x01, 0x41, 0x15,
-            0x00, 0x06, 0x00, 0x00, 0x0f, 0x0f
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x92, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
+            0x68, 0x61, 0x6e, 0x00, 0x00, 0x0a, 0xac, 0x80, 0x80, 0x80, 0x00, 0x01, 0xa6, 0x80, 0x80, 0x80,
+            0x00, 0x00, 0x02, 0x00, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x03, 0x00, 0x10, 0x00, 0x09, 0x04, 0x14,
+            0x00, 0x10, 0x00, 0x4d, 0x03, 0x00, 0x10, 0x01, 0x09, 0x0f, 0x0f, 0x14, 0x00, 0x10, 0x01, 0x41,
+            0x15, 0x00, 0x06, 0x00, 0x0f, 0x00, 0x0f
         };
 
         Plan plan(*vm, vector);
@@ -319,68 +316,14 @@ static void runWASMTests()
         CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(6) }), 0);
     }
 
-    {
-        // Generated from:
-        //    (module
-        //     (func "dumb-less-than" (param $x i32) (param $y i32) (result i32)
-        //      (loop
-        //       (block
-        //        (block
-        //         (br_if 0 (i32.eq (get_local $x) (i32.const 0)))
-        //         (br 1)
-        //         )
-        //        (return (i32.const 1))
-        //        )
-        //       (block
-        //        (block
-        //         (br_if 0 (i32.eq (get_local $x) (get_local $y)))
-        //         (br 1)
-        //         )
-        //        (return (i32.const 0))
-        //        )
-        //       (set_local $x (i32.sub (get_local $x) (i32.const 1)))
-        //       (br 0)
-        //       )
-        //      )
-        //     )
-        Vector<uint8_t> vector = {
-            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x87, 0x80, 0x80,
-            0x00, 0x01, 0x40, 0x02, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
-            0x6e, 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x91, 0x80,
-            0x80, 0x00, 0x01, 0x00, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
-            0x68, 0x61, 0x6e, 0x04, 0x63, 0x6f, 0x64, 0x65, 0xb9, 0x80, 0x80, 0x00, 0x01, 0xb4, 0x80, 0x80,
-            0x00, 0x00, 0x02, 0x01, 0x01, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x07, 0x00, 0x00, 0x06, 0x00, 0x01,
-            0x0f, 0x10, 0x00, 0x09, 0x01, 0x0f, 0x01, 0x01, 0x14, 0x00, 0x10, 0x00, 0x4d, 0x07, 0x00, 0x00,
-            0x06, 0x00, 0x01, 0x0f, 0x10, 0x01, 0x09, 0x01, 0x0f, 0x14, 0x00, 0x10, 0x01, 0x41, 0x15, 0x00,
-            0x06, 0x00, 0x00, 0x0f, 0x0f
-        };
-
-        Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
-            dataLogLn("Module failed to compile correctly.");
-            CRASH();
-        }
-
-        // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(2) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(2) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(6) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(6) }), 0);
-    }
 
     {
-        // Generated from: (module (func "return-i32" (result i32) (return (i32.const 5))) )
+        // Generated from: (module (func (export "return-i32") (result i32) (return (i32.const 5))) )
         Vector<uint8_t> vector = {
-            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x85, 0x80, 0x80,
-            0x00, 0x01, 0x40, 0x00, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x82,
-            0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x8d, 0x80, 0x80, 0x00,
-            0x01, 0x00, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x04, 0x63, 0x6f,
-            0x64, 0x65, 0x8b, 0x80, 0x80, 0x00, 0x01, 0x86, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x09, 0x01,
-            0x0f
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x00, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8e, 0x80, 0x80, 0x80,
+            0x00, 0x01, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x00, 0x00, 0x0a,
+            0x8b, 0x80, 0x80, 0x80, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x09, 0x0f
         };
 
         Plan plan(*vm, vector);
@@ -395,14 +338,13 @@ static void runWASMTests()
 
 
     {
-        // Generated from: (module (func "return-i32" (result i32) (return (i32.add (i32.const 5) (i32.const 6)))) )
+        // Generated from: (module (func (export "return-i32") (result i32) (return (i32.add (i32.const 5) (i32.const 6)))) )
         Vector<uint8_t> vector = {
-            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x85, 0x80, 0x80,
-            0x00, 0x01, 0x40, 0x00, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x82,
-            0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x8d, 0x80, 0x80, 0x00,
-            0x01, 0x00, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x04, 0x63, 0x6f,
-            0x64, 0x65, 0x8e, 0x80, 0x80, 0x00, 0x01, 0x89, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x10, 0x06,
-            0x40, 0x09, 0x01, 0x0f
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x00, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8e, 0x80, 0x80, 0x80,
+            0x00, 0x01, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x00, 0x00, 0x0a,
+            0x8e, 0x80, 0x80, 0x80, 0x00, 0x01, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x10, 0x06,
+            0x40, 0x09, 0x0f
         };
 
         Plan plan(*vm, vector);
@@ -414,16 +356,15 @@ static void runWASMTests()
         // Test this doesn't crash.
         CHECK_EQ(invoke<int>(*plan.result[0], { }), 11);
     }
-    
+
     {
-        // Generated from: (module (func "return-i32" (result i32) (return (i32.add (i32.add (i32.const 5) (i32.const 3)) (i32.const 3)))) )
+        // Generated from: (module (func (export "return-i32") (result i32) (return (i32.add (i32.add (i32.const 5) (i32.const 3)) (i32.const 3)))) )
         Vector<uint8_t> vector = {
-            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x85, 0x80, 0x80,
-            0x00, 0x01, 0x40, 0x00, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x82,
-            0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x8d, 0x80, 0x80, 0x00,
-            0x01, 0x00, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x04, 0x63, 0x6f,
-            0x64, 0x65, 0x91, 0x80, 0x80, 0x00, 0x01, 0x8c, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x10, 0x03,
-            0x40, 0x10, 0x03, 0x40, 0x09, 0x01, 0x0f
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x00, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8e, 0x80, 0x80, 0x80,
+            0x00, 0x01, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x00, 0x00, 0x0a,
+            0x91, 0x80, 0x80, 0x80, 0x00, 0x01, 0x8b, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x10, 0x03,
+            0x40, 0x10, 0x03, 0x40, 0x09, 0x0f
         };
 
         Plan plan(*vm, vector);
@@ -437,14 +378,13 @@ static void runWASMTests()
     }
 
     {
-        // Generated from: (module (func "return-i32" (result i32) (block (return (i32.add (i32.add (i32.const 5) (i32.const 3)) (i32.const 3))))) )
+        // Generated from: (module (func (export "return-i32") (result i32) (block (return (i32.add (i32.add (i32.const 5) (i32.const 3)) (i32.const 3)))) (unreachable)) )
         Vector<uint8_t> vector = {
-            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x85, 0x80, 0x80,
-            0x00, 0x01, 0x40, 0x00, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x82,
-            0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x8d, 0x80, 0x80, 0x00,
-            0x01, 0x00, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x04, 0x63, 0x6f,
-            0x64, 0x65, 0x93, 0x80, 0x80, 0x00, 0x01, 0x8e, 0x80, 0x80, 0x00, 0x00, 0x01, 0x10, 0x05, 0x10,
-            0x03, 0x40, 0x10, 0x03, 0x40, 0x09, 0x01, 0x0f, 0x0f
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x00, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8e, 0x80, 0x80, 0x80,
+            0x00, 0x01, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x00, 0x00, 0x0a,
+            0x95, 0x80, 0x80, 0x80, 0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x01, 0x00, 0x10, 0x05,
+            0x10, 0x03, 0x40, 0x10, 0x03, 0x40, 0x09, 0x0f, 0x00, 0x0f
         };
 
         Plan plan(*vm, vector);
@@ -458,12 +398,12 @@ static void runWASMTests()
     }
 
     {
-        // Generated from: (module (func $add (param $x i32) (param $y i32) (result i32) (return (i32.add (get_local $x) (get_local $y)))) )
+        // Generated from: (module (func (export "add") (param $x i32) (param $y i32) (result i32) (return (i32.add (get_local $x) (get_local $y)))) )
         Vector<uint8_t> vector = {
-            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x87, 0x80, 0x80,
-            0x00, 0x01, 0x40, 0x02, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
-            0x6e, 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x8e, 0x80, 0x80, 0x00,
-            0x01, 0x89, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x40, 0x09, 0x01, 0x0f
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x87, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x8e, 0x80, 0x80, 0x80, 0x00,
+            0x01, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x40, 0x09, 0x0f
         };
 
         Plan plan(*vm, vector);
@@ -482,18 +422,17 @@ static void runWASMTests()
     {
         // Generated from:
         //    (module
-        //     (func "locals" (param $x i32) (result i32) (local $num i32)
+        //     (func (export "locals") (param $x i32) (result i32) (local $num i32)
         //      (set_local $num (get_local $x))
         //      (return (get_local $num))
         //      )
         //     )
         Vector<uint8_t> vector = {
-            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x86, 0x80, 0x80,
-            0x00, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
-            0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x89, 0x80, 0x80,
-            0x00, 0x01, 0x00, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x91,
-            0x80, 0x80, 0x00, 0x01, 0x8c, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x14, 0x00, 0x15, 0x01, 0x14,
-            0x01, 0x09, 0x01, 0x0f
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8a, 0x80, 0x80,
+            0x80, 0x00, 0x01, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x00, 0x00, 0x0a, 0x91, 0x80, 0x80,
+            0x80, 0x00, 0x01, 0x8b, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x14, 0x00, 0x15, 0x01, 0x14,
+            0x01, 0x09, 0x0f
         };
 
         Plan plan(*vm, vector);
@@ -510,33 +449,26 @@ static void runWASMTests()
     {
         // Generated from:
         //    (module
-        //     (func "dumb-mult" (param $x i32) (param $y i32) (result i32) (local $total i32) (local $i i32) (local $j i32)
-        //      (set_local $total (i32.const 0))
-        //      (set_local $i (i32.const 0))
-        //      (block
-        //       (loop
-        //        (br_if 1 (i32.eq (get_local $i) (get_local $x)))
-        //        (set_local $j (i32.const 0))
-        //        (set_local $i (i32.add (get_local $i) (i32.const 1)))
-        //        (loop
-        //         (br_if 1 (i32.eq (get_local $j) (get_local $y)))
-        //         (set_local $total (i32.add (get_local $total) (i32.const 1)))
-        //         (set_local $j (i32.add (get_local $j) (i32.const 1)))
-        //         (br 0)
-        //         )
+        //     (func (export "sum") (param $x i32) (result i32) (local $y i32)
+        //      (set_local $y (i32.const 0))
+        //      (loop
+        //       (block
+        //        (br_if 0 (i32.eq (get_local $x) (i32.const 0)))
+        //        (set_local $y (i32.add (get_local $x) (get_local $y)))
+        //        (set_local $x (i32.sub (get_local $x) (i32.const 1)))
+        //        (br 1)
         //        )
         //       )
-        //      (return (get_local $total))
+        //      (return (get_local $y))
         //      )
         //     )
         Vector<uint8_t> vector = {
-            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x86, 0x80, 0x80,
-            0x00, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
-            0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x86, 0x80, 0x80,
-            0x00, 0x01, 0x00, 0x03, 0x73, 0x75, 0x6d, 0x04, 0x63, 0x6f, 0x64, 0x65, 0xae, 0x80, 0x80, 0x00,
-            0x01, 0xa9, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x01, 0x02, 0x01, 0x14, 0x00,
-            0x10, 0x00, 0x4d, 0x07, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x40, 0x15, 0x01, 0x14, 0x00, 0x10,
-            0x01, 0x41, 0x15, 0x00, 0x06, 0x00, 0x01, 0x0f, 0x0f, 0x14, 0x01, 0x09, 0x01, 0x0f
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x87, 0x80, 0x80,
+            0x80, 0x00, 0x01, 0x03, 0x73, 0x75, 0x6d, 0x00, 0x00, 0x0a, 0xae, 0x80, 0x80, 0x80, 0x00, 0x01,
+            0xa8, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x01, 0x02, 0x00, 0x01, 0x00,
+            0x14, 0x00, 0x10, 0x00, 0x4d, 0x07, 0x00, 0x14, 0x00, 0x14, 0x01, 0x40, 0x15, 0x01, 0x14, 0x00,
+            0x10, 0x01, 0x41, 0x15, 0x00, 0x06, 0x01, 0x0f, 0x0f, 0x14, 0x01, 0x09, 0x0f
         };
 
         Plan plan(*vm, vector);
@@ -555,7 +487,7 @@ static void runWASMTests()
     {
         // Generated from:
         //    (module
-        //     (func "dumb-mult" (param $x i32) (param $y i32) (result i32) (local $total i32) (local $i i32) (local $j i32)
+        //     (func (export "dumb-mult") (param $x i32) (param $y i32) (result i32) (local $total i32) (local $i i32) (local $j i32)
         //      (set_local $total (i32.const 0))
         //      (set_local $i (i32.const 0))
         //      (block (loop
@@ -573,15 +505,14 @@ static void runWASMTests()
         //      )
         //     )
         Vector<uint8_t> vector = {
-            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x87, 0x80, 0x80,
-            0x00, 0x01, 0x40, 0x02, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
-            0x6e, 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x8c, 0x80,
-            0x80, 0x00, 0x01, 0x00, 0x09, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6d, 0x75, 0x6c, 0x74, 0x04, 0x63,
-            0x6f, 0x64, 0x65, 0xc7, 0x80, 0x80, 0x00, 0x01, 0xc2, 0x80, 0x80, 0x00, 0x01, 0x03, 0x01, 0x10,
-            0x00, 0x15, 0x02, 0x10, 0x00, 0x15, 0x03, 0x01, 0x02, 0x14, 0x03, 0x14, 0x00, 0x4d, 0x07, 0x00,
-            0x01, 0x10, 0x00, 0x15, 0x04, 0x14, 0x03, 0x10, 0x01, 0x40, 0x15, 0x03, 0x02, 0x14, 0x04, 0x14,
-            0x01, 0x4d, 0x07, 0x00, 0x01, 0x14, 0x02, 0x10, 0x01, 0x40, 0x15, 0x02, 0x14, 0x04, 0x10, 0x01,
-            0x40, 0x15, 0x04, 0x06, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x14, 0x02, 0x09, 0x01, 0x0f
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8d, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x09, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6d, 0x75, 0x6c, 0x74, 0x00, 0x00,
+            0x0a, 0xc7, 0x80, 0x80, 0x80, 0x00, 0x01, 0xc1, 0x80, 0x80, 0x80, 0x00, 0x01, 0x03, 0x01, 0x10,
+            0x00, 0x15, 0x02, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00, 0x02, 0x00, 0x14, 0x03, 0x14, 0x00, 0x4d,
+            0x07, 0x01, 0x10, 0x00, 0x15, 0x04, 0x14, 0x03, 0x10, 0x01, 0x40, 0x15, 0x03, 0x02, 0x00, 0x14,
+            0x04, 0x14, 0x01, 0x4d, 0x07, 0x01, 0x14, 0x02, 0x10, 0x01, 0x40, 0x15, 0x02, 0x14, 0x04, 0x10,
+            0x01, 0x40, 0x15, 0x04, 0x06, 0x00, 0x0f, 0x0f, 0x0f, 0x14, 0x02, 0x09, 0x0f
         };
 
         Plan plan(*vm, vector);
@@ -608,33 +539,33 @@ static void runWASMTests()
         //      (loop
         //       (block
         //        (block
-        //         (br_if 0 (i32.eq (get_local $x) (i32.const 0)))
+        //         (br_if 0 (i32.eq (get_local $x) (get_local $y)))
         //         (br 1)
         //         )
-        //        (return (i32.const 1))
+        //        (return (i32.const 0))
         //        )
         //       (block
         //        (block
-        //         (br_if 0 (i32.eq (get_local $x) (get_local $y)))
+        //         (br_if 0 (i32.eq (get_local $x) (i32.const 0)))
         //         (br 1)
         //         )
-        //        (return (i32.const 0))
+        //        (return (i32.const 1))
         //        )
         //       (set_local $x (i32.sub (get_local $x) (i32.const 1)))
         //       (br 0)
         //       )
+        //       (unreachable)
         //      )
         //     )
         Vector<uint8_t> vector = {
-            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x87, 0x80, 0x80,
-            0x00, 0x01, 0x40, 0x02, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
-            0x6e, 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x91, 0x80,
-            0x80, 0x00, 0x01, 0x00, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
-            0x68, 0x61, 0x6e, 0x04, 0x63, 0x6f, 0x64, 0x65, 0xb9, 0x80, 0x80, 0x00, 0x01, 0xb4, 0x80, 0x80,
-            0x00, 0x00, 0x02, 0x01, 0x01, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x07, 0x00, 0x00, 0x06, 0x00, 0x01,
-            0x0f, 0x10, 0x00, 0x09, 0x01, 0x0f, 0x01, 0x01, 0x14, 0x00, 0x10, 0x00, 0x4d, 0x07, 0x00, 0x00,
-            0x06, 0x00, 0x01, 0x0f, 0x10, 0x01, 0x09, 0x01, 0x0f, 0x14, 0x00, 0x10, 0x01, 0x41, 0x15, 0x00,
-            0x06, 0x00, 0x00, 0x0f, 0x0f
+            0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
+            0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x92, 0x80,
+            0x80, 0x80, 0x00, 0x01, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
+            0x68, 0x61, 0x6e, 0x00, 0x00, 0x0a, 0xb9, 0x80, 0x80, 0x80, 0x00, 0x01, 0xb3, 0x80, 0x80, 0x80,
+            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x07, 0x00, 0x06,
+            0x01, 0x0f, 0x10, 0x00, 0x09, 0x0f, 0x01, 0x00, 0x01, 0x00, 0x14, 0x00, 0x10, 0x00, 0x4d, 0x07,
+            0x00, 0x06, 0x01, 0x0f, 0x10, 0x01, 0x09, 0x0f, 0x14, 0x00, 0x10, 0x01, 0x41, 0x15, 0x00, 0x06,
+            0x00, 0x0f, 0x00, 0x0f
         };
 
         Plan plan(*vm, vector);
index fb0af1b..0b71c1a 100644 (file)
@@ -105,11 +105,12 @@ private:
 
 public:
     struct ControlData {
-        ControlData(Optional<Vector<Variable*>>&& stack, BasicBlock* special = nullptr, BasicBlock* continuation = nullptr)
+        ControlData(Procedure& proc, Type signature, BasicBlock* special = nullptr, BasicBlock* continuation = nullptr)
             : continuation(continuation)
             , special(special)
-            , stack(stack)
         {
+            if (signature != Void)
+                result.append(proc.addVariable(toB3Type(signature)));
         }
 
         void dump(PrintStream& out) const
@@ -143,7 +144,7 @@ public:
 
         BasicBlock* targetBlockForBranch(Procedure& proc)
         {
-            if (special)
+            if (type() == BlockType::Loop)
                 return special;
             return continuation.get(proc);
         }
@@ -155,11 +156,13 @@ public:
         // that example, if we eagerly allocate a BasicBlock for the continuation it will never be reachable.
         LazyBlock continuation;
         BasicBlock* special;
-        Optional<Vector<Variable*>> stack;
+        Vector<Variable*, 1> result;
     };
 
     typedef Value* ExpressionType;
     typedef ControlData ControlType;
+    typedef Vector<ExpressionType, 1> ExpressionList;
+    typedef Vector<Variable*, 1> ResultList;
     static constexpr ExpressionType emptyExpression = nullptr;
 
     B3IRGenerator(Procedure&);
@@ -174,23 +177,22 @@ public:
     bool WARN_UNUSED_RETURN binaryOp(BinaryOpType, ExpressionType left, ExpressionType right, ExpressionType& result);
     bool WARN_UNUSED_RETURN unaryOp(UnaryOpType, ExpressionType arg, ExpressionType& result);
 
-    ControlData WARN_UNUSED_RETURN addBlock();
-    ControlData WARN_UNUSED_RETURN addLoop();
-    ControlData WARN_UNUSED_RETURN addIf(ExpressionType condition);
+    ControlData WARN_UNUSED_RETURN addBlock(Type signature);
+    ControlData WARN_UNUSED_RETURN addLoop(Type signature);
+    ControlData WARN_UNUSED_RETURN addIf(ExpressionType condition, Type signature);
     bool WARN_UNUSED_RETURN addElse(ControlData&);
 
-    bool WARN_UNUSED_RETURN addReturn(const Vector<ExpressionType, 1>& returnValues);
-    bool WARN_UNUSED_RETURN addBranch(ControlData&, ExpressionType condition, const Vector<ExpressionType, 1>& returnValues);
-    bool WARN_UNUSED_RETURN endBlock(ControlData&, Vector<ExpressionType, 1>& expressionStack);
+    bool WARN_UNUSED_RETURN addReturn(const ExpressionList& returnValues);
+    bool WARN_UNUSED_RETURN addBranch(ControlData&, ExpressionType condition, const ExpressionList& returnValues);
+    bool WARN_UNUSED_RETURN endBlock(ControlData&, ExpressionList& expressionStack);
 
     bool isContinuationReachable(ControlData&);
 
-    void dump(const Vector<ControlType>& controlStack, const Vector<ExpressionType, 1>& expressionStack);
+    void dump(const Vector<ControlType>& controlStack, const ExpressionList& expressionStack);
 
 private:
     void unify(Variable* target, const ExpressionType source);
-    Vector<Variable*> initializeIncommingTypes(BasicBlock*, const Vector<ExpressionType, 1>&);
-    void unifyValuesWithBlock(const Vector<ExpressionType, 1>& resultStack, Optional<Vector<Variable*>>& stack, BasicBlock* target);
+    void unifyValuesWithBlock(const ExpressionList& resultStack, ResultList& stack);
 
     Procedure& m_proc;
     BasicBlock* m_currentBlock;
@@ -265,21 +267,21 @@ B3IRGenerator::ExpressionType B3IRGenerator::addConstant(Type type, uint64_t val
     }
 }
 
-B3IRGenerator::ControlData B3IRGenerator::addBlock()
+B3IRGenerator::ControlData B3IRGenerator::addBlock(Type signature)
 {
-    return ControlData(Nullopt);
+    return ControlData(m_proc, signature);
 }
 
-B3IRGenerator::ControlData B3IRGenerator::addLoop()
+B3IRGenerator::ControlData B3IRGenerator::addLoop(Type signature)
 {
     BasicBlock* body = m_proc.addBlock();
     m_currentBlock->appendNewControlValue(m_proc, Jump, Origin(), body);
     body->addPredecessor(m_currentBlock);
     m_currentBlock = body;
-    return ControlData(Vector<Variable*>(), body);
+    return ControlData(m_proc, signature, body);
 }
 
-B3IRGenerator::ControlData B3IRGenerator::addIf(ExpressionType condition)
+B3IRGenerator::ControlData B3IRGenerator::addIf(ExpressionType condition, Type signature)
 {
     // FIXME: This needs to do some kind of stack passing.
 
@@ -293,7 +295,7 @@ B3IRGenerator::ControlData B3IRGenerator::addIf(ExpressionType condition)
     notTaken->addPredecessor(m_currentBlock);
 
     m_currentBlock = taken;
-    return ControlData(Nullopt, notTaken, continuation);
+    return ControlData(m_proc, signature, notTaken, continuation);
 }
 
 bool B3IRGenerator::addElse(ControlData& data)
@@ -306,7 +308,7 @@ bool B3IRGenerator::addElse(ControlData& data)
     return true;
 }
 
-bool B3IRGenerator::addReturn(const Vector<ExpressionType, 1>& returnValues)
+bool B3IRGenerator::addReturn(const ExpressionList& returnValues)
 {
     ASSERT(returnValues.size() <= 1);
     if (returnValues.size())
@@ -316,10 +318,10 @@ bool B3IRGenerator::addReturn(const Vector<ExpressionType, 1>& returnValues)
     return true;
 }
 
-bool B3IRGenerator::addBranch(ControlData& data, ExpressionType condition, const Vector<ExpressionType, 1>& returnValues)
+bool B3IRGenerator::addBranch(ControlData& data, ExpressionType condition, const ExpressionList& returnValues)
 {
     BasicBlock* target = data.targetBlockForBranch(m_proc);
-    unifyValuesWithBlock(returnValues, data.stack, target);
+    unifyValuesWithBlock(returnValues, data.result);
     if (condition) {
         BasicBlock* continuation = m_proc.addBlock();
         m_currentBlock->appendNew<Value>(m_proc, B3::Branch, Origin(), condition);
@@ -335,7 +337,7 @@ bool B3IRGenerator::addBranch(ControlData& data, ExpressionType condition, const
     return true;
 }
 
-bool B3IRGenerator::endBlock(ControlData& data, Vector<ExpressionType, 1>& expressionStack)
+bool B3IRGenerator::endBlock(ControlData& data, ExpressionList& expressionStack)
 {
     if (!data.continuation)
         return true;
@@ -349,7 +351,7 @@ bool B3IRGenerator::endBlock(ControlData& data, Vector<ExpressionType, 1>& expre
         continuation->addPredecessor(data.special);
     }
 
-    unifyValuesWithBlock(expressionStack, data.stack, continuation);
+    unifyValuesWithBlock(expressionStack, data.result);
     m_currentBlock->appendNewControlValue(m_proc, Jump, Origin(), continuation);
     continuation->addPredecessor(m_currentBlock);
     m_currentBlock = continuation;
@@ -377,34 +379,15 @@ void B3IRGenerator::unify(Variable* variable, ExpressionType source)
     m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), variable, source);
 }
 
-Vector<Variable*> B3IRGenerator::initializeIncommingTypes(BasicBlock* block, const Vector<ExpressionType, 1>& source)
-{
-    Vector<Variable*> result;
-    result.reserveInitialCapacity(source.size());
-    for (ExpressionType expr : source) {
-        ASSERT(expr->type() != B3::Void);
-        Variable* var = m_proc.addVariable(expr->type());
-        result.append(var);
-        block->appendNew<VariableValue>(m_proc, B3::Get, Origin(), var);
-    }
-
-    return result;
-}
-
-void B3IRGenerator::unifyValuesWithBlock(const Vector<ExpressionType, 1>& resultStack, Optional<Vector<Variable*>>& stack, BasicBlock* target)
+void B3IRGenerator::unifyValuesWithBlock(const ExpressionList& resultStack, ResultList& result)
 {
-    if (!stack) {
-        stack = initializeIncommingTypes(target, resultStack);
-        return;
-    }
-
-    ASSERT(stack.value().size() == resultStack.size());
+    ASSERT(result.size() >= resultStack.size());
 
     for (size_t i = 0; i < resultStack.size(); ++i)
-        unify(stack.value()[i], resultStack[i]);
+        unify(result[i], resultStack[i]);
 }
 
-void B3IRGenerator::dump(const Vector<ControlType>& controlStack, const Vector<ExpressionType, 1>& expressionStack)
+void B3IRGenerator::dump(const Vector<ControlType>& controlStack, const ExpressionList& expressionStack)
 {
     dataLogLn("Processing Graph:");
     dataLog(m_proc);
index 9c96b5d..7a04137 100644 (file)
@@ -55,12 +55,12 @@ class JSFunction;
 namespace WASM {
 
 enum Type : uint8_t {
-    I32 = 1,
+    Void,
+    I32,
     I64,
     F32,
     F64,
     LastValueType = F64,
-    Void
 };
 
 static_assert(I32 == 1, "WASM needs I32 to have the value 1");
index 8f63fce..ab82be9 100644 (file)
@@ -59,6 +59,7 @@ private:
     Context& m_context;
     Vector<ExpressionType, 1> m_expressionStack;
     Vector<ControlType> m_controlStack;
+    const Signature& m_signature;
     unsigned m_unreachableBlocks { 0 };
 };
 
@@ -66,8 +67,11 @@ template<typename Context>
 FunctionParser<Context>::FunctionParser(Context& context, const Vector<uint8_t>& sourceBuffer, const FunctionInformation& info)
     : Parser(sourceBuffer, info.start, info.end)
     , m_context(context)
+    , m_signature(*info.signature)
 {
-    m_context.addArguments(info.signature->arguments);
+    if (verbose)
+        dataLogLn("Parsing function starting at: ", info.start, " ending at: ", info.end);
+    m_context.addArguments(m_signature.arguments);
 }
 
 template<typename Context>
@@ -101,7 +105,7 @@ bool FunctionParser<Context>::parseBlock()
             return false;
 
         if (verbose) {
-            dataLogLn("processing op (", m_unreachableBlocks, "): ",  RawPointer(reinterpret_cast<void*>(op)));
+            dataLogLn("processing op (", m_unreachableBlocks, "): ",  RawPointer(reinterpret_cast<void*>(op)), " at offset: ", RawPointer(reinterpret_cast<void*>(m_offset)));
             m_context.dump(m_controlStack, m_expressionStack);
         }
 
@@ -179,18 +183,30 @@ bool FunctionParser<Context>::parseExpression(OpType op)
     }
 
     case OpType::Block: {
-        m_controlStack.append(m_context.addBlock());
+        Type inlineSignature;
+        if (!parseValueType(inlineSignature))
+            return false;
+
+        m_controlStack.append(m_context.addBlock(inlineSignature));
         return true;
     }
 
     case OpType::Loop: {
-        m_controlStack.append(m_context.addLoop());
+        Type inlineSignature;
+        if (!parseValueType(inlineSignature))
+            return false;
+
+        m_controlStack.append(m_context.addLoop(inlineSignature));
         return true;
     }
 
     case OpType::If: {
+        Type inlineSignature;
+        if (!parseValueType(inlineSignature))
+            return false;
+
         ExpressionType condition = m_expressionStack.takeLast();
-        m_controlStack.append(m_context.addIf(condition));
+        m_controlStack.append(m_context.addIf(condition, inlineSignature));
         return true;
     }
 
@@ -200,12 +216,8 @@ bool FunctionParser<Context>::parseExpression(OpType op)
 
     case OpType::Branch:
     case OpType::BranchIf: {
-        uint32_t arity;
-        if (!parseVarUInt32(arity) || arity > m_expressionStack.size())
-            return false;
-
         uint32_t target;
-        if (!parseVarUInt32(target))
+        if (!parseVarUInt32(target) || target >= m_controlStack.size())
             return false;
 
         ExpressionType condition = Context::emptyExpression;
@@ -214,23 +226,14 @@ bool FunctionParser<Context>::parseExpression(OpType op)
         else
             m_unreachableBlocks = 1;
 
-        Vector<ExpressionType, 1> values(arity);
-        for (unsigned i = arity; i; i--)
-            values[i-1] = m_expressionStack.takeLast();
-
-        if (target >= m_controlStack.size())
-            return false;
         ControlType& data = m_controlStack[m_controlStack.size() - 1 - target];
 
-        return m_context.addBranch(data, condition, values);
+        return m_context.addBranch(data, condition, m_expressionStack);
     }
 
     case OpType::Return: {
-        uint8_t returnCount;
-        if (!parseVarUInt1(returnCount))
-            return false;
         Vector<ExpressionType, 1> returnValues;
-        if (returnCount)
+        if (m_signature.returnType != Void)
             returnValues.append(m_expressionStack.takeLast());
 
         m_unreachableBlocks = 1;
index f0c0425..5e053a5 100644 (file)
@@ -61,18 +61,33 @@ bool ModuleParser::parse()
     while (m_offset < m_sourceLength) {
         if (verbose)
             dataLogLn("Starting to parse next section at offset: ", m_offset);
-        uint32_t sectionNameLength;
-        if (!parseVarUInt32(sectionNameLength))
-            return false;
 
-        // Make sure we can read up to the section's size.
-        if (m_offset + sectionNameLength + maxLEBByteLength >= m_sourceLength)
+        Sections::Section section = Sections::Unknown;
+        uint8_t sectionByte;
+        if (!parseUInt7(sectionByte))
             return false;
 
-        Sections::Section section = Sections::lookup(m_source.data() + m_offset, sectionNameLength);
+        if (sectionByte) {
+            if (sectionByte >= Sections::Unknown)
+                section = Sections::Unknown;
+            else
+                section = static_cast<Sections::Section>(sectionByte);
+        } else {
+            uint32_t sectionNameLength;
+            if (!parseVarUInt32(sectionNameLength))
+                return false;
+
+            // Make sure we can read up to the section's size.
+            if (m_offset + sectionNameLength + maxLEBByteLength >= m_sourceLength)
+                return false;
+
+            // We don't support any custom sections yet.
+
+            m_offset += sectionNameLength;
+        }
+
         if (!Sections::validateOrder(previousSection, section))
             return false;
-        m_offset += sectionNameLength;
 
         uint32_t sectionLength;
         if (!parseVarUInt32(sectionLength))
@@ -81,9 +96,6 @@ bool ModuleParser::parse()
         unsigned end = m_offset + sectionLength;
 
         switch (section) {
-        case Sections::End:
-            return true;
-
         case Sections::FunctionTypes: {
             if (verbose)
                 dataLogLn("Parsing types.");
@@ -108,7 +120,9 @@ bool ModuleParser::parse()
             break;
         }
 
-        case Sections::Unknown: {
+        case Sections::Unknown:
+        // FIXME: Delete this when we support all the sections.
+        default: {
             if (verbose)
                 dataLogLn("Unknown section, skipping.");
             m_offset += sectionLength;
diff --git a/Source/JavaScriptCore/wasm/WASMSections.cpp b/Source/JavaScriptCore/wasm/WASMSections.cpp
deleted file mode 100644 (file)
index 8a2208c..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "WASMSections.h"
-
-#if ENABLE(WEBASSEMBLY)
-
-#include <wtf/DataLog.h>
-#include <wtf/text/WTFString.h>
-
-namespace JSC { namespace WASM {
-
-struct SectionData {
-    unsigned length;
-    const char* name;
-};
-
-static const bool verbose = false;
-
-static const unsigned sectionDataLength = static_cast<unsigned>(Sections::Unknown);
-static const SectionData sectionData[sectionDataLength] {
-#define CREATE_SECTION_DATA(name, str) { sizeof(str) - 1, str },
-    FOR_EACH_WASM_SECTION_TYPE(CREATE_SECTION_DATA)
-#undef CREATE_SECTION_DATA
-};
-
-Sections::Section Sections::lookup(const uint8_t* name, unsigned length)
-{
-    if (verbose)
-        dataLogLn("Decoding section with name: ", String(name, length));
-    for (unsigned i = 0; i < sectionDataLength; ++i) {
-        if (sectionData[i].length != length)
-            continue;
-        if (!memcmp(name, sectionData[i].name, length))
-            return static_cast<Sections::Section>(i);
-    }
-    return Sections::Unknown;
-}
-
-} } // namespace JSC::WASM
-
-#endif // ENABLE(WEBASSEMBLY)
index bd0ed95..53e9356 100644 (file)
 
 namespace JSC { namespace WASM {
 
-// These should be in the order that we expect them to be in the binary.
-#define FOR_EACH_WASM_SECTION_TYPE(macro) \
-    macro(FunctionTypes, "type") \
-    macro(Signatures, "function") \
-    macro(Definitions, "code") \
-    macro(End, "end")
-
 struct Sections {
-    enum Section {
-#define CREATE_SECTION_ENUM(name, str) name,
-        FOR_EACH_WASM_SECTION_TYPE(CREATE_SECTION_ENUM)
-#undef CREATE_SECTION_ENUM
+    enum Section : uint8_t {
+        FunctionTypes = 1,
+        Signatures = 3,
+        Definitions = 10,
         Unknown
     };
-    static Section lookup(const uint8_t*, unsigned);
     static bool validateOrder(Section previous, Section next)
     {
-        // This allows unknown sections after End, which I doubt will ever be supported but
-        // there is no reason to potentially break backwards compatability.
         if (previous == Unknown)
             return true;
         return previous < next;