Diff
Modified: trunk/Tools/ChangeLog (222327 => 222328)
--- trunk/Tools/ChangeLog 2017-09-21 17:35:18 UTC (rev 222327)
+++ trunk/Tools/ChangeLog 2017-09-21 17:41:11 UTC (rev 222328)
@@ -1,3 +1,50 @@
+2017-09-20 Filip Pizlo <[email protected]>
+
+ WSL needs a way to verify that structs are not cyclic
+ https://bugs.webkit.org/show_bug.cgi?id=177044
+
+ Reviewed by Myles Maxfield.
+
+ This adds a recursive type checking phase. Even before adding this phase, the compiler would
+ successfully detect recursive types - but at the cost of also rejecting programs that had
+ recursive types indirectly through pointers. To make both things work, I had to change Visitor
+ to no longer visit TypeRef.type by default. This resulted in some other changes in a few other
+ parts of the code that previously relied on that behavior.
+
+ * WebGPUShadingLanguageRI/All.js:
+ * WebGPUShadingLanguageRI/CheckRecursiveTypes.js: Added.
+ (checkRecursiveTypes):
+ * WebGPUShadingLanguageRI/Checker.js:
+ (Checker.prototype._checkShaderType.NonNumericSearcher.prototype.visitArrayRefType):
+ (Checker.prototype._checkShaderType.NonNumericSearcher.prototype.visitPtrType):
+ (Checker.prototype._checkShaderType.NonNumericSearcher.prototype.visitTypeRef):
+ (Checker.prototype._checkShaderType.NonNumericSearcher):
+ (Checker.prototype._checkShaderType):
+ (Checker.prototype.visitTypeRef):
+ * WebGPUShadingLanguageRI/NameResolver.js:
+ (NameResolver.prototype.visitProtocolDecl):
+ * WebGPUShadingLanguageRI/Prepare.js:
+ (let.prepare):
+ * WebGPUShadingLanguageRI/RecursiveTypeChecker.js: Added.
+ (RecursiveTypeChecker):
+ (RecursiveTypeChecker.prototype.visitFuncDef):
+ (RecursiveTypeChecker.prototype.visitNativeFunc):
+ (RecursiveTypeChecker.prototype.visitStructType):
+ (RecursiveTypeChecker.prototype.visitReferenceType):
+ (RecursiveTypeChecker.prototype.visitTypeRef):
+ * WebGPUShadingLanguageRI/StructLayoutBuilder.js:
+ (StructLayoutBuilder.prototype.visitTypeRef):
+ (StructLayoutBuilder):
+ * WebGPUShadingLanguageRI/Test.html:
+ * WebGPUShadingLanguageRI/Test.js:
+ (TEST_simpleRecursiveStruct):
+ * WebGPUShadingLanguageRI/TypeDefResolver.js:
+ (TypeDefResolver.prototype.visitTypeRef):
+ (TypeDefResolver):
+ * WebGPUShadingLanguageRI/Visitor.js:
+ (Visitor.prototype.visitProtocolDecl):
+ * WebGPUShadingLanguageRI/index.html:
+
2017-09-21 Ryan Haddad <[email protected]>
Update TestResultsServer for iOS 11 queues.
Modified: trunk/Tools/WebGPUShadingLanguageRI/All.js (222327 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/All.js 2017-09-21 17:35:18 UTC (rev 222327)
+++ trunk/Tools/WebGPUShadingLanguageRI/All.js 2017-09-21 17:41:11 UTC (rev 222328)
@@ -49,6 +49,7 @@
load("Check.js");
load("CheckLiteralTypes.js");
load("CheckLoops.js");
+load("CheckRecursiveTypes.js");
load("CheckRecursion.js");
load("CheckReturns.js");
load("CheckUnreachableCode.js");
@@ -131,6 +132,7 @@
load("PtrType.js");
load("ReadModifyWriteExpression.js");
load("RecursionChecker.js");
+load("RecursiveTypeChecker.js");
load("ResolveNames.js");
load("ResolveOverloadImpl.js");
load("ResolveProperties.js");
Modified: trunk/Tools/WebGPUShadingLanguageRI/CallFunction.js (222327 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/CallFunction.js 2017-09-21 17:35:18 UTC (rev 222327)
+++ trunk/Tools/WebGPUShadingLanguageRI/CallFunction.js 2017-09-21 17:41:11 UTC (rev 222328)
@@ -39,17 +39,7 @@
type.visit(new StructLayoutBuilder());
func.parameters[i].ePtr.copyFrom(argumentList[i].ePtr, type.size);
}
- 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;
- }
+ let result = new Evaluator(program).runFunc(func);
return new TypedValue(func.uninstantiatedReturnType, result);
}
Added: trunk/Tools/WebGPUShadingLanguageRI/CheckRecursiveTypes.js (0 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/CheckRecursiveTypes.js (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/CheckRecursiveTypes.js 2017-09-21 17:41:11 UTC (rev 222328)
@@ -0,0 +1,30 @@
+/*
+ * 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";
+
+function checkRecursiveTypes(program)
+{
+ program.visit(new RecursiveTypeChecker());
+}
Modified: trunk/Tools/WebGPUShadingLanguageRI/Checker.js (222327 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/Checker.js 2017-09-21 17:35:18 UTC (rev 222327)
+++ trunk/Tools/WebGPUShadingLanguageRI/Checker.js 2017-09-21 17:41:11 UTC (rev 222328)
@@ -60,7 +60,8 @@
{
// FIXME: Relax these checks once we have implemented support for textures and samplers.
if (node.typeParameters.length != 0)
- throw new WTypeError("Entry point " + node.name + " must not have type arguments.");
+ throw new WTypeError(node.origin.originString, "Entry point " + node.name + " must not have type arguments.");
+ let shaderFunc = node;
class NonNumericSearcher extends Visitor {
constructor(name)
{
@@ -69,42 +70,47 @@
}
visitArrayRefType(node)
{
- throw new WTypeError(this._name + " must transitively only have numeric types.");
+ throw new WTypeError(node.origin.originString, shaderFunc.name + " must transitively only have numeric types.");
}
visitPtrType(node)
{
- throw new WTypeError(this._name + " must transitively only have numeric types.");
+ throw new WTypeError(node.origin.originString, shaderFunc.name + " must transitively only have numeric types.");
}
+ visitTypeRef(node)
+ {
+ super.visitTypeRef(node);
+ node.type.visit(this);
+ }
}
switch (node.shaderType) {
case "vertex":
if (this._vertexEntryPoints.has(node.name))
- throw new WTypeError("Duplicate vertex entry point name " + node.name);
+ throw new WTypeError(node.origin.originString, "Duplicate vertex entry point name " + node.name);
this._vertexEntryPoints.add(node.name);
if (!(node.returnType.type instanceof StructType))
- throw new WTypeError("Vertex shader " + node.name + " must return a struct.");
+ throw new WTypeError(node.origin.originString, "Vertex shader " + node.name + " must return a struct.");
for (let parameter of node.parameters) {
if (parameter.type.type instanceof StructType)
parameter.type.visit(new NonNumericSearcher(node.name));
else if (!(parameter.type.type instanceof ArrayRefType))
- throw new WTypeError(node.name + " accepts a parameter " + parameter.name + " which isn't a struct and isn't an ArrayRef.");
+ throw new WTypeError(node.origin.originString, node.name + " accepts a parameter " + parameter.name + " which isn't a struct and isn't an ArrayRef.");
}
node.returnType.type.visit(new NonNumericSearcher);
break;
case "fragment":
if (this._fragmentEntryPoints.has(node.name))
- throw new WTypeError("Duplicate fragment entry point name " + node.name);
+ throw new WTypeError(node.origin.originString, "Duplicate fragment entry point name " + node.name);
this._fragmentEntryPoints.add(node.name);
if (!(node.returnType.type instanceof StructType))
- throw new WTypeError("Fragment shader " + node.name + " must return a struct.");
+ throw new WTypeError(node.origin.originString, "Fragment shader " + node.name + " must return a struct.");
for (let parameter of node.parameters) {
if (parameter.name == "stageIn") {
if (!(parameter.type.type instanceof StructType))
- throw new WTypeError("Fragment entry points' stageIn parameter (of " + node.name + ") must be a struct type.");
+ throw new WTypeError(node.origin.originString, "Fragment entry points' stageIn parameter (of " + node.name + ") must be a struct type.");
parameter.type.visit(new NonNumericSearcher(node.name));
} else {
if (!(parameter.type.type instanceof ArrayRefType))
- throw new WTypeError("Fragment entry point's " + parameter.name + " parameter is not an array reference.");
+ throw new WTypeError(node.origin.originString, "Fragment entry point's " + parameter.name + " parameter is not an array reference.");
}
}
node.returnType.type.visit(new NonNumericSearcher);
@@ -209,7 +215,8 @@
{
if (!node.type)
throw new Error("Type reference without a type in checker: " + node + " at " + node.origin);
- node.type.visit(this);
+ if (!(node.type instanceof StructType))
+ node.type.visit(this);
this._checkTypeArguments(node.origin, node.type.typeParameters, node.typeArguments);
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/EvaluationCommon.js (222327 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/EvaluationCommon.js 2017-09-21 17:35:18 UTC (rev 222327)
+++ trunk/Tools/WebGPUShadingLanguageRI/EvaluationCommon.js 2017-09-21 17:41:11 UTC (rev 222328)
@@ -26,6 +26,5 @@
const BreakException = Symbol("BreakException");
const ContinueException = Symbol("ContinueException");
-const TrapException = Symbol("TrapException");
Modified: trunk/Tools/WebGPUShadingLanguageRI/Evaluator.js (222327 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/Evaluator.js 2017-09-21 17:35:18 UTC (rev 222327)
+++ trunk/Tools/WebGPUShadingLanguageRI/Evaluator.js 2017-09-21 17:41:11 UTC (rev 222328)
@@ -256,7 +256,7 @@
visitTrapStatement(node)
{
- throw TrapException;
+ throw new WTrapError(node.origin.originString, "Trap statement");
}
visitAnonymousVariable(node)
Modified: trunk/Tools/WebGPUShadingLanguageRI/NameResolver.js (222327 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/NameResolver.js 2017-09-21 17:35:18 UTC (rev 222327)
+++ trunk/Tools/WebGPUShadingLanguageRI/NameResolver.js 2017-09-21 17:41:11 UTC (rev 222328)
@@ -211,8 +211,6 @@
if (!parameterIsType && argumentIsType)
throw new WTypeError(node.origin.originString, "Expected value, but got type at argument #" + i);
}
-
- super.visitTypeRef(node);
}
visitReferenceType(node)
Modified: trunk/Tools/WebGPUShadingLanguageRI/Prepare.js (222327 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/Prepare.js 2017-09-21 17:35:18 UTC (rev 222327)
+++ trunk/Tools/WebGPUShadingLanguageRI/Prepare.js 2017-09-21 17:41:11 UTC (rev 222328)
@@ -45,8 +45,7 @@
resolveNamesInProtocols(program, nameResolver);
resolveTypeDefsInTypes(program);
resolveTypeDefsInProtocols(program);
- // FIXME: Need to verify that structre are not cyclic.
- // https://bugs.webkit.org/show_bug.cgi?id=177044
+ checkRecursiveTypes(program);
synthesizeStructAccessors(program);
synthesizeEnumFunctions(program);
resolveNamesInFunctions(program, nameResolver);
Added: trunk/Tools/WebGPUShadingLanguageRI/RecursiveTypeChecker.js (0 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/RecursiveTypeChecker.js (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/RecursiveTypeChecker.js 2017-09-21 17:41:11 UTC (rev 222328)
@@ -0,0 +1,57 @@
+/*
+ * 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 RecursiveTypeChecker extends Visitor {
+ constructor()
+ {
+ super();
+ this._visiting = new VisitingSet();
+ }
+
+ visitFuncDef(node)
+ {
+ }
+
+ visitNativeFunc(node)
+ {
+ }
+
+ visitStructType(node)
+ {
+ this._visiting.doVisit(node, () => super.visitStructType(node));
+ }
+
+ visitReferenceType(node)
+ {
+ }
+
+ visitTypeRef(node)
+ {
+ super.visitTypeRef(node);
+ node.type.visit(this);
+ }
+}
+
Modified: trunk/Tools/WebGPUShadingLanguageRI/StructLayoutBuilder.js (222327 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/StructLayoutBuilder.js 2017-09-21 17:35:18 UTC (rev 222327)
+++ trunk/Tools/WebGPUShadingLanguageRI/StructLayoutBuilder.js 2017-09-21 17:41:11 UTC (rev 222328)
@@ -65,5 +65,11 @@
super.visitNativeFuncInstance(node);
node.func.didLayoutStructsInImplementationData(node.implementationData);
}
+
+ visitTypeRef(node)
+ {
+ super.visitTypeRef(node);
+ node.type.visit(this);
+ }
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.html (222327 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/Test.html 2017-09-21 17:35:18 UTC (rev 222327)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.html 2017-09-21 17:41:11 UTC (rev 222328)
@@ -27,6 +27,7 @@
<script src=""
<script src=""
<script src=""
+<script src=""
<script src=""
<script src=""
<script src=""
@@ -108,6 +109,7 @@
<script src=""
<script src=""
<script src=""
+<script src=""
<script src=""
<script src=""
<script src=""
Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.js (222327 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/Test.js 2017-09-21 17:35:18 UTC (rev 222327)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.js 2017-09-21 17:41:11 UTC (rev 222328)
@@ -4352,14 +4352,16 @@
trap;
}
`);
- checkInt(program, callFunction(program, "foo", [], []), 0);
+ checkFail(
+ () => callFunction(program, "foo", [], []),
+ e => e instanceof WTrapError);
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");
- }
+ checkFail(
+ () => callFunction(program, "foo2", [], [makeInt(program, 3)]),
+ e => e instanceof WTrapError);
+ checkFail(
+ () => callFunction(program, "foo3", [], []),
+ e => e instanceof WTrapError);
}
function TEST_swizzle()
@@ -4387,6 +4389,102 @@
checkFloat(program, callFunction(program, "foo3", [], []), 4);
}
+function TEST_simpleRecursiveStruct()
+{
+ checkFail(
+ () => doPrep(`
+ struct Foo {
+ Foo foo;
+ }
+ `),
+ e => e instanceof WTypeError);
+}
+
+function TEST_mutuallyRecursiveStruct()
+{
+ checkFail(
+ () => doPrep(`
+ struct Foo {
+ Bar bar;
+ }
+ struct Bar {
+ Foo foo;
+ }
+ `),
+ e => e instanceof WTypeError);
+}
+
+function TEST_mutuallyRecursiveStructWithPointersBroken()
+{
+ let program = doPrep(`
+ struct Foo {
+ thread Bar^ bar;
+ int foo;
+ }
+ struct Bar {
+ thread Foo^ foo;
+ int bar;
+ }
+ int foo()
+ {
+ Foo foo;
+ Bar bar;
+ foo.foo = 564;
+ bar.bar = 53;
+ return foo.bar->bar - bar.foo->foo;
+ }
+ `);
+ checkFail(
+ () => checkInt(program, callFunction(program, "foo", [], []), -511),
+ e => e instanceof WTrapError);
+}
+
+function TEST_mutuallyRecursiveStructWithPointers()
+{
+ let program = doPrep(`
+ struct Foo {
+ thread Bar^ bar;
+ int foo;
+ }
+ struct Bar {
+ thread Foo^ foo;
+ int bar;
+ }
+ int foo()
+ {
+ Foo foo;
+ Bar bar;
+ foo.bar = &bar;
+ bar.foo = &foo;
+ foo.foo = 564;
+ bar.bar = 53;
+ return foo.bar->bar - bar.foo->foo;
+ }
+ `);
+ checkInt(program, callFunction(program, "foo", [], []), -511);
+}
+
+function TEST_linkedList()
+{
+ let program = doPrep(`
+ struct Node {
+ thread Node^ next;
+ int value;
+ }
+ int foo()
+ {
+ Node x, y, z;
+ x.next = &y;
+ y.next = &z;
+ x.value = 1;
+ y.value = 2;
+ z.value = 3;
+ return x.next->next->value;
+ }
+ `);
+ checkInt(program, callFunction(program, "foo", [], []), 3);
+}
+
let filter = /.*/; // run everything by default
if (this["arguments"]) {
for (let i = 0; i < arguments.length; i++) {
@@ -4424,7 +4522,10 @@
print("That took " + (after - before) * 1000 + " ms.");
}
-if (!this.window)
+if (!this.window) {
+ Error.stackTraceLimit = Infinity;
for (let _ of doTest(this)) { }
+}
+
Modified: trunk/Tools/WebGPUShadingLanguageRI/TypeDefResolver.js (222327 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/TypeDefResolver.js 2017-09-21 17:35:18 UTC (rev 222327)
+++ trunk/Tools/WebGPUShadingLanguageRI/TypeDefResolver.js 2017-09-21 17:41:11 UTC (rev 222328)
@@ -34,7 +34,8 @@
visitTypeRef(node)
{
this._visiting.doVisit(node, () => {
- super.visitTypeRef(node);
+ for (let typeArgument of node.typeArguments)
+ typeArgument.visit(this);
if (node.type instanceof TypeDef) {
let unificationContext = new UnificationContext(node.type.typeParameters);
if (node.typeArguments.length != node.type.typeParameters.length)
Modified: trunk/Tools/WebGPUShadingLanguageRI/Visitor.js (222327 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/Visitor.js 2017-09-21 17:35:18 UTC (rev 222327)
+++ trunk/Tools/WebGPUShadingLanguageRI/Visitor.js 2017-09-21 17:41:11 UTC (rev 222328)
@@ -95,7 +95,6 @@
{
for (let typeArgument of node.typeArguments)
typeArgument.visit(this);
- Node.visit(node.type, this);
}
visitNativeType(node)
Modified: trunk/Tools/WebGPUShadingLanguageRI/index.html (222327 => 222328)
--- trunk/Tools/WebGPUShadingLanguageRI/index.html 2017-09-21 17:35:18 UTC (rev 222327)
+++ trunk/Tools/WebGPUShadingLanguageRI/index.html 2017-09-21 17:41:11 UTC (rev 222328)
@@ -27,6 +27,7 @@
<script src=""
<script src=""
<script src=""
+<script src=""
<script src=""
<script src=""
<script src=""
@@ -108,6 +109,7 @@
<script src=""
<script src=""
<script src=""
+<script src=""
<script src=""
<script src=""
<script src=""