WSL should be able to trap when something fatal happens
authormmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Sep 2017 05:36:26 +0000 (05:36 +0000)
committermmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Sep 2017 05:36:26 +0000 (05:36 +0000)
https://bugs.webkit.org/show_bug.cgi?id=177110

Reviewed by Filip Pizlo.

WSL programs can include a statement "trap;" which causes the entry
point to immediately return the default value of its return type.
This is implemented by throw/catch and populateDefaultValue().

* WebGPUShadingLanguageRI/All.js:
* WebGPUShadingLanguageRI/EvaluationCommon.js:
* WebGPUShadingLanguageRI/Evaluator.js:
(Evaluator.prototype.visitTrapStatement):
* WebGPUShadingLanguageRI/Parse.js:
(parseStatement):
* WebGPUShadingLanguageRI/ReturnChecker.js:
(ReturnChecker.prototype.visitTrapStatement):
* WebGPUShadingLanguageRI/Rewriter.js:
(Rewriter.prototype.visitTrapStatement):
* WebGPUShadingLanguageRI/StandardLibrary.js:
* WebGPUShadingLanguageRI/Test.html:
* WebGPUShadingLanguageRI/Test.js:
* WebGPUShadingLanguageRI/TrapStatement.js: Copied from Tools/WebGPUShadingLanguageRI/EvaluationCommon.js.
(TrapStatement):
(TrapStatement.prototype.get origin):
(TrapStatement.prototype.toString):
* WebGPUShadingLanguageRI/Visitor.js:
(Visitor.prototype.visitProtocolDecl):

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

13 files changed:
Tools/ChangeLog
Tools/WebGPUShadingLanguageRI/All.js
Tools/WebGPUShadingLanguageRI/CallFunction.js
Tools/WebGPUShadingLanguageRI/EvaluationCommon.js
Tools/WebGPUShadingLanguageRI/Evaluator.js
Tools/WebGPUShadingLanguageRI/Parse.js
Tools/WebGPUShadingLanguageRI/ReturnChecker.js
Tools/WebGPUShadingLanguageRI/Rewriter.js
Tools/WebGPUShadingLanguageRI/StandardLibrary.js
Tools/WebGPUShadingLanguageRI/Test.html
Tools/WebGPUShadingLanguageRI/Test.js
Tools/WebGPUShadingLanguageRI/TrapStatement.js [new file with mode: 0644]
Tools/WebGPUShadingLanguageRI/Visitor.js

index f771ea8..4d91431 100644 (file)
@@ -1,3 +1,34 @@
+2017-09-19  Myles C. Maxfield  <mmaxfield@apple.com>
+
+        WSL should be able to trap when something fatal happens
+        https://bugs.webkit.org/show_bug.cgi?id=177110
+
+        Reviewed by Filip Pizlo.
+
+        WSL programs can include a statement "trap;" which causes the entry
+        point to immediately return the default value of its return type.
+        This is implemented by throw/catch and populateDefaultValue().
+
+        * WebGPUShadingLanguageRI/All.js:
+        * WebGPUShadingLanguageRI/EvaluationCommon.js:
+        * WebGPUShadingLanguageRI/Evaluator.js:
+        (Evaluator.prototype.visitTrapStatement):
+        * WebGPUShadingLanguageRI/Parse.js:
+        (parseStatement):
+        * WebGPUShadingLanguageRI/ReturnChecker.js:
+        (ReturnChecker.prototype.visitTrapStatement):
+        * WebGPUShadingLanguageRI/Rewriter.js:
+        (Rewriter.prototype.visitTrapStatement):
+        * WebGPUShadingLanguageRI/StandardLibrary.js:
+        * WebGPUShadingLanguageRI/Test.html:
+        * WebGPUShadingLanguageRI/Test.js:
+        * WebGPUShadingLanguageRI/TrapStatement.js: Copied from Tools/WebGPUShadingLanguageRI/EvaluationCommon.js.
+        (TrapStatement):
+        (TrapStatement.prototype.get origin):
+        (TrapStatement.prototype.toString):
+        * WebGPUShadingLanguageRI/Visitor.js:
+        (Visitor.prototype.visitProtocolDecl):
+
 2017-09-19  Ryan Haddad  <ryanhaddad@apple.com>
 
         Unreviewed follow-up to r222229, remove invalid triggers.
index e811765..debfaff 100644 (file)
@@ -141,6 +141,7 @@ load("StructType.js");
 load("Substitution.js");
 load("SynthesizeEnumFunctions.js");
 load("SynthesizeStructAccessors.js");
+load("TrapStatement.js");
 load("TypeDef.js");
 load("TypeDefResolver.js");
 load("TypeOrVariableRef.js");
index 4330c9b..637617c 100644 (file)
@@ -39,7 +39,17 @@ function callFunction(program, name, typeArguments, argumentList)
         type.visit(new StructLayoutBuilder());
         func.parameters[i].ePtr.copyFrom(argumentList[i].ePtr, type.size);
     }
-    let result = new Evaluator(program).runFunc(func);
+    let result;
+    try {
+        result = new Evaluator(program).runFunc(func);
+    } catch (e) {
+        if (e == TrapException) {
+            let buffer = new EBuffer(func.returnType.size);
+            func.returnType.populateDefaultValue(buffer, 0);
+            result = new EPtr(buffer, 0);
+        } else
+            throw e;
+    }
     return new TypedValue(func.uninstantiatedReturnType, result);
 }
 
index ba24304..4e36954 100644 (file)
@@ -26,5 +26,6 @@
 
 const BreakException = Symbol("BreakException");
 const ContinueException = Symbol("ContinueException");
