[WHLSL] Pointers should have automatically-generated equality checks
authormmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 29 Sep 2018 00:48:34 +0000 (00:48 +0000)
committermmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 29 Sep 2018 00:48:34 +0000 (00:48 +0000)
https://bugs.webkit.org/show_bug.cgi?id=189986

Reviewed by Filip Pizlo.

C allows for pointer equality, and we need it so people can do null checks.
This is generated the same way all our other NativeFuncs are generated - by Checker
creating NativeFuncs inside CallExpression.resolve().

This patch also does some general cleanup.

* WebGPUShadingLanguageRI/All.js: Everything the late checker does is no longer necessary.
The last thing it was doing was making sure that only primitive types are in resources, but
it's totally reasonable to put structs and arrays in resources, so I removed this pass. We
still have to add a check to make sure resources can't live within resources, but I expect
that will be done in the same place that semantics are checked.
* WebGPUShadingLanguageRI/AllocateAtEntryPoints.js:
(allocateAtEntryPoints.updateFunction.UpdateFunctions.prototype._addVariableDeclaration):
Name the global struct for debugging purposes.
* WebGPUShadingLanguageRI/CallExpression.js:
(CallExpression.prototype._resolveByInstantiation): Cleanup
(CallExpression.prototype._resolveWithOperatorAnderIndexer): Ditto
(CallExpression.prototype._resolveWithOperatorLength): Ditto
(CallExpression.prototype._resolveWithReferenceComparator): Add support to automatically
generate pointer equality NativeFuncs.
* WebGPUShadingLanguageRI/EPtr.js: Implement pointer equality in the interpreter.
* WebGPUShadingLanguageRI/LateChecker.js: Removed.
* WebGPUShadingLanguageRI/LayoutBuffers.js: Renamed from Tools/WebGPUShadingLanguageRI/LateCheckAndLayoutBuffers.js.
(layoutBuffers):
* WebGPUShadingLanguageRI/Metal/WHLSL Tests/WHLSL Tests.xcodeproj/project.pbxproj:
* WebGPUShadingLanguageRI/NativeFunc.js:
* WebGPUShadingLanguageRI/OperatorArrayRefLength.js:
(OperatorArrayRefLength.prototype.instantiateImplementation):
(OperatorArrayRefLength):
* WebGPUShadingLanguageRI/Prepare.js:
(let.prepare):
* WebGPUShadingLanguageRI/SPIRV.html:
* WebGPUShadingLanguageRI/Test.html:
* WebGPUShadingLanguageRI/Test.js:
(tests.ternaryExpression):
(tests.break): Speed up testing time
(tests.doWhile): Ditto
(tests.forLoop): Ditto
(tests.atomics): Ditto
(tests.atomicsNull): Ditto
(tests.pointerEquality): Test pointer equality
(tests.standardLibraryDevicePointers):
(tests.devicePtrPtr): Deleted.
(tests.threadgroupPtrPtr): Deleted.
(tests.constantPtrPtr): Deleted.
* WebGPUShadingLanguageRI/index.html:

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

16 files changed:
Tools/ChangeLog
Tools/WebGPUShadingLanguageRI/All.js
Tools/WebGPUShadingLanguageRI/AllocateAtEntryPoints.js
Tools/WebGPUShadingLanguageRI/CallExpression.js
Tools/WebGPUShadingLanguageRI/EArrayRef.js
Tools/WebGPUShadingLanguageRI/EPtr.js
Tools/WebGPUShadingLanguageRI/LateChecker.js [deleted file]
Tools/WebGPUShadingLanguageRI/LayoutBuffers.js [moved from Tools/WebGPUShadingLanguageRI/LateCheckAndLayoutBuffers.js with 94% similarity]
Tools/WebGPUShadingLanguageRI/Metal/WHLSL Tests/WHLSL Tests.xcodeproj/project.pbxproj
Tools/WebGPUShadingLanguageRI/NativeFunc.js
Tools/WebGPUShadingLanguageRI/OperatorArrayRefLength.js
Tools/WebGPUShadingLanguageRI/Prepare.js
Tools/WebGPUShadingLanguageRI/SPIRV.html
Tools/WebGPUShadingLanguageRI/Test.html
Tools/WebGPUShadingLanguageRI/Test.js
Tools/WebGPUShadingLanguageRI/index.html

index 604add6..47087b0 100644 (file)
@@ -1,3 +1,57 @@
+2018-09-28  Myles C. Maxfield  <mmaxfield@apple.com>
+
+        [WHLSL] Pointers should have automatically-generated equality checks
+        https://bugs.webkit.org/show_bug.cgi?id=189986
+
+        Reviewed by Filip Pizlo.
+
+        C allows for pointer equality, and we need it so people can do null checks.
+        This is generated the same way all our other NativeFuncs are generated - by Checker
+        creating NativeFuncs inside CallExpression.resolve().
+
+        This patch also does some general cleanup.
+
+        * WebGPUShadingLanguageRI/All.js: Everything the late checker does is no longer necessary.
+        The last thing it was doing was making sure that only primitive types are in resources, but
+        it's totally reasonable to put structs and arrays in resources, so I removed this pass. We
+        still have to add a check to make sure resources can't live within resources, but I expect
+        that will be done in the same place that semantics are checked.
+        * WebGPUShadingLanguageRI/AllocateAtEntryPoints.js:
+        (allocateAtEntryPoints.updateFunction.UpdateFunctions.prototype._addVariableDeclaration):
+        Name the global struct for debugging purposes.
+        * WebGPUShadingLanguageRI/CallExpression.js: 
+        (CallExpression.prototype._resolveByInstantiation): Cleanup
+        (CallExpression.prototype._resolveWithOperatorAnderIndexer): Ditto
+        (CallExpression.prototype._resolveWithOperatorLength): Ditto
+        (CallExpression.prototype._resolveWithReferenceComparator): Add support to automatically
+        generate pointer equality NativeFuncs.
+        * WebGPUShadingLanguageRI/EPtr.js: Implement pointer equality in the interpreter.
+        * WebGPUShadingLanguageRI/LateChecker.js: Removed.
+        * WebGPUShadingLanguageRI/LayoutBuffers.js: Renamed from Tools/WebGPUShadingLanguageRI/LateCheckAndLayoutBuffers.js.
+        (layoutBuffers):
+        * WebGPUShadingLanguageRI/Metal/WHLSL Tests/WHLSL Tests.xcodeproj/project.pbxproj:
+        * WebGPUShadingLanguageRI/NativeFunc.js:
+        * WebGPUShadingLanguageRI/OperatorArrayRefLength.js:
+        (OperatorArrayRefLength.prototype.instantiateImplementation):
+        (OperatorArrayRefLength):
+        * WebGPUShadingLanguageRI/Prepare.js:
+        (let.prepare):
+        * WebGPUShadingLanguageRI/SPIRV.html:
+        * WebGPUShadingLanguageRI/Test.html:
+        * WebGPUShadingLanguageRI/Test.js:
+        (tests.ternaryExpression):
+        (tests.break): Speed up testing time
+        (tests.doWhile): Ditto
+        (tests.forLoop): Ditto
+        (tests.atomics): Ditto
+        (tests.atomicsNull): Ditto
+        (tests.pointerEquality): Test pointer equality
+        (tests.standardLibraryDevicePointers):
+        (tests.devicePtrPtr): Deleted.
+        (tests.threadgroupPtrPtr): Deleted.
+        (tests.constantPtrPtr): Deleted.
+        * WebGPUShadingLanguageRI/index.html:
+
 2018-09-28  Jiewen Tan  <jiewen_tan@apple.com>
 
         [WebAuthN] Polish WebAuthN auto-test environment
index 7039252..ba65cc5 100644 (file)
@@ -108,8 +108,7 @@ load("Inliner.js");
 load("IntLiteral.js");
 load("IntLiteralType.js");
 load("Intrinsics.js");
-load("LateCheckAndLayoutBuffers.js");
-load("LateChecker.js");
+load("LayoutBuffers.js");
 load("Lexer.js");
 load("LexerToken.js");
 load("LiteralTypeChecker.js");
index b8747e6..2cde53f 100644 (file)
@@ -142,7 +142,7 @@ function allocateAtEntryPoints(program)
 
             _addVariableDeclaration()
             {
-                this._variableDecl = new VariableDecl(func.origin, null, globalStructTypeRef, null);
+                this._variableDecl = new VariableDecl(func.origin, "global struct", globalStructTypeRef, null);
                 this.makeGlobalStructVariableRef = () => new MakePtrExpression(func.origin, VariableRef.wrap(this._variableDecl));
                 func.body.statements.unshift(this._variableDecl);
             }
