Title: [210090] trunk
Revision
210090
Author
[email protected]
Date
2016-12-21 17:06:20 -0800 (Wed, 21 Dec 2016)

Log Message

WebAssembly: Allow br, br_if, and br_table to act as a return
https://bugs.webkit.org/show_bug.cgi?id=166393

Reviewed by Saam Barati.

JSTests:

Add tests for breaks acting as returns and fix tests that
validate error messages.

* wasm/function-tests/br-as-return.js: Added.
* wasm/function-tests/br-if-as-return.js: Added.
* wasm/function-tests/br-table-as-return.js: Added.
* wasm/function-tests/if-no-else-non-void.js:
* wasm/function-tests/struct.js: Added.
* wasm/js-api/global-error.js:
(assert.throws):
* wasm/js-api/table.js:
(assert.throws):

Source/_javascript_Core:

This patch allows br, br_if, and br_table to treat branching to
the size of the control stack to act as a return. This change was
made by adding a new block type to the wasm function parser,
TopLevel. Adding this new block eliminates a lot of the special
case code we had in the parser previously. The only special case
we need is when the end opcode is parsed from the top level.  The
B3 IR generator needs to automatically emit a return at that
point.

Also, this patch adds the function number to validation errors
in the function parser. The current error message is not helpful
otherwise.

* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::ControlData::dump):
(JSC::Wasm::B3IRGenerator::addTopLevel):
* wasm/WasmFunctionParser.h:
* wasm/WasmPlan.cpp:
(JSC::Wasm::Plan::parseAndValidateModule):
(JSC::Wasm::Plan::run):
* wasm/WasmValidate.cpp:
(JSC::Wasm::Validate::ControlData::dump):
(JSC::Wasm::Validate::Validate):
(JSC::Wasm::Validate::addTopLevel):
(JSC::Wasm::validateFunction):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (210089 => 210090)


--- trunk/JSTests/ChangeLog	2016-12-22 00:53:25 UTC (rev 210089)
+++ trunk/JSTests/ChangeLog	2016-12-22 01:06:20 UTC (rev 210090)
@@ -1,3 +1,23 @@
+2016-12-21  Keith Miller  <[email protected]>
+
+        WebAssembly: Allow br, br_if, and br_table to act as a return
+        https://bugs.webkit.org/show_bug.cgi?id=166393
+
+        Reviewed by Saam Barati.
+
+        Add tests for breaks acting as returns and fix tests that
+        validate error messages.
+
+        * wasm/function-tests/br-as-return.js: Added.
+        * wasm/function-tests/br-if-as-return.js: Added.
+        * wasm/function-tests/br-table-as-return.js: Added.
+        * wasm/function-tests/if-no-else-non-void.js:
+        * wasm/function-tests/struct.js: Added.
+        * wasm/js-api/global-error.js:
+        (assert.throws):
+        * wasm/js-api/table.js:
+        (assert.throws):
+
 2016-12-21  Saam Barati  <[email protected]>
 
         WebAssembly: Import spec tests

Added: trunk/JSTests/wasm/function-tests/br-as-return.js (0 => 210090)


--- trunk/JSTests/wasm/function-tests/br-as-return.js	                        (rev 0)
+++ trunk/JSTests/wasm/function-tests/br-as-return.js	2016-12-22 01:06:20 UTC (rev 210090)
@@ -0,0 +1,31 @@
+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const builder = (new Builder())
+      .Type().End()
+      .Function().End()
+      .Export()
+          .Function("br1")
+          .Function("br0")
+      .End()
+      .Code()
+          .Function("br1", { params: [], ret: "i32" })
+              .Block("void", b => {
+                  return b.I32Const(0)
+                  .Br(1)
+              })
+             .Unreachable()
+          .End()
+
+          .Function("br0", { params: [], ret: "i32" })
+              .I32Const(0)
+              .Br(0)
+          .End()
+
+      .End();
+
+const bin = builder.WebAssembly().get();
+const module = new WebAssembly.Module(bin);
+const instance = new WebAssembly.Instance(module);
+assert.eq(instance.exports.br1(), 0)
+assert.eq(instance.exports.br0(), 0)

