[WSL] Cannot put templated structs inside structs
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 19 Sep 2017 04:15:56 +0000 (04:15 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 19 Sep 2017 04:15:56 +0000 (04:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=177120

Reviewed by Myles Maxfield.

It turns out that we still need to instantiate structs even if not passing type arguments,
since its fields may need to be instantiated.

This makes Myles's test case pass. When writing the test case, I encountered parser bugs, and
I fixed them.

* WebGPUShadingLanguageRI/CallFunction.js:
(callFunction):
* WebGPUShadingLanguageRI/Checker.js:
(Checker.prototype.visitReferenceType):
* WebGPUShadingLanguageRI/FuncInstantiator.js:
(FuncInstantiator.prototype.getUnique):
(FuncInstantiator):
* WebGPUShadingLanguageRI/Parse.js:
(parseSuffixOperator):
(parsePossibleSuffix):
(parsePostIncrement):
* WebGPUShadingLanguageRI/StructType.js:
(StructType.prototype.instantiate):
* WebGPUShadingLanguageRI/Test.js:
(checkNumber):
(checkEnum):
(TEST_instantiateStructInStruct):
* WebGPUShadingLanguageRI/TypeRef.js:
(TypeRef.prototype.get instantiatedType):
(TypeRef.prototype.get isPrimitive):

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

Tools/ChangeLog
Tools/WebGPUShadingLanguageRI/CallFunction.js
Tools/WebGPUShadingLanguageRI/Checker.js
Tools/WebGPUShadingLanguageRI/FuncInstantiator.js
Tools/WebGPUShadingLanguageRI/Parse.js
Tools/WebGPUShadingLanguageRI/StructType.js
Tools/WebGPUShadingLanguageRI/Test.js
Tools/WebGPUShadingLanguageRI/TypeRef.js

index 6834826..783ecc6 100644 (file)
@@ -1,5 +1,39 @@
 2017-09-18  Filip Pizlo  <fpizlo@apple.com>
 
+        [WSL] Cannot put templated structs inside structs
+        https://bugs.webkit.org/show_bug.cgi?id=177120
+
+        Reviewed by Myles Maxfield.
+        
+        It turns out that we still need to instantiate structs even if not passing type arguments,
+        since its fields may need to be instantiated.
+        
+        This makes Myles's test case pass. When writing the test case, I encountered parser bugs, and
+        I fixed them.
+
+        * WebGPUShadingLanguageRI/CallFunction.js:
+        (callFunction):
+        * WebGPUShadingLanguageRI/Checker.js:
+        (Checker.prototype.visitReferenceType):
+        * WebGPUShadingLanguageRI/FuncInstantiator.js:
+        (FuncInstantiator.prototype.getUnique):
+        (FuncInstantiator):
+        * WebGPUShadingLanguageRI/Parse.js:
+        (parseSuffixOperator):
+        (parsePossibleSuffix):
+        (parsePostIncrement):
+        * WebGPUShadingLanguageRI/StructType.js:
+        (StructType.prototype.instantiate):
+        * WebGPUShadingLanguageRI/Test.js:
+        (checkNumber):
+        (checkEnum):
+        (TEST_instantiateStructInStruct):
+        * WebGPUShadingLanguageRI/TypeRef.js:
+        (TypeRef.prototype.get instantiatedType):
+        (TypeRef.prototype.get isPrimitive):
+
+2017-09-18  Filip Pizlo  <fpizlo@apple.com>
+
         WSL should support enum
         https://bugs.webkit.org/show_bug.cgi?id=176977
 
index 8e01925..4330c9b 100644 (file)
@@ -40,6 +40,6 @@ function callFunction(program, name, typeArguments, argumentList)
         func.parameters[i].ePtr.copyFrom(argumentList[i].ePtr, type.size);
     }
     let result = new Evaluator(program).runFunc(func);
-    return new TypedValue(func.returnType.unifyNode, result);
+    return new TypedValue(func.uninstantiatedReturnType, result);
 }
 
index 398dc2e..55e5460 100644 (file)
@@ -160,7 +160,8 @@ class Checker extends Visitor {
         if (node.addressSpace == "thread")
             return;
         
-        if (!node.elementType.instantiatedType.isPrimitive)
+        let instantiatedType = node.elementType.instantiatedType;
+        if (!instantiatedType.isPrimitive)
             throw new WTypeError(node.origin.originString, "Illegal pointer to non-primitive type: " + node.elementType + " (instantiated to " + node.elementType.instantiatedType + ")");
     }
     
index db85530..fe7b9b5 100644 (file)
@@ -117,6 +117,7 @@ class FuncInstantiator {
             }
         }
         let resultingFunc = func.visit(new Instantiate());
+        resultingFunc.uninstantiatedReturnType = func.returnType.visit(substitution);
         let instance = {func: resultingFunc, typeArguments};
         instances.push(instance);
         return resultingFunc;
index 6b017fa..431eace 100644 (file)
@@ -400,24 +400,14 @@ function parse(program, origin, originKind, lineNumberOffset, text)
         return readModifyWrite;
     }
     
