WebKit Bugzilla
Attachment 370332 Details for
Bug 195925
: [WHLSL] Implement property resolver
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP
bug-195925-20190521120029.patch (text/plain), 156.44 KB, created by
Myles C. Maxfield
on 2019-05-21 12:00:30 PDT
(
hide
)
Description:
WIP
Filename:
MIME Type:
Creator:
Myles C. Maxfield
Created:
2019-05-21 12:00:30 PDT
Size:
156.44 KB
patch
obsolete
>Subversion Revision: 245545 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 1dc6f1f7d3de311ddab05b3bca41eb3e984feb35..8d660aaf5f792da38298243a7cf23f6877427c2c 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,48 @@ >+2019-05-20 Myles C. Maxfield <mmaxfield@apple.com> >+ >+ [WHLSL] Implement property resolver >+ https://bugs.webkit.org/show_bug.cgi?id=195925 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ No new tests (OOPS!). >+ >+ * Modules/webgpu/WHLSL/AST/WHLSLAddressSpace.h: >+ (WebCore::WHLSL::AST::TypeAnnotation::TypeAnnotation): >+ (WebCore::WHLSL::AST::TypeAnnotation::leftAddressSpace const): >+ (WebCore::WHLSL::AST::TypeAnnotation::isRightValue const): >+ (WebCore::WHLSL::AST::TypeAnnotation::visit): >+ * Modules/webgpu/WHLSL/AST/WHLSLExpression.h: >+ (WebCore::WHLSL::AST::Expression::typeAnnotation const): >+ (WebCore::WHLSL::AST::Expression::setTypeAnnotation): >+ (WebCore::WHLSL::AST::Expression::addressSpace const): Deleted. >+ (WebCore::WHLSL::AST::Expression::setAddressSpace): Deleted. >+ * Modules/webgpu/WHLSL/AST/WHLSLMakeArrayReferenceExpression.h: >+ (WebCore::WHLSL::AST::MakeArrayReferenceExpression::MakeArrayReferenceExpression): >+ (WebCore::WHLSL::AST::MakeArrayReferenceExpression::leftValue): >+ (WebCore::WHLSL::AST::MakeArrayReferenceExpression::lValue): Deleted. >+ * Modules/webgpu/WHLSL/AST/WHLSLMakePointerExpression.h: >+ (WebCore::WHLSL::AST::MakePointerExpression::MakePointerExpression): >+ (WebCore::WHLSL::AST::MakePointerExpression::leftValue): >+ (WebCore::WHLSL::AST::MakePointerExpression::lValue): Deleted. >+ * Modules/webgpu/WHLSL/AST/WHLSLReadModifyWriteExpression.h: >+ (WebCore::WHLSL::AST::ReadModifyWriteExpression::leftValue): >+ (WebCore::WHLSL::AST::ReadModifyWriteExpression::ReadModifyWriteExpression): >+ (WebCore::WHLSL::AST::ReadModifyWriteExpression::lValue): Deleted. >+ * Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp: >+ (WebCore::WHLSL::Metal::FunctionDefinitionWriter::visit): >+ * Modules/webgpu/WHLSL/WHLSLChecker.cpp: >+ (WebCore::WHLSL::Checker::assignTypes): >+ (WebCore::WHLSL::Checker::recurseAndGetInfo): >+ (WebCore::WHLSL::Checker::getInfo): >+ (WebCore::WHLSL::Checker::assignType): >+ (WebCore::WHLSL::Checker::forwardType): >+ (WebCore::WHLSL::Checker::visit): >+ (WebCore::WHLSL::Checker::finishVisitingPropertyAccess): >+ * Modules/webgpu/WHLSL/WHLSLResolvingType.h: >+ * Modules/webgpu/WHLSL/WHLSLVisitor.cpp: >+ (WebCore::WHLSL::Visitor::visit): >+ > 2019-05-20 Ross Kirsling <ross.kirsling@sony.com> > > Make lossy LayoutUnit constructors explicit >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAddressSpace.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAddressSpace.h >index 4a6d7c4695dc4cac829054e4055578765175f863..d436d689c78e040c5fddce3960f38f430150b2b3 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAddressSpace.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAddressSpace.h >@@ -28,6 +28,7 @@ > #if ENABLE(WEBGPU) > > #include <cstdint> >+#include <wtf/Variant.h> > > namespace WebCore { > >@@ -42,6 +43,70 @@ enum class AddressSpace : uint8_t { > Thread > }; > >+struct LeftValue { >+ AddressSpace addressSpace; >+}; >+ >+struct AbstractLeftValue { >+}; >+ >+struct RightValue { >+}; >+ >+// FIXME: This wrapper might not be necessary. >+class TypeAnnotation { >+public: >+ TypeAnnotation() >+ : m_empty(true) >+ { >+ } >+ >+ TypeAnnotation(LeftValue v) >+ : m_inner(v) >+ { >+ } >+ >+ TypeAnnotation(AbstractLeftValue v) >+ : m_inner(v) >+ { >+ } >+ >+ TypeAnnotation(RightValue v) >+ : m_inner(v) >+ { >+ } >+ >+ TypeAnnotation(const TypeAnnotation&) = default; >+ TypeAnnotation(TypeAnnotation&& other) = default; >+ >+ TypeAnnotation& operator=(const TypeAnnotation&) = default; >+ TypeAnnotation& operator=(TypeAnnotation&& other) = default; >+ >+ Optional<AddressSpace> leftAddressSpace() const >+ { >+ ASSERT(!m_empty); >+ if (WTF::holds_alternative<LeftValue>(m_inner)) >+ return WTF::get<LeftValue>(m_inner).addressSpace; >+ return WTF::nullopt; >+ } >+ >+ bool isRightValue() const >+ { >+ ASSERT(!m_empty); >+ return WTF::holds_alternative<RightValue>(m_inner); >+ } >+ >+ template <typename Visitor> auto visit(const Visitor& visitor) -> decltype(WTF::visit(visitor, std::declval<Variant<LeftValue, AbstractLeftValue, RightValue>&>())) >+ { >+ ASSERT(!m_empty); >+ return WTF::visit(visitor, m_inner); >+ } >+ >+private: >+ Variant<LeftValue, AbstractLeftValue, RightValue> m_inner; >+ bool m_empty { false }; >+}; >+ > } > > } >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAssignmentExpression.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAssignmentExpression.h >index b121fb6c1e1d1792615d9bb0274fe23588a7f2b5..79415e2ff303029106b5bf419767eb5998f0e4e7 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAssignmentExpression.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAssignmentExpression.h >@@ -55,6 +55,7 @@ public: > > Expression& left() { return m_left; } > Expression& right() { return m_right; } >+ UniqueRef<Expression>&& takeRight() { return WTFMove(m_right); } > > private: > UniqueRef<Expression> m_left; >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLExpression.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLExpression.h >index b7ab20ced2c453f95f1c2e3efc281fda48e5c3ad..318a8106163db87e85ef481ec887d9d6c5c29cc1 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLExpression.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLExpression.h >@@ -65,12 +65,12 @@ public: > m_type = WTFMove(type); > } > >- const Optional<AddressSpace>& addressSpace() const { return m_addressSpace; } >+ const TypeAnnotation* typeAnnotation() const { return m_typeAnnotation ? &*m_typeAnnotation : nullptr; } > >- void setAddressSpace(Optional<AddressSpace>& addressSpace) >+ void setTypeAnnotation(TypeAnnotation&& typeAnnotation) > { >- ASSERT(!m_addressSpace); >- m_addressSpace = addressSpace; >+ ASSERT(!m_typeAnnotation); >+ m_typeAnnotation = WTFMove(typeAnnotation); > } > > virtual bool isAssignmentExpression() const { return false; } >@@ -97,7 +97,7 @@ public: > private: > Lexer::Token m_origin; > Optional<UniqueRef<UnnamedType>> m_type; >- Optional<AddressSpace> m_addressSpace; >+ Optional<TypeAnnotation> m_typeAnnotation; > }; > > } // namespace AST >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLMakeArrayReferenceExpression.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLMakeArrayReferenceExpression.h >index 6316f54e16326b4a483fa872e1f47bb048edf88e..770cf8ba9f252726f69c1ae6de5ea4a5b12bf77d 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLMakeArrayReferenceExpression.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLMakeArrayReferenceExpression.h >@@ -39,9 +39,9 @@ namespace AST { > > class MakeArrayReferenceExpression : public Expression { > public: >- MakeArrayReferenceExpression(Lexer::Token&& origin, UniqueRef<Expression>&& lValue) >+ MakeArrayReferenceExpression(Lexer::Token&& origin, UniqueRef<Expression>&& leftValue) > : Expression(WTFMove(origin)) >- , m_lValue(WTFMove(lValue)) >+ , m_leftValue(WTFMove(leftValue)) > { > } > >@@ -52,10 +52,10 @@ public: > > bool isMakeArrayReferenceExpression() const override { return true; } > >- Expression& lValue() { return m_lValue; } >+ Expression& leftValue() { return m_leftValue; } > > private: >- UniqueRef<Expression> m_lValue; >+ UniqueRef<Expression> m_leftValue; > }; > > } // namespace AST >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLMakePointerExpression.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLMakePointerExpression.h >index 7b052b6d5f2887f592df44fd9409c4fa95203aa8..34604d56aecc4b630d7a7e6f796b9c85347ce1fb 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLMakePointerExpression.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLMakePointerExpression.h >@@ -39,9 +39,9 @@ namespace AST { > > class MakePointerExpression : public Expression { > public: >- MakePointerExpression(Lexer::Token&& origin, UniqueRef<Expression>&& lValue) >+ MakePointerExpression(Lexer::Token&& origin, UniqueRef<Expression>&& leftValue) > : Expression(WTFMove(origin)) >- , m_lValue(WTFMove(lValue)) >+ , m_leftValue(WTFMove(leftValue)) > { > } > >@@ -52,10 +52,10 @@ public: > > bool isMakePointerExpression() const override { return true; } > >- Expression& lValue() { return m_lValue; } >+ Expression& leftValue() { return m_leftValue; } > > private: >- UniqueRef<Expression> m_lValue; >+ UniqueRef<Expression> m_leftValue; > }; > > } // namespace AST >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLPropertyAccessExpression.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLPropertyAccessExpression.h >index 2ec34e15d8a40e5ad2e2bf89680c21c3344c9988..157092d650facea029b9b17760d805057e1add90 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLPropertyAccessExpression.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLPropertyAccessExpression.h >@@ -28,6 +28,7 @@ > #if ENABLE(WEBGPU) > > #include "WHLSLExpression.h" >+#include "WHLSLFunctionDeclaration.h" > #include "WHLSLLexer.h" > #include <wtf/UniqueRef.h> > >@@ -59,27 +60,56 @@ public: > Vector<std::reference_wrapper<FunctionDeclaration>, 1>& possibleGetOverloads() { return m_possibleGetOverloads; } > Vector<std::reference_wrapper<FunctionDeclaration>, 1>& possibleSetOverloads() { return m_possibleSetOverloads; } > Vector<std::reference_wrapper<FunctionDeclaration>, 1>& possibleAndOverloads() { return m_possibleAndOverloads; } >+ FunctionDeclaration* getFunction() { return m_getFunction; } >+ FunctionDeclaration* andFunction() { return m_andFunction; } >+ FunctionDeclaration* threadAndFunction() { return m_threadAndFunction; } >+ FunctionDeclaration* setFunction() { return m_setFunction; } > > void setPossibleGetOverloads(const Vector<std::reference_wrapper<FunctionDeclaration>, 1>& overloads) > { > m_possibleGetOverloads = overloads; > } >+ void setPossibleAndOverloads(const Vector<std::reference_wrapper<FunctionDeclaration>, 1>& overloads) >+ { >+ m_possibleAndOverloads = overloads; >+ } > void setPossibleSetOverloads(const Vector<std::reference_wrapper<FunctionDeclaration>, 1>& overloads) > { > m_possibleSetOverloads = overloads; > } >- void setPossibleAndOverloads(const Vector<std::reference_wrapper<FunctionDeclaration>, 1>& overloads) >+ >+ void setGetFunction(FunctionDeclaration* getFunction) > { >- m_possibleAndOverloads = overloads; >+ m_getFunction = getFunction; >+ } >+ >+ void setAndFunction(FunctionDeclaration* andFunction) >+ { >+ m_andFunction = andFunction; >+ } >+ >+ void setThreadAndFunction(FunctionDeclaration* threadAndFunction) >+ { >+ m_threadAndFunction = threadAndFunction; >+ } >+ >+ void setSetFunction(FunctionDeclaration* setFunction) >+ { >+ m_setFunction = setFunction; > } > > Expression& base() { return m_base; } >+ UniqueRef<Expression>&& takeBase() { return WTFMove(m_base); } > > private: > UniqueRef<Expression> m_base; > Vector<std::reference_wrapper<FunctionDeclaration>, 1> m_possibleGetOverloads; > Vector<std::reference_wrapper<FunctionDeclaration>, 1> m_possibleSetOverloads; > Vector<std::reference_wrapper<FunctionDeclaration>, 1> m_possibleAndOverloads; >+ FunctionDeclaration* m_getFunction { nullptr }; >+ FunctionDeclaration* m_andFunction { nullptr }; >+ FunctionDeclaration* m_threadAndFunction { nullptr }; >+ FunctionDeclaration* m_setFunction { nullptr }; > }; > > } // namespace AST >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLReadModifyWriteExpression.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLReadModifyWriteExpression.h >index 79d8d0f708e8d0578312c81794e88edaf3487cf9..209a52651e7eb3eb5a9cc1f6bc1702beb6582bc9 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLReadModifyWriteExpression.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLReadModifyWriteExpression.h >@@ -41,11 +41,11 @@ namespace WHLSL { > namespace AST { > > /* >- * 1. Evaluate m_lValue >+ * 1. Evaluate m_leftValue > * 2. Assign the result to m_oldValue > * 3. Evaluate m_newValueExpression > * 4. Assign the result to m_newValue >- * 5. Assign the result to m_lValue >+ * 5. Assign the result to m_leftValue > * 6. Evaluate m_resultExpression > * 7. Return the result > */ >@@ -73,38 +73,41 @@ public: > > UniqueRef<VariableReference> oldVariableReference() > { >- // The only reason we don't get use-after-frees is the fact that every instance of ReadModifyWriteExpression is allocated on the heap. > return makeUniqueRef<VariableReference>(VariableReference::wrap(m_oldValue)); > } > > UniqueRef<VariableReference> newVariableReference() > { >- // The only reason we don't get use-after-frees is the fact that every instance of ReadModifyWriteExpression is allocated on the heap. > return makeUniqueRef<VariableReference>(VariableReference::wrap(m_newValue)); > } > > bool isReadModifyWriteExpression() const override { return true; } > >- Expression& lValue() { return m_lValue; } >+ Expression& leftValue() { return m_leftValue; } > VariableDeclaration& oldValue() { return m_oldValue; } > VariableDeclaration& newValue() { return m_newValue; } > Expression* newValueExpression() { return m_newValueExpression ? &*m_newValueExpression : nullptr; } > Expression* resultExpression() { return m_resultExpression ? &*m_resultExpression : nullptr; } >+ UniqueRef<Expression>&& takeLeftValue() { return WTFMove(m_leftValue); } >+ UniqueRef<VariableDeclaration>&& takeOldValue() { return WTFMove(m_oldValue); } >+ UniqueRef<VariableDeclaration>&& takeNewValue() { return WTFMove(m_newValue); } >+ Optional<UniqueRef<Expression>>&& takeNewValueExpression() { return WTFMove(m_newValueExpression); } >+ Optional<UniqueRef<Expression>>&& takeResultExpression() { return WTFMove(m_resultExpression); } > > private: > template<class U, class... Args> friend UniqueRef<U> WTF::makeUniqueRef(Args&&...); > >- ReadModifyWriteExpression(Lexer::Token&& origin, UniqueRef<Expression> lValue) >+ ReadModifyWriteExpression(Lexer::Token&& origin, UniqueRef<Expression> leftValue) > : Expression(Lexer::Token(origin)) >- , m_lValue(WTFMove(lValue)) >- , m_oldValue(Lexer::Token(origin), Qualifiers(), WTF::nullopt, String(), WTF::nullopt, WTF::nullopt) >- , m_newValue(WTFMove(origin), Qualifiers(), WTF::nullopt, String(), WTF::nullopt, WTF::nullopt) >+ , m_leftValue(WTFMove(leftValue)) >+ , m_oldValue(makeUniqueRef<VariableDeclaration>(Lexer::Token(origin), Qualifiers(), WTF::nullopt, String(), WTF::nullopt, WTF::nullopt)) >+ , m_newValue(makeUniqueRef<VariableDeclaration>(WTFMove(origin), Qualifiers(), WTF::nullopt, String(), WTF::nullopt, WTF::nullopt)) > { > } > >- UniqueRef<Expression> m_lValue; >- VariableDeclaration m_oldValue; >- VariableDeclaration m_newValue; >+ UniqueRef<Expression> m_leftValue; >+ UniqueRef<VariableDeclaration> m_oldValue; >+ UniqueRef<VariableDeclaration> m_newValue; > Optional<UniqueRef<Expression>> m_newValueExpression; > Optional<UniqueRef<Expression>> m_resultExpression; > }; >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLVariableDeclaration.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLVariableDeclaration.h >index 19824f94054e4b3b7d7cf24f63c0119b8a63f4fb..e50aaadde788f4ed89e9c26bf44639c214049cfa 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLVariableDeclaration.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLVariableDeclaration.h >@@ -79,7 +79,7 @@ private: > Optional<UniqueRef<Expression>> m_initializer; > }; > >-using VariableDeclarations = Vector<VariableDeclaration>; >+using VariableDeclarations = Vector<UniqueRef<VariableDeclaration>>; > > } // namespace AST > >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLVariableDeclarationsStatement.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLVariableDeclarationsStatement.h >index e8e1fc7f5b238dbb0403e9f4027804a70a7e881c..09a02d01f49684ab963ef8725b0452d5a38edf4b 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLVariableDeclarationsStatement.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLVariableDeclarationsStatement.h >@@ -40,7 +40,7 @@ namespace AST { > > class VariableDeclarationsStatement : public Statement { > public: >- VariableDeclarationsStatement(Lexer::Token&& origin, Vector<VariableDeclaration>&& variableDeclarations) >+ VariableDeclarationsStatement(Lexer::Token&& origin, VariableDeclarations&& variableDeclarations) > : Statement(WTFMove(origin)) > , m_variableDeclarations(WTFMove(variableDeclarations)) > { >@@ -53,10 +53,10 @@ public: > > bool isVariableDeclarationsStatement() const override { return true; } > >- Vector<VariableDeclaration>& variableDeclarations() { return m_variableDeclarations; } >+ Vector<UniqueRef<VariableDeclaration>>& variableDeclarations() { return m_variableDeclarations; } > > private: >- Vector<VariableDeclaration> m_variableDeclarations; >+ VariableDeclarations m_variableDeclarations; > }; > > } // namespace AST >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp b/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp >index 624c562e51ca60c6ef8de28afebac514f2be0dbd..1a0053c9c4d4c666fe583c12168e9172edf26645 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp >@@ -188,9 +188,9 @@ String EntryPointScaffolding::mangledInputPath(Vector<String>& path) > bool found = false; > AST::StructureDefinition* structureDefinition = nullptr; > for (size_t i = 0; i < m_functionDefinition.parameters().size(); ++i) { >- if (m_functionDefinition.parameters()[i].name() == path[0]) { >+ if (m_functionDefinition.parameters()[i]->name() == path[0]) { > stringBuilder.append(m_parameterVariables[i]); >- auto& unifyNode = m_functionDefinition.parameters()[i].type()->unifyNode(); >+ auto& unifyNode = m_functionDefinition.parameters()[i]->type()->unifyNode(); > if (is<AST::NamedType>(unifyNode)) { > auto& namedType = downcast<AST::NamedType>(unifyNode); > if (is<AST::StructureDefinition>(namedType)) >@@ -249,7 +249,7 @@ String EntryPointScaffolding::unpackResourcesAndNamedBuiltIns() > { > StringBuilder stringBuilder; > for (size_t i = 0; i < m_functionDefinition.parameters().size(); ++i) >- stringBuilder.append(makeString(m_typeNamer.mangledNameForType(*m_functionDefinition.parameters()[i].type()), ' ', m_parameterVariables[i], ";\n")); >+ stringBuilder.append(makeString(m_typeNamer.mangledNameForType(*m_functionDefinition.parameters()[i]->type()), ' ', m_parameterVariables[i], ";\n")); > > for (size_t i = 0; i < m_layout.size(); ++i) { > auto variableName = m_namedBindGroups[i].variableName; >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp b/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp >index 2fc14658616c989ca217c69282ae86dc48719f08..09d69b103ad1639a5296422f6bba47b58a928ad9 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp >@@ -107,7 +107,7 @@ void FunctionDeclarationWriter::visit(AST::FunctionDeclaration& functionDeclarat > for (size_t i = 0; i < functionDeclaration.parameters().size(); ++i) { > if (i) > m_stringBuilder.append(", "); >- m_stringBuilder.append(m_typeNamer.mangledNameForType(*functionDeclaration.parameters()[i].type())); >+ m_stringBuilder.append(m_typeNamer.mangledNameForType(*functionDeclaration.parameters()[i]->type())); > } > m_stringBuilder.append(");\n"); > } >@@ -227,7 +227,7 @@ void FunctionDefinitionWriter::visit(AST::FunctionDefinition& functionDefinition > auto parameterName = generateNextVariableName(); > auto addResult = m_variableMapping.add(¶meter, parameterName); > ASSERT_UNUSED(addResult, addResult.isNewEntry); >- m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(*parameter.type()), ' ', parameterName)); >+ m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(*parameter->type()), ' ', parameterName)); > } > m_stringBuilder.append(") {\n"); > checkErrorAndVisit(functionDefinition.block()); >@@ -486,12 +486,21 @@ void FunctionDefinitionWriter::visit(AST::VariableDeclaration& variableDeclarati > > void FunctionDefinitionWriter::visit(AST::AssignmentExpression& assignmentExpression) > { >+ if (is<AST::DereferenceExpression>(assignmentExpression.left())) { >+ checkErrorAndVisit(downcast<AST::DereferenceExpression>(assignmentExpression.left()).pointer()); >+ auto leftName = m_stack.takeLast(); >+ checkErrorAndVisit(assignmentExpression.right()); >+ auto rightName = m_stack.takeLast(); >+ m_stringBuilder.append(makeString('*', leftName, " = ", rightName, ";\n")); >+ m_stack.append(rightName); >+ return; >+ } > checkErrorAndVisit(assignmentExpression.left()); > auto leftName = m_stack.takeLast(); > checkErrorAndVisit(assignmentExpression.right()); > auto rightName = m_stack.takeLast(); > m_stringBuilder.append(makeString(leftName, " = ", rightName, ";\n")); >- m_stack.append(leftName); >+ m_stack.append(rightName); > } > > void FunctionDefinitionWriter::visit(AST::CallExpression& callExpression) >@@ -570,7 +579,7 @@ void FunctionDefinitionWriter::visit(AST::LogicalNotExpression& logicalNotExpres > > void FunctionDefinitionWriter::visit(AST::MakeArrayReferenceExpression& makeArrayReferenceExpression) > { >- checkErrorAndVisit(makeArrayReferenceExpression.lValue()); >+ checkErrorAndVisit(makeArrayReferenceExpression.leftValue()); > auto lValue = m_stack.takeLast(); > ASSERT(makeArrayReferenceExpression.resolvedType()); > auto variableName = generateNextVariableName(); >@@ -587,7 +596,7 @@ void FunctionDefinitionWriter::visit(AST::MakeArrayReferenceExpression& makeArra > > void FunctionDefinitionWriter::visit(AST::MakePointerExpression& makePointerExpression) > { >- checkErrorAndVisit(makePointerExpression.lValue()); >+ checkErrorAndVisit(makePointerExpression.leftValue()); > auto lValue = m_stack.takeLast(); > ASSERT(makePointerExpression.resolvedType()); > auto variableName = generateNextVariableName(); >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp b/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp >index 6972e989050a9a1b7da811a87c33c33d1e4ed29c..2edf41ff326ad1c37e63d838788eeb1b56bd2e95 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp >@@ -111,8 +111,8 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara > } > > ASSERT(nativeFunctionDeclaration.parameters().size() == 1); >- auto metalParameterName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0].type()); >- auto& parameterType = nativeFunctionDeclaration.parameters()[0].type()->unifyNode(); >+ auto metalParameterName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); >+ auto& parameterType = nativeFunctionDeclaration.parameters()[0]->type()->unifyNode(); > if (is<AST::NamedType>(parameterType)) { > auto& parameterNamedType = downcast<AST::NamedType>(parameterType); > if (is<AST::NativeTypeDeclaration>(parameterNamedType)) { >@@ -134,7 +134,7 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara > > if (nativeFunctionDeclaration.name() == "operator.value") { > ASSERT(nativeFunctionDeclaration.parameters().size() == 1); >- auto metalParameterName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0].type()); >+ auto metalParameterName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); > auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); > stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameterName, " x) {\n")); > stringBuilder.append(makeString(" return static_cast<", metalReturnName, ">(x);\n")); >@@ -142,11 +142,12 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara > return stringBuilder.toString(); > } > >+ // FIXME: Authors can make a struct field named "length" too. Autogenerated getters for those shouldn't take this codepath. > if (nativeFunctionDeclaration.name() == "operator.length") { > ASSERT_UNUSED(intrinsics, matches(nativeFunctionDeclaration.type(), intrinsics.uintType())); > ASSERT(nativeFunctionDeclaration.parameters().size() == 1); >- auto metalParameterName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0].type()); >- auto& parameterType = nativeFunctionDeclaration.parameters()[0].type()->unifyNode(); >+ auto metalParameterName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); >+ auto& parameterType = nativeFunctionDeclaration.parameters()[0]->type()->unifyNode(); > ASSERT(is<AST::UnnamedType>(parameterType)); > auto& unnamedParameterType = downcast<AST::UnnamedType>(parameterType); > if (is<AST::ArrayType>(unnamedParameterType)) { >@@ -165,45 +166,74 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara > } > > if (nativeFunctionDeclaration.name().startsWith("operator."_str)) { >+ auto mangledFieldName = [&](String& fieldName) -> String { >+ auto& unifyNode = nativeFunctionDeclaration.parameters()[0]->type()->unifyNode(); >+ auto& namedType = downcast<AST::NamedType>(unifyNode); >+ if (is<AST::StructureDefinition>(namedType)) { >+ auto& structureDefinition = downcast<AST::StructureDefinition>(namedType); >+ auto* structureElement = structureDefinition.find(fieldName); >+ ASSERT(structureElement); >+ return typeNamer.mangledNameForStructureElement(*structureElement); >+ } else { >+ ASSERT(is<AST::NativeTypeDeclaration>(namedType)); >+ return fieldName; >+ } >+ }; >+ > if (nativeFunctionDeclaration.name().endsWith("=")) { > ASSERT(nativeFunctionDeclaration.parameters().size() == 2); >- auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0].type()); >- auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1].type()); >+ auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); >+ auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1]->type()); > auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); > auto fieldName = nativeFunctionDeclaration.name().substring("operator."_str.length()); > fieldName = fieldName.substring(0, fieldName.length() - 1); >+ auto metalFieldName = mangledFieldName(fieldName); > stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameter1Name, " v, ", metalParameter2Name, " n) {\n")); >- stringBuilder.append(makeString(" v.", fieldName, " = n;\n")); >+ stringBuilder.append(makeString(" v.", metalFieldName, " = n;\n")); > stringBuilder.append(makeString(" return v;\n")); > stringBuilder.append("}\n"); > return stringBuilder.toString(); > } > > ASSERT(nativeFunctionDeclaration.parameters().size() == 1); >- auto metalParameterName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0].type()); >- auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); > auto fieldName = nativeFunctionDeclaration.name().substring("operator."_str.length()); >+ auto metalParameterName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); >+ auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); >+ auto metalFieldName = mangledFieldName(fieldName); > stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameterName, " v) {\n")); >- stringBuilder.append(makeString(" return v.", fieldName, ";\n")); >+ stringBuilder.append(makeString(" return v.", metalFieldName, ";\n")); > stringBuilder.append("}\n"); > return stringBuilder.toString(); > } > > if (nativeFunctionDeclaration.name().startsWith("operator&."_str)) { > ASSERT(nativeFunctionDeclaration.parameters().size() == 1); >- auto metalParameterName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0].type()); >+ auto metalParameterName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); > auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); > auto fieldName = nativeFunctionDeclaration.name().substring("operator&."_str.length()); >+ >+ String metalFieldName; >+ auto& unnamedType = *nativeFunctionDeclaration.parameters()[0]->type(); >+ auto& unifyNode = downcast<AST::PointerType>(unnamedType).elementType().unifyNode(); >+ auto& namedType = downcast<AST::NamedType>(unifyNode); >+ if (is<AST::StructureDefinition>(namedType)) { >+ auto& structureDefinition = downcast<AST::StructureDefinition>(namedType); >+ auto* structureElement = structureDefinition.find(fieldName); >+ ASSERT(structureElement); >+ metalFieldName = typeNamer.mangledNameForStructureElement(*structureElement); >+ } else >+ metalFieldName = fieldName; >+ > stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameterName, " v) {\n")); >- stringBuilder.append(makeString(" return &(v->", fieldName, ");\n")); >+ stringBuilder.append(makeString(" return &(v->", metalFieldName, ");\n")); > stringBuilder.append("}\n"); > return stringBuilder.toString(); > } > > if (nativeFunctionDeclaration.name() == "operator[]") { > ASSERT(nativeFunctionDeclaration.parameters().size() == 2); >- auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0].type()); >- auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1].type()); >+ auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); >+ auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1]->type()); > auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); > stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameter1Name, " m, ", metalParameter2Name, " i) {\n")); > stringBuilder.append(makeString(" return m[i];\n")); >@@ -213,8 +243,8 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara > > if (nativeFunctionDeclaration.name() == "operator&[]") { > ASSERT(nativeFunctionDeclaration.parameters().size() == 2); >- auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0].type()); >- auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0].type()); >+ auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); >+ auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1]->type()); > auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); > auto fieldName = nativeFunctionDeclaration.name().substring("operator&[]."_str.length()); > stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameter1Name, " v, ", metalParameter2Name, " n) {\n")); >@@ -225,9 +255,9 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara > > if (nativeFunctionDeclaration.name() == "operator[]=") { > ASSERT(nativeFunctionDeclaration.parameters().size() == 3); >- auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0].type()); >- auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1].type()); >- auto metalParameter3Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[2].type()); >+ auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); >+ auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1]->type()); >+ auto metalParameter3Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[2]->type()); > auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); > stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameter1Name, " m, ", metalParameter2Name, " i, ", metalParameter3Name, " v) {\n")); > stringBuilder.append(makeString(" m[i] = v;\n")); >@@ -239,7 +269,7 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara > if (nativeFunctionDeclaration.isOperator()) { > if (nativeFunctionDeclaration.parameters().size() == 1) { > auto operatorName = nativeFunctionDeclaration.name().substring("operator"_str.length()); >- auto metalParameterName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0].type()); >+ auto metalParameterName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); > auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); > stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameterName, " x) {\n")); > stringBuilder.append(makeString(" return ", operatorName, "x;\n")); >@@ -249,8 +279,8 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara > > ASSERT(nativeFunctionDeclaration.parameters().size() == 2); > auto operatorName = nativeFunctionDeclaration.name().substring("operator"_str.length()); >- auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0].type()); >- auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1].type()); >+ auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); >+ auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1]->type()); > auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); > stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameter1Name, " x, ", metalParameter2Name, " y) {\n")); > stringBuilder.append(makeString(" return x ", operatorName, " y;\n")); >@@ -283,7 +313,7 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara > || nativeFunctionDeclaration.name() == "asuint" > || nativeFunctionDeclaration.name() == "asfloat") { > ASSERT(nativeFunctionDeclaration.parameters().size() == 1); >- auto metalParameterName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0].type()); >+ auto metalParameterName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); > auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); > stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameterName, " x) {\n")); > stringBuilder.append(makeString(" return ", mapFunctionName(nativeFunctionDeclaration.name()), "(x);\n")); >@@ -293,8 +323,8 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara > > if (nativeFunctionDeclaration.name() == "pow" || nativeFunctionDeclaration.name() == "atan2") { > ASSERT(nativeFunctionDeclaration.parameters().size() == 2); >- auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0].type()); >- auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1].type()); >+ auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); >+ auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1]->type()); > auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); > stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameter1Name, " x, ", metalParameter2Name, " y) {\n")); > stringBuilder.append(makeString(" return ", nativeFunctionDeclaration.name(), "(x, y);\n")); >@@ -336,14 +366,14 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara > if (nativeFunctionDeclaration.name().startsWith("Interlocked"_str)) { > if (nativeFunctionDeclaration.name() == "InterlockedCompareExchange") { > ASSERT(nativeFunctionDeclaration.parameters().size() == 4); >- ASSERT(is<AST::PointerType>(*nativeFunctionDeclaration.parameters()[0].type())); >- auto& firstArgumentPointer = downcast<AST::PointerType>(*nativeFunctionDeclaration.parameters()[0].type()); >+ ASSERT(is<AST::PointerType>(*nativeFunctionDeclaration.parameters()[0]->type())); >+ auto& firstArgumentPointer = downcast<AST::PointerType>(*nativeFunctionDeclaration.parameters()[0]->type()); > auto firstArgumentAddressSpace = firstArgumentPointer.addressSpace(); > auto firstArgumentPointee = typeNamer.mangledNameForType(firstArgumentPointer.elementType()); >- auto secondArgument = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1].type()); >- auto thirdArgument = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[2].type()); >- ASSERT(is<AST::PointerType>(*nativeFunctionDeclaration.parameters()[3].type())); >- auto& fourthArgumentPointer = downcast<AST::PointerType>(*nativeFunctionDeclaration.parameters()[3].type()); >+ auto secondArgument = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1]->type()); >+ auto thirdArgument = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[2]->type()); >+ ASSERT(is<AST::PointerType>(*nativeFunctionDeclaration.parameters()[3]->type())); >+ auto& fourthArgumentPointer = downcast<AST::PointerType>(*nativeFunctionDeclaration.parameters()[3]->type()); > auto fourthArgumentAddressSpace = fourthArgumentPointer.addressSpace(); > auto fourthArgumentPointee = typeNamer.mangledNameForType(fourthArgumentPointer.elementType()); > stringBuilder.append(makeString("void ", outputFunctionName, '(', convertAddressSpace(firstArgumentAddressSpace), ' ', firstArgumentPointee, "* object, ", secondArgument, " compare, ", thirdArgument, " desired, ", convertAddressSpace(fourthArgumentAddressSpace), ' ', fourthArgumentPointee, "* out) {\n")); >@@ -354,13 +384,13 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara > } > > ASSERT(nativeFunctionDeclaration.parameters().size() == 3); >- ASSERT(is<AST::PointerType>(*nativeFunctionDeclaration.parameters()[0].type())); >- auto& firstArgumentPointer = downcast<AST::PointerType>(*nativeFunctionDeclaration.parameters()[0].type()); >+ ASSERT(is<AST::PointerType>(*nativeFunctionDeclaration.parameters()[0]->type())); >+ auto& firstArgumentPointer = downcast<AST::PointerType>(*nativeFunctionDeclaration.parameters()[0]->type()); > auto firstArgumentAddressSpace = firstArgumentPointer.addressSpace(); > auto firstArgumentPointee = typeNamer.mangledNameForType(firstArgumentPointer.elementType()); >- auto secondArgument = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1].type()); >- ASSERT(is<AST::PointerType>(*nativeFunctionDeclaration.parameters()[2].type())); >- auto& thirdArgumentPointer = downcast<AST::PointerType>(*nativeFunctionDeclaration.parameters()[2].type()); >+ auto secondArgument = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1]->type()); >+ ASSERT(is<AST::PointerType>(*nativeFunctionDeclaration.parameters()[2]->type())); >+ auto& thirdArgumentPointer = downcast<AST::PointerType>(*nativeFunctionDeclaration.parameters()[2]->type()); > auto thirdArgumentAddressSpace = thirdArgumentPointer.addressSpace(); > auto thirdArgumentPointee = typeNamer.mangledNameForType(thirdArgumentPointer.elementType()); > auto name = atomicName(nativeFunctionDeclaration.name().substring("Interlocked"_str.length())); >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckDuplicateFunctions.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckDuplicateFunctions.cpp >index 61d348af1596623af4c3798ea9981f94a4169565..41ebae6b40dfea30db135ea3fe9b14ec19778e34 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckDuplicateFunctions.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckDuplicateFunctions.cpp >@@ -70,7 +70,7 @@ bool checkDuplicateFunctions(const Program& program) > continue; > bool same = true; > for (size_t k = 0; k < functions[i].get().parameters().size(); ++k) { >- if (!matches(*functions[i].get().parameters()[k].type(), *functions[j].get().parameters()[k].type())) { >+ if (!matches(*functions[i].get().parameters()[k]->type(), *functions[j].get().parameters()[k]->type())) { > same = false; > break; > } >@@ -80,8 +80,8 @@ bool checkDuplicateFunctions(const Program& program) > } > > if (functions[i].get().name() == "operator&[]" && functions[i].get().parameters().size() == 2 >- && is<AST::ArrayReferenceType>(static_cast<const AST::UnnamedType&>(*functions[i].get().parameters()[0].type()))) { >- auto& type = static_cast<const AST::UnnamedType&>(*functions[i].get().parameters()[1].type()); >+ && is<AST::ArrayReferenceType>(static_cast<const AST::UnnamedType&>(*functions[i].get().parameters()[0]->type()))) { >+ auto& type = static_cast<const AST::UnnamedType&>(*functions[i].get().parameters()[1]->type()); > if (is<AST::TypeReference>(type)) { > if (auto* resolvedType = downcast<AST::TypeReference>(type).resolvedType()) { > if (is<AST::NativeTypeDeclaration>(*resolvedType)) { >@@ -92,14 +92,14 @@ bool checkDuplicateFunctions(const Program& program) > } > } > } else if (functions[i].get().name() == "operator.length" && functions[i].get().parameters().size() == 1 >- && (is<AST::ArrayReferenceType>(static_cast<const AST::UnnamedType&>(*functions[i].get().parameters()[0].type())) >- || is<AST::ArrayType>(static_cast<const AST::UnnamedType&>(*functions[i].get().parameters()[0].type())))) >+ && (is<AST::ArrayReferenceType>(static_cast<const AST::UnnamedType&>(*functions[i].get().parameters()[0]->type())) >+ || is<AST::ArrayType>(static_cast<const AST::UnnamedType&>(*functions[i].get().parameters()[0]->type())))) > return false; > else if (functions[i].get().name() == "operator==" > && functions[i].get().parameters().size() == 2 >- && is<AST::ReferenceType>(static_cast<const AST::UnnamedType&>(*functions[i].get().parameters()[0].type())) >- && is<AST::ReferenceType>(static_cast<const AST::UnnamedType&>(*functions[i].get().parameters()[1].type())) >- && matches(*functions[i].get().parameters()[0].type(), *functions[i].get().parameters()[1].type())) >+ && is<AST::ReferenceType>(static_cast<const AST::UnnamedType&>(*functions[i].get().parameters()[0]->type())) >+ && is<AST::ReferenceType>(static_cast<const AST::UnnamedType&>(*functions[i].get().parameters()[1]->type())) >+ && matches(*functions[i].get().parameters()[0]->type(), *functions[i].get().parameters()[1]->type())) > return false; > } > return true; >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp >index 1365f26d123482000ee74047cb321e802b2c6083..469fac6f8fdb36f5e7c733409eb5a4cba1cdccd8 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp >@@ -122,8 +122,8 @@ static AST::NativeFunctionDeclaration resolveWithOperatorAnderIndexer(AST::CallE > const bool isOperator = true; > auto returnType = makeUniqueRef<AST::PointerType>(Lexer::Token(callExpression.origin()), firstArgument.addressSpace(), firstArgument.elementType().clone()); > AST::VariableDeclarations parameters; >- parameters.append(AST::VariableDeclaration(Lexer::Token(callExpression.origin()), AST::Qualifiers(), { firstArgument.clone() }, String(), WTF::nullopt, WTF::nullopt)); >- parameters.append(AST::VariableDeclaration(Lexer::Token(callExpression.origin()), AST::Qualifiers(), { AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.uintType()) }, String(), WTF::nullopt, WTF::nullopt)); >+ parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), firstArgument.clone(), String(), WTF::nullopt, WTF::nullopt)); >+ parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.uintType())), String(), WTF::nullopt, WTF::nullopt)); > return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(callExpression.origin()), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator&[]", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator)); > } > >@@ -132,7 +132,7 @@ static AST::NativeFunctionDeclaration resolveWithOperatorLength(AST::CallExpress > const bool isOperator = true; > auto returnType = AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.uintType()); > AST::VariableDeclarations parameters; >- parameters.append(AST::VariableDeclaration(Lexer::Token(callExpression.origin()), AST::Qualifiers(), { firstArgument.clone() }, String(), WTF::nullopt, WTF::nullopt)); >+ parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), firstArgument.clone(), String(), WTF::nullopt, WTF::nullopt)); > return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(callExpression.origin()), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator.length", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator)); > } > >@@ -153,8 +153,8 @@ static AST::NativeFunctionDeclaration resolveWithReferenceComparator(AST::CallEx > })); > })); > AST::VariableDeclarations parameters; >- parameters.append(AST::VariableDeclaration(Lexer::Token(callExpression.origin()), AST::Qualifiers(), { argumentType->clone() }, String(), WTF::nullopt, WTF::nullopt)); >- parameters.append(AST::VariableDeclaration(Lexer::Token(callExpression.origin()), AST::Qualifiers(), { WTFMove(argumentType) }, String(), WTF::nullopt, WTF::nullopt)); >+ parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), argumentType->clone(), String(), WTF::nullopt, WTF::nullopt)); >+ parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(WTFMove(argumentType)), String(), WTF::nullopt, WTF::nullopt)); > return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(callExpression.origin()), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator==", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator)); > } > >@@ -203,8 +203,8 @@ static Optional<AST::NativeFunctionDeclaration> resolveByInstantiation(AST::Call > auto rightAcceptability = acceptability(types[1].get()); > bool success = false; > if (leftAcceptability == Acceptability::Yes && rightAcceptability == Acceptability::Yes) { >- auto& unnamedType1 = types[0].get().getUnnamedType(); >- auto& unnamedType2 = types[1].get().getUnnamedType(); >+ auto& unnamedType1 = *types[0].get().getUnnamedType(); >+ auto& unnamedType2 = *types[1].get().getUnnamedType(); > success = matches(unnamedType1, unnamedType2); > } else if ((leftAcceptability == Acceptability::Maybe && rightAcceptability == Acceptability::Yes) > || (leftAcceptability == Acceptability::Yes && rightAcceptability == Acceptability::Maybe)) >@@ -304,14 +304,14 @@ static bool checkOperatorOverload(const AST::FunctionDefinition& functionDefinit > size_t numExpectedParameters = kind == CheckKind::Index ? 2 : 1; > if (functionDefinition.parameters().size() != numExpectedParameters) > return false; >- auto& firstParameterUnifyNode = (*functionDefinition.parameters()[0].type())->unifyNode(); >+ auto& firstParameterUnifyNode = (*functionDefinition.parameters()[0]->type())->unifyNode(); > if (is<AST::UnnamedType>(firstParameterUnifyNode)) { > auto& unnamedType = downcast<AST::UnnamedType>(firstParameterUnifyNode); > if (is<AST::PointerType>(unnamedType) || is<AST::ArrayReferenceType>(unnamedType) || is<AST::ArrayType>(unnamedType)) > return false; > } > if (kind == CheckKind::Index) { >- auto& secondParameterUnifyNode = (*functionDefinition.parameters()[1].type())->unifyNode(); >+ auto& secondParameterUnifyNode = (*functionDefinition.parameters()[1]->type())->unifyNode(); > if (!is<AST::NamedType>(secondParameterUnifyNode)) > return false; > auto& namedType = downcast<AST::NamedType>(secondParameterUnifyNode); >@@ -328,14 +328,14 @@ static bool checkOperatorOverload(const AST::FunctionDefinition& functionDefinit > size_t numExpectedParameters = kind == CheckKind::Index ? 3 : 2; > if (functionDefinition.parameters().size() != numExpectedParameters) > return false; >- auto& firstArgumentUnifyNode = (*functionDefinition.parameters()[0].type())->unifyNode(); >+ auto& firstArgumentUnifyNode = (*functionDefinition.parameters()[0]->type())->unifyNode(); > if (is<AST::UnnamedType>(firstArgumentUnifyNode)) { > auto& unnamedType = downcast<AST::UnnamedType>(firstArgumentUnifyNode); > if (is<AST::PointerType>(unnamedType) || is<AST::ArrayReferenceType>(unnamedType) || is<AST::ArrayType>(unnamedType)) > return false; > } > if (kind == CheckKind::Index) { >- auto& secondParameterUnifyNode = (*functionDefinition.parameters()[1].type())->unifyNode(); >+ auto& secondParameterUnifyNode = (*functionDefinition.parameters()[1]->type())->unifyNode(); > if (!is<AST::NamedType>(secondParameterUnifyNode)) > return false; > auto& namedType = downcast<AST::NamedType>(secondParameterUnifyNode); >@@ -345,9 +345,9 @@ static bool checkOperatorOverload(const AST::FunctionDefinition& functionDefinit > if (!nativeTypeDeclaration.isInt()) > return false; > } >- if (!matches(functionDefinition.type(), *functionDefinition.parameters()[0].type())) >+ if (!matches(functionDefinition.type(), *functionDefinition.parameters()[0]->type())) > return false; >- auto& valueType = *functionDefinition.parameters()[numExpectedParameters - 1].type(); >+ auto& valueType = *functionDefinition.parameters()[numExpectedParameters - 1]->type(); > auto getterName = functionDefinition.name().substring(0, functionDefinition.name().length() - 1); > auto* getterFuncs = nameContext.getFunctions(getterName); > if (!getterFuncs) >@@ -355,7 +355,7 @@ static bool checkOperatorOverload(const AST::FunctionDefinition& functionDefinit > Vector<ResolvingType> argumentTypes; > Vector<std::reference_wrapper<ResolvingType>> argumentTypeReferences; > for (size_t i = 0; i < numExpectedParameters - 1; ++i) >- argumentTypes.append((*functionDefinition.parameters()[0].type())->clone()); >+ argumentTypes.append((*functionDefinition.parameters()[0]->type())->clone()); > for (auto& argumentType : argumentTypes) > argumentTypeReferences.append(argumentType); > auto* overload = resolveFunctionOverloadImpl(*getterFuncs, argumentTypeReferences, nullptr); >@@ -378,7 +378,7 @@ static bool checkOperatorOverload(const AST::FunctionDefinition& functionDefinit > return false; > } > { >- auto& unifyNode = (*functionDefinition.parameters()[0].type())->unifyNode(); >+ auto& unifyNode = (*functionDefinition.parameters()[0]->type())->unifyNode(); > if (!is<AST::UnnamedType>(unifyNode)) > return false; > auto& unnamedType = downcast<AST::UnnamedType>(unifyNode); >@@ -392,7 +392,7 @@ static bool checkOperatorOverload(const AST::FunctionDefinition& functionDefinit > return true; > if (functionDefinition.name() == "operator++" || functionDefinition.name() == "operator--") { > return functionDefinition.parameters().size() == 1 >- && matches(*functionDefinition.parameters()[0].type(), functionDefinition.type()); >+ && matches(*functionDefinition.parameters()[0]->type(), functionDefinition.type()); > } > if (functionDefinition.name() == "operator+" || functionDefinition.name() == "operator-") > return functionDefinition.parameters().size() == 1 || functionDefinition.parameters().size() == 2; >@@ -447,19 +447,18 @@ public: > > private: > bool checkShaderType(const AST::FunctionDefinition&); >- void finishVisitingPropertyAccess(AST::PropertyAccessExpression&, AST::UnnamedType& wrappedBaseType, AST::UnnamedType* extraArgumentType = nullptr); > bool isBoolType(ResolvingType&); > struct RecurseInfo { > ResolvingType& resolvingType; >- Optional<AST::AddressSpace>& addressSpace; >+ AST::TypeAnnotation& typeAnnotation; > }; >- Optional<RecurseInfo> recurseAndGetInfo(AST::Expression&, bool requiresLValue = false); >- Optional<RecurseInfo> getInfo(AST::Expression&, bool requiresLValue = false); >+ Optional<RecurseInfo> recurseAndGetInfo(AST::Expression&, bool requiresLeftValue = false); >+ Optional<RecurseInfo> getInfo(AST::Expression&, bool requiresLeftValue = false); > Optional<UniqueRef<AST::UnnamedType>> recurseAndWrapBaseType(AST::PropertyAccessExpression&); > bool recurseAndRequireBoolType(AST::Expression&); >- void assignType(AST::Expression&, UniqueRef<AST::UnnamedType>&&, Optional<AST::AddressSpace> = WTF::nullopt); >- void assignType(AST::Expression&, RefPtr<ResolvableTypeReference>&&, Optional<AST::AddressSpace> = WTF::nullopt); >- void forwardType(AST::Expression&, ResolvingType&, Optional<AST::AddressSpace> = WTF::nullopt); >+ void assignType(AST::Expression&, UniqueRef<AST::UnnamedType>&&, AST::TypeAnnotation); >+ void assignType(AST::Expression&, RefPtr<ResolvableTypeReference>&&, AST::TypeAnnotation); >+ void forwardType(AST::Expression&, ResolvingType&, AST::TypeAnnotation); > > void visit(AST::FunctionDefinition&) override; > void visit(AST::EnumerationDefinition&) override; >@@ -494,7 +493,7 @@ private: > void visit(AST::CallExpression&) override; > > HashMap<AST::Expression*, ResolvingType> m_typeMap; >- HashMap<AST::Expression*, Optional<AST::AddressSpace>> m_addressSpaceMap; >+ HashMap<AST::Expression*, AST::TypeAnnotation> m_typeAnnotations; > HashSet<String> m_vertexEntryPoints; > HashSet<String> m_fragmentEntryPoints; > HashSet<String> m_computeEntryPoints; >@@ -538,8 +537,8 @@ bool Checker::assignTypes() > return false; > } > >- for (auto& keyValuePair : m_addressSpaceMap) >- keyValuePair.key->setAddressSpace(keyValuePair.value); >+ for (auto& keyValuePair : m_typeAnnotations) >+ keyValuePair.key->setTypeAnnotation(WTFMove(keyValuePair.value)); > return true; > } > >@@ -621,6 +620,17 @@ static Optional<UniqueRef<AST::UnnamedType>> matchAndCommit(ResolvingType& resol > })); > } > >+static Optional<UniqueRef<AST::UnnamedType>> commit(ResolvingType& resolvingType) >+{ >+ return resolvingType.visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& unnamedType) -> Optional<UniqueRef<AST::UnnamedType>> { >+ return unnamedType->clone(); >+ }, [&](RefPtr<ResolvableTypeReference>& resolvableTypeReference) -> Optional<UniqueRef<AST::UnnamedType>> { >+ if (!resolvableTypeReference->resolvableType().resolvedType()) >+ return commit(resolvableTypeReference->resolvableType()); >+ return resolvableTypeReference->resolvableType().resolvedType()->clone(); >+ })); >+} >+ > void Checker::visit(AST::EnumerationDefinition& enumerationDefinition) > { > auto* baseType = ([&]() -> AST::NativeTypeDeclaration* { >@@ -728,26 +738,26 @@ void Checker::visit(AST::TypeReference& typeReference) > checkErrorAndVisit(typeArgument); > } > >-auto Checker::recurseAndGetInfo(AST::Expression& expression, bool requiresLValue) -> Optional<RecurseInfo> >+auto Checker::recurseAndGetInfo(AST::Expression& expression, bool requiresLeftValue) -> Optional<RecurseInfo> > { > Visitor::visit(expression); > if (error()) > return WTF::nullopt; >- return getInfo(expression, requiresLValue); >+ return getInfo(expression, requiresLeftValue); > } > >-auto Checker::getInfo(AST::Expression& expression, bool requiresLValue) -> Optional<RecurseInfo> >+auto Checker::getInfo(AST::Expression& expression, bool requiresLeftValue) -> Optional<RecurseInfo> > { > auto typeIterator = m_typeMap.find(&expression); > ASSERT(typeIterator != m_typeMap.end()); > >- auto addressSpaceIterator = m_addressSpaceMap.find(&expression); >- ASSERT(addressSpaceIterator != m_addressSpaceMap.end()); >- if (requiresLValue && !addressSpaceIterator->value) { >+ auto typeAnnotationIterator = m_typeAnnotations.find(&expression); >+ ASSERT(typeAnnotationIterator != m_typeAnnotations.end()); >+ if (requiresLeftValue && typeAnnotationIterator->value.isRightValue()) { > setError(); > return WTF::nullopt; > } >- return {{ typeIterator->value, addressSpaceIterator->value }}; >+ return {{ typeIterator->value, typeAnnotationIterator->value }}; > } > > void Checker::visit(AST::VariableDeclaration& variableDeclaration) >@@ -767,19 +777,32 @@ void Checker::visit(AST::VariableDeclaration& variableDeclaration) > } > } > >-void Checker::assignType(AST::Expression& expression, UniqueRef<AST::UnnamedType>&& unnamedType, Optional<AST::AddressSpace> addressSpace) >+void Checker::assignType(AST::Expression& expression, UniqueRef<AST::UnnamedType>&& unnamedType, AST::TypeAnnotation typeAnnotation = AST::RightValue()) > { > auto addResult = m_typeMap.add(&expression, WTFMove(unnamedType)); > ASSERT_UNUSED(addResult, addResult.isNewEntry); >- auto addressSpaceAddResult = m_addressSpaceMap.add(&expression, addressSpace); >+ auto addressSpaceAddResult = m_typeAnnotations.add(&expression, WTFMove(typeAnnotation)); > ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); > } > >-void Checker::assignType(AST::Expression& expression, RefPtr<ResolvableTypeReference>&& resolvableTypeReference, Optional<AST::AddressSpace> addressSpace) >+void Checker::assignType(AST::Expression& expression, RefPtr<ResolvableTypeReference>&& resolvableTypeReference, AST::TypeAnnotation typeAnnotation = AST::RightValue()) > { > auto addResult = m_typeMap.add(&expression, WTFMove(resolvableTypeReference)); > ASSERT_UNUSED(addResult, addResult.isNewEntry); >- auto addressSpaceAddResult = m_addressSpaceMap.add(&expression, addressSpace); >+ auto addressSpaceAddResult = m_typeAnnotations.add(&expression, WTFMove(typeAnnotation)); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+} >+ >+void Checker::forwardType(AST::Expression& expression, ResolvingType& resolvingType, AST::TypeAnnotation typeAnnotation = AST::RightValue()) >+{ >+ resolvingType.visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& result) { >+ auto addResult = m_typeMap.add(&expression, result->clone()); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ }, [&](RefPtr<ResolvableTypeReference>& result) { >+ auto addResult = m_typeMap.add(&expression, result.copyRef()); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ })); >+ auto addressSpaceAddResult = m_typeAnnotations.add(&expression, WTFMove(typeAnnotation)); > ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); > } > >@@ -789,6 +812,11 @@ void Checker::visit(AST::AssignmentExpression& assignmentExpression) > if (!leftInfo) > return; > >+ if (leftInfo->typeAnnotation.isRightValue()) { >+ setError(); >+ return; >+ } >+ > auto rightInfo = recurseAndGetInfo(assignmentExpression.right()); > if (!rightInfo) > return; >@@ -802,23 +830,10 @@ void Checker::visit(AST::AssignmentExpression& assignmentExpression) > assignType(assignmentExpression, WTFMove(*resultType)); > } > >-void Checker::forwardType(AST::Expression& expression, ResolvingType& resolvingType, Optional<AST::AddressSpace> addressSpace) >-{ >- resolvingType.visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& result) { >- auto addResult = m_typeMap.add(&expression, result->clone()); >- ASSERT_UNUSED(addResult, addResult.isNewEntry); >- }, [&](RefPtr<ResolvableTypeReference>& result) { >- auto addResult = m_typeMap.add(&expression, result.copyRef()); >- ASSERT_UNUSED(addResult, addResult.isNewEntry); >- })); >- auto addressSpaceAddResult = m_addressSpaceMap.add(&expression, addressSpace); >- ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >-} >- > void Checker::visit(AST::ReadModifyWriteExpression& readModifyWriteExpression) > { >- auto lValueInfo = recurseAndGetInfo(readModifyWriteExpression.lValue(), true); >- if (!lValueInfo) >+ auto leftValueInfo = recurseAndGetInfo(readModifyWriteExpression.leftValue(), true); >+ if (!leftValueInfo) > return; > > // FIXME: Figure out what to do with the ReadModifyWriteExpression's AnonymousVariables. >@@ -827,7 +842,7 @@ void Checker::visit(AST::ReadModifyWriteExpression& readModifyWriteExpression) > if (!newValueInfo) > return; > >- if (!matchAndCommit(lValueInfo->resolvingType, newValueInfo->resolvingType)) { >+ if (!matchAndCommit(leftValueInfo->resolvingType, newValueInfo->resolvingType)) { > setError(); > return; > } >@@ -873,37 +888,43 @@ void Checker::visit(AST::DereferenceExpression& dereferenceExpression) > return; > } > >- assignType(dereferenceExpression, pointerType->clone(), pointerType->addressSpace()); >+ assignType(dereferenceExpression, pointerType->clone(), AST::LeftValue { pointerType->addressSpace() }); > } > > void Checker::visit(AST::MakePointerExpression& makePointerExpression) > { >- auto lValueInfo = recurseAndGetInfo(makePointerExpression.lValue(), true); >- if (!lValueInfo) >+ auto leftValueInfo = recurseAndGetInfo(makePointerExpression.leftValue(), true); >+ if (!leftValueInfo) >+ return; >+ >+ auto leftAddressSpace = leftValueInfo->typeAnnotation.leftAddressSpace(); >+ if (!leftAddressSpace) { >+ setError(); > return; >+ } > >- auto* lValueType = getUnnamedType(lValueInfo->resolvingType); >- if (!lValueType) { >+ auto* leftValueType = getUnnamedType(leftValueInfo->resolvingType); >+ if (!leftValueType) { > setError(); > return; > } > >- assignType(makePointerExpression, makeUniqueRef<AST::PointerType>(Lexer::Token(makePointerExpression.origin()), *lValueInfo->addressSpace, lValueType->clone())); >+ assignType(makePointerExpression, makeUniqueRef<AST::PointerType>(Lexer::Token(makePointerExpression.origin()), *leftAddressSpace, leftValueType->clone())); > } > > void Checker::visit(AST::MakeArrayReferenceExpression& makeArrayReferenceExpression) > { >- auto lValueInfo = recurseAndGetInfo(makeArrayReferenceExpression.lValue()); >- if (!lValueInfo) >+ auto leftValueInfo = recurseAndGetInfo(makeArrayReferenceExpression.leftValue()); >+ if (!leftValueInfo) > return; > >- auto* lValueType = getUnnamedType(lValueInfo->resolvingType); >- if (!lValueType) { >+ auto* leftValueType = getUnnamedType(leftValueInfo->resolvingType); >+ if (!leftValueType) { > setError(); > return; > } > >- auto& unifyNode = lValueType->unifyNode(); >+ auto& unifyNode = leftValueType->unifyNode(); > if (is<AST::UnnamedType>(unifyNode)) { > auto& unnamedType = downcast<AST::UnnamedType>(unifyNode); > if (is<AST::PointerType>(unnamedType)) { >@@ -913,7 +934,8 @@ void Checker::visit(AST::MakeArrayReferenceExpression& makeArrayReferenceExpress > return; > } > >- if (!lValueInfo->addressSpace) { >+ auto leftAddressSpace = leftValueInfo->typeAnnotation.leftAddressSpace(); >+ if (!leftAddressSpace) { > setError(); > return; > } >@@ -921,183 +943,112 @@ void Checker::visit(AST::MakeArrayReferenceExpression& makeArrayReferenceExpress > if (is<AST::ArrayType>(unnamedType)) { > auto& arrayType = downcast<AST::ArrayType>(unnamedType); > // FIXME: Save the number of elements. >- assignType(makeArrayReferenceExpression, makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(makeArrayReferenceExpression.origin()), *lValueInfo->addressSpace, arrayType.type().clone())); >+ assignType(makeArrayReferenceExpression, makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(makeArrayReferenceExpression.origin()), *leftAddressSpace, arrayType.type().clone())); > return; > } > } > >- if (!lValueInfo->addressSpace) { >+ auto leftAddressSpace = leftValueInfo->typeAnnotation.leftAddressSpace(); >+ if (!leftAddressSpace) { > setError(); > return; > } > >- assignType(makeArrayReferenceExpression, makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(makeArrayReferenceExpression.origin()), *lValueInfo->addressSpace, lValueType->clone())); >+ assignType(makeArrayReferenceExpression, makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(makeArrayReferenceExpression.origin()), *leftAddressSpace, leftValueType->clone())); > } > >-void Checker::finishVisitingPropertyAccess(AST::PropertyAccessExpression& propertyAccessExpression, AST::UnnamedType& wrappedBaseType, AST::UnnamedType* extraArgumentType) >+void Checker::visit(AST::DotExpression& dotExpression) > { >- using OverloadResolution = std::tuple<AST::FunctionDeclaration*, AST::UnnamedType*>; >- >- AST::FunctionDeclaration* getFunction; >- AST::UnnamedType* getReturnType; >- std::tie(getFunction, getReturnType) = ([&]() -> OverloadResolution { >- ResolvingType getArgumentType1(wrappedBaseType.clone()); >- Optional<ResolvingType> getArgumentType2; >- if (extraArgumentType) >- getArgumentType2 = ResolvingType(extraArgumentType->clone()); >+ auto baseInfo = recurseAndGetInfo(dotExpression.base()); >+ if (!baseInfo) >+ return; >+ auto baseUnnamedType = commit(baseInfo->resolvingType); >+ if (!baseUnnamedType) >+ return; > >+ AST::FunctionDeclaration* getFunction = nullptr; >+ AST::UnnamedType* getReturnType = nullptr; >+ { > Vector<std::reference_wrapper<ResolvingType>> getArgumentTypes; >- getArgumentTypes.append(getArgumentType1); >- if (getArgumentType2) >- getArgumentTypes.append(*getArgumentType2); >- >- auto* getFunction = resolveFunctionOverloadImpl(propertyAccessExpression.possibleGetOverloads(), getArgumentTypes, nullptr); >- if (!getFunction) >- return std::make_pair(nullptr, nullptr); >- return std::make_pair(getFunction, &getFunction->type()); >- })(); >- >- AST::FunctionDeclaration* andFunction; >- AST::UnnamedType* andReturnType; >- std::tie(andFunction, andReturnType) = ([&]() -> OverloadResolution { >- auto computeAndArgumentType = [&](AST::UnnamedType& unnamedType) -> Optional<ResolvingType> { >- if (is<AST::ArrayReferenceType>(unnamedType)) >- return { unnamedType.clone() }; >- if (is<AST::ArrayType>(unnamedType)) >- return { ResolvingType(makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(propertyAccessExpression.origin()), AST::AddressSpace::Thread, downcast<AST::ArrayType>(unnamedType).type().clone())) }; >- if (is<AST::PointerType>(unnamedType)) >- return WTF::nullopt; >- return { ResolvingType(makeUniqueRef<AST::PointerType>(Lexer::Token(propertyAccessExpression.origin()), AST::AddressSpace::Thread, downcast<AST::TypeReference>(unnamedType).clone())) }; >- }; >- auto computeAndReturnType = [&](AST::UnnamedType& unnamedType) -> AST::UnnamedType* { >- if (is<AST::PointerType>(unnamedType)) >- return &downcast<AST::PointerType>(unnamedType).elementType(); >- return nullptr; >- }; >- >- auto andArgumentType1 = computeAndArgumentType(wrappedBaseType); >- if (!andArgumentType1) >- return std::make_pair(nullptr, nullptr); >- Optional<ResolvingType> andArgumentType2; >- if (extraArgumentType) >- andArgumentType2 = ResolvingType(extraArgumentType->clone()); >+ getArgumentTypes.append(baseInfo->resolvingType); >+ getFunction = resolveFunctionOverloadImpl(dotExpression.possibleGetOverloads(), getArgumentTypes, nullptr); >+ if (getFunction) >+ getReturnType = &getFunction->type(); >+ } > >+ AST::FunctionDeclaration* andFunction = nullptr; >+ AST::UnnamedType* andReturnType = nullptr; >+ if (auto leftAddressSpace = baseInfo->typeAnnotation.leftAddressSpace()) { >+ auto argumentType = makeUniqueRef<AST::PointerType>(Lexer::Token(dotExpression.origin()), *leftAddressSpace, baseUnnamedType->get().clone()); > Vector<std::reference_wrapper<ResolvingType>> andArgumentTypes; >- andArgumentTypes.append(*andArgumentType1); >- if (andArgumentType2) >- andArgumentTypes.append(*andArgumentType2); >- >- auto* andFunction = resolveFunctionOverloadImpl(propertyAccessExpression.possibleAndOverloads(), andArgumentTypes, nullptr); >- if (!andFunction) >- return std::make_pair(nullptr, nullptr); >- return std::make_pair(andFunction, computeAndReturnType(andFunction->type())); >- })(); >+ andArgumentTypes.append(baseInfo->resolvingType); >+ andFunction = resolveFunctionOverloadImpl(dotExpression.possibleAndOverloads(), andArgumentTypes, nullptr); >+ if (andFunction) >+ andReturnType = &downcast<AST::PointerType>(andFunction->type()).elementType(); // FIXME: Enforce the return of anders will always be a pointer >+ } >+ >+ AST::FunctionDeclaration* threadAndFunction = nullptr; >+ AST::UnnamedType* threadAndReturnType = nullptr; >+ { >+ auto argumentType = makeUniqueRef<AST::PointerType>(Lexer::Token(dotExpression.origin()), AST::AddressSpace::Thread, baseUnnamedType->get().clone()); >+ Vector<std::reference_wrapper<ResolvingType>> threadAndArgumentTypes; >+ threadAndArgumentTypes.append(baseInfo->resolvingType); >+ threadAndFunction = resolveFunctionOverloadImpl(dotExpression.possibleAndOverloads(), threadAndArgumentTypes, nullptr); >+ if (threadAndFunction) >+ threadAndReturnType = &downcast<AST::PointerType>(threadAndFunction->type()).elementType(); // FIXME: Enforce the return of anders will always be a pointer >+ } > >- if (!getReturnType && !andReturnType) { >+ if (!getFunction && !andFunction) { > setError(); > return; > } >- >- if (getReturnType && andReturnType && !matches(*getReturnType, *andReturnType)) { >+ if (getFunction && andFunction) { >+ setError(); >+ return; >+ } >+ if (andFunction && threadAndFunction && !matches(*andReturnType, *threadAndReturnType)) { > setError(); > return; > } > >- AST::FunctionDeclaration* setFunction; >- AST::UnnamedType* setReturnType; >- std::tie(setFunction, setReturnType) = ([&]() -> OverloadResolution { >- ResolvingType setArgument1Type(wrappedBaseType.clone()); >- Optional<ResolvingType> setArgumentType2; >- if (extraArgumentType) >- setArgumentType2 = ResolvingType(extraArgumentType->clone()); >- ResolvingType setArgument3Type(getReturnType ? getReturnType->clone() : andReturnType->clone()); >+ AST::UnnamedType* fieldType = getReturnType ? getReturnType : andReturnType; > >+ AST::FunctionDeclaration* setFunction = nullptr; >+ AST::UnnamedType* setReturnType = nullptr; >+ { > Vector<std::reference_wrapper<ResolvingType>> setArgumentTypes; >- setArgumentTypes.append(setArgument1Type); >- if (setArgumentType2) >- setArgumentTypes.append(*setArgumentType2); >- setArgumentTypes.append(setArgument3Type); >- >- auto* setFunction = resolveFunctionOverloadImpl(propertyAccessExpression.possibleSetOverloads(), setArgumentTypes, nullptr); >- if (!setFunction) >- return std::make_pair(nullptr, nullptr); >- return std::make_pair(setFunction, &setFunction->type()); >- })(); >- >- if (setFunction) { >- if (!matches(setFunction->type(), wrappedBaseType)) { >- setError(); >- return; >- } >- } >- >- Optional<AST::AddressSpace> addressSpace; >- if (getReturnType || andReturnType) { >- // FIXME: The reference compiler has "else if (!node.base.isLValue && !baseType.isArrayRef)", >- // but I don't understand why it exists. I haven't written it here, and I'll investigate >- // if we can remove it from the reference compiler. >- if (is<AST::ReferenceType>(wrappedBaseType)) >- addressSpace = downcast<AST::ReferenceType>(wrappedBaseType).addressSpace(); >- else { >- auto addressSpaceIterator = m_addressSpaceMap.find(&propertyAccessExpression.base()); >- ASSERT(addressSpaceIterator != m_addressSpaceMap.end()); >- if (addressSpaceIterator->value) >- addressSpace = *addressSpaceIterator->value; >- else { >- setError(); >- return; >- } >- } >+ setArgumentTypes.append(baseInfo->resolvingType); >+ ResolvingType fieldResolvingType(fieldType->clone()); >+ setArgumentTypes.append(fieldResolvingType); >+ setFunction = resolveFunctionOverloadImpl(dotExpression.possibleSetOverloads(), setArgumentTypes, nullptr); >+ if (setFunction) >+ setReturnType = &setFunction->type(); > } > >- // FIXME: Generate the call expressions >- >- assignType(propertyAccessExpression, getReturnType ? getReturnType->clone() : andReturnType->clone(), addressSpace); >-} >- >-Optional<UniqueRef<AST::UnnamedType>> Checker::recurseAndWrapBaseType(AST::PropertyAccessExpression& propertyAccessExpression) >-{ >- auto baseInfo = recurseAndGetInfo(propertyAccessExpression.base()); >- if (!baseInfo) >- return WTF::nullopt; >- >- auto* baseType = getUnnamedType(baseInfo->resolvingType); >- if (!baseType) { >+ if (setFunction && andFunction) { > setError(); >- return WTF::nullopt; >- } >- auto& baseUnifyNode = baseType->unifyNode(); >- if (is<AST::UnnamedType>(baseUnifyNode)) >- return downcast<AST::UnnamedType>(baseUnifyNode).clone(); >- ASSERT(is<AST::NamedType>(baseUnifyNode)); >- return { AST::TypeReference::wrap(Lexer::Token(propertyAccessExpression.origin()), downcast<AST::NamedType>(baseUnifyNode)) }; >-} >- >-void Checker::visit(AST::DotExpression& dotExpression) >-{ >- auto baseType = recurseAndWrapBaseType(dotExpression); >- if (!baseType) > return; >+ } > >- finishVisitingPropertyAccess(dotExpression, *baseType); >+ dotExpression.setGetFunction(getFunction); >+ dotExpression.setAndFunction(andFunction); >+ dotExpression.setThreadAndFunction(threadAndFunction); >+ dotExpression.setSetFunction(setFunction); >+ >+ AST::TypeAnnotation typeAnnotation = AST::RightValue(); >+ if (auto leftAddressSpace = baseInfo->typeAnnotation.leftAddressSpace()) { >+ if (andFunction) >+ typeAnnotation = AST::LeftValue { *leftAddressSpace }; >+ else if (setFunction) >+ typeAnnotation = AST::AbstractLeftValue(); >+ } else if (!baseInfo->typeAnnotation.isRightValue() && (setFunction || andFunction)) >+ typeAnnotation = AST::AbstractLeftValue(); >+ assignType(dotExpression, fieldType->clone(), WTFMove(typeAnnotation)); > } > >-void Checker::visit(AST::IndexExpression& indexExpression) >+void Checker::visit(AST::IndexExpression&) > { >- auto baseType = recurseAndWrapBaseType(indexExpression); >- if (!baseType) >- return; >- >- auto indexInfo = recurseAndGetInfo(indexExpression.indexExpression()); >- if (!indexInfo) >- return; >- auto indexExpressionType = getUnnamedType(indexInfo->resolvingType); >- if (!indexExpressionType) { >- setError(); >- return; >- } >- >- finishVisitingPropertyAccess(indexExpression, WTFMove(*baseType), indexExpressionType); >+ // FIXME: Implement this. > } > > void Checker::visit(AST::VariableReference& variableReference) >@@ -1105,10 +1056,10 @@ void Checker::visit(AST::VariableReference& variableReference) > ASSERT(variableReference.variable()); > ASSERT(variableReference.variable()->type()); > >- Optional<AST::AddressSpace> addressSpace; >- if (!variableReference.variable()->isAnonymous()) >- addressSpace = AST::AddressSpace::Thread; >- assignType(variableReference, variableReference.variable()->type()->clone(), addressSpace); >+ AST::TypeAnnotation typeAnnotation = AST::RightValue(); >+ if (!variableReference.variable()->isAnonymous()) // FIXME: This doesn't seem right. >+ typeAnnotation = AST::LeftValue { AST::AddressSpace::Thread }; >+ assignType(variableReference, variableReference.variable()->type()->clone(), WTFMove(typeAnnotation)); > } > > void Checker::visit(AST::Return& returnStatement) >@@ -1407,7 +1358,7 @@ void Checker::visit(AST::CommaExpression& commaExpression) > if (error()) > return; > auto lastInfo = getInfo(commaExpression.list().last()); >- forwardType(commaExpression, lastInfo->resolvingType); >+ forwardType(commaExpression, lastInfo->resolvingType, lastInfo->typeAnnotation); > } > > void Checker::visit(AST::TernaryExpression& ternaryExpression) >@@ -1456,7 +1407,7 @@ void Checker::visit(AST::CallExpression& callExpression) > } > > for (size_t i = 0; i < function->parameters().size(); ++i) { >- if (!matchAndCommit(types[i].get(), *function->parameters()[i].type())) { >+ if (!matchAndCommit(types[i].get(), *function->parameters()[i]->type())) { > setError(); > return; > } >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.cpp >index 2fcc6f139de84a32c4c707ca060b9be1b42fd3e0..158e23b472de49931eb7842c97b84aa23d0970e4 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.cpp >@@ -227,9 +227,9 @@ bool inferTypesForCall(AST::FunctionDeclaration& possibleFunction, Vector<std::r > return false; > for (size_t i = 0; i < possibleFunction.parameters().size(); ++i) { > auto success = argumentTypes[i].get().visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& unnamedType) -> bool { >- return matches(*possibleFunction.parameters()[i].type(), unnamedType); >+ return matches(*possibleFunction.parameters()[i]->type(), unnamedType); > }, [&](RefPtr<ResolvableTypeReference>& resolvableTypeReference) -> bool { >- return resolvableTypeReference->resolvableType().canResolve(possibleFunction.parameters()[i].type()->unifyNode()); >+ return resolvableTypeReference->resolvableType().canResolve(possibleFunction.parameters()[i]->type()->unifyNode()); > })); > if (!success) > return false; >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp >index 05350e0dc985ecb390f586f0a34d2a6ecfedca32..3cbedd9c25788fe5de05612ff0dd26d4c854f7e3 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp >@@ -197,9 +197,10 @@ void NameResolver::visit(AST::DotExpression& dotExpression) > static_assert(sizeof(AST::EnumerationMemberLiteral) <= sizeof(AST::DotExpression), "Dot expressions need to be able to become EnumerationMemberLiterals without updating backreferences"); > Lexer::Token origin = dotExpression.origin(); > // FIXME: Perhaps do this with variants or a Rewriter instead. >+ void* location = &dotExpression; > dotExpression.~DotExpression(); > auto enumerationMemberLiteral = AST::EnumerationMemberLiteral::wrap(WTFMove(origin), WTFMove(baseName), WTFMove(memberName), enumerationDefinition, *member); >- new (&dotExpression) AST::EnumerationMemberLiteral(WTFMove(enumerationMemberLiteral)); >+ new (location) AST::EnumerationMemberLiteral(WTFMove(enumerationMemberLiteral)); > return; > } > setError(); >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp >index 39dd7a2a1bab0a97b09398e507e4887187e9ad6b..a97789790307468cf6f0f30b100d5ff5e97a6b4e 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp >@@ -1082,13 +1082,13 @@ auto Parser::parseParameters() -> Expected<AST::VariableDeclarations, Error> > auto firstParameter = parseParameter(); > if (!firstParameter) > return Unexpected<Error>(firstParameter.error()); >- parameters.append(WTFMove(*firstParameter)); >+ parameters.append(makeUniqueRef<AST::VariableDeclaration>(WTFMove(*firstParameter))); > > while (tryType(Lexer::Token::Type::Comma)) { > auto parameter = parseParameter(); > if (!parameter) > return Unexpected<Error>(parameter.error()); >- parameters.append(WTFMove(*parameter)); >+ parameters.append(makeUniqueRef<AST::VariableDeclaration>(WTFMove(*parameter))); > } > > auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >@@ -1567,14 +1567,14 @@ auto Parser::parseVariableDeclarations() -> Expected<AST::VariableDeclarationsSt > if (!firstVariableDeclaration) > return Unexpected<Error>(firstVariableDeclaration.error()); > >- Vector<AST::VariableDeclaration> result; >- result.append(WTFMove(*firstVariableDeclaration)); >+ Vector<UniqueRef<AST::VariableDeclaration>> result; >+ result.append(makeUniqueRef<AST::VariableDeclaration>(WTFMove(*firstVariableDeclaration))); > > while (tryType(Lexer::Token::Type::Comma)) { > auto variableDeclaration = parseVariableDeclaration((*type)->clone()); > if (!variableDeclaration) > return Unexpected<Error>(variableDeclaration.error()); >- result.append(WTFMove(*variableDeclaration)); >+ result.append(makeUniqueRef<AST::VariableDeclaration>(WTFMove(*variableDeclaration))); > } > > return AST::VariableDeclarationsStatement(WTFMove(*origin), WTFMove(result)); >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp >index 9a1035a4b8cad33a21e670f2200591cc148d6b13..869b7c38cdb4a9dcc1b2941964be9d681ad8e088 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp >@@ -37,6 +37,7 @@ > #include "WHLSLNameResolver.h" > #include "WHLSLParser.h" > #include "WHLSLProgram.h" >+#include "WHLSLPropertyResolver.h" > #include "WHLSLRecursionChecker.h" > #include "WHLSLRecursiveTypeChecker.h" > #include "WHLSLSemanticMatcher.h" >@@ -82,7 +83,7 @@ static Optional<Program> prepareShared(String& whlslSource) > if (!check(program)) > return WTF::nullopt; > checkLiteralTypes(program); >- // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195788 Resolve properties here >+ resolveProperties(program); > findHighZombies(program); > if (!checkStatementBehavior(program)) > return WTF::nullopt; >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..3deaa0275fd9f70a8c1479b0cd152c874804b456 >--- /dev/null >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp >@@ -0,0 +1,762 @@ >+/* >+ * Copyright (C) 2019 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. AND ITS CONTRIBUTORS ``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 ITS 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. >+ */ >+ >+#include "config.h" >+#include "WHLSLPropertyResolver.h" >+ >+#if ENABLE(WEBGPU) >+ >+#include "WHLSLAssignmentExpression.h" >+#include "WHLSLCallExpression.h" >+#include "WHLSLCommaExpression.h" >+#include "WHLSLDereferenceExpression.h" >+#include "WHLSLDotExpression.h" >+#include "WHLSLFunctionDeclaration.h" >+#include "WHLSLFunctionDefinition.h" >+#include "WHLSLMakePointerExpression.h" >+#include "WHLSLPointerType.h" >+#include "WHLSLReadModifyWriteExpression.h" >+#include "WHLSLVariableDeclaration.h" >+#include "WHLSLVariableReference.h" >+#include "WHLSLVisitor.h" >+ >+namespace WebCore { >+ >+namespace WHLSL { >+ >+class PropertyResolver : public Visitor { >+public: >+private: >+ void visit(AST::FunctionDefinition&) override; >+ void visit(AST::DotExpression&) override; >+ void visit(AST::AssignmentExpression&) override; >+ void visit(AST::ReadModifyWriteExpression&) override; >+ >+ bool simplifyRightValue(AST::DotExpression&); >+ bool simplifyAbstractLeftValue(AST::AssignmentExpression&, AST::DotExpression&, UniqueRef<AST::Expression>&& right); >+ void simplifyLeftValue(AST::Expression&); >+ >+ AST::VariableDeclarations m_variableDeclarations; >+}; >+ >+void PropertyResolver::visit(AST::DotExpression& dotExpression) >+{ >+ // Unless we're inside an AssignmentExpression or a ReadModifyWriteExpression, we're a right value. >+ if (!simplifyRightValue(dotExpression)) >+ setError(); >+} >+ >+void PropertyResolver::visit(AST::FunctionDefinition& functionDefinition) >+{ >+ Visitor::visit(functionDefinition); >+ if (!m_variableDeclarations.isEmpty()) >+ functionDefinition.block().statements().insert(0, makeUniqueRef<AST::VariableDeclarationsStatement>(Lexer::Token(m_variableDeclarations[0]->origin()), WTFMove(m_variableDeclarations))); >+} >+ >+static Optional<UniqueRef<AST::Expression>> setterCall(AST::DotExpression& dotExpression, UniqueRef<AST::Expression>&& newValue, const std::function<UniqueRef<AST::Expression>()>& leftValueFactory, const std::function<UniqueRef<AST::Expression>()>& pointerToLeftValueFactory) >+{ >+ if (dotExpression.andFunction()) { >+ // *operator&.foo(&v) = newValue >+ if (!dotExpression.threadAndFunction()) >+ return WTF::nullopt; >+ >+ Vector<UniqueRef<AST::Expression>> arguments; >+ arguments.append(pointerToLeftValueFactory()); >+ auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(dotExpression.origin()), String(dotExpression.threadAndFunction()->name()), WTFMove(arguments)); >+ callExpression->setType(dotExpression.threadAndFunction()->type().clone()); >+ callExpression->setTypeAnnotation(AST::RightValue()); >+ callExpression->setFunction(*dotExpression.threadAndFunction()); >+ >+ auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(Lexer::Token(dotExpression.origin()), WTFMove(callExpression)); >+ dereferenceExpression->setType(downcast<AST::PointerType>(dotExpression.threadAndFunction()->type()).elementType().clone()); >+ dereferenceExpression->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); >+ >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(dotExpression.origin()), WTFMove(dereferenceExpression), WTFMove(newValue)); >+ assignmentExpression->setType(downcast<AST::PointerType>(dotExpression.threadAndFunction()->type()).elementType().clone()); >+ assignmentExpression->setTypeAnnotation(AST::RightValue()); >+ >+ return UniqueRef<AST::Expression>(WTFMove(assignmentExpression)); >+ } >+ >+ // v = operator.foo=(v, newValue) >+ ASSERT(dotExpression.setFunction()); >+ >+ Vector<UniqueRef<AST::Expression>> arguments; >+ arguments.append(leftValueFactory()); >+ arguments.append(WTFMove(newValue)); >+ auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(dotExpression.origin()), String(dotExpression.setFunction()->name()), WTFMove(arguments)); >+ callExpression->setType(dotExpression.setFunction()->type().clone()); >+ callExpression->setTypeAnnotation(AST::RightValue()); >+ callExpression->setFunction(*dotExpression.setFunction()); >+ >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(dotExpression.origin()), leftValueFactory(), WTFMove(callExpression)); >+ assignmentExpression->setType(dotExpression.setFunction()->type().clone()); >+ assignmentExpression->setTypeAnnotation(AST::RightValue()); >+ >+ return UniqueRef<AST::Expression>(WTFMove(assignmentExpression)); >+} >+ >+static Optional<UniqueRef<AST::Expression>> getterCall(AST::DotExpression& dotExpression, const std::function<UniqueRef<AST::Expression>()>& leftValueFactory, const std::function<UniqueRef<AST::Expression>()>& pointerToLeftValueFactory) >+{ >+ if (dotExpression.andFunction()) { >+ // *operator&.foo(&v) >+ if (!dotExpression.threadAndFunction()) >+ return WTF::nullopt; >+ >+ Vector<UniqueRef<AST::Expression>> arguments; >+ arguments.append(pointerToLeftValueFactory()); >+ auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(dotExpression.origin()), String(dotExpression.threadAndFunction()->name()), WTFMove(arguments)); >+ callExpression->setType(dotExpression.threadAndFunction()->type().clone()); >+ callExpression->setTypeAnnotation(AST::RightValue()); >+ callExpression->setFunction(*dotExpression.threadAndFunction()); >+ >+ auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(Lexer::Token(dotExpression.origin()), WTFMove(callExpression)); >+ dereferenceExpression->setType(downcast<AST::PointerType>(dotExpression.threadAndFunction()->type()).elementType().clone()); >+ dereferenceExpression->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); >+ >+ return UniqueRef<AST::Expression>(WTFMove(dereferenceExpression)); >+ } >+ >+ // operator.foo(v) >+ ASSERT(dotExpression.getFunction()); >+ >+ Vector<UniqueRef<AST::Expression>> arguments; >+ arguments.append(leftValueFactory()); >+ auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(dotExpression.origin()), String(dotExpression.getFunction()->name()), WTFMove(arguments)); >+ callExpression->setType(dotExpression.getFunction()->type().clone()); >+ callExpression->setTypeAnnotation(AST::RightValue()); >+ callExpression->setFunction(*dotExpression.getFunction()); >+ >+ return UniqueRef<AST::Expression>(WTFMove(callExpression)); >+} >+ >+struct ModifyResult { >+ AST::Expression& innerLeftValue; >+ Vector<UniqueRef<AST::Expression>> expressions; >+ Vector<UniqueRef<AST::VariableDeclaration>> variableDeclarations; >+}; >+struct ModificationResult { >+ Vector<UniqueRef<AST::Expression>> expressions; >+ UniqueRef<AST::Expression> result; >+}; >+static Optional<ModifyResult> modify(AST::DotExpression& dotExpression, std::function<Optional<ModificationResult>(Optional<UniqueRef<AST::Expression>>&&)> modification) >+{ >+ // Consider a.b.c.d++; >+ // This would get transformed into: >+ // >+ // Step 1: >+ // p = &a; >+ // >+ // Step 2: >+ // q = operator.b(*p); >+ // r = operator.c(q); >+ // >+ // Step 3: >+ // oldValue = operator.d(r); >+ // newValue = ...; >+ // >+ // Step 4: >+ // r = operator.d=(r, newValue); >+ // q = operator.c=(q, r); >+ // >+ // Step 4: >+ // *p = operator.b=(*p, q); >+ >+ // If the expression is a.b.c.d = e, Step 3 disappears and "newValue" in step 4 becomes "e". >+ >+ >+ // Find the ".b" ".c" and ".d" expressions. >+ Vector<std::reference_wrapper<AST::DotExpression>> chain; >+ AST::DotExpression* iterator = &dotExpression; >+ while (true) { >+ chain.append(*iterator); >+ ASSERT(iterator->base().typeAnnotation()); >+ if (iterator->base().typeAnnotation()->leftAddressSpace()) >+ break; >+ ASSERT(!iterator->base().typeAnnotation()->isRightValue()); >+ ASSERT(is<AST::DotExpression>(iterator->base())); // FIXME: Make this work with index expressions >+ iterator = &downcast<AST::DotExpression>(iterator->base()); >+ } >+ auto leftExpression = iterator->takeBase(); >+ AST::Expression& innerLeftExpression = leftExpression; >+ >+ // Create "p" variable. >+ ASSERT(leftExpression->resolvedType()); >+ auto pointerVariable = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(leftExpression->origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(makeUniqueRef<AST::PointerType>(Lexer::Token(leftExpression->origin()), *leftExpression->typeAnnotation()->leftAddressSpace(), leftExpression->resolvedType()->clone())), String(), WTF::nullopt, WTF::nullopt); >+ >+ // Create "q" and "r" variables. >+ Vector<UniqueRef<AST::VariableDeclaration>> intermediateVariables; >+ intermediateVariables.reserveInitialCapacity(chain.size() - 1); >+ for (size_t i = 1; i < chain.size(); ++i) { >+ auto& dotExpression = static_cast<AST::DotExpression&>(chain[i]); >+ ASSERT(dotExpression.resolvedType()); >+ intermediateVariables.uncheckedAppend(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(dotExpression.origin()), AST::Qualifiers(), dotExpression.resolvedType()->clone(), String(), WTF::nullopt, WTF::nullopt)); >+ } >+ >+ Vector<UniqueRef<AST::Expression>> expressions; >+ >+ // Step 1: >+ { >+ auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(innerLeftExpression.origin()), WTFMove(leftExpression)); >+ makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(innerLeftExpression.origin()), *innerLeftExpression.typeAnnotation()->leftAddressSpace(), innerLeftExpression.resolvedType()->clone())); >+ makePointerExpression->setTypeAnnotation(AST::RightValue()); >+ >+ auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable)); >+ ASSERT(pointerVariable->type()); >+ variableReference->setType(pointerVariable->type()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(innerLeftExpression.origin()), WTFMove(variableReference), WTFMove(makePointerExpression)); >+ assignmentExpression->setType(pointerVariable->type()->clone()); >+ assignmentExpression->setTypeAnnotation(AST::RightValue()); >+ >+ expressions.append(WTFMove(assignmentExpression)); >+ } >+ >+ // Step 2: >+ AST::VariableDeclaration* previous = nullptr; >+ auto previousLeftValue = [&]() -> UniqueRef<AST::Expression> { >+ if (previous) { >+ auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(*previous)); >+ ASSERT(previous->type()); >+ variableReference->setType(previous->type()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ return variableReference; >+ } >+ >+ auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable)); >+ ASSERT(pointerVariable->type()); >+ variableReference->setType(pointerVariable->type()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ >+ auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(Lexer::Token(dotExpression.origin()), WTFMove(variableReference)); >+ ASSERT(pointerVariable->type()); >+ dereferenceExpression->setType(downcast<AST::PointerType>(*pointerVariable->type()).elementType().clone()); >+ dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(*pointerVariable->type()).addressSpace() }); >+ return dereferenceExpression; >+ }; >+ auto pointerToPreviousLeftValue = [&]() -> UniqueRef<AST::Expression> { >+ if (previous) { >+ auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(*previous)); >+ ASSERT(previous->type()); >+ variableReference->setType(previous->type()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ >+ auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(dotExpression.origin()), WTFMove(variableReference)); >+ ASSERT(previous->type()); >+ makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(dotExpression.origin()), AST::AddressSpace::Thread, previous->type()->clone())); >+ makePointerExpression->setTypeAnnotation(AST::RightValue()); >+ return makePointerExpression; >+ } >+ >+ auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable)); >+ ASSERT(pointerVariable->type()); >+ variableReference->setType(pointerVariable->type()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ return variableReference; >+ }; >+ for (size_t i = chain.size() - 1; i > 0; --i) { >+ AST::DotExpression& dotExpression = chain[i]; >+ AST::VariableDeclaration& variableDeclaration = intermediateVariables[i - 1]; >+ >+ auto callExpression = getterCall(dotExpression, previousLeftValue, pointerToPreviousLeftValue); >+ >+ if (!callExpression) >+ return WTF::nullopt; >+ >+ auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration)); >+ ASSERT(variableDeclaration.type()); >+ variableReference->setType(variableDeclaration.type()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(dotExpression.origin()), WTFMove(variableReference), WTFMove(*callExpression)); >+ assignmentExpression->setType(variableDeclaration.type()->clone()); >+ assignmentExpression->setTypeAnnotation(AST::RightValue()); >+ >+ expressions.append(WTFMove(assignmentExpression)); >+ >+ previous = &variableDeclaration; >+ } >+ auto lastGetterCallExpression = getterCall(chain[0], previousLeftValue, pointerToPreviousLeftValue); >+ >+ // ModificationResult(UniqueRef<AST::Expression>&&) >+ // Step 3: >+ auto modificationResult = modification(WTFMove(lastGetterCallExpression)); >+ if (!modificationResult) >+ return WTF::nullopt; >+ for (size_t i = 0; i < modificationResult->expressions.size(); ++i) >+ expressions.append(WTFMove(modificationResult->expressions[i])); >+ >+ // Step 4: >+ UniqueRef<AST::Expression> rightValue = WTFMove(modificationResult->result); >+ ASSERT(rightValue->resolvedType()); >+ auto expressionType = rightValue->resolvedType()->clone(); >+ for (size_t i = 0; i < chain.size() - 1; ++i) { >+ AST::DotExpression& dotExpression = chain[i]; >+ AST::VariableDeclaration& variableDeclaration = intermediateVariables[i]; >+ >+ auto assignmentExpression = setterCall(dotExpression, WTFMove(rightValue), [&]() -> UniqueRef<AST::Expression> { >+ auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration)); >+ ASSERT(variableDeclaration.type()); >+ variableReference->setType(variableDeclaration.type()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ return variableReference; >+ }, [&]() -> UniqueRef<AST::Expression> { >+ auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration)); >+ ASSERT(variableDeclaration.type()); >+ variableReference->setType(variableDeclaration.type()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ >+ auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(dotExpression.origin()), WTFMove(variableReference)); >+ ASSERT(variableDeclaration.type()); >+ makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(dotExpression.origin()), AST::AddressSpace::Thread, variableDeclaration.type()->clone())); >+ makePointerExpression->setTypeAnnotation(AST::RightValue()); >+ return makePointerExpression; >+ }); >+ >+ if (!assignmentExpression) >+ return WTF::nullopt; >+ >+ expressions.append(WTFMove(*assignmentExpression)); >+ >+ rightValue = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration)); >+ ASSERT(variableDeclaration.type()); >+ rightValue->setType(variableDeclaration.type()->clone()); >+ rightValue->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ } >+ >+ // Step 5: >+ { >+ auto assignmentExpression = setterCall(chain[chain.size() - 1], WTFMove(rightValue), [&]() -> UniqueRef<AST::Expression> { >+ auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable)); >+ ASSERT(pointerVariable->type()); >+ variableReference->setType(pointerVariable->type()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ >+ auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(Lexer::Token(dotExpression.origin()), WTFMove(variableReference)); >+ ASSERT(pointerVariable->type()); >+ dereferenceExpression->setType(downcast<AST::PointerType>(*pointerVariable->type()).elementType().clone()); >+ dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(*pointerVariable->type()).addressSpace() }); >+ return dereferenceExpression; >+ }, [&]() -> UniqueRef<AST::Expression> { >+ auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable)); >+ ASSERT(pointerVariable->type()); >+ variableReference->setType(pointerVariable->type()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ return variableReference; >+ }); >+ >+ if (!assignmentExpression) >+ return WTF::nullopt; >+ >+ expressions.append(WTFMove(*assignmentExpression)); >+ } >+ >+ Vector<UniqueRef<AST::VariableDeclaration>> variableDeclarations; >+ variableDeclarations.append(WTFMove(pointerVariable)); >+ for (auto& intermediateVariable : intermediateVariables) >+ variableDeclarations.append(WTFMove(intermediateVariable)); >+ >+ return {{ innerLeftExpression, WTFMove(expressions), WTFMove(variableDeclarations) }}; >+} >+ >+void PropertyResolver::visit(AST::AssignmentExpression& assignmentExpression) >+{ >+ ASSERT(assignmentExpression.left().typeAnnotation()); >+ if (assignmentExpression.left().typeAnnotation()->leftAddressSpace()) { >+ simplifyLeftValue(assignmentExpression.left()); >+ checkErrorAndVisit(assignmentExpression.right()); >+ return; >+ } >+ ASSERT(!assignmentExpression.left().typeAnnotation()->isRightValue()); >+ if (!is<AST::DotExpression>(assignmentExpression.left())) { >+ setError(); // FIXME: Make this work with index expressions. >+ return; >+ } >+ >+ ASSERT(assignmentExpression.right().resolvedType()); >+ auto type = assignmentExpression.right().resolvedType()->clone(); >+ >+ checkErrorAndVisit(assignmentExpression.right()); >+ >+ auto modifyResult = modify(downcast<AST::DotExpression>(assignmentExpression.left()), [&](Optional<UniqueRef<AST::Expression>>&&) -> Optional<ModificationResult> { >+ return {{ Vector<UniqueRef<AST::Expression>>(), assignmentExpression.takeRight() }}; >+ }); >+ >+ if (!modifyResult) { >+ setError(); >+ return; >+ } >+ simplifyLeftValue(modifyResult->innerLeftValue); >+ >+ static_assert(sizeof(AST::CommaExpression) <= sizeof(AST::AssignmentExpression), "Assignment expressions need to be able to become comma expressions without updating backreferences"); >+ Lexer::Token origin = assignmentExpression.origin(); >+ void* location = &assignmentExpression; >+ assignmentExpression.~AssignmentExpression(); >+ auto* commaExpression = new (location) AST::CommaExpression(WTFMove(origin), WTFMove(modifyResult->expressions)); >+ commaExpression->setType(WTFMove(type)); >+ commaExpression->setTypeAnnotation(AST::RightValue()); >+ >+ for (auto& variableDeclaration : modifyResult->variableDeclarations) >+ m_variableDeclarations.append(WTFMove(variableDeclaration)); >+} >+ >+void PropertyResolver::visit(AST::ReadModifyWriteExpression& readModifyWriteExpression) >+{ >+ ASSERT(readModifyWriteExpression.leftValue().typeAnnotation()); >+ if (readModifyWriteExpression.leftValue().typeAnnotation()->leftAddressSpace()) { >+ // Consider a++; >+ // This would get transformed into: >+ // >+ // p = &a; >+ // oldValue = *p; >+ // newValue = ...; >+ // *p = newValue; >+ >+ ASSERT(readModifyWriteExpression.leftValue().resolvedType()); >+ auto baseType = readModifyWriteExpression.leftValue().resolvedType()->clone(); >+ auto pointerType = makeUniqueRef<AST::PointerType>(Lexer::Token(readModifyWriteExpression.leftValue().origin()), *readModifyWriteExpression.leftValue().typeAnnotation()->leftAddressSpace(), baseType->clone()); >+ >+ auto pointerVariable = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(readModifyWriteExpression.leftValue().origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(pointerType->clone()), String(), WTF::nullopt, WTF::nullopt); >+ >+ Vector<UniqueRef<AST::Expression>> expressions; >+ >+ { >+ auto origin = Lexer::Token(readModifyWriteExpression.leftValue().origin()); >+ auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), readModifyWriteExpression.takeLeftValue()); >+ makePointerExpression->setType(pointerType->clone()); >+ makePointerExpression->setTypeAnnotation(AST::RightValue()); >+ >+ auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable)); >+ variableReference->setType(pointerType->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(WTFMove(origin), WTFMove(variableReference), WTFMove(makePointerExpression)); >+ assignmentExpression->setType(pointerType->clone()); >+ assignmentExpression->setTypeAnnotation(AST::RightValue()); >+ >+ expressions.append(WTFMove(assignmentExpression)); >+ } >+ >+ { >+ auto variableReference1 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable)); >+ variableReference1->setType(pointerType->clone()); >+ variableReference1->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ >+ auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(Lexer::Token(readModifyWriteExpression.origin()), WTFMove(variableReference1)); >+ dereferenceExpression->setType(baseType->clone()); >+ dereferenceExpression->setTypeAnnotation(AST::RightValue()); >+ >+ auto variableReference2 = readModifyWriteExpression.oldVariableReference(); >+ variableReference2->setType(baseType->clone()); >+ variableReference2->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(readModifyWriteExpression.origin()), WTFMove(variableReference2), WTFMove(dereferenceExpression)); >+ assignmentExpression->setType(baseType->clone()); >+ assignmentExpression->setTypeAnnotation(AST::RightValue()); >+ >+ expressions.append(WTFMove(assignmentExpression)); >+ } >+ >+ { >+ auto variableReference = readModifyWriteExpression.newVariableReference(); >+ variableReference->setType(baseType->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ >+ auto newValueExpression = readModifyWriteExpression.takeNewValueExpression(); >+ ASSERT(newValueExpression); // FIXME: Relax this constraint. >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(readModifyWriteExpression.origin()), WTFMove(variableReference), WTFMove(*newValueExpression)); >+ assignmentExpression->setType(baseType->clone()); >+ assignmentExpression->setTypeAnnotation(AST::RightValue()); >+ >+ expressions.append(WTFMove(assignmentExpression)); >+ } >+ >+ { >+ auto variableReference1 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable)); >+ variableReference1->setType(pointerType->clone()); >+ variableReference1->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ >+ auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(Lexer::Token(readModifyWriteExpression.origin()), WTFMove(variableReference1)); >+ dereferenceExpression->setType(baseType->clone()); >+ dereferenceExpression->setTypeAnnotation(AST::RightValue()); >+ >+ auto variableReference2 = readModifyWriteExpression.newVariableReference(); >+ variableReference2->setType(baseType->clone()); >+ variableReference2->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(readModifyWriteExpression.origin()), WTFMove(dereferenceExpression), WTFMove(variableReference2)); >+ assignmentExpression->setType(baseType->clone()); >+ assignmentExpression->setTypeAnnotation(AST::RightValue()); >+ >+ expressions.append(WTFMove(assignmentExpression)); >+ } >+ >+ auto resultExpression = readModifyWriteExpression.takeResultExpression(); >+ ASSERT(resultExpression); // FIXME: Be resilient to this being null. >+ ASSERT((*resultExpression)->resolvedType()); >+ auto type = (*resultExpression)->resolvedType()->clone(); >+ expressions.append(WTFMove(*resultExpression)); >+ >+ UniqueRef<AST::VariableDeclaration> oldVariableDeclaration = readModifyWriteExpression.takeOldValue(); >+ UniqueRef<AST::VariableDeclaration> newVariableDeclaration = readModifyWriteExpression.takeNewValue(); >+ >+ static_assert(sizeof(AST::CommaExpression) <= sizeof(AST::ReadModifyWriteExpression), "ReadModifyWrite expressions need to be able to become comma expressions without updating backreferences"); >+ Lexer::Token origin = readModifyWriteExpression.origin(); >+ void* location = &readModifyWriteExpression; >+ readModifyWriteExpression.~ReadModifyWriteExpression(); >+ auto* commaExpression = new (location) AST::CommaExpression(WTFMove(origin), WTFMove(expressions)); >+ commaExpression->setType(WTFMove(type)); >+ commaExpression->setTypeAnnotation(AST::RightValue()); >+ >+ m_variableDeclarations.append(WTFMove(pointerVariable)); >+ m_variableDeclarations.append(WTFMove(oldVariableDeclaration)); >+ m_variableDeclarations.append(WTFMove(newVariableDeclaration)); >+ return; >+ } >+ >+ ASSERT(!readModifyWriteExpression.leftValue().typeAnnotation()->isRightValue()); >+ if (!is<AST::DotExpression>(readModifyWriteExpression.leftValue())) { >+ setError(); // FIXME: Make this work with index expressions. >+ return; >+ } >+ auto modifyResult = modify(downcast<AST::DotExpression>(readModifyWriteExpression.leftValue()), [&](Optional<UniqueRef<AST::Expression>>&& lastGetterCallExpression) -> Optional<ModificationResult> { >+ Vector<UniqueRef<AST::Expression>> expressions; >+ if (!lastGetterCallExpression) >+ return WTF::nullopt; >+ >+ { >+ auto variableReference = readModifyWriteExpression.oldVariableReference(); >+ ASSERT(readModifyWriteExpression.leftValue().resolvedType()); >+ variableReference->setType(readModifyWriteExpression.leftValue().resolvedType()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(readModifyWriteExpression.leftValue().origin()), WTFMove(variableReference), WTFMove(*lastGetterCallExpression)); >+ assignmentExpression->setType(readModifyWriteExpression.leftValue().resolvedType()->clone()); >+ assignmentExpression->setTypeAnnotation(AST::RightValue()); >+ >+ expressions.append(WTFMove(assignmentExpression)); >+ } >+ >+ { >+ auto variableReference = readModifyWriteExpression.newVariableReference(); >+ ASSERT(readModifyWriteExpression.leftValue().resolvedType()); >+ variableReference->setType(readModifyWriteExpression.leftValue().resolvedType()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: Is this right? >+ >+ auto newValueExpression = readModifyWriteExpression.takeNewValueExpression(); >+ ASSERT(newValueExpression); // FIXME: Relax this constraint >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(readModifyWriteExpression.leftValue().origin()), WTFMove(variableReference), WTFMove(*newValueExpression)); >+ assignmentExpression->setType(readModifyWriteExpression.leftValue().resolvedType()->clone()); >+ assignmentExpression->setTypeAnnotation(AST::RightValue()); >+ >+ expressions.append(WTFMove(assignmentExpression)); >+ } >+ >+ return {{ WTFMove(expressions), readModifyWriteExpression.newVariableReference() }}; >+ }); >+ >+ if (!modifyResult) { >+ setError(); >+ return; >+ } >+ simplifyLeftValue(modifyResult->innerLeftValue); >+ >+ auto resultExpression = readModifyWriteExpression.takeResultExpression(); >+ ASSERT(resultExpression); // FIXME: Be resilient to this being null. >+ ASSERT((*resultExpression)->resolvedType()); >+ auto type = (*resultExpression)->resolvedType()->clone(); >+ modifyResult->expressions.append(WTFMove(*resultExpression)); >+ >+ UniqueRef<AST::VariableDeclaration> oldVariableDeclaration = readModifyWriteExpression.takeOldValue(); >+ UniqueRef<AST::VariableDeclaration> newVariableDeclaration = readModifyWriteExpression.takeNewValue(); >+ >+ static_assert(sizeof(AST::CommaExpression) <= sizeof(AST::ReadModifyWriteExpression), "ReadModifyWrite expressions need to be able to become comma expressions without updating backreferences"); >+ Lexer::Token origin = readModifyWriteExpression.origin(); >+ void* location = &readModifyWriteExpression; >+ readModifyWriteExpression.~ReadModifyWriteExpression(); >+ auto* commaExpression = new (location) AST::CommaExpression(WTFMove(origin), WTFMove(modifyResult->expressions)); >+ commaExpression->setType(WTFMove(type)); >+ commaExpression->setTypeAnnotation(AST::RightValue()); >+ >+ for (auto& variableDeclaration : modifyResult->variableDeclarations) >+ m_variableDeclarations.append(WTFMove(variableDeclaration)); >+ m_variableDeclarations.append(WTFMove(oldVariableDeclaration)); >+ m_variableDeclarations.append(WTFMove(newVariableDeclaration)); >+} >+ >+bool PropertyResolver::simplifyRightValue(AST::DotExpression& dotExpression) >+{ >+ Lexer::Token origin = dotExpression.origin(); >+ >+ if (auto* andFunction = dotExpression.andFunction()) { >+ auto& base = dotExpression.base(); >+ ASSERT(base.resolvedType()); >+ ASSERT(base.typeAnnotation()); >+ if (auto leftAddressSpace = base.typeAnnotation()->leftAddressSpace()) { >+ auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), dotExpression.takeBase()); >+ makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(origin), *leftAddressSpace, base.resolvedType()->clone())); >+ makePointerExpression->setTypeAnnotation(AST::RightValue()); >+ >+ Vector<UniqueRef<AST::Expression>> arguments; >+ arguments.append(WTFMove(makePointerExpression)); >+ auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), String(andFunction->name()), WTFMove(arguments)); >+ callExpression->setType(andFunction->type().clone()); >+ callExpression->setTypeAnnotation(AST::RightValue()); >+ callExpression->setFunction(*andFunction); >+ >+ static_assert(sizeof(AST::DereferenceExpression) <= sizeof(AST::DotExpression), "Dot expressions need to be able to become dereference expressions without updating backreferences"); >+ void* location = &dotExpression; >+ dotExpression.~DotExpression(); >+ auto* dereferenceExpression = new (location) AST::DereferenceExpression(WTFMove(origin), WTFMove(callExpression)); >+ dereferenceExpression->setType(downcast<AST::PointerType>(andFunction->type()).elementType().clone()); >+ dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(andFunction->type()).addressSpace() }); >+ return true; >+ } >+ >+ // We have an ander, but no left value to call it on. Let's save the value into a temporary variable to create a left value. >+ // This is effectively inlining the functions the spec says are generated. >+ if (!dotExpression.threadAndFunction()) >+ return false; >+ >+ auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), base.resolvedType()->clone(), String(), WTF::nullopt, WTF::nullopt); >+ >+ auto variableReference1 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration)); >+ variableReference1->setType(base.resolvedType()->clone()); >+ variableReference1->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); >+ >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(origin), WTFMove(variableReference1), dotExpression.takeBase()); >+ assignmentExpression->setType(base.resolvedType()->clone()); >+ assignmentExpression->setTypeAnnotation(AST::RightValue()); >+ >+ auto variableReference2 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration)); >+ variableReference2->setType(base.resolvedType()->clone()); >+ variableReference2->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); >+ >+ auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), WTFMove(variableReference2)); >+ makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(origin), AST::AddressSpace::Thread, base.resolvedType()->clone())); >+ makePointerExpression->setTypeAnnotation(AST::RightValue()); >+ >+ Vector<UniqueRef<AST::Expression>> arguments; >+ arguments.append(WTFMove(makePointerExpression)); >+ auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), String(andFunction->name()), WTFMove(arguments)); >+ callExpression->setType(andFunction->type().clone()); >+ callExpression->setTypeAnnotation(AST::RightValue()); >+ callExpression->setFunction(*andFunction); >+ >+ auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(WTFMove(origin), WTFMove(callExpression)); >+ dereferenceExpression->setType(downcast<AST::PointerType>(andFunction->type()).elementType().clone()); >+ dereferenceExpression->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); >+ >+ static_assert(sizeof(AST::CommaExpression) <= sizeof(AST::DotExpression), "Dot expressions need to be able to become comma expressions without updating backreferences"); >+ void* location = &dotExpression; >+ dotExpression.~DotExpression(); >+ Vector<UniqueRef<AST::Expression>> expressions; >+ expressions.append(WTFMove(assignmentExpression)); >+ expressions.append(WTFMove(dereferenceExpression)); >+ auto* commaExpression = new (location) AST::CommaExpression(WTFMove(origin), WTFMove(expressions)); >+ commaExpression->setType(downcast<AST::PointerType>(andFunction->type()).elementType().clone()); >+ commaExpression->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); >+ >+ m_variableDeclarations.append(WTFMove(variableDeclaration)); >+ return true; >+ } >+ >+ static_assert(sizeof(AST::CallExpression) <= sizeof(AST::DotExpression), "Dot expressions need to be able to become call expressions without updating backreferences"); >+ ASSERT(dotExpression.getFunction()); >+ auto& getFunction = *dotExpression.getFunction(); >+ Vector<UniqueRef<AST::Expression>> arguments; >+ arguments.append(dotExpression.takeBase()); >+ void* location = &dotExpression; >+ dotExpression.~DotExpression(); >+ auto* callExpression = new (location) AST::CallExpression(WTFMove(origin), String(getFunction.name()), WTFMove(arguments)); >+ callExpression->setFunction(getFunction); >+ callExpression->setType(getFunction.type().clone()); >+ callExpression->setTypeAnnotation(AST::RightValue()); >+ return true; >+} >+ >+class LeftValueSimplifier : public Visitor { >+public: >+ void visit(AST::DotExpression&) override; >+ void visit(AST::DereferenceExpression&) override; >+ >+private: >+}; >+ >+void LeftValueSimplifier::visit(AST::DotExpression& dotExpression) >+{ >+ Visitor::visit(dotExpression); >+ ASSERT(dotExpression.base().typeAnnotation()); >+ ASSERT(dotExpression.base().typeAnnotation()->leftAddressSpace()); >+ ASSERT(dotExpression.andFunction()); >+ >+ Lexer::Token origin = dotExpression.origin(); >+ auto* andFunction = dotExpression.andFunction(); >+ auto& base = dotExpression.base(); >+ auto leftAddressSpace = *dotExpression.base().typeAnnotation()->leftAddressSpace(); >+ auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), dotExpression.takeBase()); >+ makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(origin), leftAddressSpace, base.resolvedType()->clone())); >+ makePointerExpression->setTypeAnnotation(AST::RightValue()); >+ >+ Vector<UniqueRef<AST::Expression>> arguments; >+ arguments.append(WTFMove(makePointerExpression)); >+ auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), String(andFunction->name()), WTFMove(arguments)); >+ callExpression->setType(andFunction->type().clone()); >+ callExpression->setTypeAnnotation(AST::RightValue()); >+ callExpression->setFunction(*andFunction); >+ >+ static_assert(sizeof(AST::DereferenceExpression) <= sizeof(AST::DotExpression), "Dot expressions need to be able to become dereference expressions without updating backreferences"); >+ void* location = &dotExpression; >+ dotExpression.~DotExpression(); >+ auto* dereferenceExpression = new (location) AST::DereferenceExpression(WTFMove(origin), WTFMove(callExpression)); >+ dereferenceExpression->setType(downcast<AST::PointerType>(andFunction->type()).elementType().clone()); >+ dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(andFunction->type()).addressSpace() }); >+} >+ >+void LeftValueSimplifier::visit(AST::DereferenceExpression& dereferenceExpression) >+{ >+ // Dereference expressions are the only expressions where the children might be more-right than we are. >+ // For example, a dereference expression may be a left value but its child may be a call expression which is a right value. >+ // LeftValueSimplifier doesn't handle right values, so we instead need to use PropertyResolver. >+ // FIXME: What about function call arguments? >+ PropertyResolver().Visitor::visit(dereferenceExpression); >+} >+ >+void PropertyResolver::simplifyLeftValue(AST::Expression& expression) >+{ >+ LeftValueSimplifier().Visitor::visit(expression); >+} >+ >+void resolveProperties(Program& program) >+{ >+ PropertyResolver().Visitor::visit(program); >+} >+ >+} // namespace WHLSL >+ >+} // namespace WebCore >+ >+#endif // ENABLE(WEBGPU) >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.h >new file mode 100644 >index 0000000000000000000000000000000000000000..e2205f902bcc94eca9ef33b58da1c701ab72b347 >--- /dev/null >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.h >@@ -0,0 +1,42 @@ >+/* >+ * Copyright (C) 2019 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. AND ITS CONTRIBUTORS ``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 ITS 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. >+ */ >+ >+#pragma once >+ >+#if ENABLE(WEBGPU) >+ >+namespace WebCore { >+ >+namespace WHLSL { >+ >+class Program; >+ >+void resolveProperties(Program&); >+ >+} >+ >+} >+ >+#endif >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.cpp >index e7838ce3f725ae09aba1edb50a6592c346313ee5..dc934dbf726a814a0804b4ccb5752dbecb81f38b 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.cpp >@@ -44,7 +44,7 @@ static unsigned conversionCost(AST::FunctionDeclaration& candidate, const Vector > conversionCost += argumentTypes[i].get().visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>&) -> unsigned { > return 0; > }, [&](RefPtr<ResolvableTypeReference>& resolvableTypeReference) -> unsigned { >- return resolvableTypeReference->resolvableType().conversionCost(*candidate.parameters()[i].type()); >+ return resolvableTypeReference->resolvableType().conversionCost(*candidate.parameters()[i]->type()); > })); > } > // The return type can never be a literal type, so its conversion cost is always 0. >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolvingType.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolvingType.h >index ca5cbb5929cf9e1818c2cd741e79d936caac68ee..50e532b6a6e82f1e02a046791b8e6696d5b11e15 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolvingType.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolvingType.h >@@ -72,6 +72,7 @@ private: > > // This is a thin wrapper around a Variant. > // It exists so we can make sure that the default constructor does the right thing. >+// FIXME: This wrapper might not be necessary. > class ResolvingType { > public: > ResolvingType() >@@ -102,10 +103,11 @@ public: > return *this; > } > >- AST::UnnamedType& getUnnamedType() >+ AST::UnnamedType* getUnnamedType() > { >- ASSERT(WTF::holds_alternative<UniqueRef<AST::UnnamedType>>(m_inner)); >- return WTF::get<UniqueRef<AST::UnnamedType>>(m_inner); >+ if (WTF::holds_alternative<UniqueRef<AST::UnnamedType>>(m_inner)) >+ return &WTF::get<UniqueRef<AST::UnnamedType>>(m_inner); >+ return nullptr; > } > > template <typename Visitor> auto visit(const Visitor& visitor) -> decltype(WTF::visit(visitor, std::declval<Variant<UniqueRef<AST::UnnamedType>, RefPtr<ResolvableTypeReference>>&>())) >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt >index 79a2c60e0606b13265bb230367acf97250bf9a7f..0fb5d3932d45fb0afde0959615ebd81feaa91c53 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt >@@ -390,4 +390,13 @@ native void AllMemoryBarrierWithGroupSync(); > native void DeviceMemoryBarrierWithGroupSync(); > native void GroupMemoryBarrierWithGroupSync(); > >+operator float4(float x, float y, float z, float w) { >+ float4 result; >+ result.x = x; >+ result.y = y; >+ result.z = z; >+ result.w = w; >+ return result; >+} >+ > // FIXME: https://bugs.webkit.org/show_bug.cgi?id=192890 Insert the rest of the standard library once the parser is fast enough >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeArrayOperatorLength.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeArrayOperatorLength.cpp >index ae3ca64239e3b59d36aaaaeec7ba471bcb67ceb9..65ed7acf43f20040250f9066a14b640b57bbf0cc 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeArrayOperatorLength.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeArrayOperatorLength.cpp >@@ -65,7 +65,7 @@ bool synthesizeArrayOperatorLength(Program& program) > bool isOperator = true; > > for (auto& arrayType : arrayTypes) { >- AST::VariableDeclaration variableDeclaration(Lexer::Token(arrayType.get().origin()), AST::Qualifiers(), { arrayType.get().clone() }, String(), WTF::nullopt, WTF::nullopt); >+ auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(arrayType.get().origin()), AST::Qualifiers(), arrayType.get().clone(), String(), WTF::nullopt, WTF::nullopt); > AST::VariableDeclarations parameters; > parameters.append(WTFMove(variableDeclaration)); > AST::NativeFunctionDeclaration nativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(arrayType.get().origin()), AST::AttributeBlock(), WTF::nullopt, AST::TypeReference::wrap(Lexer::Token(arrayType.get().origin()), program.intrinsics().uintType()), "operator.length"_str, WTFMove(parameters), WTF::nullopt, isOperator)); >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeConstructors.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeConstructors.cpp >index cd7c3702adbea29ac18c5cbe6db6087b9e02ed8a..74cc8f184e835b3ce1c49b5ce6ec8d6a4a868c1d 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeConstructors.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeConstructors.cpp >@@ -110,7 +110,7 @@ bool synthesizeConstructors(Program& program) > bool isOperator = true; > > for (auto& unnamedType : unnamedTypes) { >- AST::VariableDeclaration variableDeclaration(Lexer::Token(unnamedType.get().origin()), AST::Qualifiers(), { unnamedType.get().clone() }, String(), WTF::nullopt, WTF::nullopt); >+ auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(unnamedType.get().origin()), AST::Qualifiers(), unnamedType.get().clone(), String(), WTF::nullopt, WTF::nullopt); > AST::VariableDeclarations parameters; > parameters.append(WTFMove(variableDeclaration)); > AST::NativeFunctionDeclaration copyConstructor(AST::FunctionDeclaration(Lexer::Token(unnamedType.get().origin()), AST::AttributeBlock(), WTF::nullopt, unnamedType.get().clone(), "operator cast"_str, WTFMove(parameters), WTF::nullopt, isOperator)); >@@ -127,7 +127,7 @@ bool synthesizeConstructors(Program& program) > if (is<AST::NativeTypeDeclaration>(static_cast<AST::NamedType&>(namedType)) && downcast<AST::NativeTypeDeclaration>(static_cast<AST::NamedType&>(namedType)).isAtomic()) > continue; > >- AST::VariableDeclaration variableDeclaration(Lexer::Token(namedType.get().origin()), AST::Qualifiers(), { AST::TypeReference::wrap(Lexer::Token(namedType.get().origin()), namedType.get()) }, String(), WTF::nullopt, WTF::nullopt); >+ auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(namedType.get().origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(namedType.get().origin()), namedType.get())), String(), WTF::nullopt, WTF::nullopt); > AST::VariableDeclarations parameters; > parameters.append(WTFMove(variableDeclaration)); > AST::NativeFunctionDeclaration copyConstructor(AST::FunctionDeclaration(Lexer::Token(namedType.get().origin()), AST::AttributeBlock(), WTF::nullopt, AST::TypeReference::wrap(Lexer::Token(namedType.get().origin()), namedType.get()), "operator cast"_str, WTFMove(parameters), WTF::nullopt, isOperator)); >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeEnumerationFunctions.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeEnumerationFunctions.cpp >index 1797fe5394c81eacd3954abc6a8a65a6c8fc96e2..d74af33a1f05a692219c8cce4afdcc929510971d 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeEnumerationFunctions.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeEnumerationFunctions.cpp >@@ -41,8 +41,8 @@ bool synthesizeEnumerationFunctions(Program& program) > bool isOperator = true; > for (auto& enumerationDefinition : program.enumerationDefinitions()) { > { >- AST::VariableDeclaration variableDeclaration1(Lexer::Token(enumerationDefinition->origin()), AST::Qualifiers(), { AST::TypeReference::wrap(Lexer::Token(enumerationDefinition->origin()), enumerationDefinition) }, String(), WTF::nullopt, WTF::nullopt); >- AST::VariableDeclaration variableDeclaration2(Lexer::Token(enumerationDefinition->origin()), AST::Qualifiers(), { AST::TypeReference::wrap(Lexer::Token(enumerationDefinition->origin()), enumerationDefinition) }, String(), WTF::nullopt, WTF::nullopt); >+ auto variableDeclaration1 = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(enumerationDefinition->origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(enumerationDefinition->origin()), enumerationDefinition)), String(), WTF::nullopt, WTF::nullopt); >+ auto variableDeclaration2 = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(enumerationDefinition->origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(enumerationDefinition->origin()), enumerationDefinition)), String(), WTF::nullopt, WTF::nullopt); > AST::VariableDeclarations parameters; > parameters.append(WTFMove(variableDeclaration1)); > parameters.append(WTFMove(variableDeclaration2)); >@@ -52,7 +52,7 @@ bool synthesizeEnumerationFunctions(Program& program) > } > > { >- AST::VariableDeclaration variableDeclaration(Lexer::Token(enumerationDefinition->origin()), AST::Qualifiers(), { AST::TypeReference::wrap(Lexer::Token(enumerationDefinition->origin()), enumerationDefinition) }, String(), WTF::nullopt, WTF::nullopt); >+ auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(enumerationDefinition->origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(enumerationDefinition->origin()), enumerationDefinition)), String(), WTF::nullopt, WTF::nullopt); > AST::VariableDeclarations parameters; > parameters.append(WTFMove(variableDeclaration)); > AST::NativeFunctionDeclaration nativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(enumerationDefinition->origin()), AST::AttributeBlock(), WTF::nullopt, enumerationDefinition->type().clone(), "operator.value"_str, WTFMove(parameters), WTF::nullopt, isOperator)); >@@ -61,7 +61,7 @@ bool synthesizeEnumerationFunctions(Program& program) > } > > { >- AST::VariableDeclaration variableDeclaration(Lexer::Token(enumerationDefinition->origin()), AST::Qualifiers(), { AST::TypeReference::wrap(Lexer::Token(enumerationDefinition->origin()), enumerationDefinition) }, String(), WTF::nullopt, WTF::nullopt); >+ auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(enumerationDefinition->origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(enumerationDefinition->origin()), enumerationDefinition)), String(), WTF::nullopt, WTF::nullopt); > AST::VariableDeclarations parameters; > parameters.append(WTFMove(variableDeclaration)); > AST::NativeFunctionDeclaration nativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(enumerationDefinition->origin()), AST::AttributeBlock(), WTF::nullopt, enumerationDefinition->type().clone(), "operator cast"_str, WTFMove(parameters), WTF::nullopt, isOperator)); >@@ -70,10 +70,10 @@ bool synthesizeEnumerationFunctions(Program& program) > } > > { >- AST::VariableDeclaration variableDeclaration(Lexer::Token(enumerationDefinition->origin()), AST::Qualifiers(), enumerationDefinition->type().clone(), String(), WTF::nullopt, WTF::nullopt); >+ auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(enumerationDefinition->origin()), AST::Qualifiers(), enumerationDefinition->type().clone(), String(), WTF::nullopt, WTF::nullopt); > AST::VariableDeclarations parameters; > parameters.append(WTFMove(variableDeclaration)); >- AST::NativeFunctionDeclaration nativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(enumerationDefinition->origin()), AST::AttributeBlock(), WTF::nullopt, { AST::TypeReference::wrap(Lexer::Token(enumerationDefinition->origin()), enumerationDefinition) }, "operator cast"_str, WTFMove(parameters), WTF::nullopt, isOperator)); >+ AST::NativeFunctionDeclaration nativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(enumerationDefinition->origin()), AST::AttributeBlock(), WTF::nullopt, UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(enumerationDefinition->origin()), enumerationDefinition)), "operator cast"_str, WTFMove(parameters), WTF::nullopt, isOperator)); > if (!program.append(WTFMove(nativeFunctionDeclaration))) > return false; > } >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeStructureAccessors.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeStructureAccessors.cpp >index 826722137e4c3e38227780dae12b29aaba1b72ee..945d0ceefaa39ce5074607d2c4493cf397e983de 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeStructureAccessors.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeStructureAccessors.cpp >@@ -46,7 +46,7 @@ bool synthesizeStructureAccessors(Program& program) > for (auto& structureElement : structureDefinition->structureElements()) { > { > // The getter: operator.field >- AST::VariableDeclaration variableDeclaration(Lexer::Token(structureElement.origin()), AST::Qualifiers(), { AST::TypeReference::wrap(Lexer::Token(structureElement.origin()), structureDefinition) }, String(), WTF::nullopt, WTF::nullopt); >+ auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(structureElement.origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(structureElement.origin()), structureDefinition)), String(), WTF::nullopt, WTF::nullopt); > AST::VariableDeclarations parameters; > parameters.append(WTFMove(variableDeclaration)); > AST::NativeFunctionDeclaration nativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(structureElement.origin()), AST::AttributeBlock(), WTF::nullopt, structureElement.type().clone(), makeString("operator.", structureElement.name()), WTFMove(parameters), WTF::nullopt, isOperator)); >@@ -56,8 +56,8 @@ bool synthesizeStructureAccessors(Program& program) > > { > // The setter: operator.field= >- AST::VariableDeclaration variableDeclaration1(Lexer::Token(structureElement.origin()), AST::Qualifiers(), { AST::TypeReference::wrap(Lexer::Token(structureElement.origin()), structureDefinition) }, String(), WTF::nullopt, WTF::nullopt); >- AST::VariableDeclaration variableDeclaration2(Lexer::Token(structureElement.origin()), AST::Qualifiers(), { structureElement.type().clone() }, String(), WTF::nullopt, WTF::nullopt); >+ auto variableDeclaration1 = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(structureElement.origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(structureElement.origin()), structureDefinition)), String(), WTF::nullopt, WTF::nullopt); >+ auto variableDeclaration2 = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(structureElement.origin()), AST::Qualifiers(), structureElement.type().clone(), String(), WTF::nullopt, WTF::nullopt); > AST::VariableDeclarations parameters; > parameters.append(WTFMove(variableDeclaration1)); > parameters.append(WTFMove(variableDeclaration2)); >@@ -69,7 +69,7 @@ bool synthesizeStructureAccessors(Program& program) > // The ander: operator&.field > auto createAnder = [&](AST::AddressSpace addressSpace) -> AST::NativeFunctionDeclaration { > auto argumentType = makeUniqueRef<AST::PointerType>(Lexer::Token(structureElement.origin()), addressSpace, AST::TypeReference::wrap(Lexer::Token(structureElement.origin()), structureDefinition)); >- AST::VariableDeclaration variableDeclaration(Lexer::Token(structureElement.origin()), AST::Qualifiers(), { WTFMove(argumentType) }, String(), WTF::nullopt, WTF::nullopt); >+ auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(structureElement.origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(WTFMove(argumentType)), String(), WTF::nullopt, WTF::nullopt); > AST::VariableDeclarations parameters; > parameters.append(WTFMove(variableDeclaration)); > auto returnType = makeUniqueRef<AST::PointerType>(Lexer::Token(structureElement.origin()), addressSpace, structureElement.type().clone()); >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp >index ed2e8c0052d6dfe9bd07baf7649d8ce48c9b09bb..2f20152cab7ad1c7826ba3d21517a4ec09eaeead 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp >@@ -532,7 +532,7 @@ void Visitor::visit(AST::Trap&) > void Visitor::visit(AST::VariableDeclarationsStatement& variableDeclarationsStatement) > { > for (auto& variableDeclaration : variableDeclarationsStatement.variableDeclarations()) >- checkErrorAndVisit(variableDeclaration); >+ checkErrorAndVisit(variableDeclaration.get()); > } > > void Visitor::visit(AST::WhileLoop& whileLoop) >@@ -589,17 +589,17 @@ void Visitor::visit(AST::LogicalNotExpression& logicalNotExpression) > > void Visitor::visit(AST::MakeArrayReferenceExpression& makeArrayReferenceExpression) > { >- checkErrorAndVisit(makeArrayReferenceExpression.lValue()); >+ checkErrorAndVisit(makeArrayReferenceExpression.leftValue()); > } > > void Visitor::visit(AST::MakePointerExpression& makePointerExpression) > { >- checkErrorAndVisit(makePointerExpression.lValue()); >+ checkErrorAndVisit(makePointerExpression.leftValue()); > } > > void Visitor::visit(AST::ReadModifyWriteExpression& readModifyWriteExpression) > { >- checkErrorAndVisit(readModifyWriteExpression.lValue()); >+ checkErrorAndVisit(readModifyWriteExpression.leftValue()); > checkErrorAndVisit(readModifyWriteExpression.oldValue()); > checkErrorAndVisit(readModifyWriteExpression.newValue()); > if (readModifyWriteExpression.newValueExpression()) >diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt >index 3675e004b8673e9d68b1c6bd8d468a0d4d41257e..cf746cea2e8cbd1c13e20c961551069e73203c1e 100644 >--- a/Source/WebCore/Sources.txt >+++ b/Source/WebCore/Sources.txt >@@ -348,6 +348,7 @@ Modules/webgpu/WHLSL/AST/WHLSLTypeReference.cpp > Modules/webgpu/WHLSL/AST/WHLSLIntegerLiteral.cpp > Modules/webgpu/WHLSL/AST/WHLSLUnsignedIntegerLiteral.cpp > Modules/webgpu/WHLSL/WHLSLPrepare.cpp >+Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp > Modules/webgpu/WebGPU.cpp > Modules/webgpu/WebGPUAdapter.cpp > Modules/webgpu/WebGPUBindGroup.cpp >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index f69cff232128cbbe8ea5cc1dee84070cb6f8701e..2ed77b2a622921bca5322a9baec4d9fc60d471d7 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -6390,6 +6390,8 @@ > 1CA0C2EC21EED6F600A11860 /* WHLSLLiteralTypeChecker.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLLiteralTypeChecker.cpp; sourceTree = "<group>"; }; > 1CA19E030DC255950065A994 /* EventLoopMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = EventLoopMac.mm; sourceTree = "<group>"; }; > 1CA19E150DC255CA0065A994 /* EventLoop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventLoop.h; sourceTree = "<group>"; }; >+ 1CAA82F62242AE0500E84BBB /* WHLSLPropertyResolver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLPropertyResolver.cpp; sourceTree = "<group>"; }; >+ 1CAA82F72242AE0500E84BBB /* WHLSLPropertyResolver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLPropertyResolver.h; sourceTree = "<group>"; }; > 1CAF347E0A6C405200ABE06E /* WebScriptObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebScriptObject.h; sourceTree = "<group>"; }; > 1CAF347F0A6C405200ABE06E /* WebScriptObject.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebScriptObject.mm; sourceTree = "<group>"; }; > 1CAF34800A6C405200ABE06E /* WebScriptObjectPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebScriptObjectPrivate.h; sourceTree = "<group>"; }; >@@ -25402,6 +25404,8 @@ > C24A57BA21FEAFEA004C6DD1 /* WHLSLPrepare.cpp */, > C24A57BB21FEAFEA004C6DD1 /* WHLSLPrepare.h */, > C21BF73A21CD8D7000227979 /* WHLSLProgram.h */, >+ 1CAA82F62242AE0500E84BBB /* WHLSLPropertyResolver.cpp */, >+ 1CAA82F72242AE0500E84BBB /* WHLSLPropertyResolver.h */, > 1CA0C2E021EEB5F500A11860 /* WHLSLRecursionChecker.cpp */, > 1CA0C2DE21EEB5F400A11860 /* WHLSLRecursionChecker.h */, > C234A9AD21E92C19003C984D /* WHLSLRecursiveTypeChecker.cpp */, >diff --git a/Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm b/Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm >index 8fb4a26ca48b54caab187db29e3469a38504405f..e0292b8f544d4eacdba179fc0b234e4ec3aa73fd 100644 >--- a/Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm >+++ b/Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm >@@ -263,6 +263,8 @@ static bool trySetWHLSLFunctionsForPipelineDescriptor(const char* const function > if (!result) > return false; > >+ WTFLogAlways("Metal Source: %s", result->metalSource.utf8().data()); >+ > NSError *error = nil; > auto library = adoptNS([device.platformDevice() newLibraryWithSource:result->metalSource options:nil error:&error]); > ASSERT(library); >diff --git a/LayoutTests/webgpu/whlsl-dot-expressions.html b/LayoutTests/webgpu/whlsl-dot-expressions.html >new file mode 100644 >index 0000000000000000000000000000000000000000..d44a0f6ff846febe306912d7852ebf43fd1ce1e6 >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl-dot-expressions.html >@@ -0,0 +1,128 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+struct VertexOut { >+ float4 position : SV_Position; >+ float shade : attribute(0); >+} >+ >+vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >+ VertexOut result; >+ result.position = position; >+ result.shade = shade; >+ return result; >+} >+ >+fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >+ return float4(shade, shade, shade, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, inputSlot: 0, format: "float4"}; >+ const attribute1 = {shaderLocation: 1, inputSlot: 1, format: "float"}; >+ const attributes = [attribute0, attribute1]; >+ const input0 = {inputSlot: 0, stride: 16 }; >+ const input1 = {inputSlot: 1, stride: 4 }; >+ const inputs = [input0, input1]; >+ const inputState = {indexFormat: "uint32", attributes, inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, inputState, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1; >+ vertexBuffer0Float32Array[4] = -0.5; >+ vertexBuffer0Float32Array[5] = 0.5; >+ vertexBuffer0Float32Array[6] = 1.0; >+ vertexBuffer0Float32Array[7] = 1; >+ vertexBuffer0Float32Array[8] = 0.5; >+ vertexBuffer0Float32Array[9] = -0.5; >+ vertexBuffer0Float32Array[10] = 1.0; >+ vertexBuffer0Float32Array[11] = 1; >+ vertexBuffer0Float32Array[12] = 0.5; >+ vertexBuffer0Float32Array[13] = 0.5; >+ vertexBuffer0Float32Array[14] = 1.0; >+ vertexBuffer0Float32Array[15] = 1; >+ vertexBuffer0.unmap(); >+ >+ const vertexBuffer1Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer1 = device.createBuffer(vertexBuffer1Descriptor); >+ const vertexBuffer1ArrayBuffer = await vertexBuffer1.mapWriteAsync(); >+ const vertexBuffer1Float32Array = new Float32Array(vertexBuffer1ArrayBuffer); >+ vertexBuffer1Descriptor[0] = 1; >+ vertexBuffer1Descriptor[1] = 1; >+ vertexBuffer1Descriptor[2] = 1; >+ vertexBuffer1Descriptor[3] = 1; >+ vertexBuffer1.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0, vertexBuffer1], [0, 0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html>
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 195925
:
365100
|
365130
|
365275
|
365291
|
365455
|
365648
|
365651
|
365669
|
365787
|
369928
|
370332
|
370338
|
370361
|
370366
|
370369
|
370493