Diff
Modified: trunk/Tools/ChangeLog (221459 => 221460)
--- trunk/Tools/ChangeLog 2017-08-31 23:55:12 UTC (rev 221459)
+++ trunk/Tools/ChangeLog 2017-09-01 00:09:14 UTC (rev 221460)
@@ -1,3 +1,70 @@
+2017-08-31 Filip Pizlo <fpi...@apple.com>
+
+ WSL should support makeptr (\)
+ https://bugs.webkit.org/show_bug.cgi?id=176197
+
+ Reviewed by Saam Barati.
+
+ This required introducing some sanity about how pointers are carried around in the evaluator.
+ It turns out that we need to be careful about when a pointer to an rvalue is dereferenced. It
+ should be dereferenced basically immediately. If it cannot be, then we need to snapshot the
+ value. To do that, we need to know the types of things in a few more places. That's what this
+ change accomplishes.
+
+ * WebGPUShadingLanguageRI/All.js:
+ * WebGPUShadingLanguageRI/CallFunction.js:
+ (callFunction):
+ * WebGPUShadingLanguageRI/Checker.js:
+ (Checker.prototype.visitProtocolDecl.set throw):
+ * WebGPUShadingLanguageRI/DereferenceExpression.js:
+ (DereferenceExpression.prototype.get isLValue):
+ * WebGPUShadingLanguageRI/Evaluator.js:
+ (Evaluator.prototype._snapshot):
+ (Evaluator.prototype.runBody):
+ (Evaluator.prototype.visitFunctionLikeBlock):
+ (Evaluator.prototype.visitDereferenceExpression):
+ (Evaluator.prototype.visitMakePtrExpression):
+ (Evaluator.prototype.visitCommaExpression):
+ (Evaluator.prototype.visitCallExpression):
+ (Evaluator):
+ (Evaluator.prototype._dereference): Deleted.
+ * WebGPUShadingLanguageRI/FuncInstantiator.js:
+ (FuncInstantiator.prototype.getUnique.Instantiate.prototype.visitFuncDef):
+ (FuncInstantiator.prototype.getUnique.Instantiate.prototype.visitNativeFunc):
+ (FuncInstantiator.prototype.getUnique.Instantiate):
+ (FuncInstantiator.prototype.getUnique):
+ (FuncInstantiator):
+ * WebGPUShadingLanguageRI/FunctionLikeBlock.js:
+ (FunctionLikeBlock):
+ (FunctionLikeBlock.prototype.get returnType):
+ (FunctionLikeBlock.prototype.toString):
+ * WebGPUShadingLanguageRI/Inliner.js:
+ (Inliner.prototype.visitCallExpression):
+ (Inliner):
+ * WebGPUShadingLanguageRI/MakePtrExpression.js: Added.
+ (MakePtrExpression):
+ (MakePtrExpression.prototype.get lValue):
+ (MakePtrExpression.prototype.toString):
+ * WebGPUShadingLanguageRI/NativeFuncInstance.js: Added.
+ (NativeFuncInstance):
+ (NativeFuncInstance.prototype.get func):
+ (NativeFuncInstance.prototype.toString):
+ * WebGPUShadingLanguageRI/Rewriter.js:
+ (Rewriter.prototype.visitMakePtrExpression):
+ (Rewriter.prototype.visitCallExpression):
+ * WebGPUShadingLanguageRI/Test.js:
+ (TEST_dereferenceStore):
+ (TEST_simpleMakePtr):
+ * WebGPUShadingLanguageRI/Value.js:
+ (Value.prototype.get isLValue):
+ (Value):
+ * WebGPUShadingLanguageRI/VariableRef.js:
+ (VariableRef.prototype.get isLValue):
+ (VariableRef.prototype.get addressSpace):
+ * WebGPUShadingLanguageRI/Visitor.js:
+ (Visitor.prototype.visitMakePtrExpression):
+ (Visitor.prototype.visitCallExpression):
+
2017-08-31 Ryan Haddad <ryanhad...@apple.com>
Unreviewed, rolling out r221445.
Modified: trunk/Tools/WebGPUShadingLanguageRI/All.js (221459 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/All.js 2017-08-31 23:55:12 UTC (rev 221459)
+++ trunk/Tools/WebGPUShadingLanguageRI/All.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -63,9 +63,11 @@
load("Intrinsics.js");
load("Lexer.js");
load("LexerToken.js");
+load("MakePtrExpression.js");
load("NameContext.js");
load("NameResolver.js");
load("NativeFunc.js");
+load("NativeFuncInstance.js");
load("NativeType.js");
load("NativeTypeInstance.js");
load("NullType.js");
Modified: trunk/Tools/WebGPUShadingLanguageRI/CallFunction.js (221459 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/CallFunction.js 2017-08-31 23:55:12 UTC (rev 221459)
+++ trunk/Tools/WebGPUShadingLanguageRI/CallFunction.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -33,7 +33,7 @@
throw new WTypeError("<callFunction>", "Cannot resolve function call " + name + "<" + typeArguments + ">(" + argumentList + ")");
for (let i = 0; i < func.parameters.length; ++i)
func.parameters[i].ePtr.copyFrom(argumentList[i].ePtr, argumentTypes[i].size);
- let result = new Evaluator(program).runBody(func.body);
- return new TypedValue(func.returnType, result);
+ let result = new Evaluator(program).runBody(func.returnType, func.body);
+ return new TypedValue(func.returnType.unifyNode, result);
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/Checker.js (221459 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/Checker.js 2017-08-31 23:55:12 UTC (rev 221459)
+++ trunk/Tools/WebGPUShadingLanguageRI/Checker.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -123,7 +123,8 @@
visitAssignment(node)
{
- // FIXME: We need to check that the lhs is assignable.
+ if (!node.lhs.isLValue)
+ throw new WTypeError(node.origin.originString, "LHS of assignment is not an LValue: " + node.lhs);
let lhsType = node.lhs.visit(this);
let rhsType = node.rhs.visit(this);
if (!lhsType.equals(rhsType))
@@ -138,9 +139,20 @@
if (!type.isPtr)
throw new WTypeError(node.origin.originString, "Type passed to dereference is not a pointer: " + type);
node.type = type.elementType;
+ node.addressSpace = type.addressSpace;
return node.type;
}
+ visitMakePtrExpression(node)
+ {
+ if (!node.lValue.isLValue)
+ throw new WTypeError(node.origin.originString, "Operand to \\ is not an LValue: " + node.lValue);
+
+ let elementType = node.lValue.visit(this).unifyNode;
+
+ return new PtrType(node.origin, node.lValue.addressSpace, elementType);
+ }
+
visitVariableRef(node)
{
return node.variable.type;
Modified: trunk/Tools/WebGPUShadingLanguageRI/DereferenceExpression.js (221459 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/DereferenceExpression.js 2017-08-31 23:55:12 UTC (rev 221459)
+++ trunk/Tools/WebGPUShadingLanguageRI/DereferenceExpression.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -32,6 +32,7 @@
}
get ptr() { return this._ptr; }
+ get isLValue() { return true; }
toString()
{
Modified: trunk/Tools/WebGPUShadingLanguageRI/Evaluator.js (221459 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/Evaluator.js 2017-08-31 23:55:12 UTC (rev 221459)
+++ trunk/Tools/WebGPUShadingLanguageRI/Evaluator.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -32,8 +32,21 @@
this._program = program;
}
- runBody(block)
+ // You must snapshot if you use a value in rvalue context. For example, a call _expression_ will
+ // snapshot all of its arguments immedaitely upon executing them. In general, it should not be
+ // possible for a pointer returned from a visit method in rvalue context to live across any effects.
+ _snapshot(type, ptr)
{
+ let size = type.size;
+ if (!size)
+ throw new Error("Cannot get size of type: " + type);
+ let result = new EPtr(new EBuffer(size), 0);
+ result.copyFrom(ptr, size);
+ return result;
+ }
+
+ runBody(type, block)
+ {
try {
block.visit(this);
// FIXME: We should have a check that there is no way to drop out of a function without
@@ -43,7 +56,7 @@
if (e == BreakException || e == ContinueException)
throw new Error("Should not see break/continue at function scope");
if (e instanceof ReturnException)
- return e.value;
+ return this._snapshot(type, e.value);
throw e;
}
}
@@ -55,7 +68,7 @@
node.argumentList[i].visit(this),
node.parameters[i].type.size);
}
- return this.runBody(node.body);
+ return this.runBody(node.returnType, node.body);
}
visitReturn(node)
@@ -79,17 +92,14 @@
return result;
}
- _dereference(ptr, type)
+ visitDereferenceExpression(node)
{
- let size = type.size;
- let result = new EPtr(new EBuffer(size), 0);
- result.copyFrom(ptr.loadValue(), size);
- return result;
+ return node.ptr.visit(this).loadValue();
}
- visitDereferenceExpression(node)
+ visitMakePtrExpression(node)
{
- return this._dereference(node.ptr.visit(this), node.type);
+ return EPtr.box(node.lValue.visit(this));
}
visitCommaExpression(node)
@@ -97,6 +107,7 @@
let result;
for (let _expression_ of node.list)
result = _expression_.visit(this);
+ // This should almost snapshot, except that tail-returning a pointer is totally OK.
return result;
}
@@ -113,12 +124,14 @@
visitCallExpression(node)
{
// We evaluate inlined ASTs, so this can only be a native call.
- let callArguments = node.argumentList.map(argument => {
- let result = argument.visit(this);
- if (!result)
- throw new Error("Null result from " + argument);
- return result;
- });
+ let callArguments = [];
+ for (let i = 0; i < node.argumentList.length; ++i) {
+ let argument = node.argumentList[i];
+ let type = node.nativeFuncInstance.parameterTypes[i];
+ if (!type || !argument)
+ throw new Error("Cannot get type or argument; i = " + i + ", argument = " + argument + ", type = " + type + "; in " + node);
+ callArguments.push(this._snapshot(type, argument.visit(this)));
+ }
return node.func.implementation(callArguments, node);
}
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/FuncInstantiator.js (221459 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/FuncInstantiator.js 2017-08-31 23:55:12 UTC (rev 221459)
+++ trunk/Tools/WebGPUShadingLanguageRI/FuncInstantiator.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -54,12 +54,27 @@
}
let substitution = Substitution.mapping(func.typeParameters, typeArguments);
- let resultingFunc = new FuncDef(
- func.origin, func.name,
- func.returnType.visit(substitution),
- [], // We're instantiated so we no longer take type parameters.
- func.parameters.map(parameter => parameter.visit(substitution)),
- func.body.visit(substitution));
+
+ class Instantiate {
+ visitFuncDef(func)
+ {
+ return new FuncDef(
+ func.origin, func.name,
+ func.returnType.visit(substitution),
+ [], // We're instantiated so we no longer take type parameters.
+ func.parameters.map(parameter => parameter.visit(substitution)),
+ func.body.visit(substitution));
+ }
+
+ visitNativeFunc(func)
+ {
+ return new NativeFuncInstance(
+ func,
+ func.returnType.visit(substitution),
+ parameters.map(parameter => parameter.visit(substitution)));
+ }
+ }
+ let resultingFunc = func.visit(new Instantiate());
let instance = {func: resultingFunc, typeArguments};
instances.push(instance);
return resultingFunc;
Modified: trunk/Tools/WebGPUShadingLanguageRI/FunctionLikeBlock.js (221459 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/FunctionLikeBlock.js 2017-08-31 23:55:12 UTC (rev 221459)
+++ trunk/Tools/WebGPUShadingLanguageRI/FunctionLikeBlock.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -25,10 +25,11 @@
"use strict";
class FunctionLikeBlock extends Value {
- constructor(origin, argumentList, parameters, body)
+ constructor(origin, returnType, argumentList, parameters, body)
{
super();
this._origin = origin;
+ this._returnType = returnType;
this._argumentList = argumentList;
this._parameters = parameters;
this._body = body;
@@ -35,6 +36,7 @@
}
get origin() { return this._origin; }
+ get returnType() { return this._returnType; }
get argumentList() { return this._argumentList; }
get parameters() { return this._parameters; }
get body() { return this._body; }
@@ -41,6 +43,6 @@
toString()
{
- return "[&] (" + this.parameters + ") { " + this.block + " }(" + this.argumentList + ")";
+ return "([&] (" + this.parameters + ") -> " + this.returnType + " { " + this.block + " }(" + this.argumentList + "))";
}
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/Inliner.js (221459 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/Inliner.js 2017-08-31 23:55:12 UTC (rev 221459)
+++ trunk/Tools/WebGPUShadingLanguageRI/Inliner.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -34,13 +34,17 @@
visitCallExpression(node)
{
- if (node.func.isNative)
- return super.visitCallExpression(node);
return this._visiting.doVisit(node.func, () => {
let func = this._program.funcInstantiator.getUnique(node.func, node.actualTypeArguments);
+ if (func.isNative) {
+ let result = super.visitCallExpression(node);
+ result.nativeFuncInstance = func;
+ return result;
+ }
_inlineFunction(this._program, func, this._visiting);
return new FunctionLikeBlock(
node.origin,
+ func.returnType,
node.argumentList.map(argument => argument.visit(this)),
func.parameters, func.body);
});
Added: trunk/Tools/WebGPUShadingLanguageRI/MakePtrExpression.js (0 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/MakePtrExpression.js (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/MakePtrExpression.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -0,0 +1,40 @@
+/*
+ * 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 MakePtrExpression extends _expression_ {
+ constructor(origin, lValue)
+ {
+ super(origin);
+ this._lValue = lValue;
+ }
+
+ get lValue() { return this._lValue; }
+
+ toString()
+ {
+ return "\\(" + this.ptr + ")";
+ }
+}
Added: trunk/Tools/WebGPUShadingLanguageRI/NativeFuncInstance.js (0 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/NativeFuncInstance.js (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/NativeFuncInstance.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -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 NativeFuncInstance extends Func {
+ constructor(func, returnType, parameters)
+ {
+ super(func.name, returnType, [], parameters);
+ this._func = func;
+ }
+
+ get func() { return this._func; }
+
+ toString()
+ {
+ return "native " + super.toString();
+ }
+}
+
Modified: trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js (221459 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js 2017-08-31 23:55:12 UTC (rev 221459)
+++ trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -150,6 +150,11 @@
return result;
}
+ visitMakePtrExpression(node)
+ {
+ return new MakePtrExpression(node.origin, node.lValue.visit(this));
+ }
+
visitVariableRef(node)
{
node.variable = this._getMapping(node.variable);
@@ -178,6 +183,7 @@
actualTypeArguments.map(actualTypeArgument => actualTypeArgument.visit(this));
}
result.func = node.func;
+ result.nativeFuncInstance = node.nativeFuncInstance;
return result;
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.js (221459 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/Test.js 2017-08-31 23:55:12 UTC (rev 221459)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -123,6 +123,40 @@
checkInt(program, callFunction(program, "foo", [], [TypedValue.box(new PtrType(null, "device", program.intrinsics.int32), new EPtr(buffer, 0))]), 13);
}
+function TEST_dereferenceStore()
+{
+ let program = doPrep(`
+ void foo(device int^ p)
+ {
+ ^p = 52;
+ }`);
+ let buffer = new EBuffer(1);
+ buffer.set(0, 13);
+ callFunction(program, "foo", [], [TypedValue.box(new PtrType(null, "device", program.intrinsics.int32), new EPtr(buffer, 0))]);
+ if (buffer.get(0) != 52)
+ throw new Error("Expected buffer to contain 52 but it contains: " + buffer.get(0));
+}
+
+function TEST_simpleMakePtr()
+{
+ let program = doPrep(`
+ thread int^ foo()
+ {
+ int x = 42;
+ return \\x;
+ }`);
+ let result = callFunction(program, "foo", [], []);
+ if (!result.type.isPtr)
+ throw new Error("Return type is not a pointer: " + result.type);
+ if (!result.type.elementType.equals(program.intrinsics.int32))
+ throw new Error("Return type is not a pointer to an int: " + result.type);
+ if (!(result.value instanceof EPtr))
+ throw new Error("Return value is not an EPtr: " + result.value);
+ let value = result.value.loadValue();
+ if (value != 42)
+ throw new Error("Expected 42 but got: " + value);
+}
+
let before = preciseTime();
let filter = /.*/; // run everything by default
Modified: trunk/Tools/WebGPUShadingLanguageRI/Value.js (221459 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/Value.js 2017-08-31 23:55:12 UTC (rev 221459)
+++ trunk/Tools/WebGPUShadingLanguageRI/Value.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -27,5 +27,6 @@
class Value extends Node {
get kind() { return Value; }
get isConstexpr() { return false; }
+ get isLValue() { return false; }
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/VariableRef.js (221459 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/VariableRef.js 2017-08-31 23:55:12 UTC (rev 221459)
+++ trunk/Tools/WebGPUShadingLanguageRI/VariableRef.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -35,6 +35,8 @@
get name() { return this._name; }
get isConstexpr() { return this.variable.isConstexpr; }
get unifyNode() { return this.variable.unifyNode; }
+ get isLValue() { return true; }
+ get addressSpace() { return "thread"; }
toString()
{
Modified: trunk/Tools/WebGPUShadingLanguageRI/Visitor.js (221459 => 221460)
--- trunk/Tools/WebGPUShadingLanguageRI/Visitor.js 2017-08-31 23:55:12 UTC (rev 221459)
+++ trunk/Tools/WebGPUShadingLanguageRI/Visitor.js 2017-09-01 00:09:14 UTC (rev 221460)
@@ -158,6 +158,11 @@
node.ptr.visit(this);
}
+ visitMakePtrExpression(node)
+ {
+ node.lValue.visit(this);
+ }
+
visitVariableRef(node)
{
}
@@ -178,6 +183,11 @@
typeArgument.visit(this);
for (let argument of node.argumentList)
argument.visit(this);
+ let actualTypeArguments = node.actualTypeArguments;
+ if (actualTypeArguments) {
+ for (let argument of actualTypeArguments)
+ argument.visit(this);
+ }
}
visitFunctionLikeBlock(node)