Tools/ChangeLog

 12018-08-21 Myles C. Maxfield <mmaxfield@apple.com>
 2
 3 [WHLSL] Allow native types to have type arguments (like "vector<float, 4>")
 4 https://bugs.webkit.org/show_bug.cgi?id=188773
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * WebGPUShadingLanguageRI/Intrinsics.js:
 9 (Intrinsics.cast):
 10 (Intrinsics.bitwiseCast):
 11 (Intrinsics.castToHalf):
 12 (Intrinsics.):
 13 (Intrinsics):
 14 * WebGPUShadingLanguageRI/NativeType.js:
 15 (NativeType):
 16 (NativeType.prototype.get typeArguments):
 17 (NativeType.prototype.toString):
 18 (NativeType.create):
 19 * WebGPUShadingLanguageRI/Parse.js:
 20 (isCallExpression):
 21 (parseNative):
 22 * WebGPUShadingLanguageRI/StandardLibrary.js:
 23 (bool.operator):
 24 * WebGPUShadingLanguageRI/VectorType.js:
 25 (VectorType):
 26 (VectorType.prototype.get elementType):
 27 (VectorType.prototype.get numElementsValue):
 28
1292018-08-21 Alex Christensen <achristensen@webkit.org>
230
331 Translate WebKit.LimitTitleSize API test into ObjC

Tools/WebGPUShadingLanguageRI/All.js

@@load("CheckLoops.js");
6060load("CheckRecursion.js");
6161load("CheckRecursiveTypes.js");
6262load("CheckReturns.js");
 63load("CheckTypesWithArguments.js");
6364load("CheckUnreachableCode.js");
6465load("CheckWrapped.js");
6566load("Checker.js");

@@load("PtrType.js");
133134load("ReadModifyWriteExpression.js");
134135load("RecursionChecker.js");
135136load("RecursiveTypeChecker.js");
136 load("RemoveTypeArguments.js");
137137load("ResolveNames.js");
138138load("ResolveOverloadImpl.js");
139139load("ResolveProperties.js");

@@load("TrapStatement.js");
157157load("TypeDef.js");
158158load("TypeDefResolver.js");
159159load("TypeRef.js");
 160load("TypeOverloadResolutionFailure.js");
160161load("TypedValue.js");
161162load("UintLiteral.js");
162163load("UintLiteralType.js");

@@load("WSyntaxError.js");
170171load("WTrapError.js");
171172load("WTypeError.js");
172173load("WhileLoop.js");
173 load("WrapChecker.js");
174174\ No newline at end of file
 175load("WrapChecker.js");

Tools/WebGPUShadingLanguageRI/CallExpression.js

