Minor changes to the WHLSL interpreter to support the new compiler
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Jul 2018 23:08:26 +0000 (23:08 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Jul 2018 23:08:26 +0000 (23:08 +0000)
https://bugs.webkit.org/show_bug.cgi?id=187728

Patch by Thomas Denney <tdenney@apple.com> on 2018-07-24
Reviewed by Myles C. Maxfield.

This bug contains small changes that are make minor changes to the
behaviour of the existing interpreter (the tests are unaffected and all
still pass).

* WebGPUShadingLanguageRI/EnumType.js:
(EnumType.prototype.get isEnum): Property added to EnumType and Type
* WebGPUShadingLanguageRI/Evaluator.js: Correct typo
* WebGPUShadingLanguageRI/Func.js:
(Func.prototype.get isEntryPoint): Add boolean property
* WebGPUShadingLanguageRI/FuncInstantiator.js:
(FuncInstantiator.prototype.get instances): Public accessor for existing
private field
* WebGPUShadingLanguageRI/FunctionLikeBlock.js: Refactored the class so
that it directly wraps a Func instance (therefore the only interface
change is to the constructor and the addition of the func accessor).
This change allows the de-inlining of functions.
(FunctionLikeBlock):
(FunctionLikeBlock.prototype.get func):
(FunctionLikeBlock.prototype.get returnType):
(FunctionLikeBlock.prototype.get parameters):
(FunctionLikeBlock.prototype.get body):
* WebGPUShadingLanguageRI/Inliner.js: Use the new FunctionLikeBlock
constructor
(Inliner.prototype.visitCallExpression):
(Inliner):
* WebGPUShadingLanguageRI/Intrinsics.js: Migrate the swizzle operators
to native functions (with additional support in StandardLibrary.js).
This reduces first-time compile-time from around 4s to around 0.1s.
(Intrinsics):
* WebGPUShadingLanguageRI/Lexer.js: Ensure that the parsing of multiline
comments completes correctly
(Lexer.prototype.next):
(Lexer):
* WebGPUShadingLanguageRI/MakeArrayRefExpression.js: Addition of type
property, which is based on the type of the lValue and the semantics of
the language (the @ operator yields an array reference with the thread
scope).
(MakeArrayRefExpression):
(MakeArrayRefExpression.prototype.get type):
* WebGPUShadingLanguageRI/NativeFunc.js: Add setter/getter for
implementationData to support swizzle operator change
(NativeFunc.prototype.get implementationData):
(NativeFunc.prototype.set implementationData):
* WebGPUShadingLanguageRI/Rewriter.js: Use new FunctionLikeBlock
constructor
(Rewriter.prototype.visitFunctionLikeBlock):
* WebGPUShadingLanguageRI/StandardLibrary.js:
(_generateSwizzle): Deleted.
* WebGPUShadingLanguageRI/SwizzleOp.js: Introduces a new class for
carrying metadata about swizzle operators so that they are implemented
as native functions rather than generated at compile time.
(SwizzleOp):
(SwizzleOp.prototype.get outSize):
(SwizzleOp.prototype.get components):
(SwizzleOp.prototype.get inSize):
(SwizzleOp.prototype.toString):
(SwizzleOp.allSwizzleOperators.):
(SwizzleOp.allSwizzleOperators):
* WebGPUShadingLanguageRI/StandardLibrary.js: +        (SwizzleOp):
(SwizzleOp.prototype.get outSize):
(SwizzleOp.prototype.get components):
(SwizzleOp.prototype.get inSize):
(SwizzleOp.prototype.toString):
(generateSwizzles):
(_generateSwizzle): Deleted.
* WebGPUShadingLanguageRI/Type.js: Addition of isEnum property, as
above.
(Type.prototype.get isEnum):

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

19 files changed:
Tools/ChangeLog
Tools/WebGPUShadingLanguageRI/EnumType.js
Tools/WebGPUShadingLanguageRI/Evaluator.js
Tools/WebGPUShadingLanguageRI/Func.js
Tools/WebGPUShadingLanguageRI/FuncInstantiator.js
Tools/WebGPUShadingLanguageRI/FunctionLikeBlock.js
Tools/WebGPUShadingLanguageRI/Inliner.js
Tools/WebGPUShadingLanguageRI/Intrinsics.js
Tools/WebGPUShadingLanguageRI/Lexer.js
Tools/WebGPUShadingLanguageRI/MakeArrayRefExpression.js
Tools/WebGPUShadingLanguageRI/NativeFunc.js
Tools/WebGPUShadingLanguageRI/Rewriter.js
Tools/WebGPUShadingLanguageRI/SPIRV.html
Tools/WebGPUShadingLanguageRI/StandardLibrary.js
Tools/WebGPUShadingLanguageRI/SwizzleOp.js [new file with mode: 0644]
Tools/WebGPUShadingLanguageRI/Test.html
Tools/WebGPUShadingLanguageRI/Test.js
Tools/WebGPUShadingLanguageRI/Type.js
Tools/WebGPUShadingLanguageRI/index.html

index 5b4a895..ff459c4 100644 (file)
@@ -1,3 +1,78 @@
+2018-07-24  Thomas Denney  <tdenney@apple.com>
+        Minor changes to the WHLSL interpreter to support the new compiler
+        https://bugs.webkit.org/show_bug.cgi?id=187728
+
+        Reviewed by Myles C. Maxfield.
+
+        This bug contains small changes that are make minor changes to the
+        behaviour of the existing interpreter (the tests are unaffected and all
+        still pass).
+
+        * WebGPUShadingLanguageRI/EnumType.js:
+        (EnumType.prototype.get isEnum): Property added to EnumType and Type
+        * WebGPUShadingLanguageRI/Evaluator.js: Correct typo
+        * WebGPUShadingLanguageRI/Func.js:
+        (Func.prototype.get isEntryPoint): Add boolean property
+        * WebGPUShadingLanguageRI/FuncInstantiator.js:
+        (FuncInstantiator.prototype.get instances): Public accessor for existing
+        private field
+        * WebGPUShadingLanguageRI/FunctionLikeBlock.js: Refactored the class so
+        that it directly wraps a Func instance (therefore the only interface
+        change is to the constructor and the addition of the func accessor).
+        This change allows the de-inlining of functions.
+        (FunctionLikeBlock):
+        (FunctionLikeBlock.prototype.get func):
+        (FunctionLikeBlock.prototype.get returnType):
+        (FunctionLikeBlock.prototype.get parameters):
+        (FunctionLikeBlock.prototype.get body):
+        * WebGPUShadingLanguageRI/Inliner.js: Use the new FunctionLikeBlock
+        constructor
+        (Inliner.prototype.visitCallExpression):
+        (Inliner):
+        * WebGPUShadingLanguageRI/Intrinsics.js: Migrate the swizzle operators
+        to native functions (with additional support in StandardLibrary.js).
+        This reduces first-time compile-time from around 4s to around 0.1s.
+        (Intrinsics):
+        * WebGPUShadingLanguageRI/Lexer.js: Ensure that the parsing of multiline
+        comments completes correctly
+        (Lexer.prototype.next):
+        (Lexer):
+        * WebGPUShadingLanguageRI/MakeArrayRefExpression.js: Addition of type
+        property, which is based on the type of the lValue and the semantics of
+        the language (the @ operator yields an array reference with the thread
+        scope).
+        (MakeArrayRefExpression):
+        (MakeArrayRefExpression.prototype.get type):
+        * WebGPUShadingLanguageRI/NativeFunc.js: Add setter/getter for
+        implementationData to support swizzle operator change
+        (NativeFunc.prototype.get implementationData):
+        (NativeFunc.prototype.set implementationData):
+        * WebGPUShadingLanguageRI/Rewriter.js: Use new FunctionLikeBlock
+        constructor
+        (Rewriter.prototype.visitFunctionLikeBlock):
+        * WebGPUShadingLanguageRI/StandardLibrary.js:
+        (_generateSwizzle): Deleted.
+        * WebGPUShadingLanguageRI/SwizzleOp.js: Introduces a new class for
+        carrying metadata about swizzle operators so that they are implemented
+        as native functions rather than generated at compile time.
+        (SwizzleOp):
+        (SwizzleOp.prototype.get outSize):
+        (SwizzleOp.prototype.get components):
+        (SwizzleOp.prototype.get inSize):
+        (SwizzleOp.prototype.toString):
+        (SwizzleOp.allSwizzleOperators.):
+        (SwizzleOp.allSwizzleOperators):
+        * WebGPUShadingLanguageRI/StandardLibrary.js: +        (SwizzleOp):
+        (SwizzleOp.prototype.get outSize):
+        (SwizzleOp.prototype.get components):
+        (SwizzleOp.prototype.get inSize):
+        (SwizzleOp.prototype.toString):
+        (generateSwizzles):
+        (_generateSwizzle): Deleted.
+        * WebGPUShadingLanguageRI/Type.js: Addition of isEnum property, as
+        above.
+        (Type.prototype.get isEnum):
+
 2018-07-24  Ryan Haddad  <ryanhaddad@apple.com>
 
         Unreviewed, rolling out r234121.
index 9d7b368..c4a1551 100644 (file)
@@ -45,6 +45,7 @@ class EnumType extends Type {
     get origin() { return this._origin; }
     get name() { return this._name; }
     get baseType() { return this._baseType; }
+    get isEnum() { return true; }
     
     get memberNames() { return this._members.keys(); }
     memberByName(name) { return this._members.get(name); }
index 42d0185..58ced89 100644 (file)
@@ -33,7 +33,7 @@ class Evaluator extends Visitor {
     }
     
     // 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
+    // snapshot all of its arguments immediately 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, dstPtr, srcPtr)
     {
index 47f232f..6fa7c9d 100644 (file)
@@ -54,6 +54,7 @@ class Func extends Node {
     get parameterTypes() { return this.parameters.map(parameter => parameter.type); }
     get isCast() { return this._isCast; }
     get shaderType() { return this._shaderType; }
+    get isEntryPoint() { return this.shaderType != null; }
     get returnTypeForOverloadResolution() { return this.isCast ? this.returnType : null; }
     
     get kind() { return Func; }
index 3ba34f6..892862a 100644 (file)
@@ -31,6 +31,8 @@ class FuncInstantiator {
         this._instances = new Map();
     }
     
+    get instances() { return this._instances; }
+    
     // Returns a Func object that uniquely identifies a particular system of type arguments. You must
     // intantiate things with concrete types, because this code casually assumes this. Note that this
     // will return a different func from `func` no matter what. This ensures that we can use the
index 0450054..40f995e 100644 (file)
 "use strict";
 
 class FunctionLikeBlock extends Value {
-    constructor(origin, returnType, argumentList, parameters, body)
+    constructor(origin, func, argumentList)
     {
         super();
         this._origin = origin;
-        this._returnType = returnType;
+        this._func = func;
         this._argumentList = argumentList;
-        this._parameters = parameters;
-        this._body = body;
     }
     
     get origin() { return this._origin; }
-    get returnType() { return this._returnType; }
+    get func() { return this._func; }
+    get returnType() { return this.func._returnType; }
     get argumentList() { return this._argumentList; }
-    get parameters() { return this._parameters; }
-    get body() { return this._body; }
+    get parameters() { return this.func._parameters; }
+    get body() { return this.func._body; }
     
     toString()
     {
index 8012e32..491ef3e 100644 (file)
@@ -42,8 +42,7 @@ class Inliner extends Rewriter {
             if (func.isNative)
                 throw new Error("Unexpected native func: " + func);
             _inlineFunction(this._program, func, this._visiting);
-            let resultingBlock = new FunctionLikeBlock(
-                result.origin, func.returnType, result.argumentList, func.parameters, func.body);
+            let resultingBlock = new FunctionLikeBlock(result.origin, func, result.argumentList);
             resultingBlock.returnEPtr = result.resultEPtr;
             return resultingBlock;
         });
index 43003aa..b1d9311 100644 (file)
@@ -30,7 +30,7 @@ class Intrinsics {
         this._map = new Map();
 
         // NOTE: Intrinsic resolution happens before type name resolution, so the strings we use here
-        // to catch the intrinsics must be based on the type names that StandardLibraryPrologue.js uses.
+        // to catch the intrinsics must be based on the type names that StandardLibrary.js uses.
         // For example, if a native function is declared using "int" rather than "int32", then we must
         // use "int" here, since we don't yet know that they are the same type.
         
@@ -654,6 +654,23 @@ class Intrinsics {
                     };
                 });
         }
+
+        for (let swizzle of SwizzleOp.allSwizzleOperators()) {
+            this._map.set(swizzle.toString(), 
+            func => {
+                func.implementation = ([vec], node) => {
+                    const outputBuffer = new EBuffer(swizzle.outSize);
+                    const readIndices = { 'x': 0, 'y': 1, 'z': 2, 'w': 3 };
+                    for (let i = 0; i < swizzle.outSize; i++)
+                        outputBuffer.set(i, vec.get(readIndices[swizzle.components[i]]));
+                    
+                    
+                    return new EPtr(outputBuffer, 0);
+                },
+                func.implementationData = swizzle;
+            });
+            console.log(swizzle.toString());
+        }
     }
     
     add(thing)
index ba30359..be2165d 100644 (file)
@@ -103,7 +103,7 @@ class Lexer {
                 let endIndex = relevantText.search(/\*\//);
                 if (endIndex < 0)
                     this.fail("Unterminated comment");
-                this._index += endIndex;
+                this._index += endIndex + 2;
                 continue;
             }
             if (/^\/\/.*/.test(relevantText)) {
index c061876..0cc6f6e 100644 (file)
@@ -29,10 +29,14 @@ class MakeArrayRefExpression extends Expression {
     {
         super(origin);
         this._lValue = lValue;
+        if (this.lValue.variable && this.lValue.variable.type && this.lValue.variable.type.isArray && this.lValue.variable.type.elementType) {
+            this._type = new ArrayRefType(origin, "thread", this.lValue.variable.type.elementType);
+        }
     }
-    
+
+    get type() { return this._type; }
     get lValue() { return this._lValue; }
-    
+
     toString()
     {
         return "@" + (this.numElements ? "<<" + this.numElements + ">>" : "") + "(" + this.lValue + ")";
index 134700f..a553352 100644 (file)
@@ -30,13 +30,17 @@ class NativeFunc extends Func {
         super(origin, name, returnType, typeParameters, parameters, isCast, shaderType);
         this.isRestricted = false;
         this.implementation = null;
+        this._implementationData = null;
         this.instantiateImplementation = (substitution) => {};
         this.visitImplementationData = (implementationData, visitor) => null;
         this.didLayoutStructsInImplementationData = implementationData => null;
     }
-    
+
     get isNative() { return true; }
 
+    get implementationData() { return this._implementationData; }
+    set implementationData(newImplData) { this._implementationData = newImplData; }
+
     toDeclString()
     {
         return "native " + super.toDeclString();
index 646d06b..f40d6b8 100644 (file)
@@ -351,10 +351,9 @@ class Rewriter {
     {
         let result = new FunctionLikeBlock(
             node.origin,
-            Node.visit(node.returnType, this),
-            node.argumentList.map(argument => argument.visit(this)),
-            node.parameters.map(parameter => parameter.visit(this)),
-            node.body.visit(this));
+            node.func.visit(this),
+            node.argumentList.map(arg => arg.visit(this))
+        );
         result.returnEPtr = node.returnEPtr;
         return result;
     }
index d173f7e..fa1f6a4 100644 (file)
@@ -17,6 +17,7 @@ td {
     <script src="CreateLiteral.js"></script>
     <script src="CreateLiteralType.js"></script>
     <script src="PropertyAccessExpression.js"></script>
+    <script src="SwizzleOp.js"></script>
 
     <script src="AddressSpace.js"></script>
     <script src="AnonymousVariable.js"></script>
index 1eddd1a..5f9ccbf 100644 (file)
@@ -406,35 +406,6 @@ function intToString(x)
     }
 }
 
-// There are 481 swizzle operators. Let's not list them explicitly.
-function _generateSwizzle(maxDepth, maxItems, array)
-{
-    if (!array)
-        array = [];
-    if (array.length == maxDepth) {
-        let result = `vec${array.length}<T> operator.${array.join("")}<T>(vec${maxItems}<T> v)
-{
-    vec${array.length}<T> result;
-`;
-        for (let i = 0; i < array.length; ++i) {
-            result += `    result.${intToString(i)} = v.${array[i]};
-`;
-        }
-        result += `    return result;
-}
-`;
-        return result;
-    }
-    let result = "";
-    for (let i = 0; i < maxItems; ++i) {
-        array.push(intToString(i));
-        result += _generateSwizzle(maxDepth, maxItems, array);
-        array.pop();
-    }
-    return result;
-}
-
-for (let maxDepth = 2; maxDepth <= 4; maxDepth++) {
-    for (let maxItems = 2; maxItems <= 4; maxItems++)
-        standardLibrary += _generateSwizzle(maxDepth, maxItems);
-}
+// There are 481 swizzle operators, so we compile them as native functions
+standardLibrary += SwizzleOp.allSwizzleOperators().join(";\n") + ";";
+console.log(standardLibrary);
\ No newline at end of file
diff --git a/Tools/WebGPUShadingLanguageRI/SwizzleOp.js b/Tools/WebGPUShadingLanguageRI/SwizzleOp.js
new file mode 100644 (file)
index 0000000..d1c5bd0
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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 SwizzleOp {
+    constructor(outSize, components, inSize)
+    {
+        this._outSize = outSize;
+        this._components = components.slice(); // Shallow clone
+        this._inSize = inSize;
+    }
+
+    get outSize() { return this._outSize; }
+    get components() { return this._components; }
+    get inSize() { return this._inSize; }
+
+    toString()
+    {
+        return `native vec${this.outSize}<T> operator.${this.components.join("")}<T>(vec${this.inSize}<T> v)`;
+    }
+
+    static allSwizzleOperators()
+    {
+        if (!SwizzleOp._allSwizzleOperators) {
+            SwizzleOp._allSwizzleOperators = [];
+            
+            function _generateSwizzle(maxDepth, maxItems, array) {
+                if (!array)
+                    array = [];
+                if (array.length == maxDepth) {
+                    SwizzleOp._allSwizzleOperators.push(new SwizzleOp(array.length, array, maxItems));
+                    return;
+                }
+                for (let i = 0; i < maxItems; ++i) {
+                    array.push(intToString(i));
+                    _generateSwizzle(maxDepth, maxItems, array);
+                    array.pop();
+                }
+            };
+        
+            for (let maxDepth = 2; maxDepth <= 4; maxDepth++) {
+                for (let maxItems = 2; maxItems <= 4; maxItems++)
+                    _generateSwizzle(maxDepth, maxItems);
+            }
+        }
+        return SwizzleOp._allSwizzleOperators;
+    }
+}
+
+// Initialise the static member (JS doesn't allow static fields declared in the class)
+SwizzleOp._allSwizzleOperators = null;
\ No newline at end of file
index 320fba9..21c77f6 100644 (file)
@@ -11,6 +11,7 @@
 <script src="CreateLiteral.js"></script>
 <script src="CreateLiteralType.js"></script>
 <script src="PropertyAccessExpression.js"></script>
+<script src="SwizzleOp.js"></script>
 
 <script src="AddressSpace.js"></script>
 <script src="AnonymousVariable.js"></script>
index acd6804..3614ead 100644 (file)
@@ -194,6 +194,23 @@ tests = new Proxy({}, {
     }
 });
 
+tests.commentParsing = function() {
+    let program = doPrep(`
+        /* this comment
+        runs over multiple lines */
+        bool foo() { return true; }
+    `);
+    checkBool(program, callFunction(program, "foo", [], []), true);
+
+    checkFail(
+        () => doPrep(`
+        /* this comment
+        runs over multiple lines
+        bool foo() { return true; }
+        `),
+        (e) => e instanceof WSyntaxError);
+}
+
 tests.literalBool = function() {
     let program = doPrep("bool foo() { return true; }");
     checkBool(program, callFunction(program, "foo", [], []), true);
index 09abe4d..7c28791 100644 (file)
@@ -34,6 +34,7 @@ class Type extends Node {
     get isNumber() { return false; }
     get isInt() { return false; }
     get isFloating() { return false; }
+    get isEnum() { return false; }
     get isPrimitive() { return false; }
     
     inherits(protocol)
index 3a7e948..7a7c4b4 100644 (file)
@@ -11,6 +11,7 @@
 <script src="CreateLiteral.js"></script>
 <script src="CreateLiteralType.js"></script>
 <script src="PropertyAccessExpression.js"></script>
+<script src="SwizzleOp.js"></script>
 
 <script src="AddressSpace.js"></script>
 <script src="AnonymousVariable.js"></script>