index b4c0da7..04be2da 100644 (file)
@@ -102,6 +102,11 @@ class CallExpression extends Expression {
             func = this._resolveWithOperatorAnderIndexer(program);
         else if (this.name == "operator.length")
             func = this._resolveWithOperatorLength(program);
+        else if (this.name == "operator==" && this.argumentTypes.length == 2
+            && (this.argumentTypes[0] instanceof NullType || this.argumentTypes[0] instanceof ReferenceType)
+            && (this.argumentTypes[1] instanceof NullType || this.argumentTypes[1] instanceof ReferenceType)
+            && this.argumentTypes[0].equals(this.argumentTypes[1]))
+                func = this._resolveWithReferenceComparator(program);
         else
             return null;
 
@@ -119,17 +124,17 @@ class CallExpression extends Expression {
         const addressSpace = arrayRefType.addressSpace;
 
         // The later checkLiteralTypes stage will verify that the literal can be represented as a uint.
-        const uintType = TypeRef.wrap(program.types.get("uint"));
+        const uintType = TypeRef.wrap(program.intrinsics.uint);
         indexType.type = uintType;
 
         const elementType = this.argumentTypes[0].elementType;
-        this.resultType = this._returnType = TypeRef.wrap(new PtrType(this.origin, addressSpace, TypeRef.wrap(elementType)))
+        this.resultType = TypeRef.wrap(new PtrType(this.origin, addressSpace, TypeRef.wrap(elementType)))
 
-        let arrayRefAccessor = new OperatorAnderIndexer(this.returnType.toString(), addressSpace);
+        let arrayRefAccessor = new OperatorAnderIndexer(this.resultType.toString(), addressSpace);
         const func = new NativeFunc(this.origin, "operator&[]", this.resultType, [
             new FuncParameter(this.origin, null, arrayRefType),
             new FuncParameter(this.origin, null, uintType)
-        ], false);
+        ]);
 
         arrayRefAccessor.instantiateImplementation(func);
 
@@ -138,14 +143,14 @@ class CallExpression extends Expression {
 
     _resolveWithOperatorLength(program)
     {
-        this.resultType = this._returnType = TypeRef.wrap(program.types.get("uint"));
+        this.resultType = TypeRef.wrap(program.intrinsics.uint);
 
         if (this.argumentTypes[0].isArray) {
             const arrayType = this.argumentTypes[0];
             const func = new NativeFunc(this.origin, "operator.length", this.resultType, [
                 new FuncParameter(this.origin, null, arrayType)
-            ], false);
-            func.implementation = (args, node) => EPtr.box(arrayType.numElementsValue);
+            ]);
+            func.implementation = (args) => EPtr.box(arrayType.numElementsValue);
             return func;
         } else if (this.argumentTypes[0].isArrayRef) {
             const arrayRefType = this.argumentTypes[0];
@@ -153,12 +158,38 @@ class CallExpression extends Expression {
             const operatorLength = new OperatorArrayRefLength(arrayRefType.toString(), addressSpace);
             const func = new NativeFunc(this.origin, "operator.length", this.resultType, [
                 new FuncParameter(this.origin, null, arrayRefType)
-            ], false);
+            ]);
             operatorLength.instantiateImplementation(func);
             return func;
         } else
             throw new WTypeError(this.origin.originString, `Expected ${this.argumentTypes[0]} to be array/array ref type for operator.length`);
     }