@@class CallExpression extends Expression {
6666 overload.func = func;
6767 }
6868
69 
7069 if (!overload.func) {
7170 failures.push(...overload.failures);
7271 let message = "Did not find function named " + this.name + " for call with ";

@@class CallExpression extends Expression {
117116
118117 const elementType = this.argumentTypes[0].elementType;
119118 this.resultType = this._returnType = TypeRef.wrap(new PtrType(this.origin, addressSpace, TypeRef.wrap(elementType)))
 119 if (this.returnType.name == "vector" && this.returnType.typeArguments.length == 0)
 120 throw new Error("asdf");
120121
121122 let arrayRefAccessor = new OperatorAnderIndexer(this.returnType.toString(), addressSpace);
122123 const func = new NativeFunc(this.origin, "operator&[]", this.resultType, [

@@class CallExpression extends Expression {
132133 _resolveWithOperatorLength(program)
133134 {
134135 this.resultType = this._returnType = TypeRef.wrap(program.types.get("uint"));
 136 if (this.returnType.name == "vector" && this.returnType.typeArguments.length == 0)
 137 throw new Error("asdf");
135138
136139 if (this.argumentTypes[0].isArray) {
137140 const arrayType = this.argumentTypes[0];

@@class CallExpression extends Expression {
166169
167170 becomeCast(returnType)
168171 {
169  this._returnType = new TypeRef(this.origin, this.name);
 172 this._returnType = new TypeRef(this.origin, this.name, returnType.typeArguments);
 173 if (this.returnType.name == "vector" && this.returnType.typeArguments.length == 0)
 174 throw new Error("asdf");
170175 this._returnType.type = returnType;
171176 this._name = "operator cast";
172177 this._isCast = true;

@@class CallExpression extends Expression {
175180 setCastData(returnType)
176181 {
177182 this._returnType = returnType;
 183 if (this.returnType.name == "vector" && this.returnType.typeArguments.length == 0)
 184 throw new Error("asdf");
178185 this._isCast = true;
179186 }
180187

Tools/WebGPUShadingLanguageRI/Checker.js

@@class Checker extends Visitor {
4141 statement.visit(this);
4242 }
4343
44  for (let type of node.types.values())
45  doStatement(type);
 44 for (let type of node.types.values()) {
 45 if (type instanceof Array) {
 46 for (let constituentType of type)
 47 doStatement(constituentType);
 48 } else
 49 doStatement(type);
 50 }
4651 for (let funcs of node.functions.values()) {
4752 for (let func of funcs) {
4853 this.visitFunc(func);

@@class Checker extends Visitor {
245250
246251 visitTypeRef(node)
247252 {
248  if (!node.type)
 253 if (!node.type && !node.possibleOverloads)
249254 throw new Error("Type reference without a type in checker: " + node + " at " + node.origin);
250  if (!(node.type instanceof StructType))
 255 if (!node.type)
 256 node.resolve(node.possibleOverloads, this._program);
 257 if (!node.type || !node.type.visit)
 258 throw new Error("Type reference without a type after possibly resolving in checker: " + node + " at " + node.origin);
 259 if (!(node.type instanceof StructType)) // FIXME: Why don't we recurse on StructTypes?
251260 node.type.visit(this);
252261 }
253262

Tools/WebGPUShadingLanguageRI/InferTypesForCall.js

@@function inferTypesForCall(func, argumentTypes, returnType)
3636 if (!argumentTypes[i].unify(unificationContext, func.parameters[i].type))
3737 return {failure: new OverloadResolutionFailure(func, "Argument #" + (i + 1) + " " + (func.parameters[i].name ? "for parameter " + func.parameters[i].name + " " : "") + "does not match (passed " + argumentTypes[i] + ", require " + func.parameters[i].type + ")")};
3838 }
39  if (returnType && !returnType.unify(unificationContext, func.returnType)) {
40  if (func.returnType.toString() == "vector") {
41  returnType.unify(unificationContext, func.returnType)
42  }
 39 if (returnType && !returnType.unify(unificationContext, func.returnType))
4340 return {failure: new OverloadResolutionFailure(func, "Return type " + func.returnType + " does not match " + returnType)};
44  }
4541 let verificationResult = unificationContext.verify();
4642 if (!verificationResult.result)
4743 return {failure: new OverloadResolutionFailure(func, verificationResult.reason)};

@@function inferTypesForCall(func, argumentTypes, returnType)
4945 return {func, unificationContext};
5046}
5147
 48function inferTypesForTypeArguments(type, typeArguments)
 49{
 50 if (typeArguments.length != type.typeArguments.length)
 51 return {failure: new TypeOverloadResolutionFailure(type, "Wrong number of arguments (passed " + typeArguments.length + ", require " + type.typeArguments.length + ")")};
 52 let unificationContext = new UnificationContext();
 53
 54 for (let i = 0; i < typeArguments.length; ++i) {
 55 if (!typeArguments[i])
 56 throw new Error("Null type argument at i = " + i);
 57 if (!typeArguments[i].unify(unificationContext, type.typeArguments[i]))
 58 return {failure: new TypeOverloadResolutionFailure(type, "Argument #" + (i + 1) + " " + (type.typeArguments[i].name ? "for parameter " + type.typeArguments[i].name + " " : "") + "does not match (passed " + typeArguments[i] + ", require " + type.typeArguments[i].type + ")")};
 59 }
 60 let verificationResult = unificationContext.verify();
 61 if (!verificationResult.result)
 62 return {failure: new TypeOverloadResolutionFailure(type, verificationResult.reason)};
 63
 64 return {type, unificationContext};
 65}

Tools/WebGPUShadingLanguageRI/Intrinsics.js

@@class Intrinsics {
3333 // to catch the intrinsics must be based on the type names that StandardLibrary.js uses.
3434 // For example, if a native function is declared using "int" rather than "int", then we must
3535 // use "int" here, since we don't yet know that they are the same type.
36 
37  this._map.set(
38  "native typedef void",
39  type => {
40  this.void = type;
41  type.size = 0;
42  type.populateDefaultValue = () => { };
43  });
44 
 36
4537 function isBitwiseEquivalent(left, right)
4638 {
4739 let doubleArray = new Float64Array(1);

@@class Intrinsics {
5648 return true;
5749 }
5850
 51 function cast(typedArrayConstructor, number)
 52 {
 53 var array = new typedArrayConstructor(1);
 54 array[0] = number;
 55 return array[0];
 56 }
 57
 58 function bitwiseCast(typedArrayConstructor1, typedArrayConstructor2, value)
 59 {
 60 let typedArray1 = new typedArrayConstructor1(1);
 61 let typedArray2 = new typedArrayConstructor2(typedArray1.buffer);
 62 typedArray1[0] = value;
 63 return typedArray2[0];
 64 }
 65
 66 function castToHalf(number)
 67 {
 68 // FIXME: Make this math obey IEEE 754.
 69 if (Number.isNaN(number))
 70 return number
 71 if (number > 65504)
 72 return Number.POSITIVE_INFINITY;
 73 if (number < -65504)
 74 return Number.NEGATIVE_INFINITY;
 75 if (number > 0 && number < Math.pow(2, -24))
 76 return 0;
 77 if (number < 0 && number > -Math.pow(2, -24))
 78 return -0;
 79 let doubleArray = new Float64Array(1);
 80 let uintArray = new Uint8Array(doubleArray.buffer);
 81 doubleArray[0] = number;
 82 let sign = uintArray[7] & 0x80;
 83 let exponent = ((uintArray[7] & 0x7f) << 4) | ((uintArray[6] & 0xf0) >>> 4);
 84 let significand = ((uintArray[6] & 0x0f) << 6) | ((uintArray[5] & 0xfc) >>> 2);
 85
 86 if ((exponent - 1023) < -14) {
 87 exponent = 0;
 88 significand = (Math.abs(number) * Math.pow(2, 24)) >>> 0;
 89 let value = Math.pow(2, -14) * significand / 1024;
 90 if (sign != 0)
 91 value *= -1;
 92 return value;
 93 }
 94
 95 doubleArray[0] = 0;
 96
 97 uintArray[7] |= sign;
 98 uintArray[7] |= (exponent >>> 4);
 99 uintArray[6] |= ((exponent << 4) & 0xf0);
 100 uintArray[6] |= (significand >>> 6);
 101 uintArray[5] |= ((significand << 2) & 0xfc);
 102
 103 return doubleArray[0];
 104 }
 105
59106 this._map.set(
60  "native typedef int",
 107 "native typedef void",
61108 type => {
62  this.int = type;
63  type.isPrimitive = true;
64  type.isInt = true;
65  type.isNumber = true;
66  type.isSigned = true;
67  type.canRepresent = value => isBitwiseEquivalent(value | 0, value);
68  type.size = 1;
69  type.defaultValue = 0;
70  type.createLiteral = (origin, value) => IntLiteral.withType(origin, value | 0, type);
71  type.successorValue = value => (value + 1) | 0;
72  type.valuesEqual = (a, b) => a === b;
73  type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
74  type.formatValueFromIntLiteral = value => value | 0;
75  type.formatValueFromUintLiteral = value => value | 0;
76  type.allValues = function*() {
77  for (let i = 0; i <= 0xffffffff; ++i) {
78  let value = i | 0;
79  yield {value: value, name: value};
80  }
81  };
 109 this.void = type;
 110 type.size = 0;
 111 type.populateDefaultValue = () => { };
82112 });
83113
84114 this._map.set(
85  "native typedef uint",
 115 "native typedef bool",
86116 type => {
87  this.uint = type;
 117 this.bool = type;
88118 type.isPrimitive = true;
89  type.isInt = true;
90  type.isNumber = true;
91  type.isSigned = false;
92  type.canRepresent = value => isBitwiseEquivalent(value >>> 0, value);
93119 type.size = 1;
94  type.defaultValue = 0;
95  type.createLiteral = (origin, value) => IntLiteral.withType(origin, value >>> 0, type);
96  type.successorValue = value => (value + 1) >>> 0;
97  type.valuesEqual = (a, b) => a === b;
98  type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
99  type.formatValueFromIntLiteral = value => value >>> 0;
100  type.formatValueFromUintLiteral = value => value >>> 0;
101  type.allValues = function*() {
102  for (let i = 0; i <= 0xffffffff; ++i)
103  yield {value: i, name: i};
104  };
 120 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, false);
105121 });
106122
107123 this._map.set(
108124 "native typedef uchar",
109125 type => {
110126 this.uchar = type;
 127 type.isPrimitive = true;
111128 type.isInt = true;
112129 type.isNumber = true;
113130 type.isSigned = false;

@@class Intrinsics {
126143 };
127144 });
128145
 146
 147 this._map.set(
 148 "native typedef ushort",
 149 type => {
 150 this.ushort = type;
 151 type.isPrimitive = true;
 152 type.isInt = true;
 153 type.isNumber = true;
 154 type.isSigned = false;
 155 type.canRepresent = value => isBitwiseEquivalent(value & 0xffff, value);
 156 type.size = 1;
 157 type.defaultValue = 0;
 158 type.createLiteral = (origin, value) => IntLiteral.withType(origin, value & 0xffff, type);
 159 type.successorValue = value => (value + 1) & 0xffff;
 160 type.valuesEqual = (a, b) => a === b;
 161 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
 162 type.formatValueFromIntLiteral = value => value & 0xffff;
 163 type.formatValueFromUintLiteral = value => value & 0xffff;
 164 type.allValues = function*() {
 165 for (let i = 0; i <= 0xffff; ++i)
 166 yield {value: i, name: i};
 167 };
 168 });
 169
129170 this._map.set(
130  "native typedef float",
131  type => {
132  this.float = type;
133  type.isPrimitive = true;
134  type.size = 1;
135  type.isFloating = true;
136  type.isNumber = true;
137  type.canRepresent = value => isBitwiseEquivalent(Math.fround(value), value);
138  type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
139  type.formatValueFromIntLiteral = value => value;
140  type.formatValueFromUintLiteral = value => value;
141  type.formatValueFromFloatLiteral = value => Math.fround(value);
142  });
 171 "native typedef uint",
 172 type => {
 173 this.uint = type;
 174 type.isPrimitive = true;
 175 type.isInt = true;
 176 type.isNumber = true;
 177 type.isSigned = false;
 178 type.canRepresent = value => isBitwiseEquivalent(value >>> 0, value);
 179 type.size = 1;
 180 type.defaultValue = 0;
 181 type.createLiteral = (origin, value) => IntLiteral.withType(origin, value >>> 0, type);
 182 type.successorValue = value => (value + 1) >>> 0;
 183 type.valuesEqual = (a, b) => a === b;
 184 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
 185 type.formatValueFromIntLiteral = value => value >>> 0;
 186 type.formatValueFromUintLiteral = value => value >>> 0;
 187 type.allValues = function*() {
 188 for (let i = 0; i <= 0xffffffff; ++i)
 189 yield {value: i, name: i};
 190 };
 191 });
143192
144193 this._map.set(
145  "native typedef bool",
146  type => {
147  this.bool = type;
148  type.isPrimitive = true;
149  type.size = 1;
150  type.populateDefaultValue = (buffer, offset) => buffer.set(offset, false);
151  });
 194 "native typedef char",
 195 type => {
 196 this.char = type;
 197 type.isPrimitive = true;
 198 type.isInt = true;
 199 type.isNumber = true;
 200 type.isSigned = true;
 201 type.canRepresent = value => isBitwiseEquivalent(cast(Int8Array, value), value);
 202 type.size = 1;
 203 type.defaultValue = 0;
 204 type.createLiteral = (origin, value) => IntLiteral.withType(origin, cast(Int8Array, value), type);
 205 type.successorValue = value => cast(Int8Array, value + 1);
 206 type.valuesEqual = (a, b) => a === b;
 207 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
 208 type.formatValueFromIntLiteral = value => cast(Int8Array, value);
 209 type.formatValueFromUintLiteral = value => cast(Int8Array, value);
 210 type.allValues = function*() {
 211 for (let i = 0; i <= 0xff; ++i) {
 212 let value = cast(Int8Array, i);
 213 yield {value: value, name: value};
 214 }
 215 };
 216 });
 217
 218 this._map.set(
 219 "native typedef short",
 220 type => {
 221 this.short = type;
 222 type.isPrimitive = true;
 223 type.isInt = true;
 224 type.isNumber = true;
 225 type.isSigned = true;
 226 type.canRepresent = value => isBitwiseEquivalent(cast(Int16Array, value), value);
 227 type.size = 1;
 228 type.defaultValue = 0;
 229 type.createLiteral = (origin, value) => IntLiteral.withType(origin, cast(Int16Array, value), type);
 230 type.successorValue = value => cast(Int16Array, value + 1);
 231 type.valuesEqual = (a, b) => a === b;
 232 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
 233 type.formatValueFromIntLiteral = value => cast(Int16Array, value);
 234 type.formatValueFromUintLiteral = value => cast(Int16Array, value);
 235 type.allValues = function*() {
 236 for (let i = 0; i <= 0xffff; ++i) {
 237 let value = cast(Int16Array, i);
 238 yield {value: value, name: value};
 239 }
 240 };
 241 });
 242
 243 this._map.set(
 244 "native typedef int",
 245 type => {
 246 this.int = type;
 247 type.isPrimitive = true;
 248 type.isInt = true;
 249 type.isNumber = true;
 250 type.isSigned = true;
 251 type.canRepresent = value => isBitwiseEquivalent(value | 0, value);
 252 type.size = 1;
 253 type.defaultValue = 0;
 254 type.createLiteral = (origin, value) => IntLiteral.withType(origin, value | 0, type);
 255 type.successorValue = value => (value + 1) | 0;
 256 type.valuesEqual = (a, b) => a === b;
 257 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
 258 type.formatValueFromIntLiteral = value => value | 0;
 259 type.formatValueFromUintLiteral = value => value | 0;
 260 type.allValues = function*() {
 261 for (let i = 0; i <= 0xffffffff; ++i) {
 262 let value = i | 0;
 263 yield {value: value, name: value};
 264 }
 265 };
 266 });
 267
 268 this._map.set(
 269 "native typedef half",
 270 type => {
 271 this.half = type;
 272 type.isPrimitive = true;
 273 type.size = 1;
 274 type.isFloating = true;
 275 type.isNumber = true;
 276 type.canRepresent = value => isBitwiseEquivalent(castToHalf(value), value);
 277 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
 278 type.formatValueFromIntLiteral = value => value;
 279 type.formatValueFromUintLiteral = value => value;
 280 type.formatValueFromFloatLiteral = value => castToHalf(value);
 281 });
 282
 283 this._map.set(
 284 "native typedef float",
 285 type => {
 286 this.float = type;
 287 type.isPrimitive = true;
 288 type.size = 1;
 289 type.isFloating = true;
 290 type.isNumber = true;
 291 type.canRepresent = value => isBitwiseEquivalent(Math.fround(value), value);
 292 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
 293 type.formatValueFromIntLiteral = value => value;
 294 type.formatValueFromUintLiteral = value => value;
 295 type.formatValueFromFloatLiteral = value => Math.fround(value);
 296 });
 297
 298 this._map.set(
 299 "native typedef atomic_int",
 300 type => {
 301 this.atomic_int = type;
 302 // FIXME: Figure out what to put here.
 303 });
 304
 305 this._map.set(
 306 "native typedef atomic_uint",
 307 type => {
 308 this.atomic_uint = type;
 309 // FIXME: Figure out what to put here.
 310 });
152311
153312 for (let vectorType of VectorElementTypes) {
154  for (let vectorSize of VectorElementSizes)
155  this._map.set(`native typedef vector<${vectorType}, ${vectorSize}>`, type => {});
 313 for (let vectorSize of VectorElementSizes) {
 314 this._map.set(`native typedef vector<${vectorType}, ${vectorSize}>`, type => {
 315 this[`vector<${vectorType}, ${vectorSize}>`] = type;
 316 // FIXME: Figure out what to put here.
 317 });
 318 }
156319 }
157 
 320
158321 this._map.set(
159322 "native operator int(uint)",
160323 func => {
161324 func.implementation = ([value]) => EPtr.box(value.loadValue() | 0);
162325 });
163 
 326
164327 this._map.set(
165328 "native operator int(uchar)",
166329 func => {
167330 func.implementation = ([value]) => EPtr.box(value.loadValue() | 0);
168331 });
169 
 332
170333 this._map.set(
171334 "native operator int(float)",
172335 func => {
173336 func.implementation = ([value]) => EPtr.box(value.loadValue() | 0);
174337 });
175 
 338
176339 this._map.set(
177340 "native operator uint(int)",
178341 func => {
179342 func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
180343 });
181 
 344
182345 this._map.set(
183346 "native operator uint(uchar)",
184347 func => {
185348 func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
186349 });
187 
 350
188351 this._map.set(
189352 "native operator uint(float)",
190353 func => {
191354 func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
192355 });
193 
 356
194357 this._map.set(
195358 "native operator uchar(int)",
196359 func => {
197360 func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff);
198361 });
199 
 362
200363 this._map.set(
201364 "native operator uchar(uint)",
202365 func => {
203366 func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff);
204367 });
205 
 368
206369 this._map.set(
207370 "native operator uchar(float)",
208371 func => {
209372 func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff);
210373 });
211 
 374
212375 this._map.set(
213376 "native operator float(int)",
214377 func => {
215378 func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
216379 });
217 
 380
218381 this._map.set(
219382 "native operator float(uint)",
220383 func => {
221384 func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
222385 });
223 
 386
224387 this._map.set(
225388 "native operator float(uchar)",
226389 func => {
227390 func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
228391 });
229 
 392
230393 this._map.set(
231394 "native int operator+(int,int)",
232395 func => {
233396 func.implementation = ([left, right]) =>
234397 EPtr.box((left.loadValue() + right.loadValue()) | 0);
235398 });
236 
 399
237400 this._map.set(
238401 "native uint operator+(uint,uint)",
239402 func => {
240403 func.implementation = ([left, right]) =>
241404 EPtr.box((left.loadValue() + right.loadValue()) >>> 0);
242405 });
243 
 406
244407 this._map.set(
245408 "native float operator+(float,float)",
246409 func => {
247410 func.implementation = ([left, right]) =>
248411 EPtr.box(Math.fround(left.loadValue() + right.loadValue()));
249412 });
250 
 413
251414 this._map.set(
252415 "native int operator-(int,int)",
253416 func => {
254417 func.implementation = ([left, right]) =>
255418 EPtr.box((left.loadValue() - right.loadValue()) | 0);
256419 });
257 
 420
258421 this._map.set(
259422 "native uint operator-(uint,uint)",
260423 func => {
261424 func.implementation = ([left, right]) =>
262425 EPtr.box((left.loadValue() - right.loadValue()) >>> 0);
263426 });
264 
 427
265428 this._map.set(
266429 "native float operator-(float,float)",
267430 func => {
268431 func.implementation = ([left, right]) =>
269432 EPtr.box(Math.fround(left.loadValue() - right.loadValue()));
270433 });
271 
 434
272435 this._map.set(
273436 "native int operator*(int,int)",
274437 func => {

@@class Intrinsics {
276439 return EPtr.box((left.loadValue() * right.loadValue()) | 0);
277440 };
278441 });
279 
 442
280443 this._map.set(
281444 "native uint operator*(uint,uint)",
282445 func => {
283446 func.implementation = ([left, right]) =>
284447 EPtr.box((left.loadValue() * right.loadValue()) >>> 0);
285448 });
286 
 449
287450 this._map.set(
288451 "native float operator*(float,float)",
289452 func => {
290453 func.implementation = ([left, right]) =>
291454 EPtr.box(Math.fround(left.loadValue() * right.loadValue()));
292455 });
293 
 456
294457 this._map.set(
295458 "native int operator/(int,int)",
296459 func => {
297460 func.implementation = ([left, right]) =>
298461 EPtr.box((left.loadValue() / right.loadValue()) | 0);
299462 });
300 
 463
301464 this._map.set(
302465 "native uint operator/(uint,uint)",
303466 func => {
304467 func.implementation = ([left, right]) =>
305468 EPtr.box((left.loadValue() / right.loadValue()) >>> 0);
306469 });
307 
 470
308471 this._map.set(
309472 "native int operator&(int,int)",
310473 func => {
311474 func.implementation = ([left, right]) =>
312475 EPtr.box(left.loadValue() & right.loadValue());
313476 });
314 
 477
315478 this._map.set(
316479 "native uint operator&(uint,uint)",
317480 func => {
318481 func.implementation = ([left, right]) =>
319482 EPtr.box((left.loadValue() & right.loadValue()) >>> 0);
320483 });
321 
 484
322485 this._map.set(
323486 "native int operator|(int,int)",
324487 func => {
325488 func.implementation = ([left, right]) =>
326489 EPtr.box(left.loadValue() | right.loadValue());
327490 });
328 
 491
329492 this._map.set(
330493 "native uint operator|(uint,uint)",
331494 func => {
332495 func.implementation = ([left, right]) =>
333496 EPtr.box((left.loadValue() | right.loadValue()) >>> 0);
334497 });
335 
 498
336499 this._map.set(
337500 "native int operator^(int,int)",
338501 func => {
339502 func.implementation = ([left, right]) =>
340503 EPtr.box(left.loadValue() ^ right.loadValue());
341504 });
342 
 505
343506 this._map.set(
344507 "native uint operator^(uint,uint)",
345508 func => {
346509 func.implementation = ([left, right]) =>
347510 EPtr.box((left.loadValue() ^ right.loadValue()) >>> 0);
348511 });
349 
 512
350513 this._map.set(
351514 "native int operator<<(int,uint)",
352515 func => {
353516 func.implementation = ([left, right]) =>
354517 EPtr.box(left.loadValue() << right.loadValue());
355518 });
356 
 519
357520 this._map.set(
358521 "native uint operator<<(uint,uint)",
359522 func => {
360523 func.implementation = ([left, right]) =>
361524 EPtr.box((left.loadValue() << right.loadValue()) >>> 0);
362525 });
363 
 526
364527 this._map.set(
365528 "native int operator>>(int,uint)",
366529 func => {
367530 func.implementation = ([left, right]) =>
368531 EPtr.box(left.loadValue() >> right.loadValue());
369532 });
370 
 533
371534 this._map.set(
372535 "native uint operator>>(uint,uint)",
373536 func => {
374537 func.implementation = ([left, right]) =>
375538 EPtr.box(left.loadValue() >>> right.loadValue());
376539 });
377 
 540
378541 this._map.set(
379542 "native int operator~(int)",
380543 func => {
381544 func.implementation = ([value]) => EPtr.box(~value.loadValue());
382545 });
383 
 546
384547 this._map.set(
385548 "native uint operator~(uint)",
386549 func => {
387550 func.implementation = ([value]) => EPtr.box((~value.loadValue()) >>> 0);
388551 });
389 
 552
390553 this._map.set(
391554 "native float operator/(float,float)",
392555 func => {
393556 func.implementation = ([left, right]) =>
394557 EPtr.box(Math.fround(left.loadValue() / right.loadValue()));
395558 });
396 
 559
397560 this._map.set(
398561 "native bool operator==(int,int)",
399562 func => {
400563 func.implementation = ([left, right]) =>
401564 EPtr.box(left.loadValue() == right.loadValue());
402565 });
403 
 566
404567 this._map.set(
405568 "native bool operator==(uint,uint)",
406569 func => {
407570 func.implementation = ([left, right]) =>
408571 EPtr.box(left.loadValue() == right.loadValue());
409572 });
410 
 573
411574 this._map.set(
412575 "native bool operator==(bool,bool)",
413576 func => {
414577 func.implementation = ([left, right]) =>
415578 EPtr.box(left.loadValue() == right.loadValue());
416579 });
417 
 580
418581 this._map.set(
419582 "native bool operator==(float,float)",
420583 func => {
421584 func.implementation = ([left, right]) =>
422585 EPtr.box(left.loadValue() == right.loadValue());
423586 });
424 
 587
425588 this._map.set(
426589 "native bool operator<(int,int)",
427590 func => {
428591 func.implementation = ([left, right]) =>
429592 EPtr.box(left.loadValue() < right.loadValue());
430593 });
431 
 594
432595 this._map.set(
433596 "native bool operator<(uint,uint)",
434597 func => {
435598 func.implementation = ([left, right]) =>
436599 EPtr.box(left.loadValue() < right.loadValue());
437600 });
438 
 601
439602 this._map.set(
440603 "native bool operator<(float,float)",
441604 func => {
442605 func.implementation = ([left, right]) =>
443606 EPtr.box(left.loadValue() < right.loadValue());
444607 });
445 
 608
446609 this._map.set(
447610 "native bool operator<=(int,int)",
448611 func => {
449612 func.implementation = ([left, right]) =>
450613 EPtr.box(left.loadValue() <= right.loadValue());
451614 });
452 
 615
453616 this._map.set(
454617 "native bool operator<=(uint,uint)",
455618 func => {
456619 func.implementation = ([left, right]) =>
457620 EPtr.box(left.loadValue() <= right.loadValue());
458621 });
459 
 622
460623 this._map.set(
461624 "native bool operator<=(float,float)",
462625 func => {
463626 func.implementation = ([left, right]) =>
464627 EPtr.box(left.loadValue() <= right.loadValue());
465628 });
466 
 629
467630 this._map.set(
468631 "native bool operator>(int,int)",
469632 func => {
470633 func.implementation = ([left, right]) =>
471634 EPtr.box(left.loadValue() > right.loadValue());
472635 });
473 
 636
474637 this._map.set(
475638 "native bool operator>(uint,uint)",
476639 func => {
477640 func.implementation = ([left, right]) =>
478641 EPtr.box(left.loadValue() > right.loadValue());
479642 });
480 
 643
481644 this._map.set(
482645 "native bool operator>(float,float)",
483646 func => {
484647 func.implementation = ([left, right]) =>
485648 EPtr.box(left.loadValue() > right.loadValue());
486649 });
487 
 650
488651 this._map.set(
489652 "native bool operator>=(int,int)",
490653 func => {
491654 func.implementation = ([left, right]) =>
492655 EPtr.box(left.loadValue() >= right.loadValue());
493656 });
494 
 657
495658 this._map.set(
496659 "native bool operator>=(uint,uint)",
497660 func => {
498661 func.implementation = ([left, right]) =>
499662 EPtr.box(left.loadValue() >= right.loadValue());
500663 });
501 
 664
502665 this._map.set(
503666 "native bool operator>=(float,float)",
504667 func => {

@@class Intrinsics {
538701 for (let setter of BuiltinVectorSetter.functions())
539702 this._map.set(setter.toString(), func => setter.instantiateImplementation(func));
540703 }
541 
 704
542705 add(thing)
543706 {
544707 let intrinsic = this._map.get(thing.toString());

Tools/WebGPUShadingLanguageRI/NameContext.js

@@class NameContext {
6969 return;
7070 }
7171
 72 if (thing.kind == Type) {
 73 this._set.add(thing);
 74 if (thing.name == "vector") {
 75 let array = this._map.get(thing.name);
 76 if (!array) {
 77 array = [];
 78 array.kind = Type;
 79 this._map.set(thing.name, array);
 80 }
 81 if (array.kind != Type)
 82 throw new WTypeError(thing.origin.originString, "Cannot reuse type name for function: " + thing.name);
 83 array.push(thing);
 84 return;
 85 } else {
 86 if (this._map.has(thing.name))
 87 throw new WTypeError(thing.origin.originString, "Duplicate name: " + thing.name);
 88 this._map.set(thing.name, thing);
 89 }
 90 return;
 91 }
 92
7293 if (this._map.has(thing.name))
7394 throw new WTypeError(thing.origin.originString, "Duplicate name: " + thing.name);
7495
7596 this._set.add(thing);
7697 this._map.set(thing.name, thing);
 98
7799 }
78100
79101 get(kind, name)

@@class NameContext {
102124 for (let func of thing)
103125 yield func;
104126 return;
 127 } else if (thing.kind === Type && (thing instanceof Array)) {
 128 for (let type of thing)
 129 yield type;
 130 return;
105131 }
106132 yield thing;
107133 }

@@class NameContext {
163189 {
164190 for (let value of this._map.values()) {
165191 if (value instanceof Array) {
166  for (let func of value)
167  yield func;
 192 for (let thing of value)
 193 yield thing;
168194 continue;
169195 }
170196 yield value;

Tools/WebGPUShadingLanguageRI/NameResolver.js

@@class NameResolver extends Visitor {
120120
121121 visitTypeRef(node)
122122 {
 123 super.visitTypeRef(node);
123124 let type = node.type;
124125 if (!type) {
125126 type = this._nameContext.get(Type, node.name);
126127 if (!type)
127128 throw new WTypeError(node.origin.originString, "Could not find type named " + node.name);
128  node.type = type;
 129 if (type instanceof Array)
 130 node.possibleOverloads = type;
 131 else
 132 node.type = type;
129133 }
130134 }
131135

@@class NameResolver extends Visitor {
210214
211215 super.visitCallExpression(node);
212216 }
213 
214  visitVectorType(node)
215  {
216  node.elementType.visit(this);
217  }
218217}

Tools/WebGPUShadingLanguageRI/NativeType.js

2525"use strict";
2626
2727class NativeType extends Type {
28  constructor(origin, name)
 28 constructor(origin, name, typeArguments)
2929 {
 30 if (!(typeArguments instanceof Array))
 31 throw new Error("type parameters not array: " + typeArguments);
3032 super();
3133 this._origin = origin;
3234 this._name = name;
 35 this._typeArguments = typeArguments;
3336 this._isNumber = false;
3437 this._isInt = false;
3538 this._isFloating = false;

@@class NativeType extends Type {
3841
3942 get origin() { return this._origin; }
4043 get name() { return this._name; }
 44 get typeArguments() { return this._typeArguments; }
4145 get isNative() { return true; }
4246
4347 // We let Intrinsics.js set these as it likes.

@@class NativeType extends Type {
5256
5357 toString()
5458 {
55  return `native typedef ${this.name}`;
 59 let result = `native typedef ${this.name}`;
 60 if (this.typeArguments.length)
 61 result += "<" + this.typeArguments.join(",") + ">";
 62 return result;
5663 }
5764
5865 static create(origin, name, typeArguments)
5966 {
60  // FIXME: For native types like Texture1D this should resolve the type to something concrete by changing the type name.
61  if (typeArguments.length)
62  throw new WTypeError(origin.originString, `${name}<${typeArguments.join(",")}>: Support for native types with type arguments is currently unimplemented.`);
 67 if (name == "vector")
 68 return new VectorType(origin, name, typeArguments);
6369
64  if (allVectorTypeNames().indexOf(name) > -1)
65  return new VectorType(origin, name);
66 
67  return new NativeType(origin, name);
 70 return new NativeType(origin, name, typeArguments);
6871 }
6972}
7073

Tools/WebGPUShadingLanguageRI/Parse.js

@@function parse(program, origin, originKind, lineNumberOffset, text)
327327 function isCallExpression()
328328 {
329329 return lexer.testScope(() => {
330  consumeKind("identifier");
331  parseTypeArguments();
332  consume("(");
333  });
 330 consumeKind("identifier");
 331 consume("(");
 332 }) || lexer.testScope(() => {
 333 parseType();
 334 consume("(");
 335 });
334336 }
335337
336338 function emitIncrement(token, old, extraArg)

Tools/WebGPUShadingLanguageRI/Prepare.js

@@let prepare = (() => {
4040 }
4141
4242 foldConstexprs(program);
43  removeTypeArguments(program);
4443
 44 checkTypesWithArguments(program);
4545 let nameResolver = createNameResolver(program);
 46 checkTypesWithArguments(program);
4647 resolveNamesInTypes(program, nameResolver);
 48 checkTypesWithArguments(program);
4749 resolveTypeDefsInTypes(program);
 50 checkTypesWithArguments(program);
4851 checkRecursiveTypes(program);
 52 checkTypesWithArguments(program);
4953 synthesizeStructAccessors(program);
 54 checkTypesWithArguments(program);
5055 synthesizeOperatorBool(program);
 56 checkTypesWithArguments(program);
5157 synthesizeEnumFunctions(program);
 58 checkTypesWithArguments(program);
5259 synthesizeArrayOperatorLength(program);
 60 checkTypesWithArguments(program);
5361 synthesizeCopyConstructorOperator(program);
 62 checkTypesWithArguments(program);
5463 synthesizeDefaultConstructorOperator(program);
 64 checkTypesWithArguments(program);
5565 resolveNamesInFunctions(program, nameResolver);
 66 checkTypesWithArguments(program);
5667 resolveTypeDefsInFunctions(program);
 68 checkTypesWithArguments(program);
5769
5870 check(program);
5971 checkLiteralTypes(program);

Tools/WebGPUShadingLanguageRI/Program.js

@@class Program extends Node {
4848 if (statement instanceof Func) {
4949 let array = this._functions.get(statement.name);
5050 if (!array)
51  this._functions.set(statement.name, array = []);
 51 this.functions.set(statement.name, array = []);
5252 array.push(statement);
53  } else if (statement instanceof Type)
54  this._types.set(statement.name, statement);
55  else
 53 } else if (statement instanceof Type) {
 54 if (statement.isNative && statement.name == "vector") {
 55 let array = this.types.get(statement.name);
 56 if (!array)
 57 this.types.set(statement.name, array = []);
 58 array.push(statement);
 59 } else
 60 this.types.set(statement.name, statement);
 61 } else
5662 throw new Error("Statement is not a function or type: " + statement);
57  this._topLevelStatements.push(statement);
58  this._globalNameContext.add(statement);
 63 this.topLevelStatements.push(statement);
 64 this.globalNameContext.add(statement);
5965 }
6066
6167 toString()
6268 {
63  if (!this._topLevelStatements.length)
 69 if (!this.topLevelStatements.length)
6470 return "";
6571 return this._topLevelStatements.join(";") + ";";
6672 }

Tools/WebGPUShadingLanguageRI/RecursiveTypeChecker.js

@@class RecursiveTypeChecker extends Visitor {
5151 visitTypeRef(node)
5252 {
5353 super.visitTypeRef(node);
54  node.type.visit(this);
 54 if (node.possibleOverloads) {
 55 for (let overload of node.possibleOverloads)
 56 overload.visit(this);
 57 } else
 58 node.type.visit(this);
5559 }
5660}
5761

Tools/WebGPUShadingLanguageRI/RemoveTypeArguments.js

1 /*
2  * Copyright (C) 2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 "use strict";
26 
27 function removeTypeArguments(program)
28 {
29  class RemoveTypeArguments extends Visitor {
30  static resolveNameAndArguments(node)
31  {
32  if (!node.typeArguments)
33  return node.name;
34 
35  switch (node.name) {
36  case "vector":
37  if (node.typeArguments.length != 2)
38  throw new WSyntaxError(node.originString, `${node.name} should have 2 type arguments, got ${node.typeArguments.length}.`);
39 
40  const elementTypeName = node.typeArguments[0].name;
41  const lengthValue = node.typeArguments[1].value;
42 
43  if (VectorElementTypes.indexOf(elementTypeName) < 0)
44  throw new WSyntaxError(node.originString, `${elementTypeName} is not a valid vector element type.`);
45  if (VectorElementSizes.indexOf(lengthValue) < 0)
46  throw new WSyntaxError(node.originString, `${lengthValue} is not a valid size for vectors with element type ${elementTypeName}.`);
47 
48  return `${elementTypeName}${lengthValue}`;
49  // FIXME: Further cases for matrices, textures, etc.
50  default:
51  if (node.typeArguments.length)
52  throw new WSyntaxError(`${node.name}${arguments.join(", ")} is not a permitted generic type or function`);
53  return node.name;
54  }
55  }
56 
57  visitTypeRef(node)
58  {
59  node._name = RemoveTypeArguments.resolveNameAndArguments(node);
60  node._typeArguments = null;
61  }
62 
63  visitCallExpression(node)
64  {
65  node._name = RemoveTypeArguments.resolveNameAndArguments(node);
66  if (!node._name || !node._name.length)
67  throw new Error("lazy");
68  node._typeArguments = null;
69  }
70  }
71 
72  program.visit(new RemoveTypeArguments());
73 }

Tools/WebGPUShadingLanguageRI/ResolveNames.js

@@function createNameResolver(program)
3131
3232function resolveNamesInTypes(program, nameResolver)
3333{
34  for (let type of program.types.values())
35  nameResolver.doStatement(type);
 34 for (let type of program.types.values()) {
 35 if (type instanceof Array) {
 36 for (let constituentType of type)
 37 nameResolver.doStatement(constituentType);
 38 } else
 39 nameResolver.doStatement(type);
 40 }
3641}
3742
3843function resolveNamesInFunctions(program, nameResolver)

Tools/WebGPUShadingLanguageRI/ResolveOverloadImpl.js

@@function resolveOverloadImpl(functions, argumentTypes, returnType, allowEntryPoi
100100
101101 return {failures: ambiguityList.map(overload => new OverloadResolutionFailure(overload.func, message))};
102102}
 103
 104function resolveTypeOverloadImpl(types, typeArguments)
 105{
 106 if (!types)
 107 throw new Error("Null types; that should have been caught by the caller.");
 108
 109 let failures = [];
 110 let successes = [];
 111 for (let type of types) {
 112 let overload = inferTypesForTypeArguments(type, typeArguments);
 113 if (overload.failure)
 114 failures.push(overload.failure);
 115 else
 116 successes.push(overload);
 117 }
 118
 119 if (!successes.length)
 120 return {failures: failures};
 121
 122 if (successes.length == 1)
 123 return successes[0];
 124
 125 let message = "Ambiguous overload - types mutually applicable";
 126 return {failures: successes.map(overload => new TypeOverloadResolutionFailure(overload.type, message))};
 127}

Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js

2727function resolveTypeDefsInTypes(program)
2828{
2929 let resolver = new TypeDefResolver();
30  for (let type of program.types.values())
31  type.visit(resolver);
 30 for (let type of program.types.values()) {
 31 if (type instanceof Array) {
 32 for (let constituentType of type)
 33 constituentType.visit(resolver);
 34 } else
 35 type.visit(resolver);
 36 }
3237}
3338
3439function resolveTypeDefsInFunctions(program)

Tools/WebGPUShadingLanguageRI/Rewriter.js

@@class Rewriter {
9797
9898 visitTypeRef(node)
9999 {
100  let result = new TypeRef(node.origin, node.name);
 100 let result = new TypeRef(node.origin, node.name, node.typeArguments.map(argument => argument.visit(this)));
 101 if (node.possibleOverloads)
 102 result.possibleOverloads = node.possibleOverloads.map(overload => Node.visit(overload, this));
101103 if (node.type)
102104 result.type = Node.visit(node.type, this);
103105 return result;

@@class Rewriter {
382384
383385 visitVectorType(node)
384386 {
385  const vecType = new VectorType(node.origin, node.name);
 387 const vecType = new VectorType(node.origin, node.name, node.typeArguments.map(argument => argument.visit(this)));
386388 vecType._elementType = node.elementType.visit(this);
387389 return vecType;
388390 }

Tools/WebGPUShadingLanguageRI/SPIRV.html

@@td {
4343 <script src="CheckRecursion.js"></script>
4444 <script src="CheckRecursiveTypes.js"></script>
4545 <script src="CheckReturns.js"></script>
 46 <script src="CheckTypesWithArguments.js"></script>
4647 <script src="CheckUnreachableCode.js"></script>
4748 <script src="CheckWrapped.js"></script>
4849 <script src="Checker.js"></script>

@@td {
116117 <script src="ReadModifyWriteExpression.js"></script>
117118 <script src="RecursionChecker.js"></script>
118119 <script src="RecursiveTypeChecker.js"></script>
119  <script src="RemoveTypeArguments.js"></script>
120120 <script src="ResolveNames.js"></script>
121121 <script src="ResolveOverloadImpl.js"></script>
122122 <script src="ResolveProperties.js"></script>

@@td {
140140 <script src="TypeDef.js"></script>
141141 <script src="TypeDefResolver.js"></script>
142142 <script src="TypeRef.js"></script>
 143 <script src="TypeOverloadResolutionFailure.js"></script>
143144 <script src="TypedValue.js"></script>
144145 <script src="UintLiteral.js"></script>
145146 <script src="UintLiteralType.js"></script>

Tools/WebGPUShadingLanguageRI/StandardLibrary.js

@@let standardLibrary = `
3333native typedef void;
3434native typedef bool;
3535native typedef uchar;
 36native typedef ushort;
3637native typedef uint;
 38native typedef char;
 39native typedef short;
3740native typedef int;
 41native typedef half;
3842native typedef float;
39 
40 // FIXME: Add support for these types to Intrinsics.js
41 // native typedef ushort;
42 // native typedef char;
43 // native typedef short;
44 // native typedef half;
45 // native typedef atomic_int;
46 // native typedef atomic_uint;
 43native typedef atomic_int;
 44native typedef atomic_uint;
 45
 46native typedef vector<bool, 2>;
 47typedef bool2 = vector<bool, 2>;
 48native typedef vector<bool, 3>;
 49typedef bool3 = vector<bool, 3>;
 50native typedef vector<bool, 4>;
 51typedef bool4 = vector<bool, 4>;
 52native typedef vector<uchar, 2>;
 53typedef uchar2 = vector<uchar, 2>;
 54native typedef vector<uchar, 3>;
 55typedef uchar3 = vector<uchar, 3>;
 56native typedef vector<uchar, 4>;
 57typedef uchar4 = vector<uchar, 4>;
 58native typedef vector<ushort, 2>;
 59typedef ushort2 = vector<ushort, 2>;
 60native typedef vector<ushort, 3>;
 61typedef ushort3 = vector<ushort, 3>;
 62native typedef vector<ushort, 4>;
 63typedef ushort4 = vector<ushort, 4>;
 64native typedef vector<uint, 2>;
 65typedef uint2 = vector<uint, 2>;
 66native typedef vector<uint, 3>;
 67typedef uint3 = vector<uint, 3>;
 68native typedef vector<uint, 4>;
 69typedef uint4 = vector<uint, 4>;
 70native typedef vector<char, 2>;
 71typedef char2 = vector<char, 2>;
 72native typedef vector<char, 3>;
 73typedef char3 = vector<char, 3>;
 74native typedef vector<char, 4>;
 75typedef char4 = vector<char, 4>;
 76native typedef vector<short, 2>;
 77typedef short2 = vector<short, 2>;
 78native typedef vector<short, 3>;
 79typedef short3 = vector<short, 3>;
 80native typedef vector<short, 4>;
 81typedef short4 = vector<short, 4>;
 82native typedef vector<int, 2>;
 83typedef int2 = vector<int, 2>;
 84native typedef vector<int, 3>;
 85typedef int3 = vector<int, 3>;
 86native typedef vector<int, 4>;
 87typedef int4 = vector<int, 4>;
 88native typedef vector<half, 2>;
 89typedef half2 = vector<half, 2>;
 90native typedef vector<half, 3>;
 91typedef half3 = vector<half, 3>;
 92native typedef vector<half, 4>;
 93typedef half4 = vector<half, 4>;
 94native typedef vector<float, 2>;
 95typedef float2 = vector<float, 2>;
 96native typedef vector<float, 3>;
 97typedef float3 = vector<float, 3>;
 98native typedef vector<float, 4>;
 99typedef float4 = vector<float, 4>;
47100
48101native operator int(uint);
49102native operator int(uchar);

@@bool operator~(bool value)
147200{
148201 return !value;
149202}
150 
151 native typedef uchar2;
152 native typedef uchar3;
153 native typedef uchar4;
154 
155 native typedef uint2;
156 native typedef uint3;
157 native typedef uint4;
158 
159 native typedef int2;
160 native typedef int3;
161 native typedef int4;
162 
163 native typedef float2;
164 native typedef float3;
165 native typedef float4;
166203`;
167204
168205// FIXME: Once the standard library has been replaced with a new version, this comments should be removed.
169206// This list is used to restrict the availability of vector types available in the langauge.
170207// Permissible vector element types must appear in this list and in the standard library
171 const VectorElementTypes = [ /*"bool",*/ "uchar", /*"char", "ushort", "short",*/ "uint", "int", /* "half", */"float" ];
 208const VectorElementTypes = [ "bool", "uchar", "char", "ushort", "short", "uint", "int", "half", "float" ];
172209const VectorElementSizes = [ 2, 3, 4 ];
173210
174211function allVectorTypeNames()

Tools/WebGPUShadingLanguageRI/StatementCloner.js

@@class StatementCloner extends Rewriter {
5050
5151 visitNativeType(node)
5252 {
53  return new NativeType(node.origin, node.name);
 53 return new NativeType(node.origin, node.name, node.typeArguments.map(argument => argument.visit(this)));
5454 }
5555
5656 visitTypeDef(node)

Tools/WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js

@@function synthesizeDefaultConstructorOperator(program)
4545 types.add(node);
4646 super.visitElementalType(node);
4747 }
 48
 49 visitVectorType(node)
 50 {
 51 types.add(node);
 52 super.visitVectorType(node);
 53 }
4854 }
4955
5056 program.visit(new FindAllTypes());

Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js

@@function synthesizeStructAccessors(program)
5151
5252 function createTypeRef()
5353 {
54  return TypeRef.instantiate(type);
 54 return TypeRef.wrap(type);
5555 }
5656
5757 let isCast = false;

Tools/WebGPUShadingLanguageRI/Test.html

3737<script src="CheckRecursion.js"></script>
3838<script src="CheckRecursiveTypes.js"></script>
3939<script src="CheckReturns.js"></script>
 40<script src="CheckTypesWithArguments.js"></script>
4041<script src="CheckUnreachableCode.js"></script>
4142<script src="CheckWrapped.js"></script>
4243<script src="Checker.js"></script>

110111<script src="ReadModifyWriteExpression.js"></script>
111112<script src="RecursionChecker.js"></script>
112113<script src="RecursiveTypeChecker.js"></script>
113 <script src="RemoveTypeArguments.js"></script>
114114<script src="ResolveNames.js"></script>
115115<script src="ResolveOverloadImpl.js"></script>
116116<script src="ResolveProperties.js"></script>

134134<script src="TypeDef.js"></script>
135135<script src="TypeDefResolver.js"></script>
136136<script src="TypeRef.js"></script>
 137<script src="TypeOverloadResolutionFailure.js"></script>
137138<script src="TypedValue.js"></script>
138139<script src="UintLiteral.js"></script>
139140<script src="UintLiteralType.js"></script>

154155<script>
155156function doTestInBrowser()
156157{
157  var tester = doTest(/.*/);
 158 var tester = doTest(/vectorTypeSyntax/);
158159 var lastTime;
159160 function next()
160161 {

Tools/WebGPUShadingLanguageRI/Test.js

@@tests.shaderTypes = function()
28812881 }
28822882 fragment Boo bar(Foo stageIn)
28832883 {
2884  return boo();
 2884 return Boo();
28852885 }
28862886 `),
28872887 (e) => e instanceof WTypeError);

Tools/WebGPUShadingLanguageRI/TypeOverloadResolutionFailure.js

 1/*
 2 * Copyright (C) 2018 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25"use strict";
 26
 27class TypeOverloadResolutionFailure {
 28 constructor(type, reason)
 29 {
 30 this._type = type;
 31 this._reason = reason;
 32 }
 33
 34 get type() { return this._type; }
 35 get reason() { return this._reason; }
 36
 37 toString()
 38 {
 39 return this.type.toString() + " did not match because: " + this.reason;
 40 }
 41}
 42

Tools/WebGPUShadingLanguageRI/TypeRef.js

2525"use strict";
2626
2727class TypeRef extends Type {
28  constructor(origin, name, typeArguments = null)
 28 constructor(origin, name, typeArguments = [])
2929 {
3030 super();
3131 this._origin = origin;
3232 this._name = name;
3333 this._type = null;
 34 this._possibleOverloads = null;
3435 this._typeArguments = typeArguments;
3536 }
3637

@@class TypeRef extends Type {
3839 {
3940 if (type instanceof TypeRef)
4041 return type;
41  let result = new TypeRef(type.origin, type.name);
42  result.type = type;
43  return result;
44  }
45 
46  static instantiate(type)
47  {
48  let result = new TypeRef(type.origin, type.name);
 42 let result;
 43 if (type instanceof NativeType)
 44 result = new TypeRef(type.origin, type.name, type.typeArguments);
 45 else
 46 result = new TypeRef(type.orgin, type.name);
4947 result.type = type;
5048 return result;
5149 }

@@class TypeRef extends Type {
6361 {
6462 this._type = newType;
6563 }
 64
 65 get possibleOverloads()
 66 {
 67 return this._possibleOverloads;
 68 }
 69
 70 set possibleOverloads(newOverloads)
 71 {
 72 if (this.type)
 73 throw new Error("TypeRefs with known type should not have overloads.");
 74 this._possibleOverloads = newOverloads;
 75 }
 76
 77 resolve(possibleOverloads, program)
 78 {
 79 if (!possibleOverloads)
 80 throw new WTypeError(this.origin.originString, "Did not find any types named " + this.name);
 81
 82 let failures = [];
 83 let overload = resolveTypeOverloadImpl(possibleOverloads, this.typeArguments);
 84
 85 if (!overload.type) {
 86 failures.push(...overload.failures);
 87 let message = "Did not find type named " + this.name + " for type arguments ";
 88 message += "(" + this.typeArguments + ")";
 89 if (failures.length)
 90 message += ", but considered:\n" + failures.join("\n")
 91 throw new WTypeError(this.origin.originString, message);
 92 }
 93
 94 for (let i = 0; i < this.typeArguments.length; ++i) {
 95 let typeArgument = this.typeArguments[i];
 96 let resolvedTypeArgument = overload.type.typeArguments[i];
 97 let result = typeArgument.equalsWithCommit(resolvedTypeArgument);
 98 if (!result)
 99 throw new Error("At " + this.origin.originString + " argument types for Type and TypeRef not equal: argument type = " + typeArgument + ", resolved type argument = " + resolvedTypeArgument);
 100 if (resolvedTypeArgument.constructor.name == "GenericLiteral") {
 101 // FIXME: This is probably wrong.
 102 result = typeArgument.type.equalsWithCommit(resolvedTypeArgument.type);
 103 if (!result)
 104 throw new Error("At " + this.origin.originString + " argument types for Type and TypeRef not equal: argument type = " + typeArgument + ", resolved type argument = " + resolvedTypeArgument);
 105 }
 106
 107 }
 108 this.type = overload.type;
 109 }
66110
67111 get unifyNode()
68112 {

@@class TypeRef extends Type {
99143 {
100144 if (!this.name)
101145 return this.type.toString();
102  return this.name;
 146 let result = this.name;
 147 if (this.typeArguments.length > 0)
 148 result += "<" + this.typeArguments.map(argument => argument.toString()).join(",") + ">";
 149 return result;
103150 }
104151}
105152

Tools/WebGPUShadingLanguageRI/UnificationContext.js

@@class UnificationContext {
9292
9393 verify()
9494 {
 95 // We do a two-phase pre-verification. This gives literals a chance to select a more specific type.
 96 let preparations = [];
 97 for (let node of this.nodes) {
 98 let preparation = node.prepareToVerify(this);
 99 if (preparation)
 100 preparations.push(preparation);
 101 }
 102 for (let preparation of preparations) {
 103 let result = preparation();
 104 if (!result.result)
 105 return result;
 106 }
 107
95108 for (let typeArgument of this.typeArguments()) {
96109 let result = typeArgument.verifyAsArgument(this);
97110 if (!result.result)

Tools/WebGPUShadingLanguageRI/VectorType.js

2525"use strict";
2626
2727class VectorType extends NativeType {
28  constructor(origin, name)
 28 constructor(origin, name, typeArguments)
2929 {
30  super(origin, name);
31  const match = /^([A-z]+)([0-9])$/.exec(name);
32  if (!match)
33  throw new WTypeError(origin.originString, `${name} doesn't match the format for vector type names.'`);
34 
35  this._elementType = new TypeRef(origin, match[1]);
36  this._numElementsValue = parseInt(match[2]);
 30 super(origin, name, typeArguments);
3731 }
3832
39  get elementType() { return this._elementType; }
40  get numElementsValue() { return this._numElementsValue; }
 33 get elementType() { return this.typeArguments[0]; }
 34 get numElements() { return this.typeArguments[1]; }
 35 get numElementsValue() { return this.numElements.value; }
4136 get size() { return this.elementType.size * this.numElementsValue; }
4237
4338 unifyImpl(unificationContext, other)

@@class VectorType extends NativeType {
5954
6055 toString()
6156 {
62  return `native typedef ${this.elementType}${this.numElementsValue}`;
 57 return `native typedef vector<${this.elementType}, ${this.numElementsValue}>`;
6358 }
6459}
6560

Tools/WebGPUShadingLanguageRI/Visitor.js

@@class Visitor {
6868
6969 visitTypeRef(node)
7070 {
 71 for (let typeArgument of node.typeArguments)
 72 typeArgument.visit(this);
7173 }
7274
7375 visitNativeType(node)
7476 {
 77 for (let typeArgument of node.typeArguments)
 78 typeArgument.visit(this);
7579 }
7680
7781 visitTypeDef(node)

@@class Visitor {
327331 visitVectorType(node)
328332 {
329333 node.elementType.visit(this);
 334 node.numElements.visit(this);
330335 }
331336}
332337

Tools/WebGPUShadingLanguageRI/checkTypesWithArguments.js

 1/*
 2 * Copyright (C) 2018 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25"use strict";
 26
 27function checkTypesWithArguments(program)
 28{
 29 class TypeWithArgumentsChecker extends Visitor {
 30 visitTypeRef(node)
 31 {
 32 if (node.name == "vector" && node.typeArguments.length == 0)
 33 throw new Error("Builtin type ${node.name} should always have type arguments.");
 34 }
 35 }
 36 program.visit(new TypeWithArgumentsChecker());
 37}
 38

Tools/WebGPUShadingLanguageRI/index.html

3838<script src="CheckRecursiveTypes.js"></script>
3939<script src="CheckReturns.js"></script>
4040<script src="CheckUnreachableCode.js"></script>
 41<script src="CheckTypesWithArguments.js"></script>
4142<script src="CheckWrapped.js"></script>
4243<script src="Checker.js"></script>
4344<script src="CloneProgram.js"></script>

110111<script src="ReadModifyWriteExpression.js"></script>
111112<script src="RecursionChecker.js"></script>
112113<script src="RecursiveTypeChecker.js"></script>
113 <script src="RemoveTypeArguments.js"></script>
114114<script src="ResolveNames.js"></script>
115115<script src="ResolveOverloadImpl.js"></script>
116116<script src="ResolveProperties.js"></script>

134134<script src="TypeDef.js"></script>
135135<script src="TypeDefResolver.js"></script>
136136<script src="TypeRef.js"></script>
 137<script src="TypeOverloadResolutionFailure.js"></script>
137138<script src="TypedValue.js"></script>
138139<script src="UintLiteral.js"></script>
139140<script src="UintLiteralType.js"></script>