Added: trunk/JSTests/wasm/function-tests/br-if-as-return.js (0 => 210090)


--- trunk/JSTests/wasm/function-tests/br-if-as-return.js	                        (rev 0)
+++ trunk/JSTests/wasm/function-tests/br-if-as-return.js	2016-12-22 01:06:20 UTC (rev 210090)
@@ -0,0 +1,33 @@
+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const builder = (new Builder())
+      .Type().End()
+      .Function().End()
+      .Export()
+          .Function("br1")
+          .Function("br0")
+      .End()
+      .Code()
+          .Function("br1", { params: [], ret: "i32" })
+              .Block("void", b => {
+                  return b.I32Const(0)
+                  .I32Const(1)
+                  .BrIf(1)
+              })
+             .Unreachable()
+          .End()
+
+          .Function("br0", { params: [], ret: "i32" })
+              .I32Const(0)
+              .I32Const(1)
+              .BrIf(0)
+          .End()
+
+      .End();
+
+const bin = builder.WebAssembly().get();
+const module = new WebAssembly.Module(bin);
+const instance = new WebAssembly.Instance(module);
+assert.eq(instance.exports.br1(), 0)
+assert.eq(instance.exports.br0(), 0)

Added: trunk/JSTests/wasm/function-tests/br-table-as-return.js (0 => 210090)


--- trunk/JSTests/wasm/function-tests/br-table-as-return.js	                        (rev 0)
+++ trunk/JSTests/wasm/function-tests/br-table-as-return.js	2016-12-22 01:06:20 UTC (rev 210090)
@@ -0,0 +1,52 @@
+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const builder = (new Builder())
+      .Type().End()
+      .Function().End()
+      .Export()
+          .Function("br1Default")
+          .Function("br0Default")
+          .Function("br1Case")
+          .Function("br0Case")
+      .End()
+      .Code()
+          .Function("br1Default", { params: [], ret: "i32" })
+              .Block("void", b => {
+                  return b.I32Const(0)
+                  .I32Const(100)
+                  .BrTable(1, 1)
+              })
+             .Unreachable()
+          .End()
+
+          .Function("br0Default", { params: [], ret: "i32" })
+              .I32Const(0)
+              .I32Const(100)
+              .BrTable(0, 0)
+          .End()
+
+          .Function("br1Case", { params: [], ret: "i32" })
+              .Block("void", b => {
+                  return b.I32Const(0)
+                  .I32Const(100)
+                  .BrTable(1, 1)
+              })
+             .Unreachable()
+          .End()
+
+          .Function("br0Case", { params: [], ret: "i32" })
+              .I32Const(0)
+              .I32Const(0)
+              .BrTable(0, 0)
+          .End()
+
+      .End();
+
+const bin = builder.WebAssembly().get();
+const module = new WebAssembly.Module(bin);
+const instance = new WebAssembly.Instance(module);
+assert.eq(instance.exports.br1Default(), 0)
+assert.eq(instance.exports.br0Default(), 0)
+assert.eq(instance.exports.br1Case(), 0)
+assert.eq(instance.exports.br0Case(), 0)

Modified: trunk/JSTests/wasm/function-tests/if-no-else-non-void.js (210089 => 210090)


--- trunk/JSTests/wasm/function-tests/if-no-else-non-void.js	2016-12-22 00:53:25 UTC (rev 210089)
+++ trunk/JSTests/wasm/function-tests/if-no-else-non-void.js	2016-12-22 01:06:20 UTC (rev 210090)
@@ -13,4 +13,4 @@
       .End();
 
 const bin = builder.WebAssembly().get();
