WebKit Bugzilla
Attachment 359002 Details for
Bug 193080
: [WHLSL] Implement the Type Checker
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-193080-20190112235232.patch (text/plain), 124.73 KB, created by
Myles C. Maxfield
on 2019-01-12 23:52:33 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Myles C. Maxfield
Created:
2019-01-12 23:52:33 PST
Size:
124.73 KB
patch
obsolete
>Subversion Revision: 239896 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 356730a7c4c589b53975e25fd3d4ed56202479df..268ea68e798474c45c7e894878222fb32de943e2 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,35 @@ >+2019-01-12 Myles C. Maxfield <mmaxfield@apple.com> >+ >+ [WHLSL] Implement the Type Checker >+ https://bugs.webkit.org/show_bug.cgi?id=193080 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ No new tests (OOPS!). >+ >+ * Modules/webgpu/WHLSL/WHLSLChecker.cpp: Added. >+ (WebCore::WHLSL::resolveWithOperatorAnderIndexer): >+ (WebCore::WHLSL::resolveWithOperatorLength): >+ (WebCore::WHLSL::resolveWithReferenceComparator): >+ (WebCore::WHLSL::resolveByInstantiation): >+ (WebCore::WHLSL::Checker::Checker): >+ (WebCore::WHLSL::Checker::checkShaderType): >+ (WebCore::WHLSL::Checker::checkSemantics): >+ (WebCore::WHLSL::Checker::checkOperatorOverload): >+ (WebCore::WHLSL::Checker::isBoolType): >+ (WebCore::WHLSL::check): >+ * Modules/webgpu/WHLSL/WHLSLChecker.h: Added. >+ * Modules/webgpu/WHLSL/WHLSLGatherEntryPointItems.cpp: Added. >+ (WebCore::WHLSL::Gatherer::Gatherer): >+ (WebCore::WHLSL::Gatherer::reset): >+ (WebCore::WHLSL::Gatherer::takeEntryPointItems): >+ (WebCore::WHLSL::Gatherer::visit): >+ (WebCore::WHLSL::gatherEntryPointItems): >+ * Modules/webgpu/WHLSL/WHLSLGatherEntryPointItems.h: Added. >+ (WebCore::WHLSL::EntryPointItem::EntryPointItem): >+ * Sources.txt: >+ * WebCore.xcodeproj/project.pbxproj: >+ > 2019-01-11 Myles C. Maxfield <mmaxfield@apple.com> > > [WHLSL] Implement the NameResolver >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLConstantExpression.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLConstantExpression.h >index df68c2a1334d29e913bad45fcc41a257931c087a..3d1ae1cec357899bd87fffd145406db329f0864a 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLConstantExpression.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLConstantExpression.h >@@ -28,7 +28,7 @@ > #if ENABLE(WEBGPU) > > #include "WHLSLBooleanLiteral.h" >-#include "WHLSLConstantExpressionEnumerationMemberReference.h" >+#include "WHLSLEnumerationMemberLiteral.h" > #include "WHLSLFloatLiteral.h" > #include "WHLSLIntegerLiteral.h" > #include "WHLSLNullLiteral.h" >@@ -71,8 +71,8 @@ public: > { > } > >- ConstantExpression(ConstantExpressionEnumerationMemberReference&& constantExpressionEnumerationMemberReference) >- : m_variant(WTFMove(constantExpressionEnumerationMemberReference)) >+ ConstantExpression(EnumerationMemberLiteral&& enumerationMemberLiteral) >+ : m_variant(WTFMove(enumerationMemberLiteral)) > { > } > >@@ -110,8 +110,8 @@ public: > return nullLiteral.clone(); > }, [&](const BooleanLiteral& booleanLiteral) -> ConstantExpression { > return booleanLiteral.clone(); >- }, [&](const ConstantExpressionEnumerationMemberReference& constantExpressionEnumerationMemberReference) -> ConstantExpression { >- return constantExpressionEnumerationMemberReference.clone(); >+ }, [&](const EnumerationMemberLiteral& enumerationMemberLiteral) -> ConstantExpression { >+ return enumerationMemberLiteral.clone(); > }), m_variant); > } > >@@ -133,10 +133,10 @@ public: > result = booleanLiteral.value() == otherBooleanLiteral.value(); > } else > result = false; >- }, [&](const ConstantExpressionEnumerationMemberReference& constantExpressionEnumerationMemberReference) { >- if (WTF::holds_alternative<ConstantExpressionEnumerationMemberReference>(other.m_variant)) { >- const auto& otherMemberReference = WTF::get<ConstantExpressionEnumerationMemberReference>(other.m_variant); >- result = constantExpressionEnumerationMemberReference.enumerationMember() == otherMemberReference.enumerationMember(); >+ }, [&](const EnumerationMemberLiteral& enumerationMemberLiteral) { >+ if (WTF::holds_alternative<EnumerationMemberLiteral>(other.m_variant)) { >+ const auto& otherMemberReference = WTF::get<EnumerationMemberLiteral>(other.m_variant); >+ result = enumerationMemberLiteral.enumerationMember() == otherMemberReference.enumerationMember(); > } else > result = false; > })); >@@ -154,7 +154,7 @@ public: > result = false; > }, [&](const BooleanLiteral&) { > result = false; >- }, [&](const ConstantExpressionEnumerationMemberReference&) { >+ }, [&](const EnumerationMemberLiteral&) { > result = false; > })); > >@@ -169,7 +169,7 @@ private: > FloatLiteral, > NullLiteral, > BooleanLiteral, >- ConstantExpressionEnumerationMemberReference >+ EnumerationMemberLiteral > > m_variant; > }; > >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLConstantExpressionEnumerationMemberReference.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLConstantExpressionEnumerationMemberReference.h >deleted file mode 100644 >index 5857d947285b967ad11d916e0ee02fba5f150d0a..0000000000000000000000000000000000000000 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLConstantExpressionEnumerationMemberReference.h >+++ /dev/null >@@ -1,108 +0,0 @@ >-/* >- * 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) >- >-#include "WHLSLLexer.h" >-#include <wtf/text/WTFString.h> >- >-namespace WebCore { >- >-namespace WHLSL { >- >-namespace AST { >- >-class EnumerationDefinition; >-class EnumerationMember; >- >-class ConstantExpressionEnumerationMemberReference : public Expression { >-public: >- ConstantExpressionEnumerationMemberReference(Lexer::Token&& origin, String&& left, String&& right) >- : Expression(WTFMove(origin)) >- , m_left(WTFMove(left)) >- , m_right(WTFMove(right)) >- { >- } >- >- virtual ~ConstantExpressionEnumerationMemberReference() = default; >- >- explicit ConstantExpressionEnumerationMemberReference(const ConstantExpressionEnumerationMemberReference&) = default; >- ConstantExpressionEnumerationMemberReference(ConstantExpressionEnumerationMemberReference&&) = default; >- >- ConstantExpressionEnumerationMemberReference& operator=(const ConstantExpressionEnumerationMemberReference&) = delete; >- ConstantExpressionEnumerationMemberReference& operator=(ConstantExpressionEnumerationMemberReference&&) = default; >- >- const String& left() const { return m_left; } >- const String& right() const { return m_right; } >- >- ConstantExpressionEnumerationMemberReference clone() const >- { >- auto result = ConstantExpressionEnumerationMemberReference(Lexer::Token(origin()), String(m_left), String(m_right)); >- result.m_enumerationMember = m_enumerationMember; >- return result; >- } >- >- EnumerationDefinition* enumerationDefinition() >- { >- return m_enumerationDefinition; >- } >- >- EnumerationDefinition* enumerationDefinition() const >- { >- return m_enumerationDefinition; >- } >- >- EnumerationMember* enumerationMember() >- { >- return m_enumerationMember; >- } >- >- EnumerationMember* enumerationMember() const >- { >- return m_enumerationMember; >- } >- >- void setEnumerationMember(EnumerationDefinition& enumerationDefinition, EnumerationMember& enumerationMember) >- { >- m_enumerationDefinition = &enumerationDefinition; >- m_enumerationMember = &enumerationMember; >- } >- >-private: >- String m_left; >- String m_right; >- EnumerationDefinition* m_enumerationDefinition { nullptr }; >- EnumerationMember* m_enumerationMember { nullptr }; >-}; >- >-} // namespace AST >- >-} >- >-} >- >-#endif >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLEnumerationMemberLiteral.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLEnumerationMemberLiteral.h >index ba64303802b1b5a4197d9916c1a1520b20f60cc9..ee745e54bd0542f37bb3d9814374eb3e60fca591 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLEnumerationMemberLiteral.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLEnumerationMemberLiteral.h >@@ -27,9 +27,8 @@ > > #if ENABLE(WEBGPU) > >-#include "WHLSLEnumerationMember.h" >-#include "WHLSLExpression.h" > #include "WHLSLLexer.h" >+#include <wtf/text/WTFString.h> > > namespace WebCore { > >@@ -37,25 +36,77 @@ namespace WHLSL { > > namespace AST { > >+class EnumerationDefinition; >+class EnumerationMember; >+ > class EnumerationMemberLiteral : public Expression { > public: >- EnumerationMemberLiteral(Lexer::Token&& origin, EnumerationMember& enumerationMember) >+ EnumerationMemberLiteral(Lexer::Token&& origin, String&& left, String&& right) > : Expression(WTFMove(origin)) >- , m_enumerationMember(enumerationMember) >+ , m_left(WTFMove(left)) >+ , m_right(WTFMove(right)) > { > } > > virtual ~EnumerationMemberLiteral() = default; > >- EnumerationMemberLiteral(const EnumerationMemberLiteral&) = delete; >+ explicit EnumerationMemberLiteral(const EnumerationMemberLiteral&) = default; > EnumerationMemberLiteral(EnumerationMemberLiteral&&) = default; > >+ EnumerationMemberLiteral& operator=(const EnumerationMemberLiteral&) = delete; >+ EnumerationMemberLiteral& operator=(EnumerationMemberLiteral&&) = default; >+ > bool isEnumerationMemberLiteral() const override { return true; } > >- EnumerationMember& enumerationMember() { return m_enumerationMember; } >+ static EnumerationMemberLiteral wrap(Lexer::Token&& origin, String&& left, String&& right, EnumerationDefinition& enumerationDefinition, EnumerationMember& enumerationMember) >+ { >+ EnumerationMemberLiteral result(WTFMove(origin), WTFMove(left), WTFMove(right)); >+ result.m_enumerationDefinition = &enumerationDefinition; >+ result.m_enumerationMember = &enumerationMember; >+ return result; >+ } >+ >+ const String& left() const { return m_left; } >+ const String& right() const { return m_right; } >+ >+ EnumerationMemberLiteral clone() const >+ { >+ auto result = EnumerationMemberLiteral(Lexer::Token(origin()), String(m_left), String(m_right)); >+ result.m_enumerationMember = m_enumerationMember; >+ return result; >+ } >+ >+ EnumerationDefinition* enumerationDefinition() >+ { >+ return m_enumerationDefinition; >+ } >+ >+ EnumerationDefinition* enumerationDefinition() const >+ { >+ return m_enumerationDefinition; >+ } >+ >+ EnumerationMember* enumerationMember() >+ { >+ return m_enumerationMember; >+ } >+ >+ EnumerationMember* enumerationMember() const >+ { >+ return m_enumerationMember; >+ } >+ >+ void setEnumerationMember(EnumerationDefinition& enumerationDefinition, EnumerationMember& enumerationMember) >+ { >+ m_enumerationDefinition = &enumerationDefinition; >+ m_enumerationMember = &enumerationMember; >+ } > > private: >- EnumerationMember& m_enumerationMember; >+ String m_left; >+ String m_right; >+ EnumerationDefinition* m_enumerationDefinition { nullptr }; >+ EnumerationMember* m_enumerationMember { nullptr }; > }; > > } // namespace AST >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLVariableDeclaration.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLVariableDeclaration.h >index b4494602cfbaab1135d7162356a0a20870122ebe..9beb758cc389c40841ec044f26da192e00517809 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLVariableDeclaration.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLVariableDeclaration.h >@@ -68,6 +68,7 @@ public: > UnnamedType* type() { return m_type ? &static_cast<UnnamedType&>(*m_type) : nullptr; } > Optional<Semantic>& semantic() { return m_semantic; } > Expression* initializer() { return m_initializer ? &static_cast<Expression&>(*m_initializer) : nullptr; } >+ bool isAnonymous() const { return m_name.isNull(); } > > private: > Lexer::Token m_origin; >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..62a1255b439e7eec58c4e446f37a553951798b7f >--- /dev/null >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp >@@ -0,0 +1,1649 @@ >+/* >+ * 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 "WHLSLChecker.h" >+ >+#if ENABLE(WEBGPU) >+ >+#include "WHLSLArrayReferenceType.h" >+#include "WHLSLArrayType.h" >+#include "WHLSLAssignmentExpression.h" >+#include "WHLSLCallExpression.h" >+#include "WHLSLCommaExpression.h" >+#include "WHLSLDereferenceExpression.h" >+#include "WHLSLDoWhileLoop.h" >+#include "WHLSLDotExpression.h" >+#include "WHLSLForLoop.h" >+#include "WHLSLGatherEntryPointItems.h" >+#include "WHLSLIfStatement.h" >+#include "WHLSLIndexExpression.h" >+#include "WHLSLInferTypes.h" >+#include "WHLSLLogicalExpression.h" >+#include "WHLSLLogicalNotExpression.h" >+#include "WHLSLMakeArrayReferenceExpression.h" >+#include "WHLSLMakePointerExpression.h" >+#include "WHLSLPointerType.h" >+#include "WHLSLProgram.h" >+#include "WHLSLReadModifyWriteExpression.h" >+#include "WHLSLResolvableType.h" >+#include "WHLSLResolveOverloadImpl.h" >+#include "WHLSLResolvingType.h" >+#include "WHLSLReturn.h" >+#include "WHLSLSwitchStatement.h" >+#include "WHLSLTernaryExpression.h" >+#include "WHLSLVisitor.h" >+#include "WHLSLWhileLoop.h" >+#include <wtf/HashMap.h> >+#include <wtf/HashSet.h> >+#include <wtf/Ref.h> >+#include <wtf/Vector.h> >+#include <wtf/text/WTFString.h> >+ >+namespace WebCore { >+ >+namespace WHLSL { >+ >+class PODChecker : public Visitor { >+public: >+ PODChecker() = default; >+ >+ virtual ~PODChecker() = default; >+ >+ void visit(AST::EnumerationDefinition& enumerationDefinition) override >+ { >+ Visitor::visit(enumerationDefinition); >+ } >+ >+ void visit(AST::NativeTypeDeclaration& nativeTypeDeclaration) override >+ { >+ if (!nativeTypeDeclaration.isNumber() >+ && !nativeTypeDeclaration.isVector() >+ && !nativeTypeDeclaration.isMatrix()) >+ setError(); >+ } >+ >+ void visit(AST::StructureDefinition& structureDefinition) override >+ { >+ Visitor::visit(structureDefinition); >+ } >+ >+ void visit(AST::TypeDefinition& typeDefinition) override >+ { >+ Visitor::visit(typeDefinition); >+ } >+ >+ void visit(AST::ArrayType& arrayType) override >+ { >+ Visitor::visit(arrayType); >+ } >+ >+ void visit(AST::PointerType&) override >+ { >+ setError(); >+ } >+ >+ void visit(AST::ArrayReferenceType&) override >+ { >+ setError(); >+ } >+ >+ void visit(AST::TypeReference& typeReference) override >+ { >+ ASSERT(typeReference.resolvedType()); >+ checkErrorAndVisit(*typeReference.resolvedType()); >+ } >+}; >+ >+static Optional<AST::NativeFunctionDeclaration> resolveWithOperatorAnderIndexer(AST::CallExpression& callExpression, AST::ArrayReferenceType& firstArgument, const Intrinsics& intrinsics) >+{ >+ bool isRestricted = false; >+ 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)); >+ return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(callExpression.origin()), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator&[]", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator), isRestricted); >+} >+ >+static Optional<AST::NativeFunctionDeclaration> resolveWithOperatorLength(AST::CallExpression& callExpression, AST::UnnamedType& firstArgument, const Intrinsics& intrinsics) >+{ >+ bool isRestricted = false; >+ 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)); >+ 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), isRestricted); >+} >+ >+static Optional<AST::NativeFunctionDeclaration> resolveWithReferenceComparator(AST::CallExpression& callExpression, ResolvingType& firstArgument, ResolvingType& secondArgument, const Intrinsics& intrinsics) >+{ >+ bool isRestricted = false; >+ bool isOperator = true; >+ auto returnType = AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.boolType()); >+ auto argumentType = WTF::visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> UniqueRef<AST::UnnamedType> { >+ return unnamedType->clone(); >+ }, [&](Ref<ResolvableTypeReference>&) -> UniqueRef<AST::UnnamedType> { >+ return WTF::visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> UniqueRef<AST::UnnamedType> { >+ return unnamedType->clone(); >+ }, [&](Ref<ResolvableTypeReference>&) -> UniqueRef<AST::UnnamedType> { >+ // We encountered "null == null". >+ // The type isn't observable, so we can pick whatever we want. >+ // FIXME: This can probably be generalized, using the "preferred type" infrastructure used by generic literals >+ return AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.intType()); >+ }), secondArgument); >+ }), firstArgument); >+ 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)); >+ return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(callExpression.origin()), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator==", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator), isRestricted); >+} >+ >+static Optional<AST::NativeFunctionDeclaration> resolveByInstantiation(AST::CallExpression& callExpression, const Vector<std::reference_wrapper<ResolvingType>>& types, const Intrinsics& intrinsics) >+{ >+ if (callExpression.name() == "operator&[]" && types.size() == 2) { >+ auto* firstArgumentArrayRef = WTF::visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> AST::ArrayReferenceType* { >+ if (is<AST::ArrayReferenceType>(static_cast<AST::UnnamedType&>(unnamedType))) >+ return &downcast<AST::ArrayReferenceType>(static_cast<AST::UnnamedType&>(unnamedType)); >+ return nullptr; >+ }, [](Ref<ResolvableTypeReference>&) -> AST::ArrayReferenceType* { >+ return nullptr; >+ }), types[0].get()); >+ bool secondArgumentIsUint = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& unnamedType) -> bool { >+ return matches(static_cast<AST::UnnamedType&>(unnamedType), intrinsics.uintType()); >+ }, [&](Ref<ResolvableTypeReference>& resolvableTypeReference) -> bool { >+ return resolvableTypeReference->resolvableType().canResolve(intrinsics.uintType()); >+ }), types[1].get()); >+ if (firstArgumentArrayRef && secondArgumentIsUint) >+ return resolveWithOperatorAnderIndexer(callExpression, *firstArgumentArrayRef, intrinsics); >+ } else if (callExpression.name() == "operator.length" && types.size() == 1) { >+ auto* firstArgumentReference = WTF::visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> AST::UnnamedType* { >+ if (is<AST::ArrayReferenceType>(static_cast<AST::UnnamedType&>(unnamedType)) || is<AST::ArrayType>(static_cast<AST::UnnamedType&>(unnamedType))) >+ return &static_cast<AST::UnnamedType&>(unnamedType); >+ return nullptr; >+ }, [](Ref<ResolvableTypeReference>&) -> AST::UnnamedType* { >+ return nullptr; >+ }), types[0].get()); >+ if (firstArgumentReference) >+ return resolveWithOperatorLength(callExpression, *firstArgumentReference, intrinsics); >+ } else if (callExpression.name() == "operator==" && types.size() == 2) { >+ auto isAcceptable = [](ResolvingType& resolvingType) -> bool { >+ return WTF::visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> bool { >+ return is<AST::ReferenceType>(static_cast<AST::UnnamedType&>(unnamedType)); >+ }, [](Ref<ResolvableTypeReference>& resolvableTypeReference) -> bool { >+ return is<AST::NullLiteralType>(resolvableTypeReference->resolvableType()); >+ }), resolvingType); >+ }; >+ if (isAcceptable(types[0].get()) && isAcceptable(types[1].get())) >+ return resolveWithReferenceComparator(callExpression, types[0].get(), types[1].get(), intrinsics); >+ } >+ return WTF::nullopt; >+} >+ >+// FIXME: We need to check error() before all the ASSERT(iterator != m_typeMap.end()); checks. >+class Checker : public Visitor { >+public: >+ Checker(const Intrinsics& intrinsics, Program& program) >+ : m_intrinsics(intrinsics) >+ , m_program(program) >+ { >+ } >+ >+ ~Checker() = default; >+ >+ void visit(Program& program) override >+ { >+ for (auto& typeDefinition : program.typeDefinitions()) >+ checkErrorAndVisit(static_cast<AST::TypeDefinition&>(typeDefinition)); >+ for (auto& structureDefinition : program.structureDefinitions()) >+ checkErrorAndVisit(static_cast<AST::StructureDefinition&>(structureDefinition)); >+ for (auto& enumerationDefinition : program.enumerationDefinitions()) >+ checkErrorAndVisit(static_cast<AST::EnumerationDefinition&>(enumerationDefinition)); >+ for (auto& nativeTypeDeclaration : program.nativeTypeDeclarations()) >+ checkErrorAndVisit(static_cast<AST::NativeTypeDeclaration&>(nativeTypeDeclaration)); >+ >+ for (auto& functionDefinition : program.functionDefinitions()) >+ checkErrorAndVisit(static_cast<AST::FunctionDefinition&>(functionDefinition)); >+ for (auto& nativeFunctionDeclaration : program.nativeFunctionDeclarations()) >+ checkErrorAndVisit(static_cast<AST::NativeFunctionDeclaration&>(nativeFunctionDeclaration)); >+ } >+ >+private: >+ bool checkShaderType(const AST::FunctionDefinition& functionDefinition) >+ { >+ switch (*functionDefinition.entryPointType()) { >+ case AST::FunctionDefinition::EntryPointType::Vertex: >+ return !m_vertexEntryPoints.add(functionDefinition.name()).isNewEntry; >+ case AST::FunctionDefinition::EntryPointType::Fragment: >+ return !m_fragmentEntryPoints.add(functionDefinition.name()).isNewEntry; >+ case AST::FunctionDefinition::EntryPointType::Compute: >+ return !m_computeEntryPoints.add(functionDefinition.name()).isNewEntry; >+ } >+ } >+ >+ bool checkSemantics(AST::FunctionDefinition& functionDefinition) >+ { >+ auto entryPointItems = gatherEntryPointItems(m_intrinsics, functionDefinition); >+ if (!entryPointItems) >+ return false; >+ auto inputItems = WTFMove(entryPointItems->inputs); >+ auto outputItems = WTFMove(entryPointItems->outputs); >+ >+ { >+ auto checkDuplicateSemantics = [&](const Vector<EntryPointItem>& items) -> bool { >+ for (size_t i = 0; i < items.size(); ++i) { >+ for (size_t j = i + 1; j < items.size(); ++j) { >+ if (items[i].semantic == items[j].semantic) >+ return false; >+ } >+ } >+ return true; >+ }; >+ if (!checkDuplicateSemantics(inputItems)) >+ return false; >+ if (!checkDuplicateSemantics(outputItems)) >+ return false; >+ } >+ >+ { >+ auto checkSemanticTypes = [&](const Vector<EntryPointItem>& items) -> bool { >+ for (auto& item : items) { >+ auto acceptable = WTF::visit(WTF::makeVisitor([&](const AST::BaseSemantic& semantic) -> bool { >+ return semantic.isAcceptableType(item.unnamedType, m_intrinsics); >+ }), item.semantic); >+ if (!acceptable) >+ return false; >+ } >+ return true; >+ }; >+ if (!checkSemanticTypes(inputItems)) >+ return false; >+ if (!checkSemanticTypes(outputItems)) >+ return false; >+ } >+ >+ { >+ auto checkSemanticForShaderType = [&](const Vector<EntryPointItem>& items, AST::BaseSemantic::ShaderItemDirection direction) -> bool { >+ for (auto& item : items) { >+ auto acceptable = WTF::visit(WTF::makeVisitor([&](const AST::BaseSemantic& semantic) -> bool { >+ return semantic.isAcceptableForShaderItemDirection(direction, functionDefinition); >+ }), item.semantic); >+ if (!acceptable) >+ return false; >+ } >+ return true; >+ }; >+ if (!checkSemanticForShaderType(inputItems, AST::BaseSemantic::ShaderItemDirection::Input)) >+ return false; >+ if (!checkSemanticForShaderType(outputItems, AST::BaseSemantic::ShaderItemDirection::Output)) >+ return false; >+ } >+ >+ { >+ auto checkPODData = [&](const Vector<EntryPointItem>& items) -> bool { >+ for (auto& item : items) { >+ PODChecker podChecker; >+ if (is<AST::PointerType>(item.unnamedType)) >+ podChecker.checkErrorAndVisit(downcast<AST::PointerType>(item.unnamedType).elementType()); >+ else if (is<AST::ArrayReferenceType>(item.unnamedType)) >+ podChecker.checkErrorAndVisit(downcast<AST::ArrayReferenceType>(item.unnamedType).elementType()); >+ else if (is<AST::ArrayType>(item.unnamedType)) >+ podChecker.checkErrorAndVisit(downcast<AST::ArrayType>(item.unnamedType).type()); >+ else >+ continue; >+ if (podChecker.error()) >+ return false; >+ } >+ return true; >+ }; >+ if (!checkPODData(inputItems)) >+ return false; >+ if (!checkPODData(outputItems)) >+ return false; >+ } >+ >+ return true; >+ } >+ >+ bool checkOperatorOverload(const AST::FunctionDefinition& functionDefinition) >+ { >+ enum class CheckKind { >+ Index, >+ Dot >+ }; >+ >+ auto checkGetter = [&](CheckKind kind) -> bool { >+ size_t numExpectedParameters = kind == CheckKind::Index ? 2 : 1; >+ if (functionDefinition.parameters().size() != numExpectedParameters) >+ return false; >+ auto& unifyNode = (*functionDefinition.parameters()[0].type())->unifyNode(); >+ if (is<AST::UnnamedType>(unifyNode)) { >+ auto& unnamedType = downcast<AST::UnnamedType>(unifyNode); >+ if (is<AST::PointerType>(unnamedType)) >+ return false; >+ } >+ return true; >+ }; >+ >+ auto checkSetter = [&](CheckKind kind) -> bool { >+ size_t numExpectedParameters = kind == CheckKind::Index ? 3 : 2; >+ if (functionDefinition.parameters().size() != numExpectedParameters) >+ return false; >+ auto& firstArgumentUnifyNode = (*functionDefinition.parameters()[0].type())->unifyNode(); >+ if (is<AST::UnnamedType>(firstArgumentUnifyNode)) { >+ auto& unnamedType = downcast<AST::UnnamedType>(firstArgumentUnifyNode); >+ if (is<AST::PointerType>(unnamedType)) >+ return false; >+ } >+ if (!matches(functionDefinition.type(), *functionDefinition.parameters()[0].type())) >+ return false; >+ auto& valueType = *functionDefinition.parameters()[numExpectedParameters - 1].type(); >+ auto getterName = functionDefinition.name().substring(0, functionDefinition.name().length() - 1); >+ auto* getterFuncs = m_program.nameContext().getFunctions(getterName); >+ if (!getterFuncs) >+ return false; >+ 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()); >+ for (auto& argumentType : argumentTypes) >+ argumentTypeReferences.append(argumentType); >+ Optional<std::reference_wrapper<AST::NamedType>> castReturnType = WTF::nullopt; >+ auto* overload = resolveFunctionOverloadImpl(*getterFuncs, argumentTypeReferences, castReturnType); >+ if (!overload) >+ return false; >+ auto& resultType = overload->type(); >+ if (!matches(resultType, valueType)) >+ return false; >+ return true; >+ }; >+ >+ auto checkAnder = [&](CheckKind kind) -> bool { >+ size_t numExpectedParameters = kind == CheckKind::Index ? 2 : 1; >+ if (functionDefinition.parameters().size() != numExpectedParameters) >+ return false; >+ { >+ auto& unifyNode = functionDefinition.type().unifyNode(); >+ if (!is<AST::UnnamedType>(unifyNode)) >+ return false; >+ auto& unnamedType = downcast<AST::UnnamedType>(unifyNode); >+ if (!is<AST::PointerType>(unnamedType)) >+ return false; >+ } >+ { >+ auto& unifyNode = (*functionDefinition.parameters()[0].type())->unifyNode(); >+ if (!is<AST::UnnamedType>(unifyNode)) >+ return false; >+ auto& unnamedType = downcast<AST::UnnamedType>(unifyNode); >+ if (!is<AST::PointerType>(unnamedType) && !is<AST::ArrayReferenceType>(unnamedType)) >+ return false; >+ } >+ >+ return true; >+ }; >+ >+ if (!functionDefinition.isOperator()) >+ return true; >+ if (functionDefinition.isCast()) >+ return true; >+ if (functionDefinition.name() == "operator++" >+ || functionDefinition.name() == "operator--") { >+ if (functionDefinition.parameters().size() != 1) >+ return false; >+ if (!matches(*functionDefinition.parameters()[0].type(), functionDefinition.type())) >+ return false; >+ return true; >+ } >+ if (functionDefinition.name() == "operator+" >+ || functionDefinition.name() == "operator-") { >+ if (functionDefinition.parameters().size() != 1 >+ && functionDefinition.parameters().size() != 2) >+ return false; >+ return true; >+ } >+ if (functionDefinition.name() == "operator*" >+ || functionDefinition.name() == "operator/" >+ || functionDefinition.name() == "operator%" >+ || functionDefinition.name() == "operator&" >+ || functionDefinition.name() == "operator|" >+ || functionDefinition.name() == "operator^" >+ || functionDefinition.name() == "operator<<" >+ || functionDefinition.name() == "opreator>>") { >+ if (functionDefinition.parameters().size() != 2) >+ return false; >+ return true; >+ } >+ if (functionDefinition.name() == "operator~") { >+ if (functionDefinition.parameters().size() != 1) >+ return false; >+ return true; >+ } >+ if (functionDefinition.name() == "operator==" >+ || functionDefinition.name() == "operator<" >+ || functionDefinition.name() == "operator<=" >+ || functionDefinition.name() == "operator>" >+ || functionDefinition.name() == "operator>=") { >+ if (functionDefinition.parameters().size() != 2) >+ return false; >+ if (!matches(functionDefinition.type(), m_intrinsics.boolType())) >+ return false; >+ return true; >+ } >+ if (functionDefinition.name() == "operator[]") { >+ if (!checkGetter(CheckKind::Index)) >+ return false; >+ return true; >+ } >+ if (functionDefinition.name() == "operator[]=") { >+ if (!checkSetter(CheckKind::Index)) >+ return false; >+ return true; >+ } >+ if (functionDefinition.name() == "operator&[]") { >+ if (!checkAnder(CheckKind::Index)) >+ return false; >+ return true; >+ } >+ if (functionDefinition.name().startsWith("operator.")) { >+ if (functionDefinition.name().endsWith("=")) { >+ if (!checkSetter(CheckKind::Dot)) >+ return false; >+ } else { >+ if (!checkGetter(CheckKind::Dot)) >+ return false; >+ } >+ return true; >+ } >+ if (functionDefinition.name().startsWith("operator&.")) { >+ if (!checkAnder(CheckKind::Dot)) >+ return false; >+ return true; >+ } >+ return false; >+ } >+ >+ void visit(AST::FunctionDefinition& functionDefinition) override >+ { >+ if (functionDefinition.entryPointType()) { >+ if (!checkShaderType(functionDefinition)) { >+ setError(); >+ return; >+ } >+ if (!checkSemantics(functionDefinition)) { >+ setError(); >+ return; >+ } >+ } >+ if (!checkOperatorOverload(functionDefinition)) { >+ setError(); >+ return; >+ } >+ >+ checkErrorAndVisit(functionDefinition); >+ } >+ >+ void visit(AST::EnumerationDefinition& enumerationDefinition) override >+ { >+ if (!enumerationDefinition.type()) { >+ // FIXME: Handle a null base type. >+ setError(); >+ return; >+ } >+ checkErrorAndVisit(static_cast<AST::UnnamedType&>(*enumerationDefinition.type())); >+ >+ auto& baseType = static_cast<AST::UnnamedType&>(*enumerationDefinition.type()).unifyNode(); >+ >+ if (!is<AST::UnnamedType>(baseType)) { >+ setError(); >+ return; >+ } >+ auto& unnamedBase = downcast<AST::UnnamedType>(baseType); >+ if (!is<AST::TypeReference>(unnamedBase)) { >+ setError(); >+ return; >+ } >+ auto& typeReferenceBase = downcast<AST::TypeReference>(unnamedBase); >+ ASSERT(typeReferenceBase.resolvedType()); >+ if (!is<AST::NativeTypeDeclaration>(*typeReferenceBase.resolvedType())) { >+ setError(); >+ return; >+ } >+ auto& nativeTypeDeclaration = downcast<AST::NativeTypeDeclaration>(*typeReferenceBase.resolvedType()); >+ if (!nativeTypeDeclaration.isInt()) { >+ setError(); >+ return; >+ } >+ >+ auto enumerationMembers = enumerationDefinition.enumerationMembers(); >+ >+ for (auto& member : enumerationMembers) { >+ if (!member.get().value()) >+ continue; >+ >+ bool success; >+ member.get().value()->visit(WTF::makeVisitor([&](auto& value) { >+ checkErrorAndVisit(value); >+ auto iterator = m_typeMap.find(&value); >+ ASSERT(iterator != m_typeMap.end()); >+ success = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& unnamedType) -> bool { >+ return matches(static_cast<AST::UnnamedType&>(unnamedType), enumerationDefinition); >+ }, [&](ResolvableTypeReference& resolvableTypeReference) -> bool { >+ return static_cast<bool>(matchAndCommit(enumerationDefinition, resolvableTypeReference.resolvableType())); >+ }), iterator->value); >+ })); >+ if (!success) { >+ setError(); >+ return; >+ } >+ } >+ >+ int64_t nextValue = 0; >+ for (auto& member : enumerationMembers) { >+ if (member.get().value()) { >+ int64_t value; >+ member.get().value()->visit(WTF::makeVisitor([&](AST::IntegerLiteral& integerLiteral) { >+ value = integerLiteral.valueForSelectedType(); >+ }, [&](AST::UnsignedIntegerLiteral& unsignedIntegerLiteral) { >+ value = unsignedIntegerLiteral.valueForSelectedType(); >+ }, [&](AST::FloatLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::NullLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::BooleanLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::EnumerationMemberLiteral&) { >+ ASSERT_NOT_REACHED(); >+ })); >+ nextValue = nativeTypeDeclaration.successor()(value); >+ } else { >+ member.get().setValue(AST::ConstantExpression(AST::IntegerLiteral(Lexer::Token(member.get().origin()), nextValue))); >+ nextValue = nativeTypeDeclaration.successor()(nextValue); >+ } >+ } >+ >+ for (size_t i = 0; i < enumerationMembers.size(); ++i) { >+ auto& member = enumerationMembers[i].get(); >+ ASSERT(member.value()); >+ int64_t value; >+ member.value()->visit(WTF::makeVisitor([&](AST::IntegerLiteral& integerLiteral) { >+ value = integerLiteral.value(); >+ }, [&](AST::UnsignedIntegerLiteral& unsignedIntegerLiteral) { >+ value = unsignedIntegerLiteral.value(); >+ }, [&](AST::FloatLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::NullLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::BooleanLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::EnumerationMemberLiteral&) { >+ ASSERT_NOT_REACHED(); >+ })); >+ for (size_t j = i + 1; j < enumerationMembers.size(); ++j) { >+ auto& otherMember = enumerationMembers[j].get(); >+ ASSERT(otherMember.value()); >+ bool fail = false; >+ otherMember.value()->visit(WTF::makeVisitor([&](AST::IntegerLiteral& integerLiteral) { >+ fail = value == integerLiteral.value(); >+ }, [&](AST::UnsignedIntegerLiteral& unsignedIntegerLiteral) { >+ fail = value == unsignedIntegerLiteral.value(); >+ }, [&](AST::FloatLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::NullLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::BooleanLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::EnumerationMemberLiteral&) { >+ ASSERT_NOT_REACHED(); >+ })); >+ if (fail) { >+ setError(); >+ return; >+ } >+ } >+ } >+ >+ bool foundZero = false; >+ for (auto& member : enumerationMembers) { >+ ASSERT(member.get().value()); >+ member.get().value()->visit(WTF::makeVisitor([&](AST::IntegerLiteral& integerLiteral) { >+ if (!integerLiteral.value()) >+ foundZero = true; >+ }, [&](AST::UnsignedIntegerLiteral& unsignedIntegerLiteral) { >+ if (!unsignedIntegerLiteral.value()) >+ foundZero = true; >+ }, [&](AST::FloatLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::NullLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::BooleanLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::EnumerationMemberLiteral&) { >+ ASSERT_NOT_REACHED(); >+ })); >+ } >+ if (!foundZero) { >+ setError(); >+ return; >+ } >+ } >+ >+ void visit(AST::TypeReference& typeReference) override >+ { >+ ASSERT(typeReference.resolvedType()); >+ >+ checkErrorAndVisit(typeReference); >+ } >+ >+ void visit(AST::VariableDeclaration& variableDeclaration) override >+ { >+ checkErrorAndVisit(*variableDeclaration.type()); // FIXME: Make this work with anonymous variables which don't have types. >+ if (variableDeclaration.initializer()) { >+ auto& lhsType = *variableDeclaration.type(); >+ checkErrorAndVisit(*variableDeclaration.initializer()); >+ auto iterator = m_typeMap.find(variableDeclaration.initializer()); >+ ASSERT(iterator != m_typeMap.end()); >+ auto& rhs = iterator->value; >+ auto success = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& unnamedType) -> bool { >+ return matches(lhsType, static_cast<AST::UnnamedType&>(unnamedType)); >+ }, [&](Ref<ResolvableTypeReference>& resolvableTypeReference) -> bool { >+ return static_cast<bool>(matchAndCommit(lhsType, resolvableTypeReference->resolvableType())); >+ }), rhs); >+ if (!success) { >+ setError(); >+ return; >+ } >+ } >+ } >+ >+ void visit(AST::AssignmentExpression& assignmentExpression) override >+ { >+ checkErrorAndVisit(assignmentExpression.left()); >+ auto leftIterator = m_typeMap.find(&assignmentExpression.left()); >+ ASSERT(leftIterator != m_typeMap.end()); >+ auto& lhsType = leftIterator->value; >+ auto addressSpaceIterator = m_addressSpaceMap.find(&assignmentExpression.left()); >+ ASSERT(addressSpaceIterator != m_addressSpaceMap.end()); >+ if (!addressSpaceIterator->value) { >+ setError(); >+ return; >+ } >+ checkErrorAndVisit(assignmentExpression.right()); >+ auto rightIterator = m_typeMap.find(&assignmentExpression.right()); >+ ASSERT(rightIterator != m_typeMap.end()); >+ auto& rhsType = rightIterator->value; >+ auto resultType = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& left) -> Optional<UniqueRef<AST::UnnamedType>> { >+ return WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& right) -> Optional<UniqueRef<AST::UnnamedType>> { >+ if (matches(static_cast<AST::UnnamedType&>(left), static_cast<AST::UnnamedType&>(right))) >+ return left->clone(); >+ return WTF::nullopt; >+ }, [&](Ref<ResolvableTypeReference>& right) -> Optional<UniqueRef<AST::UnnamedType>> { >+ return matchAndCommit(static_cast<AST::UnnamedType&>(left), right->resolvableType()); >+ }), rhsType); >+ }, [&](Ref<ResolvableTypeReference>& left) -> Optional<UniqueRef<AST::UnnamedType>> { >+ return WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& right) -> Optional<UniqueRef<AST::UnnamedType>> { >+ return matchAndCommit(static_cast<AST::UnnamedType&>(right), left->resolvableType()); >+ }, [&](Ref<ResolvableTypeReference>& right) -> Optional<UniqueRef<AST::UnnamedType>> { >+ return matchAndCommit(left->resolvableType(), right->resolvableType()); >+ }), rhsType); >+ }), lhsType); >+ if (!resultType) { >+ setError(); >+ return; >+ } >+ auto addResult = m_typeMap.add(&assignmentExpression, WTFMove(*resultType)); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&assignmentExpression, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void visit(AST::ReadModifyWriteExpression& readModifyWriteExpression) override >+ { >+ checkErrorAndVisit(readModifyWriteExpression.lValue()); >+ auto lValueIterator = m_typeMap.find(&readModifyWriteExpression.lValue()); >+ ASSERT(lValueIterator != m_typeMap.end()); >+ auto& lhsType = lValueIterator->value; >+ auto addressSpaceIterator = m_addressSpaceMap.find(&readModifyWriteExpression.lValue()); >+ ASSERT(addressSpaceIterator != m_addressSpaceMap.end()); >+ if (!addressSpaceIterator->value) { >+ setError(); >+ return; >+ } >+ // FIXME: Figure out what to do with the ReadModifyWriteExpression's AnonymousVariables. >+ ASSERT(readModifyWriteExpression.newValueExpression()); >+ checkErrorAndVisit(*readModifyWriteExpression.newValueExpression()); >+ auto newValueIterator = m_typeMap.find(readModifyWriteExpression.newValueExpression()); >+ ASSERT(newValueIterator != m_typeMap.end()); >+ auto& newValueType = newValueIterator->value; >+ auto success = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& left) -> bool { >+ return WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& right) -> bool { >+ return matches(static_cast<AST::UnnamedType&>(left), static_cast<AST::UnnamedType&>(right)); >+ }, [&](Ref<ResolvableTypeReference>& right) -> bool { >+ return static_cast<bool>(matchAndCommit(static_cast<AST::UnnamedType&>(left), right->resolvableType())); >+ }), newValueType); >+ }, [&](Ref<ResolvableTypeReference>& left) -> bool { >+ return WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& right) -> bool { >+ return static_cast<bool>(matchAndCommit(static_cast<AST::UnnamedType&>(right), left->resolvableType())); >+ }, [&](Ref<ResolvableTypeReference>& right) -> bool { >+ return static_cast<bool>(matchAndCommit(left->resolvableType(), right->resolvableType())); >+ }), newValueType); >+ }), lhsType); >+ if (!success) { >+ setError(); >+ return; >+ } >+ ASSERT(readModifyWriteExpression.resultExpression()); >+ checkErrorAndVisit(*readModifyWriteExpression.resultExpression()); >+ auto resultIterator = m_typeMap.find(readModifyWriteExpression.resultExpression()); >+ ASSERT(resultIterator != m_typeMap.end()); >+ auto& resultType = resultIterator->value; >+ WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& result) { >+ auto addResult = m_typeMap.add(&readModifyWriteExpression, result->clone()); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ }, [&](Ref<ResolvableTypeReference>& result) { >+ auto addResult = m_typeMap.add(&readModifyWriteExpression, result.copyRef()); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ }), resultType); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&readModifyWriteExpression, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void visit(AST::DereferenceExpression& dereferenceExpression) override >+ { >+ checkErrorAndVisit(dereferenceExpression.pointer()); >+ auto pointerIterator = m_typeMap.find(&dereferenceExpression.pointer()); >+ ASSERT(pointerIterator != m_typeMap.end()); >+ auto& type = pointerIterator->value; >+ auto* pointerType = WTF::visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& type) -> AST::PointerType* { >+ auto& unifyNode = type->unifyNode(); >+ if (!is<AST::UnnamedType>(unifyNode)) >+ return nullptr; >+ auto& unnamedType = downcast<AST::UnnamedType>(unifyNode); >+ if (!is<AST::PointerType>(unnamedType)) >+ return nullptr; >+ return &downcast<AST::PointerType>(unnamedType); >+ }, [](Ref<ResolvableTypeReference>& type) -> AST::PointerType* { >+ auto* resolvedType = type->resolvableType().resolvedType(); >+ if (!resolvedType) >+ return nullptr; >+ auto& unifyNode = resolvedType->unifyNode(); >+ if (!is<AST::UnnamedType>(unifyNode)) >+ return nullptr; >+ auto& unnamedType = downcast<AST::UnnamedType>(unifyNode); >+ if (!is<AST::PointerType>(unnamedType)) >+ return nullptr; >+ return &downcast<AST::PointerType>(unnamedType); >+ }), type); >+ if (!pointerType) { >+ setError(); >+ return; >+ } >+ auto addResult = m_typeMap.add(&dereferenceExpression, pointerType->clone()); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&dereferenceExpression, pointerType->addressSpace()); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void visit(AST::MakePointerExpression& makePointerExpression) override >+ { >+ checkErrorAndVisit(makePointerExpression.lValue()); >+ auto lValueIterator = m_typeMap.find(&makePointerExpression.lValue()); >+ ASSERT(lValueIterator != m_typeMap.end()); >+ auto& elementType = lValueIterator->value; >+ auto* lValueType = WTF::visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& type) -> AST::UnnamedType* { >+ return &static_cast<AST::UnnamedType&>(type); >+ }, [](Ref<ResolvableTypeReference>& type) -> AST::UnnamedType* { >+ // FIXME: Should we commit() the type? >+ return type->resolvableType().resolvedType(); >+ }), elementType); >+ if (!lValueType) { >+ setError(); >+ return; >+ } >+ auto addressSpaceIterator = m_addressSpaceMap.find(&makePointerExpression.lValue()); >+ ASSERT(addressSpaceIterator != m_addressSpaceMap.end()); >+ if (!addressSpaceIterator->value) { >+ setError(); >+ return; >+ } >+ auto addResult = m_typeMap.add(&makePointerExpression, ResolvingType(makeUniqueRef<AST::PointerType>(Lexer::Token(makePointerExpression.origin()), *addressSpaceIterator->value, lValueType->clone()))); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&makePointerExpression, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void visit(AST::MakeArrayReferenceExpression& makeArrayReferenceExpression) override >+ { >+ checkErrorAndVisit(makeArrayReferenceExpression.lValue()); >+ auto lValueIterator = m_typeMap.find(&makeArrayReferenceExpression.lValue()); >+ ASSERT(lValueIterator != m_typeMap.end()); >+ auto& elementType = lValueIterator->value; >+ auto* unnamedType = WTF::visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& type) -> AST::UnnamedType* { >+ return &static_cast<AST::UnnamedType&>(type); >+ }, [](Ref<ResolvableTypeReference>& type) -> AST::UnnamedType* { >+ return type->resolvableType().resolvedType(); >+ }), elementType); >+ if (!unnamedType) { >+ setError(); >+ return; >+ } >+ auto& unifyNode = unnamedType->unifyNode(); >+ if (is<AST::UnnamedType>(unifyNode)) { >+ auto& unnamedType = downcast<AST::UnnamedType>(unifyNode); >+ if (is<AST::PointerType>(unnamedType)) { >+ auto& pointerType = downcast<AST::PointerType>(unnamedType); >+ // FIXME: Save the fact that we're not targetting the item; we're targetting the item's inner element. >+ auto addResult = m_typeMap.add(&makeArrayReferenceExpression, ResolvingType(makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(makeArrayReferenceExpression.origin()), pointerType.addressSpace(), pointerType.elementType().clone()))); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&makeArrayReferenceExpression, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ return; >+ } >+ >+ auto addressSpaceIterator = m_addressSpaceMap.find(&makeArrayReferenceExpression.lValue()); >+ ASSERT(addressSpaceIterator != m_addressSpaceMap.end()); >+ if (!addressSpaceIterator->value) { >+ setError(); >+ return; >+ } >+ >+ if (is<AST::ArrayType>(unnamedType)) { >+ auto& arrayType = downcast<AST::ArrayType>(unnamedType); >+ // FIXME: Save the number of elements. >+ auto addResult = m_typeMap.add(&makeArrayReferenceExpression, ResolvingType(makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(makeArrayReferenceExpression.origin()), *addressSpaceIterator->value, arrayType.type().clone()))); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&makeArrayReferenceExpression, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ return; >+ } >+ } >+ >+ auto addressSpaceIterator = m_addressSpaceMap.find(&makeArrayReferenceExpression.lValue()); >+ ASSERT(addressSpaceIterator != m_addressSpaceMap.end()); >+ if (!addressSpaceIterator->value) { >+ setError(); >+ return; >+ } >+ auto addResult = m_typeMap.add(&makeArrayReferenceExpression, ResolvingType(makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(makeArrayReferenceExpression.origin()), *addressSpaceIterator->value, unnamedType->clone()))); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&makeArrayReferenceExpression, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void finishVisitingPropertyAccess(AST::PropertyAccessExpression& propertyAccessExpression, AST::UnnamedType& wrappedBaseType, AST::UnnamedType* extraArgumentType = nullptr) >+ { >+ Optional<std::reference_wrapper<AST::NamedType>> castReturnType; >+ 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()); >+ >+ Vector<std::reference_wrapper<ResolvingType>> getArgumentTypes; >+ getArgumentTypes.append(getArgumentType1); >+ if (getArgumentType2) >+ getArgumentTypes.append(*getArgumentType2); >+ >+ auto* getFunction = resolveFunctionOverloadImpl(propertyAccessExpression.possibleGetOverloads(), getArgumentTypes, castReturnType); >+ 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 { makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(propertyAccessExpression.origin()), AST::ReferenceType::AddressSpace::Thread, downcast<AST::ArrayType>(unnamedType).type().clone()) }; >+ if (is<AST::PointerType>(unnamedType)) >+ return WTF::nullopt; >+ return { makeUniqueRef<AST::PointerType>(Lexer::Token(propertyAccessExpression.origin()), AST::ReferenceType::AddressSpace::Thread, downcast<AST::ArrayType>(unnamedType).type().clone()) }; >+ }; >+ auto computeAndReturnType = [&](AST::UnnamedType& unnamedType) -> AST::UnnamedType* { >+ if (is<AST::PointerType>(unnamedType)) >+ return &downcast<AST::PointerType>(unnamedType).elementType(); >+ return nullptr; >+ }; >+ >+ auto andArgumentType1 = computeAndArgumentType(static_cast<AST::UnnamedType&>(wrappedBaseType)); >+ if (!andArgumentType1) >+ return std::make_pair(nullptr, nullptr); >+ Optional<ResolvingType> andArgumentType2; >+ if (extraArgumentType) >+ andArgumentType2 = ResolvingType(extraArgumentType->clone()); >+ >+ Vector<std::reference_wrapper<ResolvingType>> andArgumentTypes; >+ andArgumentTypes.append(*andArgumentType1); >+ if (andArgumentType2) >+ andArgumentTypes.append(*andArgumentType2); >+ >+ auto* andFunction = resolveFunctionOverloadImpl(propertyAccessExpression.possibleAndOverloads(), andArgumentTypes, castReturnType); >+ if (!andFunction) >+ return std::make_pair(nullptr, nullptr); >+ return std::make_pair(andFunction, computeAndReturnType(andFunction->type())); >+ })(); >+ >+ if (!getReturnType && !andReturnType) { >+ setError(); >+ return; >+ } >+ >+ if (getReturnType && andReturnType && !matches(*getReturnType, *andReturnType)) { >+ 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()); >+ >+ Vector<std::reference_wrapper<ResolvingType>> setArgumentTypes; >+ setArgumentTypes.append(setArgument1Type); >+ if (setArgumentType2) >+ setArgumentTypes.append(*setArgumentType2); >+ setArgumentTypes.append(setArgument3Type); >+ >+ auto* setFunction = resolveFunctionOverloadImpl(propertyAccessExpression.possibleSetOverloads(), setArgumentTypes, castReturnType); >+ if (!setFunction) >+ return std::make_pair(nullptr, nullptr); >+ return std::make_pair(setFunction, &setFunction->type()); >+ })(); >+ >+ if (setFunction) { >+ if (!matches(setFunction->type(), static_cast<AST::UnnamedType&>(wrappedBaseType))) { >+ setError(); >+ return; >+ } >+ } >+ >+ if (!getReturnType && !andReturnType) { >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&propertyAccessExpression, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } else { >+ // FIXME: The reference compiler has "else if (!node.base.isLValue && !baseType.isArrayRef)", >+ // but I don't understand why it exists. I haven't reproduced it here, and I'll investigate >+ // if we can remove it from the reference compiler. >+ AST::ReferenceType::AddressSpace addressSpace; >+ 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; >+ } >+ } >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&propertyAccessExpression, addressSpace); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ // FIXME: Generate the call expressions >+ } >+ >+ void visit(AST::DotExpression& dotExpression) override >+ { >+ checkErrorAndVisit(dotExpression.base()); >+ auto baseIterator = m_typeMap.find(&dotExpression.base()); >+ ASSERT(baseIterator != m_typeMap.end()); >+ auto& baseType = baseIterator->value; >+ auto* baseUnifyNode = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& baseType) -> AST::Type* { >+ return &baseType->unifyNode(); >+ }, [&](Ref<ResolvableTypeReference>& baseType) -> AST::Type* { >+ if (!baseType->resolvableType().resolvedType()) { >+ if (!static_cast<bool>(commit(baseType->resolvableType()))) >+ return nullptr; >+ } >+ return &baseType->resolvableType().resolvedType()->unifyNode(); >+ }), baseType); >+ if (!baseUnifyNode) { >+ setError(); >+ return; >+ } >+ auto wrappedBaseType = ([&]() -> UniqueRef<AST::UnnamedType> { >+ if (is<AST::UnnamedType>(*baseUnifyNode)) >+ return downcast<AST::UnnamedType>(*baseUnifyNode).clone(); >+ ASSERT(is<AST::NamedType>(baseUnifyNode)); >+ return AST::TypeReference::wrap(Lexer::Token(dotExpression.origin()), downcast<AST::NamedType>(*baseUnifyNode)); >+ })(); >+ >+ finishVisitingPropertyAccess(dotExpression, static_cast<AST::UnnamedType&>(wrappedBaseType)); >+ } >+ >+ void visit(AST::IndexExpression& indexExpression) override >+ { >+ auto wrappedBaseType = ([&]() -> Optional<UniqueRef<AST::UnnamedType>> { >+ checkErrorAndVisit(indexExpression.base()); >+ auto baseIterator = m_typeMap.find(&indexExpression.base()); >+ ASSERT(baseIterator != m_typeMap.end()); >+ auto& baseType = baseIterator->value; >+ auto* baseUnifyNode = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& baseType) -> AST::Type* { >+ return &baseType->unifyNode(); >+ }, [&](Ref<ResolvableTypeReference>& baseType) -> AST::Type* { >+ if (!baseType->resolvableType().resolvedType()) { >+ if (!static_cast<bool>(commit(baseType->resolvableType()))) >+ return nullptr; >+ } >+ return &baseType->resolvableType().resolvedType()->unifyNode(); >+ }), baseType); >+ if (!baseUnifyNode) >+ return WTF::nullopt; >+ return ([&]() -> UniqueRef<AST::UnnamedType> { >+ if (is<AST::UnnamedType>(*baseUnifyNode)) >+ return downcast<AST::UnnamedType>(*baseUnifyNode).clone(); >+ ASSERT(is<AST::NamedType>(baseUnifyNode)); >+ return AST::TypeReference::wrap(Lexer::Token(indexExpression.origin()), downcast<AST::NamedType>(*baseUnifyNode)); >+ })(); >+ })(); >+ if (!wrappedBaseType) { >+ setError(); >+ return; >+ } >+ >+ auto indexExpressionType = ([&]() -> AST::UnnamedType* { >+ checkErrorAndVisit(indexExpression.indexExpression()); >+ auto indexExpressionIterator = m_typeMap.find(&indexExpression.indexExpression()); >+ ASSERT(indexExpressionIterator != m_typeMap.end()); >+ auto& indexExpressionType = indexExpressionIterator->value; >+ // FIXME: Should we be calling unifyNode() here? >+ auto* committedIndexExpressionType = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& indexExpressionType) -> AST::UnnamedType* { >+ return &static_cast<AST::UnnamedType&>(indexExpressionType); >+ }, [&](Ref<ResolvableTypeReference>& indexExpressionType) -> AST::UnnamedType* { >+ if (!indexExpressionType->resolvableType().resolvedType()) { >+ if (!static_cast<bool>(commit(indexExpressionType->resolvableType()))) >+ return nullptr; >+ } >+ return indexExpressionType->resolvableType().resolvedType(); >+ }), indexExpressionType); >+ return committedIndexExpressionType; >+ })(); >+ if (!indexExpressionType) { >+ setError(); >+ return; >+ } >+ >+ finishVisitingPropertyAccess(indexExpression, WTFMove(*wrappedBaseType), indexExpressionType); >+ } >+ >+ void visit(AST::VariableReference& variableReference) override >+ { >+ ASSERT(variableReference.variable()); >+ ASSERT(variableReference.variable()->type()); >+ auto addResult = m_typeMap.add(&variableReference, variableReference.variable()->type()->clone()); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ Optional<AST::ReferenceType::AddressSpace> addressSpace; >+ if (!variableReference.variable()->isAnonymous()) >+ addressSpace = AST::ReferenceType::AddressSpace::Thread; >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&variableReference, WTFMove(addressSpace)); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void visit(AST::Return& returnStatement) override >+ { >+ ASSERT(returnStatement.function()); >+ if (returnStatement.value()) { >+ checkErrorAndVisit(*returnStatement.value()); >+ auto valueIterator = m_typeMap.find(returnStatement.value()); >+ ASSERT(valueIterator != m_typeMap.end()); >+ auto& resultType = valueIterator->value; >+ auto success = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& resultType) -> bool { >+ return matches(returnStatement.function()->type(), static_cast<AST::UnnamedType&>(resultType)); >+ }, [&](Ref<ResolvableTypeReference>& resultType) -> bool { >+ return static_cast<bool>(matchAndCommit(returnStatement.function()->type(), resultType->resolvableType())); >+ }), resultType); >+ if (!success) >+ setError(); >+ return; >+ } >+ >+ if (!matches(returnStatement.function()->type(), m_intrinsics.voidType())) >+ setError(); >+ } >+ >+ void visit(AST::PointerType&) override >+ { >+ // Following pointer types can cause infinite loops because of data structures >+ // like linked lists. >+ // FIXME: Make sure this function should be empty >+ } >+ >+ void visit(AST::ArrayReferenceType&) override >+ { >+ // Following array reference types can cause infinite loops because of data >+ // structures like linked lists. >+ // FIXME: Make sure this function should be empty >+ } >+ >+ void visit(AST::IntegerLiteral& integerLiteral) override >+ { >+ auto ref = adoptRef(*new ResolvableTypeReference(integerLiteral.type())); >+ auto addResult = m_typeMap.add(&integerLiteral, WTFMove(ref)); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&integerLiteral, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void visit(AST::UnsignedIntegerLiteral& unsignedIntegerLiteral) override >+ { >+ auto ref = adoptRef(*new ResolvableTypeReference(unsignedIntegerLiteral.type())); >+ auto addResult = m_typeMap.add(&unsignedIntegerLiteral, WTFMove(ref)); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&unsignedIntegerLiteral, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void visit(AST::FloatLiteral& floatLiteral) override >+ { >+ auto ref = adoptRef(*new ResolvableTypeReference(floatLiteral.type())); >+ auto addResult = m_typeMap.add(&floatLiteral, WTFMove(ref)); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&floatLiteral, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void visit(AST::NullLiteral& nullLiteral) override >+ { >+ auto ref = adoptRef(*new ResolvableTypeReference(nullLiteral.type())); >+ auto addResult = m_typeMap.add(&nullLiteral, WTFMove(ref)); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&nullLiteral, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void visit(AST::BooleanLiteral& booleanLiteral) override >+ { >+ auto addResult = m_typeMap.add(&booleanLiteral, ResolvingType(AST::TypeReference::wrap(Lexer::Token(booleanLiteral.origin()), m_intrinsics.boolType()))); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&booleanLiteral, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void visit(AST::EnumerationMemberLiteral& enumerationMemberLiteral) override >+ { >+ ASSERT(enumerationMemberLiteral.enumerationDefinition()); >+ auto& enumerationDefinition = *enumerationMemberLiteral.enumerationDefinition(); >+ auto addResult = m_typeMap.add(&enumerationMemberLiteral, ResolvingType(AST::TypeReference::wrap(Lexer::Token(enumerationMemberLiteral.origin()), enumerationDefinition))); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&enumerationMemberLiteral, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ bool isBoolType(ResolvingType& resolvingType) >+ { >+ return WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& left) -> bool { >+ return matches(static_cast<AST::UnnamedType&>(left), m_intrinsics.boolType()); >+ }, [&](Ref<ResolvableTypeReference>& left) -> bool { >+ return static_cast<bool>(matchAndCommit(m_intrinsics.boolType(), left->resolvableType())); >+ }), resolvingType); >+ } >+ >+ void visit(AST::LogicalNotExpression& logicalNotExpression) override >+ { >+ checkErrorAndVisit(logicalNotExpression.operand()); >+ auto operandIterator = m_typeMap.find(&logicalNotExpression.operand()); >+ ASSERT(operandIterator != m_typeMap.end()); >+ auto& operandType = operandIterator->value; >+ if (!isBoolType(operandType)) { >+ setError(); >+ return; >+ } >+ auto addResult = m_typeMap.add(&logicalNotExpression, ResolvingType(AST::TypeReference::wrap(Lexer::Token(logicalNotExpression.origin()), m_intrinsics.boolType()))); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&logicalNotExpression, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void visit(AST::LogicalExpression& logicalExpression) override >+ { >+ checkErrorAndVisit(logicalExpression.left()); >+ auto leftIterator = m_typeMap.find(&logicalExpression.left()); >+ ASSERT(leftIterator != m_typeMap.end()); >+ auto& leftType = leftIterator->value; >+ >+ checkErrorAndVisit(logicalExpression.right()); >+ auto rightIterator = m_typeMap.find(&logicalExpression.right()); >+ ASSERT(rightIterator != m_typeMap.end()); >+ auto& rightType = rightIterator->value; >+ >+ if (!isBoolType(leftType) || !isBoolType(rightType)) { >+ setError(); >+ return; >+ } >+ auto addResult = m_typeMap.add(&logicalExpression, ResolvingType(AST::TypeReference::wrap(Lexer::Token(logicalExpression.origin()), m_intrinsics.boolType()))); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&logicalExpression, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void visit(AST::IfStatement& ifStatement) override >+ { >+ checkErrorAndVisit(ifStatement.conditional()); >+ auto conditionalIterator = m_typeMap.find(&ifStatement.conditional()); >+ ASSERT(conditionalIterator != m_typeMap.end()); >+ auto& conditionalType = conditionalIterator->value; >+ if (!isBoolType(conditionalType)) { >+ setError(); >+ return; >+ } >+ checkErrorAndVisit(ifStatement.body()); >+ if (ifStatement.elseBody()) >+ checkErrorAndVisit(static_cast<AST::Statement&>(*ifStatement.elseBody())); >+ } >+ >+ void visit(AST::WhileLoop& whileLoop) override >+ { >+ checkErrorAndVisit(whileLoop.conditional()); >+ auto conditionalIterator = m_typeMap.find(&whileLoop.conditional()); >+ ASSERT(conditionalIterator != m_typeMap.end()); >+ auto& conditionalType = conditionalIterator->value; >+ if (!isBoolType(conditionalType)) { >+ setError(); >+ return; >+ } >+ checkErrorAndVisit(whileLoop.body()); >+ } >+ >+ void visit(AST::DoWhileLoop& doWhileLoop) override >+ { >+ checkErrorAndVisit(doWhileLoop.body()); >+ checkErrorAndVisit(doWhileLoop.conditional()); >+ auto conditionalIterator = m_typeMap.find(&doWhileLoop.conditional()); >+ ASSERT(conditionalIterator != m_typeMap.end()); >+ auto& conditionalType = conditionalIterator->value; >+ if (!isBoolType(conditionalType)) { >+ setError(); >+ return; >+ } >+ } >+ >+ void visit(AST::ForLoop& forLoop) override >+ { >+ WTF::visit(WTF::makeVisitor([&](AST::VariableDeclarationsStatement& variableDeclarationsStatement) { >+ checkErrorAndVisit(variableDeclarationsStatement); >+ }, [&](UniqueRef<AST::Expression>& expression) { >+ checkErrorAndVisit(static_cast<AST::Expression&>(expression)); >+ }), forLoop.initialization()); >+ if (forLoop.condition()) { >+ checkErrorAndVisit(*forLoop.condition()); >+ auto conditionIterator = m_typeMap.find(forLoop.condition()); >+ ASSERT(conditionIterator != m_typeMap.end()); >+ auto& conditionType = conditionIterator->value; >+ if (!isBoolType(conditionType)) { >+ setError(); >+ return; >+ } >+ } >+ if (forLoop.increment()) >+ checkErrorAndVisit(*forLoop.increment()); >+ checkErrorAndVisit(forLoop.body()); >+ } >+ >+ void visit(AST::SwitchStatement& switchStatement) override >+ { >+ checkErrorAndVisit(switchStatement.value()); >+ auto valueIterator = m_typeMap.find(&switchStatement.value()); >+ ASSERT(valueIterator != m_typeMap.end()); >+ auto& valueType = valueIterator->value; >+ auto valueUnifyNode = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& left) -> AST::Type* { >+ return &left->unifyNode(); >+ }, [&](Ref<ResolvableTypeReference>& left) -> AST::Type* { >+ if (!left->resolvableType().resolvedType()) { >+ if (!static_cast<bool>(commit(left->resolvableType()))) >+ return nullptr; >+ } >+ return &left->resolvableType().resolvedType()->unifyNode(); >+ }), valueType); >+ if (!is<AST::NamedType>(*valueUnifyNode)) { >+ setError(); >+ return; >+ } >+ auto& valueNamedUnifyNode = downcast<AST::NamedType>(*valueUnifyNode); >+ if (!(is<AST::NativeTypeDeclaration>(valueNamedUnifyNode) && downcast<AST::NativeTypeDeclaration>(valueNamedUnifyNode).isInt()) >+ && !is<AST::EnumerationDefinition>(valueNamedUnifyNode)) { >+ setError(); >+ return; >+ } >+ >+ bool hasDefault = false; >+ for (auto& switchCase : switchStatement.switchCases()) { >+ checkErrorAndVisit(switchCase.block()); >+ if (!switchCase.value()) { >+ hasDefault = true; >+ continue; >+ } >+ bool success; >+ switchCase.value()->visit(WTF::makeVisitor([&](AST::IntegerLiteral& integerLiteral) { >+ success = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& valueType) -> bool { >+ return static_cast<bool>(matchAndCommit(static_cast<AST::UnnamedType&>(valueType), integerLiteral.type())); >+ }, [&](Ref<ResolvableTypeReference>& valueType) -> bool { >+ return static_cast<bool>(matchAndCommit(valueType->resolvableType(), integerLiteral.type())); >+ }), valueType); >+ }, [&](AST::UnsignedIntegerLiteral& unsignedIntegerLiteral) { >+ success = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& valueType) -> bool { >+ return static_cast<bool>(matchAndCommit(static_cast<AST::UnnamedType&>(valueType), unsignedIntegerLiteral.type())); >+ }, [&](Ref<ResolvableTypeReference>& valueType) -> bool { >+ return static_cast<bool>(matchAndCommit(valueType->resolvableType(), unsignedIntegerLiteral.type())); >+ }), valueType); >+ }, [&](AST::FloatLiteral& floatLiteral) { >+ success = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& valueType) -> bool { >+ return static_cast<bool>(matchAndCommit(static_cast<AST::UnnamedType&>(valueType), floatLiteral.type())); >+ }, [&](Ref<ResolvableTypeReference>& valueType) -> bool { >+ return static_cast<bool>(matchAndCommit(valueType->resolvableType(), floatLiteral.type())); >+ }), valueType); >+ }, [&](AST::NullLiteral& nullLiteral) { >+ success = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& valueType) -> bool { >+ return static_cast<bool>(matchAndCommit(static_cast<AST::UnnamedType&>(valueType), nullLiteral.type())); >+ }, [&](Ref<ResolvableTypeReference>& valueType) -> bool { >+ return static_cast<bool>(matchAndCommit(valueType->resolvableType(), nullLiteral.type())); >+ }), valueType); >+ }, [&](AST::BooleanLiteral&) { >+ success = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& valueType) -> bool { >+ return matches(static_cast<AST::UnnamedType&>(valueType), m_intrinsics.boolType()); >+ }, [&](Ref<ResolvableTypeReference>& valueType) -> bool { >+ return static_cast<bool>(matchAndCommit(m_intrinsics.boolType(), valueType->resolvableType())); >+ }), valueType); >+ }, [&](AST::EnumerationMemberLiteral& enumerationMemberLiteral) { >+ ASSERT(enumerationMemberLiteral.enumerationDefinition()); >+ success = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& valueType) -> bool { >+ return matches(static_cast<AST::UnnamedType&>(valueType), *enumerationMemberLiteral.enumerationDefinition()); >+ }, [&](Ref<ResolvableTypeReference>& valueType) -> bool { >+ return static_cast<bool>(matchAndCommit(*enumerationMemberLiteral.enumerationDefinition(), valueType->resolvableType())); >+ }), valueType); >+ })); >+ if (!success) { >+ setError(); >+ return; >+ } >+ } >+ >+ for (size_t i = 0; i < switchStatement.switchCases().size(); ++i) { >+ auto& firstCase = switchStatement.switchCases()[i]; >+ for (size_t j = i + 1; j < switchStatement.switchCases().size(); ++j) { >+ auto& secondCase = switchStatement.switchCases()[j]; >+ >+ if (static_cast<bool>(firstCase.value()) != static_cast<bool>(secondCase.value())) >+ continue; >+ >+ if (!static_cast<bool>(firstCase.value())) { >+ setError(); >+ return; >+ } >+ >+ bool success = true; >+ firstCase.value()->visit(WTF::makeVisitor([&](AST::IntegerLiteral& firstIntegerLiteral) { >+ secondCase.value()->visit(WTF::makeVisitor([&](AST::IntegerLiteral& secondIntegerLiteral) { >+ success = firstIntegerLiteral.value() != secondIntegerLiteral.value(); >+ }, [&](AST::UnsignedIntegerLiteral& secondUnsignedIntegerLiteral) { >+ success = static_cast<int64_t>(firstIntegerLiteral.value()) != static_cast<int64_t>(secondUnsignedIntegerLiteral.value()); >+ }, [&](AST::FloatLiteral&) { >+ }, [&](AST::NullLiteral&) { >+ }, [&](AST::BooleanLiteral&) { >+ }, [&](AST::EnumerationMemberLiteral&) { >+ })); >+ }, [&](AST::UnsignedIntegerLiteral& firstUnsignedIntegerLiteral) { >+ secondCase.value()->visit(WTF::makeVisitor([&](AST::IntegerLiteral& secondIntegerLiteral) { >+ success = static_cast<int64_t>(firstUnsignedIntegerLiteral.value()) != static_cast<int64_t>(secondIntegerLiteral.value()); >+ }, [&](AST::UnsignedIntegerLiteral& secondUnsignedIntegerLiteral) { >+ success = firstUnsignedIntegerLiteral.value() != secondUnsignedIntegerLiteral.value(); >+ }, [&](AST::FloatLiteral&) { >+ }, [&](AST::NullLiteral&) { >+ }, [&](AST::BooleanLiteral&) { >+ }, [&](AST::EnumerationMemberLiteral&) { >+ })); >+ }, [&](AST::FloatLiteral&) { >+ }, [&](AST::NullLiteral&) { >+ }, [&](AST::BooleanLiteral&) { >+ }, [&](AST::EnumerationMemberLiteral& firstEnumerationMemberLiteral) { >+ secondCase.value()->visit(WTF::makeVisitor([&](AST::IntegerLiteral&) { >+ }, [&](AST::UnsignedIntegerLiteral&) { >+ }, [&](AST::FloatLiteral&) { >+ }, [&](AST::NullLiteral&) { >+ }, [&](AST::BooleanLiteral&) { >+ }, [&](AST::EnumerationMemberLiteral& secondEnumerationMemberLiteral) { >+ success = firstEnumerationMemberLiteral.enumerationMember() != secondEnumerationMemberLiteral.enumerationMember(); >+ })); >+ })); >+ } >+ } >+ >+ if (!hasDefault) { >+ if (is<AST::NativeTypeDeclaration>(valueNamedUnifyNode)) { >+ HashSet<int64_t> values; >+ bool zeroValueExists; >+ for (auto& switchCase : switchStatement.switchCases()) { >+ int64_t value; >+ switchCase.value()->visit(WTF::makeVisitor([&](AST::IntegerLiteral& integerLiteral) { >+ value = integerLiteral.valueForSelectedType(); >+ }, [&](AST::UnsignedIntegerLiteral& unsignedIntegerLiteral) { >+ value = unsignedIntegerLiteral.valueForSelectedType(); >+ }, [&](AST::FloatLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::NullLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::BooleanLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::EnumerationMemberLiteral&) { >+ ASSERT_NOT_REACHED(); >+ })); >+ if (!value) >+ zeroValueExists = true; >+ else >+ values.add(value); >+ } >+ bool success = true; >+ downcast<AST::NativeTypeDeclaration>(valueNamedUnifyNode).iterateAllValues([&](int64_t value) -> bool { >+ if (!value) { >+ if (!zeroValueExists) { >+ success = false; >+ return true; >+ } >+ return false; >+ } >+ if (!values.contains(value)) { >+ success = false; >+ return true; >+ } >+ return false; >+ }); >+ if (!success) { >+ setError(); >+ return; >+ } >+ } else { >+ ASSERT(is<AST::EnumerationDefinition>(valueNamedUnifyNode)); >+ HashSet<AST::EnumerationMember*> values; >+ for (auto& switchCase : switchStatement.switchCases()) { >+ switchCase.value()->visit(WTF::makeVisitor([&](AST::IntegerLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::UnsignedIntegerLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::FloatLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::NullLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::BooleanLiteral&) { >+ ASSERT_NOT_REACHED(); >+ }, [&](AST::EnumerationMemberLiteral& enumerationMemberLiteral) { >+ ASSERT(enumerationMemberLiteral.enumerationMember()); >+ values.add(enumerationMemberLiteral.enumerationMember()); >+ })); >+ } >+ for (auto& enumerationMember : downcast<AST::EnumerationDefinition>(valueNamedUnifyNode).enumerationMembers()) { >+ if (!values.contains(&enumerationMember.get())) { >+ setError(); >+ return; >+ } >+ } >+ } >+ } >+ } >+ >+ void visit(AST::CommaExpression& commaExpression) override >+ { >+ ASSERT(commaExpression.list().size() > 0); >+ Visitor::visit(commaExpression); >+ auto lastIterator = m_typeMap.find(&static_cast<AST::Expression&>(commaExpression.list().last())); >+ ASSERT(lastIterator != m_typeMap.end()); >+ auto& lastType = lastIterator->value; >+ WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& lastType) { >+ auto addResult = m_typeMap.add(&commaExpression, ResolvingType(lastType->clone())); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ }, [&](Ref<ResolvableTypeReference>& lastType) { >+ auto addResult = m_typeMap.add(&commaExpression, ResolvingType(lastType.copyRef())); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ }), lastType); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&commaExpression, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void visit(AST::TernaryExpression& ternaryExpression) override >+ { >+ checkErrorAndVisit(ternaryExpression.predicate()); >+ auto predicateIterator = m_typeMap.find(&ternaryExpression.predicate()); >+ ASSERT(predicateIterator != m_typeMap.end()); >+ auto& predicateType = predicateIterator->value; >+ if (!isBoolType(predicateType)) { >+ setError(); >+ return; >+ } >+ >+ checkErrorAndVisit(ternaryExpression.bodyExpression()); >+ auto bodyIterator = m_typeMap.find(&ternaryExpression.bodyExpression()); >+ ASSERT(bodyIterator != m_typeMap.end()); >+ auto& bodyType = bodyIterator->value; >+ >+ checkErrorAndVisit(ternaryExpression.elseExpression()); >+ auto elseIterator = m_typeMap.find(&ternaryExpression.elseExpression()); >+ ASSERT(elseIterator != m_typeMap.end()); >+ auto& elseType = elseIterator->value; >+ >+ auto resultType = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& bodyType) -> Optional<UniqueRef<AST::UnnamedType>> { >+ return WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& elseType) -> Optional<UniqueRef<AST::UnnamedType>> { >+ if (matches(static_cast<AST::UnnamedType&>(bodyType), static_cast<AST::UnnamedType&>(elseType))) >+ return bodyType->clone(); >+ return WTF::nullopt; >+ }, [&](Ref<ResolvableTypeReference>& elseType) -> Optional<UniqueRef<AST::UnnamedType>> { >+ return matchAndCommit(static_cast<AST::UnnamedType&>(bodyType), elseType->resolvableType()); >+ }), elseType); >+ }, [&](Ref<ResolvableTypeReference>& bodyType) -> Optional<UniqueRef<AST::UnnamedType>> { >+ return WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& elseType) -> Optional<UniqueRef<AST::UnnamedType>> { >+ return matchAndCommit(static_cast<AST::UnnamedType&>(elseType), bodyType->resolvableType()); >+ }, [&](Ref<ResolvableTypeReference>& elseType) -> Optional<UniqueRef<AST::UnnamedType>> { >+ return matchAndCommit(bodyType->resolvableType(), elseType->resolvableType()); >+ }), elseType); >+ }), bodyType); >+ if (!resultType) { >+ setError(); >+ return; >+ } >+ auto addResult = m_typeMap.add(&ternaryExpression, ResolvingType(WTFMove(*resultType))); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&ternaryExpression, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+ void visit(AST::CallExpression& callExpression) override >+ { >+ for (auto& argument : callExpression.arguments()) >+ checkErrorAndVisit(static_cast<AST::Expression&>(argument)); >+ if (callExpression.castReturnType()) >+ checkErrorAndVisit(callExpression.castReturnType()->get()); >+ Vector<std::reference_wrapper<ResolvingType>> types; >+ types.reserveInitialCapacity(callExpression.arguments().size()); >+ for (auto& argument : callExpression.arguments()) { >+ auto iterator = m_typeMap.find(&static_cast<AST::Expression&>(argument)); >+ ASSERT(iterator != m_typeMap.end()); >+ types.uncheckedAppend(iterator->value); >+ } >+ >+ ASSERT(callExpression.hasOverloads()); >+ auto* function = resolveFunctionOverloadImpl(*callExpression.overloads(), types, callExpression.castReturnType()); >+ if (!function) { >+ if (auto newFunction = resolveByInstantiation(callExpression, types, m_intrinsics)) { >+ m_program.append(WTFMove(*newFunction)); >+ function = &static_cast<AST::NativeFunctionDeclaration&>(m_program.nativeFunctionDeclarations().last()); >+ } >+ } >+ >+ if (!function) { >+ setError(); >+ return; >+ } >+ >+ for (size_t i = 0; i < function->parameters().size(); ++i) { >+ auto success = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>&) -> bool { >+ return true; >+ }, [&](Ref<ResolvableTypeReference>& resolvableTypeReference) -> bool { >+ return static_cast<bool>(matchAndCommit(*function->parameters()[i].type(), resolvableTypeReference->resolvableType())); >+ }), types[i].get()); >+ if (!success) { >+ setError(); >+ return; >+ } >+ } >+ >+ callExpression.setFunction(*function); >+ >+ auto addResult = m_typeMap.add(&callExpression, ResolvingType(function->type().clone())); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ auto addressSpaceAddResult = m_addressSpaceMap.add(&callExpression, WTF::nullopt); >+ ASSERT_UNUSED(addressSpaceAddResult, addressSpaceAddResult.isNewEntry); >+ } >+ >+private: >+ HashMap<AST::Expression*, ResolvingType> m_typeMap; >+ HashMap<AST::Expression*, Optional<AST::ReferenceType::AddressSpace>> m_addressSpaceMap; >+ HashSet<String> m_vertexEntryPoints; >+ HashSet<String> m_fragmentEntryPoints; >+ HashSet<String> m_computeEntryPoints; >+ const Intrinsics& m_intrinsics; >+ Program& m_program; >+}; >+ >+bool check(Program& program) >+{ >+ Checker checker(program.intrinsics(), program); >+ checker.checkErrorAndVisit(program); >+ return !checker.error(); >+} >+ >+} >+ >+} >+ >+#endif >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.h >new file mode 100644 >index 0000000000000000000000000000000000000000..f6f085778184fe547672101dfbe0120e636b9a88 >--- /dev/null >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.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; >+ >+bool check(Program&); >+ >+} >+ >+} >+ >+#endif >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLGatherEntryPointItems.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLGatherEntryPointItems.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..5bd54c9b910d1baaf6705184574a1696d41969ce >--- /dev/null >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLGatherEntryPointItems.cpp >@@ -0,0 +1,184 @@ >+/* >+ * 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 "WHLSLGatherEntryPointItems.h" >+ >+#if ENABLE(WEBGPU) >+ >+#include "WHLSLArrayReferenceType.h" >+#include "WHLSLArrayType.h" >+#include "WHLSLFunctionDefinition.h" >+#include "WHLSLInferTypes.h" >+#include "WHLSLIntrinsics.h" >+#include "WHLSLPointerType.h" >+#include "WHLSLStructureDefinition.h" >+#include "WHLSLTypeDefinition.h" >+#include "WHLSLTypeReference.h" >+#include "WHLSLVariableDeclaration.h" >+#include "WHLSLVisitor.h" >+#include <wtf/Optional.h> >+ >+namespace WebCore { >+ >+namespace WHLSL { >+ >+class Gatherer : public Visitor { >+public: >+ Gatherer(const Intrinsics& intrinsics, AST::Semantic* semantic = nullptr) >+ : m_intrinsics(intrinsics) >+ , m_currentSemantic(semantic) >+ { >+ } >+ >+ virtual ~Gatherer() = default; >+ >+ void reset() >+ { >+ m_currentSemantic = nullptr; >+ } >+ >+ Vector<EntryPointItem>&& takeEntryPointItems() >+ { >+ return WTFMove(m_entryPointItems); >+ } >+ >+ void visit(AST::EnumerationDefinition&) >+ { >+ if (!m_currentSemantic) { >+ setError(); >+ return; >+ } >+ m_entryPointItems.append(EntryPointItem(m_typeReferences.last().get(), *m_currentSemantic)); >+ } >+ >+ void visit(AST::NativeTypeDeclaration& nativeTypeDeclaration) >+ { >+ if (!m_currentSemantic) { >+ setError(); >+ return; >+ } >+ if (matches(nativeTypeDeclaration, m_intrinsics.voidType())) { >+ setError(); >+ return; >+ } >+ >+ m_entryPointItems.append(EntryPointItem(m_typeReferences.last().get(), *m_currentSemantic)); >+ } >+ >+ void visit(AST::StructureDefinition& structureDefinition) >+ { >+ if (m_currentSemantic) { >+ setError(); >+ return; >+ } >+ >+ for (auto& structureElement : structureDefinition.structureElements()) { >+ if (structureElement.semantic()) >+ m_currentSemantic = &*structureElement.semantic(); >+ checkErrorAndVisit(structureElement); >+ } >+ } >+ >+ void visit(AST::TypeDefinition& typeDefinition) >+ { >+ checkErrorAndVisit(typeDefinition.type()); >+ } >+ >+ void visit(AST::TypeReference& typeReference) >+ { >+ ASSERT(typeReference.resolvedType()); >+ m_typeReferences.append(typeReference); >+ auto depth = m_typeReferences.size(); >+ checkErrorAndVisit(*typeReference.resolvedType()); >+ ASSERT_UNUSED(depth, m_typeReferences.size() == depth); >+ } >+ >+ void visit(AST::PointerType& pointerType) >+ { >+ if (!m_currentSemantic) { >+ setError(); >+ return; >+ } >+ m_entryPointItems.append(EntryPointItem(pointerType, *m_currentSemantic)); >+ } >+ >+ void visit(AST::ArrayReferenceType& arrayReferenceType) >+ { >+ if (!m_currentSemantic) { >+ setError(); >+ return; >+ } >+ m_entryPointItems.append(EntryPointItem(arrayReferenceType, *m_currentSemantic)); >+ } >+ >+ void visit(AST::ArrayType& arrayType) >+ { >+ if (!m_currentSemantic) { >+ setError(); >+ return; >+ } >+ m_entryPointItems.append(EntryPointItem(arrayType, *m_currentSemantic)); >+ } >+ >+ void visit(AST::VariableDeclaration& variableDeclaration) >+ { >+ ASSERT(!m_currentSemantic); >+ if (variableDeclaration.semantic()) >+ m_currentSemantic = &*variableDeclaration.semantic(); >+ if (variableDeclaration.type()) >+ checkErrorAndVisit(*variableDeclaration.type()); >+ } >+ >+private: >+ const Intrinsics& m_intrinsics; >+ AST::Semantic* m_currentSemantic { nullptr }; >+ Vector<std::reference_wrapper<AST::TypeReference>> m_typeReferences; >+ Vector<EntryPointItem> m_entryPointItems; >+}; >+ >+Optional<EntryPointItems> gatherEntryPointItems(const Intrinsics& intrinsics, AST::FunctionDefinition& functionDefinition) >+{ >+ ASSERT(functionDefinition.entryPointType()); >+ Gatherer inputGatherer(intrinsics); >+ for (auto& parameter : functionDefinition.parameters()) { >+ inputGatherer.reset(); >+ inputGatherer.checkErrorAndVisit(parameter); >+ if (inputGatherer.error()) >+ return WTF::nullopt; >+ } >+ Gatherer outputGatherer(intrinsics, functionDefinition.semantic() ? &*functionDefinition.semantic() : nullptr); >+ outputGatherer.checkErrorAndVisit(functionDefinition.type()); >+ if (outputGatherer.error()) >+ return WTF::nullopt; >+ >+ return {{ inputGatherer.takeEntryPointItems(), outputGatherer.takeEntryPointItems() }}; >+} >+ >+} >+ >+} >+ >+#endif >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLGatherEntryPointItems.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLGatherEntryPointItems.h >new file mode 100644 >index 0000000000000000000000000000000000000000..9d4f7dd84457fea60691a65eb3f1d7f3a5489308 >--- /dev/null >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLGatherEntryPointItems.h >@@ -0,0 +1,69 @@ >+/* >+ * 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) >+ >+#include "WHLSLSemantic.h" >+#include <wtf/Optional.h> >+#include <wtf/Vector.h> >+ >+namespace WebCore { >+ >+namespace WHLSL { >+ >+namespace AST { >+ >+class FunctionDefinition; >+ >+} >+ >+class Intrinsics; >+class UnnamedType; >+ >+struct EntryPointItem { >+ EntryPointItem(AST::UnnamedType& unnamedType, AST::Semantic& semantic) >+ : unnamedType(unnamedType) >+ , semantic(semantic) >+ { >+ } >+ >+ AST::UnnamedType& unnamedType; >+ AST::Semantic& semantic; >+}; >+ >+struct EntryPointItems { >+ Vector<EntryPointItem> inputs; >+ Vector<EntryPointItem> outputs; >+}; >+ >+Optional<EntryPointItems> gatherEntryPointItems(const Intrinsics&, AST::FunctionDefinition&); >+ >+} >+ >+} >+ >+#endif >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.cpp >index 20e0ef09e41415251e084a82deb55e1f1fce29e2..a5aaa5e15ebdb376d2a8b944c7ec5fd033adf5ec 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.cpp >@@ -159,16 +159,19 @@ Optional<UniqueRef<AST::UnnamedType>> commit(AST::ResolvableType& resolvableType > { > ASSERT(!resolvableType.resolvedType()); > if (is<AST::FloatLiteralType>(resolvableType)) { >- resolvableType.resolve(downcast<AST::FloatLiteralType>(resolvableType).preferredType().clone()); >- return downcast<AST::FloatLiteralType>(resolvableType).preferredType().clone(); >+ auto& floatLiteralType = downcast<AST::FloatLiteralType>(resolvableType); >+ resolvableType.resolve(floatLiteralType.preferredType().clone()); >+ return floatLiteralType.preferredType().clone(); > } > if (is<AST::IntegerLiteralType>(resolvableType)) { >- resolvableType.resolve(downcast<AST::IntegerLiteralType>(resolvableType).preferredType().clone()); >- return downcast<AST::IntegerLiteralType>(resolvableType).preferredType().clone(); >+ auto& integerLiteralType = downcast<AST::IntegerLiteralType>(resolvableType); >+ resolvableType.resolve(integerLiteralType.preferredType().clone()); >+ return integerLiteralType.preferredType().clone(); > } > if (is<AST::UnsignedIntegerLiteralType>(resolvableType)) { >- resolvableType.resolve(downcast<AST::UnsignedIntegerLiteralType>(resolvableType).preferredType().clone()); >- return downcast<AST::UnsignedIntegerLiteralType>(resolvableType).preferredType().clone(); >+ auto& unsignedIntegerLiteralType = downcast<AST::UnsignedIntegerLiteralType>(resolvableType); >+ resolvableType.resolve(unsignedIntegerLiteralType.preferredType().clone()); >+ return unsignedIntegerLiteralType.preferredType().clone(); > } > if (is<AST::NullLiteralType>(resolvableType)) { > // FIXME: Trying to match nullptr and nullptr fails. >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp >index 6bf18e69afc5c8fe50d745e54d9626ddc0d50e0f..259ed573fdc678a12a34714c27f64165a8245d63 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp >@@ -167,17 +167,20 @@ void NameResolver::visit(AST::PropertyAccessExpression& propertyAccessExpression > void NameResolver::visit(AST::DotExpression& dotExpression) > { > if (is<AST::VariableReference>(dotExpression.base())) { >- if (auto enumerationTypes = m_nameContext.getTypes(downcast<AST::VariableReference>(dotExpression.base()).name())) { >+ auto baseName = downcast<AST::VariableReference>(dotExpression.base()).name(); >+ if (auto enumerationTypes = m_nameContext.getTypes(baseName)) { > ASSERT(enumerationTypes->size() == 1); > AST::NamedType& type = (*enumerationTypes)[0]; > if (is<AST::EnumerationDefinition>(type)) { > AST::EnumerationDefinition& enumerationDefinition = downcast<AST::EnumerationDefinition>(type); >- if (auto* member = enumerationDefinition.memberByName(dotExpression.fieldName())) { >+ auto memberName = dotExpression.fieldName(); >+ if (auto* member = enumerationDefinition.memberByName(memberName)) { > 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. > dotExpression.~DotExpression(); >- new (&dotExpression) AST::EnumerationMemberLiteral(WTFMove(origin), *member); >+ auto enumerationMemberLiteral = AST::EnumerationMemberLiteral::wrap(WTFMove(origin), WTFMove(baseName), WTFMove(memberName), enumerationDefinition, *member); >+ new (&dotExpression) AST::EnumerationMemberLiteral(WTFMove(enumerationMemberLiteral)); > return; > } > setError(); >@@ -212,15 +215,18 @@ void NameResolver::visit(AST::CallExpression& callExpression) > checkErrorAndVisit(callExpression); > } > >-void NameResolver::visit(AST::ConstantExpressionEnumerationMemberReference& constantExpressionEnumerationMemberReference) >+void NameResolver::visit(AST::EnumerationMemberLiteral& enumerationMemberLiteral) > { >- if (auto enumerationTypes = m_nameContext.getTypes(constantExpressionEnumerationMemberReference.left())) { >+ if (enumerationMemberLiteral.enumerationMember()) >+ return; >+ >+ if (auto enumerationTypes = m_nameContext.getTypes(enumerationMemberLiteral.left())) { > ASSERT(enumerationTypes->size() == 1); > AST::NamedType& type = (*enumerationTypes)[0]; > if (is<AST::EnumerationDefinition>(type)) { > AST::EnumerationDefinition& enumerationDefinition = downcast<AST::EnumerationDefinition>(type); >- if (auto* member = enumerationDefinition.memberByName(constantExpressionEnumerationMemberReference.right())) { >- constantExpressionEnumerationMemberReference.setEnumerationMember(enumerationDefinition, *member); >+ if (auto* member = enumerationDefinition.memberByName(enumerationMemberLiteral.right())) { >+ enumerationMemberLiteral.setEnumerationMember(enumerationDefinition, *member); > return; > } > } >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h >index c72e08e0621067dbe190ca04068a9e9a70bfdcf1..65189e2a835b6851e5e0d0aae1ca8aecaf2b37e4 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h >@@ -62,7 +62,7 @@ private: > void visit(AST::PropertyAccessExpression&) override; > void visit(AST::DotExpression&) override; > void visit(AST::CallExpression&) override; >- void visit(AST::ConstantExpressionEnumerationMemberReference&) override; >+ void visit(AST::EnumerationMemberLiteral&) override; > > NameContext m_nameContext; > AST::FunctionDefinition* m_currentFunction { nullptr }; >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h >index 3cf66ced220f632a97c3a41e9d895fd5f12baf3c..5671c4513ad6ebf353aa92819b921795dcaad293 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h >@@ -39,7 +39,6 @@ > #include "WHLSLCallExpression.h" > #include "WHLSLCommaExpression.h" > #include "WHLSLConstantExpression.h" >-#include "WHLSLConstantExpressionEnumerationMemberReference.h" > #include "WHLSLContinue.h" > #include "WHLSLDereferenceExpression.h" > #include "WHLSLDoWhileLoop.h" >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp >index 7fd3675aa3a1b37c296a32c95cee82dadf69a48b..6ef576c99c75ac9a373f47f37dd9abd41d54d9d9 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp >@@ -40,7 +40,6 @@ > #include "WHLSLCallExpression.h" > #include "WHLSLCommaExpression.h" > #include "WHLSLConstantExpression.h" >-#include "WHLSLConstantExpressionEnumerationMemberReference.h" > #include "WHLSLContinue.h" > #include "WHLSLDereferenceExpression.h" > #include "WHLSLDoWhileLoop.h" >@@ -48,6 +47,7 @@ > #include "WHLSLEffectfulExpressionStatement.h" > #include "WHLSLEnumerationDefinition.h" > #include "WHLSLEnumerationMember.h" >+#include "WHLSLEnumerationMemberLiteral.h" > #include "WHLSLExpression.h" > #include "WHLSLFallthrough.h" > #include "WHLSLFloatLiteral.h" >@@ -268,8 +268,8 @@ void Visitor::visit(AST::ConstantExpression& constantExpression) > checkErrorAndVisit(nullLiteral); > }, [&](AST::BooleanLiteral& booleanLiteral) { > checkErrorAndVisit(booleanLiteral); >- }, [&](AST::ConstantExpressionEnumerationMemberReference& constantExpressionEnumerationMemberReference) { >- checkErrorAndVisit(constantExpressionEnumerationMemberReference); >+ }, [&](AST::EnumerationMemberLiteral& enumerationMemberLiteral) { >+ checkErrorAndVisit(enumerationMemberLiteral); > })); > } > >@@ -346,7 +346,7 @@ void Visitor::visit(AST::NullLiteralType& nullLiteralType) > checkErrorAndVisit(*nullLiteralType.resolvedType()); > } > >-void Visitor::visit(AST::ConstantExpressionEnumerationMemberReference&) >+void Visitor::visit(AST::EnumerationMemberLiteral&) > { > } > >@@ -451,6 +451,8 @@ void Visitor::visit(AST::Expression& expression) > checkErrorAndVisit(downcast<AST::TernaryExpression>(expression)); > else if (is<AST::UnsignedIntegerLiteral>(expression)) > checkErrorAndVisit(downcast<AST::UnsignedIntegerLiteral>(expression)); >+ else if (is<AST::EnumerationMemberLiteral>(expression)) >+ checkErrorAndVisit(downcast<AST::EnumerationMemberLiteral>(expression)); > else { > ASSERT(is<AST::VariableReference>(expression)); > checkErrorAndVisit(downcast<AST::VariableReference>(expression)); >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.h >index a6ae293a9b836d15aa167b7d409fb2a6e645b43c..a5e4c96d8a01c231382d06e7a39f61c6b2e3bce3 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.h >@@ -63,7 +63,7 @@ class UnsignedIntegerLiteral; > class FloatLiteral; > class NullLiteral; > class BooleanLiteral; >-class ConstantExpressionEnumerationMemberReference; >+class EnumerationMemberLiteral; > class NumThreadsFunctionAttribute; > class Block; > class Statement; >@@ -141,7 +141,7 @@ public: > virtual void visit(AST::UnsignedIntegerLiteralType&); > virtual void visit(AST::FloatLiteralType&); > virtual void visit(AST::NullLiteralType&); >- virtual void visit(AST::ConstantExpressionEnumerationMemberReference&); >+ virtual void visit(AST::EnumerationMemberLiteral&); > virtual void visit(AST::FunctionAttribute&); > virtual void visit(AST::NumThreadsFunctionAttribute&); > virtual void visit(AST::Block&); >diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt >index 06f32d19d82b79535e6d523a33fc4a76b84f324d..840a7db2450d10aab65c978a26ad07e6ea8be3c6 100644 >--- a/Source/WebCore/Sources.txt >+++ b/Source/WebCore/Sources.txt >@@ -309,6 +309,8 @@ Modules/webgpu/DOMWindowWebGPU.cpp > Modules/webgpu/WHLSL/WHLSLInferTypes.cpp > Modules/webgpu/WHLSL/WHLSLLexer.cpp > Modules/webgpu/WHLSL/WHLSLParser.cpp >+Modules/webgpu/WHLSL/WHLSLChecker.cpp >+Modules/webgpu/WHLSL/WHLSLGatherEntryPointItems.cpp > Modules/webgpu/WHLSL/WHLSLNameContext.cpp > Modules/webgpu/WHLSL/WHLSLNameResolver.cpp > Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.cpp >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index 7a9e1df63ba78d7315fdcdb2969dae9643829358..ae922700df413863819ad4b0160fbacdefb4767f 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -6406,7 +6406,6 @@ > 1C24EEA71C72A7B40080F8FC /* JSFontFaceSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSFontFaceSet.h; path = DerivedSources/WebCore/JSFontFaceSet.h; sourceTree = BUILT_PRODUCTS_DIR; }; > 1C2649790D7E248A00BD10F2 /* DocumentLoaderMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentLoaderMac.cpp; sourceTree = "<group>"; }; > 1C3249101C6D6A3B007EDB32 /* FontVariantBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontVariantBuilder.cpp; sourceTree = "<group>"; }; >- 1C33276C21CEDA42000DC9F2 /* WHLSLEnumerationMemberLiteral.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLEnumerationMemberLiteral.h; sourceTree = "<group>"; }; > 1C33277121CF0BE1000DC9F2 /* WHLSLNamedType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLNamedType.h; sourceTree = "<group>"; }; > 1C33277221CF0D2E000DC9F2 /* WHLSLUnnamedType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLUnnamedType.h; sourceTree = "<group>"; }; > 1C3969CF1B74211E002BCFA7 /* FontCacheCoreText.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontCacheCoreText.cpp; sourceTree = "<group>"; }; >@@ -13267,7 +13266,7 @@ > C21BF6FF21CD89C200227979 /* WHLSLIfStatement.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLIfStatement.h; sourceTree = "<group>"; }; > C21BF70021CD89C200227979 /* WHLSLFallthrough.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLFallthrough.h; sourceTree = "<group>"; }; > C21BF70121CD89C400227979 /* WHLSLDereferenceExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLDereferenceExpression.h; sourceTree = "<group>"; }; >- C21BF70221CD89C400227979 /* WHLSLConstantExpressionEnumerationMemberReference.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLConstantExpressionEnumerationMemberReference.h; sourceTree = "<group>"; }; >+ C21BF70221CD89C400227979 /* WHLSLEnumerationMemberLiteral.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLEnumerationMemberLiteral.h; sourceTree = "<group>"; }; > C21BF70321CD89C500227979 /* WHLSLReturn.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLReturn.h; sourceTree = "<group>"; }; > C21BF70421CD89C600227979 /* WHLSLWhileLoop.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLWhileLoop.h; sourceTree = "<group>"; }; > C21BF70521CD89C700227979 /* WHLSLFunctionAttribute.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLFunctionAttribute.h; sourceTree = "<group>"; }; >@@ -13323,6 +13322,10 @@ > C21BF73A21CD8D7000227979 /* WHLSLProgram.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLProgram.h; sourceTree = "<group>"; }; > C21BF74221CD963B00227979 /* WHLSLStandardLibrary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WHLSLStandardLibrary.h; path = DerivedSources/WebCore/WHLSLStandardLibrary.h; sourceTree = BUILT_PRODUCTS_DIR; }; > C21BF74521CD969800227979 /* WHLSLStandardLibrary.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = WHLSLStandardLibrary.txt; sourceTree = "<group>"; }; >+ C21DF2E71D9E4E9900F5B24C /* CSSFontVariationValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSFontVariationValue.cpp; sourceTree = "<group>"; }; >+ C21DF2E81D9E4E9900F5B24C /* CSSFontVariationValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSFontVariationValue.h; sourceTree = "<group>"; }; >+ C234A98521E886A9003C984D /* WHLSLVisitor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLVisitor.cpp; sourceTree = "<group>"; }; >+ C234A98721E886AD003C984D /* WHLSLVisitor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLVisitor.h; sourceTree = "<group>"; }; > C234A98A21E8883E003C984D /* WHLSLNameResolver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLNameResolver.cpp; sourceTree = "<group>"; }; > C234A98C21E8883E003C984D /* WHLSLNameResolver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLNameResolver.h; sourceTree = "<group>"; }; > C234A98D21E88884003C984D /* WHLSLNameContext.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLNameContext.cpp; sourceTree = "<group>"; }; >@@ -13332,10 +13335,10 @@ > C234A99A21E90F56003C984D /* WHLSLInferTypes.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLInferTypes.cpp; sourceTree = "<group>"; }; > C234A99B21E90F57003C984D /* WHLSLInferTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLInferTypes.h; sourceTree = "<group>"; }; > C234A99D21E910BD003C984D /* WHLSLResolvingType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLResolvingType.h; sourceTree = "<group>"; }; >- C21DF2E71D9E4E9900F5B24C /* CSSFontVariationValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSFontVariationValue.cpp; sourceTree = "<group>"; }; >- C21DF2E81D9E4E9900F5B24C /* CSSFontVariationValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSFontVariationValue.h; sourceTree = "<group>"; }; >- C234A98521E886A9003C984D /* WHLSLVisitor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLVisitor.cpp; sourceTree = "<group>"; }; >- C234A98721E886AD003C984D /* WHLSLVisitor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLVisitor.h; sourceTree = "<group>"; }; >+ C234A9BE21E93F50003C984D /* WHLSLChecker.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLChecker.cpp; sourceTree = "<group>"; }; >+ C234A9C021E93F51003C984D /* WHLSLChecker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLChecker.h; sourceTree = "<group>"; }; >+ C234A9C121E93F52003C984D /* WHLSLGatherEntryPointItems.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLGatherEntryPointItems.cpp; sourceTree = "<group>"; }; >+ C234A9C221E93F52003C984D /* WHLSLGatherEntryPointItems.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLGatherEntryPointItems.h; sourceTree = "<group>"; }; > C2458E611FE8979E00594759 /* FontCacheCoreText.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FontCacheCoreText.h; sourceTree = "<group>"; }; > C26017A11C72DC9900F74A16 /* CSSFontFaceSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSFontFaceSet.cpp; sourceTree = "<group>"; }; > C26017A21C72DC9900F74A16 /* CSSFontFaceSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSFontFaceSet.h; sourceTree = "<group>"; }; >@@ -25399,6 +25402,10 @@ > isa = PBXGroup; > children = ( > C21BF6F121CD898D00227979 /* AST */, >+ C234A9BE21E93F50003C984D /* WHLSLChecker.cpp */, >+ C234A9C021E93F51003C984D /* WHLSLChecker.h */, >+ C234A9C121E93F52003C984D /* WHLSLGatherEntryPointItems.cpp */, >+ C234A9C221E93F52003C984D /* WHLSLGatherEntryPointItems.h */, > C234A99A21E90F56003C984D /* WHLSLInferTypes.cpp */, > C234A99B21E90F57003C984D /* WHLSLInferTypes.h */, > C210E91121B4BD1000B7F83D /* WHLSLLexer.cpp */, >@@ -25436,7 +25443,6 @@ > C21BF71621CD89D500227979 /* WHLSLCallExpression.h */, > C21BF70621CD89C700227979 /* WHLSLCommaExpression.h */, > C21BF73321CD89F000227979 /* WHLSLConstantExpression.h */, >- C21BF70221CD89C400227979 /* WHLSLConstantExpressionEnumerationMemberReference.h */, > C21BF6F521CD89B500227979 /* WHLSLContinue.h */, > C21BF70121CD89C400227979 /* WHLSLDereferenceExpression.h */, > C21BF71821CD89D700227979 /* WHLSLDotExpression.h */, >@@ -25444,7 +25450,7 @@ > C21BF72821CD89E500227979 /* WHLSLEffectfulExpressionStatement.h */, > C21BF72021CD89DD00227979 /* WHLSLEnumerationDefinition.h */, > C21BF72621CD89E300227979 /* WHLSLEnumerationMember.h */, >- 1C33276C21CEDA42000DC9F2 /* WHLSLEnumerationMemberLiteral.h */, >+ C21BF70221CD89C400227979 /* WHLSLEnumerationMemberLiteral.h */, > C21BF70C21CD89CC00227979 /* WHLSLExpression.h */, > C21BF70021CD89C200227979 /* WHLSLFallthrough.h */, > C21BF73521CD89F200227979 /* WHLSLFloatLiteral.h */,
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 193080
:
358187
|
358234
|
358247
|
358304
|
358378
|
358425
|
358482
|
358582
|
358621
|
358667
|
358719
|
358936
|
359002
|
359018
|
359019
|
359122