WebKit Bugzilla
Attachment 347846 Details for
Bug 188773
: [WHLSL] Allow native types to have type arguments (like "vector<float, 4>")
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Setting .type in Checker will break TypeDefResolver
bug-188773-20180822142151.patch (text/plain), 78.11 KB, created by
Myles C. Maxfield
on 2018-08-22 14:21:52 PDT
(
hide
)
Description:
Setting .type in Checker will break TypeDefResolver
Filename:
MIME Type:
Creator:
Myles C. Maxfield
Created:
2018-08-22 14:21:52 PDT
Size:
78.11 KB
patch
obsolete
>Subversion Revision: 235183 >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index b2294c8a931da62400dcff9282b105acd627a750..10b7ce307ce7c1c837465de4e3df0753adaf3dba 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,124 @@ >+2018-08-22 Myles C. Maxfield <mmaxfield@apple.com> >+ >+ [WHLSL] Allow native types to have type arguments (like "vector<float, 4>") >+ https://bugs.webkit.org/show_bug.cgi?id=188773 >+ >+ Previously, the way to identify a type was strictly by name, which was represented by a string. Therefore, when something like >+ "vector<int, 3>" was parsed, it would produce a TypeRef with the name "vector" and typeArguments [TypeRef, IntLiteral]. Then, >+ there was a pass to convert the TypeRef to have the name "int3" and no typeArguments. After this transformation, each type can >+ be uniquely identified by name. >+ >+ This is okay for vectors and matrices, but it is unfortunate for textures (e.g. Texture2D<float4>) because they don't have any >+ natural string-only name. In addition, the canonicalization would have to be made aware of the fact that Texture2D<float4> is >+ the same as Texture2D<vector<float, 4>>. Similarly, an author may wish to typedef float4 to a different name. >+ >+ It would be possible to mangle the names of the texture types to something unique, but then we lose information about the inner >+ type. For example, if we did this, Visitor wouldn't recurse into the float4 when encountering Texture2D<float4> because that >+ information would be lost. This could potentially make operations like programWithUnnecessaryThingsRemoved() more difficult to >+ implement in the future. >+ >+ So, it would be better to have each type uniquely identified by (name, typeArguments). TypeRef will therefore also have >+ typeArguments which are used to determine which type it is referencing. After this analysis is done to determine what each >+ TypeRef is referencing, subsequent passes shouldn't care about the typeArguments and should only care about the .type field >+ which had been set - this was true even before this patch. >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * WebGPUShadingLanguageRI/All.js: >+ * WebGPUShadingLanguageRI/CallExpression.js: >+ (CallExpression.prototype.resolve): >+ * WebGPUShadingLanguageRI/CheckTypesWithArguments.js: Copied from Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js. >+ (checkTypesWithArguments.TypeWithArgumentsChecker.prototype.visitTypeRef): >+ (checkTypesWithArguments.TypeWithArgumentsChecker): >+ (checkTypesWithArguments): >+ * WebGPUShadingLanguageRI/Checker.js: >+ (Checker.prototype.visitProgram): >+ (Checker.prototype.visitTypeRef): >+ * WebGPUShadingLanguageRI/InferTypesForCall.js: >+ (inferTypesForCall): >+ (inferTypesForTypeArguments): >+ * WebGPUShadingLanguageRI/Intrinsics.js: >+ (Intrinsics.cast): >+ (Intrinsics.bitwiseCast): >+ (Intrinsics.castToHalf): >+ (Intrinsics.): >+ (Intrinsics): >+ * WebGPUShadingLanguageRI/NameContext.js: >+ (NameContext.prototype.add): >+ (NameContext.prototype.get let): >+ (NameContext.underlyingThings.prototype.else): >+ (NameContext.prototype.Symbol.iterator): >+ (NameContext): >+ * WebGPUShadingLanguageRI/NameResolver.js: >+ (NameResolver.prototype.visitTypeRef): >+ (NameResolver.prototype.visitCallExpression): >+ (NameResolver): >+ (NameResolver.prototype.visitVectorType): Deleted. >+ * WebGPUShadingLanguageRI/NativeType.js: >+ (NativeType): >+ (NativeType.prototype.get typeArguments): >+ (NativeType.prototype.toString): >+ (NativeType.create): >+ * WebGPUShadingLanguageRI/Prepare.js: >+ (let.prepare): >+ * WebGPUShadingLanguageRI/Program.js: >+ (Program.prototype.add): >+ (Program.prototype.toString): >+ (Program): >+ * WebGPUShadingLanguageRI/RecursiveTypeChecker.js: >+ (RecursiveTypeChecker.prototype.visitTypeRef): >+ (RecursiveTypeChecker): >+ * WebGPUShadingLanguageRI/RemoveTypeArguments.js: Removed. >+ * WebGPUShadingLanguageRI/ResolveNames.js: >+ (resolveNamesInTypes): >+ * WebGPUShadingLanguageRI/ResolveOverloadImpl.js: >+ * WebGPUShadingLanguageRI/ResolveTypeDefs.js: >+ (resolveTypeDefsInTypes): >+ * WebGPUShadingLanguageRI/Rewriter.js: >+ (Rewriter.prototype.visitTypeRef): >+ (Rewriter.prototype.visitVectorType): >+ (Rewriter): >+ * WebGPUShadingLanguageRI/SPIRV.html: >+ * WebGPUShadingLanguageRI/StandardLibrary.js: >+ (bool.operator): >+ * WebGPUShadingLanguageRI/StatementCloner.js: >+ (StatementCloner.prototype.visitNativeType): >+ * WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js: >+ (synthesizeDefaultConstructorOperator.FindAllTypes.prototype.visitVectorType): >+ (synthesizeDefaultConstructorOperator.FindAllTypes): >+ (synthesizeDefaultConstructorOperator): >+ * WebGPUShadingLanguageRI/SynthesizeStructAccessors.js: >+ (synthesizeStructAccessors.createTypeRef): >+ * WebGPUShadingLanguageRI/Test.html: >+ * WebGPUShadingLanguageRI/Test.js: >+ * WebGPUShadingLanguageRI/TypeOverloadResolutionFailure.js: Copied from Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js. >+ (TypeOverloadResolutionFailure): >+ (TypeOverloadResolutionFailure.prototype.get type): >+ (TypeOverloadResolutionFailure.prototype.get reason): >+ (TypeOverloadResolutionFailure.prototype.toString): >+ * WebGPUShadingLanguageRI/TypeRef.js: >+ (TypeRef): >+ (TypeRef.wrap): >+ (TypeRef.prototype.get possibleOverloads): >+ (TypeRef.prototype.set possibleOverloads): >+ (TypeRef.prototype.resolve): >+ (TypeRef.prototype.toString): >+ (TypeRef.instantiate): Deleted. >+ * WebGPUShadingLanguageRI/UnificationContext.js: >+ (UnificationContext.prototype.verify): >+ * WebGPUShadingLanguageRI/VectorType.js: >+ (VectorType): >+ (VectorType.prototype.get elementType): >+ (VectorType.prototype.get numElements): >+ (VectorType.prototype.get numElementsValue): >+ (VectorType.prototype.toString): >+ * WebGPUShadingLanguageRI/Visitor.js: >+ (Visitor.prototype.visitTypeRef): >+ (Visitor.prototype.visitNativeType): >+ (Visitor.prototype.visitVectorType): >+ (Visitor): >+ * WebGPUShadingLanguageRI/index.html: >+ > 2018-08-21 Alex Christensen <achristensen@webkit.org> > > Roll out r235139 and r235146 >diff --git a/Tools/WebGPUShadingLanguageRI/All.js b/Tools/WebGPUShadingLanguageRI/All.js >index 81525273ae65a14865964a13da45ce94ef10684a..f9a1d99eadc87b4a408cff9e4990a737ecb8ba1e 100644 >--- a/Tools/WebGPUShadingLanguageRI/All.js >+++ b/Tools/WebGPUShadingLanguageRI/All.js >@@ -60,6 +60,7 @@ load("CheckLoops.js"); > load("CheckRecursion.js"); > load("CheckRecursiveTypes.js"); > load("CheckReturns.js"); >+load("CheckTypesWithArguments.js"); > load("CheckUnreachableCode.js"); > load("CheckWrapped.js"); > load("Checker.js"); >@@ -133,7 +134,6 @@ load("PtrType.js"); > load("ReadModifyWriteExpression.js"); > load("RecursionChecker.js"); > load("RecursiveTypeChecker.js"); >-load("RemoveTypeArguments.js"); > load("ResolveNames.js"); > load("ResolveOverloadImpl.js"); > load("ResolveProperties.js"); >@@ -157,6 +157,7 @@ load("TrapStatement.js"); > load("TypeDef.js"); > load("TypeDefResolver.js"); > load("TypeRef.js"); >+load("TypeOverloadResolutionFailure.js"); > load("TypedValue.js"); > load("UintLiteral.js"); > load("UintLiteralType.js"); >@@ -170,4 +171,4 @@ load("WSyntaxError.js"); > load("WTrapError.js"); > load("WTypeError.js"); > load("WhileLoop.js"); >-load("WrapChecker.js"); >\ No newline at end of file >+load("WrapChecker.js"); >diff --git a/Tools/WebGPUShadingLanguageRI/CallExpression.js b/Tools/WebGPUShadingLanguageRI/CallExpression.js >index b25398f0b1b6eade1b79ac90e6a762525f819bd7..3b15455992e64e2677ba0b03ab6568ef43d5d865 100644 >--- a/Tools/WebGPUShadingLanguageRI/CallExpression.js >+++ b/Tools/WebGPUShadingLanguageRI/CallExpression.js >@@ -64,7 +64,6 @@ class CallExpression extends Expression { > overload.func = func; > } > >- > if (!overload.func) { > failures.push(...overload.failures); > let message = "Did not find function named " + this.name + " for call with "; >diff --git a/Tools/WebGPUShadingLanguageRI/CheckTypesWithArguments.js b/Tools/WebGPUShadingLanguageRI/CheckTypesWithArguments.js >new file mode 100644 >index 0000000000000000000000000000000000000000..bb6b2bd498e77b149df4c68f4ef3ac1ff1cdaab2 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/CheckTypesWithArguments.js >@@ -0,0 +1,38 @@ >+/* >+ * Copyright (C) 2018 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 checkTypesWithArguments(program) >+{ >+ class TypeWithArgumentsChecker extends Visitor { >+ visitTypeRef(node) >+ { >+ if (node.name == "vector" && node.typeArguments.length == 0) >+ throw new Error("Builtin type ${node.name} should always have type arguments."); >+ } >+ } >+ program.visit(new TypeWithArgumentsChecker()); >+} >+ >diff --git a/Tools/WebGPUShadingLanguageRI/Checker.js b/Tools/WebGPUShadingLanguageRI/Checker.js >index 1a14c866aced4112b180f69156c06d2b664d87e2..7b02d41a9208f5ece2084d41442fbe2c429ae519 100644 >--- a/Tools/WebGPUShadingLanguageRI/Checker.js >+++ b/Tools/WebGPUShadingLanguageRI/Checker.js >@@ -41,8 +41,13 @@ class Checker extends Visitor { > statement.visit(this); > } > >- for (let type of node.types.values()) >- doStatement(type); >+ for (let type of node.types.values()) { >+ if (type instanceof Array) { >+ for (let constituentType of type) >+ doStatement(constituentType); >+ } else >+ doStatement(type); >+ } > for (let funcs of node.functions.values()) { > for (let func of funcs) { > this.visitFunc(func); >@@ -245,8 +250,17 @@ class Checker extends Visitor { > > visitTypeRef(node) > { >- if (!node.type) >+ super.visitTypeRef(node); >+ if (!node.type && !node.possibleOverloads) > throw new Error("Type reference without a type in checker: " + node + " at " + node.origin); >+ if (!node.type) >+ node.resolve(node.possibleOverloads, this._program); >+ if (!node.type) >+ throw new Error("Type reference without a type after possibly resolving in checker: " + node + " at " + node.origin); >+ // All the structs will be visited by visitProgram() iterating through each top-level type. >+ // We don't want to recurse here because the contents of structs can refer to themselves (e.g. a linked list), >+ // and this would can an infinite loop. >+ // Typedefs can't refer to themselves because we check that in TypeDefResolver. > if (!(node.type instanceof StructType)) > node.type.visit(this); > } >diff --git a/Tools/WebGPUShadingLanguageRI/InferTypesForCall.js b/Tools/WebGPUShadingLanguageRI/InferTypesForCall.js >index 5f32ed1c490a7df8941e919c130cf65eaa8b6a4d..bcfeb986caff49f0287a83678bf11562847f0389 100644 >--- a/Tools/WebGPUShadingLanguageRI/InferTypesForCall.js >+++ b/Tools/WebGPUShadingLanguageRI/InferTypesForCall.js >@@ -36,12 +36,8 @@ function inferTypesForCall(func, argumentTypes, returnType) > if (!argumentTypes[i].unify(unificationContext, func.parameters[i].type)) > return {failure: new OverloadResolutionFailure(func, "Argument #" + (i + 1) + " " + (func.parameters[i].name ? "for parameter " + func.parameters[i].name + " " : "") + "does not match (passed " + argumentTypes[i] + ", require " + func.parameters[i].type + ")")}; > } >- if (returnType && !returnType.unify(unificationContext, func.returnType)) { >- if (func.returnType.toString() == "vector") { >- returnType.unify(unificationContext, func.returnType) >- } >+ if (returnType && !returnType.unify(unificationContext, func.returnType)) > return {failure: new OverloadResolutionFailure(func, "Return type " + func.returnType + " does not match " + returnType)}; >- } > let verificationResult = unificationContext.verify(); > if (!verificationResult.result) > return {failure: new OverloadResolutionFailure(func, verificationResult.reason)}; >@@ -49,3 +45,21 @@ function inferTypesForCall(func, argumentTypes, returnType) > return {func, unificationContext}; > } > >+function inferTypesForTypeArguments(type, typeArguments) >+{ >+ if (typeArguments.length != type.typeArguments.length) >+ return {failure: new TypeOverloadResolutionFailure(type, "Wrong number of arguments (passed " + typeArguments.length + ", require " + type.typeArguments.length + ")")}; >+ let unificationContext = new UnificationContext(); >+ >+ for (let i = 0; i < typeArguments.length; ++i) { >+ if (!typeArguments[i]) >+ throw new Error("Null type argument at i = " + i); >+ if (!typeArguments[i].unify(unificationContext, type.typeArguments[i])) >+ return {failure: new TypeOverloadResolutionFailure(type, "Argument #" + (i + 1) + " " + (type.typeArguments[i].name ? "for parameter " + type.typeArguments[i].name + " " : "") + "does not match (passed " + typeArguments[i] + ", require " + type.typeArguments[i].type + ")")}; >+ } >+ let verificationResult = unificationContext.verify(); >+ if (!verificationResult.result) >+ return {failure: new TypeOverloadResolutionFailure(type, verificationResult.reason)}; >+ >+ return {type, unificationContext}; >+} >diff --git a/Tools/WebGPUShadingLanguageRI/Intrinsics.js b/Tools/WebGPUShadingLanguageRI/Intrinsics.js >index 50d40c0c0e47e112bc74ccfccb7049427116b0fb..e9c3d1b34176a4bfd79b4f4494b37be0e5e9b380 100644 >--- a/Tools/WebGPUShadingLanguageRI/Intrinsics.js >+++ b/Tools/WebGPUShadingLanguageRI/Intrinsics.js >@@ -33,15 +33,7 @@ class Intrinsics { > // 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 "int", then we must > // use "int" here, since we don't yet know that they are the same type. >- >- this._map.set( >- "native typedef void", >- type => { >- this.void = type; >- type.size = 0; >- type.populateDefaultValue = () => { }; >- }); >- >+ > function isBitwiseEquivalent(left, right) > { > let doubleArray = new Float64Array(1); >@@ -56,58 +48,83 @@ class Intrinsics { > return true; > } > >+ function cast(typedArrayConstructor, number) >+ { >+ var array = new typedArrayConstructor(1); >+ array[0] = number; >+ return array[0]; >+ } >+ >+ function bitwiseCast(typedArrayConstructor1, typedArrayConstructor2, value) >+ { >+ let typedArray1 = new typedArrayConstructor1(1); >+ let typedArray2 = new typedArrayConstructor2(typedArray1.buffer); >+ typedArray1[0] = value; >+ return typedArray2[0]; >+ } >+ >+ function castToHalf(number) >+ { >+ // FIXME: Make this math obey IEEE 754. >+ if (Number.isNaN(number)) >+ return number >+ if (number > 65504) >+ return Number.POSITIVE_INFINITY; >+ if (number < -65504) >+ return Number.NEGATIVE_INFINITY; >+ if (number > 0 && number < Math.pow(2, -24)) >+ return 0; >+ if (number < 0 && number > -Math.pow(2, -24)) >+ return -0; >+ let doubleArray = new Float64Array(1); >+ let uintArray = new Uint8Array(doubleArray.buffer); >+ doubleArray[0] = number; >+ let sign = uintArray[7] & 0x80; >+ let exponent = ((uintArray[7] & 0x7f) << 4) | ((uintArray[6] & 0xf0) >>> 4); >+ let significand = ((uintArray[6] & 0x0f) << 6) | ((uintArray[5] & 0xfc) >>> 2); >+ >+ if ((exponent - 1023) < -14) { >+ exponent = 0; >+ significand = (Math.abs(number) * Math.pow(2, 24)) >>> 0; >+ let value = Math.pow(2, -14) * significand / 1024; >+ if (sign != 0) >+ value *= -1; >+ return value; >+ } >+ >+ doubleArray[0] = 0; >+ >+ uintArray[7] |= sign; >+ uintArray[7] |= (exponent >>> 4); >+ uintArray[6] |= ((exponent << 4) & 0xf0); >+ uintArray[6] |= (significand >>> 6); >+ uintArray[5] |= ((significand << 2) & 0xfc); >+ >+ return doubleArray[0]; >+ } >+ > this._map.set( >- "native typedef int", >+ "native typedef void", > type => { >- this.int = type; >- type.isPrimitive = true; >- type.isInt = true; >- type.isNumber = true; >- type.isSigned = true; >- type.canRepresent = value => isBitwiseEquivalent(value | 0, value); >- type.size = 1; >- type.defaultValue = 0; >- type.createLiteral = (origin, value) => IntLiteral.withType(origin, value | 0, type); >- type.successorValue = value => (value + 1) | 0; >- type.valuesEqual = (a, b) => a === b; >- type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0); >- type.formatValueFromIntLiteral = value => value | 0; >- type.formatValueFromUintLiteral = value => value | 0; >- type.allValues = function*() { >- for (let i = 0; i <= 0xffffffff; ++i) { >- let value = i | 0; >- yield {value: value, name: value}; >- } >- }; >+ this.void = type; >+ type.size = 0; >+ type.populateDefaultValue = () => { }; > }); > > this._map.set( >- "native typedef uint", >+ "native typedef bool", > type => { >- this.uint = type; >+ this.bool = type; > type.isPrimitive = true; >- type.isInt = true; >- type.isNumber = true; >- type.isSigned = false; >- type.canRepresent = value => isBitwiseEquivalent(value >>> 0, value); > type.size = 1; >- type.defaultValue = 0; >- type.createLiteral = (origin, value) => IntLiteral.withType(origin, value >>> 0, type); >- type.successorValue = value => (value + 1) >>> 0; >- type.valuesEqual = (a, b) => a === b; >- type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0); >- type.formatValueFromIntLiteral = value => value >>> 0; >- type.formatValueFromUintLiteral = value => value >>> 0; >- type.allValues = function*() { >- for (let i = 0; i <= 0xffffffff; ++i) >- yield {value: i, name: i}; >- }; >+ type.populateDefaultValue = (buffer, offset) => buffer.set(offset, false); > }); > > this._map.set( > "native typedef uchar", > type => { > this.uchar = type; >+ type.isPrimitive = true; > type.isInt = true; > type.isNumber = true; > type.isSigned = false; >@@ -126,149 +143,292 @@ class Intrinsics { > }; > }); > >+ >+ this._map.set( >+ "native typedef ushort", >+ type => { >+ this.ushort = type; >+ type.isPrimitive = true; >+ type.isInt = true; >+ type.isNumber = true; >+ type.isSigned = false; >+ type.canRepresent = value => isBitwiseEquivalent(value & 0xffff, value); >+ type.size = 1; >+ type.defaultValue = 0; >+ type.createLiteral = (origin, value) => IntLiteral.withType(origin, value & 0xffff, type); >+ type.successorValue = value => (value + 1) & 0xffff; >+ type.valuesEqual = (a, b) => a === b; >+ type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0); >+ type.formatValueFromIntLiteral = value => value & 0xffff; >+ type.formatValueFromUintLiteral = value => value & 0xffff; >+ type.allValues = function*() { >+ for (let i = 0; i <= 0xffff; ++i) >+ yield {value: i, name: i}; >+ }; >+ }); >+ > this._map.set( >- "native typedef float", >- type => { >- this.float = type; >- type.isPrimitive = true; >- type.size = 1; >- type.isFloating = true; >- type.isNumber = true; >- type.canRepresent = value => isBitwiseEquivalent(Math.fround(value), value); >- type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0); >- type.formatValueFromIntLiteral = value => value; >- type.formatValueFromUintLiteral = value => value; >- type.formatValueFromFloatLiteral = value => Math.fround(value); >- }); >+ "native typedef uint", >+ type => { >+ this.uint = type; >+ type.isPrimitive = true; >+ type.isInt = true; >+ type.isNumber = true; >+ type.isSigned = false; >+ type.canRepresent = value => isBitwiseEquivalent(value >>> 0, value); >+ type.size = 1; >+ type.defaultValue = 0; >+ type.createLiteral = (origin, value) => IntLiteral.withType(origin, value >>> 0, type); >+ type.successorValue = value => (value + 1) >>> 0; >+ type.valuesEqual = (a, b) => a === b; >+ type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0); >+ type.formatValueFromIntLiteral = value => value >>> 0; >+ type.formatValueFromUintLiteral = value => value >>> 0; >+ type.allValues = function*() { >+ for (let i = 0; i <= 0xffffffff; ++i) >+ yield {value: i, name: i}; >+ }; >+ }); > > this._map.set( >- "native typedef bool", >- type => { >- this.bool = type; >- type.isPrimitive = true; >- type.size = 1; >- type.populateDefaultValue = (buffer, offset) => buffer.set(offset, false); >- }); >+ "native typedef char", >+ type => { >+ this.char = type; >+ type.isPrimitive = true; >+ type.isInt = true; >+ type.isNumber = true; >+ type.isSigned = true; >+ type.canRepresent = value => isBitwiseEquivalent(cast(Int8Array, value), value); >+ type.size = 1; >+ type.defaultValue = 0; >+ type.createLiteral = (origin, value) => IntLiteral.withType(origin, cast(Int8Array, value), type); >+ type.successorValue = value => cast(Int8Array, value + 1); >+ type.valuesEqual = (a, b) => a === b; >+ type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0); >+ type.formatValueFromIntLiteral = value => cast(Int8Array, value); >+ type.formatValueFromUintLiteral = value => cast(Int8Array, value); >+ type.allValues = function*() { >+ for (let i = 0; i <= 0xff; ++i) { >+ let value = cast(Int8Array, i); >+ yield {value: value, name: value}; >+ } >+ }; >+ }); >+ >+ this._map.set( >+ "native typedef short", >+ type => { >+ this.short = type; >+ type.isPrimitive = true; >+ type.isInt = true; >+ type.isNumber = true; >+ type.isSigned = true; >+ type.canRepresent = value => isBitwiseEquivalent(cast(Int16Array, value), value); >+ type.size = 1; >+ type.defaultValue = 0; >+ type.createLiteral = (origin, value) => IntLiteral.withType(origin, cast(Int16Array, value), type); >+ type.successorValue = value => cast(Int16Array, value + 1); >+ type.valuesEqual = (a, b) => a === b; >+ type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0); >+ type.formatValueFromIntLiteral = value => cast(Int16Array, value); >+ type.formatValueFromUintLiteral = value => cast(Int16Array, value); >+ type.allValues = function*() { >+ for (let i = 0; i <= 0xffff; ++i) { >+ let value = cast(Int16Array, i); >+ yield {value: value, name: value}; >+ } >+ }; >+ }); >+ >+ this._map.set( >+ "native typedef int", >+ type => { >+ this.int = type; >+ type.isPrimitive = true; >+ type.isInt = true; >+ type.isNumber = true; >+ type.isSigned = true; >+ type.canRepresent = value => isBitwiseEquivalent(value | 0, value); >+ type.size = 1; >+ type.defaultValue = 0; >+ type.createLiteral = (origin, value) => IntLiteral.withType(origin, value | 0, type); >+ type.successorValue = value => (value + 1) | 0; >+ type.valuesEqual = (a, b) => a === b; >+ type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0); >+ type.formatValueFromIntLiteral = value => value | 0; >+ type.formatValueFromUintLiteral = value => value | 0; >+ type.allValues = function*() { >+ for (let i = 0; i <= 0xffffffff; ++i) { >+ let value = i | 0; >+ yield {value: value, name: value}; >+ } >+ }; >+ }); >+ >+ this._map.set( >+ "native typedef half", >+ type => { >+ this.half = type; >+ type.isPrimitive = true; >+ type.size = 1; >+ type.isFloating = true; >+ type.isNumber = true; >+ type.canRepresent = value => isBitwiseEquivalent(castToHalf(value), value); >+ type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0); >+ type.formatValueFromIntLiteral = value => value; >+ type.formatValueFromUintLiteral = value => value; >+ type.formatValueFromFloatLiteral = value => castToHalf(value); >+ }); >+ >+ this._map.set( >+ "native typedef float", >+ type => { >+ this.float = type; >+ type.isPrimitive = true; >+ type.size = 1; >+ type.isFloating = true; >+ type.isNumber = true; >+ type.canRepresent = value => isBitwiseEquivalent(Math.fround(value), value); >+ type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0); >+ type.formatValueFromIntLiteral = value => value; >+ type.formatValueFromUintLiteral = value => value; >+ type.formatValueFromFloatLiteral = value => Math.fround(value); >+ }); >+ >+ this._map.set( >+ "native typedef atomic_int", >+ type => { >+ this.atomic_int = type; >+ }); >+ >+ this._map.set( >+ "native typedef atomic_uint", >+ type => { >+ this.atomic_uint = type; >+ }); > > for (let vectorType of VectorElementTypes) { >- for (let vectorSize of VectorElementSizes) >- this._map.set(`native typedef vector<${vectorType}, ${vectorSize}>`, type => {}); >+ for (let vectorSize of VectorElementSizes) { >+ this._map.set(`native typedef vector<${vectorType}, ${vectorSize}>`, type => { >+ this[`vector<${vectorType}, ${vectorSize}>`] = type; >+ }); >+ } > } >- >+ > this._map.set( > "native operator int(uint)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() | 0); > }); >- >+ > this._map.set( > "native operator int(uchar)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() | 0); > }); >- >+ > this._map.set( > "native operator int(float)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() | 0); > }); >- >+ > this._map.set( > "native operator uint(int)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0); > }); >- >+ > this._map.set( > "native operator uint(uchar)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0); > }); >- >+ > this._map.set( > "native operator uint(float)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0); > }); >- >+ > this._map.set( > "native operator uchar(int)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff); > }); >- >+ > this._map.set( > "native operator uchar(uint)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff); > }); >- >+ > this._map.set( > "native operator uchar(float)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff); > }); >- >+ > this._map.set( > "native operator float(int)", > func => { > func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue())); > }); >- >+ > this._map.set( > "native operator float(uint)", > func => { > func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue())); > }); >- >+ > this._map.set( > "native operator float(uchar)", > func => { > func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue())); > }); >- >+ > this._map.set( > "native int operator+(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() + right.loadValue()) | 0); > }); >- >+ > this._map.set( > "native uint operator+(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() + right.loadValue()) >>> 0); > }); >- >+ > this._map.set( > "native float operator+(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(Math.fround(left.loadValue() + right.loadValue())); > }); >- >+ > this._map.set( > "native int operator-(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() - right.loadValue()) | 0); > }); >- >+ > this._map.set( > "native uint operator-(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() - right.loadValue()) >>> 0); > }); >- >+ > this._map.set( > "native float operator-(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(Math.fround(left.loadValue() - right.loadValue())); > }); >- >+ > this._map.set( > "native int operator*(int,int)", > func => { >@@ -276,229 +436,229 @@ class Intrinsics { > return EPtr.box((left.loadValue() * right.loadValue()) | 0); > }; > }); >- >+ > this._map.set( > "native uint operator*(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() * right.loadValue()) >>> 0); > }); >- >+ > this._map.set( > "native float operator*(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(Math.fround(left.loadValue() * right.loadValue())); > }); >- >+ > this._map.set( > "native int operator/(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() / right.loadValue()) | 0); > }); >- >+ > this._map.set( > "native uint operator/(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() / right.loadValue()) >>> 0); > }); >- >+ > this._map.set( > "native int operator&(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() & right.loadValue()); > }); >- >+ > this._map.set( > "native uint operator&(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() & right.loadValue()) >>> 0); > }); >- >+ > this._map.set( > "native int operator|(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() | right.loadValue()); > }); >- >+ > this._map.set( > "native uint operator|(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() | right.loadValue()) >>> 0); > }); >- >+ > this._map.set( > "native int operator^(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() ^ right.loadValue()); > }); >- >+ > this._map.set( > "native uint operator^(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() ^ right.loadValue()) >>> 0); > }); >- >+ > this._map.set( > "native int operator<<(int,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() << right.loadValue()); > }); >- >+ > this._map.set( > "native uint operator<<(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() << right.loadValue()) >>> 0); > }); >- >+ > this._map.set( > "native int operator>>(int,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() >> right.loadValue()); > }); >- >+ > this._map.set( > "native uint operator>>(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() >>> right.loadValue()); > }); >- >+ > this._map.set( > "native int operator~(int)", > func => { > func.implementation = ([value]) => EPtr.box(~value.loadValue()); > }); >- >+ > this._map.set( > "native uint operator~(uint)", > func => { > func.implementation = ([value]) => EPtr.box((~value.loadValue()) >>> 0); > }); >- >+ > this._map.set( > "native float operator/(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(Math.fround(left.loadValue() / right.loadValue())); > }); >- >+ > this._map.set( > "native bool operator==(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() == right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator==(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() == right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator==(bool,bool)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() == right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator==(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() == right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator<(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() < right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator<(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() < right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator<(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() < right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator<=(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() <= right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator<=(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() <= right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator<=(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() <= right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator>(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() > right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator>(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() > right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator>(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() > right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator>=(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() >= right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator>=(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() >= right.loadValue()); > }); >- >+ > this._map.set( > "native bool operator>=(float,float)", > func => { >@@ -538,7 +698,7 @@ class Intrinsics { > for (let setter of BuiltinVectorSetter.functions()) > this._map.set(setter.toString(), func => setter.instantiateImplementation(func)); > } >- >+ > add(thing) > { > let intrinsic = this._map.get(thing.toString()); >diff --git a/Tools/WebGPUShadingLanguageRI/NameContext.js b/Tools/WebGPUShadingLanguageRI/NameContext.js >index 1bab3fc5602601077b3fa885a6054ab860b0a193..dc68578ff556b312b0927ef3c0dffa0068f1be63 100644 >--- a/Tools/WebGPUShadingLanguageRI/NameContext.js >+++ b/Tools/WebGPUShadingLanguageRI/NameContext.js >@@ -69,11 +69,33 @@ class NameContext { > return; > } > >+ if (thing.kind == Type) { >+ this._set.add(thing); >+ if (thing.name == "vector") { >+ let array = this._map.get(thing.name); >+ if (!array) { >+ array = []; >+ array.kind = Type; >+ this._map.set(thing.name, array); >+ } >+ if (array.kind != Type) >+ throw new WTypeError(thing.origin.originString, "Cannot reuse type name for function: " + thing.name); >+ array.push(thing); >+ return; >+ } else { >+ if (this._map.has(thing.name)) >+ throw new WTypeError(thing.origin.originString, "Duplicate name: " + thing.name); >+ this._map.set(thing.name, thing); >+ } >+ return; >+ } >+ > if (this._map.has(thing.name)) > throw new WTypeError(thing.origin.originString, "Duplicate name: " + thing.name); > > this._set.add(thing); > this._map.set(thing.name, thing); >+ > } > > get(kind, name) >@@ -102,6 +124,10 @@ class NameContext { > for (let func of thing) > yield func; > return; >+ } else if (thing.kind === Type && (thing instanceof Array)) { >+ for (let type of thing) >+ yield type; >+ return; > } > yield thing; > } >@@ -163,8 +189,8 @@ class NameContext { > { > for (let value of this._map.values()) { > if (value instanceof Array) { >- for (let func of value) >- yield func; >+ for (let thing of value) >+ yield thing; > continue; > } > yield value; >diff --git a/Tools/WebGPUShadingLanguageRI/NameResolver.js b/Tools/WebGPUShadingLanguageRI/NameResolver.js >index f615a2fb4e87dc1deb7b01b572fb7af626abd095..8e4b0214062937b6212eeaba3b0cfe0b5a359a33 100644 >--- a/Tools/WebGPUShadingLanguageRI/NameResolver.js >+++ b/Tools/WebGPUShadingLanguageRI/NameResolver.js >@@ -120,12 +120,16 @@ class NameResolver extends Visitor { > > visitTypeRef(node) > { >+ super.visitTypeRef(node); > let type = node.type; > if (!type) { > type = this._nameContext.get(Type, node.name); > if (!type) > throw new WTypeError(node.origin.originString, "Could not find type named " + node.name); >- node.type = type; >+ if (type instanceof Array) >+ node.possibleOverloads = type; >+ else >+ node.type = type; > } > } > >@@ -208,9 +212,4 @@ class NameResolver extends Visitor { > > super.visitCallExpression(node); > } >- >- visitVectorType(node) >- { >- node.elementType.visit(this); >- } > } >diff --git a/Tools/WebGPUShadingLanguageRI/NativeType.js b/Tools/WebGPUShadingLanguageRI/NativeType.js >index e2d851cbccba3a97234c7bd392907829ca9e05f2..2381b5a6b0b010e0fdd4dc53550a8ea6b4f8347b 100644 >--- a/Tools/WebGPUShadingLanguageRI/NativeType.js >+++ b/Tools/WebGPUShadingLanguageRI/NativeType.js >@@ -25,11 +25,14 @@ > "use strict"; > > class NativeType extends Type { >- constructor(origin, name) >+ constructor(origin, name, typeArguments) > { >+ if (!(typeArguments instanceof Array)) >+ throw new Error("type parameters not array: " + typeArguments); > super(); > this._origin = origin; > this._name = name; >+ this._typeArguments = typeArguments; > this._isNumber = false; > this._isInt = false; > this._isFloating = false; >@@ -38,6 +41,7 @@ class NativeType extends Type { > > get origin() { return this._origin; } > get name() { return this._name; } >+ get typeArguments() { return this._typeArguments; } > get isNative() { return true; } > > // We let Intrinsics.js set these as it likes. >@@ -52,19 +56,18 @@ class NativeType extends Type { > > toString() > { >- return `native typedef ${this.name}`; >+ let result = `native typedef ${this.name}`; >+ if (this.typeArguments.length) >+ result += "<" + this.typeArguments.join(",") + ">"; >+ return result; > } > > static create(origin, name, typeArguments) > { >- // FIXME: For native types like Texture1D this should resolve the type to something concrete by changing the type name. >- if (typeArguments.length) >- throw new WTypeError(origin.originString, `${name}<${typeArguments.join(",")}>: Support for native types with type arguments is currently unimplemented.`); >+ if (name == "vector") >+ return new VectorType(origin, name, typeArguments); > >- if (allVectorTypeNames().indexOf(name) > -1) >- return new VectorType(origin, name); >- >- return new NativeType(origin, name); >+ return new NativeType(origin, name, typeArguments); > } > } > >diff --git a/Tools/WebGPUShadingLanguageRI/Prepare.js b/Tools/WebGPUShadingLanguageRI/Prepare.js >index 7b16139e95b81e2e8da8354bd8c179b190baefa0..9faca86e205755b2c6a66f412b5692e99e7b03af 100644 >--- a/Tools/WebGPUShadingLanguageRI/Prepare.js >+++ b/Tools/WebGPUShadingLanguageRI/Prepare.js >@@ -40,7 +40,6 @@ let prepare = (() => { > } > > foldConstexprs(program); >- removeTypeArguments(program); > > let nameResolver = createNameResolver(program); > resolveNamesInTypes(program, nameResolver); >@@ -54,6 +53,7 @@ let prepare = (() => { > synthesizeDefaultConstructorOperator(program); > resolveNamesInFunctions(program, nameResolver); > resolveTypeDefsInFunctions(program); >+ checkTypesWithArguments(program); > > check(program); > checkLiteralTypes(program); >@@ -66,6 +66,7 @@ let prepare = (() => { > checkLoops(program); > checkRecursion(program); > checkProgramWrapped(program); >+ checkTypesWithArguments(program); > findHighZombies(program); > program.visit(new StructLayoutBuilder()); > inline(program); >diff --git a/Tools/WebGPUShadingLanguageRI/Program.js b/Tools/WebGPUShadingLanguageRI/Program.js >index 06625d98fc41e74c93dece80b70ce55c7af74dd5..1116c4f577562215fdd7428a317579a929165414 100644 >--- a/Tools/WebGPUShadingLanguageRI/Program.js >+++ b/Tools/WebGPUShadingLanguageRI/Program.js >@@ -48,19 +48,25 @@ class Program extends Node { > if (statement instanceof Func) { > let array = this._functions.get(statement.name); > if (!array) >- this._functions.set(statement.name, array = []); >+ this.functions.set(statement.name, array = []); > array.push(statement); >- } else if (statement instanceof Type) >- this._types.set(statement.name, statement); >- else >+ } else if (statement instanceof Type) { >+ if (statement.isNative && statement.name == "vector") { >+ let array = this.types.get(statement.name); >+ if (!array) >+ this.types.set(statement.name, array = []); >+ array.push(statement); >+ } else >+ this.types.set(statement.name, statement); >+ } else > throw new Error("Statement is not a function or type: " + statement); >- this._topLevelStatements.push(statement); >- this._globalNameContext.add(statement); >+ this.topLevelStatements.push(statement); >+ this.globalNameContext.add(statement); > } > > toString() > { >- if (!this._topLevelStatements.length) >+ if (!this.topLevelStatements.length) > return ""; > return this._topLevelStatements.join(";") + ";"; > } >diff --git a/Tools/WebGPUShadingLanguageRI/RecursiveTypeChecker.js b/Tools/WebGPUShadingLanguageRI/RecursiveTypeChecker.js >index 91f76742f60d14a37e6e606c3ab2f9c2c8fab116..de3d524bc5488c8705fea8f67bad87becbb97ddc 100644 >--- a/Tools/WebGPUShadingLanguageRI/RecursiveTypeChecker.js >+++ b/Tools/WebGPUShadingLanguageRI/RecursiveTypeChecker.js >@@ -51,7 +51,11 @@ class RecursiveTypeChecker extends Visitor { > visitTypeRef(node) > { > super.visitTypeRef(node); >- node.type.visit(this); >+ if (node.possibleOverloads) { >+ for (let overload of node.possibleOverloads) >+ overload.visit(this); >+ } else >+ node.type.visit(this); > } > } > >diff --git a/Tools/WebGPUShadingLanguageRI/RemoveTypeArguments.js b/Tools/WebGPUShadingLanguageRI/RemoveTypeArguments.js >deleted file mode 100644 >index 93db9e647c921c954e8998ce1675de7cb61f142b..0000000000000000000000000000000000000000 >--- a/Tools/WebGPUShadingLanguageRI/RemoveTypeArguments.js >+++ /dev/null >@@ -1,65 +0,0 @@ >-/* >- * Copyright (C) 2018 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 removeTypeArguments(program) >-{ >- class RemoveTypeArguments extends Visitor { >- static resolveNameAndArguments(node) >- { >- if (!node.typeArguments) >- return node.name; >- >- switch (node.name) { >- case "vector": >- if (node.typeArguments.length != 2) >- throw new WSyntaxError(node.originString, `${node.name} should have 2 type arguments, got ${node.typeArguments.length}.`); >- >- const elementTypeName = node.typeArguments[0].name; >- const lengthValue = node.typeArguments[1].value; >- >- if (VectorElementTypes.indexOf(elementTypeName) < 0) >- throw new WSyntaxError(node.originString, `${elementTypeName} is not a valid vector element type.`); >- if (VectorElementSizes.indexOf(lengthValue) < 0) >- throw new WSyntaxError(node.originString, `${lengthValue} is not a valid size for vectors with element type ${elementTypeName}.`); >- >- return `${elementTypeName}${lengthValue}`; >- // FIXME: Further cases for matrices, textures, etc. >- default: >- if (node.typeArguments.length) >- throw new WSyntaxError(`${node.name}${arguments.join(", ")} is not a permitted generic type or function`); >- return node.name; >- } >- } >- >- visitTypeRef(node) >- { >- node._name = RemoveTypeArguments.resolveNameAndArguments(node); >- node._typeArguments = null; >- } >- } >- >- program.visit(new RemoveTypeArguments()); >-} >diff --git a/Tools/WebGPUShadingLanguageRI/ResolveNames.js b/Tools/WebGPUShadingLanguageRI/ResolveNames.js >index 2e402c8d6c0a36098561e0275ee53e778fd384b8..b8b53342459ae839acf7f07c2bbaea96e8a54cdf 100644 >--- a/Tools/WebGPUShadingLanguageRI/ResolveNames.js >+++ b/Tools/WebGPUShadingLanguageRI/ResolveNames.js >@@ -31,8 +31,13 @@ function createNameResolver(program) > > function resolveNamesInTypes(program, nameResolver) > { >- for (let type of program.types.values()) >- nameResolver.doStatement(type); >+ for (let type of program.types.values()) { >+ if (type instanceof Array) { >+ for (let constituentType of type) >+ nameResolver.doStatement(constituentType); >+ } else >+ nameResolver.doStatement(type); >+ } > } > > function resolveNamesInFunctions(program, nameResolver) >diff --git a/Tools/WebGPUShadingLanguageRI/ResolveOverloadImpl.js b/Tools/WebGPUShadingLanguageRI/ResolveOverloadImpl.js >index d0f1e34d617ea27266467c161707154664a449ad..7a097bca470ecb56a6ee3def52aaf5f78b506511 100644 >--- a/Tools/WebGPUShadingLanguageRI/ResolveOverloadImpl.js >+++ b/Tools/WebGPUShadingLanguageRI/ResolveOverloadImpl.js >@@ -100,3 +100,28 @@ function resolveOverloadImpl(functions, argumentTypes, returnType, allowEntryPoi > > return {failures: ambiguityList.map(overload => new OverloadResolutionFailure(overload.func, message))}; > } >+ >+function resolveTypeOverloadImpl(types, typeArguments) >+{ >+ if (!types) >+ throw new Error("Null types; that should have been caught by the caller."); >+ >+ let failures = []; >+ let successes = []; >+ for (let type of types) { >+ let overload = inferTypesForTypeArguments(type, typeArguments); >+ if (overload.failure) >+ failures.push(overload.failure); >+ else >+ successes.push(overload); >+ } >+ >+ if (!successes.length) >+ return {failures: failures}; >+ >+ if (successes.length == 1) >+ return successes[0]; >+ >+ let message = "Ambiguous overload - types mutually applicable"; >+ return {failures: successes.map(overload => new TypeOverloadResolutionFailure(overload.type, message))}; >+} >diff --git a/Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js b/Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js >index 9143f8e1e00a049814b90a345c5af451459d8574..0574becd5531509478a2defdc2fe7c68e61c3d35 100644 >--- a/Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js >+++ b/Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js >@@ -27,8 +27,13 @@ > function resolveTypeDefsInTypes(program) > { > let resolver = new TypeDefResolver(); >- for (let type of program.types.values()) >- type.visit(resolver); >+ for (let type of program.types.values()) { >+ if (type instanceof Array) { >+ for (let constituentType of type) >+ constituentType.visit(resolver); >+ } else >+ type.visit(resolver); >+ } > } > > function resolveTypeDefsInFunctions(program) >diff --git a/Tools/WebGPUShadingLanguageRI/Rewriter.js b/Tools/WebGPUShadingLanguageRI/Rewriter.js >index d547d203f0dbf8cabee4377803bd5b084e9807bc..a1b6015b364062d1f84163aea081283014f266c7 100644 >--- a/Tools/WebGPUShadingLanguageRI/Rewriter.js >+++ b/Tools/WebGPUShadingLanguageRI/Rewriter.js >@@ -97,7 +97,9 @@ class Rewriter { > > visitTypeRef(node) > { >- let result = new TypeRef(node.origin, node.name); >+ let result = new TypeRef(node.origin, node.name, node.typeArguments.map(argument => argument.visit(this))); >+ if (node.possibleOverloads) >+ result.possibleOverloads = node.possibleOverloads.map(overload => Node.visit(overload, this)); > if (node.type) > result.type = Node.visit(node.type, this); > return result; >@@ -382,7 +384,7 @@ class Rewriter { > > visitVectorType(node) > { >- const vecType = new VectorType(node.origin, node.name); >+ const vecType = new VectorType(node.origin, node.name, node.typeArguments.map(argument => argument.visit(this))); > vecType._elementType = node.elementType.visit(this); > return vecType; > } >diff --git a/Tools/WebGPUShadingLanguageRI/SPIRV.html b/Tools/WebGPUShadingLanguageRI/SPIRV.html >index c7b3940f2b11bd89614f14a9b52c47a56166ab14..20be7c84c9af970f13d154e2e44cd349db3c7481 100644 >--- a/Tools/WebGPUShadingLanguageRI/SPIRV.html >+++ b/Tools/WebGPUShadingLanguageRI/SPIRV.html >@@ -43,6 +43,7 @@ td { > <script src="CheckRecursion.js"></script> > <script src="CheckRecursiveTypes.js"></script> > <script src="CheckReturns.js"></script> >+ <script src="CheckTypesWithArguments.js"></script> > <script src="CheckUnreachableCode.js"></script> > <script src="CheckWrapped.js"></script> > <script src="Checker.js"></script> >@@ -116,7 +117,6 @@ td { > <script src="ReadModifyWriteExpression.js"></script> > <script src="RecursionChecker.js"></script> > <script src="RecursiveTypeChecker.js"></script> >- <script src="RemoveTypeArguments.js"></script> > <script src="ResolveNames.js"></script> > <script src="ResolveOverloadImpl.js"></script> > <script src="ResolveProperties.js"></script> >@@ -140,6 +140,7 @@ td { > <script src="TypeDef.js"></script> > <script src="TypeDefResolver.js"></script> > <script src="TypeRef.js"></script> >+ <script src="TypeOverloadResolutionFailure.js"></script> > <script src="TypedValue.js"></script> > <script src="UintLiteral.js"></script> > <script src="UintLiteralType.js"></script> >diff --git a/Tools/WebGPUShadingLanguageRI/StandardLibrary.js b/Tools/WebGPUShadingLanguageRI/StandardLibrary.js >index 06b251cf0a24819cab5065ef5445e1489d5eaafc..8190a4356923a61e5485bdd4f180d1383774898b 100644 >--- a/Tools/WebGPUShadingLanguageRI/StandardLibrary.js >+++ b/Tools/WebGPUShadingLanguageRI/StandardLibrary.js >@@ -33,17 +33,70 @@ let standardLibrary = ` > native typedef void; > native typedef bool; > native typedef uchar; >+native typedef ushort; > native typedef uint; >+native typedef char; >+native typedef short; > native typedef int; >+native typedef half; > native typedef float; >- >-// FIXME: Add support for these types to Intrinsics.js >-// native typedef ushort; >-// native typedef char; >-// native typedef short; >-// native typedef half; >-// native typedef atomic_int; >-// native typedef atomic_uint; >+native typedef atomic_int; >+native typedef atomic_uint; >+ >+native typedef vector<bool, 2>; >+typedef bool2 = vector<bool, 2>; >+native typedef vector<bool, 3>; >+typedef bool3 = vector<bool, 3>; >+native typedef vector<bool, 4>; >+typedef bool4 = vector<bool, 4>; >+native typedef vector<uchar, 2>; >+typedef uchar2 = vector<uchar, 2>; >+native typedef vector<uchar, 3>; >+typedef uchar3 = vector<uchar, 3>; >+native typedef vector<uchar, 4>; >+typedef uchar4 = vector<uchar, 4>; >+native typedef vector<ushort, 2>; >+typedef ushort2 = vector<ushort, 2>; >+native typedef vector<ushort, 3>; >+typedef ushort3 = vector<ushort, 3>; >+native typedef vector<ushort, 4>; >+typedef ushort4 = vector<ushort, 4>; >+native typedef vector<uint, 2>; >+typedef uint2 = vector<uint, 2>; >+native typedef vector<uint, 3>; >+typedef uint3 = vector<uint, 3>; >+native typedef vector<uint, 4>; >+typedef uint4 = vector<uint, 4>; >+native typedef vector<char, 2>; >+typedef char2 = vector<char, 2>; >+native typedef vector<char, 3>; >+typedef char3 = vector<char, 3>; >+native typedef vector<char, 4>; >+typedef char4 = vector<char, 4>; >+native typedef vector<short, 2>; >+typedef short2 = vector<short, 2>; >+native typedef vector<short, 3>; >+typedef short3 = vector<short, 3>; >+native typedef vector<short, 4>; >+typedef short4 = vector<short, 4>; >+native typedef vector<int, 2>; >+typedef int2 = vector<int, 2>; >+native typedef vector<int, 3>; >+typedef int3 = vector<int, 3>; >+native typedef vector<int, 4>; >+typedef int4 = vector<int, 4>; >+native typedef vector<half, 2>; >+typedef half2 = vector<half, 2>; >+native typedef vector<half, 3>; >+typedef half3 = vector<half, 3>; >+native typedef vector<half, 4>; >+typedef half4 = vector<half, 4>; >+native typedef vector<float, 2>; >+typedef float2 = vector<float, 2>; >+native typedef vector<float, 3>; >+typedef float3 = vector<float, 3>; >+native typedef vector<float, 4>; >+typedef float4 = vector<float, 4>; > > native operator int(uint); > native operator int(uchar); >@@ -147,28 +200,12 @@ bool operator~(bool value) > { > return !value; > } >- >-native typedef uchar2; >-native typedef uchar3; >-native typedef uchar4; >- >-native typedef uint2; >-native typedef uint3; >-native typedef uint4; >- >-native typedef int2; >-native typedef int3; >-native typedef int4; >- >-native typedef float2; >-native typedef float3; >-native typedef float4; > `; > > // FIXME: Once the standard library has been replaced with a new version, this comments should be removed. > // This list is used to restrict the availability of vector types available in the langauge. > // Permissible vector element types must appear in this list and in the standard library >-const VectorElementTypes = [ /*"bool",*/ "uchar", /*"char", "ushort", "short",*/ "uint", "int", /* "half", */"float" ]; >+const VectorElementTypes = [ "bool", "uchar", "char", "ushort", "short", "uint", "int", "half", "float" ]; > const VectorElementSizes = [ 2, 3, 4 ]; > > function allVectorTypeNames() >diff --git a/Tools/WebGPUShadingLanguageRI/StatementCloner.js b/Tools/WebGPUShadingLanguageRI/StatementCloner.js >index b3948c450c7160977975ed4e8e98ed99c4f7a059..0d0715a9854def1bfd2a808c7404112ba1a4a0c1 100644 >--- a/Tools/WebGPUShadingLanguageRI/StatementCloner.js >+++ b/Tools/WebGPUShadingLanguageRI/StatementCloner.js >@@ -50,7 +50,7 @@ class StatementCloner extends Rewriter { > > visitNativeType(node) > { >- return new NativeType(node.origin, node.name); >+ return new NativeType(node.origin, node.name, node.typeArguments.map(argument => argument.visit(this))); > } > > visitTypeDef(node) >diff --git a/Tools/WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js b/Tools/WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js >index fefe9c03d7b10b3116b3b67f2af057f16fc1516c..3a3f7673867b9aab013221803568738c163a567e 100644 >--- a/Tools/WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js >+++ b/Tools/WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js >@@ -45,6 +45,12 @@ function synthesizeDefaultConstructorOperator(program) > types.add(node); > super.visitElementalType(node); > } >+ >+ visitVectorType(node) >+ { >+ types.add(node); >+ super.visitVectorType(node); >+ } > } > > program.visit(new FindAllTypes()); >diff --git a/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js b/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js >index bfe604494dc725ae7e74ad4a0bfe23e93c091776..a0181468a25ed4c09050d7bf1d61f44ed3a0aa66 100644 >--- a/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js >+++ b/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js >@@ -51,7 +51,7 @@ function synthesizeStructAccessors(program) > > function createTypeRef() > { >- return TypeRef.instantiate(type); >+ return TypeRef.wrap(type); > } > > let isCast = false; >diff --git a/Tools/WebGPUShadingLanguageRI/Test.html b/Tools/WebGPUShadingLanguageRI/Test.html >index 13f358239929d8a3e6ace52545b91ca52d6060e4..0de6941d5902f0dccf488c945155c1fa3ab5bb9c 100644 >--- a/Tools/WebGPUShadingLanguageRI/Test.html >+++ b/Tools/WebGPUShadingLanguageRI/Test.html >@@ -37,6 +37,7 @@ > <script src="CheckRecursion.js"></script> > <script src="CheckRecursiveTypes.js"></script> > <script src="CheckReturns.js"></script> >+<script src="CheckTypesWithArguments.js"></script> > <script src="CheckUnreachableCode.js"></script> > <script src="CheckWrapped.js"></script> > <script src="Checker.js"></script> >@@ -110,7 +111,6 @@ > <script src="ReadModifyWriteExpression.js"></script> > <script src="RecursionChecker.js"></script> > <script src="RecursiveTypeChecker.js"></script> >-<script src="RemoveTypeArguments.js"></script> > <script src="ResolveNames.js"></script> > <script src="ResolveOverloadImpl.js"></script> > <script src="ResolveProperties.js"></script> >@@ -134,6 +134,7 @@ > <script src="TypeDef.js"></script> > <script src="TypeDefResolver.js"></script> > <script src="TypeRef.js"></script> >+<script src="TypeOverloadResolutionFailure.js"></script> > <script src="TypedValue.js"></script> > <script src="UintLiteral.js"></script> > <script src="UintLiteralType.js"></script> >diff --git a/Tools/WebGPUShadingLanguageRI/Test.js b/Tools/WebGPUShadingLanguageRI/Test.js >index df417dabf6d87135e735ca8c9b1bf13ab64075a1..bffbcf0b2cb6dcb257f1fc3992e8ec6534456d9c 100644 >--- a/Tools/WebGPUShadingLanguageRI/Test.js >+++ b/Tools/WebGPUShadingLanguageRI/Test.js >@@ -2881,7 +2881,7 @@ tests.shaderTypes = function() > } > fragment Boo bar(Foo stageIn) > { >- return boo(); >+ return Boo(); > } > `), > (e) => e instanceof WTypeError); >@@ -2904,7 +2904,7 @@ tests.shaderTypes = function() > > tests.vectorTypeSyntax = function() > { >- const program = doPrep(` >+ let program = doPrep(` > int foo2() > { > int2 x; >@@ -2939,7 +2939,26 @@ tests.vectorTypeSyntax = function() > checkInt(program, callFunction(program, "foo2", []), 4); > checkInt(program, callFunction(program, "foo3", []), 5); > checkInt(program, callFunction(program, "foo4", []), 6); >+ checkBool(program, callFunction(program, "vec2OperatorCast", []), true); >+ >+ program = doPrep(` >+ typedef i = int; >+ int foo2() >+ { >+ int2 x; >+ vector<i, 2> z = int2(3, 4); >+ x = z; >+ return x.y; >+ } >+ >+ bool vec2OperatorCast() >+ { >+ int2 x = vector<i,2>(1, 2); >+ vector<i, 2> y = int2(1, 2); >+ return x == y && x.x == 1 && x.y == 2 && y.x == 1 && y.y == 2; >+ }`); > >+ checkInt(program, callFunction(program, "foo2", []), 4); > checkBool(program, callFunction(program, "vec2OperatorCast", []), true); > } > >diff --git a/Tools/WebGPUShadingLanguageRI/TypeOverloadResolutionFailure.js b/Tools/WebGPUShadingLanguageRI/TypeOverloadResolutionFailure.js >new file mode 100644 >index 0000000000000000000000000000000000000000..d5cb3f710fa0ce03d2902fa32ed8b0275fb62608 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/TypeOverloadResolutionFailure.js >@@ -0,0 +1,42 @@ >+/* >+ * Copyright (C) 2018 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 TypeOverloadResolutionFailure { >+ constructor(type, reason) >+ { >+ this._type = type; >+ this._reason = reason; >+ } >+ >+ get type() { return this._type; } >+ get reason() { return this._reason; } >+ >+ toString() >+ { >+ return this.type.toString() + " did not match because: " + this.reason; >+ } >+} >+ >diff --git a/Tools/WebGPUShadingLanguageRI/TypeRef.js b/Tools/WebGPUShadingLanguageRI/TypeRef.js >index b5f3c0b3d92532e05c680054a161f05e0ddd646b..8b64e67b9f5f7415252cb24c92eeb9f4846bdbf1 100644 >--- a/Tools/WebGPUShadingLanguageRI/TypeRef.js >+++ b/Tools/WebGPUShadingLanguageRI/TypeRef.js >@@ -25,12 +25,13 @@ > "use strict"; > > class TypeRef extends Type { >- constructor(origin, name, typeArguments = null) >+ constructor(origin, name, typeArguments = []) > { > super(); > this._origin = origin; > this._name = name; > this._type = null; >+ this._possibleOverloads = null; > this._typeArguments = typeArguments; > } > >@@ -38,14 +39,11 @@ class TypeRef extends Type { > { > if (type instanceof TypeRef) > return type; >- let result = new TypeRef(type.origin, type.name); >- result.type = type; >- return result; >- } >- >- static instantiate(type) >- { >- let result = new TypeRef(type.origin, type.name); >+ let result; >+ if (type instanceof NativeType) >+ result = new TypeRef(type.origin, type.name, type.typeArguments); >+ else >+ result = new TypeRef(type.orgin, type.name); > result.type = type; > return result; > } >@@ -63,6 +61,51 @@ class TypeRef extends Type { > { > this._type = newType; > } >+ >+ get possibleOverloads() >+ { >+ return this._possibleOverloads; >+ } >+ >+ set possibleOverloads(newOverloads) >+ { >+ if (this.type) >+ throw new Error("TypeRefs with known type should not have overloads."); >+ this._possibleOverloads = newOverloads; >+ } >+ >+ resolve(possibleOverloads, program) >+ { >+ if (!possibleOverloads) >+ throw new WTypeError(this.origin.originString, "Did not find any types named " + this.name); >+ >+ let failures = []; >+ let overload = resolveTypeOverloadImpl(possibleOverloads, this.typeArguments); >+ >+ if (!overload.type) { >+ failures.push(...overload.failures); >+ let message = "Did not find type named " + this.name + " for type arguments "; >+ message += "(" + this.typeArguments + ")"; >+ if (failures.length) >+ message += ", but considered:\n" + failures.join("\n") >+ throw new WTypeError(this.origin.originString, message); >+ } >+ >+ for (let i = 0; i < this.typeArguments.length; ++i) { >+ let typeArgument = this.typeArguments[i]; >+ let resolvedTypeArgument = overload.type.typeArguments[i]; >+ let result = typeArgument.equalsWithCommit(resolvedTypeArgument); >+ if (!result) >+ throw new Error("At " + this.origin.originString + " argument types for Type and TypeRef not equal: argument type = " + typeArgument + ", resolved type argument = " + resolvedTypeArgument); >+ if (resolvedTypeArgument.constructor.name == "GenericLiteral") { >+ result = typeArgument.type.equalsWithCommit(resolvedTypeArgument.type); >+ if (!result) >+ throw new Error("At " + this.origin.originString + " argument types for Type and TypeRef not equal: argument type = " + typeArgument + ", resolved type argument = " + resolvedTypeArgument); >+ } >+ >+ } >+ this.type = overload.type; >+ } > > get unifyNode() > { >@@ -99,7 +142,10 @@ class TypeRef extends Type { > { > if (!this.name) > return this.type.toString(); >- return this.name; >+ let result = this.name; >+ if (this.typeArguments.length > 0) >+ result += "<" + this.typeArguments.map(argument => argument.toString()).join(",") + ">"; >+ return result; > } > } > >diff --git a/Tools/WebGPUShadingLanguageRI/UnificationContext.js b/Tools/WebGPUShadingLanguageRI/UnificationContext.js >index 2f71547b0afbe180378f37996231862a2b91a82e..38191697223ef721a537914b3698976781fe6e6e 100644 >--- a/Tools/WebGPUShadingLanguageRI/UnificationContext.js >+++ b/Tools/WebGPUShadingLanguageRI/UnificationContext.js >@@ -92,6 +92,19 @@ class UnificationContext { > > verify() > { >+ // We do a two-phase pre-verification. This gives literals a chance to select a more specific type. >+ let preparations = []; >+ for (let node of this.nodes) { >+ let preparation = node.prepareToVerify(this); >+ if (preparation) >+ preparations.push(preparation); >+ } >+ for (let preparation of preparations) { >+ let result = preparation(); >+ if (!result.result) >+ return result; >+ } >+ > for (let typeArgument of this.typeArguments()) { > let result = typeArgument.verifyAsArgument(this); > if (!result.result) >diff --git a/Tools/WebGPUShadingLanguageRI/VectorType.js b/Tools/WebGPUShadingLanguageRI/VectorType.js >index 5014c671a07882002c234bb32f17c8860effc1c6..df0cbc2c7308f45413cbcc28d89621bc03ab2604 100644 >--- a/Tools/WebGPUShadingLanguageRI/VectorType.js >+++ b/Tools/WebGPUShadingLanguageRI/VectorType.js >@@ -25,19 +25,14 @@ > "use strict"; > > class VectorType extends NativeType { >- constructor(origin, name) >+ constructor(origin, name, typeArguments) > { >- super(origin, name); >- const match = /^([A-z]+)([0-9])$/.exec(name); >- if (!match) >- throw new WTypeError(origin.originString, `${name} doesn't match the format for vector type names.'`); >- >- this._elementType = new TypeRef(origin, match[1]); >- this._numElementsValue = parseInt(match[2]); >+ super(origin, name, typeArguments); > } > >- get elementType() { return this._elementType; } >- get numElementsValue() { return this._numElementsValue; } >+ get elementType() { return this.typeArguments[0]; } >+ get numElements() { return this.typeArguments[1]; } >+ get numElementsValue() { return this.numElements.value; } > get size() { return this.elementType.size * this.numElementsValue; } > > unifyImpl(unificationContext, other) >@@ -59,7 +54,7 @@ class VectorType extends NativeType { > > toString() > { >- return `native typedef ${this.elementType}${this.numElementsValue}`; >+ return `native typedef vector<${this.elementType}, ${this.numElementsValue}>`; > } > } > >diff --git a/Tools/WebGPUShadingLanguageRI/Visitor.js b/Tools/WebGPUShadingLanguageRI/Visitor.js >index 7d387b25f2589b873918af2f44c2434ad658747f..60dfcebf1ae1d598d32980d56d784f14538d553c 100644 >--- a/Tools/WebGPUShadingLanguageRI/Visitor.js >+++ b/Tools/WebGPUShadingLanguageRI/Visitor.js >@@ -68,10 +68,14 @@ class Visitor { > > visitTypeRef(node) > { >+ for (let typeArgument of node.typeArguments) >+ typeArgument.visit(this); > } > > visitNativeType(node) > { >+ for (let typeArgument of node.typeArguments) >+ typeArgument.visit(this); > } > > visitTypeDef(node) >@@ -327,6 +331,7 @@ class Visitor { > visitVectorType(node) > { > node.elementType.visit(this); >+ node.numElements.visit(this); > } > } > >diff --git a/Tools/WebGPUShadingLanguageRI/index.html b/Tools/WebGPUShadingLanguageRI/index.html >index 4c93a33e6a38662e8ba1e842403d4c02d5e9f9df..9c31ce9f4a847649456e547507b0b32e056acb1b 100644 >--- a/Tools/WebGPUShadingLanguageRI/index.html >+++ b/Tools/WebGPUShadingLanguageRI/index.html >@@ -38,6 +38,7 @@ > <script src="CheckRecursiveTypes.js"></script> > <script src="CheckReturns.js"></script> > <script src="CheckUnreachableCode.js"></script> >+<script src="CheckTypesWithArguments.js"></script> > <script src="CheckWrapped.js"></script> > <script src="Checker.js"></script> > <script src="CloneProgram.js"></script> >@@ -110,7 +111,6 @@ > <script src="ReadModifyWriteExpression.js"></script> > <script src="RecursionChecker.js"></script> > <script src="RecursiveTypeChecker.js"></script> >-<script src="RemoveTypeArguments.js"></script> > <script src="ResolveNames.js"></script> > <script src="ResolveOverloadImpl.js"></script> > <script src="ResolveProperties.js"></script> >@@ -134,6 +134,7 @@ > <script src="TypeDef.js"></script> > <script src="TypeDefResolver.js"></script> > <script src="TypeRef.js"></script> >+<script src="TypeOverloadResolutionFailure.js"></script> > <script src="TypedValue.js"></script> > <script src="UintLiteral.js"></script> > <script src="UintLiteralType.js"></script>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188773
:
347598
|
347673
|
347718
|
347754
|
347757
|
347837
|
347846
|
347863