-assert.throws(() => new WebAssembly.Module(bin), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: If-block had a non-void result type: I32 but had no else-block (evaluating 'new WebAssembly.Module(bin)')");
+assert.throws(() => new WebAssembly.Module(bin), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: If-block had a non-void result type: I32 but had no else-block, in function at index 0 (evaluating 'new WebAssembly.Module(bin)')");

Added: trunk/JSTests/wasm/function-tests/struct.js (0 => 210090)


--- trunk/JSTests/wasm/function-tests/struct.js	                        (rev 0)
+++ trunk/JSTests/wasm/function-tests/struct.js	2016-12-22 01:06:20 UTC (rev 210090)
@@ -0,0 +1,28 @@
+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const builder = (new Builder())
+
+builder.Type().End()
+    .Function().End()
+    .Memory().InitialMaxPages(1, 1).End()
+    .Export()
+        .Function("callFunc")
+    .End()
+    .Code()
+        .Function("callFunc", { params: ["i32", "i32"], ret: "i32" })
+            .GetLocal(0)
+            .If("void", b => {
+                return b.GetLocal(0)
+                .GetLocal(1)
+                .I32Load(0, 4)
+                .I32Sub()
+                .Return()
+            })
+            .I32Const(42)
+            .Return()
+        .End()
+    .End();
+const bin = builder.WebAssembly().get();
+const module = new WebAssembly.Module(bin);
+const instance = new WebAssembly.Instance(module);

Modified: trunk/JSTests/wasm/js-api/global-error.js (210089 => 210090)


--- trunk/JSTests/wasm/js-api/global-error.js	2016-12-22 00:53:25 UTC (rev 210089)
+++ trunk/JSTests/wasm/js-api/global-error.js	2016-12-22 01:06:20 UTC (rev 210090)
@@ -103,7 +103,7 @@
     const bin = builder.WebAssembly();
     bin.trim();
 
-    assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: set_global 0 is immutable (evaluating 'new WebAssembly.Module(bin.get())')");
+    assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: set_global 0 is immutable, in function at index 0 (evaluating 'new WebAssembly.Module(bin.get())')");
 }
 
 
@@ -130,7 +130,7 @@
     const bin = builder.WebAssembly();
     bin.trim();
 
-    assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: set_global 1 of unknown global, limit is 1 (evaluating 'new WebAssembly.Module(bin.get())')");
+    assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: set_global 1 of unknown global, limit is 1, in function at index 0 (evaluating 'new WebAssembly.Module(bin.get())')");
 }
 
 
@@ -156,7 +156,7 @@
     const bin = builder.WebAssembly();
     bin.trim();
 
