[WHLSL] Add more functions to the standard library
authormmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 Aug 2018 18:21:49 +0000 (18:21 +0000)
committermmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 Aug 2018 18:21:49 +0000 (18:21 +0000)
https://bugs.webkit.org/show_bug.cgi?id=188873

Reviewed by Filip Pizlo.

This patch adds the rest of the standard library to StandardLibrary.js, and updates the compiler to be able to compile it.

There are a few major pieces:
1. Swizzle operators are now implemented in the language, instead of as native functions
2. Vector constructors are now implemented in the language, instead of as native functions
3. The matrix type is implemented
4. Vector operator&[] is illegal, and is removed from the compiler
5. Vector index setters & index getters are now implemented in the language, instead of as native functions
6. Vector and matrix equality operators are implemented in the language, instead of as native functions
7. Casting a scalar to a boolean is implemented in the language, instead of as native functions
8. Casting a vector to a boolean is not part of the language, and is removed from the compiler
9. Half-precision floating point types are implemented

* WebGPUShadingLanguageRI/All.js:
* WebGPUShadingLanguageRI/BuiltinMatrixGetter.js: Copied from Tools/WebGPUShadingLanguageRI/BuiltinVectorIndexSetter.js.
(BuiltinMatrixGetter):
(BuiltinMatrixGetter.prototype.get height):
(BuiltinMatrixGetter.prototype.get width):
(BuiltinMatrixGetter.prototype.toString):
(BuiltinMatrixGetter.functions):
(BuiltinMatrixGetter.prototype.instantiateImplementation):
* WebGPUShadingLanguageRI/BuiltinMatrixSetter.js: Renamed from Tools/WebGPUShadingLanguageRI/BuiltinVectorIndexSetter.js.
(BuiltinMatrixSetter):
(BuiltinMatrixSetter.prototype.get height):
(BuiltinMatrixSetter.prototype.get width):
(BuiltinMatrixSetter.prototype.toString):
(BuiltinMatrixSetter.functions):
(BuiltinMatrixSetter.prototype.instantiateImplementation):
* WebGPUShadingLanguageRI/BuiltinVectorConstructors.js: Removed.
* WebGPUShadingLanguageRI/BuiltinVectorEqualityOperator.js: Removed.
* WebGPUShadingLanguageRI/BuiltinVectorGetter.js:
(BuiltinVectorGetter.prototype.instantiateImplementation):
(BuiltinVectorGetter):
* WebGPUShadingLanguageRI/BuiltinVectorSetter.js:
(BuiltinVectorSetter.functions):
(BuiltinVectorSetter.prototype.instantiateImplementation):
(BuiltinVectorSetter):
* WebGPUShadingLanguageRI/CallExpression.js:
(CallExpression.prototype.resolve):
* WebGPUShadingLanguageRI/CheckTypesWithArguments.js:
(checkTypesWithArguments.TypeWithArgumentsChecker.prototype.visitTypeRef):
(checkTypesWithArguments.TypeWithArgumentsChecker):
(checkTypesWithArguments):
* WebGPUShadingLanguageRI/Checker.js:
(Checker.prototype.visitVectorType):
(Checker.prototype.visitMatrixType):
* WebGPUShadingLanguageRI/ConstexprFolder.js:
(ConstexprFolder.prototype.visitCallExpression):
(ConstexprFolder):
* WebGPUShadingLanguageRI/Evaluator.js:
(Evaluator.prototype.visitTernaryExpression):
* WebGPUShadingLanguageRI/FlattenedStructOffsetGatherer.js:
(FlattenedStructOffsetGatherer.prototype.visitMatrixType):
(FlattenedStructOffsetGatherer):
* WebGPUShadingLanguageRI/Intrinsics.js:
(Intrinsics.):
(Intrinsics):
* WebGPUShadingLanguageRI/MatrixType.js: Renamed from Tools/WebGPUShadingLanguageRI/BuiltinVectorIndexGetter.js.
(MatrixType):
(MatrixType.prototype.get elementType):
(MatrixType.prototype.get numRows):
(MatrixType.prototype.get numColumns):
(MatrixType.prototype.get numRowsValue):
(MatrixType.prototype.get numColumnsValue):
(MatrixType.prototype.get size):
(MatrixType.prototype.unifyImpl):
(MatrixType.prototype.populateDefaultValue):
(MatrixType.prototype.toString):
* WebGPUShadingLanguageRI/NameContext.js:
(NameContext.prototype.add):
* WebGPUShadingLanguageRI/NativeType.js:
(NativeType.create):
(NativeType):
* WebGPUShadingLanguageRI/OperatorAnderIndexer.js: Renamed from Tools/WebGPUShadingLanguageRI/OperatorAnderIndex.js.
(OperatorAnderIndexer):
* WebGPUShadingLanguageRI/OperatorBool.js: Removed.
* WebGPUShadingLanguageRI/Prepare.js:
(let.prepare):
* WebGPUShadingLanguageRI/Program.js:
(Program.prototype.add):
* WebGPUShadingLanguageRI/Rewriter.js:
(Rewriter.prototype.visitMatrixType):
(Rewriter):
* WebGPUShadingLanguageRI/SPIRV.html:
* WebGPUShadingLanguageRI/StandardLibrary.js:
(operator.bool):
(bool.operator):
(uchar.operator):
(ushort.operator):
(char.operator):
(short.operator):
(uint.operator):
(int.operator):
(half.operator):
(float.operator):
(uchar2.operator):
(uchar3.operator):
(uchar4.operator):
(ushort2.operator):
(ushort3.operator):
(ushort4.operator):
(uint2.operator):
(uint3.operator):
(uint4.operator):
(char2.operator):
(char3.operator):
(char4.operator):
(short2.operator):
(short3.operator):
(short4.operator):
(int2.operator):
(int3.operator):
(int4.operator):
(half2.operator):
(half3.operator):
(half4.operator):
(float2.operator):
(float3.operator):
(float4.operator):
(half2x2.operator):
(half2x3.operator):
(half2x4.operator):
(half3x2.operator):
(half3x3.operator):
(half3x4.operator):
(half4x2.operator):
(half4x3.operator):
(half4x4.operator):
(float2x2.operator):
(float2x3.operator):
(float2x4.operator):
(float3x2.operator):
(float3x3.operator):
(float3x4.operator):
(float4x2.operator):
(float4x3.operator):
(float4x4.operator):
(operator.bool2):
(operator.bool3):
(operator.bool4):
(uint.operator.length):
(operator.uchar2):
(operator.uchar3):
(operator.uchar4):
(operator.ushort2):
(operator.ushort3):
(operator.ushort4):
(operator.uint2):
(operator.uint3):
(operator.uint4):
(operator.char2):
(operator.char3):
(operator.char4):
(operator.short2):
(operator.short3):
(operator.short4):
(operator.int2):
(operator.int3):
(operator.int4):
(operator.half2):
(operator.half3):
(operator.half4):
(operator.float2):
(operator.float3):
(operator.float4):
(bool2.operator):
(bool3.operator):
(bool4.operator):
(allVectorTypeNames):
* WebGPUShadingLanguageRI/SwizzleOp.js: Removed.
* WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js:
(synthesizeDefaultConstructorOperator.FindAllTypes.prototype.visitMatrixType):
(synthesizeDefaultConstructorOperator.FindAllTypes):
(synthesizeDefaultConstructorOperator):
* WebGPUShadingLanguageRI/SynthesizeOperatorBool.js: Removed.
* WebGPUShadingLanguageRI/Test.html:
* WebGPUShadingLanguageRI/Test.js:
(makeHalf):
(checkHalf):
* WebGPUShadingLanguageRI/Visitor.js:
(Visitor.prototype.visitMatrixType):
(Visitor):
* WebGPUShadingLanguageRI/index.html:

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

32 files changed:
Tools/ChangeLog
Tools/WebGPUShadingLanguageRI/All.js
Tools/WebGPUShadingLanguageRI/BuiltinMatrixGetter.js [moved from Tools/WebGPUShadingLanguageRI/BuiltinVectorIndexSetter.js with 64% similarity]
Tools/WebGPUShadingLanguageRI/BuiltinMatrixSetter.js [moved from Tools/WebGPUShadingLanguageRI/BuiltinVectorEqualityOperator.js with 58% similarity]
Tools/WebGPUShadingLanguageRI/BuiltinVectorConstructors.js [deleted file]
Tools/WebGPUShadingLanguageRI/BuiltinVectorGetter.js
Tools/WebGPUShadingLanguageRI/BuiltinVectorSetter.js
Tools/WebGPUShadingLanguageRI/CallExpression.js
Tools/WebGPUShadingLanguageRI/CheckTypesWithArguments.js
Tools/WebGPUShadingLanguageRI/Checker.js
Tools/WebGPUShadingLanguageRI/ConstexprFolder.js
Tools/WebGPUShadingLanguageRI/Evaluator.js
Tools/WebGPUShadingLanguageRI/FlattenedStructOffsetGatherer.js
Tools/WebGPUShadingLanguageRI/Intrinsics.js
Tools/WebGPUShadingLanguageRI/MatrixType.js [moved from Tools/WebGPUShadingLanguageRI/BuiltinVectorIndexGetter.js with 55% similarity]
Tools/WebGPUShadingLanguageRI/NameContext.js
Tools/WebGPUShadingLanguageRI/NativeFunc.js
Tools/WebGPUShadingLanguageRI/NativeType.js
Tools/WebGPUShadingLanguageRI/OperatorAnderIndexer.js [moved from Tools/WebGPUShadingLanguageRI/OperatorAnderIndex.js with 81% similarity]
Tools/WebGPUShadingLanguageRI/OperatorBool.js [deleted file]
Tools/WebGPUShadingLanguageRI/Prepare.js
Tools/WebGPUShadingLanguageRI/Program.js
Tools/WebGPUShadingLanguageRI/Rewriter.js
Tools/WebGPUShadingLanguageRI/SPIRV.html
Tools/WebGPUShadingLanguageRI/StandardLibrary.js
Tools/WebGPUShadingLanguageRI/SwizzleOp.js [deleted file]
Tools/WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js
Tools/WebGPUShadingLanguageRI/SynthesizeOperatorBool.js [deleted file]
Tools/WebGPUShadingLanguageRI/Test.html
Tools/WebGPUShadingLanguageRI/Test.js
Tools/WebGPUShadingLanguageRI/Visitor.js
Tools/WebGPUShadingLanguageRI/index.html

index 3a7eb4d..86700d0 100644 (file)
@@ -1,3 +1,194 @@
+2018-08-29  Myles C. Maxfield  <mmaxfield@apple.com>
+
+        [WHLSL] Add more functions to the standard library
+        https://bugs.webkit.org/show_bug.cgi?id=188873
+
+        Reviewed by Filip Pizlo.
+
+        This patch adds the rest of the standard library to StandardLibrary.js, and updates the compiler to be able to compile it.
+
+        There are a few major pieces:
+        1. Swizzle operators are now implemented in the language, instead of as native functions
+        2. Vector constructors are now implemented in the language, instead of as native functions
+        3. The matrix type is implemented
+        4. Vector operator&[] is illegal, and is removed from the compiler
+        5. Vector index setters & index getters are now implemented in the language, instead of as native functions
+        6. Vector and matrix equality operators are implemented in the language, instead of as native functions
+        7. Casting a scalar to a boolean is implemented in the language, instead of as native functions
+        8. Casting a vector to a boolean is not part of the language, and is removed from the compiler
+        9. Half-precision floating point types are implemented
+
+        * WebGPUShadingLanguageRI/All.js:
+        * WebGPUShadingLanguageRI/BuiltinMatrixGetter.js: Copied from Tools/WebGPUShadingLanguageRI/BuiltinVectorIndexSetter.js.
+        (BuiltinMatrixGetter):
+        (BuiltinMatrixGetter.prototype.get height):
+        (BuiltinMatrixGetter.prototype.get width):
+        (BuiltinMatrixGetter.prototype.toString):
+        (BuiltinMatrixGetter.functions):
+        (BuiltinMatrixGetter.prototype.instantiateImplementation):
+        * WebGPUShadingLanguageRI/BuiltinMatrixSetter.js: Renamed from Tools/WebGPUShadingLanguageRI/BuiltinVectorIndexSetter.js.
+        (BuiltinMatrixSetter):
+        (BuiltinMatrixSetter.prototype.get height):
+        (BuiltinMatrixSetter.prototype.get width):
+        (BuiltinMatrixSetter.prototype.toString):
+        (BuiltinMatrixSetter.functions):
+        (BuiltinMatrixSetter.prototype.instantiateImplementation):
+        * WebGPUShadingLanguageRI/BuiltinVectorConstructors.js: Removed.
+        * WebGPUShadingLanguageRI/BuiltinVectorEqualityOperator.js: Removed.
+        * WebGPUShadingLanguageRI/BuiltinVectorGetter.js:
+        (BuiltinVectorGetter.prototype.instantiateImplementation):
+        (BuiltinVectorGetter):
+        * WebGPUShadingLanguageRI/BuiltinVectorSetter.js:
+        (BuiltinVectorSetter.functions):
+        (BuiltinVectorSetter.prototype.instantiateImplementation):
+        (BuiltinVectorSetter):
+        * WebGPUShadingLanguageRI/CallExpression.js:
+        (CallExpression.prototype.resolve):
+        * WebGPUShadingLanguageRI/CheckTypesWithArguments.js:
+        (checkTypesWithArguments.TypeWithArgumentsChecker.prototype.visitTypeRef):
+        (checkTypesWithArguments.TypeWithArgumentsChecker):
+        (checkTypesWithArguments):
+        * WebGPUShadingLanguageRI/Checker.js:
+        (Checker.prototype.visitVectorType):
+        (Checker.prototype.visitMatrixType):
+        * WebGPUShadingLanguageRI/ConstexprFolder.js:
+        (ConstexprFolder.prototype.visitCallExpression):
+        (ConstexprFolder):
+        * WebGPUShadingLanguageRI/Evaluator.js:
+        (Evaluator.prototype.visitTernaryExpression):
+        * WebGPUShadingLanguageRI/FlattenedStructOffsetGatherer.js:
+        (FlattenedStructOffsetGatherer.prototype.visitMatrixType):
+        (FlattenedStructOffsetGatherer):
+        * WebGPUShadingLanguageRI/Intrinsics.js:
+        (Intrinsics.):
+        (Intrinsics):
+        * WebGPUShadingLanguageRI/MatrixType.js: Renamed from Tools/WebGPUShadingLanguageRI/BuiltinVectorIndexGetter.js.
+        (MatrixType):
+        (MatrixType.prototype.get elementType):
+        (MatrixType.prototype.get numRows):
+        (MatrixType.prototype.get numColumns):
+        (MatrixType.prototype.get numRowsValue):
+        (MatrixType.prototype.get numColumnsValue):
+        (MatrixType.prototype.get size):
+        (MatrixType.prototype.unifyImpl):
+        (MatrixType.prototype.populateDefaultValue):
+        (MatrixType.prototype.toString):
+        * WebGPUShadingLanguageRI/NameContext.js:
+        (NameContext.prototype.add):
+        * WebGPUShadingLanguageRI/NativeType.js:
+        (NativeType.create):
+        (NativeType):
+        * WebGPUShadingLanguageRI/OperatorAnderIndexer.js: Renamed from Tools/WebGPUShadingLanguageRI/OperatorAnderIndex.js.
+        (OperatorAnderIndexer):
+        * WebGPUShadingLanguageRI/OperatorBool.js: Removed.
+        * WebGPUShadingLanguageRI/Prepare.js:
+        (let.prepare):
+        * WebGPUShadingLanguageRI/Program.js:
+        (Program.prototype.add):
+        * WebGPUShadingLanguageRI/Rewriter.js:
+        (Rewriter.prototype.visitMatrixType):
+        (Rewriter):
+        * WebGPUShadingLanguageRI/SPIRV.html:
+        * WebGPUShadingLanguageRI/StandardLibrary.js:
+        (operator.bool):
+        (bool.operator):
+        (uchar.operator):
+        (ushort.operator):
+        (char.operator):
+        (short.operator):
+        (uint.operator):
+        (int.operator):
+        (half.operator):
+        (float.operator):
+        (uchar2.operator):
+        (uchar3.operator):
+        (uchar4.operator):
+        (ushort2.operator):
+        (ushort3.operator):
+        (ushort4.operator):
+        (uint2.operator):
+        (uint3.operator):
+        (uint4.operator):
+        (char2.operator):
+        (char3.operator):
+        (char4.operator):
+        (short2.operator):
+        (short3.operator):
+        (short4.operator):
+        (int2.operator):
+        (int3.operator):
+        (int4.operator):
+        (half2.operator):
+        (half3.operator):
+        (half4.operator):
+        (float2.operator):
+        (float3.operator):
+        (float4.operator):
+        (half2x2.operator):
+        (half2x3.operator):
+        (half2x4.operator):
+        (half3x2.operator):
+        (half3x3.operator):
+        (half3x4.operator):
+        (half4x2.operator):
+        (half4x3.operator):
+        (half4x4.operator):
+        (float2x2.operator):
+        (float2x3.operator):
+        (float2x4.operator):
+        (float3x2.operator):
+        (float3x3.operator):
+        (float3x4.operator):
+        (float4x2.operator):
+        (float4x3.operator):
+        (float4x4.operator):
+        (operator.bool2):
+        (operator.bool3):
+        (operator.bool4):
+        (uint.operator.length):
+        (operator.uchar2):
+        (operator.uchar3):
+        (operator.uchar4):
+        (operator.ushort2):
+        (operator.ushort3):
+        (operator.ushort4):
+        (operator.uint2):
+        (operator.uint3):
+        (operator.uint4):
+        (operator.char2):
+        (operator.char3):
+        (operator.char4):
+        (operator.short2):
+        (operator.short3):
+        (operator.short4):
+        (operator.int2):
+        (operator.int3):
+        (operator.int4):
+        (operator.half2):
+        (operator.half3):
+        (operator.half4):
+        (operator.float2):
+        (operator.float3):
+        (operator.float4):
+        (bool2.operator):
+        (bool3.operator):
+        (bool4.operator):
+        (allVectorTypeNames):
+        * WebGPUShadingLanguageRI/SwizzleOp.js: Removed.
+        * WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js:
+        (synthesizeDefaultConstructorOperator.FindAllTypes.prototype.visitMatrixType):
+        (synthesizeDefaultConstructorOperator.FindAllTypes):
+        (synthesizeDefaultConstructorOperator):
+        * WebGPUShadingLanguageRI/SynthesizeOperatorBool.js: Removed.
+        * WebGPUShadingLanguageRI/Test.html:
+        * WebGPUShadingLanguageRI/Test.js:
+        (makeHalf):
+        (checkHalf):
+        * WebGPUShadingLanguageRI/Visitor.js:
+        (Visitor.prototype.visitMatrixType):
+        (Visitor):
+        * WebGPUShadingLanguageRI/index.html:
+
 2018-08-29  Simon Fraser  <simon.fraser@apple.com>
 
         Teach webkitpy how to check leaks and treat leaks as test failures
index 315bec2..9c2a371 100644 (file)
@@ -34,7 +34,6 @@ load("Visitor.js");
 load("CreateLiteral.js");
 load("CreateLiteralType.js");
 load("PropertyAccessExpression.js");
-load("SwizzleOp.js");
 load("NativeType.js");
 
 load("AddressSpace.js");
@@ -46,12 +45,10 @@ load("AutoWrapper.js");
 load("Block.js");
 load("BoolLiteral.js");
 load("Break.js");
-load("BuiltinVectorConstructors.js");
+load("BuiltinMatrixGetter.js");
+load("BuiltinMatrixSetter.js");
 load("BuiltinVectorGetter.js");
 load("BuiltinVectorSetter.js");
-load("BuiltinVectorIndexGetter.js");
-load("BuiltinVectorIndexSetter.js");
-load("BuiltinVectorEqualityOperator.js");
 load("CallExpression.js");
 load("CallFunction.js");
 load("Check.js");
@@ -113,6 +110,7 @@ load("LogicalNot.js");
 load("LoopChecker.js");
 load("MakeArrayRefExpression.js");
 load("MakePtrExpression.js");
+load("MatrixType.js");
 load("NameContext.js");
 load("NameFinder.js");
 load("NameResolver.js");
@@ -120,9 +118,8 @@ load("NativeFunc.js");
 load("NormalUsePropertyResolver.js");
 load("NullLiteral.js");
 load("NullType.js");
-load("OperatorAnderIndex.js");
+load("OperatorAnderIndexer.js");
 load("OperatorArrayRefLength.js");
-load("OperatorBool.js");
 load("OriginKind.js");
 load("OverloadResolutionFailure.js");
 load("Parse.js");
@@ -150,7 +147,6 @@ load("SwitchStatement.js");
 load("SynthesizeArrayOperatorLength.js");
 load("SynthesizeEnumFunctions.js");
 load("SynthesizeStructAccessors.js");
-load("SynthesizeOperatorBool.js");
 load("SynthesizeCopyConstructorOperator.js");
 load("SynthesizeDefaultConstructorOperator.js");
 load("TernaryExpression.js");
  */
 "use strict";
 