-    function parsePossibleSuffix()
+    function parseSuffixOperator(left, acceptableOperators)
     {
-        let acceptableOperators = ["++", "--", ".", "->", "["];
-        let limitedOperators = [".", "->", "["];
-        let left;
-        if (isCallExpression()) {
-            left = parseCallExpression();
-            acceptableOperators = limitedOperators;
-        } else
-            left = parseTerm();
-        
         let token;
         while (token = tryConsume(...acceptableOperators)) {
             switch (token.text) {
             case "++":
             case "--":
-                left = finishParsingPostIncrement(token, left);
-                break;
+                return finishParsingPostIncrement(token, left);
             case ".":
             case "->":
                 if (token.text == "->")
@@ -433,11 +423,24 @@ function parse(program, origin, originKind, lineNumberOffset, text)
             default:
                 throw new Error("Bad token: " + token);
             }
-            acceptableOperators = limitedOperators;
         }
         return left;
     }
     
+    function parsePossibleSuffix()
+    {
+        let acceptableOperators = ["++", "--", ".", "->", "["];
+        let limitedOperators = [".", "->", "["];
+        let left;
+        if (isCallExpression()) {
+            left = parseCallExpression();
+            acceptableOperators = limitedOperators;
+        } else
+            left = parseTerm();
+        
+        return parseSuffixOperator(left, acceptableOperators);
+    }
+    
     function finishParsingPreIncrement(token, left, extraArg)
     {
         let readModifyWrite = new ReadModifyWriteExpression(token, left);
@@ -567,7 +570,7 @@ function parse(program, origin, originKind, lineNumberOffset, text)
     
     function parsePostIncrement()
     {
-        let left = parseTerm();
+        let left = parseSuffixOperator(parseTerm(), ".", "->", "[");
         let token = consume("++", "--");
         return finishParsingPostIncrement(token, left);
     }
index 217922e..f9d8c7d 100644 (file)
@@ -67,9 +67,6 @@ class StructType extends Type {
             if (typeArguments.length != this.typeParameters.length)
                 throw new WTypeError(this.origin.originString, "Wrong number of type arguments to instantiation");
             
-            if (!typeArguments.length)
-                return this;
-            
             substitution = new Substitution(this.typeParameters, typeArguments);
             typeParameters = [];
         }
@@ -83,6 +80,7 @@ class StructType extends Type {
             newField = newField.visit(instantiateImmediates);
             result.add(newField);
         }
+        
         return result;
     }
     
index 97bceee..51f454e 100644 (file)
@@ -88,7 +88,7 @@ function makeDouble(program, value)
 
 function checkNumber(program, result, expected)
 {
-    if (!result.type.isNumber)
+    if (!result.type.unifyNode.isNumber)
         throw new Error("Wrong result type; result: " + result);
     if (result.value != expected)
         throw new Error("Wrong result: " + result + " (expected " + expected + ")");
@@ -103,7 +103,7 @@ function checkInt(program, result, expected)
 
 function checkEnum(program, result, expected)
 {
-    if (!(result.type instanceof EnumType))
+    if (!(result.type.unifyNode instanceof EnumType))
         throw new Error("Wrong result type; result: " + result);
     if (result.value != expected)
         throw new Error("Wrong result: " + result.value + " (expected " + expected + ")");
@@ -3902,6 +3902,26 @@ function TEST_builtinVectors()
     checkBool(program, callFunction(program, "food6", [], []), false);
 }
 
+function TEST_instantiateStructInStruct()
+{
+    let program = doPrep(`
+        struct Bar<T> {
+            T x;
+        }
+        struct Foo {
+            Bar<int> x;
+        }
+        int foo()
+        {
+            Foo x;
+            x.x.x = 42;
+            x.x.x++;
+            return x.x.x;
+        }
+    `);
+    checkInt(program, callFunction(program, "foo", [], []), 43);
+}
+
 function TEST_simpleEnum()
 {
     let program = doPrep(`
index f42d0c8..8d37588 100644 (file)
@@ -57,10 +57,11 @@ class TypeRef extends Type {
     get instantiatedType()
     {
         let type = this.type.unifyNode;
-        if (!this.typeArguments.length)
-            return type;
-        if (!type.instantiate)
-            throw new Error("type does not support instantiation: " + type + " (" + type.constructor.name + ")");
+        if (!type.instantiate) {
+            if (this.typeArguments.length)
+                throw new Error("type does not support instantiation: " + type + " (" + type.constructor.name + ")");
+            return this;
+        }
         return type.instantiate(this.typeArguments);
     }
     
@@ -89,7 +90,7 @@ class TypeRef extends Type {
     {
         if (!this.typeArguments.length)
             return this.type.isPrimitive;
-        throw new Error("Cannot determine if an uninstantiated type is primitive");
+        throw new Error("Cannot determine if an uninstantiated type is primitive: " + this);
     }
     
     setTypeAndArguments(type, typeArguments)