-    assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: set_global 0 with type F32 with a variable of type I32 (evaluating 'new WebAssembly.Module(bin.get())')");
+    assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: set_global 0 with type F32 with a variable of type I32, in function at index 0 (evaluating 'new WebAssembly.Module(bin.get())')");
 }
 
 for ( let imp of [undefined, null, {}, () => {}, "number", new Number(4)]) {

Modified: trunk/JSTests/wasm/js-api/table.js (210089 => 210090)


--- trunk/JSTests/wasm/js-api/table.js	2016-12-22 00:53:25 UTC (rev 210089)
+++ trunk/JSTests/wasm/js-api/table.js	2016-12-22 01:06:20 UTC (rev 210090)
@@ -42,7 +42,7 @@
                 .CallIndirect(0, 0)
             .End()
         .End();
-    assert.throws(() => new WebAssembly.Module(builder.WebAssembly().get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 4 / 7: call_indirect is only valid when a table is defined or imported (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')");
+    assert.throws(() => new WebAssembly.Module(builder.WebAssembly().get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 4 / 7: call_indirect is only valid when a table is defined or imported, in function at index 0 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')");
 }
 
 {
@@ -61,7 +61,7 @@
                 .CallIndirect(0, 1)
             .End()
         .End();
-    assert.throws(() => new WebAssembly.Module(builder.WebAssembly().get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 6 / 7: call_indirect's 'reserved' varuint1 must be 0x0 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')");
+    assert.throws(() => new WebAssembly.Module(builder.WebAssembly().get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 6 / 7: call_indirect's 'reserved' varuint1 must be 0x0, in function at index 0 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')");
 }
 
 {

Modified: trunk/Source/_javascript_Core/ChangeLog (210089 => 210090)


--- trunk/Source/_javascript_Core/ChangeLog	2016-12-22 00:53:25 UTC (rev 210089)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-12-22 01:06:20 UTC (rev 210090)
@@ -1,3 +1,36 @@
+2016-12-21  Keith Miller  <[email protected]>
+
+        WebAssembly: Allow br, br_if, and br_table to act as a return
+        https://bugs.webkit.org/show_bug.cgi?id=166393
+
+        Reviewed by Saam Barati.
+
+        This patch allows br, br_if, and br_table to treat branching to
+        the size of the control stack to act as a return. This change was
+        made by adding a new block type to the wasm function parser,
+        TopLevel. Adding this new block eliminates a lot of the special
+        case code we had in the parser previously. The only special case
+        we need is when the end opcode is parsed from the top level.  The
+        B3 IR generator needs to automatically emit a return at that
+        point.
+
+        Also, this patch adds the function number to validation errors
+        in the function parser. The current error message is not helpful
+        otherwise.
+
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::ControlData::dump):
+        (JSC::Wasm::B3IRGenerator::addTopLevel):
+        * wasm/WasmFunctionParser.h:
+        * wasm/WasmPlan.cpp:
+        (JSC::Wasm::Plan::parseAndValidateModule):
+        (JSC::Wasm::Plan::run):
+        * wasm/WasmValidate.cpp:
+        (JSC::Wasm::Validate::ControlData::dump):
+        (JSC::Wasm::Validate::Validate):
+        (JSC::Wasm::Validate::addTopLevel):
+        (JSC::Wasm::validateFunction):
+
 2016-12-21  JF Bastien  <[email protected]>
 
         WebAssembly JS API: cleanup & pass VM around to {Compile/Runtime}Error

Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (210089 => 210090)


--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2016-12-22 00:53:25 UTC (rev 210089)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2016-12-22 01:06:20 UTC (rev 210090)
@@ -87,14 +87,17 @@
         {
             switch (type()) {
             case BlockType::If:
-                out.print("If:    ");
+                out.print("If:       ");
                 break;
             case BlockType::Block:
-                out.print("Block: ");
+                out.print("Block:    ");
                 break;
             case BlockType::Loop:
-                out.print("Loop:  ");
+                out.print("Loop:     ");
                 break;
+            case BlockType::TopLevel:
+                out.print("TopLevel: ");
+                break;
             }
             out.print("Continuation: ", *continuation, ", Special: ");
             if (special)
@@ -178,6 +181,7 @@
     PartialResult WARN_UNUSED_RETURN addSelect(ExpressionType condition, ExpressionType nonZero, ExpressionType zero, ExpressionType& result);
 
     // Control flow
+    ControlData WARN_UNUSED_RETURN addTopLevel(Type signature);
     ControlData WARN_UNUSED_RETURN addBlock(Type signature);
     ControlData WARN_UNUSED_RETURN addLoop(Type signature);
     PartialResult WARN_UNUSED_RETURN addIf(ExpressionType condition, Type signature, ControlData& result);
@@ -184,7 +188,7 @@
     PartialResult WARN_UNUSED_RETURN addElse(ControlData&, const ExpressionList&);
     PartialResult WARN_UNUSED_RETURN addElseToUnreachable(ControlData&);
 
-    PartialResult WARN_UNUSED_RETURN addReturn(const ExpressionList& returnValues);
+    PartialResult WARN_UNUSED_RETURN addReturn(const ControlData&, const ExpressionList& returnValues);
     PartialResult WARN_UNUSED_RETURN addBranch(ControlData&, ExpressionType condition, const ExpressionList& returnValues);
     PartialResult WARN_UNUSED_RETURN addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTargets, const ExpressionList& expressionStack);
     PartialResult WARN_UNUSED_RETURN endBlock(ControlEntry&, ExpressionList& expressionStack);
@@ -553,6 +557,11 @@
     return nullptr;
 }
 
+B3IRGenerator::ControlData B3IRGenerator::addTopLevel(Type signature)
+{
+    return ControlData(m_proc, signature, BlockType::TopLevel, m_proc.addBlock());
+}
+
 B3IRGenerator::ControlData B3IRGenerator::addBlock(Type signature)
 {
     return ControlData(m_proc, signature, BlockType::Block, m_proc.addBlock());
@@ -601,7 +610,7 @@
     return { };
 }
 
-auto B3IRGenerator::addReturn(const ExpressionList& returnValues) -> PartialResult
+auto B3IRGenerator::addReturn(const ControlData&, const ExpressionList& returnValues) -> PartialResult
 {
     ASSERT(returnValues.size() <= 1);
     if (returnValues.size())
@@ -671,6 +680,10 @@
     for (Variable* result : data.result)
         entry.enclosedExpressionStack.append(m_currentBlock->appendNew<VariableValue>(m_proc, B3::Get, Origin(), result));
 
+    // TopLevel does not have any code after this so we need to make sure we emit a return here.
+    if (data.type() == BlockType::TopLevel)
+        return addReturn(entry.controlData, entry.enclosedExpressionStack);
+
     return { };
 }
 

Modified: trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h (210089 => 210090)


--- trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h	2016-12-22 00:53:25 UTC (rev 210089)
+++ trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h	2016-12-22 01:06:20 UTC (rev 210090)
@@ -35,7 +35,8 @@
 enum class BlockType {
     If,
     Block,
-    Loop
+    Loop,
+    TopLevel
 };
 
 template<typename Context>
@@ -60,7 +61,6 @@
     PartialResult WARN_UNUSED_RETURN parseBody();
     PartialResult WARN_UNUSED_RETURN parseExpression(OpType);
     PartialResult WARN_UNUSED_RETURN parseUnreachableExpression(OpType);
-    PartialResult WARN_UNUSED_RETURN addReturn();
     PartialResult WARN_UNUSED_RETURN unifyControl(Vector<ExpressionType>&, unsigned level);
 
 #define WASM_TRY_POP_EXPRESSION_STACK_INTO(result, what) do {                               \
@@ -126,8 +126,9 @@
 template<typename Context>
 auto FunctionParser<Context>::parseBody() -> PartialResult
 {
-    while (true) {
-        uint8_t op;
+    m_controlStack.append({ ExpressionList(), m_context.addTopLevel(m_signature->returnType()) });
+    uint8_t op;
+    while (m_controlStack.size()) {
         WASM_PARSER_FAIL_IF(!parseUInt8(op), "can't decode opcode");
         WASM_PARSER_FAIL_IF(!isValidOpType(op), "invalid opcode ", op);
 
@@ -136,12 +137,6 @@
             m_context.dump(m_controlStack, m_expressionStack);
         }
 
-        if (op == End && !m_controlStack.size()) {
-            if (m_unreachableBlocks)
-                return { };
-            return addReturn();
-        }
-
         if (m_unreachableBlocks)
             WASM_FAIL_IF_HELPER_FAILS(parseUnreachableExpression(static_cast<OpType>(op)));
         else
@@ -148,21 +143,7 @@
             WASM_FAIL_IF_HELPER_FAILS(parseExpression(static_cast<OpType>(op)));
     }
 
-    RELEASE_ASSERT_NOT_REACHED();
-}
-
-template<typename Context>
-auto FunctionParser<Context>::addReturn() -> PartialResult
-{
-    ExpressionList returnValues;
-    if (m_signature->returnType() != Void) {
-        ExpressionType returnValue;
-        WASM_TRY_POP_EXPRESSION_STACK_INTO(returnValue, "return");
-        returnValues.append(returnValue);
-    }
-
-    m_unreachableBlocks = 1;
-    WASM_TRY_ADD_TO_CONTEXT(addReturn(returnValues));
+    ASSERT(op == OpType::End);
     return { };
 }
 
@@ -433,12 +414,13 @@
 
     case BrTable: {
         uint32_t numberOfTargets;
+        uint32_t defaultTarget;
         ExpressionType condition;
-        uint32_t defaultTarget;
+        Vector<ControlType*> targets;
+
         WASM_PARSER_FAIL_IF(!parseVarUInt32(numberOfTargets), "can't get the number of targets for br_table");
         WASM_PARSER_FAIL_IF(numberOfTargets == std::numeric_limits<uint32_t>::max(), "br_table's number of targets is too big ", numberOfTargets);
 
-        Vector<ControlType*> targets;
         WASM_PARSER_FAIL_IF(!targets.tryReserveCapacity(numberOfTargets), "can't allocate memory for ", numberOfTargets, " br_table targets");
         for (uint32_t i = 0; i < numberOfTargets; ++i) {
             uint32_t target;
@@ -449,6 +431,7 @@
 
         WASM_PARSER_FAIL_IF(!parseVarUInt32(defaultTarget), "can't get default target for br_table");
         WASM_PARSER_FAIL_IF(defaultTarget >= m_controlStack.size(), "br_table's default target ", defaultTarget, " exceeds control stack size ", m_controlStack.size());
+
         WASM_TRY_POP_EXPRESSION_STACK_INTO(condition, "br_table condition");
         WASM_TRY_ADD_TO_CONTEXT(addSwitch(condition, targets, m_controlStack[m_controlStack.size() - 1 - defaultTarget].controlData, m_expressionStack));
 
@@ -457,7 +440,16 @@
     }
 
     case Return: {
-        return addReturn();
+        ExpressionList returnValues;
+        if (m_signature->returnType() != Void) {
+            ExpressionType returnValue;
+            WASM_TRY_POP_EXPRESSION_STACK_INTO(returnValue, "return");
+            returnValues.append(returnValue);
+        }
+
+        WASM_TRY_ADD_TO_CONTEXT(addReturn(m_controlStack[0].controlData, returnValues));
+        m_unreachableBlocks = 1;
+        return { };
     }
 
     case End: {

Modified: trunk/Source/_javascript_Core/wasm/WasmPlan.cpp (210089 => 210090)


--- trunk/Source/_javascript_Core/wasm/WasmPlan.cpp	2016-12-22 00:53:25 UTC (rev 210089)
+++ trunk/Source/_javascript_Core/wasm/WasmPlan.cpp	2016-12-22 01:06:20 UTC (rev 210090)
@@ -96,7 +96,7 @@
                     dataLog(RawPointer(reinterpret_cast<void*>(functionStart[i])), ", ");
                 dataLogLn();
             }
-            m_errorMessage = validationResult.error(); // FIXME make this an Expected.
+            m_errorMessage = makeString(validationResult.error(), ", in function at index ", String::number(functionIndex)); // FIXME make this an Expected.
             return false;
         }
     }
@@ -178,7 +178,7 @@
                 auto locker = holdLock(m_lock);
                 if (!m_errorMessage) {
                     // Multiple compiles could fail simultaneously. We arbitrarily choose the first.
-                    m_errorMessage = parseAndCompileResult.error(); // FIXME make this an Expected.
+                    m_errorMessage = makeString(parseAndCompileResult.error(), ", in function at index ", String::number(functionIndex)); // FIXME make this an Expected.
                 }
                 m_currentIndex = m_functionLocationInBinary.size();
 

Modified: trunk/Source/_javascript_Core/wasm/WasmValidate.cpp (210089 => 210090)


--- trunk/Source/_javascript_Core/wasm/WasmValidate.cpp	2016-12-22 00:53:25 UTC (rev 210089)
+++ trunk/Source/_javascript_Core/wasm/WasmValidate.cpp	2016-12-22 01:06:20 UTC (rev 210090)
@@ -52,15 +52,19 @@
         {
             switch (type()) {
             case BlockType::If:
-                out.print("If:    ");
+                out.print("If:       ");
                 break;
             case BlockType::Block:
-                out.print("Block: ");
+                out.print("Block:    ");
                 break;
             case BlockType::Loop:
-                out.print("Loop:  ");
+                out.print("Loop:     ");
                 break;
+            case BlockType::TopLevel:
+                out.print("TopLevel: ");
+                break;
             }
+            out.print(makeString(signature()));
         }
 
         bool hasNonVoidSignature() const { return m_signature != Void; }
@@ -116,6 +120,7 @@
     Result WARN_UNUSED_RETURN addSelect(ExpressionType condition, ExpressionType nonZero, ExpressionType zero, ExpressionType& result);
 
     // Control flow
+    ControlData WARN_UNUSED_RETURN addTopLevel(Type signature);
     ControlData WARN_UNUSED_RETURN addBlock(Type signature);
     ControlData WARN_UNUSED_RETURN addLoop(Type signature);
     Result WARN_UNUSED_RETURN addIf(ExpressionType condition, Type signature, ControlData& result);
@@ -122,7 +127,7 @@
     Result WARN_UNUSED_RETURN addElse(ControlData&, const ExpressionList&);
     Result WARN_UNUSED_RETURN addElseToUnreachable(ControlData&);
 
-    Result WARN_UNUSED_RETURN addReturn(const ExpressionList& returnValues);
+    Result WARN_UNUSED_RETURN addReturn(ControlData& topLevel, const ExpressionList& returnValues);
     Result WARN_UNUSED_RETURN addBranch(ControlData&, ExpressionType condition, const ExpressionList& expressionStack);
     Result WARN_UNUSED_RETURN addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTarget, const ExpressionList& expressionStack);
     Result WARN_UNUSED_RETURN endBlock(ControlEntry&, ExpressionList& expressionStack);
@@ -136,9 +141,8 @@
 
     bool hasMemory() const { return !!m_module.memory; }
 
-    Validate(ExpressionType returnType, const ModuleInformation& module)
-        : m_returnType(returnType)
-        , m_module(module)
+    Validate(const ModuleInformation& module)
+        : m_module(module)
     {
     }
 
@@ -150,7 +154,6 @@
 
     Result checkBranchTarget(ControlData& target, const ExpressionList& expressionStack);
 
-    ExpressionType m_returnType;
     Vector<Type> m_locals;
     const ModuleInformation& m_module;
 };
@@ -206,6 +209,11 @@
     return { };
 }
 
+Validate::ControlType Validate::addTopLevel(Type signature)
+{
+    return ControlData(BlockType::TopLevel, signature);
+}
+
 Validate::ControlType Validate::addBlock(Type signature)
 {
     return ControlData(BlockType::Block, signature);
@@ -244,12 +252,13 @@
     return { };
 }
 
-auto Validate::addReturn(const ExpressionList& returnValues) -> Result
+auto Validate::addReturn(ControlType& topLevel, const ExpressionList& returnValues) -> Result
 {
-    if (m_returnType == Void)
+    ASSERT(topLevel.type() == BlockType::TopLevel);
+    if (topLevel.signature() == Void)
         return { };
     ASSERT(returnValues.size() == 1);
-    WASM_VALIDATOR_FAIL_IF(m_returnType != returnValues[0], "return type ", returnValues[0], " doesn't match function's return type ", m_returnType);
+    WASM_VALIDATOR_FAIL_IF(topLevel.signature() != returnValues[0], "return type ", returnValues[0], " doesn't match function's return type ", topLevel.signature());
     return { };
 }
 
@@ -355,7 +364,7 @@
 
 Expected<void, String> validateFunction(VM* vm, const uint8_t* source, size_t length, const Signature* signature, const ImmutableFunctionIndexSpace& functionIndexSpace, const ModuleInformation& module)
 {
-    Validate context(signature->returnType(), module);
+    Validate context(module);
     FunctionParser<Validate> validator(vm, context, source, length, signature, functionIndexSpace, module);
     WASM_FAIL_IF_HELPER_FAILS(validator.parse());
     return { };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to