Diff
Modified: trunk/Tools/ChangeLog (222115 => 222116)
--- trunk/Tools/ChangeLog 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/ChangeLog 2017-09-15 23:44:35 UTC (rev 222116)
@@ -1,5 +1,95 @@
2017-09-14 Filip Pizlo <[email protected]>
+ Rationalize how WSL's operator&[] works
+ https://bugs.webkit.org/show_bug.cgi?id=176958
+
+ Reviewed by Myles Maxfield.
+
+ This makes operator&[] work with non-array-ref types. The way this works is that if you do base[index]
+ then we pattern match base's type and proceed accordingly:
+
+ If base's type is T^:
+ => Reject
+
+ If base's type is T[]:
+ => Accept
+
+ If base's type is T[c]:
+ => Wrap it with a MakeArrayRefExpression and accept.
+
+ All other cases:
+ => Wrap it with a MakePtrExpression and accept.
+
+ This makes it possible for operator&[] to work with lvalues. It also means that operator&[] gets to
+ "see" the temporary values we create via snapshot() in the interpreter. We'll have to fix that, and I've
+ filed bug 176973 for that. Once that's fixed, this will have well-defined behavior, though with the very
+ peculiar caveat that an _expression_ like this:
+
+ totallyNotAnLValue()[42]
+
+ Could be used to get a pointer to a non-lvalue. But we can be extremely precise about what that means
+ and prohibit dangling pointers, which is kinda crazy.
+
+ In order to do this, I had to make MakeArrayRefExpression work, so I did that and added tests for it.
+
+ * WebGPUShadingLanguageRI/All.js:
+ * WebGPUShadingLanguageRI/ArrayRefType.js:
+ (ArrayRefType.prototype.unifyImpl):
+ (ArrayRefType.prototype.toString):
+ (ArrayRefType):
+ * WebGPUShadingLanguageRI/ArrayType.js:
+ (ArrayType):
+ (ArrayType.prototype.get numElementsValue):
+ (ArrayType.prototype.get size):
+ (ArrayType.prototype.populateDefaultValue):
+ (ArrayType.prototype.unifyImpl):
+ * WebGPUShadingLanguageRI/Checker.js:
+ * WebGPUShadingLanguageRI/ConvertPtrToArrayRefExpression.js: Added.
+ (ConvertPtrToArrayRefExpression):
+ (ConvertPtrToArrayRefExpression.prototype.get lValue):
+ (ConvertPtrToArrayRefExpression.prototype.toString):
+ * WebGPUShadingLanguageRI/CreateLiteral.js:
+ (createLiteral.GenericLiteral.withType):
+ (createLiteral.GenericLiteral.prototype.get isLiteral):
+ (createLiteral.GenericLiteral.prototype.unifyImpl):
+ * WebGPUShadingLanguageRI/DotExpression.js:
+ (DotExpression.prototype.get addressSpace):
+ * WebGPUShadingLanguageRI/Evaluator.js:
+ (Evaluator.prototype.visitMakeArrayRefExpression):
+ (Evaluator.prototype.visitConvertPtrToArrayRefExpression):
+ * WebGPUShadingLanguageRI/Intrinsics.js:
+ (Intrinsics):
+ * WebGPUShadingLanguageRI/MakeArrayRefExpression.js: Added.
+ (MakeArrayRefExpression):
+ (MakeArrayRefExpression.prototype.get lValue):
+ (MakeArrayRefExpression.prototype.becomeConvertPtrToArrayRefExpression):
+ (MakeArrayRefExpression.prototype.toString):
+ * WebGPUShadingLanguageRI/MakePtrExpression.js:
+ (MakePtrExpression.prototype.toString):
+ (MakePtrExpression):
+ * WebGPUShadingLanguageRI/PtrType.js:
+ (PtrType.prototype.toString):
+ (PtrType):
+ * WebGPUShadingLanguageRI/ReferenceType.js:
+ (ReferenceType):
+ * WebGPUShadingLanguageRI/Rewriter.js:
+ (Rewriter.prototype.visitArrayType):
+ (Rewriter.prototype.visitMakeArrayRefExpression):
+ (Rewriter.prototype.visitConvertPtrToArrayRefExpression):
+ * WebGPUShadingLanguageRI/StandardLibrary.js:
+ * WebGPUShadingLanguageRI/Test.html:
+ * WebGPUShadingLanguageRI/Test.js:
+ (TEST_buildArrayThenSumItUsingArrayReference):
+ (TEST_overrideSubscriptStruct):
+ (TEST_overrideSubscriptStructAndUsePointers):
+ (TEST_overrideSubscriptStructAndUsePointersIncorrectly):
+ (TEST_makeArrayRefFromPointer):
+ (TEST_makeArrayRefFromArrayRef):
+ * WebGPUShadingLanguageRI/Visitor.js:
+ (Visitor.prototype.visitProtocolDecl):
+
+2017-09-14 Filip Pizlo <[email protected]>
+
WSL should support ++, --, +=, and all of those things
https://bugs.webkit.org/show_bug.cgi?id=176975
Modified: trunk/Tools/WebGPUShadingLanguageRI/All.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/All.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/All.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -57,6 +57,7 @@
load("CommaExpression.js");
load("ConstexprTypeParameter.js");
load("Continue.js");
+load("ConvertPtrToArrayRefExpression.js");
load("DereferenceExpression.js");
load("DoWhileLoop.js");
load("DotExpression.js");
@@ -89,6 +90,7 @@
load("LiteralTypeChecker.js");
load("LogicalNot.js");
load("LoopChecker.js");
+load("MakeArrayRefExpression.js");
load("MakePtrExpression.js");
load("NameContext.js");
load("NameResolver.js");
Modified: trunk/Tools/WebGPUShadingLanguageRI/ArrayRefType.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/ArrayRefType.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/ArrayRefType.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -29,15 +29,12 @@
class ArrayRefType extends ReferenceType {
unifyImpl(unificationContext, other)
{
- if (other instanceof ArrayRefType) {
- if (this.addressSpace != other.addressSpace)
- return false;
- } else {
- if (!(other instanceof ArrayType))
- return false;
- if (this.addressSpace != "thread")
- return false;
- }
+ if (!(other instanceof ArrayRefType))
+ return false;
+
+ if (this.addressSpace != other.addressSpace)
+ return false;
+
return this.elementType.unify(unificationContext, other.elementType);
}
@@ -45,7 +42,7 @@
toString()
{
- return this.addressSpace + " " + this.elementType + "[]";
+ return this.elementType + "[] " + this.addressSpace;
}
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/ArrayType.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/ArrayType.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/ArrayType.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -27,6 +27,8 @@
class ArrayType extends Type {
constructor(origin, elementType, numElements)
{
+ if (!numElements)
+ throw new Error("null numElements");
super();
this._origin = origin;
this._elementType = elementType;
@@ -38,6 +40,13 @@
get numElements() { return this._numElements; }
get isPrimitive() { return this.elementType.isPrimitive; }
+ get numElementsValue()
+ {
+ if (!(this.numElements.isLiteral))
+ throw new Error("numElements is not a literal: " + this.numElements);
+ return this.numElements.value;
+ }
+
toString()
{
return this.elementType + "[" + this.numElements + "]";
@@ -45,22 +54,23 @@
get size()
{
- return this.elementType.size * this.numElements;
+ return this.elementType.size * this.numElementsValue;
}
- unifyImpl(unificatonContext, other)
+ populateDefaultValue(buffer, offset)
{
- if (other instanceof ArrayRefType) {
- if (other.addressSpace != "thread")
- return false;
- } else {
- if (!(other instanceof ArrayType))
- return false;
-
- if (!this.numElements.unify(unificationContext, other.numElements))
- return false;
- }
+ for (let i = 0; i < this.numElementsValue; ++i)
+ this.elementType.populateDefaultValue(buffer, offset + i * this.elementType.size);
+ }
+
+ unifyImpl(unificationContext, other)
+ {
+ if (!(other instanceof ArrayType))
+ return false;
+ if (!this.numElements.unify(unificationContext, other.numElements))
+ return false;
+
return this.elementType.unify(unificationContext, other.elementType);
}
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/Checker.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/Checker.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/Checker.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -107,8 +107,15 @@
visitArrayType(node)
{
+ node.elementType.visit(this);
+
if (!node.numElements.isConstexpr)
throw new WTypeError(node.origin.originString, "Array length must be constexpr");
+
+ let type = node.numElements.visit(this);
+
+ if (!type.equalsWithCommit(this._program.intrinsics.uint32))
+ throw new WTypeError(node.origin.originString, "Array length must be a uint32");
}
visitVariableDecl(node)
@@ -147,7 +154,7 @@
visitMakePtrExpression(node)
{
if (!node.lValue.isLValue)
- throw new WTypeError(node.origin.originString, "Operand to \\ is not an LValue: " + node.lValue);
+ throw new WTypeError(node.origin.originString, "Operand to & is not an LValue: " + node.lValue);
let elementType = node.lValue.visit(this).unifyNode;
@@ -154,6 +161,34 @@
return new PtrType(node.origin, node.lValue.addressSpace, elementType);
}
+ visitMakeArrayRefExpression(node)
+ {
+ let elementType = node.lValue.visit(this).unifyNode;
+ if (elementType instanceof PtrType) {
+ node.becomeConvertPtrToArrayRefExpression();
+ return new ArrayRefType(node.origin, elementType.addressSpace, elementType.elementType);
+ }
+
+ if (!node.lValue.isLValue)
+ throw new WTypeError(node.origin.originString, "Operand to @ is not an LValue: " + node.lValue);
+
+ if (elementType instanceof ArrayRefType)
+ throw new WTypeError(node.origin.originStrimg, "Operand to @ is an array reference: " + elementType);
+
+ if (elementType instanceof ArrayType) {
+ node.numElements = elementType.numElements;
+ elementType = elementType.elementType;
+ } else
+ node.numElements = UintLiteral.withType(node.origin, 1, this._program.intrinsics.uint32);
+
+ return new ArrayRefType(node.origin, node.lValue.addressSpace, elementType);
+ }
+
+ visitConvertToArrayRefExpression(node)
+ {
+ throw new Error("Should not exist yet.");
+ }
+
visitDotExpression(node)
{
let structType = node.struct.visit(this).unifyNode;
@@ -297,6 +332,24 @@
throw new Error("visitor returned null for " + argument);
return TypeRef.wrap(newArgument);
});
+
+ // Here we need to handle the cases where operator&[] is called with a type that isn't sufficiently
+ // referencey.
+ if (node.name == "operator&[]") {
+ let argType = argumentTypes[0].unifyNode;
+ if (argType instanceof PtrType)
+ throw new WTypeError(node.origin.originString, "Pointer subscript is not valid");
+
+ if (argType instanceof ArrayType) {
+ node.argumentList[0] = new MakeArrayRefExpression(node.origin, node.argumentList[0]);
+ node.argumentList[0].numElements = argType.numElements;
+ argumentTypes[0] = new ArrayRefType(node.origin, "thread", argType.elementType);
+ } else if (!(argType instanceof ArrayRefType)) {
+ node.argumentList[0] = new MakePtrExpression(node.origin, node.argumentList[0]);
+ argumentTypes[0] = new PtrType(node.origin, "thread", argumentTypes[0]);
+ }
+ }
+
node.argumentTypes = argumentTypes;
if (node.returnType)
node.returnType.visit(this);
Added: trunk/Tools/WebGPUShadingLanguageRI/ConvertPtrToArrayRefExpression.js (0 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/ConvertPtrToArrayRefExpression.js (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/ConvertPtrToArrayRefExpression.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -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 ConvertPtrToArrayRefExpression extends _expression_ {
+ constructor(origin, lValue)
+ {
+ super(origin);
+ this._lValue = lValue;
+ }
+
+ get lValue() { return this._lValue; }
+
+ toString()
+ {
+ return "@(" + this.lValue + ")";
+ }
+}
+
Modified: trunk/Tools/WebGPUShadingLanguageRI/CreateLiteral.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/CreateLiteral.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/CreateLiteral.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -34,9 +34,24 @@
this.type = config.createType.call(this, origin, value);
}
+ static withType(origin, value, type)
+ {
+ let result = new GenericLiteral(origin, value);
+ result.type = TypeRef.wrap(type);
+ return result;
+ }
+
get value() { return this._value; }
get isConstexpr() { return true; }
+ get isLiteral() { return true; }
+ unifyImpl(unificationContext, other)
+ {
+ if (!(other instanceof GenericLiteral))
+ return false;
+ return this.value == other.value;
+ }
+
toString()
{
return config.preferredTypeName + "Literal<" + this.value + ">";
Modified: trunk/Tools/WebGPUShadingLanguageRI/DotExpression.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/DotExpression.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/DotExpression.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -35,6 +35,7 @@
get struct() { return this._struct; }
get fieldName() { return this._fieldName; }
get isLValue() { return this.struct.isLValue; }
+ get addressSpace() { return this.struct.addressSpace; }
toString()
{
Modified: trunk/Tools/WebGPUShadingLanguageRI/Evaluator.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/Evaluator.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/Evaluator.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -106,6 +106,16 @@
return EPtr.box(node.lValue.visit(this));
}
+ visitMakeArrayRefExpression(node)
+ {
+ return EPtr.box(new EArrayRef(node.lValue.visit(this), node.numElements.visit(this).loadValue()));
+ }
+
+ visitConvertPtrToArrayRefExpression(node)
+ {
+ return EPtr.box(new EArrayRef(node.lValue.visit(this).loadValue(), 1));
+ }
+
visitDotExpression(node)
{
let structPtr = node.struct.visit(this);
Modified: trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -104,6 +104,18 @@
});
this._map.set(
+ "native operator int32<>(uint32)",
+ func => {
+ func.implementation = ([value]) => EPtr.box(value.loadValue() | 0);
+ });
+
+ this._map.set(
+ "native operator uint32<>(int32)",
+ func => {
+ func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
+ });
+
+ this._map.set(
"native int operator+<>(int,int)",
func => {
func.implementation = ([left, right]) =>
@@ -249,16 +261,16 @@
};
this._map.set(
- "native thread T^ operator&[]<T>(thread T[],uint)",
+ "native T^ thread operator&[]<T>(T[] thread,uint)",
arrayElementPtr);
this._map.set(
- "native threadgroup T^ operator&[]<T:primitive>(threadgroup T[],uint)",
+ "native T^ threadgroup operator&[]<T:primitive>(T[] threadgroup,uint)",
arrayElementPtr);
this._map.set(
- "native device T^ operator&[]<T:primitive>(device T[],uint)",
+ "native T^ device operator&[]<T:primitive>(T[] device,uint)",
arrayElementPtr);
this._map.set(
- "native constant T^ operator&[]<T:primitive>(constant T[],uint)",
+ "native T^ constant operator&[]<T:primitive>(T[] constant,uint)",
arrayElementPtr);
}
Added: trunk/Tools/WebGPUShadingLanguageRI/MakeArrayRefExpression.js (0 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/MakeArrayRefExpression.js (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/MakeArrayRefExpression.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -0,0 +1,46 @@
+/*
+ * 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 MakeArrayRefExpression extends _expression_ {
+ constructor(origin, lValue)
+ {
+ super(origin);
+ this._lValue = lValue;
+ }
+
+ get lValue() { return this._lValue; }
+
+ becomeConvertPtrToArrayRefExpression()
+ {
+ this.__proto__ = ConvertPtrToArrayRefExpression.prototype;
+ }
+
+ toString()
+ {
+ return "@" + (this.numElements ? "<<" + this.numElements + ">>" : "") + "(" + this.lValue + ")";
+ }
+}
+
Modified: trunk/Tools/WebGPUShadingLanguageRI/MakePtrExpression.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/MakePtrExpression.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/MakePtrExpression.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -35,6 +35,6 @@
toString()
{
- return "&(" + this.ptr + ")";
+ return "&(" + this.lValue + ")";
}
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/PtrType.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/PtrType.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/PtrType.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -38,7 +38,7 @@
toString()
{
- return this.addressSpace + " " + this.elementType + "^";
+ return this.elementType + "^ " + this.addressSpace;
}
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/ReferenceType.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/ReferenceType.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/ReferenceType.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -27,6 +27,8 @@
class ReferenceType extends Type {
constructor(origin, addressSpace, elementType)
{
+ if (!elementType)
+ throw new Error("Null elementType");
super();
validateAddressSpace(addressSpace);
this._origin = origin;
Modified: trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -157,7 +157,7 @@
visitArrayType(node)
{
- return new ArrayType(node.origin, node.elementType.visit(this));
+ return new ArrayType(node.origin, node.elementType.visit(this), node.numElements.visit(this));
}
visitAssignment(node)
@@ -189,6 +189,19 @@
return new MakePtrExpression(node.origin, node.lValue.visit(this));
}
+ visitMakeArrayRefExpression(node)
+ {
+ let result = new MakeArrayRefExpression(node.origin, node.lValue.visit(this));
+ if (node.numElements)
+ result.numElements = node.numElements.visit(this);
+ return result;
+ }
+
+ visitConvertPtrToArrayRefExpression(node)
+ {
+ return new ConvertPtrToArrayRefExpression(node.origin, node.lValue.visit(this));
+ }
+
visitVariableRef(node)
{
let result = new VariableRef(node.origin, node.name);
Modified: trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -41,6 +41,9 @@
native primitive typedef double;
+native operator int32(uint32);
+native operator uint32(int32);
+
native int operator+(int, int);
native uint operator+(uint, uint);
int operator++(int value) { return value + 1; }
Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.html (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/Test.html 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.html 2017-09-15 23:44:35 UTC (rev 222116)
@@ -34,6 +34,7 @@
<script src=""
<script src=""
<script src=""
+<script src=""
<script src=""
<script src=""
<script src=""
@@ -66,6 +67,7 @@
<script src=""
<script src=""
<script src=""
+<script src=""
<script src=""
<script src=""
<script src=""
Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/Test.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -2358,6 +2358,214 @@
(e) => e instanceof WTypeError && e.message.indexOf("Type mismatch in variable initialization") != -1);
}
+function TEST_buildArrayThenSumIt()
+{
+ let program = doPrep(`
+ int foo()
+ {
+ int[42] array;
+ for (uint i = 0; i < 42; i = i + 1)
+ array[i] = int(i + 5);
+ int result;
+ for (uint i = 0; i < 42; i = i + 1)
+ result = result + array[i];
+ return result;
+ }
+ `);
+ checkInt(program, callFunction(program, "foo", [], []), 42 * 5 + 42 * 41 / 2);
+}
+
+function TEST_buildArrayThenSumItUsingArrayReference()
+{
+ let program = doPrep(`
+ int bar(thread int[] array)
+ {
+ for (uint i = 0; i < 42; i = i + 1)
+ array[i] = int(i + 5);
+ int result;
+ for (uint i = 0; i < 42; i = i + 1)
+ result = result + array[i];
+ return result;
+ }
+ int foo()
+ {
+ int[42] array;
+ return bar(@array);
+ }
+ `);
+ checkInt(program, callFunction(program, "foo", [], []), 42 * 5 + 42 * 41 / 2);
+}
+
+function TEST_overrideSubscriptStruct()
+{
+ let program = doPrep(`
+ struct Foo {
+ int x;
+ int y;
+ }
+ thread int^ operator&[](thread Foo^ foo, uint index)
+ {
+ if (index == 0)
+ return &foo->x;
+ if (index == 1)
+ return &foo->y;
+ return null;
+ }
+ int foo()
+ {
+ Foo foo;
+ foo.x = 498;
+ foo.y = 19;
+ return foo[0] + foo[1] * 3;
+ }
+ `);
+ checkInt(program, callFunction(program, "foo", [], []), 498 + 19 * 3);
+}
+
+function TEST_overrideSubscriptStructAndDoStores()
+{
+ let program = doPrep(`
+ struct Foo {
+ int x;
+ int y;
+ }
+ thread int^ operator&[](thread Foo^ foo, uint index)
+ {
+ if (index == 0)
+ return &foo->x;
+ if (index == 1)
+ return &foo->y;
+ return null;
+ }
+ int foo()
+ {
+ Foo foo;
+ foo[0] = 498;
+ foo[1] = 19;
+ return foo.x + foo.y;
+ }
+ `);
+ checkInt(program, callFunction(program, "foo", [], []), 498 + 19);
+}
+
+function TEST_overrideSubscriptStructAndUsePointers()
+{
+ let program = doPrep(`
+ struct Foo {
+ int x;
+ int y;
+ }
+ thread int^ operator&[](thread Foo^ foo, uint index)
+ {
+ if (index == 0)
+ return &foo->x;
+ if (index == 1)
+ return &foo->y;
+ return null;
+ }
+ int bar(thread Foo^ foo)
+ {
+ return (^foo)[0] + (^foo)[1];
+ }
+ int foo()
+ {
+ Foo foo;
+ foo.x = 498;
+ foo.y = 19;
+ return bar(&foo);
+ }
+ `);
+ checkInt(program, callFunction(program, "foo", [], []), 498 + 19);
+}
+
+function TEST_overrideSubscriptStructAndUsePointersIncorrectly()
+{
+ checkFail(
+ () => doPrep(`
+ struct Foo {
+ int x;
+ int y;
+ }
+ thread int^ operator&[](thread Foo^ foo, uint index)
+ {
+ if (index == 0)
+ return &foo->x;
+ if (index == 1)
+ return &foo->y;
+ return null;
+ }
+ int bar(thread Foo^ foo)
+ {
+ return foo[0] + foo[1];
+ }
+ int foo()
+ {
+ Foo foo;
+ foo.x = 498;
+ foo.y = 19;
+ return bar(&foo);
+ }
+ `),
+ (e) => e instanceof WTypeError);
+}
+
+function TEST_makeArrayRefFromLocal()
+{
+ let program = doPrep(`
+ int bar(thread int[] ref)
+ {
+ return ref[0];
+ }
+ int foo()
+ {
+ int x = 48;
+ return bar(@x);
+ }
+ `);
+ checkInt(program, callFunction(program, "foo", [], []), 48);
+}
+
+function TEST_makeArrayRefFromPointer()
+{
+ let program = doPrep(`
+ int bar(thread int[] ref)
+ {
+ return ref[0];
+ }
+ int baz(thread int^ ptr)
+ {
+ return bar(@ptr);
+ }
+ int foo()
+ {
+ int x = 48;
+ return baz(&x);
+ }
+ `);
+ checkInt(program, callFunction(program, "foo", [], []), 48);
+}
+
+function TEST_makeArrayRefFromArrayRef()
+{
+ checkFail(
+ () => doPrep(`
+ int bar(thread int[] ref)
+ {
+ return ref[0];
+ }
+ int baz(thread int[] ptr)
+ {
+ return bar(@ptr);
+ }
+ int foo()
+ {
+ int x = 48;
+ return baz(@x);
+ }
+ `),
+ (e) => e instanceof WTypeError);
+}
+
let filter = /.*/; // run everything by default
if (this["arguments"]) {
for (let i = 0; i < arguments.length; i++) {
Modified: trunk/Tools/WebGPUShadingLanguageRI/Visitor.js (222115 => 222116)
--- trunk/Tools/WebGPUShadingLanguageRI/Visitor.js 2017-09-15 23:27:56 UTC (rev 222115)
+++ trunk/Tools/WebGPUShadingLanguageRI/Visitor.js 2017-09-15 23:44:35 UTC (rev 222116)
@@ -204,6 +204,18 @@
node.lValue.visit(this);
}
+ visitMakeArrayRefExpression(node)
+ {
+ node.lValue.visit(this);
+ if (node.numElements)
+ node.numElements.visit(this);
+ }
+
+ visitConvertPtrToArrayRefExpression(node)
+ {
+ node.lValue.visit(this);
+ }
+
visitVariableRef(node)
{
}