WebKit Bugzilla
Attachment 350096 Details for
Bug 188402
: [WHLSL] Local variables should be statically allocated
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-188402-20180919002408.patch (text/plain), 30.28 KB, created by
Thomas Denney
on 2018-09-19 00:24:12 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Thomas Denney
Created:
2018-09-19 00:24:12 PDT
Size:
30.28 KB
patch
obsolete
>Subversion Revision: 235753 >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 2767dbf827b6eb6488b3239c2403372b2b8f6b4a..195038fd2b76684ce12b399ec636ffbcec562d9f 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,45 @@ >+2018-09-10 Thomas Denney <tdenney@apple.com> >+ >+ [WHLSL] Local variables should be statically allocated >+ https://bugs.webkit.org/show_bug.cgi?id=188402 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ An additional preparation stage is now performed so that all local >+ variables and function parameters are allocated in a single struct at >+ entry points. A pointer to this struct is then passed for function >+ calls. >+ >+ * WebGPUShadingLanguageRI/All.js: Update dependencies. >+ * WebGPUShadingLanguageRI/AllocateAtEntryPoints.js: Added new stage. >+ * WebGPUShadingLanguageRI/CallExpression.js: >+ (CallExpression.prototype.set argumentList): Add setter because >+ allocateAtEntryPoints needs to change this. >+ * WebGPUShadingLanguageRI/EBufferBuilder.js: Remove a redundant >+ constructor that wasn't used anywhere. >+ * WebGPUShadingLanguageRI/Func.js: >+ (Func.prototype.set parameters): Add setter. >+ * WebGPUShadingLanguageRI/FuncDef.js: >+ (FuncDef.prototype.set body): Ditto. >+ * WebGPUShadingLanguageRI/Prepare.js: >+ (let.prepare): Add call to allocateAtEntryPoints. This call cannot >+ happen any earlier because it depends on having types for call >+ arguments. >+ * WebGPUShadingLanguageRI/Rewriter.js: >+ (Rewriter.prototype.visitReturn): Resolve issue where the return >+ statement's function wasn't copied. A null check is required as the >+ Rewriter might be used before this property is set. >+ * WebGPUShadingLanguageRI/SPIRV.html: Update dependencies. >+ * WebGPUShadingLanguageRI/SynthesizeStructAccessors.js: Abstracted logic >+ into a separate function so that allocateAtEntryPoints can create the >+ accessors for the struct type it introduces. >+ * WebGPUShadingLanguageRI/Test.html: Update dependencies. >+ * WebGPUShadingLanguageRI/Test.js: Add new tests to verify the static >+ allocation transform works safely. >+ * WebGPUShadingLanguageRI/index.html: Update dependencies. >+ >+ >+ > 2018-09-18 Jonathan Bedard <jbedard@apple.com> > > webkitpy: Clobbering and building occurs multiple times for iOS Simulator ports >diff --git a/Tools/WebGPUShadingLanguageRI/All.js b/Tools/WebGPUShadingLanguageRI/All.js >index 3c2c48742001115a1713483a1f23ce28668bb9c6..e2910d79d6c2359b763161980316aff0942270f3 100644 >--- a/Tools/WebGPUShadingLanguageRI/All.js >+++ b/Tools/WebGPUShadingLanguageRI/All.js >@@ -37,6 +37,7 @@ load("PropertyAccessExpression.js"); > load("NativeType.js"); > > load("AddressSpace.js"); >+load("AllocateAtEntryPoints.js"); > load("AnonymousVariable.js"); > load("ArrayRefType.js"); > load("ArrayType.js"); >diff --git a/Tools/WebGPUShadingLanguageRI/AllocateAtEntryPoints.js b/Tools/WebGPUShadingLanguageRI/AllocateAtEntryPoints.js >new file mode 100644 >index 0000000000000000000000000000000000000000..064af59436b3160f4824f1a3cf59e704649ebbc0 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/AllocateAtEntryPoints.js >@@ -0,0 +1,254 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+"use strict"; >+ >+function allocateAtEntryPoints(program) >+{ >+ const entryPoints = []; >+ class OnlyVisitFuncDefsThatAreEntryPoints extends Visitor { >+ visitFuncDef(node) >+ { >+ if (node.isEntryPoint) >+ entryPoints.push(node); >+ } >+ } >+ program.visit(new OnlyVisitFuncDefsThatAreEntryPoints()); >+ >+ const allVariablesAndFunctionParameters = new Set(); >+ const functionsThatAreCalledByEntryPoints = new Set(); >+ class FindAllVariablesAndFunctionParameters extends Visitor { >+ constructor(currentFunc) >+ { >+ super(); >+ this._currentFunc = currentFunc; >+ } >+ >+ visitCallExpression(node) >+ { >+ super.visitCallExpression(node); >+ if (node.func instanceof FuncDef) { >+ functionsThatAreCalledByEntryPoints.add(node.func); >+ node.func.visit(new FindAllVariablesAndFunctionParameters(node.func)); >+ } >+ } >+ >+ visitVariableDecl(node) >+ { >+ node._func = this._currentFunc; >+ allVariablesAndFunctionParameters.add(node); >+ super.visitVariableDecl(node); >+ } >+ >+ visitFuncParameter(node) >+ { >+ node._func = this._currentFunc; >+ if (!this._currentFunc.isEntryPoint) >+ allVariablesAndFunctionParameters.add(node); >+ } >+ } >+ >+ for (let entryPoint of entryPoints) >+ entryPoint.visit(new FindAllVariablesAndFunctionParameters(entryPoint)); >+ >+ if (!allVariablesAndFunctionParameters.size) >+ return; >+ >+ const globalStructType = new StructType(entryPoints[0].origin, null); >+ program.add(globalStructType); >+ // Checker requires that types that appear in the program are wrapped in TypeRefs. >+ const globalStructTypeRef = TypeRef.wrap(globalStructType); >+ const ptrToGlobalStructType = new PtrType(entryPoints[0].origin, "thread", globalStructTypeRef); >+ program.add(ptrToGlobalStructType); >+ const ptrToGlobalStructTypeRef = TypeRef.wrap(ptrToGlobalStructType); >+ >+ let counter = 0; >+ const varToFieldMap = new Map(); >+ for (let varOrParam of allVariablesAndFunctionParameters) { >+ const fieldName = `field${counter++}_${varOrParam._func.name}_${varOrParam.name}`; >+ globalStructType.add(new Field(varOrParam.origin, fieldName, varOrParam.type)); >+ varToFieldMap.set(varOrParam, fieldName); >+ } >+ >+ for (let func of functionsThatAreCalledByEntryPoints) { >+ if (func.returnType.name !== "void") { >+ const fieldName = `field${counter++}_return_${func.name}`; >+ globalStructType.add(new Field(func.origin, fieldName, func.returnType)); >+ func.returnFieldName = fieldName; >+ } >+ } >+ >+ // All other struct accessors will have been synthesized at this point (they have to be synthesized earlier for call resolution). >+ synthesizeStructAccessorsForStructType(program, globalStructType); >+ >+ const visitedFunctionSet = new Set(); >+ >+ function updateFunction(func) >+ { >+ class UpdateFunctions extends Rewriter { >+ constructor(func) >+ { >+ super(); >+ this._func = func; >+ visitedFunctionSet.add(this.func); >+ if (this.func.isEntryPoint) >+ this._addVariableDeclaration(); >+ else >+ this._reconfigureParameters(); >+ this.func.body = this.func._body.visit(this); >+ } >+ >+ _addVariableDeclaration() >+ { >+ this._variableDecl = new VariableDecl(this.func.origin, null, globalStructTypeRef, null); >+ this._variableRef = new MakePtrExpression(this.func.origin, VariableRef.wrap(this.variableDecl)); >+ this.func.body.statements.unshift(this.variableDecl); >+ } >+ >+ _reconfigureParameters() >+ { >+ const funcParam = new FuncParameter(this.func.origin, null, ptrToGlobalStructTypeRef); >+ this._variableRef = VariableRef.wrap(funcParam); >+ this.func._newParameters = [ funcParam ]; >+ } >+ >+ get func() >+ { >+ return this._func; >+ } >+ >+ get variableDecl() >+ { >+ return this._variableDecl; >+ } >+ >+ get globalStructVariableRef() >+ { >+ return this._variableRef; >+ } >+ >+ _callExpressionForFieldName(node, fieldName) >+ { >+ if (!fieldName) >+ throw new Error("Field name was null"); >+ const functionName = `operator&.${fieldName}`; >+ const possibleAndOverloads = program.globalNameContext.get(Func, functionName); >+ const callExpressionResolution = CallExpression.resolve(node.origin, possibleAndOverloads, functionName, [ this.globalStructVariableRef ], [ ptrToGlobalStructTypeRef ]); >+ return callExpressionResolution.call; >+ } >+ >+ _dereferencedCallExpressionForFieldName(node, resultType, fieldName) >+ { >+ const derefExpr = new DereferenceExpression(node.origin, this._callExpressionForFieldName(node, fieldName), node.type, "thread"); >+ derefExpr.type = resultType; >+ return derefExpr; >+ } >+ >+ visitVariableRef(node) >+ { >+ if (!varToFieldMap.has(node.variable)) >+ return super.visitVariableRef(node); >+ return this._dereferencedCallExpressionForFieldName(node, node.variable.type, varToFieldMap.get(node.variable)); >+ } >+ >+ visitVariableDecl(node) >+ { >+ if (node.initializer) { >+ if (!node.type) >+ throw new Error(`${node} doesn't have a type`); >+ return new Assignment(node.origin, this._dereferencedCallExpressionForFieldName(node, node.type, varToFieldMap.get(node)), node.initializer.visit(this), node.type); >+ } >+ else if (node == this.variableDecl) >+ return node; >+ return new Block(node.origin); >+ } >+ >+ visitCallExpression(node) >+ { >+ node = super.visitCallExpression(node); >+ if (node.func instanceof FuncDef) { >+ updateFunction(node.func); >+ >+ let exprs = []; >+ const anonymousVariableAssignments = []; >+ for (let i = node.argumentList.length; i--;) { >+ const type = node.func.parameters[i].type; >+ if (!type) >+ throw new Error(`${node.func.parameters[i]} has no type`); >+ const anonymousVariable = new AnonymousVariable(node.origin, type); >+ exprs.push(anonymousVariable); >+ exprs.push(new Assignment(node.origin, VariableRef.wrap(anonymousVariable), node.argumentList[i], type)); >+ anonymousVariableAssignments.push(new Assignment(node.origin, this._dereferencedCallExpressionForFieldName(node.func.parameters[i], node.func.parameters[i].type, varToFieldMap.get(node.func.parameters[i])), VariableRef.wrap(anonymousVariable), type)); >+ } >+ exprs = exprs.concat(anonymousVariableAssignments); >+ exprs.push(node); >+ >+ if (node.func.returnType.name !== "void") >+ exprs.push(this._dereferencedCallExpressionForFieldName(node.func, node.func.returnType, node.func.returnFieldName)); >+ >+ node.argumentList = [ this.globalStructVariableRef ]; >+ return new CommaExpression(node.origin, exprs); >+ } >+ >+ return node; >+ } >+ >+ visitReturn(node) >+ { >+ node = super.visitReturn(node); >+ if (node.value && this._func.returnFieldName) >+ return new CommaExpression(node.origin, [ >+ new Assignment(node.origin, this._dereferencedCallExpressionForFieldName(this._func, this._func.returnType, this._func.returnFieldName), node.value, this._func.returnType), >+ new Return(node.origin) ]); >+ else >+ return node; >+ } >+ } >+ >+ if (!visitedFunctionSet.has(func)) >+ new UpdateFunctions(func); >+ } >+ >+ for (let entryPoint of entryPoints) >+ updateFunction(entryPoint); >+ >+ class UpdateParams extends Visitor { >+ visitFuncDef(node) >+ { >+ super.visitFuncDef(node); >+ if (node._newParameters) >+ node.parameters = node._newParameters; >+ if (node.returnFieldName) >+ node._returnType = TypeRef.wrap(program.types.get("void")); >+ } >+ >+ visitCallExpression(node) >+ { >+ super.visitCallExpression(node); >+ if (node.func.returnFieldName) >+ node._returnType = node.resultType = TypeRef.wrap(program.types.get("void")); >+ } >+ } >+ program.visit(new UpdateParams()); >+} >diff --git a/Tools/WebGPUShadingLanguageRI/CallExpression.js b/Tools/WebGPUShadingLanguageRI/CallExpression.js >index 5fbdd505f79d4b326e093e0fb76cd375d0a2c5ba..4e4d65f0913804f4d0e70c002bf6314060b0ee2e 100644 >--- a/Tools/WebGPUShadingLanguageRI/CallExpression.js >+++ b/Tools/WebGPUShadingLanguageRI/CallExpression.js >@@ -36,7 +36,14 @@ class CallExpression extends Expression { > } > > get name() { return this._name; } >+ > get argumentList() { return this._argumentList; } >+ >+ set argumentList(newValue) >+ { >+ this._argumentList = newValue; >+ } >+ > get isCast() { return this._isCast; } > get returnType() { return this._returnType; } > >diff --git a/Tools/WebGPUShadingLanguageRI/EBufferBuilder.js b/Tools/WebGPUShadingLanguageRI/EBufferBuilder.js >index a3bee1fa2475d1f56b305f56d8db336ea8a4a717..a7f3616d9a1f5c17064c61b7684f2428fb11675b 100644 >--- a/Tools/WebGPUShadingLanguageRI/EBufferBuilder.js >+++ b/Tools/WebGPUShadingLanguageRI/EBufferBuilder.js >@@ -25,12 +25,6 @@ > "use strict"; > > class EBufferBuilder extends Visitor { >- constructor(program) >- { >- super(); >- this._program = program; >- } >- > _createEPtr(type) > { > if (type.size == null) >diff --git a/Tools/WebGPUShadingLanguageRI/Func.js b/Tools/WebGPUShadingLanguageRI/Func.js >index cbc2c333f666f687c07d33dc0188cc9846a3f6d2..4f5890607b1a291718234afa3d6e066f1d9905d5 100644 >--- a/Tools/WebGPUShadingLanguageRI/Func.js >+++ b/Tools/WebGPUShadingLanguageRI/Func.js >@@ -54,6 +54,11 @@ class Func extends Node { > get isEntryPoint() { return this.shaderType != null; } > get returnTypeForOverloadResolution() { return this.isCast ? this.returnType : null; } > >+ set parameters(newValue) >+ { >+ this._parameters = newValue; >+ } >+ > get kind() { return Func; } > > toDeclString() >diff --git a/Tools/WebGPUShadingLanguageRI/FuncDef.js b/Tools/WebGPUShadingLanguageRI/FuncDef.js >index d68e4030e59a571182c604b3e2bd37a704958323..3016b1325917dd72eaa7ded85a6eb27e580298ac 100644 >--- a/Tools/WebGPUShadingLanguageRI/FuncDef.js >+++ b/Tools/WebGPUShadingLanguageRI/FuncDef.js >@@ -33,7 +33,12 @@ class FuncDef extends Func { > } > > get body() { return this._body; } >- >+ >+ set body(newBody) >+ { >+ this._body = newBody; >+ } >+ > rewrite(rewriter) > { > this._returnType = this._returnType.visit(rewriter); >diff --git a/Tools/WebGPUShadingLanguageRI/Prepare.js b/Tools/WebGPUShadingLanguageRI/Prepare.js >index 13ebde80bd91ccb65468681292526334dd3887e8..9fe36ba8c7b861ee2acd0a308548ab9f6f9e3df0 100644 >--- a/Tools/WebGPUShadingLanguageRI/Prepare.js >+++ b/Tools/WebGPUShadingLanguageRI/Prepare.js >@@ -53,7 +53,7 @@ let prepare = (() => { > resolveNamesInFunctions(program, nameResolver); > resolveTypeDefsInFunctions(program); > checkTypesWithArguments(program); >- >+ > check(program); > checkLiteralTypes(program); > resolveProperties(program); >@@ -67,6 +67,7 @@ let prepare = (() => { > checkProgramWrapped(program); > checkTypesWithArguments(program); > findHighZombies(program); >+ allocateAtEntryPoints(program); > program.visit(new StructLayoutBuilder()); > lateCheckAndLayoutBuffers(program); > if (shouldInline) >diff --git a/Tools/WebGPUShadingLanguageRI/Rewriter.js b/Tools/WebGPUShadingLanguageRI/Rewriter.js >index 3025893a06a3f59032b9f6cd43f124651f026cb9..267e7a33234af372f1e134ee63f96cb1c7f78163 100644 >--- a/Tools/WebGPUShadingLanguageRI/Rewriter.js >+++ b/Tools/WebGPUShadingLanguageRI/Rewriter.js >@@ -233,7 +233,10 @@ class Rewriter { > > visitReturn(node) > { >- return new Return(node.origin, Node.visit(node.value, this)); >+ const returnStatement = new Return(node.origin, Node.visit(node.value, this)); >+ if (node.func) >+ returnStatement.func = node.func; >+ return returnStatement; > } > > visitContinue(node) >diff --git a/Tools/WebGPUShadingLanguageRI/SPIRV.html b/Tools/WebGPUShadingLanguageRI/SPIRV.html >index 0d2371005e710cdc60f033da5a511c49ae005c36..89186711ff5c010f5720e1688ff3ca5dfdee24ea 100644 >--- a/Tools/WebGPUShadingLanguageRI/SPIRV.html >+++ b/Tools/WebGPUShadingLanguageRI/SPIRV.html >@@ -20,6 +20,7 @@ td { > <script src="NativeType.js"></script> > > <script src="AddressSpace.js"></script> >+ <script src="AllocateAtEntryPoints.js"></script> > <script src="AnonymousVariable.js"></script> > <script src="ArrayRefType.js"></script> > <script src="ArrayType.js"></script> >diff --git a/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js b/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js >index a0181468a25ed4c09050d7bf1d61f44ed3a0aa66..2f6dd285c821eea0e9489a850817bf550d3af678 100644 >--- a/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js >+++ b/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js >@@ -20,95 +20,100 @@ > * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY > * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > */ > "use strict"; > >-function synthesizeStructAccessors(program) >+function synthesizeStructAccessorsForStructType(program, type) > { >- for (let type of program.types.values()) { >- if (!(type instanceof StructType)) >- continue; >- >- for (let field of type.fields) { >- function setupImplementationData(nativeFunc, implementation) >- { >- nativeFunc.visitImplementationData = (implementationData, visitor) => { >- // Visiting the type first ensures that the struct layout builder figures out the field's >- // offset. >- implementationData.type.visit(visitor); >- }; >+ for (let field of type.fields) { >+ function setupImplementationData(nativeFunc, implementation) >+ { >+ nativeFunc.visitImplementationData = (implementationData, visitor) => { >+ // Visiting the type first ensures that the struct layout builder figures out the field's >+ // offset. >+ implementationData.type.visit(visitor); >+ }; > >- nativeFunc.implementation = (argumentList, node) => { >- return implementation(argumentList, field.offset, type.size, field.type.size); >- }; >- } >- >- function createFieldType() >- { >- return field.type.visit(new Rewriter()); >- } >- >- function createTypeRef() >- { >- return TypeRef.wrap(type); >- } >- >- let isCast = false; >- let shaderType; >- let nativeFunc; >+ nativeFunc.implementation = (argumentList, node) => { >+ return implementation(argumentList, field.offset, type.size, field.type.size); >+ }; >+ } > >- // The getter: operator.field >- nativeFunc = new NativeFunc( >- field.origin, "operator." + field.name, createFieldType(), >- [new FuncParameter(field.origin, null, createTypeRef())], isCast, shaderType); >- setupImplementationData(nativeFunc, ([base], offset, structSize, fieldSize) => { >- let result = new EPtr(new EBuffer(fieldSize), 0); >- result.copyFrom(base.plus(offset), fieldSize); >- return result; >- }); >- program.add(nativeFunc); >- >- // The setter: operator.field= >+ function createFieldType() >+ { >+ return field.type.visit(new Rewriter()); >+ } >+ >+ function createTypeRef() >+ { >+ return TypeRef.wrap(type); >+ } >+ >+ let isCast = false; >+ let shaderType; >+ let nativeFunc; >+ >+ // The getter: operator.field >+ nativeFunc = new NativeFunc( >+ field.origin, "operator." + field.name, createFieldType(), >+ [new FuncParameter(field.origin, null, createTypeRef())], isCast, shaderType); >+ setupImplementationData(nativeFunc, ([base], offset, structSize, fieldSize) => { >+ let result = new EPtr(new EBuffer(fieldSize), 0); >+ result.copyFrom(base.plus(offset), fieldSize); >+ return result; >+ }); >+ program.add(nativeFunc); >+ >+ // The setter: operator.field= >+ nativeFunc = new NativeFunc( >+ field.origin, "operator." + field.name + "=", createTypeRef(), >+ [ >+ new FuncParameter(field.origin, null, createTypeRef()), >+ new FuncParameter(field.origin, null, createFieldType()) >+ ], >+ isCast, shaderType); >+ setupImplementationData(nativeFunc, ([base, value], offset, structSize, fieldSize) => { >+ let result = new EPtr(new EBuffer(structSize), 0); >+ result.copyFrom(base, structSize); >+ result.plus(offset).copyFrom(value, fieldSize); >+ return result; >+ }); >+ program.add(nativeFunc); >+ >+ // The ander: operator&.field >+ function setupAnder(addressSpace) >+ { > nativeFunc = new NativeFunc( >- field.origin, "operator." + field.name + "=", createTypeRef(), >+ field.origin, "operator&." + field.name, new PtrType(field.origin, addressSpace, createFieldType()), > [ >- new FuncParameter(field.origin, null, createTypeRef()), >- new FuncParameter(field.origin, null, createFieldType()) >+ new FuncParameter( >+ field.origin, null, >+ new PtrType(field.origin, addressSpace, createTypeRef())) > ], > isCast, shaderType); >- setupImplementationData(nativeFunc, ([base, value], offset, structSize, fieldSize) => { >- let result = new EPtr(new EBuffer(structSize), 0); >- result.copyFrom(base, structSize); >- result.plus(offset).copyFrom(value, fieldSize); >- return result; >+ setupImplementationData(nativeFunc, ([base], offset, structSize, fieldSize) => { >+ base = base.loadValue(); >+ if (!base) >+ throw new WTrapError(field.origin.originString, "Null dereference"); >+ return EPtr.box(base.plus(offset)); > }); > program.add(nativeFunc); >- >- // The ander: operator&.field >- function setupAnder(addressSpace) >- { >- nativeFunc = new NativeFunc( >- field.origin, "operator&." + field.name, new PtrType(field.origin, addressSpace, createFieldType()), >- [ >- new FuncParameter( >- field.origin, null, >- new PtrType(field.origin, addressSpace, createTypeRef())) >- ], >- isCast, shaderType); >- setupImplementationData(nativeFunc, ([base], offset, structSize, fieldSize) => { >- base = base.loadValue(); >- if (!base) >- throw new WTrapError(node.origin.originString, "Null dereference"); >- return EPtr.box(base.plus(offset)); >- }); >- program.add(nativeFunc); >- } >- >- setupAnder("thread"); >- setupAnder("threadgroup"); >- setupAnder("device"); >- setupAnder("constant"); > } >+ >+ setupAnder("thread"); >+ setupAnder("threadgroup"); >+ setupAnder("device"); >+ setupAnder("constant"); >+ } >+} >+ >+function synthesizeStructAccessors(program) >+{ >+ for (let type of program.types.values()) { >+ if (!(type instanceof StructType)) >+ continue; >+ >+ synthesizeStructAccessorsForStructType(program, type); > } > } >diff --git a/Tools/WebGPUShadingLanguageRI/Test.html b/Tools/WebGPUShadingLanguageRI/Test.html >index c12e5d99dc74a6f1901c95df91d34a05ae855e1c..98e3851f1699aa6ce68bfd5ab8461ae97deed1c1 100644 >--- a/Tools/WebGPUShadingLanguageRI/Test.html >+++ b/Tools/WebGPUShadingLanguageRI/Test.html >@@ -14,6 +14,7 @@ > <script src="NativeType.js"></script> > > <script src="AddressSpace.js"></script> >+<script src="AllocateAtEntryPoints.js"></script> > <script src="AnonymousVariable.js"></script> > <script src="ArrayRefType.js"></script> > <script src="ArrayType.js"></script> >diff --git a/Tools/WebGPUShadingLanguageRI/Test.js b/Tools/WebGPUShadingLanguageRI/Test.js >index 2bcea7d7da3cb382f1aabe2167ef3a7891392333..4d85284da6c4838a9d59a88d6589c3bb547f9d3b 100644 >--- a/Tools/WebGPUShadingLanguageRI/Test.js >+++ b/Tools/WebGPUShadingLanguageRI/Test.js >@@ -7924,6 +7924,152 @@ tests.inliningDoesntProduceAliasingIssues = () => { > checkInt(program, callFunction(program, "foo", []), 20); > } > >+tests.returnReferenceToParameter = () => { >+ let program = doPrep(` >+ test int foo(bool condition) >+ { >+ return *bar(condition, 1, 2); >+ } >+ >+ thread int* bar(bool condition, int a, int b) >+ { >+ return condition ? &a : &b; >+ } >+ `); >+ >+ checkInt(program, callFunction(program, "foo", [ makeBool(program, true) ]), 1); >+ checkInt(program, callFunction(program, "foo", [ makeBool(program, false) ]), 2); >+} >+ >+tests.returnReferenceToParameterWithDifferentFunctions = () => { >+ let program = doPrep(` >+ test int foo() >+ { >+ return *bar(10) + *baz(20); >+ } >+ >+ thread int* bar(int x) >+ { >+ return &x; >+ } >+ >+ thread int* baz(int y) >+ { >+ return &y; >+ } >+ `); >+ >+ checkInt(program, callFunction(program, "foo", []), 30); >+} >+ >+tests.returnReferenceToSameParameter = () => { >+ let program = doPrep(` >+ test int foo() >+ { >+ return plus(bar(5), bar(7)); >+ } >+ >+ int plus(thread int* x, thread int* y) >+ { >+ return *x + *y; >+ } >+ >+ thread int* bar(int x) >+ { >+ return &x; >+ } >+ `); >+ >+ checkInt(program, callFunction(program, "foo", []), 10); >+} >+ >+tests.returnReferenceToLocalVariable = () => { >+ let program = doPrep(` >+ test int foo() >+ { >+ return *bar(); >+ } >+ >+ thread int* bar() >+ { >+ int a = 42; >+ return &a; >+ } >+ `); >+ >+ checkInt(program, callFunction(program, "foo", []), 42); >+} >+ >+tests.returnReferenceToLocalVariableWithNesting = () => { >+ let program = doPrep(` >+ test int foo() >+ { >+ return *bar() + *baz(); >+ } >+ >+ thread int* bar() >+ { >+ int a = 20; >+ return &a; >+ } >+ >+ thread int* baz() >+ { >+ int a = 22; >+ return &a; >+ } >+ `); >+ >+ checkInt(program, callFunction(program, "foo", []), 42); >+} >+ >+tests.convertPtrToArrayRef = () => { >+ let program = doPrep(` >+ test int foo() >+ { >+ return bar()[0]; >+ } >+ >+ thread int[] bar() >+ { >+ int x = 42; >+ return @(&x); >+ } >+ `); >+ >+ checkInt(program, callFunction(program, "foo", []), 42); >+} >+ >+tests.convertLocalVariableToArrayRef = () => { >+ let program = doPrep(` >+ test int foo() >+ { >+ return bar()[0]; >+ } >+ >+ thread int[] bar() >+ { >+ int x = 42; >+ return @x; >+ } >+ `); >+ >+ checkInt(program, callFunction(program, "foo", []), 42); >+} >+ >+tests.referenceTakenToLocalVariableInEntryPointShouldntMoveAnything = () => { >+ let program = doPrep(` >+ test int foo() >+ { >+ int a = 42; >+ thread int* b = &a; >+ return *b; >+ } >+ `); >+ >+ checkInt(program, callFunction(program, "foo", []), 42); >+}; >+ > okToTest = true; > > let testFilter = /.*/; // run everything by default >diff --git a/Tools/WebGPUShadingLanguageRI/index.html b/Tools/WebGPUShadingLanguageRI/index.html >index 24415f33a1709b2e0e6d5bece67aa895306b89be..08f4ed5b0931b6bfb3a422897837eef8a1ac3290 100644 >--- a/Tools/WebGPUShadingLanguageRI/index.html >+++ b/Tools/WebGPUShadingLanguageRI/index.html >@@ -14,6 +14,7 @@ > <script src="NativeType.js"></script> > > <script src="AddressSpace.js"></script> >+<script src="AllocateAtEntryPoints.js"></script> > <script src="AnonymousVariable.js"></script> > <script src="ArrayRefType.js"></script> > <script src="ArrayType.js"></script>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188402
:
348987
|
349358
|
349372
|
350096
|
350175
|
350419
|
350421