-class BuiltinVectorIndexSetter {
-    constructor(baseTypeName, size)
+class BuiltinMatrixGetter {
+    constructor(baseTypeName, height, width)
     {
         this._baseTypeName = baseTypeName;
-        this._size = size;
+        this._height = height;
+        this._width = width;
     }
 
     get baseTypeName() { return this._baseTypeName; }
-    get size() { return this._size; }
-    get elementName() { return this._elementName; }
-    get index() { return this._index; }
+    get height() { return this._height; }
+    get width() { return this._width; }
 
     toString()
     {
-        return `native ${this.baseTypeName}${this.size} operator[]=(${this.baseTypeName}${this.size},uint,${this.baseTypeName})`;
+        return `native ${this.baseTypeName}${this.width} operator[](${this.baseTypeName}${this.height}x${this.width},uint)`;
     }
 
     static functions()
@@ -46,9 +46,11 @@ class BuiltinVectorIndexSetter {
         if (!this._functions) {
             this._functions = [];
 
-            for (let typeName of VectorElementTypes) {
-                for (let size of VectorElementSizes)
-                    this._functions.push(new BuiltinVectorIndexSetter(typeName, size));
+            for (let typeName of ["half", "float"]) {
+                for (let height of [2, 3, 4]) {
+                    for (let width of [2, 3, 4])
+                        this._functions.push(new BuiltinMatrixGetter(typeName, height, width));
+                }
             }
         }
         return this._functions;
@@ -56,16 +58,16 @@ class BuiltinVectorIndexSetter {
 
     instantiateImplementation(func)
     {
-        func.implementation = ([base, index, value], node) => {
+        func.implementation = ([mat, index]) => {
             const indexValue = index.loadValue();
-            if (indexValue >= 0 && indexValue < this.size) {
-                let result = new EPtr(new EBuffer(this.size), 0);
-                result.copyFrom(base, this.size);
-                result.plus(indexValue).copyFrom(value, 1);
+            if (indexValue >= 0 && indexValue < this.height) {
+                const result = new EPtr(new EBuffer(this.width), 0);
+                for (let i = 0; i < this.width; i++)
+                    result.set(i, mat.get(indexValue * this.width + i));
                 return result;
             } else
-                throw new Error(`${indexValue} out of bounds for vector of size ${this.size}`);
+                throw new WTrapError("[Builtin matrix getter]", "Out-of-bounds index when indexing into a matrix");
         };
         func.implementationData = this;
     }
-}
\ No newline at end of file
+}
  * 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.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 "use strict";
 
-class BuiltinVectorEqualityOperator {
-    constructor(baseTypeName, size)
+class BuiltinMatrixSetter {
+    constructor(baseTypeName, height, width)
     {
         this._baseTypeName = baseTypeName;
-        this._size = size;
+        this._height = height;
+        this._width = width;
     }
 
     get baseTypeName() { return this._baseTypeName; }
-    get size() { return this._size; }
+    get height() { return this._height; }
+    get width() { return this._width; }
 
     toString()
     {
-        return `native bool operator==(${this.baseTypeName}${this.size},${this.baseTypeName}${this.size})`;
+        return `native ${this.baseTypeName}${this.height}x${this.width} operator[]=(${this.baseTypeName}${this.height}x${this.width},uint,${this.baseTypeName}${this.width})`;
     }
 
     static functions()
@@ -44,9 +46,11 @@ class BuiltinVectorEqualityOperator {
         if (!this._functions) {
             this._functions = [];
 
-            for (let typeName of VectorElementTypes) {
-                for (let size of VectorElementSizes)
-                    this._functions.push(new BuiltinVectorEqualityOperator(typeName, size));
+            for (let typeName of ["half", "float"]) {
+                for (let height of [2, 3, 4]) {
+                    for (let width of [2, 3, 4])
+                        this._functions.push(new BuiltinMatrixSetter(typeName, height, width));
+                }
             }
         }
         return this._functions;
@@ -54,13 +58,16 @@ class BuiltinVectorEqualityOperator {
 
     instantiateImplementation(func)
     {
-        func.implementation = ([ref1, ref2], node) => {
-            for (let i = 0; i < this.size; i++) {
-                if (ref1.get(i) != ref2.get(i))
-                    return EPtr.box(false);
-            }
-            return EPtr.box(true);
+        func.implementation = ([base, index, value]) => {
+            const indexValue = index.loadValue();
+            if (indexValue >= 0 && indexValue < this.height) {
+                let result = new EPtr(new EBuffer(this.width * this.height), 0);
+                result.copyFrom(base, this.width * this.height);
+                result.plus(indexValue * this.width).copyFrom(value, this.width);
+                return result;
+            } else
+                throw new WTrapError("[Builtin matrix setter]", "Out-of-bounds index when indexing into a matrix");
         };
         func.implementationData = this;
     }
-}
\ No newline at end of file
+}
diff --git a/Tools/WebGPUShadingLanguageRI/BuiltinVectorConstructors.js b/Tools/WebGPUShadingLanguageRI/BuiltinVectorConstructors.js
deleted file mode 100644 (file)
index 2704b43..0000000
+++ /dev/null
@@ -1,84 +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";
-
-class BuiltinVectorConstructors {
-    constructor(baseTypeName, parameterSizes)
-    {
-        this._baseTypeName = baseTypeName;
-        this._parameterSizes = parameterSizes;
-    }
-
-    get baseTypeName() { return this._baseTypeName; }
-    get parameterSizes() { return this._parameterSizes; }
-    get outputSize()
-    {
-        return this.parameterSizes.reduce((a, b) => a + b, 0);
-    }
-
-    toString()
-    {
-        return `native operator ${this.baseTypeName}${this.outputSize}(${this.parameterSizes.map(x => x == 1 ? this.baseTypeName : this.baseTypeName + x).join(",")})`;
-    }
-
-    static functions()
-    {
-        if (!this._functions) {
-            this._functions = [];
-
-            for (let typeName of VectorElementTypes) {
-                for (let size of VectorElementSizes) {
-                    for (let paramSizes of this._vectorParameterSizesForMaximumSize(size))
-                        this._functions.push(new BuiltinVectorConstructors(typeName, paramSizes));
-                }
-            }
-        }
-        return this._functions;
-    }
-
-    static _vectorParameterSizesForMaximumSize(maxSize)
-    {
-        let variants = [ [ maxSize ] ];
-        for (let splitPoint = 1; splitPoint < maxSize; splitPoint++) {
-            for (let v of BuiltinVectorConstructors._vectorParameterSizesForMaximumSize(maxSize - splitPoint))
-                variants.push([ splitPoint ].concat(v));
-        }
-        return variants;
-    }
-
-    instantiateImplementation(func)
-    {
-        func.implementation = (args) => {
-            const result = new EPtr(new EBuffer(this.outputSize), 0);
-            let offset = 0;
-            for (let i = 0; i < args.length; i++) {
-                for (let j = 0; j < this.parameterSizes[i]; j++)
-                    result.set(offset++, args[i].get(j));
-            }
-            return result;
-        };
-        func.implementationData = this;
-    }
-}
\ No newline at end of file
index c253f76..40872b4 100644 (file)
@@ -62,9 +62,9 @@ class BuiltinVectorGetter {
 
     instantiateImplementation(func)
     {
-        func.implementation = ([vec], node) => {
+        func.implementation = ([vec]) => {
             return EPtr.box(vec.get(this.index));
         };
         func.implementationData = this;
     }
-}
\ No newline at end of file
+}
index a2d763b..d559591 100644 (file)
@@ -47,7 +47,7 @@ class BuiltinVectorSetter {
     {
         if (!this._functions) {
             this._functions = [];
-        
+
             const elements = [ "x", "y", "z", "w" ];
 
             for (let typeName of VectorElementTypes) {
@@ -62,7 +62,7 @@ class BuiltinVectorSetter {
 
     instantiateImplementation(func)
     {
-        func.implementation = ([base, value], node) => {
+        func.implementation = ([base, value]) => {
             let result = new EPtr(new EBuffer(this.size), 0);
             result.copyFrom(base, this.size);
             result.plus(this.index).copyFrom(value, 1);
@@ -70,4 +70,4 @@ class BuiltinVectorSetter {
         };
         func.implementationData = this;
     }
-}
\ No newline at end of file
+}
index 3b15455..5fbdd50 100644 (file)
@@ -52,19 +52,22 @@ class CallExpression extends Expression {
 
     resolve(possibleOverloads, program)
     {
-        if (!possibleOverloads)
-            throw new WTypeError(this.origin.originString, "Did not find any functions named " + this.name);
-
         let failures = [];
-        let overload = resolveOverloadImpl(possibleOverloads, this.argumentTypes, this.returnType);
+        let overload;
+        if (possibleOverloads)
+            overload = resolveOverloadImpl(possibleOverloads, this.argumentTypes, this.returnType);
 
-        if (!overload.func) {
+        if (!overload || !overload.func) {
+            if (!overload)
+                overload = {};
             const func = this._resolveByInstantiation(program);
             if (func)
                 overload.func = func;
         }
 
         if (!overload.func) {
+            if (!overload.failures)
+                overload.failures = [];
             failures.push(...overload.failures);
             let message = "Did not find function named " + this.name + " for call with ";
             message += "argument types (" + this.argumentTypes + ")";
index bb6b2bd..2f69142 100644 (file)
@@ -29,8 +29,20 @@ 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.");
+            if ((node.name == "vector" && node.typeArguments.length != 2)
+                || (node.name == "matrix" && node.typeArguments.length != 3)
+                || (node.name == "Texture1D" && node.typeArguments.length != 1)
+                || (node.name == "RWTexture1D" && node.typeArguments.length != 1)
+                || (node.name == "Texture1DArray" && node.typeArguments.length != 1)
+                || (node.name == "RWTexture1DArray" && node.typeArguments.length != 1)
+                || (node.name == "Texture2D" && node.typeArguments.length != 1)
+                || (node.name == "RWTexture2D" && node.typeArguments.length != 1)
+                || (node.name == "Texture2DArray" && node.typeArguments.length != 1)
+                || (node.name == "RWTexture2DArray" && node.typeArguments.length != 1)
+                || (node.name == "Texture3D" && node.typeArguments.length != 1)
+                || (node.name == "RWTexture3D" && node.typeArguments.length != 1)
+                || (node.name == "TextureCube" && node.typeArguments.length != 1))
+                throw new Error(`Builtin type ${node.name} should always have type arguments.`);
         }
     }
     program.visit(new TypeWithArgumentsChecker());
index c69d554..5f598b2 100644 (file)
@@ -263,6 +263,7 @@ class Checker extends Visitor {
     visitVectorType(node)
     {
         node.elementType.visit(this);
+        node.numElements.visit(this);
 
         let isKnownAllowedVectorElementType = false;
         for (let vectorElementTypeName of VectorElementTypes) {
@@ -277,6 +278,33 @@ class Checker extends Visitor {
 
         if (!isKnownAllowedVectorElementType)
             throw new WTypeError(`${node.elementType} is not a permitted vector element type.`);
+        if (node.numElementsValue != 2 && node.numElementsValue != 3 && node.numElementsValue != 4)
+            throw new WTypeError(`${node.toString()}: ${node.numElementsValue} is not 2, 3, or 4.`);
+    }
+
+    visitMatrixType(node)
+    {
+        node.elementType.visit(this);
+        node.numRows.visit(this);
+        node.numColumns.visit(this);
+
+        let isKnownAllowedVectorElementType = false;
+        for (let elementTypeName of ["half", "float"]) {
+            const elementType = this._program.globalNameContext.get(Type, elementTypeName);
+            if (!elementType)
+                throw new WTypeError(`${elementTypeName} is not a known native type in the standard library or intrinsics.`);
+            if (elementType.equals(node.elementType)) {
+                isKnownAllowedVectorElementType = true;
+                break;
+            }
+        }
+
+        if (!isKnownAllowedVectorElementType)
+            throw new WTypeError(`${node.elementType} is not a permitted vector element type.`);
+        if (node.numRowsValue != 2 && node.numRowsValue != 3 && node.numRowsValue != 4)
+            throw new WTypeError(`${node.toString()}: ${node.numRowsValue} is not 2, 3, or 4.`);
+        if (node.numColumnsValue != 2 && node.numColumnsValue != 3 && node.numColumnsValue != 4)
+            throw new WTypeError(`${node.toString()}: ${node.numColumnsValue} is not 2, 3, or 4.`);
     }
     
     visitArrayType(node)
index 5451332..36e5f6f 100644 (file)
@@ -35,9 +35,9 @@ class ConstexprFolder extends Visitor {
         
         if (node.name == "operator-"
             && node.argumentList.length == 1
-            && node.argumentList[0].unifyNode.isConstexpr
-            && node.argumentList[0].unifyNode.negConstexpr) {
-            node.become(node.argumentList[0].unifyNode.negConstexpr(node.origin));
+            && node.argumentList[0].isLiteral
+            && node.argumentList[0].negConstexpr) {
+            node.become(node.argumentList[0].negConstexpr(node.origin));
             return;
         }
     }
index 0290de2..aee0a23 100644 (file)
@@ -148,7 +148,6 @@ class Evaluator extends Visitor {
         if (node.predicate.visit(this).loadValue())
             return node.bodyExpression.visit(this);
         return node.elseExpression.visit(this);
-        
     }
     
     visitVariableRef(node)
index 53c8716..2739d7b 100644 (file)
@@ -73,5 +73,17 @@ class FlattenedStructOffsetGatherer extends Visitor {
             });
         }
     }
+
+    visitMatrixType(node)
+    {
+        const fieldNames = [ "row0", "row1", "row2", "row3" ];
+        for (let i = 0; i < node.numRowsValue; i++) {
+            this._result.push({
+                name: this._name.join(".") + "." + fieldNames[i],
+                offset: this._offset + i * node.elementType.size * node.numColumnsValue,
+                type: node.elementType.name + node.numColumnsValue.toString()
+            });
+        }
+    }
 }
 
index 7229063..79f5907 100644 (file)
@@ -273,7 +273,7 @@ class Intrinsics {
                  type.size = 1;
                  type.isFloating = true;
                  type.isNumber = true;
-                 type.canRepresent = value => isBitwiseEquivalent(castToHalf(value), value);
+                 type.canRepresent = value => true;
                  type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
                  type.formatValueFromIntLiteral = value => value;
                  type.formatValueFromUintLiteral = value => value;
@@ -288,7 +288,7 @@ class Intrinsics {
                  type.size = 1;
                  type.isFloating = true;
                  type.isNumber = true;
-                 type.canRepresent = value => isBitwiseEquivalent(Math.fround(value), value);
+                 type.canRepresent = value => true;
                  type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
                  type.formatValueFromIntLiteral = value => value;
                  type.formatValueFromUintLiteral = value => value;
@@ -316,90 +316,238 @@ class Intrinsics {
             }
         }
 
+        for (let type of ["half", "float"]) {
+            for (let height = 2; height <= 4; ++height) {
+                for (let width = 2; width <= 4; ++width) {
+                    this._map.set(`native typedef matrix<${type}, ${height}, ${width}>`, type => {
+                        this[`matrix<${type}, ${height}, ${width}>`] = type;
+                    });
+                }
+            }
+        }
+
         this._map.set(
-            "native operator int(uint)",
-            func => {
-                func.implementation = ([value]) => EPtr.box(value.loadValue() | 0);
-            });
+            "native typedef sampler",
+            type => {
+                this.sampler = type;
+                // FIXME: Figure out what to put here.
+            });
+
+        for (let textureType of ["Texture1D", "RWTexture1D", "Texture1DArray", "RWTexture1DArray", "Texture2D", "RWTexture2D", "Texture2DArray", "RWTexture2DArray", "Texture3D", "RWTexture3D", "TextureCube"]) {
+            for (let typeArgument of ["bool", "uchar", "ushort", "uint", "char", "short", "int", "half", "float"]) {
+                this._map.set(
+                    `native typedef ${textureType}<${typeArgument}>`,
+                    type => {
+                        this[`${textureType}<${typeArgument}>`] = type;
+                    });
+                for (let i = 2; i <= 4; ++i) {
+                    this._map.set(
+                        `native typedef ${textureType}<${typeArgument}${i}>`,
+                        type => {
+                            this[`${textureType}<${typeArgument}${i}>`] = type;
+                        });
+                }
+            }
+        }
+
+        for (let textureType of ["TextureDepth2D", "RWTextureDepth2D", "TextureDepth2DArray", "RWTextureDepth2DArray", "TextureDepthCube"]) {
+            for (let typeArgument of ["float", "half"]) {
+                this._map.set(
+                    `native typedef ${textureType}<${typeArgument}>`,
+                    type => {
+                        this[`${textureType}<${typeArgument}>`] = type;
+                    });
+            }
+        }
+
+        for (let primitiveType of ["ushort", "uint", "char", "short", "int", "half", "float"]) {
+            this._map.set(
+                `native operator uchar(${primitiveType})`,
+                func => {
+                    func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff);
+                });
+        }
+
+        for (let primitiveType of ["uchar", "uint", "char", "short", "int", "half", "float"]) {
+            this._map.set(
+                `native operator ushort(${primitiveType})`,
+                func => {
+                    func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xffff);
+                });
+        }
+
+        for (let primitiveType of ["uchar", "ushort", "char", "short", "int", "half", "float"]) {
+            this._map.set(
+                `native operator uint(${primitiveType})`,
+                func => {
+                    func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
+                });
+        }
+
+        for (let primitiveType of ["uchar", "ushort", "uint", "short", "int", "half", "float"]) {
+            this._map.set(
+                `native operator char(${primitiveType})`,
+                func => {
+                    func.implementation = ([value]) => EPtr.box(cast(Int8Array, value.loadValue()));
+                });
+        }
+
+        for (let primitiveType of ["uchar", "ushort", "uint", "char", "int", "half", "float"]) {
+            this._map.set(
+                `native operator short(${primitiveType})`,
+                func => {
+                    func.implementation = ([value]) => EPtr.box(cast(Int16Array, value.loadValue()));
+                });
+        }
+
+        for (let primitiveType of ["uchar", "ushort", "uint", "char", "short", "half", "float"]) {
+            this._map.set(
+                `native operator int(${primitiveType})`,
+                func => {
+                    func.implementation = ([value]) => EPtr.box(cast(Int32Array, value.loadValue()));
+                });
+        }
+
+        for (let primitiveType of ["uchar", "ushort", "uint", "char", "short", "int", "float"]) {
+            this._map.set(
+                `native operator half(${primitiveType})`,
+                func => {
+                    func.implementation = ([value]) => EPtr.box(castToHalf(value.loadValue()));
+                });
+        }
+
+        for (let primitiveType of ["uchar", "ushort", "uint", "char", "short", "int", "half"]) {
+            this._map.set(
+                `native operator float(${primitiveType})`,
+                func => {
+                    func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
+                });
+        }
 
         this._map.set(
-            "native operator int(uchar)",
+            `native operator int(atomic_int)`,
             func => {
-                func.implementation = ([value]) => EPtr.box(value.loadValue() | 0);
+                func.implementation = ([value]) => EPtr.box(value.loadValue());
             });
 
         this._map.set(
-            "native operator int(float)",
+            `native operator uint(atomic_uint)`,
             func => {
-                func.implementation = ([value]) => EPtr.box(value.loadValue() | 0);
+                func.implementation = ([value]) => EPtr.box(value.loadValue());
             });
 
         this._map.set(
-            "native operator uint(int)",
+            "native bool operator==(bool,bool)",
             func => {
-                func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
+                func.implementation = ([left, right]) =>
+                    EPtr.box(left.loadValue() == right.loadValue());
             });
 
+        for (let primitiveType of ["uint", "int", "float"]) {
+            this._map.set(
+                `native bool operator==(${primitiveType},${primitiveType})`,
+                func => {
+                    func.implementation = ([left, right]) =>
+                        EPtr.box(left.loadValue() == right.loadValue());
+                });
+
+            this._map.set(
+                `native bool operator<(${primitiveType},${primitiveType})`,
+                func => {
+                    func.implementation = ([left, right]) =>
+                        EPtr.box(left.loadValue() < right.loadValue());
+                });
+
+            this._map.set(
+                `native bool operator<=(${primitiveType},${primitiveType})`,
+                func => {
+                    func.implementation = ([left, right]) =>
+                        EPtr.box(left.loadValue() <= right.loadValue());
+                });
+
+            this._map.set(
+                `native bool operator>(${primitiveType},${primitiveType})`,
+                func => {
+                    func.implementation = ([left, right]) =>
+                        EPtr.box(left.loadValue() > right.loadValue());
+                });
+
+            this._map.set(
+                `native bool operator>=(${primitiveType},${primitiveType})`,
+                func => {
+                    func.implementation = ([left, right]) =>
+                        EPtr.box(left.loadValue() >= right.loadValue());
+                });
+        }
+
         this._map.set(
-            "native operator uint(uchar)",
+            "native int operator-(int)",
             func => {
-                func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
+                func.implementation = ([value]) =>
+                    EPtr.box((-value.loadValue()) | 0);
             });
 
         this._map.set(
-            "native operator uint(float)",
+            "native float operator-(float)",
             func => {
-                func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(-value.loadValue()));
             });
 
         this._map.set(
-            "native operator uchar(int)",
+            "native int operator+(int,int)",
             func => {
-                func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff);
+                func.implementation = ([left, right]) =>
+                    EPtr.box((left.loadValue() + right.loadValue()) | 0);
             });
 
         this._map.set(
-            "native operator uchar(uint)",
+            "native int operator-(int,int)",
             func => {
-                func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff);
+                func.implementation = ([left, right]) =>
+                    EPtr.box((left.loadValue() - right.loadValue()) | 0);
             });
 
         this._map.set(
-            "native operator uchar(float)",
+            "native int operator*(int,int)",
             func => {
-                func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff);
+                func.implementation = ([left, right]) =>
+                    EPtr.box((left.loadValue() * right.loadValue()) | 0);
             });
 
         this._map.set(
-            "native operator float(int)",
+            "native int operator/(int,int)",
             func => {
-                func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
+                func.implementation = ([left, right]) =>
+                    EPtr.box((left.loadValue() / right.loadValue()) | 0);
             });
 
         this._map.set(
-            "native operator float(uint)",
+            "native uint operator+(uint,uint)",
             func => {
-                func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
+                func.implementation = ([left, right]) =>
+                    EPtr.box((left.loadValue() + right.loadValue()) >>> 0);
             });
 
         this._map.set(
-            "native operator float(uchar)",
+            "native uint operator-(uint,uint)",
             func => {
-                func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
+                func.implementation = ([left, right]) =>
+                    EPtr.box((left.loadValue() - right.loadValue()) >>> 0);
             });
 
         this._map.set(
-            "native int operator+(int,int)",
+            "native uint operator*(uint,uint)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box((left.loadValue() + right.loadValue()) | 0);
+                    EPtr.box((left.loadValue() * right.loadValue()) >>> 0);
             });
 
         this._map.set(
-            "native uint operator+(uint,uint)",
+            "native uint operator/(uint,uint)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box((left.loadValue() + right.loadValue()) >>> 0);
+                    EPtr.box((left.loadValue() / right.loadValue()) >>> 0);
             });
 
         this._map.set(
@@ -410,67 +558,65 @@ class Intrinsics {
             });
 
         this._map.set(
-            "native int operator-(int,int)",
+            "native float operator-(float,float)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box((left.loadValue() - right.loadValue()) | 0);
+                    EPtr.box(Math.fround(left.loadValue() - right.loadValue()));
             });
 
         this._map.set(
-            "native uint operator-(uint,uint)",
+            "native float operator*(float,float)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box((left.loadValue() - right.loadValue()) >>> 0);
+                    EPtr.box(Math.fround(left.loadValue() * right.loadValue()));
             });
 
         this._map.set(
-            "native float operator-(float,float)",
+            "native float operator/(float,float)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box(Math.fround(left.loadValue() - right.loadValue()));
+                    EPtr.box(Math.fround(left.loadValue() / right.loadValue()));
             });
 
         this._map.set(
-            "native int operator*(int,int)",
+            "native int operator&(int,int)",
             func => {
-                func.implementation = ([left, right]) => {
-                    return EPtr.box((left.loadValue() * right.loadValue()) | 0);
-                };
+                func.implementation = ([left, right]) =>
+                    EPtr.box((left.loadValue() & right.loadValue()) | 0);
             });
 
         this._map.set(
-            "native uint operator*(uint,uint)",
+            "native int operator|(int,int)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box((left.loadValue() * right.loadValue()) >>> 0);
+                    EPtr.box((left.loadValue() | right.loadValue()) | 0);
             });
 
         this._map.set(
-            "native float operator*(float,float)",
+            "native int operator^(int,int)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box(Math.fround(left.loadValue() * right.loadValue()));
+                    EPtr.box((left.loadValue() ^ right.loadValue()) | 0);
             });
 
         this._map.set(
-            "native int operator/(int,int)",
+            "native int operator~(int)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box((left.loadValue() / right.loadValue()) | 0);
+                func.implementation = ([value]) => EPtr.box((~value.loadValue()) | 0);
             });
 
         this._map.set(
-            "native uint operator/(uint,uint)",
+            "native int operator<<(int,uint)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box((left.loadValue() / right.loadValue()) >>> 0);
+                    EPtr.box((left.loadValue() << right.loadValue()) | 0);
             });
 
         this._map.set(
-            "native int operator&(int,int)",
+            "native int operator>>(int,uint)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() & right.loadValue());
+                    EPtr.box((left.loadValue() >> right.loadValue()) | 0);
             });
 
         this._map.set(
@@ -481,223 +627,293 @@ class Intrinsics {
             });
 
         this._map.set(
-            "native int operator|(int,int)",
+            "native uint operator|(uint,uint)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() | right.loadValue());
+                    EPtr.box((left.loadValue() | right.loadValue()) >>> 0);
             });
 
         this._map.set(
-            "native uint operator|(uint,uint)",
+            "native uint operator^(uint,uint)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box((left.loadValue() | right.loadValue()) >>> 0);
+                    EPtr.box((left.loadValue() ^ right.loadValue()) >>> 0);
             });
 
         this._map.set(
-            "native int operator^(int,int)",
+            "native uint operator~(uint)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() ^ right.loadValue());
+                func.implementation = ([value]) => EPtr.box((~value.loadValue()) >>> 0);
             });
 
         this._map.set(
-            "native uint operator^(uint,uint)",
+            "native uint operator<<(uint,uint)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box((left.loadValue() ^ right.loadValue()) >>> 0);
+                    EPtr.box((left.loadValue() << right.loadValue()) >>> 0);
             });
 
         this._map.set(
-            "native int operator<<(int,uint)",
+            "native uint operator>>(uint,uint)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() << right.loadValue());
+                    EPtr.box((left.loadValue() >>> right.loadValue()) >>> 0);
             });
 
         this._map.set(
-            "native uint operator<<(uint,uint)",
+            "native float cos(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box((left.loadValue() << right.loadValue()) >>> 0);
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.cos(value.loadValue())));
             });
 
         this._map.set(
-            "native int operator>>(int,uint)",
+            "native float sin(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() >> right.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.sin(value.loadValue())));
             });
 
         this._map.set(
-            "native uint operator>>(uint,uint)",
+            "native float tan(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() >>> right.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.tan(value.loadValue())));
             });
 
         this._map.set(
-            "native int operator~(int)",
+            "native float acos(float)",
             func => {
-                func.implementation = ([value]) => EPtr.box(~value.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.acos(value.loadValue())));
             });
 
         this._map.set(
-            "native uint operator~(uint)",
+            "native float asin(float)",
             func => {
-                func.implementation = ([value]) => EPtr.box((~value.loadValue()) >>> 0);
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.asin(value.loadValue())));
             });
 
         this._map.set(
-            "native float operator/(float,float)",
+            "native float atan(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(Math.fround(left.loadValue() / right.loadValue()));
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.atan(value.loadValue())));
             });
 
         this._map.set(
-            "native bool operator==(int,int)",
+            "native float cosh(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() == right.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.cosh(value.loadValue())));
             });
 
         this._map.set(
-            "native bool operator==(uint,uint)",
+            "native float sinh(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() == right.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.sinh(value.loadValue())));
             });
 
         this._map.set(
-            "native bool operator==(bool,bool)",
+            "native float tanh(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() == right.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.tanh(value.loadValue())));
             });
 
         this._map.set(
-            "native bool operator==(float,float)",
+            "native float ceil(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() == right.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.ceil(value.loadValue())));
             });
 
         this._map.set(
-            "native bool operator<(int,int)",
+            "native float exp(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() < right.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.exp(value.loadValue())));
             });
 
         this._map.set(
-            "native bool operator<(uint,uint)",
+            "native float floor(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() < right.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.floor(value.loadValue())));
             });
 
         this._map.set(
-            "native bool operator<(float,float)",
+            "native float log(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() < right.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.log(value.loadValue())));
             });
 
         this._map.set(
-            "native bool operator<=(int,int)",
+            "native float round(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() <= right.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.round(value.loadValue())));
             });
 
         this._map.set(
-            "native bool operator<=(uint,uint)",
+            "native float sqrt(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() <= right.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.sqrt(value.loadValue())));
             });
 
         this._map.set(
-            "native bool operator<=(float,float)",
+            "native float trunc(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() <= right.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box(Math.fround(Math.trunc(value.loadValue())));
             });
 
         this._map.set(
-            "native bool operator>(int,int)",
+            "native float ddx(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() > right.loadValue());
+                func.implementation = ([value]) => EPtr.box(0);
             });
 
         this._map.set(
-            "native bool operator>(uint,uint)",
+            "native float ddy(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() > right.loadValue());
+                func.implementation = ([value]) => EPtr.box(0);
             });
 
         this._map.set(
-            "native bool operator>(float,float)",
+            "native float pow(float,float)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() > right.loadValue());
+                    EPtr.box(Math.fround(Math.pow(left.loadValue(), right.loadValue())));
             });
 
         this._map.set(
-            "native bool operator>=(int,int)",
+            "native bool isfinite(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() >= right.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box(Number.isFinite(value.loadValue()));
             });
 
         this._map.set(
-            "native bool operator>=(uint,uint)",
+            "native bool isinf(float)",
             func => {
-                func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() >= right.loadValue());
+                func.implementation = ([value]) =>
+                    EPtr.box((value.loadValue() == Number.POSITIVE_INFINITY) || (value.loadValue() == Number.NEGATIVE_INFINITY));
+            });
+
+        this._map.set(
+            "native bool isnan(float)",
+            func => {
+                func.implementation = ([value]) =>
+                    EPtr.box(Number.isNaN(value.loadValue()));
+            });
+
+        // FIXME: Implement this.
+        this._map.set(
+            "native bool isnormal(half)",
+            func => {
+                func.implementation = ([value]) =>
+                    EPtr.box(isNaN(value.loadValue()));
+            });
+
+        // FIXME: Implement this.
+        this._map.set(
+            "native bool isnormal(float)",
+            func => {
+                func.implementation = ([value]) =>
+                    EPtr.box(isNaN(value.loadValue()));
             });
 
         this._map.set(
-            "native bool operator>=(float,float)",
+            "native float atan2(float,float)",
             func => {
                 func.implementation = ([left, right]) =>
-                    EPtr.box(left.loadValue() >= right.loadValue());
+                    EPtr.box(Math.fround(Math.atan2(left.loadValue(), right.loadValue())));
             });
 