+const TrapException = Symbol("TrapException");
 
 
index 8e9a315..2e0313d 100644 (file)
@@ -253,6 +253,11 @@ class Evaluator extends Visitor {
     {
         throw ContinueException;
     }
+
+    visitTrapStatement(node)
+    {
+        throw TrapException;
+    }
     
     visitAnonymousVariable(node)
     {
index 3dc6ff1..3bf0edd 100644 (file)
@@ -752,6 +752,11 @@ function parse(program, origin, originKind, lineNumberOffset, text)
             return parseFor();
         if (token.text == "if")
             return parseIfStatement();
+        if (token.text == "trap") {
+            let origin = consume("trap");
+            consume(";");
+            return new TrapStatement(origin);
+        }
         if (token.text == "{")
             return parseBlock();
         let variableDecl = lexer.backtrackingScope(parseVariableDecls);
index b58f4b5..4ca53b8 100644 (file)
@@ -133,6 +133,11 @@ class ReturnChecker extends Visitor {
     {
         return this.returnStyle.DefinitelyReturns;
     }
+    
+    visitTrapStatement(node)
+    {
+        return this.returnStyle.DefinitelyReturns;
+    }
 
     visitBreak(node)
     {
index ec25d40..3be107d 100644 (file)
@@ -272,6 +272,11 @@ class Rewriter {
     {
         return new Break(node.origin);
     }
+
+    visitTrapStatement(node)
+    {
+        return new TrapStatement(node.origin);
+    }
     
     visitGenericLiteral(node)
     {
index 08a5443..42b6ef9 100644 (file)
@@ -107,6 +107,7 @@ bool operator&(bool a, bool b)
         return b;
     return false;
 }
+
 bool operator|(bool a, bool b)
 {
     if (a)
@@ -115,12 +116,14 @@ bool operator|(bool a, bool b)
         return true;
     return false;
 }
+
 bool operator^(bool a, bool b)
 {
     if (a)
         return !b;
     return b;
 }
+
 bool operator~(bool value)
 {
     return !value;
@@ -179,7 +182,7 @@ thread T^ operator&[]<T>(thread vec2<T>^ foo, uint index)
         return &foo->x;
     if (index == 1)
         return &foo->y;
-    return null;
+    trap;
 }
 
 struct vec3<T> {
@@ -233,7 +236,7 @@ thread T^ operator&[]<T>(thread vec3<T>^ foo, uint index)
         return &foo->y;
     if (index == 2)
         return &foo->z;
-    return null;
+    trap;
 }
 
 struct vec4<T> {
@@ -333,7 +336,7 @@ thread T^ operator&[]<T>(thread vec4<T>^ foo, uint index)
         return &foo->z;
     if (index == 3)
         return &foo->w;
-    return null;
+    trap;
 }
 
 native thread T^ operator&[]<T>(thread T[], uint);
index 62da230..48cb5a5 100644 (file)
@@ -75,7 +75,6 @@
 <script src="IntLiteral.js"></script>
 <script src="IntLiteralType.js"></script>
 <script src="Intrinsics.js"></script>
-<script src="LetExpression.js"></script>
 <script src="Lexer.js"></script>
 <script src="LexerToken.js"></script>
 <script src="LiteralTypeChecker.js"></script>
 <script src="Substitution.js"></script>
 <script src="SynthesizeEnumFunctions.js"></script>
 <script src="SynthesizeStructAccessors.js"></script>
+<script src="TrapStatement.js"></script>
 <script src="TypeDef.js"></script>
 <script src="TypeDefResolver.js"></script>
 <script src="TypeOrVariableRef.js"></script>
index a996c88..eea9880 100644 (file)
@@ -4214,6 +4214,38 @@ function TEST_enumConstexprGenericStruct()
     checkInt(program, callFunction(program, "testY", [], []), 1);
 }
 
+function TEST_trap()
+{
+    let program = doPrep(`
+        int foo()
+        {
+            trap;
+        }
+        int foo2(int x)
+        {
+            if (x == 3)
+                trap;
+            return 4;
+        }
+        struct Bar {
+            int3 x;
+            float y;
+        }
+        Bar foo3()
+        {
+            trap;
+        }
+    `);
+    checkInt(program, callFunction(program, "foo", [], []), 0);
+    checkInt(program, callFunction(program, "foo2", [], [makeInt(program, 1)]), 4);
+    checkInt(program, callFunction(program, "foo2", [], [makeInt(program, 3)]), 0);
+    let foo3 = callFunction(program, "foo3", [], []);
+    for (let value of foo3.ePtr.buffer._array) {
+        if (value != undefined && value != 0)
+            throw new Error("Trap returned a non-zero value");
+    }
+}
+
 let filter = /.*/; // run everything by default
 if (this["arguments"]) {
     for (let i = 0; i < arguments.length; i++) {
diff --git a/Tools/WebGPUShadingLanguageRI/TrapStatement.js b/Tools/WebGPUShadingLanguageRI/TrapStatement.js
new file mode 100644 (file)
index 0000000..a193f73
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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. 
+ */
+"use strict";
+
+class TrapStatement extends Node {
+    constructor(origin)
+    {
+        super();
+        this._origin = origin;
+    }
+    
+    get origin() { return this._origin; }
+    
+    toString()
+    {
+        return "trap";
+    }
+};
+
index a406e07..d8045c6 100644 (file)
@@ -292,6 +292,10 @@ class Visitor {
     visitBreak(node)
     {
     }
+
+    visitTrapStatement(node)
+    {
+    }
     
     visitGenericLiteral(node)
     {