+
+    _resolveWithReferenceComparator(program)
+    {
+        let argumentType = this.argumentTypes[0];
+        if (argumentType instanceof NullType)
+            argumentType = this.argumentTypes[1];
+        if (argumentType instanceof NullType) {
+            // We encountered "null == null".
+            // The type isn't observable, so we can pick whatever we want.
+            // FIXME: This can probably be generalized, using the "preferred type" infrastructure used by generic literals
+            argumentType = new PtrType(this.origin, "thread", program.intrinsics.int);
+        }
+        this.resultType = TypeRef.wrap(program.intrinsics.bool);
+        const func = new NativeFunc(this.origin, "operator==", this.resultType, [
+            new FuncParameter(this.origin, null, argumentType),
+            new FuncParameter(this.origin, null, argumentType)
+        ]);
+        func.implementation = ([lhs, rhs]) => {
+            let left = lhs.loadValue();
+            let right = rhs.loadValue();
+            if (left && right)
+                return EPtr.box(left.equals(right));
+            return EPtr.box(left == right);
+        };
+        return func;
+    }
     
     resolveToOverload(overload)
     {
index 1173b17..912def7 100644 (file)
@@ -33,6 +33,11 @@ class EArrayRef {
     
     get ptr() { return this._ptr; }
     get length() { return this._length; }
+
+    equals(other)
+    {
+        return this.ptr.equals(other.ptr) && this.length == other.length;
+    }
     
     toString()
     {
index e25826c..ef5b5b4 100644 (file)
@@ -79,6 +79,11 @@ class EPtr {
         for (let i = size; i--;)
             this.set(i, other.get(i));
     }
+
+    equals(other)
+    {
+        return this.buffer == other.buffer && this.offset == other.offset;
+    }
     
     toString()
     {
diff --git a/Tools/WebGPUShadingLanguageRI/LateChecker.js b/Tools/WebGPUShadingLanguageRI/LateChecker.js
deleted file mode 100644 (file)
index 47fd32c..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-"use strict";
-
-class LateChecker extends Visitor {
-    visitReferenceType(node)
-    {
-        if (node.addressSpace == "thread")
-            return;
-        
-        if (!node.elementType.isPrimitive)
-            throw new WTypeError(node.origin.originString, "Illegal pointer to non-primitive type: " + node);
-    }
-}
-
  */
 "use strict";
 
-function lateCheckAndLayoutBuffers(program)
+function layoutBuffers(program)
 {
     for (let funcList of program.functions.values()) {
         for (let func of funcList) {
             if (func.isNative)
                 continue;
-            func.visit(new LateChecker());
             func.visit(new EBufferBuilder());
         }
     }
-}
\ No newline at end of file
+}
index 0f847ae..9ef8ae0 100644 (file)
@@ -83,7 +83,6 @@
                E92D115A20F7060E00D776B2 /* IntLiteral.js in Resources */ = {isa = PBXBuildFile; fileRef = E92D0FE420F56DDD00D776B2 /* IntLiteral.js */; };
                E92D115B20F7060E00D776B2 /* IntLiteralType.js in Resources */ = {isa = PBXBuildFile; fileRef = E92D0FE520F56DDD00D776B2 /* IntLiteralType.js */; };
                E92D115C20F7060E00D776B2 /* Intrinsics.js in Resources */ = {isa = PBXBuildFile; fileRef = E92D0FE720F56DDD00D776B2 /* Intrinsics.js */; };
-               E92D115D20F7060E00D776B2 /* LateChecker.js in Resources */ = {isa = PBXBuildFile; fileRef = E9FCEB6420F56DA5009B3629 /* LateChecker.js */; };
                E92D115E20F7060E00D776B2 /* Lexer.js in Resources */ = {isa = PBXBuildFile; fileRef = E92D0FF120F56DEC00D776B2 /* Lexer.js */; };
                E92D115F20F7060E00D776B2 /* LexerToken.js in Resources */ = {isa = PBXBuildFile; fileRef = E92D0FF020F56DEB00D776B2 /* LexerToken.js */; };
                E92D116020F7060E00D776B2 /* LiteralTypeChecker.js in Resources */ = {isa = PBXBuildFile; fileRef = E92D0FF220F56DEC00D776B2 /* LiteralTypeChecker.js */; };
                E9D7CB98214B824200F1C918 /* MSLBackend.js in Resources */ = {isa = PBXBuildFile; fileRef = E9D7CB95214B824200F1C918 /* MSLBackend.js */; };
                E9D7CB99214B824200F1C918 /* MSLConstexprEmitter.js in Resources */ = {isa = PBXBuildFile; fileRef = E9D7CB96214B824200F1C918 /* MSLConstexprEmitter.js */; };
                E9D7CBA0214B82B800F1C918 /* Texture.js in Resources */ = {isa = PBXBuildFile; fileRef = E9D7CB9A214B82B700F1C918 /* Texture.js */; };
-               E9D7CBA1214B82B800F1C918 /* LateCheckAndLayoutBuffers.js in Resources */ = {isa = PBXBuildFile; fileRef = E9D7CB9B214B82B700F1C918 /* LateCheckAndLayoutBuffers.js */; };
+               E9D7CBA1214B82B800F1C918 /* LayoutBuffers.js in Resources */ = {isa = PBXBuildFile; fileRef = E9D7CB9B214B82B700F1C918 /* LayoutBuffers.js */; };
                E9D7CBA2214B82B800F1C918 /* Casts.js in Resources */ = {isa = PBXBuildFile; fileRef = E9D7CB9C214B82B700F1C918 /* Casts.js */; };
                E9D7CBA3214B82B800F1C918 /* Sampler.js in Resources */ = {isa = PBXBuildFile; fileRef = E9D7CB9D214B82B800F1C918 /* Sampler.js */; };
                E9D7CBA4214B82B800F1C918 /* TextureOperations.js in Resources */ = {isa = PBXBuildFile; fileRef = E9D7CB9E214B82B800F1C918 /* TextureOperations.js */; };
                E9D7CB95214B824200F1C918 /* MSLBackend.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = MSLBackend.js; path = ../../MSLBackend.js; sourceTree = "<group>"; };
                E9D7CB96214B824200F1C918 /* MSLConstexprEmitter.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = MSLConstexprEmitter.js; path = ../../MSLConstexprEmitter.js; sourceTree = "<group>"; };
                E9D7CB9A214B82B700F1C918 /* Texture.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = Texture.js; path = ../../../Texture.js; sourceTree = "<group>"; };
-               E9D7CB9B214B82B700F1C918 /* LateCheckAndLayoutBuffers.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = LateCheckAndLayoutBuffers.js; path = ../../../LateCheckAndLayoutBuffers.js; sourceTree = "<group>"; };
+               E9D7CB9B214B82B700F1C918 /* LayoutBuffers.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = LayoutBuffers.js; path = ../../../LayoutBuffers.js; sourceTree = "<group>"; };
                E9D7CB9C214B82B700F1C918 /* Casts.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = Casts.js; path = ../../../Casts.js; sourceTree = "<group>"; };
                E9D7CB9D214B82B800F1C918 /* Sampler.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = Sampler.js; path = ../../../Sampler.js; sourceTree = "<group>"; };
                E9D7CB9E214B82B800F1C918 /* TextureOperations.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = TextureOperations.js; path = ../../../TextureOperations.js; sourceTree = "<group>"; };
                E9FCEB5A20F56D93009B3629 /* ForLoop.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = ForLoop.js; path = ../../../ForLoop.js; sourceTree = "<group>"; };
                E9FCEB5B20F56D93009B3629 /* Field.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = Field.js; path = ../../../Field.js; sourceTree = "<group>"; };
                E9FCEB6320F56DA4009B3629 /* IndexExpression.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = IndexExpression.js; path = ../../../IndexExpression.js; sourceTree = "<group>"; };
-               E9FCEB6420F56DA5009B3629 /* LateChecker.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = LateChecker.js; path = ../../../LateChecker.js; sourceTree = "<group>"; };
                E9FCEB6520F56DA5009B3629 /* InferTypesForCall.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = InferTypesForCall.js; path = ../../../InferTypesForCall.js; sourceTree = "<group>"; };
                E9FCEB6620F56DA5009B3629 /* Inline.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = Inline.js; path = ../../../Inline.js; sourceTree = "<group>"; };
 /* End PBXFileReference section */
                                E92D0FE420F56DDD00D776B2 /* IntLiteral.js */,
                                E92D0FE520F56DDD00D776B2 /* IntLiteralType.js */,
                                E92D0FE720F56DDD00D776B2 /* Intrinsics.js */,
-                               E9D7CB9B214B82B700F1C918 /* LateCheckAndLayoutBuffers.js */,
-                               E9FCEB6420F56DA5009B3629 /* LateChecker.js */,
+                               E9D7CB9B214B82B700F1C918 /* LayoutBuffers.js */,
                                E92D0FF120F56DEC00D776B2 /* Lexer.js */,
                                E92D0FF020F56DEB00D776B2 /* LexerToken.js */,
                                E92D0FF220F56DEC00D776B2 /* LiteralTypeChecker.js */,
                                E92D115B20F7060E00D776B2 /* IntLiteralType.js in Resources */,
                                E92D115C20F7060E00D776B2 /* Intrinsics.js in Resources */,
                                E906B04621139B7700AD1C5E /* Julia.whlsl in Resources */,
-                               E9D7CBA1214B82B800F1C918 /* LateCheckAndLayoutBuffers.js in Resources */,
-                               E92D115D20F7060E00D776B2 /* LateChecker.js in Resources */,
+                               E9D7CBA1214B82B800F1C918 /* LayoutBuffers.js in Resources */,
                                E92D115E20F7060E00D776B2 /* Lexer.js in Resources */,
                                E92D115F20F7060E00D776B2 /* LexerToken.js in Resources */,
                                E92D116020F7060E00D776B2 /* LiteralTypeChecker.js in Resources */,
index bbf0285..ef69ebe 100644 (file)
@@ -25,7 +25,7 @@
 "use strict";
 
 class NativeFunc extends Func {
-    constructor(origin, name, returnType, parameters, isCast, stage = null)
+    constructor(origin, name, returnType, parameters, isCast = false, stage = null)
     {
         super(origin, name, returnType, parameters, isCast);
         this._stage = stage;
index 63edd79..79062c2 100644 (file)
@@ -41,7 +41,7 @@ class OperatorArrayRefLength {
 
     instantiateImplementation(func)
     {
-        func.implementation = ([ref], node) => {
+        func.implementation = ([ref]) => {
             ref = ref.loadValue();
             if (!ref)
                 return EPtr.box(0);
@@ -49,4 +49,4 @@ class OperatorArrayRefLength {
         };
         func.implementationData = this;
     }
-}
\ No newline at end of file
+}
index c1158cf..d78f974 100644 (file)
@@ -32,13 +32,13 @@ let prepare = (() => {
             let firstLineOfStandardLibrary = 28; // See StandardLibrary.js.
             parse(standardProgram, "/internal/stdlib", "native", firstLineOfStandardLibrary - 1, standardLibrary);
         }
-        
+
         let program = cloneProgram(standardProgram);
         if (arguments.length) {
             parse(program, origin, "user", lineNumberOffset, text);
             program = programWithUnnecessaryThingsRemoved(program);
         }
-        
+
         foldConstexprs(program);
 
         let nameResolver = createNameResolver(program);
@@ -69,7 +69,7 @@ let prepare = (() => {
         findHighZombies(program);
         allocateAtEntryPoints(program);
         program.visit(new StructLayoutBuilder());
-        lateCheckAndLayoutBuffers(program);
+        layoutBuffers(program);
         checkNativeFuncStages(program);
         if (shouldInline)
             inline(program);
index 6f6d6c0..ca450f7 100644 (file)
@@ -91,8 +91,7 @@ td {
     <script src="IntLiteral.js"></script>
     <script src="IntLiteralType.js"></script>
     <script src="Intrinsics.js"></script>
-    <script src="LateCheckAndLayoutBuffers.js"></script>
-    <script src="LateChecker.js"></script>
+    <script src="LayoutBuffers.js"></script>
     <script src="Lexer.js"></script>
     <script src="LexerToken.js"></script>
     <script src="LiteralTypeChecker.js"></script>
index cd3bda0..a203152 100644 (file)
@@ -85,8 +85,7 @@
 <script src="IntLiteral.js"></script>
 <script src="IntLiteralType.js"></script>
 <script src="Intrinsics.js"></script>
-<script src="LateChecker.js"></script>
-<script src="LateCheckAndLayoutBuffers.js"></script>
+<script src="LayoutBuffers.js"></script>
 <script src="Lexer.js"></script>
 <script src="LexerToken.js"></script>
 <script src="LiteralTypeChecker.js"></script>
index 659b432..e118333 100644 (file)
@@ -343,24 +343,24 @@ tests.ternaryExpression = function() {
         {
             return x < 3 ? 4 : 5;
         }
-        test int baz(int x)
+        test int bar(int x)
         {
             return x < 10 ? 11 : x < 12 ? 14 : 15;
         }
-        test int quux(int x)
+        test int baz(int x)
         {
             return 3 < 4 ? x : 5;
         }
     `);
     checkInt(program, callFunction(program, "foo", [makeInt(program, 767)]), 5);
     checkInt(program, callFunction(program, "foo", [makeInt(program, 2)]), 4);
-    checkInt(program, callFunction(program, "baz", [makeInt(program, 8)]), 11);
-    checkInt(program, callFunction(program, "baz", [makeInt(program, 9)]), 11);
-    checkInt(program, callFunction(program, "baz", [makeInt(program, 10)]), 14);
-    checkInt(program, callFunction(program, "baz", [makeInt(program, 11)]), 14);
-    checkInt(program, callFunction(program, "baz", [makeInt(program, 12)]), 15);
-    checkInt(program, callFunction(program, "baz", [makeInt(program, 13)]), 15);
-    checkInt(program, callFunction(program, "quux", [makeInt(program, 14)]), 14);
+    checkInt(program, callFunction(program, "bar", [makeInt(program, 8)]), 11);
+    checkInt(program, callFunction(program, "bar", [makeInt(program, 9)]), 11);
+    checkInt(program, callFunction(program, "bar", [makeInt(program, 10)]), 14);
+    checkInt(program, callFunction(program, "bar", [makeInt(program, 11)]), 14);
+    checkInt(program, callFunction(program, "bar", [makeInt(program, 12)]), 15);
+    checkInt(program, callFunction(program, "bar", [makeInt(program, 13)]), 15);
+    checkInt(program, callFunction(program, "baz", [makeInt(program, 14)]), 14);
     checkFail(
         () => doPrep(`
             int foo()
@@ -1384,7 +1384,7 @@ tests.intOverloadResolutionReverseOrder = function()
 tests.break = function()
 {
     let program = doPrep(`
-        test int foo(int x)
+        test int foo1(int x)
         {
             while (true) {
                 x = x * 2;
@@ -1393,11 +1393,7 @@ tests.break = function()
             }
             return x;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 8);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 10)]), 20);
-    program = doPrep(`
-        test int foo(int x)
+        test int foo2(int x)
         {
             while (true) {
                 while (true) {
@@ -1409,11 +1405,38 @@ tests.break = function()
                 break;
             }
             return x;
-
+        }
+        test int foo3(int x)
+        {
+            while (true) {
+                if (x == 7) {
+                    break;
+                }
+                x = x + 1;
+            }
+            return x;
+        }
+        test int foo4(int x)
+        {
+            while (true) {
+                break;
+            }
+            return x;
+        }
+        test int foo5()
+        {
+            while (true) {
+                return 7;
+            }
         }
     `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 7);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 10)]), 19);
+    checkInt(program, callFunction(program, "foo1", [makeInt(program, 1)]), 8);
+    checkInt(program, callFunction(program, "foo1", [makeInt(program, 10)]), 20);
+    checkInt(program, callFunction(program, "foo2", [makeInt(program, 1)]), 7);
+    checkInt(program, callFunction(program, "foo2", [makeInt(program, 10)]), 19);
+    checkInt(program, callFunction(program, "foo3", [makeInt(program, 1)]), 7);
+    checkInt(program, callFunction(program, "foo4", [makeInt(program, 1)]), 1);
+    checkInt(program, callFunction(program, "foo5", []), 7);
     checkFail(
         () => doPrep(`
             int foo(int x)
@@ -1437,38 +1460,6 @@ tests.break = function()
             }
         `),
         (e) => e instanceof WTypeError);
-    program = doPrep(`
-            test int foo(int x)
-            {
-                while (true) {
-                    if (x == 7) {
-                        break;
-                    }
-                    x = x + 1;
-                }
-                return x;
-            }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 7);
-    program = doPrep(`
-            test int foo(int x)
-            {
-                while (true) {
-                    break;
-                }
-                return x;
-            }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 1);
-    program = doPrep(`
-            test int foo()
-            {
-                while (true) {
-                    return 7;
-                }
-            }
-    `);
-    checkInt(program, callFunction(program, "foo", []), 7);
     checkFail(
         () => doPrep(`
             test int foo(int x)
@@ -1513,7 +1504,7 @@ tests.continue = function()
 tests.doWhile = function()
 {
     let program = doPrep(`
-        test int foo(int x)
+        test int foo1(int x)
         {
             int y = 7;
             do {
@@ -1522,11 +1513,7 @@ tests.doWhile = function()
             } while (x < 10);
             return y;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 8);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 11)]), 8);
-    program = doPrep(`
-        test int foo(int x)
+        test int foo2(int x)
         {
             int y = 7;
             do {
@@ -1535,10 +1522,7 @@ tests.doWhile = function()
             } while (y == 7);
             return y;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 8);
-    program = doPrep(`
-        test int foo(int x)
+        test int foo3(int x)
         {
             int sum = 0;
             do {
@@ -1552,13 +1536,16 @@ tests.doWhile = function()
             return sum;
         }
     `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 19);
+    checkInt(program, callFunction(program, "foo1", [makeInt(program, 1)]), 8);
+    checkInt(program, callFunction(program, "foo1", [makeInt(program, 11)]), 8);
+    checkInt(program, callFunction(program, "foo2", [makeInt(program, 1)]), 8);
+    checkInt(program, callFunction(program, "foo3", [makeInt(program, 9)]), 19);
 }
 
 tests.forLoop = function()
 {
     let program = doPrep(`
-        test int foo(int x)
+        test int foo1(int x)
         {
             int sum = 0;
             int i;
@@ -1567,12 +1554,7 @@ tests.forLoop = function()
             }
             return sum;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
-    program = doPrep(`
-        test int foo(int x)
+        test int foo2(int x)
         {
             int sum = 0;
             for (int i = 0; i < x; i = i + 1) {
@@ -1580,12 +1562,7 @@ tests.forLoop = function()
             }
             return sum;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
-    program = doPrep(`
-        test int foo(int x)
+        test int foo3(int x)
         {
             int sum = 0;
             int i = 100;
@@ -1594,12 +1571,7 @@ tests.forLoop = function()
             }
             return sum;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
-    program = doPrep(`
-        test int foo(int x)
+        test int foo4(int x)
         {
             int sum = 0;
             for (int i = 0; i < x; i = i + 1) {
@@ -1609,13 +1581,7 @@ tests.forLoop = function()
             }
             return sum;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 6);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 11);
-    program = doPrep(`
-        test int foo(int x)
+        test int foo5(int x)
         {
             int sum = 0;
             for (int i = 0; i < x; i = i + 1) {
@@ -1625,14 +1591,7 @@ tests.forLoop = function()
             }
             return sum;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 10);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 10);
-    program = doPrep(`
-        test int foo(int x)
+        test int foo6(int x)
         {
             int sum = 0;
             for (int i = 0; ; i = i + 1) {
@@ -1642,14 +1601,7 @@ tests.forLoop = function()
             }
             return sum;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 15);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 21);
-    program = doPrep(`
-        test int foo(int x)
+        test int foo7(int x)
         {
             int sum = 0;
             int i = 0;
@@ -1660,14 +1612,7 @@ tests.forLoop = function()
             }
             return sum;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 15);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 21);
-    program = doPrep(`
-        test int foo(int x)
+        test int foo8(int x)
         {
             int sum = 0;
             int i = 0;
@@ -1679,12 +1624,62 @@ tests.forLoop = function()
             }
             return sum;
         }
+        test int foo9(int x)
+        {
+            for ( ; ; ) {
+                return 7;
+            }
+        }
+        test int foo10(int x)
+        {
+            for ( ; true; ) {
+                return 7;
+            }
+        }
     `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 15);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 21);
+    checkInt(program, callFunction(program, "foo1", [makeInt(program, 3)]), 3);
+    checkInt(program, callFunction(program, "foo1", [makeInt(program, 4)]), 6);
+    checkInt(program, callFunction(program, "foo1", [makeInt(program, 5)]), 10);
+    checkInt(program, callFunction(program, "foo2", [makeInt(program, 3)]), 3);
+    checkInt(program, callFunction(program, "foo2", [makeInt(program, 4)]), 6);
+    checkInt(program, callFunction(program, "foo2", [makeInt(program, 5)]), 10);
+    checkInt(program, callFunction(program, "foo3", [makeInt(program, 3)]), 3);
+    checkInt(program, callFunction(program, "foo3", [makeInt(program, 4)]), 6);
+    checkInt(program, callFunction(program, "foo3", [makeInt(program, 5)]), 10);
+    checkInt(program, callFunction(program, "foo4", [makeInt(program, 3)]), 3);
+    checkInt(program, callFunction(program, "foo4", [makeInt(program, 4)]), 6);
+    checkInt(program, callFunction(program, "foo4", [makeInt(program, 5)]), 6);
+    checkInt(program, callFunction(program, "foo4", [makeInt(program, 6)]), 11);
+    checkInt(program, callFunction(program, "foo5", [makeInt(program, 3)]), 3);
+    checkInt(program, callFunction(program, "foo5", [makeInt(program, 4)]), 6);
+    checkInt(program, callFunction(program, "foo5", [makeInt(program, 5)]), 10);
+    checkInt(program, callFunction(program, "foo5", [makeInt(program, 6)]), 10);
+    checkInt(program, callFunction(program, "foo5", [makeInt(program, 7)]), 10);
+    checkInt(program, callFunction(program, "foo6", [makeInt(program, 3)]), 3);
+    checkInt(program, callFunction(program, "foo6", [makeInt(program, 4)]), 6);
+    checkInt(program, callFunction(program, "foo6", [makeInt(program, 5)]), 10);
+    checkInt(program, callFunction(program, "foo6", [makeInt(program, 6)]), 15);
+    checkInt(program, callFunction(program, "foo6", [makeInt(program, 7)]), 21);
+    checkInt(program, callFunction(program, "foo7", [makeInt(program, 3)]), 3);
+    checkInt(program, callFunction(program, "foo7", [makeInt(program, 4)]), 6);
+    checkInt(program, callFunction(program, "foo7", [makeInt(program, 5)]), 10);
+    checkInt(program, callFunction(program, "foo7", [makeInt(program, 6)]), 15);
+    checkInt(program, callFunction(program, "foo7", [makeInt(program, 7)]), 21);
+    checkInt(program, callFunction(program, "foo8", [makeInt(program, 3)]), 3);
+    checkInt(program, callFunction(program, "foo8", [makeInt(program, 4)]), 6);
+    checkInt(program, callFunction(program, "foo8", [makeInt(program, 5)]), 10);
+    checkInt(program, callFunction(program, "foo8", [makeInt(program, 6)]), 15);
+    checkInt(program, callFunction(program, "foo8", [makeInt(program, 7)]), 21);
+    checkInt(program, callFunction(program, "foo9", [makeInt(program, 3)]), 7);
+    checkInt(program, callFunction(program, "foo9", [makeInt(program, 4)]), 7);
+    checkInt(program, callFunction(program, "foo9", [makeInt(program, 5)]), 7);
+    checkInt(program, callFunction(program, "foo9", [makeInt(program, 6)]), 7);
+    checkInt(program, callFunction(program, "foo9", [makeInt(program, 7)]), 7);
+    checkInt(program, callFunction(program, "foo10", [makeInt(program, 3)]), 7);
+    checkInt(program, callFunction(program, "foo10", [makeInt(program, 4)]), 7);
+    checkInt(program, callFunction(program, "foo10", [makeInt(program, 5)]), 7);
+    checkInt(program, callFunction(program, "foo10", [makeInt(program, 6)]), 7);
+    checkInt(program, callFunction(program, "foo10", [makeInt(program, 7)]), 7);
     checkFail(
         () => doPrep(`
             void foo(int x)
@@ -1696,19 +1691,6 @@ tests.forLoop = function()
             }
         `),
         (e) => e instanceof WTypeError);
-    program = doPrep(`
-        test int foo(int x)
-        {
-            for ( ; ; ) {
-                return 7;
-            }
-        }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 7);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 7);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 7);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 7);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 7);
     checkFail(
         () => doPrep(`
             int foo(int x)
@@ -1719,19 +1701,6 @@ tests.forLoop = function()
             }
         `),
         (e) => e instanceof WTypeError);
-    program = doPrep(`
-        test int foo(int x)
-        {
-            for ( ; true; ) {
-                return 7;
-            }
-        }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 7);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 7);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 7);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 7);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 7);
 }
 
 tests.prefixPlusPlus = function()
@@ -5828,42 +5797,6 @@ tests.indexAnderWithArrayRef = function()
     checkInt(program, callFunction(program, "foo", []), 13);
 }
 
-tests.devicePtrPtr = function()
-{
-    checkFail(
-        () => doPrep(`
-            void foo()
-            {
-                device int** p;
-            }
-        `),
-        e => e instanceof WTypeError && e.message.indexOf("Illegal pointer to non-primitive type: int* device* device") != -1);
-}
-
-tests.threadgroupPtrPtr = function()
-{
-    checkFail(
-        () => doPrep(`
-            void foo()
-            {
-                threadgroup int** p;
-            }
-        `),
-        e => e instanceof WTypeError && e.message.indexOf("Illegal pointer to non-primitive type: int* threadgroup* threadgroup") != -1);
-}
-
-tests.constantPtrPtr = function()
-{
-    checkFail(
-        () => doPrep(`
-            void foo()
-            {
-                constant int** p;
-            }
-        `),
-        e => e instanceof WTypeError && e.message.indexOf("Illegal pointer to non-primitive type: int* constant* constant") != -1);
-}
-
 tests.andReturnedArrayRef = function()
 {
     let program = doPrep(`
@@ -6056,364 +5989,248 @@ tests.casts = function()
 tests.atomics = function()
 {
     let program = doPrep(`
-        test int foo(int z) {
+        test int foo1(int z) {
             atomic_int x;
             int result;
             InterlockedAdd(&x, z, &result);
             return result;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 0);
-    program = doPrep(`
-        test int foo(int z) {
+        test int foo2(int z) {
             atomic_int x;
             int result;
             InterlockedAdd(&x, z, &result);
             InterlockedAdd(&x, z, &result);
             return result;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 6);
-    program = doPrep(`
-        test int foo(int z) {
+        test int foo3(int z) {
             atomic_int x;
             int result;
             InterlockedAdd(&x, z, &result);
             return int(x);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 6);
-    program = doPrep(`
-        test int foo(int z) {
+        test int foo4(int z) {
             atomic_int x;
             int result;
             InterlockedAdd(&x, z, &result);
             InterlockedAdd(&x, z, &result);
             return int(x);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 12);
-    program = doPrep(`
-        test uint foo(uint z) {
+        test uint foo5(uint z) {
             atomic_uint x;
             uint result;
             InterlockedAdd(&x, z, &result);
             return result;
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 6)]), 0);
-    program = doPrep(`
-        test uint foo(uint z) {
+        test uint foo6(uint z) {
             atomic_uint x;
             uint result;
             InterlockedAdd(&x, z, &result);
             InterlockedAdd(&x, z, &result);
             return result;
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 6)]), 6);
-    program = doPrep(`
-        test uint foo(uint z) {
+        test uint foo7(uint z) {
             atomic_uint x;
             uint result;
             InterlockedAdd(&x, z, &result);
             return uint(x);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 6)]), 6);
-    program = doPrep(`
-        test uint foo(uint z) {
+        test uint foo8(uint z) {
             atomic_uint x;
             uint result;
             InterlockedAdd(&x, z, &result);
             InterlockedAdd(&x, z, &result);
             return uint(x);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 6)]), 12);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo9(uint x, uint y) {
             atomic_uint z;
             uint result;
             InterlockedAdd(&z, x, &result);
             InterlockedAnd(&z, y, &result);
             return uint(z);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 1);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo10(uint x, uint y) {
             atomic_uint z;
             uint result;
             InterlockedAdd(&z, x, &result);
             InterlockedAnd(&z, y, &result);
             return result;
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 3);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo11(int x, int y) {
             atomic_int z;
             int result;
             InterlockedAdd(&z, x, &result);
             InterlockedAnd(&z, y, &result);
             return int(z);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 1);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo12(int x, int y) {
             atomic_int z;
             int result;
             InterlockedAdd(&z, x, &result);
             InterlockedAnd(&z, y, &result);
             return result;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 3);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo13(uint x, uint y) {
             atomic_uint z;
             uint result;
             InterlockedAdd(&z, x, &result);
             InterlockedExchange(&z, y, &result);
             return uint(z);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 5);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo14(uint x, uint y) {
             atomic_uint z;
             uint result;
             InterlockedAdd(&z, x, &result);
             InterlockedExchange(&z, y, &result);
             return result;
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 3);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo15(int x, int y) {
             atomic_int z;
             int result;
             InterlockedAdd(&z, x, &result);
             InterlockedExchange(&z, y, &result);
             return int(z);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 5);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo16(int x, int y) {
             atomic_int z;
             int result;
             InterlockedAdd(&z, x, &result);
             InterlockedExchange(&z, y, &result);
             return result;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 3);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo17(uint x, uint y) {
             atomic_uint z;
             uint result;
             InterlockedAdd(&z, x, &result);
             InterlockedMax(&z, y, &result);
             return uint(z);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 5);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 5), makeUint(program, 3)]), 5);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo18(uint x, uint y) {
             atomic_uint z;
             uint result;
             InterlockedAdd(&z, x, &result);
             InterlockedMax(&z, y, &result);
             return result;
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 3);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 5), makeUint(program, 3)]), 5);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo19(int x, int y) {
             atomic_int z;
             int result;
             InterlockedAdd(&z, x, &result);
             InterlockedMax(&z, y, &result);
             return int(z);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 5);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5), makeInt(program, 3)]), 5);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo20(int x, int y) {
             atomic_int z;
             int result;
             InterlockedAdd(&z, x, &result);
             InterlockedMax(&z, y, &result);
             return result;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 3);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5), makeInt(program, 3)]), 5);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo21(uint x, uint y) {
             atomic_uint z;
             uint result;
             InterlockedAdd(&z, x, &result);
             InterlockedMin(&z, y, &result);
             return uint(z);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 3);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 5), makeUint(program, 3)]), 3);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo22(uint x, uint y) {
             atomic_uint z;
             uint result;
             InterlockedAdd(&z, x, &result);
             InterlockedMin(&z, y, &result);
             return result;
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 3);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 5), makeUint(program, 3)]), 5);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo23(int x, int y) {
             atomic_int z;
             int result;
             InterlockedAdd(&z, x, &result);
             InterlockedMin(&z, y, &result);
             return int(z);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 3);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5), makeInt(program, 3)]), 3);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo24(int x, int y) {
             atomic_int z;
             int result;
             InterlockedAdd(&z, x, &result);
             InterlockedMin(&z, y, &result);
             return result;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 3);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5), makeInt(program, 3)]), 5);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo25(uint x, uint y) {
             atomic_uint z;
             uint result;
             InterlockedAdd(&z, x, &result);
             InterlockedOr(&z, y, &result);
             return uint(z);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 7);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo26(uint x, uint y) {
             atomic_uint z;
             uint result;
             InterlockedAdd(&z, x, &result);
             InterlockedOr(&z, y, &result);
             return result;
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 3);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo27(int x, int y) {
             atomic_int z;
             int result;
             InterlockedAdd(&z, x, &result);
             InterlockedOr(&z, y, &result);
             return int(z);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 7);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo28(int x, int y) {
             atomic_int z;
             int result;
             InterlockedAdd(&z, x, &result);
             InterlockedOr(&z, y, &result);
             return result;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 3);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo29(uint x, uint y) {
             atomic_uint z;
             uint result;
             InterlockedAdd(&z, x, &result);
             InterlockedXor(&z, y, &result);
             return uint(z);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 6);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo30(uint x, uint y) {
             atomic_uint z;
             uint result;
             InterlockedAdd(&z, x, &result);
             InterlockedXor(&z, y, &result);
             return result;
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 3);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo31(int x, int y) {
             atomic_int z;
             int result;
             InterlockedAdd(&z, x, &result);
             InterlockedXor(&z, y, &result);
             return int(z);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 6);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo32(int x, int y) {
             atomic_int z;
             int result;
             InterlockedAdd(&z, x, &result);
             InterlockedXor(&z, y, &result);
             return result;
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 3);
-    program = doPrep(`
-        test uint foo(uint x, uint y, uint z) {
+        test uint foo33(uint x, uint y, uint z) {
             atomic_uint w;
             uint result;
             InterlockedAdd(&w, x, &result);
             InterlockedCompareExchange(&w, y, z, &result);
             return uint(w);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 3), makeUint(program, 5)]), 5);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 4), makeUint(program, 5)]), 3);
-    program = doPrep(`
-        test uint foo(uint x, uint y, uint z) {
+        test uint foo34(uint x, uint y, uint z) {
             atomic_uint w;
             uint result;
             InterlockedAdd(&w, x, &result);
             InterlockedCompareExchange(&w, y, z, &result);
             return result;
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 3), makeUint(program, 5)]), 3);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 4), makeUint(program, 5)]), 3);
-    program = doPrep(`
-        test int foo(int x, int y, int z) {
+        test int foo35(int x, int y, int z) {
             atomic_int w;
             int result;
             InterlockedAdd(&w, x, &result);
             InterlockedCompareExchange(&w, y, z, &result);
             return int(w);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 3), makeInt(program, 5)]), 5);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 4), makeInt(program, 5)]), 3);
-    program = doPrep(`
-        test int foo(int x, int y, int z) {
+        test int foo36(int x, int y, int z) {
             atomic_int w;
             int result;
             InterlockedAdd(&w, x, &result);
@@ -6421,322 +6238,286 @@ tests.atomics = function()
             return result;
         }
     `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 3), makeInt(program, 5)]), 3);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 4), makeInt(program, 5)]), 3);
+    checkInt(program, callFunction(program, "foo1", [makeInt(program, 6)]), 0);
+    checkInt(program, callFunction(program, "foo2", [makeInt(program, 6)]), 6);
+    checkInt(program, callFunction(program, "foo3", [makeInt(program, 6)]), 6);
+    checkInt(program, callFunction(program, "foo4", [makeInt(program, 6)]), 12);
+    checkUint(program, callFunction(program, "foo5", [makeUint(program, 6)]), 0);
+    checkUint(program, callFunction(program, "foo6", [makeUint(program, 6)]), 6);
+    checkUint(program, callFunction(program, "foo7", [makeUint(program, 6)]), 6);
+    checkUint(program, callFunction(program, "foo8", [makeUint(program, 6)]), 12);
+    checkUint(program, callFunction(program, "foo9", [makeUint(program, 3), makeUint(program, 5)]), 1);
+    checkUint(program, callFunction(program, "foo10", [makeUint(program, 3), makeUint(program, 5)]), 3);
+    checkInt(program, callFunction(program, "foo11", [makeInt(program, 3), makeInt(program, 5)]), 1);
+    checkInt(program, callFunction(program, "foo12", [makeInt(program, 3), makeInt(program, 5)]), 3);
+    checkUint(program, callFunction(program, "foo13", [makeUint(program, 3), makeUint(program, 5)]), 5);
+    checkUint(program, callFunction(program, "foo14", [makeUint(program, 3), makeUint(program, 5)]), 3);
+    checkInt(program, callFunction(program, "foo15", [makeInt(program, 3), makeInt(program, 5)]), 5);
+    checkInt(program, callFunction(program, "foo16", [makeInt(program, 3), makeInt(program, 5)]), 3);
+    checkUint(program, callFunction(program, "foo17", [makeUint(program, 3), makeUint(program, 5)]), 5);
+    checkUint(program, callFunction(program, "foo17", [makeUint(program, 5), makeUint(program, 3)]), 5);
+    checkUint(program, callFunction(program, "foo18", [makeUint(program, 3), makeUint(program, 5)]), 3);
+    checkUint(program, callFunction(program, "foo18", [makeUint(program, 5), makeUint(program, 3)]), 5);
+    checkInt(program, callFunction(program, "foo19", [makeInt(program, 3), makeInt(program, 5)]), 5);
+    checkInt(program, callFunction(program, "foo19", [makeInt(program, 5), makeInt(program, 3)]), 5);
+    checkInt(program, callFunction(program, "foo20", [makeInt(program, 3), makeInt(program, 5)]), 3);
+    checkInt(program, callFunction(program, "foo20", [makeInt(program, 5), makeInt(program, 3)]), 5);
+    checkUint(program, callFunction(program, "foo21", [makeUint(program, 3), makeUint(program, 5)]), 3);
+    checkUint(program, callFunction(program, "foo21", [makeUint(program, 5), makeUint(program, 3)]), 3);
+    checkUint(program, callFunction(program, "foo22", [makeUint(program, 3), makeUint(program, 5)]), 3);
+    checkUint(program, callFunction(program, "foo22", [makeUint(program, 5), makeUint(program, 3)]), 5);
+    checkInt(program, callFunction(program, "foo23", [makeInt(program, 3), makeInt(program, 5)]), 3);
+    checkInt(program, callFunction(program, "foo23", [makeInt(program, 5), makeInt(program, 3)]), 3);
+    checkInt(program, callFunction(program, "foo24", [makeInt(program, 3), makeInt(program, 5)]), 3);
+    checkInt(program, callFunction(program, "foo24", [makeInt(program, 5), makeInt(program, 3)]), 5);
+    checkUint(program, callFunction(program, "foo25", [makeUint(program, 3), makeUint(program, 5)]), 7);
+    checkUint(program, callFunction(program, "foo26", [makeUint(program, 3), makeUint(program, 5)]), 3);
+    checkInt(program, callFunction(program, "foo27", [makeInt(program, 3), makeInt(program, 5)]), 7);
+    checkInt(program, callFunction(program, "foo28", [makeInt(program, 3), makeInt(program, 5)]), 3);
+    checkUint(program, callFunction(program, "foo29", [makeUint(program, 3), makeUint(program, 5)]), 6);
+    checkUint(program, callFunction(program, "foo30", [makeUint(program, 3), makeUint(program, 5)]), 3);
+    checkInt(program, callFunction(program, "foo31", [makeInt(program, 3), makeInt(program, 5)]), 6);
+    checkInt(program, callFunction(program, "foo32", [makeInt(program, 3), makeInt(program, 5)]), 3);
+    checkUint(program, callFunction(program, "foo33", [makeUint(program, 3), makeUint(program, 3), makeUint(program, 5)]), 5);
+    checkUint(program, callFunction(program, "foo33", [makeUint(program, 3), makeUint(program, 4), makeUint(program, 5)]), 3);
+    checkUint(program, callFunction(program, "foo34", [makeUint(program, 3), makeUint(program, 3), makeUint(program, 5)]), 3);
+    checkUint(program, callFunction(program, "foo34", [makeUint(program, 3), makeUint(program, 4), makeUint(program, 5)]), 3);
+    checkInt(program, callFunction(program, "foo35", [makeInt(program, 3), makeInt(program, 3), makeInt(program, 5)]), 5);
+    checkInt(program, callFunction(program, "foo35", [makeInt(program, 3), makeInt(program, 4), makeInt(program, 5)]), 3);
+    checkInt(program, callFunction(program, "foo36", [makeInt(program, 3), makeInt(program, 3), makeInt(program, 5)]), 3);
+    checkInt(program, callFunction(program, "foo36", [makeInt(program, 3), makeInt(program, 4), makeInt(program, 5)]), 3);
 }
 
 tests.atomicsNull = function()
 {
     let program = doPrep(`
-        test int foo(int z) {
+        test int foo1(int z) {
             atomic_int x;
             InterlockedAdd(&x, z, null);
             return int(x);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 6);
-    program = doPrep(`
-        test int foo(int z) {
+        test int foo2(int z) {
             atomic_int x;
             InterlockedAdd(&x, z, null);
             InterlockedAdd(&x, z, null);
             return int(x);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 12);
-    program = doPrep(`
-        test uint foo(uint z) {
+        test uint foo3(uint z) {
             atomic_uint x;
             InterlockedAdd(&x, z, null);
             return uint(x);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 6)]), 6);
-    program = doPrep(`
-        test uint foo(uint z) {
+        test uint foo4(uint z) {
             atomic_uint x;
             InterlockedAdd(&x, z, null);
             InterlockedAdd(&x, z, null);
             return uint(x);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 6)]), 12);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo5(uint x, uint y) {
             atomic_uint z;
             InterlockedAdd(&z, x, null);
             InterlockedAnd(&z, y, null);
             return uint(z);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 1);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo6(int x, int y) {
             atomic_int z;
             InterlockedAdd(&z, x, null);
             InterlockedAnd(&z, y, null);
             return int(z);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 1);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo7(uint x, uint y) {
             atomic_uint z;
             InterlockedAdd(&z, x, null);
             InterlockedExchange(&z, y, null);
             return uint(z);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 5);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo8(int x, int y) {
             atomic_int z;
             InterlockedAdd(&z, x, null);
             InterlockedExchange(&z, y, null);
             return int(z);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 5);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo9(uint x, uint y) {
             atomic_uint z;
             InterlockedAdd(&z, x, null);
             InterlockedMax(&z, y, null);
             return uint(z);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 5);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 5), makeUint(program, 3)]), 5);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo10(int x, int y) {
             atomic_int z;
             InterlockedAdd(&z, x, null);
             InterlockedMax(&z, y, null);
             return int(z);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 5);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5), makeInt(program, 3)]), 5);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo11(uint x, uint y) {
             atomic_uint z;
             InterlockedAdd(&z, x, null);
             InterlockedMin(&z, y, null);
             return uint(z);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 3);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 5), makeUint(program, 3)]), 3);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo12(int x, int y) {
             atomic_int z;
             InterlockedAdd(&z, x, null);
             InterlockedMin(&z, y, null);
             return int(z);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 3);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 5), makeInt(program, 3)]), 3);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo13(uint x, uint y) {
             atomic_uint z;
             InterlockedAdd(&z, x, null);
             InterlockedOr(&z, y, null);
             return uint(z);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 7);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo14(int x, int y) {
             atomic_int z;
             InterlockedAdd(&z, x, null);
             InterlockedOr(&z, y, null);
             return int(z);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 7);
-    program = doPrep(`
-        test uint foo(uint x, uint y) {
+        test uint foo15(uint x, uint y) {
             atomic_uint z;
             InterlockedAdd(&z, x, null);
             InterlockedXor(&z, y, null);
             return uint(z);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 5)]), 6);
-    program = doPrep(`
-        test int foo(int x, int y) {
+        test int foo16(int x, int y) {
             atomic_int z;
             InterlockedAdd(&z, x, null);
             InterlockedXor(&z, y, null);
             return int(z);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 5)]), 6);
-    program = doPrep(`
-        test uint foo(uint x, uint y, uint z) {
+        test uint foo17(uint x, uint y, uint z) {
             atomic_uint w;
             InterlockedAdd(&w, x, null);
             InterlockedCompareExchange(&w, y, z, null);
             return uint(w);
         }
-    `);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 3), makeUint(program, 5)]), 5);
-    checkUint(program, callFunction(program, "foo", [makeUint(program, 3), makeUint(program, 4), makeUint(program, 5)]), 3);
-    program = doPrep(`
-        test int foo(int x, int y, int z) {
+        test int foo18(int x, int y, int z) {
             atomic_int w;
             InterlockedAdd(&w, x, null);
             InterlockedCompareExchange(&w, y, z, null);
             return int(w);
         }
-    `);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 3), makeInt(program, 5)]), 5);
-    checkInt(program, callFunction(program, "foo", [makeInt(program, 3), makeInt(program, 4), makeInt(program, 5)]), 3);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo19() {
             thread atomic_int* x = null;
             InterlockedAdd(x, 1, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo20() {
             thread atomic_uint* x = null;
             InterlockedAdd(x, 1, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo21() {
             thread atomic_int* x = null;
             InterlockedAnd(x, 1, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo22() {
             thread atomic_uint* x = null;
             InterlockedAnd(x, 1, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo23() {
             thread atomic_int* x = null;
             InterlockedExchange(x, 1, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo24() {
             thread atomic_uint* x = null;
             InterlockedExchange(x, 1, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo25() {
             thread atomic_int* x = null;
             InterlockedMax(x, 1, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo26() {
             thread atomic_uint* x = null;
             InterlockedMax(x, 1, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo27() {
             thread atomic_int* x = null;
             InterlockedMin(x, 1, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo28() {
             thread atomic_uint* x = null;
             InterlockedMin(x, 1, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo29() {
             thread atomic_int* x = null;
             InterlockedOr(x, 1, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo30() {
             thread atomic_uint* x = null;
             InterlockedOr(x, 1, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo31() {
             thread atomic_int* x = null;
             InterlockedXor(x, 1, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo32() {
             thread atomic_uint* x = null;
             InterlockedXor(x, 1, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo33() {
             thread atomic_int* x = null;
             InterlockedCompareExchange(x, 1, 2, null);
             return 1;
         }
-    `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
-
-    program = doPrep(`
-        test int foo() {
+        test int foo34() {
             thread atomic_uint* x = null;
             InterlockedCompareExchange(x, 1, 2, null);
             return 1;
         }
     `);
-    checkTrap(program, () => callFunction(program, "foo", []), checkInt);
+    checkInt(program, callFunction(program, "foo1", [makeInt(program, 6)]), 6);
+    checkInt(program, callFunction(program, "foo2", [makeInt(program, 6)]), 12);
+    checkUint(program, callFunction(program, "foo3", [makeUint(program, 6)]), 6);
+    checkUint(program, callFunction(program, "foo4", [makeUint(program, 6)]), 12);
+    checkUint(program, callFunction(program, "foo5", [makeUint(program, 3), makeUint(program, 5)]), 1);
+    checkInt(program, callFunction(program, "foo6", [makeInt(program, 3), makeInt(program, 5)]), 1);
+    checkUint(program, callFunction(program, "foo7", [makeUint(program, 3), makeUint(program, 5)]), 5);
+    checkInt(program, callFunction(program, "foo8", [makeInt(program, 3), makeInt(program, 5)]), 5);
+    checkUint(program, callFunction(program, "foo9", [makeUint(program, 3), makeUint(program, 5)]), 5);
+    checkUint(program, callFunction(program, "foo9", [makeUint(program, 5), makeUint(program, 3)]), 5);
+    checkInt(program, callFunction(program, "foo10", [makeInt(program, 3), makeInt(program, 5)]), 5);
+    checkInt(program, callFunction(program, "foo10", [makeInt(program, 5), makeInt(program, 3)]), 5);
+    checkUint(program, callFunction(program, "foo11", [makeUint(program, 3), makeUint(program, 5)]), 3);
+    checkUint(program, callFunction(program, "foo11", [makeUint(program, 5), makeUint(program, 3)]), 3);
+    checkInt(program, callFunction(program, "foo12", [makeInt(program, 3), makeInt(program, 5)]), 3);
+    checkInt(program, callFunction(program, "foo12", [makeInt(program, 5), makeInt(program, 3)]), 3);
+    checkUint(program, callFunction(program, "foo13", [makeUint(program, 3), makeUint(program, 5)]), 7);
+    checkInt(program, callFunction(program, "foo14", [makeInt(program, 3), makeInt(program, 5)]), 7);
+    checkUint(program, callFunction(program, "foo15", [makeUint(program, 3), makeUint(program, 5)]), 6);
+    checkInt(program, callFunction(program, "foo16", [makeInt(program, 3), makeInt(program, 5)]), 6);
+    checkUint(program, callFunction(program, "foo17", [makeUint(program, 3), makeUint(program, 3), makeUint(program, 5)]), 5);
+    checkUint(program, callFunction(program, "foo17", [makeUint(program, 3), makeUint(program, 4), makeUint(program, 5)]), 3);
+    checkInt(program, callFunction(program, "foo18", [makeInt(program, 3), makeInt(program, 3), makeInt(program, 5)]), 5);
+    checkInt(program, callFunction(program, "foo18", [makeInt(program, 3), makeInt(program, 4), makeInt(program, 5)]), 3);
+    checkTrap(program, () => callFunction(program, "foo19", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo20", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo21", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo22", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo23", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo24", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo25", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo26", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo27", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo28", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo29", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo30", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo31", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo32", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo33", []), checkInt);
+    checkTrap(program, () => callFunction(program, "foo34", []), checkInt);
 }
 
 tests.selfCasts = function()
@@ -9088,6 +8869,303 @@ tests.textureGather = function() {
     // FIXME: Gather other components
 }
 
+tests.referenceEquality = function() {
+    let program = doPrep(`
+        test bool foo1() {
+            int x;
+            thread int* y = &x;
+            thread int* z = &x;
+            return y == z;
+        }
+        test bool foo2() {
+            int x;
+            thread int* z = &x;
+            return &x == z;
+        }
+        test bool foo3() {
+            int x;
+            thread int* y = &x;
+            return y == &x;
+        }
+        test bool foo4() {
+            int x;
+            return &x == &x;
+        }
+        test bool foo5() {
+            int x;
+            return &x != &x;
+        }
+        test bool foo6() {
+            int x = 7;
+            int y = 7;
+            return &x == &y;
+        }
+        test bool foo7() {
+            return null == null;
+        }
+        test bool foo8() {
+            int x;
+            thread int* y = &x;
+            thread int* z = &x;
+            return &y == &z;
+        }
+        test bool foo9() {
+            int x;
+            thread int* y = &x;
+            return &y == &y;
+        }
+        test bool foo10() {
+            thread int* y;
+            return null == y;
+        }
+        test bool foo11() {
+            thread int* y;
+            return y == null;
+        }
+        test bool foo12() {
+            int x;
+            thread int* y = &x;
+            return null == y;
+        }
+        test bool foo13() {
+            int x;
+            thread int* y = &x;
+            return y == null;
+        }
+        test bool foo14() {
+            int x;
+            thread int[] y = @x;
+            thread int[] z = @x;
+            return y == z;
+        }
+        test bool foo15() {
+            int x;
+            thread int[] z = @x;
+            return @x == z;
+        }
+        test bool foo16() {
+            int x;
+            thread int[] y = @x;
+            return y == @x;
+        }
+        test bool foo17() {
+            int x;
+            return @x == @x;
+        }
+        test bool foo18() {
+            int x;
+            return @x != @x;
+        }
+        test bool foo19() {
+            int x = 7;
+            int y = 7;
+            return @x == @y;
+        }
+        test bool foo21() {
+            int x;
+            thread int[] y = @x;
+            thread int[] z = @x;
+            return @y == @z;
+        }
+        test bool foo22() {
+            int x;
+            thread int[] y = @x;
+            return @y == @y;
+        }
+        test bool foo23() {
+            thread int[] y;
+            return null == y;
+        }
+        test bool foo24() {
+            thread int[] y;
+            return y == null;
+        }
+        test bool foo25() {
+            int x;
+            thread int[] y = @x;
+            return null == y;
+        }
+        test bool foo26() {
+            int x;
+            thread int[] y = @x;
+            return y == null;
+        }
+        test bool foo27() {
+            int[3] x;
+            thread int[] y = @x;
+            thread int[] z = @x;
+            return y == z;
+        }
+        test bool foo28() {
+            int[3] x;
+            thread int[] z = @x;
+            return @x == z;
+        }
+        test bool foo29() {
+            int[3] x;
+            thread int[] y = @x;
+            return y == @x;
+        }
+        test bool foo30() {
+            int[3] x;
+            return @x == @x;
+        }
+        test bool foo31() {
+            int[3] x;
+            return @x != @x;
+        }
+        test bool foo32() {
+            int[3] x;
+            x[0] = 7;
+            x[1] = 8;
+            x[2] = 9;
+            int[3] y;
+            y[0] = 7;
+            y[1] = 8;
+            y[2] = 9;
+            return @x == @y;
+        }
+        test bool foo33() {
+            int[3] x;
+            thread int[] y = @x;
+            thread int[] z = @x;
+            return @y == @z;
+        }
+        test bool foo34() {
+            int[3] x;
+            thread int[] y = @x;
+            return @y == @y;
+        }
+        test bool foo35() {
+            thread int[] y;
+            return null == y;
+        }
+        test bool foo36() {
+            thread int[] y;
+            return y == null;
+        }
+        test bool foo37() {
+            int[3] x;
+            thread int[] y = @x;
+            return null == y;
+        }
+        test bool foo38() {
+            int[3] x;
+            thread int[] y = @x;
+            return y == null;
+        }
+    `);
+    checkBool(program, callFunction(program, "foo1", []), true);
+    checkBool(program, callFunction(program, "foo2", []), true);
+    checkBool(program, callFunction(program, "foo3", []), true);
+    checkBool(program, callFunction(program, "foo4", []), true);
+    checkBool(program, callFunction(program, "foo5", []), false);
+    checkBool(program, callFunction(program, "foo6", []), false);
+    checkBool(program, callFunction(program, "foo7", []), true);
+    checkBool(program, callFunction(program, "foo8", []), false);
+    checkBool(program, callFunction(program, "foo9", []), true);
+    checkBool(program, callFunction(program, "foo10", []), true);
+    checkBool(program, callFunction(program, "foo11", []), true);
+    checkBool(program, callFunction(program, "foo12", []), false);
+    checkBool(program, callFunction(program, "foo13", []), false);
+    checkBool(program, callFunction(program, "foo14", []), true);
+    checkBool(program, callFunction(program, "foo15", []), true);
+    checkBool(program, callFunction(program, "foo16", []), true);
+    checkBool(program, callFunction(program, "foo17", []), true);
+    checkBool(program, callFunction(program, "foo18", []), false);
+    checkBool(program, callFunction(program, "foo19", []), false);
+    checkBool(program, callFunction(program, "foo21", []), false);
+    checkBool(program, callFunction(program, "foo22", []), true);
+    checkBool(program, callFunction(program, "foo23", []), true);
+    checkBool(program, callFunction(program, "foo24", []), true);
+    checkBool(program, callFunction(program, "foo25", []), false);
+    checkBool(program, callFunction(program, "foo26", []), false);
+    checkBool(program, callFunction(program, "foo27", []), true);
+    checkBool(program, callFunction(program, "foo28", []), true);
+    checkBool(program, callFunction(program, "foo29", []), true);
+    checkBool(program, callFunction(program, "foo30", []), true);
+    checkBool(program, callFunction(program, "foo31", []), false);
+    checkBool(program, callFunction(program, "foo32", []), false);
+    checkBool(program, callFunction(program, "foo33", []), false);
+    checkBool(program, callFunction(program, "foo34", []), true);
+    checkBool(program, callFunction(program, "foo35", []), true);
+    checkBool(program, callFunction(program, "foo36", []), true);
+    checkBool(program, callFunction(program, "foo37", []), false);
+    checkBool(program, callFunction(program, "foo38", []), false);
+    checkFail(
+        () => doPrep(`
+            void foo()
+            {
+                int x;
+                float y;
+                bool z = (&x == &y);
+            }
+        `),
+        (e) => e instanceof WTypeError);
+    checkFail(
+        () => doPrep(`
+            void foo()
+            {
+                int x;
+                thread int* y = &x;
+                bool z = (&x == &y);
+            }
+        `),
+        (e) => e instanceof WTypeError);
+    checkFail(
+        () => doPrep(`
+            void foo()
+            {
+                int x;
+                float y;
+                bool z = (@x == @y);
+            }
+        `),
+        (e) => e instanceof WTypeError);
+    checkFail(
+        () => doPrep(`
+            void foo()
+            {
+                int x;
+                thread int[] y = @x;
+                bool z = (@x == @y);
+            }
+        `),
+        (e) => e instanceof WTypeError);
+}
+
+tests.standardLibraryDevicePointers = function() {
+    let program = doPrep(`
+        test float foo1() {
+            float s;
+            float c;
+            sincos(0, &s, &c);
+            return c;
+        }
+        test float foo2() {
+            float s;
+            float c;
+            sincos(0, &s, &c);
+            return s;
+        }
+        test float foo3() {
+            thread float* s = null;
+            float c;
+            sincos(0, s, &c);
+            return c;
+        }
+        test float foo4() {
+            float s;
+            thread float* c = null;
+            sincos(0, &s, c);
+            return s;
+        }
+    `);
+    checkFloat(program, callFunction(program, "foo1", []), 1);
+    checkFloat(program, callFunction(program, "foo2", []), 0);
+    checkFloat(program, callFunction(program, "foo3", []), 1);
+    checkFloat(program, callFunction(program, "foo4", []), 0);
+}
 
 tests.commentParsing = function() {
     let program = doPrep(`
index b355624..e8d8358 100644 (file)
@@ -85,8 +85,7 @@
 <script src="IntLiteral.js"></script>
 <script src="IntLiteralType.js"></script>
 <script src="Intrinsics.js"></script>
-<script src="LateCheckAndLayoutBuffers.js"></script>
-<script src="LateChecker.js"></script>
+<script src="LayoutBuffers.js"></script>
 <script src="Lexer.js"></script>
 <script src="LexerToken.js"></script>
 <script src="LiteralTypeChecker.js"></script>