-        for (let nativeVectorTypeName of allVectorTypeNames())
-            this._map.set(`native typedef ${nativeVectorTypeName}`, type => {
-                type.isPrimitive = true;
+        this._map.set(
+            "native int asint(float)",
+            func => {
+                func.implementation = ([value]) =>
+                    EPtr.box(bitwiseCast(Float32Array, Int32Array, value.loadValue()));
             });
 
-        for (let swizzle of SwizzleOp.functions())
-            this._map.set(swizzle.toString(), func => swizzle.instantiateImplementation(func));
+        this._map.set(
+            "native uint asuint(float)",
+            func => {
+                func.implementation = ([value]) =>
+                    EPtr.box(bitwiseCast(Float32Array, Uint32Array, value.loadValue()));
+            });
+
+        this._map.set(
+            "native float asfloat(int)",
+            func => {
+                func.implementation = ([value]) =>
+                    EPtr.box(bitwiseCast(Int32Array, Float32Array, value.loadValue()));
+            });
+
+        this._map.set(
+            "native float asfloat(uint)",
+            func => {
+                func.implementation = ([value]) =>
+                    EPtr.box(bitwiseCast(Uint32Array, Float32Array, value.loadValue()));
+            });
 
-        for (let boolOp of OperatorBool.functions())
-            this._map.set(boolOp.toString(), func => boolOp.instantiateImplementation(func));
+        // FIXME: Implement this.
+        this._map.set(
+            "native float f16tof32(uint)",
+            func => {
+                func.implementation = ([value]) =>
+                    EPtr.box(0);
+            });
 
-        for (let anderIndex of OperatorAnderIndexer.functions())
-            this._map.set(anderIndex.toString(), func => anderIndex.instantiateImplementation(func));
+        // FIXME: Implement this.
+        this._map.set(
+            "native uint f32tof16(float)",
+            func => {
+                func.implementation = ([value]) =>
+                    EPtr.box(0);
+            });
 
-        for (let cast of BuiltinVectorConstructors.functions())
-            this._map.set(cast.toString(), func => cast.instantiateImplementation(func));
+        this._map.set(
+            "native void AllMemoryBarrierWithGroupSync()",
+            func => {
+                func.implementation = function() {};
+            });
 
-        for (let getter of BuiltinVectorIndexGetter.functions())
-            this._map.set(getter.toString(), func => getter.instantiateImplementation(func));
+        this._map.set(
+            "native void DeviceMemoryBarrierWithGroupSync()",
+            func => {
+                func.implementation = function() {};
+            });
 
-        for (let setter of BuiltinVectorIndexSetter.functions())
-            this._map.set(setter.toString(), func => setter.instantiateImplementation(func));
+        this._map.set(
+            "native void GroupMemoryBarrierWithGroupSync()",
+            func => {
+                func.implementation = function() {};
+            });
 
-        for (let equalityOperator of BuiltinVectorEqualityOperator.functions())
-            this._map.set(equalityOperator.toString(), func => equalityOperator.instantiateImplementation(func));
+        for (let nativeVectorTypeName of allVectorTypeNames()) {
+            this._map.set(`native typedef ${nativeVectorTypeName}`, type => {
+                type.isPrimitive = true;
+            });
+        }
 
         for (let getter of BuiltinVectorGetter.functions())
             this._map.set(getter.toString(), func => getter.instantiateImplementation(func));
 
         for (let setter of BuiltinVectorSetter.functions())
             this._map.set(setter.toString(), func => setter.instantiateImplementation(func));
+
+        for (let getter of BuiltinMatrixGetter.functions())
+            this._map.set(getter.toString(), func => getter.instantiateImplementation(func));
+
+        for (let setter of BuiltinMatrixSetter.functions())
+            this._map.set(setter.toString(), func => setter.instantiateImplementation(func));
     }
 
     add(thing)
  */
 "use strict";
 
-class BuiltinVectorIndexGetter {
-    constructor(baseTypeName, size)
+class MatrixType extends NativeType {
+    constructor(origin, name, typeArguments)
     {
-        this._baseTypeName = baseTypeName;
-        this._size = size;
+        super(origin, name, typeArguments);
     }
 
-    get baseTypeName() { return this._baseTypeName; }
-    get size() { return this._size; }
+    get elementType() { return this.typeArguments[0]; }
+    get numRows() { return this.typeArguments[1]; }
+    get numColumns() { return this.typeArguments[2]; }
+    get numRowsValue() { return this.numRows.value; }
+    get numColumnsValue() { return this.numColumns.value; }
+    get size() { return this.elementType.size * this.numRowsValue * this.numColumnsValue; }
 
-    toString()
+    unifyImpl(unificationContext, other)
     {
-        return `native ${this.baseTypeName} operator[](${this.baseTypeName}${this.size},uint)`;
+        if (!(other instanceof MatrixType))
+            return false;
+
+        if (this.numRowsValue !== other.numRowsValue || this.numColumnsValue !== other.numColumnsValue)
+            return false;
+
+        return this.elementType.unify(unificationContext, other.elementType);
     }
 
-    static functions()
+    populateDefaultValue(buffer, offset)
     {
-        if (!this._allIndexGetters) {
-            this._allIndexGetters = [];
-
-            for (let typeName of VectorElementTypes) {
-                for (let size of VectorElementSizes)
-                    this._allIndexGetters.push(new BuiltinVectorIndexGetter(typeName, size));
-            }
-        }
-        return this._allIndexGetters;
+        for (let i = 0; i < this.numRowsValue * this.numColumnsValue; ++i)
+            this.elementType.populateDefaultValue(buffer, offset + i * this.elementType.size);
     }
 
-    instantiateImplementation(func)
+    toString()
     {
-        func.implementation = ([vec, index], node) => {
-            const indexValue = index.loadValue();
-            if (indexValue >= 0 && indexValue < this.size)
-                return EPtr.box(vec.get(index.loadValue()));
-            else
-                throw new Error(`${indexValue} out of bounds for vector of size ${this.size}`);
-        };
-        func.implementationData = this;
+        return `native typedef matrix<${this.elementType}, ${this.numRowsValue}, ${this.numColumnsValue}>`;
     }
-}
\ No newline at end of file
+}
index dc68578..c89968c 100644 (file)
@@ -71,7 +71,7 @@ class NameContext {
 
         if (thing.kind == Type) {
             this._set.add(thing);
-            if (thing.name == "vector") {
+            if (thing.typeArguments && thing.typeArguments.length != 0) {
                 let array = this._map.get(thing.name);
                 if (!array) {
                     array = [];
index 997bd48..f086534 100644 (file)
@@ -31,7 +31,6 @@ class NativeFunc extends Func {
         this.isRestricted = false;
         this.implementation = null;
         this._implementationData = null;
-        this.instantiateImplementation = (substitution) => {};
         this.visitImplementationData = (implementationData, visitor) => null;
     }
 
index 2381b5a..b368a2e 100644 (file)
@@ -66,6 +66,8 @@ class NativeType extends Type {
     {
         if (name == "vector")
             return new VectorType(origin, name, typeArguments);
+        if (name == "matrix")
+            return new MatrixType(origin, name, typeArguments);
 
         return new NativeType(origin, name, typeArguments);
     }
@@ -39,22 +39,6 @@ class OperatorAnderIndexer {
         return `native ${this.baseTypeName}* ${this.addressSpace} operator&[](${this.baseTypeName}[] ${this.addressSpace},uint)`;
     }
 
-    static functions()
-    {
-        if (!this._functions) {
-            this._functions = [];
-
-            const typeNames = [ "uint", "int", "float", "bool" ].concat(allVectorTypeNames());
-            const addressSpaces = [ "thread", "threadgroup", "device", "constant" ];
-
-            for (let addressSpace of addressSpaces) {
-                for (let typeName of typeNames)
-                    this._functions.push(new OperatorAnderIndexer(typeName, addressSpace));
-            }
-        }
-        return this._functions;
-    }
-
     instantiateImplementation(func)
     {
         func.implementation = ([ref, index], node) => {
@@ -68,4 +52,4 @@ class OperatorAnderIndexer {
         };
         func.implementationData = this;
     }
-}
\ No newline at end of file
+}
diff --git a/Tools/WebGPUShadingLanguageRI/OperatorBool.js b/Tools/WebGPUShadingLanguageRI/OperatorBool.js
deleted file mode 100644 (file)
index 58bb0e0..0000000
+++ /dev/null
@@ -1,68 +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";
-
-class OperatorBool {
-    constructor(baseTypeName)
-    {
-        this._baseTypeName = baseTypeName;
-    }
-
-    get baseTypeName() { return this._baseTypeName; }
-
-    toString()
-    {
-        return `native operator bool(${this.baseTypeName})`;
-    }
-
-    static functions()
-    {
-        // FIXME: These operators should be in the standard library where possible.
-        if (!OperatorBool._functions) {
-            OperatorBool._functions = [];
-
-            // bool is not included because this is generated by the copy constructor.
-            // FIXME: Include all native types.
-            const typeNames = [ "uchar", "uint", "int", "float" ].concat(allVectorTypeNames());
-
-            for (let typeName of typeNames)
-                OperatorBool._functions.push(new OperatorBool(typeName));
-        }
-        return OperatorBool._functions;
-    }
-
-    instantiateImplementation(func)
-    {
-        func.implementation = ([ref], node) => {
-            const size = node.argumentTypes[0].size;
-            for (let i = 0; i < size; ++i) {
-                if (!!ref.get(i))
-                    return EPtr.box(true);
-            }
-            return EPtr.box(false);
-        }
-        func.implementationData = this;
-    }
-}
\ No newline at end of file
index 9faca86..834592d 100644 (file)
@@ -46,7 +46,6 @@ let prepare = (() => {
         resolveTypeDefsInTypes(program);
         checkRecursiveTypes(program);
         synthesizeStructAccessors(program);
-        synthesizeOperatorBool(program);
         synthesizeEnumFunctions(program);
         synthesizeArrayOperatorLength(program);
         synthesizeCopyConstructorOperator(program);
index 1116c4f..ac1defb 100644 (file)
@@ -51,7 +51,7 @@ class Program extends Node {
                 this.functions.set(statement.name, array = []);
             array.push(statement);
         } else if (statement instanceof Type) {
-            if (statement.isNative && statement.name == "vector") {
+            if (statement.isNative && statement.typeArguments.length != 0) {
                 let array = this.types.get(statement.name);
                 if (!array)
                     this.types.set(statement.name, array = []);
index 94d3a76..7c2dfba 100644 (file)
@@ -391,5 +391,11 @@ class Rewriter {
         vecType._elementType = node.elementType.visit(this);
         return vecType;
     }
+
+    visitMatrixType(node)
+    {
+        const matType = new MatrixType(node.origin, node.name, node.typeArguments.map(argument => argument.visit(this)));
+        return matType;
+    }
 }
 
index ff2c02c..78d008f 100644 (file)
@@ -17,7 +17,6 @@ td {
     <script src="CreateLiteral.js"></script>
     <script src="CreateLiteralType.js"></script>
     <script src="PropertyAccessExpression.js"></script>
-    <script src="SwizzleOp.js"></script>
     <script src="NativeType.js"></script>
 
     <script src="AddressSpace.js"></script>
@@ -29,12 +28,10 @@ td {
     <script src="Block.js"></script>
     <script src="BoolLiteral.js"></script>
     <script src="Break.js"></script>
-    <script src="BuiltinVectorConstructors.js"></script>
+    <script src="BuiltinMatrixGetter.js"></script>
+    <script src="BuiltinMatrixSetter.js"></script>
     <script src="BuiltinVectorGetter.js"></script>
     <script src="BuiltinVectorSetter.js"></script>
-    <script src="BuiltinVectorIndexGetter.js"></script>
-    <script src="BuiltinVectorIndexSetter.js"></script>
-    <script src="BuiltinVectorEqualityOperator.js"></script>
     <script src="CallExpression.js"></script>
     <script src="CallFunction.js"></script>
     <script src="Check.js"></script>
@@ -96,6 +93,7 @@ td {
     <script src="LoopChecker.js"></script>
     <script src="MakeArrayRefExpression.js"></script>
     <script src="MakePtrExpression.js"></script>
+    <script src="MatrixType.js"></script>
     <script src="NameContext.js"></script>
     <script src="NameFinder.js"></script>
     <script src="NameResolver.js"></script>
@@ -103,9 +101,8 @@ td {
     <script src="NormalUsePropertyResolver.js"></script>
     <script src="NullLiteral.js"></script>
     <script src="NullType.js"></script>
-    <script src="OperatorAnderIndex.js"></script>
+    <script src="OperatorAnderIndexer.js"></script>
     <script src="OperatorArrayRefLength.js"></script>
-    <script src="OperatorBool.js"></script>
     <script src="OriginKind.js"></script>
     <script src="OverloadResolutionFailure.js"></script>
     <script src="Parse.js"></script>
@@ -133,7 +130,6 @@ td {
     <script src="SynthesizeArrayOperatorLength.js"></script>
     <script src="SynthesizeEnumFunctions.js"></script>
     <script src="SynthesizeStructAccessors.js"></script>
-    <script src="SynthesizeOperatorBool.js"></script>
     <script src="SynthesizeCopyConstructorOperator.js"></script>
     <script src="SynthesizeDefaultConstructorOperator.js"></script>
     <script src="TernaryExpression.js"></script>
index 8190a43..6a33236 100644 (file)
  */
 "use strict";
 
-// NOTE: The next line is line 28, and we rely on this in Prepare.js.
-let standardLibrary = `
-// This is the WSL standard library. Implementations of all of these things are in
-// Intrinsics.js.
-
-// Need to bootstrap void first.
-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;
-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);
-native operator int(float);
-native operator uint(int);
-native operator uint(uchar);
-native operator uint(float);
-native operator uchar(int);
-native operator uchar(uint);
-native operator uchar(float);
-native operator float(int);
-native operator float(uint);
-native operator float(uchar);
-
-native int operator+(int, int);
-native uint operator+(uint, uint);
-uchar operator+(uchar a, uchar b) { return uchar(uint(a) + uint(b)); }
-native float operator+(float, float);
-int operator++(int value) { return value + 1; }
-uint operator++(uint value) { return value + 1; }
-uchar operator++(uchar value) { return value + 1; }
-native int operator-(int, int);
-native uint operator-(uint, uint);
-uchar operator-(uchar a, uchar b) { return uchar(uint(a) - uint(b)); }
-native float operator-(float, float);
-int operator--(int value) { return value - 1; }
-uint operator--(uint value) { return value - 1; }
-uchar operator--(uchar value) { return value - 1; }
-native int operator*(int, int);
-native uint operator*(uint, uint);
-uchar operator*(uchar a, uchar b) { return uchar(uint(a) * uint(b)); }
-native float operator*(float, float);
-native int operator/(int, int);
-native uint operator/(uint, uint);
-uchar operator/(uchar a, uchar b) { return uchar(uint(a) / uint(b)); }
-native int operator&(int, int);
-native int operator|(int, int);
-native int operator^(int, int);
-native int operator~(int);
-native int operator<<(int, uint);
-native int operator>>(int, uint);
-native uint operator&(uint, uint);
-native uint operator|(uint, uint);
-native uint operator^(uint, uint);
-native uint operator~(uint);
-native uint operator<<(uint, uint);
-native uint operator>>(uint, uint);
-uchar operator&(uchar a, uchar b) { return uchar(uint(a) & uint(b)); }
-uchar operator|(uchar a, uchar b) { return uchar(uint(a) | uint(b)); }
-uchar operator^(uchar a, uchar b) { return uchar(uint(a) ^ uint(b)); }
-uchar operator~(uchar value) { return uchar(~uint(value)); }
-uchar operator<<(uchar a, uint b) { return uchar(uint(a) << (b & 7)); }
-uchar operator>>(uchar a, uint b) { return uchar(uint(a) >> (b & 7)); }
-native float operator/(float, float);
-native bool operator==(int, int);
-native bool operator==(uint, uint);
-bool operator==(uchar a, uchar b) { return uint(a) == uint(b); }
-native bool operator==(bool, bool);
-native bool operator==(float, float);
-native bool operator<(int, int);
-native bool operator<(uint, uint);
-bool operator<(uchar a, uchar b) { return uint(a) < uint(b); }
-native bool operator<(float, float);
-native bool operator<=(int, int);
-native bool operator<=(uint, uint);
-bool operator<=(uchar a, uchar b) { return uint(a) <= uint(b); }
-native bool operator<=(float, float);
-native bool operator>(int, int);
-native bool operator>(uint, uint);
-bool operator>(uchar a, uchar b) { return uint(a) > uint(b); }
-native bool operator>(float, float);
-native bool operator>=(int, int);
-native bool operator>=(uint, uint);
-bool operator>=(uchar a, uchar b) { return uint(a) >= uint(b); }
-native bool operator>=(float, float);
-
-bool operator&(bool a, bool b)
-{
-    if (a)
-        return b;
-    return false;
-}
-
-bool operator|(bool a, bool b)
-{
-    if (a)
-        return true;
-    if (b)
-        return true;
-    return false;
-}
-
-bool operator^(bool a, bool b)
-{
-    if (a)
-        return !b;
-    return b;
-}
-
-bool operator~(bool value)
-{
-    return !value;
-}
-`;
+let standardLibrary = (function() {
+    let result = "";
+    function print(s)
+    {
+        if (s)
+            result += s;
+        result += "\n";
+    }
+    (function() {
+        print(`// This was autogenerated from Generate_Standard_Library.swift! Do not edit!!`);
+        print();
+        
+        for (var type of [`void`, `bool`, `uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`, `atomic_int`, `atomic_uint`]) {
+            print(`native typedef ${type};`);
+        }
+        for (var type of [`bool`, `uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            for (var size of [2, 3, 4]) {
+                print(`native typedef vector<${type}, ${size}>;`);
+                print(`typedef ${type}${size} = vector<${type}, ${size}>;`);
+            }
+        }
+        print();
+        
+        for (var type of [`half`, `float`]) {
+            for (var i of [2, 3, 4]) {
+                for (var j of [2, 3, 4]) {
+                    print(`native typedef matrix<${type}, ${i}, ${j}>;`);
+                    print(`typedef ${type}${i}x${j} = matrix<${type}, ${i}, ${j}>;`);
+                }
+            }
+        }
+        print(`native typedef sampler;`);
+        for (var type of [`Texture1D`, `RWTexture1D`, `Texture1DArray`, `RWTexture1DArray`, `Texture2D`, `RWTexture2D`, `Texture2DArray`, `RWTexture2DArray`, `Texture3D`, `RWTexture3D`, `TextureCube`]) {
+            for (var typeArgumentBase of [`bool`, `uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+                for (var size of [``, `2`, `3`, `4`]) {
+                    print(`native typedef ${type}<${typeArgumentBase}${size}>;`);
+                }
+            }
+        }
+        for (var type of [`TextureDepth2D`, `RWTextureDepth2D`, `TextureDepth2DArray`, `RWTextureDepth2DArray`, `TextureDepthCube`]) {
+            for (var typeArgument of [`float`, `half`]) {
+                print(`native typedef ${type}<${typeArgument}>;`);
+            }
+        }
+        print();
+        
+        for (var type1 of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            for (var type2 of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+                if (type1 != type2) {
+                    print(`native operator ${type1}(${type2});`);
+                }
+            }
+        }
+        print();
+        
+        for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            print(`operator bool(${type} x) {`);
+            print(`    return x != 0;`);
+            print(`}`);
+        }
+        print();
+        
+        print(`native operator int(atomic_int);`);
+        print(`native operator uint(atomic_uint);`);
+        print();
+        
+        print(`native bool operator==(bool, bool);`);
+        
+        print(`bool operator&(bool a, bool b) {`);
+        print(`    return a && b;`);
+        print(`}`);
+        
+        print(`bool operator|(bool a, bool b) {`);
+        print(`    return a || b;`);
+        print(`}`);
+        
+        print(`bool operator^(bool a, bool b) {`);
+        print(`    if (a)`);
+        print(`        return !b;`);
+        print(`    return b;`);
+        print(`}`);
+        
+        print(`bool operator~(bool value) {`);
+        print(`    return !value;`);
+        print(`}`);
+        
+        for (var type of [`int`, `uint`, `float`]) {
+            print(`native ${type} operator+(${type}, ${type});`);
+            print(`native ${type} operator-(${type}, ${type});`);
+            print(`native ${type} operator*(${type}, ${type});`);
+            print(`native ${type} operator/(${type}, ${type});`);
+            print(`native bool operator==(${type}, ${type});`);
+            print(`native bool operator<(${type}, ${type});`);
+            print(`native bool operator<=(${type}, ${type});`);
+            print(`native bool operator>(${type}, ${type});`);
+            print(`native bool operator>=(${type}, ${type});`);
+        }
+        
+        for (var type of [`int`, `uint`]) {
+            print(`native ${type} operator&(${type}, ${type});`);
+            print(`native ${type} operator|(${type}, ${type});`);
+            print(`native ${type} operator^(${type}, ${type});`);
+            print(`native ${type} operator~(${type});`);
+            print(`native ${type} operator<<(${type}, uint);`);
+            print(`native ${type} operator>>(${type}, uint);`);
+        }
+        
+        for (var type of [`uchar`, `ushort`]) {
+            print(`${type} operator+(${type} a, ${type} b) {`);
+            print(`    return ${type}(uint(a) + uint(b));`);
+            print(`}`);
+            print(`${type} operator-(${type} a, ${type} b) {`);
+            print(`    return ${type}(uint(a) - uint(b));`);
+            print(`}`);
+            print(`${type} operator*(${type} a, ${type} b) {`);
+            print(`    return ${type}(uint(a) * uint(b));`);
+            print(`}`);
+            print(`${type} operator/(${type} a, ${type} b) {`);
+            print(`    return ${type}(uint(a) / uint(b));`);
+            print(`}`);
+            print(`${type} operator&(${type} a, ${type} b) {`);
+            print(`    return ${type}(uint(a) & uint(b));`);
+            print(`}`);
+            print(`${type} operator|(${type} a, ${type} b) {`);
+            print(`    return ${type}(uint(a) | uint(b));`);
+            print(`}`);
+            print(`${type} operator^(${type} a, ${type} b) {`);
+            print(`    return ${type}(uint(a) ^ uint(b));`);
+            print(`}`);
+            print(`${type} operator~(${type} a) {`);
+            print(`    return ${type}(~uint(a));`);
+            print(`}`);
+            print(`bool operator==(${type} a, ${type} b) {`);
+            print(`    return uint(a) == uint(b);`);
+            print(`}`);
+            print(`bool operator<(${type} a, ${type} b) {`);
+            print(`    return uint(a) < uint(b);`);
+            print(`}`);
+            print(`bool operator<=(${type} a, ${type} b) {`);
+            print(`    return uint(a) <= uint(b);`);
+            print(`}`);
+            print(`bool operator>(${type} a, ${type} b) {`);
+            print(`    return uint(a) > uint(b);`);
+            print(`}`);
+            print(`bool operator>=(${type} a, ${type} b) {`);
+            print(`    return uint(a) >= uint(b);`);
+            print(`}`);
+        }
+        print(`uchar operator<<(uchar a, uint b) {`);
+        print(`    return uchar(uint(a) << (b & 255));`);
+        print(`}`);
+        print(`ushort operator<<(ushort a, uint b) {`);
+        print(`    return ushort(uint(a) << (b & 65535));`);
+        print(`}`);
+        print(`uchar operator>>(uchar a, uint b) {`);
+        print(`    return uchar(uint(a) >> (b & 255));`);
+        print(`}`);
+        print(`ushort operator>>(ushort a, uint b) {`);
+        print(`    return ushort(uint(a) >> (b & 65535));`);
+        print(`}`);
+        
+        for (var type of [`char`, `short`]) {
+            print(`${type} operator+(${type} a, ${type} b) {`);
+            print(`    return ${type}(int(a) + int(b));`);
+            print(`}`);
+            print(`${type} operator-(${type} a, ${type} b) {`);
+            print(`    return ${type}(int(a) - int(b));`);
+            print(`}`);
+            print(`${type} operator*(${type} a, ${type} b) {`);
+            print(`    return ${type}(int(a) * int(b));`);
+            print(`}`);
+            print(`${type} operator/(${type} a, ${type} b) {`);
+            print(`    return ${type}(int(a) / int(b));`);
+            print(`}`);
+            print(`${type} operator&(${type} a, ${type} b) {`);
+            print(`    return ${type}(int(a) & int(b));`);
+            print(`}`);
+            print(`${type} operator|(${type} a, ${type} b) {`);
+            print(`    return ${type}(int(a) | int(b));`);
+            print(`}`);
+            print(`${type} operator^(${type} a, ${type} b) {`);
+            print(`    return ${type}(int(a) ^ int(b));`);
+            print(`}`);
+            print(`${type} operator~(${type} a) {`);
+            print(`    return ${type}(~int(a));`);
+            print(`}`);
+            print(`bool operator==(${type} a, ${type} b) {`);
+            print(`    return int(a) == int(b);`);
+            print(`}`);
+            print(`bool operator>(${type} a, ${type} b) {`);
+            print(`    return int(a) > int(b);`);
+            print(`}`);
+            print(`bool operator>=(${type} a, ${type} b) {`);
+            print(`    return int(a) >= int(b);`);
+            print(`}`);
+            print(`bool operator<(${type} a, ${type} b) {`);
+            print(`    return int(a) < int(b);`);
+            print(`}`);
+            print(`bool operator<=(${type} a, ${type} b) {`);
+            print(`    return int(a) <= int(b);`);
+            print(`}`);
+        }
+        print(`char operator<<(char a, uint b) {`);
+        print(`    return char(int(a) << (b & 255));`);
+        print(`}`);
+        print(`short operator<<(short a, uint b) {`);
+        print(`    return short(int(a) << (b & 65535));`);
+        print(`}`);
+        print(`char operator>>(char a, uint b) {`);
+        print(`    return char(int(a) >> (b & 255));`);
+        print(`}`);
+        print(`short operator>>(short a, uint b) {`);
+        print(`    return short(int(a) >> (b & 65535));`);
+        print(`}`);
+        
+        for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            print(`${type} operator++(${type} value) {`);
+            print(`    return value + 1;`);
+            print(`}`);
+            print(`${type} operator--(${type} value) {`);
+            print(`    return value - 1;`);
+            print(`}`);
+        }
+        
+        print(`half operator+(half a, half b) {`);
+        print(`    return half(float(a) + float(b));`);
+        print(`}`);
+        print(`half operator-(half a, half b) {`);
+        print(`    return half(float(a) - float(b));`);
+        print(`}`);
+        print(`half operator*(half a, half b) {`);
+        print(`    return half(float(a) * float(b));`);
+        print(`}`);
+        print(`half operator/(half a, half b) {`);
+        print(`    return half(float(a) / float(b));`);
+        print(`}`);
+        print(`bool operator==(half a, half b) {`);
+        print(`    return float(a) == float(b);`);
+        print(`}`);
+        print(`bool operator<(half a, half b) {`);
+        print(`    return float(a) < float(b);`);
+        print(`}`);
+        print(`bool operator<=(half a, half b) {`);
+        print(`    return float(a) <= float(b);`);
+        print(`}`);
+        print(`bool operator>(half a, half b) {`);
+        print(`    return float(a) < float(b);`);
+        print(`}`);
+        print(`bool operator>=(half a, half b) {`);
+        print(`    return float(a) <= float(b);`);
+        print(`}`);
+        print(`char operator-(char x) {`);
+        print(`    return char(-int(x));`);
+        print(`}`);
+        print(`short operator-(short x) {`);
+        print(`    return short(-int(x));`);
+        print(`}`);
+        print(`half operator-(half x) {`);
+        print(`    return half(-float(x));`);
+        print(`}`);
+        print(`native int operator-(int);`);
+        print(`native float operator-(float);`);
+        print();
+        
+        for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            for (var size of [2, 3, 4]) {
+                print(`${type}${size} operator+(${type}${size} a, ${type}${size} b) {`);
+                print(`    ${type}${size} result;`);
+                for (var m = 0; m < size; ++m) {
+                    print(`    result[${m}] = a[${m}] + b[${m}];`);
+                }
+                print(`    return result;`);
+                print(`}`);
+                print(`${type}${size} operator-(${type}${size} a, ${type}${size} b) {`);
+                print(`    ${type}${size} result;`);
+                for (var m = 0; m < size; ++m) {
+                    print(`    result[${m}] = a[${m}] - b[${m}];`);
+                }
+                print(`    return result;`);
+                print(`}`);
+                print(`${type}${size} operator*(${type}${size} a, ${type}${size} b) {`);
+                print(`    ${type}${size} result;`);
+                for (var m = 0; m < size; ++m) {
+                    print(`    result[${m}] = a[${m}] * b[${m}];`);
+                }
+                print(`    return result;`);
+                print(`}`);
+                print(`${type}${size} operator*(${type}${size} a, ${type} b) {`);
+                print(`    ${type}${size} result;`);
+                for (var m = 0; m < size; ++m) {
+                    print(`    result[${m}] = a[${m}] * b;`);
+                }
+                print(`    return result;`);
+                print(`}`);
+                print(`${type}${size} operator*(${type} a, ${type}${size} b) {`);
+                print(`    ${type}${size} result;`);
+                for (var m = 0; m < size; ++m) {
+                    print(`    result[${m}] = a * b[${m}];`);
+                }
+                print(`    return result;`);
+                print(`}`);
+                print(`${type}${size} operator/(${type}${size} a, ${type}${size} b) {`);
+                print(`    ${type}${size} result;`);
+                for (var m = 0; m < size; ++m) {
+                    print(`    result[${m}] = a[${m}] / b[${m}];`);
+                }
+                print(`    return result;`);
+                print(`}`);
+                print(`${type}${size} operator/(${type}${size} a, ${type} b) {`);
+                print(`    ${type}${size} result;`);
+                for (var m = 0; m < size; ++m) {
+                    print(`    result[${m}] = a[${m}] / b;`);
+                }
+                print(`    return result;`);
+                print(`}`);
+                print(`${type}${size} operator/(${type} a, ${type}${size} b) {`);
+                print(`    ${type}${size} result;`);
+                for (var m = 0; m < size; ++m) {
+                    print(`    result[${m}] = a / b[${m}];`);
+                }
+                print(`    return result;`);
+                print(`}`);
+            }
+        }
+        for (var type of [`char`, `short`, `int`, `half`, `float`]) {
+            for (var size of [2, 3, 4]) {
+                print(`${type}${size} operator-(${type}${size} a) {`);
+                print(`    ${type}${size} result;`);
+                for (var m = 0; m < size; ++m) {
+                    print(`    result[${m}] = -a[${m}];`);
+                }
+                print(`    return result;`);
+                print(`}`);
+            }
+        }
+        for (var type of [`half`, `float`]) {
+            for (var i of [2, 3, 4]) {
+                for (var j of [2, 3, 4]) {
+                    print(`${type}${i}x${j} operator+(${type}${i}x${j} a, ${type}${i}x${j} b) {`);
+                    print(`    ${type}${i}x${j} result;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}][${n}] = a[${m}][${n}] + b[${m}][${n}];`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                    print(`${type}${i}x${j} operator-(${type}${i}x${j} a, ${type}${i}x${j} b) {`);
+                    print(`    ${type}${i}x${j} result;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}][${n}] = a[${m}][${n}] - b[${m}][${n}];`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                    print(`${type}${i}x${j} operator-(${type}${i}x${j} a) {`);
+                    print(`    ${type}${i}x${j} result;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}][${n}] = -a[${m}][${n}];`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                    print(`${type}${i}x${j} operator*(${type}${i}x${j} a, ${type}${i}x${j} b) {`);
+                    print(`    ${type}${i}x${j} result;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}][${n}] = a[${m}][${n}] * b[${m}][${n}];`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                    print(`${type}${i}x${j} operator*(${type}${i}x${j} a, ${type} b) {`);
+                    print(`    ${type}${i}x${j} result;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}][${n}] = a[${m}][${n}] * b;`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                    print(`${type}${i}x${j} operator*(${type} a, ${type}${i}x${j} b) {`);
+                    print(`    ${type}${i}x${j} result;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}][${n}] = a * b[${m}][${n}];`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                    print(`${type}${i}x${j} operator/(${type}${i}x${j} a, ${type}${i}x${j} b) {`);
+                    print(`    ${type}${i}x${j} result;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}][${n}] = a[${m}][${n}] / b[${m}][${n}];`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                    print(`${type}${i}x${j} operator/(${type}${i}x${j} a, ${type} b) {`);
+                    print(`    ${type}${i}x${j} result;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}][${n}] = a[${m}][${n}] / b;`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                    print(`${type}${i}x${j} operator/(${type} a, ${type}${i}x${j} b) {`);
+                    print(`    ${type}${i}x${j} result;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}][${n}] = a / b[${m}][${n}];`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                }
+            }
+        }
+        
+        for (var type of [`bool`, `uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            print(`operator ${type}2(${type} x, ${type} y) {`);
+            print(`    ${type}2 result;`);
+            print(`    result.x = x;`);
+            print(`    result.y = y;`);
+            print(`    return result;`);
+            print(`}`);
+            print(`operator ${type}3(${type} x, ${type} y, ${type} z) {`);
+            print(`    ${type}3 result;`);
+            print(`    result.x = x;`);
+            print(`    result.y = y;`);
+            print(`    result.z = z;`);
+            print(`    return result;`);
+            print(`}`);
+            print(`operator ${type}3(${type}2 x, ${type} y) {`);
+            print(`    ${type}3 result;`);
+            print(`    result.x = x.x;`);
+            print(`    result.y = x.y;`);
+            print(`    result.z = y;`);
+            print(`    return result;`);
+            print(`}`);
+            print(`operator ${type}3(${type} x, ${type}2 y) {`);
+            print(`    ${type}3 result;`);
+            print(`    result.x = x;`);
+            print(`    result.y = y.x;`);
+            print(`    result.z = y.y;`);
+            print(`    return result;`);
+            print(`}`);
+            print(`operator ${type}4(${type} x, ${type} y, ${type} z, ${type} w) {`);
+            print(`    ${type}4 result;`);
+            print(`    result.x = x;`);
+            print(`    result.y = y;`);
+            print(`    result.z = z;`);
+            print(`    result.w = w;`);
+            print(`    return result;`);
+            print(`}`);
+            print(`operator ${type}4(${type}2 x, ${type} y, ${type} z) {`);
+            print(`    ${type}4 result;`);
+            print(`    result.x = x.x;`);
+            print(`    result.y = x.y;`);
+            print(`    result.z = y;`);
+            print(`    result.w = z;`);
+            print(`    return result;`);
+            print(`}`);
+            print(`operator ${type}4(${type} x, ${type}2 y, ${type} z) {`);
+            print(`    ${type}4 result;`);
+            print(`    result.x = x;`);
+            print(`    result.y = y.x;`);
+            print(`    result.z = y.y;`);
+            print(`    result.w = z;`);
+            print(`    return result;`);
+            print(`}`);
+            print(`operator ${type}4(${type} x, ${type} y, ${type}2 z) {`);
+            print(`    ${type}4 result;`);
+            print(`    result.x = x;`);
+            print(`    result.y = y;`);
+            print(`    result.z = z.x;`);
+            print(`    result.w = z.y;`);
+            print(`    return result;`);
+            print(`}`);
+            print(`operator ${type}4(${type}2 x, ${type}2 y) {`);
+            print(`    ${type}4 result;`);
+            print(`    result.x = x.x;`);
+            print(`    result.y = x.y;`);
+            print(`    result.z = y.x;`);
+            print(`    result.w = y.y;`);
+            print(`    return result;`);
+            print(`}`);
+            print(`operator ${type}4(${type}3 x, ${type} y) {`);
+            print(`    ${type}4 result;`);
+            print(`    result.x = x.x;`);
+            print(`    result.y = x.y;`);
+            print(`    result.z = x.z;`);
+            print(`    result.w = y;`);
+            print(`    return result;`);
+            print(`}`);
+            print(`operator ${type}4(${type} x, ${type}3 y) {`);
+            print(`    ${type}4 result;`);
+            print(`    result.x = x;`);
+            print(`    result.y = y.x;`);
+            print(`    result.z = y.y;`);
+            print(`    result.w = y.z;`);
+            print(`    return result;`);
+            print(`}`);
+            print(`uint operator.length(${type}2) {`);
+            print(`    return 2;`);
+            print(`}`);
+            print(`uint operator.length(${type}3) {`);
+            print(`    return 3;`);
+            print(`}`);
+            print(`uint operator.length(${type}4) {`);
+            print(`    return 4;`);
+            print(`}`);
+        }
+        print();
+        
+        for (var type of [`half`, `float`]) {
+            let variables = [`a`, `b`, `c`, `d`];
+            for (var m of [2, 3, 4]) {
+                for (var n of [2, 3, 4]) {
+                    let signature = `operator ${type}${m}x${n}(`;
+                    for (var i = 0; i < m; ++i) {
+                        if (i != 0) {
+                            signature += `, `;
+                        }
+                        signature += `${type}${n} ${variables[i]}`;
+                    }
+                    signature += `) {`;
+                    print(signature);
+                    print(`    ${type}${m}x${n} result;`);
+                    for (var i = 0; i < m; ++i) {
+                        print(`    result[${i}] = ${variables[i]};`);
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                }
+            }
+        }
+        print();
+        
+        for (var type of [`bool`, `uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            print(`bool operator==(${type}2 a, ${type}2 b) {`);
+            print(`    return a.x == b.x && a.y == b.y;`);
+            print(`}`);
+            print(`bool operator==(${type}3 a, ${type}3 b) {`);
+            print(`    return a.x == b.x && a.y == b.y && a.z == b.z;`);
+            print(`}`);
+            print(`bool operator==(${type}4 a, ${type}4 b) {`);
+            print(`    return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w;`);
+            print(`}`);
+            print(`native ${type} operator.x(${type}2);`);
+            print(`native ${type} operator.y(${type}2);`);
+            print(`native ${type} operator.x(${type}3);`);
+            print(`native ${type} operator.y(${type}3);`);
+            print(`native ${type} operator.z(${type}3);`);
+            print(`native ${type} operator.x(${type}4);`);
+            print(`native ${type} operator.y(${type}4);`);
+            print(`native ${type} operator.z(${type}4);`);
+            print(`native ${type} operator.w(${type}4);`);
+            print(`native ${type}2 operator.x=(${type}2, ${type});`);
+            print(`native ${type}2 operator.y=(${type}2, ${type});`);
+            print(`native ${type}3 operator.x=(${type}3, ${type});`);
+            print(`native ${type}3 operator.y=(${type}3, ${type});`);
+            print(`native ${type}3 operator.z=(${type}3, ${type});`);
+            print(`native ${type}4 operator.x=(${type}4, ${type});`);
+            print(`native ${type}4 operator.y=(${type}4, ${type});`);
+            print(`native ${type}4 operator.z=(${type}4, ${type});`);
+            print(`native ${type}4 operator.w=(${type}4, ${type});`);
+            print(`${type} operator[](${type}2 v, uint index) {`);
+            print(`    switch (index) {`);
+            print(`        case 0:`);
+            print(`            return v.x;`);
+            print(`        case 1:`);
+            print(`            return v.y;`);
+            print(`        default:`);
+            print(`            trap;`);
+            print(`    }`);
+            print(`}`);
+            print(`${type} operator[](${type}3 v, uint index) {`);
+            print(`    switch (index) {`);
+            print(`        case 0:`);
+            print(`            return v.x;`);
+            print(`        case 1:`);
+            print(`            return v.y;`);
+            print(`        case 2:`);
+            print(`            return v.z;`);
+            print(`        default:`);
+            print(`            trap;`);
+            print(`    }`);
+            print(`}`);
+            print(`${type} operator[](${type}4 v, uint index) {`);
+            print(`    switch (index) {`);
+            print(`        case 0:`);
+            print(`            return v.x;`);
+            print(`        case 1:`);
+            print(`            return v.y;`);
+            print(`        case 2:`);
+            print(`            return v.z;`);
+            print(`        case 3:`);
+            print(`            return v.w;`);
+            print(`        default:`);
+            print(`            trap;`);
+            print(`    }`);
+            print(`}`);
+            print(`${type}2 operator[]=(${type}2 v, uint index, ${type} a) {`);
+            print(`    switch (index) {`);
+            print(`        case 0:`);
+            print(`            v.x = a;`);
+            print(`            break;`);
+            print(`        case 1:`);
+            print(`            v.y = a;`);
+            print(`            break;`);
+            print(`        default:`);
+            print(`            trap;`);
+            print(`    }`);
+            print(`    return v;`);
+            print(`}`);
+            print(`${type}3 operator[]=(${type}3 v, uint index, ${type} a) {`);
+            print(`    switch (index) {`);
+            print(`        case 0:`);
+            print(`            v.x = a;`);
+            print(`            break;`);
+            print(`        case 1:`);
+            print(`            v.y = a;`);
+            print(`            break;`);
+            print(`        case 2:`);
+            print(`            v.z = a;`);
+            print(`            break;`);
+            print(`        default:`);
+            print(`            trap;`);
+            print(`    }`);
+            print(`    return v;`);
+            print(`}`);
+            print(`${type}4 operator[]=(${type}4 v, uint index, ${type} a) {`);
+            print(`    switch (index) {`);
+            print(`        case 0:`);
+            print(`            v.x = a;`);
+            print(`            break;`);
+            print(`        case 1:`);
+            print(`            v.y = a;`);
+            print(`            break;`);
+            print(`        case 2:`);
+            print(`            v.z = a;`);
+            print(`            break;`);
+            print(`        case 3:`);
+            print(`            v.w = a;`);
+            print(`            break;`);
+            print(`        default:`);
+            print(`            trap;`);
+            print(`    }`);
+            print(`    return v;`);
+            print(`}`);
+        }
+        print();
+        
+        for (var type of [`half`, `float`]) {
+            for (var m of [2, 3, 4]) {
+                for (var n of [2, 3, 4]) {
+                    print(`native ${type}${n} operator[](${type}${m}x${n}, uint);`);
+                    print(`native ${type}${m}x${n} operator[]=(${type}${m}x${n}, uint, ${type}${n});`);
+                }
+            }
+        }
+        print();
+        
+        for (var type of [`half`, `float`]) {
+            for (var i of [2, 3, 4]) {
+                for (var j of [2, 3, 4]) {
+                    print(`bool operator==(${type}${i}x${j} a, ${type}${i}x${j} b) {`);
+                    print(`    return`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`        a[${m}][${n}] == b[${m}][${n}] &&`);
+                        }
+                    }
+                    print(`    true;`);
+                    print(`}`);
+                }
+            }
+        }
+        
+        function computeSwizzle(components, maxValue, maxLength) {
+            if (components.length == maxLength) {
+                return [components];
+            } else {
+                let result = [];
+                for (var i = 0; i < maxValue; ++i) {
+                    result = result.concat(computeSwizzle(components.concat([i]), maxValue, maxLength));
+                }
+                return result;
+            }
+        }
+        
+        function component(value) {
+            switch (value) {
+                case 0:
+                    return `x`;
+                case 1:
+                    return `y`;
+                case 2:
+                    return `z`;
+                case 3:
+                    return `w`;
+                default:
+                    fatalError();
+            }
+        }
+        
+        function uniqueLength([Int]) {
+            let has0 = false;
+            let has1 = false;
+            let has2 = false;
+            let has3 = false;
+            for (var v of swizzle) {
+                switch (v) {
+                    case 0:
+                        has0 = true;
+                        break;
+                    case 1:
+                        has1 = true;
+                        break;
+                    case 2:
+                        has2 = true;
+                        break;
+                    case 3:
+                        has3 = true;
+                        break;
+                    default:
+                        fatalError();
+                }
+            }
+            let result = 0;
+            if (has0) {
+                result += 1;
+            }
+            if (has1) {
+                result += 1;
+            }
+            if (has2) {
+                result += 1;
+            }
+            if (has3) {
+                result += 1;
+            }
+            return result;
+        }
+        
+        /*
+        for (var type of [`bool`, `uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            for (var size of [2, 3, 4]) {
+                for (var maxValue of [2, 3, 4]) {
+                    for (var swizzle of computeSwizzle([], maxValue, size)) {
+                        let swizzleName = swizzle.map(component).join("");
+                        print(`${type}${size} operator.${swizzleName}(${type}${maxValue} v) {`);
+                        print(`    ${type}${size} result;`);
+                        for (var i = 0; i < size; ++i) {
+                            print(`    result.${component(i)} = v.${component(swizzle[i])};`);
+                        }
+                        print(`    return result;`);
+                        print(`}`);
+                        if (uniqueLength(swizzle) == size) {
+                            print(`${type}${maxValue} operator.${swizzleName}=(${type}${maxValue} v, ${type}${size} c) {`);
+                            print(`    ${type}${maxValue} result = v;`);
+                            for (var i = 0; i < size; ++i) {
+                                print(`    result.${component(swizzle[i])} = c.${component(i)};`);
+                            }
+                            print(`    return result;`);
+                            print(`}`);
+                        }
+                    }
+                }
+            }
+        }
+        
+        // These functions are unary floating-point scalar functions,
+        // which can also be applied to vectors and matrices component-wise.
+        (function() {
+            let nativeFunctions = [`cos`, `sin`, `tan`, `acos`, `asin`, `atan`, `cosh`, `sinh`, `tanh`, `ceil`, `exp`, `floor`, `log`, `round`, `trunc`, `ddx`, `ddy`];
+            let nonNativeFunctions = [`sqrt`, `log2`, `log10`, `frac`, `exp2`, `degrees`, `radians`, `rcp`, `rsqrt`, `saturate`, `ddx_coarse`, `ddx_fine`, `ddy_coarse`, `ddy_fine`, `fwidth`];
+        
+            for (var nativeFunction of nativeFunctions) {
+                print(`native float ${nativeFunction}(float);`);
+                print(`half ${nativeFunction}(half x) {`);
+                print(`    return half(${nativeFunction}(float(x)));`);
+                print(`}`);
+            }
+        
+            for (var type of [`half`, `float`]) {
+                print(`${type} sqrt(${type} x) {`);
+                print(`    return pow(x, 0.5);`);
+                print(`}`);
+                print(`${type} log2(${type} x) {`);
+                print(`    return log(x) / log(${type}(2));`);
+                print(`}`);
+                print(`${type} log10(${type} x) {`);
+                print(`    return log(x) / log(${type}(10));`);
+                print(`}`);
+                print(`${type} frac(${type} x) {`);
+                print(`    return x - floor(x);`);
+                print(`}`);
+                print(`${type} exp2(${type} x) {`);
+                print(`    return exp(x * log(${type}(2)));`);
+                print(`}`);
+                print(`${type} degrees(${type} x) {`);
+                print(`    return x * 180 / 3.14159;`);
+                print(`}`);
+                print(`${type} radians(${type} x) {`);
+                print(`    return x * 3.14159 / 180;`);
+                print(`}`);
+                print(`${type} rcp(${type} x) {`);
+                print(`    return 1 / x;`);
+                print(`}`);
+                print(`${type} rsqrt(${type} x) {`);
+                print(`    return 1 / sqrt(x);`);
+                print(`}`);
+                print(`${type} saturate(${type} x) {`);
+                print(`    return clamp(x, 0, 1);`);
+                print(`}`);
+                print(`${type} ddx_coarse(${type} x) {`);
+                print(`    return ddx(x);`);
+                print(`}`);
+                print(`${type} ddx_fine(${type} x) {`);
+                print(`    return ddx(x);`);
+                print(`}`);
+                print(`${type} ddy_coarse(${type} x) {`);
+                print(`    return ddy(x);`);
+                print(`}`);
+                print(`${type} ddy_fine(${type} x) {`);
+                print(`    return ddy(x);`);
+                print(`}`);
+                print(`${type} fwidth(${type} x) {`);
+                print(`    return abs(ddx(x)) + abs(ddy(x));`);
+                print(`}`);
+        
+                for (var outputFunction of nativeFunctions.concat(nonNativeFunctions)) {
+                    for (var size of [2, 3, 4]) {
+                        print(`${type}${size} ${outputFunction}(${type}${size} x) {`);
+                        print(`    ${type}${size} result;`);
+                        for (var i = 0; i < size; ++i) {
+                            print(`    result[${i}] = ${outputFunction}(x[${i}]);`);
+                        }
+                        print(`    return result;`);
+                        print(`}`);
+                    }
+                    for (var i of [2, 3, 4]) {
+                        for (var j of [2, 3, 4]) {
+                            print(`${type}${i}x${j} ${outputFunction}(${type}${i}x${j} x) {`);
+                            print(`    ${type}${i}x${j} result;`);
+                            for (var m = 0; m < i; ++m) {
+                                for (var n = 0; n < j; ++n) {
+                                    print(`    result[${m}][${n}] = ${outputFunction}(x[${m}][${n}]);`);
+                                }
+                            }
+                            print(`    return result;`);
+                            print(`}`);
+                        }
+                    }
+                }
+                print();
+            }
+        })();
+        
+        // These functions are binary floating-point scalar functions,
+        // which can also be applied to vectors and matrices component-wise.
+        (function() {
+            let nativeFunctions = [`pow`];
+        
+            for (var nativeFunction of nativeFunctions) {
+                print(`native float ${nativeFunction}(float, float);`);
+                print(`half ${nativeFunction}(half x, half y) {`);
+                print(`    return half(${nativeFunction}(float(x), float(y)));`);
+                print(`}`);
+            }
+        
+            for (var type of [`half`, `float`]) {
+                let nonNativeFunctions = [`step`, `ldexp`, `fmod`];
+        
+                print(`${type} step(${type} y, ${type} x) {`);
+                print(`    return x >= y ? 1 : 0;`);
+                print(`}`);
+                print(`${type} ldexp(${type} x, ${type} e) {`);
+                print(`    return x * pow(2, e);`);
+                print(`}`);
+                print(`${type} fmod(${type} x, ${type} y) {`);
+                print(`    uint whole = uint(x / y);`);
+                print(`    ${type} multiple = ${type}(whole) * y;`);
+                print(`    return x - multiple;`);
+                print(`}`);
+        
+                for (var outputFunction of nativeFunctions.concat(nonNativeFunctions)) {
+                    for (var size of [2, 3, 4]) {
+                        print(`${type}${size} ${outputFunction}(${type}${size} x, ${type}${size} y) {`);
+                        print(`    ${type}${size} result;`);
+                        for (var i = 0; i < size; ++i) {
+                            print(`    result[${i}] = ${outputFunction}(x[${i}], y[${i}]);`);
+                        }
+                        print(`    return result;`);
+                        print(`}`);
+                    }
+                    for (var i of [2, 3, 4]) {
+                        for (var j of [2, 3, 4]) {
+                            print(`${type}${i}x${j} ${outputFunction}(${type}${i}x${j} x, ${type}${i}x${j} y) {`);
+                            print(`    ${type}${i}x${j} result;`);
+                            for (var m = 0; m < i; ++m) {
+                                for (var n = 0; n < j; ++n) {
+                                    print(`    result[${m}][${n}] = ${outputFunction}(x[${m}][${n}], y[${m}][${n}]);`);
+                                }
+                            }
+                            print(`    return result;`);
+                            print(`}`);
+                        }
+                    }
+                }
+                print();
+            }
+        })();
+        
+        // These functions are ternary floating-point scalar functions,
+        // which can also be applied to vectors and matrices component-wise.
+        for (var type of [`half`, `float`]) {
+            let nonNativeFunctions = [`smoothstep`, `lerp`, `fma`, `mad`];
+        
+            print(`${type} smoothstep(${type} edge0, ${type} edge1, ${type} x) {`);
+            print(`    ${type} t = clamp((x - edge0) / (edge1 - edge0), 0, 1);`);
+            print(`    return t * t * (3 - 2 * t);`);
+            print(`}`);
+            print(`${type} lerp(${type} x, ${type} y, ${type} s) {`);
+            print(`    return x * (1 - s) + y * s;`);
+            print(`}`);
+            print(`${type} fma(${type} x, ${type} y, ${type} z) {`);
+            print(`    return x * y + z;`);
+            print(`}`);
+            print(`${type} mad(${type} x, ${type} y, ${type} z) {`);
+            print(`    return x * y + z;`);
+            print(`}`);
+        
+            for (var nonNativeFunction of nonNativeFunctions) {
+                for (var size of [2, 3, 4]) {
+                    print(`${type}${size} ${nonNativeFunction}(${type}${size} x, ${type}${size} y, ${type}${size} z) {`);
+                    print(`    ${type}${size} result;`);
+                    for (var i = 0; i < size; ++i) {
+                        print(`    result[${i}] = ${nonNativeFunction}(x[${i}], y[${i}], z[${i}]);`);
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                }
+                for (var i of [2, 3, 4]) {
+                    for (var j of [2, 3, 4]) {
+                        print(`${type}${i}x${j} ${nonNativeFunction}(${type}${i}x${j} x, ${type}${i}x${j} y, ${type}${i}x${j} z) {`);
+                        print(`    ${type}${i}x${j} result;`);
+                        for (var m = 0; m < i; ++m) {
+                            for (var n = 0; n < j; ++n) {
+                                print(`    result[${m}][${n}] = ${nonNativeFunction}(x[${m}][${n}], y[${m}][${n}], z[${m}][${n}]);`);
+                            }
+                        }
+                        print(`    return result;`);
+                        print(`}`);
+                    }
+                }
+            }
+            print();
+        }
+        
+        print(`native bool isnormal(half);`);
+        print(`native bool isnormal(float);`);
+        for (var type of [`half`, `float`]) {
+            for (var size of [2, 3, 4]) {
+                print(`bool${size} isnormal(${type}${size} x) {`);
+                print(`    bool${size} result;`);
+                for (var i = 0; i < size; ++i) {
+                    print(`    result[${i}] = isnormal(x[${i}]);`);
+                }
+                print(`    return result;`);
+                print(`}`);
+            }
+            print();
+        }
+        
+        (function() {
+            let nativeFunctions = [`isfinite`, `isinf`, `isnan`];
+        
+            for (var nativeFunction of nativeFunctions) {
+                print(`native bool ${nativeFunction}(float);`);
+                print(`bool ${nativeFunction}(half x) {`);
+                print(`    return ${nativeFunction}(float(x));`);
+                print(`}`);
+            }
+        
+            for (var type of [`half`, `float`]) {
+                for (var nativeFunction of nativeFunctions) {
+                    for (var size of [2, 3, 4]) {
+                        print(`bool${size} ${nativeFunction}(${type}${size} x) {`);
+                        print(`    bool${size} result;`);
+                        for (var i = 0; i < size; ++i) {
+                            print(`    result[${i}] = ${nativeFunction}(x[${i}]);`);
+                        }
+                        print(`    return result;`);
+                        print(`}`);
+                    }
+                }
+                print();
+            }
+        })()
+        
+        for (var type of [`half`, `float`]) {
+            let nonNativeFunctions = [`isordered`, `isunordered`];
+        
+            print(`bool isordered(${type} x, ${type} y) {`);
+            print(`    return (x == x) && (y == y);`);
+            print(`}`);
+            print(`bool isunordered(${type} x, ${type} y) {`);
+            print(`    return isnan(x) || isnan(y);`);
+            print(`}`);
+        
+            for (var nonNativeFunction of nonNativeFunctions) {
+                for (var size of [2, 3, 4]) {
+                    print(`bool${size} ${nonNativeFunction}(${type}${size} x, ${type}${size} y) {`);
+                    print(`    bool${size} result;`);
+                    for (var i = 0; i < size; ++i) {
+                        print(`    result[${i}] = ${nonNativeFunction}(x[${i}], y[${i}]);`);
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                }
+            }
+            print();
+        }
+        
+        print(`native float atan2(float, float);`);
+        print(`half atan2(half x, half y) {`);
+        print(`    return half(atan2(float(x), float(y)));`);
+        print(`}`);
+        for (var type of [`half`, `float`]) {
+            for (var size of [2, 3, 4]) {
+                print(`${type}${size} atan2(${type}${size} x, ${type}${size} y) {`);
+                print(`    ${type}${size} result;`);
+                for (var i = 0; i < size; ++i) {
+                    print(`    result[${i}] = atan2(x[${i}], y[${i}]);`);
+                }
+                print(`    return result;`);
+                print(`}`);
+            }
+            for (var i of [2, 3, 4]) {
+                for (var j of [2, 3, 4]) {
+                    print(`${type}${i}x${j} atan2(${type}${i}x${j} x, ${type}${i}x${j} y) {`);
+                    print(`    ${type}${i}x${j} result;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}][${n}] = atan2(x[${m}][${n}], y[${m}][${n}]);`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                }
+            }
+        }
+        print();
+        
+        for (var type of [`half`, `float`]) {
+            print(`void sincos(${type} x, thread ${type}* y, thread ${type}* z) {`);
+            print(`    *y = sin(x);`);
+            print(`    *z = cos(x);`);
+            print(`}`);
+            for (var size of [2, 3, 4]) {
+                print(`void sincos(${type}${size} x, thread ${type}${size}* y, thread ${type}${size}* z) {`);
+                // Can't take a pointer to a member of a vector.
+                print(`    ${type} sinResult;`);
+                print(`    ${type} cosResult;`);
+                for (var i = 0; i < size; ++i) {
+                    print(`    sincos(x[${i}], &sinResult, &cosResult);`);
+                    print(`    (*y)[${i}] = sinResult;`);
+                    print(`    (*z)[${i}] = cosResult;`);
+                }
+                print(`}`);
+            }
+            for (var i of [2, 3, 4]) {
+                for (var j of [2, 3, 4]) {
+                    print(`void sincos(${type}${i}x${j} x, thread ${type}${i}x${j}* y, thread ${type}${i}x${j}* z) {`);
+                    // Can't take a pointer to a member of a matrix.
+                    print(`    ${type} sinResult;`);
+                    print(`    ${type} cosResult;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    sincos(x[${m}][${n}], &sinResult, &cosResult);`);
+                            print(`    (*y)[${m}][${n}] = sinResult;`);
+                            print(`    (*z)[${m}][${n}] = cosResult;`);
+                        }
+                    }
+                    print(`}`);
+                }
+            }
+        }
+        print();
+        
+        for (var binaryFunction of [[`all`, `true`, `&&`], [`any`, `false`, `||`]]) {
+            print(`bool ${binaryFunction[0]}(bool x) {`);
+            print(`    return x;`);
+            print(`}`);
+            for (var size of [2, 3, 4]) {
+                print(`bool ${binaryFunction[0]}(bool${size} x) {`);
+                print(`    bool result = ${binaryFunction[1]};`);
+                for (var i = 0; i < size; ++i) {
+                    print(`    result = result ${binaryFunction[2]} (x[${i}]);`);
+                }
+                print(`    return result;`);
+                print(`}`);
+            }
+            for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+                print(`bool ${binaryFunction[0]}(${type} x) {`);
+                print(`    return x != 0;`);
+                print(`}`);
+                for (var size of [2, 3, 4]) {
+                    print(`bool ${binaryFunction[0]}(${type}${size} x) {`);
+                    print(`    bool result = ${binaryFunction[1]};`);
+                    for (var i = 0; i < size; ++i) {
+                        print(`    result = result ${binaryFunction[2]} (x[${i}] != 0);`);
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                }
+                if (type == `half` || type == `float`) {
+                    for (var i of [2, 3, 4]) {
+                        for (var j of [2, 3, 4]) {
+                            print(`bool ${binaryFunction[0]}(${type}${i}x${j} x) {`);
+                            print(`    bool result = ${binaryFunction[1]};`);
+                            for (var m = 0; m < i; ++m) {
+                                for (var n = 0; n < j; ++n) {
+                                    print(`    result = result ${binaryFunction[2]} (x[${m}][${n}] != 0);`);
+                                }
+                            }
+                            print(`    return result;`);
+                            print(`}`);
+                        }
+                    }
+                }
+            }
+            print();
+        }
+        
+        for (var type of [`uchar`, `ushort`, `uint`]) {
+            print(`${type} abs(${type} x) {`);
+            print(`    return x;`);
+            print(`}`);
+        }
+        for (var type of [`char`, `short`, `int`, `half`, `float`]) {
+            print(`${type} abs(${type} x) {`);
+            print(`    if (x < 0)`);
+            print(`        return -x;`);
+            print(`    return x;`);
+            print(`}`);
+        }
+        for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            for (var size of [2, 3, 4]) {
+                print(`${type}${size} abs(${type}${size} x) {`);
+                print(`    ${type}${size} result;`);
+                for (var i = 0; i < size; ++i) {
+                    print(`    result[${i}] = abs(x[${i}]);`);
+                }
+                print(`    return result;`);
+                print(`}`);
+            }
+            if (type == `half` || type == `float`) {
+                for (var i of [2, 3, 4]) {
+                    for (var j of [2, 3, 4]) {
+                        print(`${type}${i}x${j} abs(${type}${i}x${j} x) {`);
+                        print(`    ${type}${i}x${j} result;`);
+                        for (var m = 0; m < i; ++m) {
+                            for (var n = 0; n < j; ++n) {
+                                print(`    result[${m}][${n}] = abs(x[${m}][${n}]);`);
+                            }
+                        }
+                        print(`    return result;`);
+                        print(`}`);
+                    }
+                }
+            }
+        }
+        print();
+        
+        for (var type of [`uchar`, `ushort`, `uint`]) {
+            print(`${type} sign(${type} x) {`);
+            print(`    return x == 0 ? 0 : 1;`);
+            print(`}`);
+        }
+        for (var type of [`char`, `short`, `int`, `half`, `float`]) {
+            print(`${type} sign(${type} x) {`);
+            print(`    if (x < 0)`);
+            print(`        return -1;`);
+            print(`    if (x == 0)`);
+            print(`        return 0;`);
+            print(`    return 1;`);
+            print(`}`);
+        }
+        for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            for (var size of [2, 3, 4]) {
+                print(`${type}${size} sign(${type}${size} x) {`);
+                print(`    ${type}${size} result;`);
+                for (var i = 0; i < size; ++i) {
+                    print(`    result[${i}] = sign(x[${i}]);`);
+                }
+                print(`    return result;`);
+                print(`}`);
+            }
+            if (type == `half` || type == `float`) {
+                for (var i of [2, 3, 4]) {
+                    for (var j of [2, 3, 4]) {
+                        print(`${type}${i}x${j} sign(${type}${i}x${j} x) {`);
+                        print(`    ${type}${i}x${j} result;`);
+                        for (var m = 0; m < i; ++m) {
+                            for (var n = 0; n < j; ++n) {
+                                print(`    result[${m}][${n}] = sign(x[${m}][${n}]);`);
+                            }
+                        }
+                        print(`    return result;`);
+                        print(`}`);
+                    }
+                }
+            }
+        }
+        print();
+        
+        for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            let nonNativeFunctions = [`min`, `max`];
+        
+            print(`${type} min(${type} x, ${type} y) {`);
+            print(`    return x > y ? y : x;`);
+            print(`}`);
+            print(`${type} max(${type} x, ${type} y) {`);
+            print(`    return x > y ? x : y;`);
+            print(`}`);
+        
+            for (var nonNativeFunction of nonNativeFunctions) {
+                for (var size of [2, 3, 4]) {
+                    print(`${type}${size} ${nonNativeFunction}(${type}${size} x, ${type}${size} y) {`);
+                    print(`    ${type}${size} result;`);
+                    for (var i = 0; i < size; ++i) {
+                        print(`    result[${i}] = ${nonNativeFunction}(x[${i}], y[${i}]);`);
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                }
+                if (type == `half` || type == `float`) {
+                    for (var i of [2, 3, 4]) {
+                        for (var j of [2, 3, 4]) {
+                            print(`${type}${i}x${j} ${nonNativeFunction}(${type}${i}x${j} x, ${type}${i}x${j} y) {`);
+                            print(`    ${type}${i}x${j} result;`);
+                            for (var m = 0; m < i; ++m) {
+                                for (var n = 0; n < j; ++n) {
+                                    print(`    result[${m}][${n}] = ${nonNativeFunction}(x[${m}][${n}], y[${m}][${n}]);`);
+                                }
+                            }
+                            print(`    return result;`);
+                            print(`}`);
+                        }
+                    }
+                }
+            }
+            print();
+        }
+        
+        for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            let nonNativeFunctions = [`clamp`];
+        
+            print(`${type} clamp(${type} x, ${type} lower, ${type} upper) {`);
+            print(`    return max(min(upper, x), lower);`);
+            print(`}`);
+        
+            for (var nonNativeFunction of nonNativeFunctions) {
+                for (var size of [2, 3, 4]) {
+                    print(`${type}${size} ${nonNativeFunction}(${type}${size} x, ${type}${size} y, ${type}${size} z) {`);
+                    print(`    ${type}${size} result;`);
+                    for (var i = 0; i < size; ++i) {
+                        print(`    result[${i}] = ${nonNativeFunction}(x[${i}], y[${i}], z[${i}]);`);
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                }
+                if (type == `half` || type == `float`) {
+                    for (var i of [2, 3, 4]) {
+                        for (var j of [2, 3, 4]) {
+                            print(`${type}${i}x${j} ${nonNativeFunction}(${type}${i}x${j} x, ${type}${i}x${j} y, ${type}${i}x${j} z) {`);
+                            print(`    ${type}${i}x${j} result;`);
+                            for (var m = 0; m < i; ++m) {
+                                for (var n = 0; n < j; ++n) {
+                                    print(`    result[${m}][${n}] = ${nonNativeFunction}(x[${m}][${n}], y[${m}][${n}], z[${m}][${n}]);`);
+                                }
+                            }
+                            print(`    return result;`);
+                            print(`}`);
+                        }
+                    }
+                }
+            }
+            print();
+        }
+        
+        for (var type of [`half`, `float`]) {
+            print(`${type} modf(${type} x, thread ${type}* ip) {`);
+            print(`    uint result = uint(x);`);
+            print(`    *ip = x - ${type}(result);`);
+            print(`    return ${type}(result);`);
+            print(`}`);
+        
+            for (var size of [2, 3, 4]) {
+                print(`${type}${size} modf(${type}${size} x, thread ${type}${size}* y) {`);
+                print(`    ${type}${size} result;`);
+                // Can't take a pointer to a member of a vector.
+                print(`    ${type} buffer;`);
+                for (var i = 0; i < size; ++i) {
+                    print(`    result[${i}] = modf(x[${i}], &buffer);`);
+                    print(`    (*y)[${i}] = buffer;`);
+                }
+                print(`    return result;`);
+                print(`}`);
+            }
+            for (var i of [2, 3, 4]) {
+                for (var j of [2, 3, 4]) {
+                    print(`${type}${i}x${j} modf(${type}${i}x${j} x, thread ${type}${i}x${j}* y) {`);
+                    print(`    ${type}${i}x${j} result;`);
+                    // Can't take a pointer to a member of a matrix.
+                    print(`    ${type} buffer;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}][${n}] = modf(x[${m}][${n}], &buffer);`);
+                            print(`    (*y)[${m}][${n}] = buffer;`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                }
+            }
+            print();
+        }
+        
+        print(`uchar count_bits(uchar x) {`);
+        print(`    return uchar(((x | uchar(1 << 0)) == 0 ? 0 : 1) +`);
+        for (var i = 1; i < 7; ++i) {
+            print(`           ((x | uchar(1 << ${i})) == 0 ? 0 : 1) +`);
+        }
+        print(`           ((x | uchar(1 << 7)) == 0 ? 0 : 1));`);
+        print(`}`);
+        print(`uchar count_bits(ushort x) {`);
+        print(`    return uchar(((x | ushort(1 << 0)) == 0 ? 0 : 1) +`);
+        for (var i = 1; i < 15; ++i) {
+            print(`           ((x | ushort(1 << ${i})) == 0 ? 0 : 1) +`);
+        }
+        print(`           ((x | ushort(1 << 15)) == 0 ? 0 : 1));`);
+        print(`}`);
+        print(`uchar count_bits(uint x) {`);
+        print(`    return uchar(((x | uint(1 << 0)) == 0 ? 0 : 1) +`);
+        for (var i = 1; i < 31; ++i) {
+            print(`           ((x | uint(1 << ${i})) == 0 ? 0 : 1) +`);
+        }
+        print(`           ((x | uint(1 << 31)) == 0 ? 0 : 1));`);
+        print(`}`);
+        print(`uchar reversebits(uchar x) {`);
+        print(`    return uchar(((x & uchar(1 << 0)) << 7) |`);
+        for (var i = 1; i < 7; ++i) {
+            let offset = 7 - 2 * i
+            print(`           ((x & uchar(1 << ${i})) ${offset > 0 ? `<<` : `>>`} ${Math.abs(offset)}) |`);
+        }
+        print(`           ((x & uchar(1 << 7)) >> 7));`);
+        print(`}`);
+        print(`ushort reversebits(ushort x) {`);
+        print(`    return ushort(((x & ushort(1 << 0)) << 15) |`);
+        for (var i = 1; i < 15; ++i) {
+            let offset = 15 - 2 * i
+            print(`           ((x & ushort(1 << ${i})) ${offset > 0 ? `<<` : `>>`} ${Math.abs(offset)}) |`);
+        }
+        print(`           ((x & ushort(1 << 15)) >> 15));`);
+        print(`}`);
+        print(`uint reversebits(uint x) {`);
+        print(`    return uint(((x & uint(1 << 0)) << 31) |`);
+        for (var i = 1; i < 31; ++i) {
+            let offset = 31 - 2 * i
+            print(`           ((x & uint(1 << ${i})) ${offset > 0 ? `<<` : `>>`} ${Math.abs(offset)}) |`);
+        }
+        print(`           ((x & uint(1 << 31)) >> 31));`);
+        print(`}`);
+        for (var type of [`uchar`, `ushort`, `uint`]) {
+            for (var size of [2, 3, 4]) {
+                print(`uchar${size} count_bits(${type}${size} x) {`);
+                print(`    uchar${size} result;`);
+                for (var i = 0; i < size; ++i) {
+                    print(`    result[${i}] = count_bits(x[${i}]);`);
+                }
+                print(`    return result;`);
+                print(`}`);
+            }
+        }
+        for (var type of [`uchar`, `ushort`, `uint`]) {
+            for (var size of [2, 3, 4]) {
+                print(`${type}${size} reversebits(${type}${size} x) {`);
+                print(`    ${type}${size} result;`);
+                for (var i = 0; i < size; ++i) {
+                    print(`    result[${i}] = reversebits(x[${i}]);`);
+                }
+                print(`    return result;`);
+                print(`}`);
+            }
+        }
+        print();
+        
+        print(`uint firstbithigh(uchar x) {`);
+        for (var i = 0; i <= 7; ++i) {
+            print(`    if ((x & uchar(1 << ${7 - i})) != 0)`);
+            print(`        return ${i};`);
+        }
+        print(`    return 8;`);
+        print(`}`);
+        print(`uint firstbithigh(ushort x) {`);
+        for (var i = 0; i <= 15; ++i) {
+            print(`    if ((x & ushort(1 << ${15 - i})) != 0)`);
+            print(`        return ${i};`);
+        }
+            print(`    return 16;`);
+        print(`}`);
+        print(`uint firstbithigh(uint x) {`);
+        for (var i = 0; i <= 31; ++i) {
+            print(`    if ((x & uint(1 << ${31 - i})) != 0)`);
+            print(`        return ${i};`);
+        }
+        print(`    return 32;`);
+        print(`}`);
+        print(`uint firstbithigh(char x) {`);
+        print(`    return firstbithigh(uchar(x));`);
+        print(`}`);
+        print(`uint firstbithigh(short x) {`);
+        print(`    return firstbithigh(ushort(x));`);
+        print(`}`);
+        print(`uint firstbithigh(int x) {`);
+        print(`    return firstbithigh(uint(x));`);
+        print(`}`);
+        print(`uint firstbitlow(uchar x) {`);
+        for (var i = 0; i <= 7; ++i) {
+            print(`    if ((x & uchar(1 << ${i})) != 0)`);
+            print(`        return ${7 - i};`);
+        }
+        print(`    return 8;`);
+        print(`}`);
+        print(`uint firstbitlow(ushort x) {`);
+        for (var i = 0; i <= 15; ++i) {
+            print(`    if ((x & ushort(1 << ${i})) != 0)`);
+            print(`        return ${15 - i};`);
+        }
+        print(`    return 16;`);
+        print(`}`);
+        print(`uint firstbitlow(uint x) {`);
+        for (var i = 0; i <= 31; ++i) {
+            print(`    if ((x & uint(1 << ${i})) != 0)`);
+            print(`        return ${31 - i};`);
+        }
+        print(`    return 32;`);
+        print(`}`);
+        print(`uint firstbitlow(char x) {`);
+        print(`    return firstbitlow(uchar(x));`);
+        print(`}`);
+        print(`uint firstbitlow(short x) {`);
+        print(`    return firstbitlow(ushort(x));`);
+        print(`}`);
+        print(`uint firstbitlow(int x) {`);
+        print(`    return firstbitlow(uint(x));`);
+        print(`}`);
+        for (var functionName of [`firstbithigh`, `firstbitlow`]) {
+            for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`]) {
+                for (var size of [2, 3, 4]) {
+                    print(`uint${size} ${functionName}(${type}${size} x) {`);
+                    print(`    uint${size} result;`);
+                    for (var i = 0; i < size; ++i) {
+                        print(`    result[${i}] = ${functionName}(x[${i}]);`);
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                }
+            }
+        }
+        print();
+        
+        // Row-major, so the first index selects which row, and the second index selects which column
+        for (var type of [`half`, `float`]) {
+            print(`${type} determinant(${type} x) {`);
+            print(`    return x;`);
+            print(`}`);
+            print(`${type} determinant(${type}2x2 x) {`);
+            print(`    return x[0][0] * x[1][1] - x[0][1] * x[1][0];`);
+            print(`}`);
+            print(`${type} determinant(${type}3x3 x) {`);
+            print(`    return x[0][0] * x[1][1] * x[2][2] +`);
+            print(`           x[0][1] * x[1][2] * x[2][0] +`);
+            print(`           x[0][2] * x[1][0] * x[2][1] -`);
+            print(`           x[2][0] * x[1][1] * x[0][2] -`);
+            print(`           x[2][1] * x[1][2] * x[0][0] -`);
+            print(`           x[2][2] * x[1][0] * x[0][1];`);
+            print(`}`);
+            print(`${type} determinant(${type}4x4 x) {`);
+            print(`    ${type} result;`);
+            print(`    ${type}3x3 minor;`);
+            print(`    minor[0][0] = x[1][1];`);
+            print(`    minor[0][1] = x[1][2];`);
+            print(`    minor[0][2] = x[1][3];`);
+            print(`    minor[1][0] = x[2][1];`);
+            print(`    minor[1][1] = x[2][2];`);
+            print(`    minor[1][2] = x[2][3];`);
+            print(`    minor[2][0] = x[3][1];`);
+            print(`    minor[2][1] = x[3][2];`);
+            print(`    minor[2][2] = x[3][3];`);
+            print(`    result = result + x[0][0] * determinant(minor);`);
+            print(`    minor[0][0] = x[1][0];`);
+            print(`    minor[0][1] = x[1][2];`);
+            print(`    minor[0][2] = x[1][3];`);
+            print(`    minor[1][0] = x[2][0];`);
+            print(`    minor[1][1] = x[2][2];`);
+            print(`    minor[1][2] = x[2][3];`);
+            print(`    minor[2][0] = x[3][0];`);
+            print(`    minor[2][1] = x[3][2];`);
+            print(`    minor[2][2] = x[3][3];`);
+            print(`    result = result - x[0][1] * determinant(minor);`);
+            print(`    minor[0][0] = x[1][0];`);
+            print(`    minor[0][1] = x[1][1];`);
+            print(`    minor[0][2] = x[1][3];`);
+            print(`    minor[1][0] = x[2][0];`);
+            print(`    minor[1][1] = x[2][1];`);
+            print(`    minor[1][2] = x[2][3];`);
+            print(`    minor[2][0] = x[3][0];`);
+            print(`    minor[2][1] = x[3][1];`);
+            print(`    minor[2][2] = x[3][3];`);
+            print(`    result = result + x[0][2] * determinant(minor);`);
+            print(`    minor[0][0] = x[1][0];`);
+            print(`    minor[0][1] = x[1][1];`);
+            print(`    minor[0][2] = x[1][2];`);
+            print(`    minor[1][0] = x[2][0];`);
+            print(`    minor[1][1] = x[2][1];`);
+            print(`    minor[1][2] = x[2][2];`);
+            print(`    minor[2][0] = x[3][0];`);
+            print(`    minor[2][1] = x[3][1];`);
+            print(`    minor[2][2] = x[3][2];`);
+            print(`    result = result - x[0][3] * determinant(minor);`);
+            print(`    return result;`);
+            print(`}`);
+        }
+        print();
+        
+        for (var type of [`uchar4`, `ushort4`, `uint4`, `char4`, `short4`, `int4`, `half4`, `float4`]) {
+            print(`${type} dst(${type} src0, ${type} src1) {`);
+            print(`    ${type} result;`);
+            print(`    result.x = 1;`);
+            print(`    result.y = src0.y * src1.y;`);
+            print(`    result.z = src0.z;`);
+            print(`    result.w = src1.w;`);
+            print(`    return result;`);
+            print(`}`);
+        }
+        print();
+        
+        for (var type of [`half`, `float`]) {
+            print(`${type} distance(${type} x, ${type} y) {`);
+            print(`    return length(x - y);`);
+            print(`}`);
+            for (var size of [2, 3, 4]) {
+                print(`${type} distance(${type}${size} x, ${type}${size} y) {`);
+                print(`    return length(x - y);`);
+                print(`}`);
+            }
+        }
+        print();
+        
+        for (var type of [`half3`, `float3`]) {
+            print(`${type} cross(${type} u, ${type} v) {`);
+            print(`    ${type} result;`);
+            print(`    result.x = u.y * v.z - u.z * v.y;`);
+            print(`    result.y = u.z * v.x - u.x * v.z;`);
+            print(`    result.z = u.x * v.y - u.y * v.x;`);
+            print(`    return result;`);
+            print(`}`);
+        }
+        print();
+        
+        for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            print(`${type} dot(${type} a, ${type} b) {`);
+            print(`    return a * b;`);
+            print(`}`);
+            for (var size of [2, 3, 4]) {
+                print(`${type} dot(${type}${size} a, ${type}${size} b) {`);
+                print(`    ${type} result = 0;`);
+                for (var i = 0; i < size; ++i) {
+                    print(`    result = result + a[${i}] * b[${i}];`);
+                }
+                print(`    return result;`);
+                print(`}`);
+            }
+        }
+        print();
+        
+        for (var type of [`half`, `float`]) {
+            for (var size of [``, `2`, `3`, `4`]) {
+                print(`${type}${size} faceforward(${type}${size} n, ${type}${size} i, ${type}${size} ng) {`);
+                print(`    return -n * sign(dot(i, ng));`);
+                print(`}`);
+            }
+        }
+        print();
+        
+        for (var type of [`half`, `float`]) {
+            for (var size of [``, `2`, `3`, `4`]) {
+                print(`${type} length(${type}${size} x) {`);
+                print(`    return sqrt(dot(x, x));`);
+                print(`}`);
+            }
+        }
+        print();
+        
+        for (var type of [`half`, `float`]) {
+            print(`${type}4 lit(${type} n_dot_l, ${type} n_dot_h, ${type} m) {`);
+            print(`    ${type} ambient = 1;`);
+            print(`    ${type} diffuse = max(0, n_dot_l);`);
+            print(`    ${type} specular = n_dot_l < 0 || n_dot_h < 0 ? 0 : n_dot_h * m;`);
+            print(`    ${type}4 result;`);
+            print(`    result.x = ambient;`);
+            print(`    result.y = diffuse;`);
+            print(`    result.z = specular;`);
+            print(`    result.w = 1;`);
+            print(`    return result;`);
+            print(`}`);
+        }
+        print();
+        
+        for (var type of [`half`, `float`]) {
+            for (var size of [``, `2`, `3`, `4`]) {
+                print(`${type}${size} normalize(${type}${size} x) {`);
+                print(`    return x / length(x);`);
+                print(`}`);
+            }
+        }
+        print();
+        
+        for (var type of [`half`, `float`]) {
+            for (var size of [``, `2`, `3`, `4`]) {
+                print(`${type}${size} reflect(${type}${size} i, ${type}${size} n) {`);
+                print(`    return i - 2 * n * dot(i, n);`);
+                print(`}`);
+            }
+        }
+        print();
+        
+        // OpenGL ES v3.30 section 8.4
+        for (var type of [`half`, `float`]) {
+            for (var size of [``, `2`, `3`, `4`]) {
+                print(`${type}${size} refract(${type}${size} i, ${type}${size} n, ${type} eta) {`);
+                print(`    ${type}${size} result;`);
+                print(`    ${type} k = 1 - eta * eta * (1 - dot(n, i) * dot(n, i));`);
+                print(`    if (k < 0)`);
+                print(`        return result;`);
+                print(`    return eta * i - (eta * dot(n, i) + sqrt(k)) * n;`);
+                print(`}`);
+            }
+        }
+        print();
+        
+        for (var type of [`half`, `float`]) {
+            print(`${type} transpose(${type} x) {`);
+            print(`    return x;`);
+            print(`}`);
+            for (var i of [2, 3, 4]) {
+                for (var j of [2, 3, 4]) {
+                    print(`${type}${i}x${j} transpose(${type}${j}x${i} x) {`);
+                    print(`    ${type}${i}x${j} result;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}][${n}] = x[${n}][${m}];`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                }
+            }
+        }
+        print();
+        
+        for (var resultType of [`int`, `uint`, `float`]) {
+            for (var type of [`int`, `uint`, `float`]) {
+                if (type == resultType) {
+                    print(`${resultType} as${resultType}(${type} x) {`);
+                    print(`    return x;`);
+                    print(`}`);
+                } else  if (resultType == `int` && type == `uint` || resultType == `uint` && type == `int`) {
+                    print(`${resultType} as${resultType}(${type} x) {`);
+                    print(`    return ${resultType}(x);`);
+                    print(`}`);
+                } else {
+                    print(`native ${resultType} as${resultType}(${type});`);
+                }
+                for (var size of [2, 3, 4]) {
+                    if (type == resultType) {
+                        print(`${resultType}${size} as${resultType}(${type}${size} x) {`);
+                        print(`    return x;`);
+                        print(`}`);
+                    } else {
+                        print(`${resultType}${size} as${resultType}(${type}${size} x) {`);
+                        print(`    ${resultType}${size} result;`);
+                        for (var i = 0; i < size; ++i) {
+                            print(`    result[${i}] = as${resultType}(x[${i}]);`);
+                        }
+                        print(`    return result;`);
+                        print(`}`);
+                    }
+                }
+                if (resultType == `float` && type == `float`) {
+                    for (var i of [2, 3, 4]) {
+                        for (var j of [2, 3, 4]) {
+                            if (type == resultType) {
+                                print(`${resultType}${i}x${j} as${resultType}(${type}${i}x${j} x) {`);
+                                print(`    return x;`);
+                                print(`}`);
+                            } else {
+                                print(`${resultType}${i}x${j} as${resultType}(${type}${i}x${j} x) {`);
+                                print(`    ${resultType}${i}x${j} result;`);
+                                for (var m = 0; m < i; ++m) {
+                                    for (var n = 0; n < j; ++n) {
+                                        print(`    result[${m}][${n}] = as${resultType}(x[${m}][${n}]);`);
+                                    }
+                                }
+                                print(`    return result;`);
+                                print(`}`);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        print();
+        
+        print(`native float f16tof32(uint);`);
+        print(`native uint f32tof16(float);`);
+        for (var size of [2, 3, 4]) {
+            print(`float${size} f16tof32(uint${size} x) {`);
+            print(`    float${size} result;`);
+            for (var i = 0; i < size; ++i) {
+                print(`    result[${i}] = f16tof32(x[${i}]);`);
+            }
+            print(`    return result;`);
+            print(`}`);
+            print(`uint${size} f32tof16(float${size} x) {`);
+            print(`    uint${size} result;`);
+            for (var i = 0; i < size; ++i) {
+                print(`    result[${i}] = f32tof16(x[${i}]);`);
+            }
+            print(`    return result;`);
+            print(`}`);
+        }
+        print();
+        
+        print(`native void AllMemoryBarrierWithGroupSync();`);
+        print(`native void DeviceMemoryBarrierWithGroupSync();`);
+        print(`native void GroupMemoryBarrierWithGroupSync();`);
+        print();
+        
+        for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            print(`${type} mul(${type} x, ${type} y) {`);
+            print(`    return x * y;`);
+            print(`}`);
+        }
+        
+        for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            for (var size of [2, 3, 4]) {
+                print(`${type}${size} mul(${type} x, ${type}${size} y) {`);
+                print(`    ${type}${size} result;`);
+                for (var i = 0; i < size; ++i) {
+                    print(`    result[${i}] = x * y[${i}];`);
+                }
+                print(`    return result;`);
+                print(`}`);
+                print(`${type}${size} mul(${type}${size} x, ${type} y) {`);
+                print(`    ${type}${size} result;`);
+                for (var i = 0; i < size; ++i) {
+                    print(`    result[${i}] = x[${i}] * y;`);
+                }
+                print(`    return result;`);
+                print(`}`);
+            }
+        }
+        
+        for (var type of [`half`, `float`]) {
+            for (var i of [2, 3, 4]) {
+                for (var j of [2, 3, 4]) {
+                    print(`${type}${i}x${j} mul(${type} x, ${type}${i}x${j} y) {`);
+                    print(`    ${type}${i}x${j} result;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}][${n}] = x * y[${m}][${n}];`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                    print(`${type}${i}x${j} mul(${type}${i}x${j} x, ${type} y) {`);
+                    print(`    ${type}${i}x${j} result;`);
+                    for (var m = 0; m < i; ++m) {
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}][${n}] = x[${m}][${n}] * y;`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                }
+            }
+        }
+        
+        for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            for (var size of [2, 3, 4]) {
+                print(`${type} mul(${type}${size} x, ${type}${size} y) {`);
+                print(`    return dot(x, y);`);
+                print(`}`);
+            }
+        }
+        
+        for (var type of [`half`, `float`]) {
+            for (var i of [2, 3, 4]) {
+                for (var j of [2, 3, 4]) {
+                    print(`${type}${j} mul(${type}${i} x, ${type}${i}x${j} y) {`);
+                    print(`    ${type}${j} result;`);
+                    for (var m = 0; m < j; ++m) {
+                        print(`    result[${m}] = 0;`);
+                        for (var n = 0; n < i; ++n) {
+                            print(`    result[${m}] += x[${n}] * y[${n}][${m}];`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                    print(`${type}${i} mul(${type}${i}x${j} x, ${type}${j} y) {`);
+                    print(`    ${type}${i} result;`);
+                    for (var m = 0; m < i; ++m) {
+                        print(`    result[${m}] = 0;`);
+                        for (var n = 0; n < j; ++n) {
+                            print(`    result[${m}] += x[${m}][${n}] * y[${n}];`);
+                        }
+                    }
+                    print(`    return result;`);
+                    print(`}`);
+                }
+            }
+        }
+        
+        for (var type of [`half`, `float`]) {
+            for (var i of [2, 3, 4]) {
+                for (var j of [2, 3, 4]) {
+                    for (var k of [2, 3, 4]) {
+                        print(`${type}${i}x${k} mul(${type}${i}x${j} x, ${type}${j}x${k} y) {`);
+                        print(`    ${type}${i}x${k} result;`);
+                        for (var p = 0; p < i; ++p) {
+                            for (var r = 0; r < k; ++r) {
+                                print(`    result[${p}][${k}] = 0;`);
+                                for (var q = 0; q < j; ++q) {
+                                    print(`    result[${p}][${k}] += x[${p}][${q}] * y[${q}][${r}];`);
+                                }
+                            }
+                        }
+                        print(`    return result;`);
+                        print(`}`);
+                    }
+                }
+            }
+        }
+        print();
+        
+        for (var type of [`uint`, `int`]) {
+            for (var functionName of [`Add`, `And`, `Exchange`, `Max`, `Min`, `Or`, `Xor`]) {
+                print(`native void Interlocked${functionName}(thread atomic_${type}*, ${type}, thread ${type}*);`);
+            }
+            print(`native void InterlockedCompareExchange(thread atomic_${type}*, ${type}, ${type}, thread ${type}*);`);
+        }
+        print();
+        
+        for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
+            for (var length of [``, `2`, `3`, `4`]) {
+                print(`native ${type}${length} Sample(Texture1D<${type}${length}>, sampler, float location);`);
+                print(`native ${type}${length} Sample(Texture1D<${type}${length}>, sampler, float location, int offset);`);
+                print(`native ${type}${length} Load(Texture1D<${type}${length}>, int2 location);`);
+                print(`native ${type}${length} Load(Texture1D<${type}${length}>, int2 location, int offset);`);
+                print(`native void GetDimensions(Texture1D<${type}${length}>, uint MipLevel, thread uint* Width, thread uint* NumberOfLevels);`);
+                print();
+                print(`native ${type}${length} Sample(Texture1DArray<${type}${length}>, sampler, float2 location);`);
+                print(`native ${type}${length} Sample(Texture1DArray<${type}${length}>, sampler, float2 location, int offset);`);
+                print(`native ${type}${length} Load(Texture1DArray<${type}${length}>, int3 location);`);
+                print(`native ${type}${length} Load(Texture1DArray<${type}${length}>, int3 location, int offset);`);
+                print(`native void GetDimensions(Texture1DArray<${type}${length}>, uint MipLevel, thread uint* Width, thread uint* Elements, thread uint* NumberOfLevels);`);
+                print();
+                print(`native ${type}${length} Sample(Texture2D<${type}${length}>, sampler, float2 location);`);
+                print(`native ${type}${length} Sample(Texture2D<${type}${length}>, sampler, float2 location, int2 offset);`);
+                print(`native ${type}${length} SampleBias(Texture2D<${type}${length}>, sampler, float2 location, float Bias);`);
+                print(`native ${type}${length} SampleBias(Texture2D<${type}${length}>, sampler, float2 location, float Bias, int2 offset);`);
+                print(`native ${type}${length} SampleGrad(Texture2D<${type}${length}>, sampler, float2 location, float2 DDX, float2 DDY);`);
+                print(`native ${type}${length} SampleGrad(Texture2D<${type}${length}>, sampler, float2 location, float2 DDX, float2 DDY, int2 offset);`);
+                print(`native ${type}${length} SampleLevel(Texture2D<${type}${length}>, sampler, float2 location, float LOD);`);
+                print(`native ${type}${length} SampleLevel(Texture2D<${type}${length}>, sampler, float2 location, float LOD, int2 offset);`);
+                print(`native ${type}4 Gather(Texture2D<${type}${length}>, sampler, float2 location);`);
+                print(`native ${type}4 Gather(Texture2D<${type}${length}>, sampler, float2 location, int2 offset);`);
+                print(`native ${type}4 GatherRed(Texture2D<${type}${length}>, sampler, float2 location);`);
+                print(`native ${type}4 GatherRed(Texture2D<${type}${length}>, sampler, float2 location, int2 offset);`);
+                print(`native ${type}4 GatherGreen(Texture2D<${type}${length}>, sampler, float2 location);`);
+                print(`native ${type}4 GatherGreen(Texture2D<${type}${length}>, sampler, float2 location, int2 offset);`);
+                print(`native ${type}4 GatherBlue(Texture2D<${type}${length}>, sampler, float2 location);`);
+                print(`native ${type}4 GatherBlue(Texture2D<${type}${length}>, sampler, float2 location, int2 offset);`);
+                print(`native ${type}4 GatherAlpha(Texture2D<${type}${length}>, sampler, float2 location);`);
+                print(`native ${type}4 GatherAlpha(Texture2D<${type}${length}>, sampler, float2 location, int2 offset);`);
+                print(`native ${type}${length} Load(Texture2D<${type}${length}>, int3 location);`);
+                print(`native ${type}${length} Load(Texture2D<${type}${length}>, int3 location, int2 offset);`);
+                print(`native void GetDimensions(Texture2D<${type}${length}>, uint MipLevel, thread uint* Width, thread uint* Height, thread uint* NumberOfLevels);`);
+                print();
+                print(`native ${type}${length} Sample(Texture2DArray<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}${length} Sample(Texture2DArray<${type}${length}>, sampler, float3 location, int2 offset);`);
+                print(`native ${type}${length} SampleBias(Texture2DArray<${type}${length}>, sampler, float3 location, float Bias);`);
+                print(`native ${type}${length} SampleBias(Texture2DArray<${type}${length}>, sampler, float3 location, float Bias, int2 offset);`);
+                print(`native ${type}${length} SampleGrad(Texture2DArray<${type}${length}>, sampler, float3 location, float2 DDX, float2 DDY);`);
+                print(`native ${type}${length} SampleGrad(Texture2DArray<${type}${length}>, sampler, float3 location, float2 DDX, float2 DDY, int2 offset);`);
+                print(`native ${type}${length} SampleLevel(Texture2DArray<${type}${length}>, sampler, float3 location, float LOD);`);
+                print(`native ${type}${length} SampleLevel(Texture2DArray<${type}${length}>, sampler, float3 location, float LOD, int2 offset);`);
+                print(`native ${type}4 Gather(Texture2DArray<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}4 Gather(Texture2DArray<${type}${length}>, sampler, float3 location, int2 offset);`);
+                print(`native ${type}4 GatherRed(Texture2DArray<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}4 GatherRed(Texture2DArray<${type}${length}>, sampler, float3 location, int2 offset);`);
+                print(`native ${type}4 GatherGreen(Texture2DArray<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}4 GatherGreen(Texture2DArray<${type}${length}>, sampler, float3 location, int2 offset);`);
+                print(`native ${type}4 GatherBlue(Texture2DArray<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}4 GatherBlue(Texture2DArray<${type}${length}>, sampler, float3 location, int2 offset);`);
+                print(`native ${type}4 GatherAlpha(Texture2DArray<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}4 GatherAlpha(Texture2DArray<${type}${length}>, sampler, float3 location, int2 offset);`);
+                print(`native ${type}${length} Load(Texture2DArray<${type}${length}>, int4 location);`);
+                print(`native ${type}${length} Load(Texture2DArray<${type}${length}>, int4 location, int2 offset);`);
+                print(`native void GetDimensions(Texture2DArray<${type}${length}>, uint MipLevel, thread uint* Width, thread uint* Height, thread uint* Elements, thread uint* NumberOfLevels);`);
+                print();
+                print(`native ${type}${length} Sample(Texture3D<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}${length} Sample(Texture3D<${type}${length}>, sampler, float3 location, int3 offset);`);
+                print(`native ${type}4 Gather(Texture3D<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}4 Gather(Texture3D<${type}${length}>, sampler, float3 location, int3 offset);`);
+                print(`native ${type}4 GatherRed(Texture3D<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}4 GatherRed(Texture3D<${type}${length}>, sampler, float3 location, int3 offset);`);
+                print(`native ${type}4 GatherGreen(Texture3D<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}4 GatherGreen(Texture3D<${type}${length}>, sampler, float3 location, int3 offset);`);
+                print(`native ${type}4 GatherBlue(Texture3D<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}4 GatherBlue(Texture3D<${type}${length}>, sampler, float3 location, int3 offset);`);
+                print(`native ${type}4 GatherAlpha(Texture3D<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}4 GatherAlpha(Texture3D<${type}${length}>, sampler, float3 location, int3 offset);`);
+                print(`native ${type}${length} Load(Texture3D<${type}${length}>, int4 location);`);
+                print(`native ${type}${length} Load(Texture3D<${type}${length}>, int4 location, int3 offset);`);
+                print(`native void GetDimensions(Texture3D<${type}${length}>, uint MipLevel, thread uint* Width, thread uint* Height, thread uint* Depth, thread uint* NumberOfLevels);`);
+                print();
+                print(`native ${type}${length} Sample(TextureCube<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}${length} SampleBias(TextureCube<${type}${length}>, sampler, float3 location, float Bias);`);
+                print(`native ${type}${length} SampleGrad(TextureCube<${type}${length}>, sampler, float3 location, float3 DDX, float3 DDY);`);
+                print(`native ${type}${length} SampleLevel(TextureCube<${type}${length}>, sampler, float3 location, float LOD);`);
+                print(`native ${type}4 Gather(TextureCube<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}4 GatherRed(TextureCube<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}4 GatherGreen(TextureCube<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}4 GatherBlue(TextureCube<${type}${length}>, sampler, float3 location);`);
+                print(`native ${type}4 GatherAlpha(TextureCube<${type}${length}>, sampler, float3 location);`);
+                print(`native void GetDimensions(TextureCube<${type}${length}>, uint MipLevel, thread uint* Width, thread uint* Height, thread uint* NumberOfLevels);`);
+                print();
+                print(`native void GetDimensions(RWTexture1D<${type}${length}>, thread uint* Width);`);
+                print(`native void GetDimensions(RWTexture1D<${type}${length}>, thread float* Width);`);
+                print(`native ${type}${length} Load(RWTexture1D<${type}${length}>, int location);`);
+                print(`native void Store(RWTexture1D<${type}${length}>, ${type}${length}, uint location);`);
+                print();
+                print(`native void GetDimensions(RWTexture1DArray<${type}${length}>, thread uint* Width, thread uint* Elements);`);
+                print(`native void GetDimensions(RWTexture1DArray<${type}${length}>, thread float* Width, thread uint* Elements);`);
+                print(`native ${type}${length} Load(RWTexture1DArray<${type}${length}>, int2 location);`);
+                print(`native void Store(RWTexture1DArray<${type}${length}>, ${type}${length}, uint2 location);`);
+                print();
+                print(`native void GetDimensions(RWTexture2D<${type}${length}>, thread uint* Width, thread uint* Height);`);
+                print(`native void GetDimensions(RWTexture2D<${type}${length}>, thread float* Width, thread float* Height);`);
+                print(`native ${type}${length} Load(RWTexture2D<${type}${length}>, int2 location);`);
+                print(`native void Store(RWTexture2D<${type}${length}>, ${type}${length}, uint2 location);`);
+                print();
+                print(`native void GetDimensions(RWTexture2DArray<${type}${length}>, thread uint* Width, thread uint* Height, thread uint* Elements);`);
+                print(`native void GetDimensions(RWTexture2DArray<${type}${length}>, thread float* Width, thread float* Height, thread float* Elements);`);
+                print(`native ${type}${length} Load(RWTexture2DArray<${type}${length}>, int3 location);`);
+                print(`native void Store(RWTexture2DArray<${type}${length}>, ${type}${length}, uint3 location);`);
+                print();
+                print(`native void GetDimensions(RWTexture3D<${type}${length}>, thread uint* Width, thread uint* Height, thread uint* Depth);`);
+                print(`native void GetDimensions(RWTexture3D<${type}${length}>, thread float* Width, thread float* Height, thread float* Depth);`);
+                print(`native ${type}${length} Load(RWTexture3D<${type}${length}>, int3 location);`);
+                print(`native void Store(RWTexture3D<${type}${length}>, ${type}${length}, uint3 location);`);
+                print();
+            }
+        }
+        
+        for (var type of [`half`, `float`]) {
+            print(`native ${type} Sample(TextureDepth2D<${type}>, sampler, float2 location);`);
+            print(`native ${type} Sample(TextureDepth2D<${type}>, sampler, float2 location, int2 offset);`);
+            print(`native ${type} SampleCmp(TextureDepth2D<${type}>, SamplerComparisonState, float2 location, float CompareValue);`);
+            print(`native ${type} SampleCmp(TextureDepth2D<${type}>, SamplerComparisonState, float2 location, float CompareValue, int2 offset);`);
+            print(`native ${type} SampleCmpLevelZero(TextureDepth2D<${type}>, SamplerComparisonState, float2 location, float CompareValue);`);
+            print(`native ${type} SampleCmpLevelZero(TextureDepth2D<${type}>, SamplerComparisonState, float2 location, float CompareValue, int2 offset);`);
+            print(`native ${type} SampleBias(TextureDepth2D<${type}>, sampler, float2 location, float Bias);`);
+            print(`native ${type} SampleBias(TextureDepth2D<${type}>, sampler, float2 location, float Bias, int2 offset);`);
+            print(`native ${type} SampleGrad(TextureDepth2D<${type}>, sampler, float2 location, float2 DDX, float2 DDY);`);
+            print(`native ${type} SampleGrad(TextureDepth2D<${type}>, sampler, float2 location, float2 DDX, float2 DDY, int2 offset);`);
+            print(`native ${type} SampleLevel(TextureDepth2D<${type}>, sampler, float2 location, float LOD);`);
+            print(`native ${type} SampleLevel(TextureDepth2D<${type}>, sampler, float2 location, float LOD, int2 offset);`);
+            print(`native ${type} Gather(TextureDepth2D<${type}>, sampler, float2 location);`);
+            print(`native ${type} Gather(TextureDepth2D<${type}>, sampler, float2 location, int2 offset);`);
+            print(`native ${type} GatherRed(TextureDepth2D<${type}>, sampler, float2 location);`);
+            print(`native ${type} GatherRed(TextureDepth2D<${type}>, sampler, float2 location, int2 offset);`);
+            print(`native ${type} GatherGreen(TextureDepth2D<${type}>, sampler, float2 location);`);
+            print(`native ${type} GatherGreen(TextureDepth2D<${type}>, sampler, float2 location, int2 offset);`);
+            print(`native ${type} GatherBlue(TextureDepth2D<${type}>, sampler, float2 location);`);
+            print(`native ${type} GatherBlue(TextureDepth2D<${type}>, sampler, float2 location, int2 offset);`);
+            print(`native ${type} GatherAlpha(TextureDepth2D<${type}>, sampler, float2 location);`);
+            print(`native ${type} GatherAlpha(TextureDepth2D<${type}>, sampler, float2 location, int2 offset);`);
+            print(`native ${type} GatherCmp(TextureDepth2D<${type}>, SamplerComparisonState, float2 location, float compare_value);`);
+            print(`native ${type} GatherCmp(TextureDepth2D<${type}>, SamplerComparisonState, float2 location, float compare_value, int2 offset);`);
+            print(`native ${type} GatherCmpRed(TextureDepth2D<${type}>, SamplerComparisonState, float2 location, float compare_value);`);
+            print(`native ${type} GatherCmpRed(TextureDepth2D<${type}>, SamplerComparisonState, float2 location, float compare_value, int2 offset);`);
+            print(`native ${type} GatherCmpGreen(TextureDepth2D<${type}>, SamplerComparisonState, float2 location, float compare_value);`);
+            print(`native ${type} GatherCmpGreen(TextureDepth2D<${type}>, SamplerComparisonState, float2 location, float compare_value, int2 offset);`);
+            print(`native ${type} GatherCmpBlue(TextureDepth2D<${type}>, SamplerComparisonState, float2 location, float compare_value);`);
+            print(`native ${type} GatherCmpBlue(TextureDepth2D<${type}>, SamplerComparisonState, float2 location, float compare_value, int2 offset);`);
+            print(`native ${type} GatherCmpAlpha(TextureDepth2D<${type}>, SamplerComparisonState, float2 location, float compare_value);`);
+            print(`native ${type} GatherCmpAlpha(TextureDepth2D<${type}>, SamplerComparisonState, float2 location, float compare_value, int2 offset);`);
+            print(`native ${type} Load(TextureDepth2D<${type}>, int3 location);`);
+            print(`native ${type} Load(TextureDepth2D<${type}>, int3 location, int2 offset);`);
+            print(`native void GetDimensions(TextureDepth2D<${type}>, uint MipLevel, thread uint* Width, thread uint* Height, thread uint* NumberOfLevels);`);
+            print();
+            print(`native ${type} Sample(TextureDepth2DArray<${type}>, sampler, float3 location);`);
+            print(`native ${type} Sample(TextureDepth2DArray<${type}>, sampler, float3 location, int2 offset);`);
+            print(`native ${type} SampleCmp(TextureDepth2DArray<${type}>, SamplerComparisonState, float3 location, float CompareValue);`);
+            print(`native ${type} SampleCmp(TextureDepth2DArray<${type}>, SamplerComparisonState, float3 location, float CompareValue, int2 offset);`);
+            print(`native ${type} SampleCmpLevelZero(TextureDepth2DArray<${type}>, SamplerComparisonState, float3 location, float CompareValue);`);
+            print(`native ${type} SampleCmpLevelZero(TextureDepth2DArray<${type}>, SamplerComparisonState, float3 location, float CompareValue, int2 offset);`);
+            print(`native ${type} SampleBias(TextureDepth2DArray<${type}>, sampler, float3 location, float Bias);`);
+            print(`native ${type} SampleBias(TextureDepth2DArray<${type}>, sampler, float3 location, float Bias, int2 offset);`);
+            print(`native ${type} SampleGrad(TextureDepth2DArray<${type}>, sampler, float3 location, float2 DDX, float2 DDY);`);
+            print(`native ${type} SampleGrad(TextureDepth2DArray<${type}>, sampler, float3 location, float2 DDX, float2 DDY, int2 offset);`);
+            print(`native ${type} SampleLevel(TextureDepth2DArray<${type}>, sampler, float3 location, float LOD);`);
+            print(`native ${type} SampleLevel(TextureDepth2DArray<${type}>, sampler, float3 location, float LOD, int2 offset);`);
+            print(`native ${type} Gather(TextureDepth2DArray<${type}>, sampler, float3 location);`);
+            print(`native ${type} Gather(TextureDepth2DArray<${type}>, sampler, float3 location, int2 offset);`);
+            print(`native ${type} GatherRed(TextureDepth2DArray<${type}>, sampler, float3 location);`);
+            print(`native ${type} GatherRed(TextureDepth2DArray<${type}>, sampler, float3 location, int2 offset);`);
+            print(`native ${type} GatherGreen(TextureDepth2DArray<${type}>, sampler, float3 location);`);
+            print(`native ${type} GatherGreen(TextureDepth2DArray<${type}>, sampler, float3 location, int2 offset);`);
+            print(`native ${type} GatherBlue(TextureDepth2DArray<${type}>, sampler, float3 location);`);
+            print(`native ${type} GatherBlue(TextureDepth2DArray<${type}>, sampler, float3 location, int2 offset);`);
+            print(`native ${type} GatherAlpha(TextureDepth2DArray<${type}>, sampler, float3 location);`);
+            print(`native ${type} GatherAlpha(TextureDepth2DArray<${type}>, sampler, float3 location, int2 offset);`);
+            print(`native ${type} GatherCmp(TextureDepth2DArray<${type}>, SamplerComparisonState, float3 location, float compare_value);`);
+            print(`native ${type} GatherCmp(TextureDepth2DArray<${type}>, SamplerComparisonState, float3 location, float compare_value, int2 offset);`);
+            print(`native ${type} GatherCmpRed(TextureDepth2DArray<${type}>, SamplerComparisonState, float3 location, float compare_value);`);
+            print(`native ${type} GatherCmpRed(TextureDepth2DArray<${type}>, SamplerComparisonState, float3 location, float compare_value, int2 offset);`);
+            print(`native ${type} GatherCmpGreen(TextureDepth2DArray<${type}>, SamplerComparisonState, float3 location, float compare_value);`);
+            print(`native ${type} GatherCmpGreen(TextureDepth2DArray<${type}>, SamplerComparisonState, float3 location, float compare_value, int2 offset);`);
+            print(`native ${type} GatherCmpBlue(TextureDepth2DArray<${type}>, SamplerComparisonState, float3 location, float compare_value);`);
+            print(`native ${type} GatherCmpBlue(TextureDepth2DArray<${type}>, SamplerComparisonState, float3 location, float compare_value, int2 offset);`);
+            print(`native ${type} GatherCmpAlpha(TextureDepth2DArray<${type}>, SamplerComparisonState, float3 location, float compare_value);`);
+            print(`native ${type} GatherCmpAlpha(TextureDepth2DArray<${type}>, SamplerComparisonState, float3 location, float compare_value, int2 offset);`);
+            print(`native ${type} Load(TextureDepth2DArray<${type}>, int4 location);`);
+            print(`native ${type} Load(TextureDepth2DArray<${type}>, int4 location, int2 offset);`);
+            print(`native void GetDimensions(TextureDepth2DArray<${type}>, uint MipLevel, thread uint* Width, thread uint* Height, thread uint* Elements, thread uint* NumberOfLevels);`);
+            print();
+            print(`native ${type} Sample(TextureDepthCube<${type}>, sampler, float3 location);`);
+            print(`native ${type} SampleCmp(TextureDepthCube<${type}>, SamplerComparisonState, float3 location, float CompareValue);`);
+            print(`native ${type} SampleCmpLevelZero(TextureDepthCube<${type}>, SamplerComparisonState, float3 location, float CompareValue);`);
+            print(`native ${type} SampleBias(TextureDepthCube<${type}>, sampler, float3 location, float Bias);`);
+            print(`native ${type} SampleGrad(TextureDepthCube<${type}>, sampler, float3 location, float2 DDX, float2 DDY);`);
+            print(`native ${type} SampleLevel(TextureDepthCube<${type}>, sampler, float3 location, float LOD);`);
+            print(`native ${type} Gather(TextureDepthCube<${type}>, sampler, float3 location);`);
+            print(`native ${type} GatherRed(TextureDepthCube<${type}>, sampler, float3 location);`);
+            print(`native ${type} GatherGreen(TextureDepthCube<${type}>, sampler, float3 location);`);
+            print(`native ${type} GatherBlue(TextureDepthCube<${type}>, sampler, float3 location);`);
+            print(`native ${type} GatherAlpha(TextureDepthCube<${type}>, sampler, float3 location);`);
+            print(`native ${type} GatherCmp(TextureDepthCube<${type}>, SamplerComparisonState, float3 location, float compare_value);`);
+            print(`native ${type} GatherCmpRed(TextureDepthCube<${type}>, SamplerComparisonState, float3 location, float compare_value);`);
+            print(`native ${type} GatherCmpGreen(TextureDepthCube<${type}>, SamplerComparisonState, float3 location, float compare_value);`);
+            print(`native ${type} GatherCmpBlue(TextureDepthCube<${type}>, SamplerComparisonState, float3 location, float compare_value);`);
+            print(`native ${type} GatherCmpAlpha(TextureDepthCube<${type}>, SamplerComparisonState, float3 location, float compare_value);`);
+            print(`native ${type} Load(TextureDepthCube<${type}>, int4 location);`);
+            print(`native void GetDimensions(TextureDepthCube<${type}>, uint MipLevel, thread uint* Width, thread uint* Height, thread uint* NumberOfLevels);`);
+            print();
+            print(`native void GetDimensions(RWTextureDepth2D<${type}>, thread uint* Width, thread uint* Height);`);
+            print(`native void GetDimensions(RWTextureDepth2D<${type}>, thread float* Width, thread float* Height);`);
+            print(`native ${type} Load(RWTextureDepth2D<${type}>, int2 location);`);
+            print(`native void Store(RWTextureDepth2D<${type}>, ${type}, uint2 location);`);
+            print();
+            print(`native void GetDimensions(RWTextureDepth2DArray<${type}>, thread uint* Width, thread uint* Height, thread uint* Elements);`);
+            print(`native void GetDimensions(RWTextureDepth2DArray<${type}>, thread float* Width, thread float* Height, thread float* Elements);`);
+            print(`native ${type} Load(RWTextureDepth2DArray<${type}>, int3 location);`);
+            print(`native void Store(RWTextureDepth2DArray<${type}>, ${type}, uint3 location);`);
+            print();
+        }
+        */
+    })();
+    return result;
+})();
 
 // 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.
@@ -217,22 +2134,3 @@ function allVectorTypeNames()
     }
     return names;
 }
-
-// Provides operator&[]
-standardLibrary += OperatorAnderIndexer.functions().join(";\n") + ";\n";
-
-// Native vector types are like structs in the langauge, but they do not have the ander field access.
-// It is not possible to take the address of a vector field.
-standardLibrary += BuiltinVectorGetter.functions().join(";\n") + ";\n";
-standardLibrary += BuiltinVectorSetter.functions().join(";\n") + ";\n";
-standardLibrary += BuiltinVectorIndexGetter.functions().join(";\n") + ";\n";
-standardLibrary += BuiltinVectorIndexSetter.functions().join(";\n") + ";\n";
-
-// FIXME: For native types these could be included as source in the standard library.
-// https://bugs.webkit.org/show_bug.cgi?id=188685
-standardLibrary += OperatorBool.functions().join(";\n") + ";\n";
-standardLibrary += BuiltinVectorEqualityOperator.functions().join(";\n") + ";\n";
-
-// FIXME: These need to be included as source in the standard library.
-standardLibrary += SwizzleOp.functions().join(";\n") + ";\n";
-standardLibrary += BuiltinVectorConstructors.functions().join(";\n") + ";\n";
diff --git a/Tools/WebGPUShadingLanguageRI/SwizzleOp.js b/Tools/WebGPUShadingLanguageRI/SwizzleOp.js
deleted file mode 100644 (file)
index 25998ef..0000000
+++ /dev/null
@@ -1,107 +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";
-
-class SwizzleOp {
-    constructor(baseTypeName, outSize, components, inSize)
-    {
-        this._baseTypeName = baseTypeName;
-        this._outSize = outSize;
-        this._components = components.slice(); // Shallow clone
-        this._inSize = inSize;
-    }
-
-    get baseTypeName() { return this._baseTypeName; }
-    get outSize() { return this._outSize; }
-    get components() { return this._components; }
-    get inSize() { return this._inSize; }
-
-    toString()
-    {
-        return `native ${this.baseTypeName}${this.outSize} operator.${this.components.join("")}(${this.baseTypeName}${this.inSize} v)`;
-    }
-
-    static intToString(x)
-    {
-        switch (x) {
-        case 0:
-            return "x";
-        case 1:
-            return "y";
-        case 2:
-            return "z";
-        case 3:
-            return "w";
-        default:
-            throw new Error("Could not generate standard library.");
-        }
-    }
-
-    static functions()
-    {
-        if (!this._functions) {
-            // We can't directly use this._functions in _generateSwizzles.
-            const functions = [];
-
-            function _generateSwizzle(baseTypeName, maxDepth, maxItems, array) {
-                if (!array)
-                    array = [];
-                if (array.length == maxDepth) {
-                    functions.push(new SwizzleOp(baseTypeName, array.length, array, maxItems));
-                    return;
-                }
-                for (let i = 0; i < maxItems; ++i) {
-                    array.push(SwizzleOp.intToString(i));
-                    _generateSwizzle(baseTypeName, maxDepth, maxItems, array);
-                    array.pop();
-                }
-            };
-
-            for (let typeName of VectorElementTypes) {
-                for (let maxDepth of VectorElementSizes) {
-                    for (let maxItems = 2; maxItems <= 4; maxItems++)
-                        _generateSwizzle(typeName, maxDepth, maxItems);
-                }
-            }
-
-            this._functions = functions;
-        }
-        return this._functions;
-    }
-
-    instantiateImplementation(func)
-    {
-        func.implementation = ([vec], node) => {
-            const outputBuffer = new EBuffer(this.outSize);
-            const readIndices = { 'x': 0, 'y': 1, 'z': 2, 'w': 3 };
-            for (let i = 0; i < this.outSize; i++)
-                outputBuffer.set(i, vec.get(readIndices[this.components[i]]));
-
-
-            return new EPtr(outputBuffer, 0);
-        };
-        func.implementationData = this;
-    }
-}
\ No newline at end of file
index 3a3f767..dc50653 100644 (file)
@@ -51,6 +51,12 @@ function synthesizeDefaultConstructorOperator(program)
             types.add(node);
             super.visitVectorType(node);
         }
+
+        visitMatrixType(node)
+        {
+            types.add(node);
+            super.visitMatrixType(node);
+        }
     }
 
     program.visit(new FindAllTypes());
diff --git a/Tools/WebGPUShadingLanguageRI/SynthesizeOperatorBool.js b/Tools/WebGPUShadingLanguageRI/SynthesizeOperatorBool.js
deleted file mode 100644 (file)
index 695fe13..0000000
+++ /dev/null
@@ -1,37 +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 synthesizeOperatorBool(program)
-{
-    for (let type of program.types.values()) {
-        if (!(type instanceof StructType) && !(type instanceof EnumType))
-            continue;
-        const func = new NativeFunc(type.origin, "operator cast", TypeRef.wrap(program.types.get("bool")), [ new FuncParameter(type.origin, null, TypeRef.wrap(type)) ], true, null);
-        const operatorBool = new OperatorBool(type.name);
-        operatorBool.instantiateImplementation(func);
-        program.add(func);
-    }
-}
index 7d26d26..607a695 100644 (file)
@@ -11,7 +11,6 @@
 <script src="CreateLiteral.js"></script>
 <script src="CreateLiteralType.js"></script>
 <script src="PropertyAccessExpression.js"></script>
-<script src="SwizzleOp.js"></script>
 <script src="NativeType.js"></script>
 
 <script src="AddressSpace.js"></script>
 <script src="Block.js"></script>
 <script src="BoolLiteral.js"></script>
 <script src="Break.js"></script>
-<script src="BuiltinVectorConstructors.js"></script>
+<script src="BuiltinMatrixGetter.js"></script>
+<script src="BuiltinMatrixSetter.js"></script>
 <script src="BuiltinVectorGetter.js"></script>
 <script src="BuiltinVectorSetter.js"></script>
-<script src="BuiltinVectorIndexGetter.js"></script>
-<script src="BuiltinVectorIndexSetter.js"></script>
-<script src="BuiltinVectorEqualityOperator.js"></script>
 <script src="CallExpression.js"></script>
 <script src="CallFunction.js"></script>
 <script src="Check.js"></script>
@@ -90,6 +87,7 @@
 <script src="LoopChecker.js"></script>
 <script src="MakeArrayRefExpression.js"></script>
 <script src="MakePtrExpression.js"></script>
+<script src="MatrixType.js"></script>
 <script src="NameContext.js"></script>
 <script src="NameFinder.js"></script>
 <script src="NameResolver.js"></script>
@@ -97,9 +95,8 @@
 <script src="NormalUsePropertyResolver.js"></script>
 <script src="NullLiteral.js"></script>
 <script src="NullType.js"></script>
-<script src="OperatorAnderIndex.js"></script>
+<script src="OperatorAnderIndexer.js"></script>
 <script src="OperatorArrayRefLength.js"></script>
-<script src="OperatorBool.js"></script>
 <script src="OriginKind.js"></script>
 <script src="OverloadResolutionFailure.js"></script>
 <script src="Parse.js"></script>
 <script src="SynthesizeArrayOperatorLength.js"></script>
 <script src="SynthesizeEnumFunctions.js"></script>
 <script src="SynthesizeStructAccessors.js"></script>
-<script src="SynthesizeOperatorBool.js"></script>
 <script src="SynthesizeCopyConstructorOperator.js"></script>
 <script src="SynthesizeDefaultConstructorOperator.js"></script>
 <script src="TernaryExpression.js"></script>
index 4f395a9..ccbdd27 100644 (file)
@@ -78,6 +78,11 @@ function makeFloat(program, value)
     return TypedValue.box(program.intrinsics.float, value);
 }
 
+function makeHalf(program, value)
+{
+    return TypedValue.box(program.intrinsics.half, value);
+}
+
 function makeEnum(program, enumName, value)
 {
     let enumType = program.types.get(enumName);
@@ -144,6 +149,14 @@ function checkFloat(program, result, expected)
         throw new Error("Wrong result: " + result.value + " (expected " + expected + ")");
 }
 
+function checkHalf(program, result, expected)
+{
+    if (!result.type.equals(program.intrinsics.half))
+        throw new Error("Wrong result type: " + result.type);
+    if (result.value != expected)
+        throw new Error("Wrong result: " + result.value + " (expected " + expected + ")");
+}
+
 function checkLexerToken(result, expectedIndex, expectedKind, expectedText)
 {
     if (result._index != expectedIndex)
@@ -2215,41 +2228,6 @@ tests.operatorBool = function()
 
         bool boolFromFloatFalse() { return bool(float(0)); }
         bool boolFromFloatTrue() { return bool(float(1)); }
-
-        bool boolFromInt2False() { return bool(int2(0, 0)); }
-        bool boolFromInt2True1() { return bool(int2(1, 0)); }
-        bool boolFromInt2True2() { return bool(int2(0, 1)); }
-
-        bool boolFromFloat3False() { return bool(float3(0, 0, 0)); }
-        bool boolFromFloat3True1() { return bool(float3(1, 0, 0)); }
-        bool boolFromFloat3True2() { return bool(float3(0, 1, 0)); }
-        bool boolFromFloat3True3() { return bool(float3(0, 0, 1)); }
-
-        bool boolFromUint4False() { return bool(uint4(0, 0, 0, 0)); }
-        bool boolFromUint4True1() { return bool(uint4(1, 0, 0, 0)); }
-        bool boolFromUint4True2() { return bool(uint4(0, 1, 0, 0)); }
-        bool boolFromUint4True3() { return bool(uint4(0, 0, 1, 0)); }
-        bool boolFromUint4True4() { return bool(uint4(0, 0, 0, 1)); }
-
-        struct X { int x; }
-
-        bool boolFromStructFalse()
-        {
-            X x;
-            return bool(x);
-        }
-
-        bool boolFromStructTrue()
-        {
-            X x;
-            x.x = 1;
-            return bool(x);
-        }
-
-        enum Y { A, B }
-
-        bool boolFromEnumFalse() { return bool(Y.A); }
-        bool boolFromEnumTrue() { return bool(Y.B); }
     `);
 
     checkBool(program, callFunction(program, "boolFromUcharFalse", []), false);
@@ -2264,26 +2242,25 @@ tests.operatorBool = function()
     checkBool(program, callFunction(program, "boolFromFloatFalse", []), false);
     checkBool(program, callFunction(program, "boolFromFloatTrue", []), true);
 
-    checkBool(program, callFunction(program, "boolFromInt2False", []), false);
-    checkBool(program, callFunction(program, "boolFromInt2True1", []), true);
-    checkBool(program, callFunction(program, "boolFromInt2True2", []), true);
-
-    checkBool(program, callFunction(program, "boolFromFloat3False", []), false);
-    checkBool(program, callFunction(program, "boolFromFloat3True1", []), true);
-    checkBool(program, callFunction(program, "boolFromFloat3True2", []), true);
-    checkBool(program, callFunction(program, "boolFromFloat3True3", []), true);
-
-    checkBool(program, callFunction(program, "boolFromUint4False", []), false);
-    checkBool(program, callFunction(program, "boolFromUint4True1", []), true);
-    checkBool(program, callFunction(program, "boolFromUint4True2", []), true);
-    checkBool(program, callFunction(program, "boolFromUint4True3", []), true);
-    checkBool(program, callFunction(program, "boolFromUint4True4", []), true);
-
-    checkBool(program, callFunction(program, "boolFromStructFalse", []), false);
-    checkBool(program, callFunction(program, "boolFromStructTrue", []), true);
+    checkFail(
+        () => doPrep(`
+            void foo()
+            {
+                float3 x;
+                bool r = bool(x);
+            }
+        `),
+        e => e instanceof WTypeError);
 
-    checkBool(program, callFunction(program, "boolFromEnumFalse", []), false);
-    checkBool(program, callFunction(program, "boolFromEnumTrue", []), true);
+    checkFail(
+        () => doPrep(`
+            void foo()
+            {
+                float3x3 x;
+                bool r = bool(x);
+            }
+        `),
+        e => e instanceof WTypeError);
 }
 
 tests.boolBitAnd = function()
@@ -3548,6 +3525,7 @@ tests.trap = function()
         e => e instanceof WTrapError);
 }
 
+/*
 tests.swizzle = function()
 {
     let program = doPrep(`
@@ -3572,6 +3550,7 @@ tests.swizzle = function()
     checkFloat(program, callFunction(program, "foo2", []), 6);
     checkFloat(program, callFunction(program, "foo3", []), 4);
 }
+*/
 
 tests.enumWithExplicitIntBase = function()
 {
@@ -5322,6 +5301,133 @@ tests.casts = function()
     checkInt(program, callFunction(program, "baz", [makeInt(program, 6)]), 14);
 }
 
+tests.pointerToMember = function()
+{
+    checkFail(
+        () => doPrep(`
+            void foo()
+            {
+                float3 x;
+                thread float* y = &x[1];
+            }
+        `),
+        e => e instanceof WTypeError);
+
+    checkFail(
+        () => doPrep(`
+            void foo()
+            {
+                float3x3 x;
+                thread float3* y = &x[1];
+            }
+        `),
+        e => e instanceof WTypeError);
+}
+
+tests.builtinMatrices = function()
+{
+    let program = doPrep(`
+        float foo()
+        {
+            float2x2 a;
+            a[0][0] = 1;
+            a[0][1] = 2;
+            a[1][0] = 3;
+            a[1][1] = 4;
+            return a[0][0];
+        }
+        float foo2()
+        {
+            float2x3 a;
+            a[0][0] = 1;
+            a[0][1] = 2;
+            a[0][2] = 3;
+            a[1][0] = 4;
+            a[1][1] = 5;
+            a[1][2] = 6;
+            return a[1][2];
+        }
+        float foo3()
+        {
+            float2x2 a;
+            return a[0][0];
+        }
+        bool foo4()
+        {
+            float2x2 a;
+            a[0][0] = 1;
+            a[0][1] = 2;
+            a[1][0] = 3;
+            a[1][1] = 4;
+            float2x2 b;
+            b[0][0] = 5;
+            b[0][1] = 6;
+            b[1][0] = 7;
+            b[1][1] = 8;
+            for (uint i = 0; i < 2; ++i) {
+                for (uint j = 0; j < 2; ++j) {
+                    a[i][j] += 4;
+                }
+            }
+            return a == b;
+        }
+        bool foo5()
+        {
+            float2x2 a;
+            a[0] = float2(1, 2);
+            a[1] = float2(3, 4);
+            float2x2 b;
+            b[0][0] = 1;
+            b[0][1] = 2;
+            b[1][0] = 3;
+            b[1][1] = 4;
+            return a == b;
+        }
+        bool foo6()
+        {
+            float2x2 a;
+            a[0][0] = 1;
+            a[0][1] = 2;
+            a[1][0] = 3;
+            a[1][1] = 4;
+            float2x2 b;
+            b[0][0] = 5;
+            b[0][1] = 10;
+            b[1][0] = 18;
+            b[1][1] = 24;
+            a[0] *= 5;
+            a[1] *= 6;
+            return a == b;
+        }
+        float foo7()
+        {
+            float2x3 a = float2x3(float3(3, 4, 5), float3(6, 7, 8));
+            return a[0][2];
+        }
+    `);
+    checkFloat(program, callFunction(program, "foo", []), 1);
+    checkFloat(program, callFunction(program, "foo2", []), 6);
+    checkFloat(program, callFunction(program, "foo3", []), 0);
+    checkBool(program, callFunction(program, "foo4", []), true);
+    checkBool(program, callFunction(program, "foo5", []), true);
+    checkBool(program, callFunction(program, "foo6", []), true);
+    checkFloat(program, callFunction(program, "foo7", []), 5);
+}
+
+tests.halfSimpleMath = function() {
+    let program = doPrep("half foo(half x, half y) { return x + y; }");
+    checkHalf(program, callFunction(program, "foo", [makeHalf(program, 7), makeHalf(program, 5)]), 12);
+    program = doPrep("half foo(half x, half y) { return x - y; }");
+    checkHalf(program, callFunction(program, "foo", [makeHalf(program, 7), makeHalf(program, 5)]), 2);
+    checkHalf(program, callFunction(program, "foo", [makeHalf(program, 5), makeHalf(program, 7)]), -2);
+    program = doPrep("half foo(half x, half y) { return x * y; }");
+    checkHalf(program, callFunction(program, "foo", [makeHalf(program, 7), makeHalf(program, 5)]), 35);
+    checkHalf(program, callFunction(program, "foo", [makeHalf(program, 7), makeHalf(program, -5)]), -35);
+    program = doPrep("half foo(half x, half y) { return x / y; }");
+    checkHalf(program, callFunction(program, "foo", [makeHalf(program, 7), makeHalf(program, 2)]), 3.5);
+    checkHalf(program, callFunction(program, "foo", [makeHalf(program, 7), makeHalf(program, -2)]), -3.5);
+}
+
 okToTest = true;
 
 let testFilter = /.*/; // run everything by default
index 1f1f54d..b9ea7e4 100644 (file)
@@ -340,5 +340,12 @@ class Visitor {
         node.elementType.visit(this);
         node.numElements.visit(this);
     }
+
+    visitMatrixType(node)
+    {
+        node.elementType.visit(this);
+        node.numRows.visit(this);
+        node.numColumns.visit(this);
+    }
 }
 
index 17d0c20..65a8641 100644 (file)
@@ -11,7 +11,6 @@
 <script src="CreateLiteral.js"></script>
 <script src="CreateLiteralType.js"></script>
 <script src="PropertyAccessExpression.js"></script>
-<script src="SwizzleOp.js"></script>
 <script src="NativeType.js"></script>
 
 <script src="AddressSpace.js"></script>
 <script src="Block.js"></script>
 <script src="BoolLiteral.js"></script>
 <script src="Break.js"></script>
-<script src="BuiltinVectorConstructors.js"></script>
+<script src="BuiltinMatrixGetter.js"></script>
+<script src="BuiltinMatrixSetter.js"></script>
 <script src="BuiltinVectorGetter.js"></script>
 <script src="BuiltinVectorSetter.js"></script>
-<script src="BuiltinVectorIndexGetter.js"></script>
-<script src="BuiltinVectorIndexSetter.js"></script>
-<script src="BuiltinVectorEqualityOperator.js"></script>
 <script src="CallExpression.js"></script>
 <script src="CallFunction.js"></script>
 <script src="Check.js"></script>
@@ -90,6 +87,7 @@
 <script src="LoopChecker.js"></script>
 <script src="MakeArrayRefExpression.js"></script>
 <script src="MakePtrExpression.js"></script>
+<script src="MatrixType.js"></script>
 <script src="NameContext.js"></script>
 <script src="NameFinder.js"></script>
 <script src="NameResolver.js"></script>
@@ -97,9 +95,8 @@
 <script src="NormalUsePropertyResolver.js"></script>
 <script src="NullLiteral.js"></script>
 <script src="NullType.js"></script>
-<script src="OperatorAnderIndex.js"></script>
+<script src="OperatorAnderIndexer.js"></script>
 <script src="OperatorArrayRefLength.js"></script>
-<script src="OperatorBool.js"></script>
 <script src="OriginKind.js"></script>
 <script src="OverloadResolutionFailure.js"></script>
 <script src="Parse.js"></script>
 <script src="SynthesizeArrayOperatorLength.js"></script>
 <script src="SynthesizeEnumFunctions.js"></script>
 <script src="SynthesizeStructAccessors.js"></script>
-<script src="SynthesizeOperatorBool.js"></script>
 <script src="SynthesizeCopyConstructorOperator.js"></script>
 <script src="SynthesizeDefaultConstructorOperator.js"></script>
 <script src="TernaryExpression.js"></script>