[WHLSL] Implement the NameResolver
authormmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 12 Jan 2019 06:26:20 +0000 (06:26 +0000)
committermmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 12 Jan 2019 06:26:20 +0000 (06:26 +0000)
https://bugs.webkit.org/show_bug.cgi?id=193007

Reviewed by Dean Jackson.

This is the base implementation for WHLSL's name resolver. The name resolver matches three kinds of things:
1. It matches VariableRefs to VariableDecls
2. It matches TypeRefs to NamedTypes
3. It matches CallExpressions to FunctionDeclarations

No new tests because it isn't hooked up yet. Not enough of the compiler exists to have any meaningful sort
of test. When enough of the compiler is present, I'll port the reference implementation's test suite.

* Modules/webgpu/WHLSL/AST/WHLSLFloatLiteralType.cpp: Now that InferTypes.h exists, we can implement these
functions.
(WebCore::WHLSL::AST::FloatLiteralType::canResolve const):
(WebCore::WHLSL::AST::FloatLiteralType::conversionCost const):
* Modules/webgpu/WHLSL/AST/WHLSLFloatLiteralType.h: Remove unnecessary function.
(WebCore::WHLSL::AST::FloatLiteralType::value const): Deleted.
* Modules/webgpu/WHLSL/AST/WHLSLIntegerLiteralType.cpp: Now that InferTypes.h exists, we can implement these
functions.
(WebCore::WHLSL::AST::IntegerLiteralType::canResolve const):
(WebCore::WHLSL::AST::IntegerLiteralType::conversionCost const):
* Modules/webgpu/WHLSL/AST/WHLSLIntegerLiteralType.h: Remove unnecessary function.
(WebCore::WHLSL::AST::IntegerLiteralType::value const): Deleted.
* Modules/webgpu/WHLSL/AST/WHLSLSpecializationConstantSemantic.cpp: Modifying Sources.txt caused the sources
to get shuffled around, so the #includes need to be fixed.
* Modules/webgpu/WHLSL/AST/WHLSLUnsignedIntegerLiteralType.cpp: Now that InferTypes.h exists, we can implement
these functions.
(WebCore::WHLSL::AST::UnsignedIntegerLiteralType::canResolve const):
(WebCore::WHLSL::AST::UnsignedIntegerLiteralType::conversionCost const):
* Modules/webgpu/WHLSL/AST/WHLSLUnsignedIntegerLiteralType.h: Remove unnecessary function.
(WebCore::WHLSL::AST::UnsignedIntegerLiteralType::value const): Deleted.
* Modules/webgpu/WHLSL/WHLSLInferTypes.cpp: Added. This is the replacement for UnificationContext in the
reference compiler. It's much simpler (and we should remove UnificationContext in the reference compiler in
favor of this design). It has three sets of functions: Tell if two types are the same, tell if two types are
the same and commit the resolvable type, and run the above functions on type references or function arguments.
(WebCore::WHLSL::matches):
(WebCore::WHLSL::matchAndCommit):
(WebCore::WHLSL::commit):
(WebCore::WHLSL::inferTypesForTypeArguments):
(WebCore::WHLSL::inferTypesForCall):
* Modules/webgpu/WHLSL/WHLSLInferTypes.h: Copied from Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLIntegerLiteralType.cpp.
* Modules/webgpu/WHLSL/WHLSLNameContext.cpp: Added. This is the data structure that remembers NamedTypes,
FunctionDeclarations, and VariableDeclarations so NameResolver can work.
(WebCore::WHLSL::NameContext::NameContext):
(WebCore::WHLSL::NameContext::add):
(WebCore::WHLSL::NameContext::getTypes):
(WebCore::WHLSL::NameContext::getFunctions):
(WebCore::WHLSL::NameContext::getVariable):
(WebCore::WHLSL::NameContext::exists):
* Modules/webgpu/WHLSL/WHLSLNameContext.h: Copied from Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLFloatLiteralType.h.
* Modules/webgpu/WHLSL/WHLSLNameResolver.cpp: Added. Use the NameContext to match up the three types of names.
(WebCore::WHLSL::NameResolver::NameResolver):
(WebCore::WHLSL::NameResolver::visit):
(WebCore::WHLSL::resolveNamesInTypes):
(WebCore::WHLSL::resolveNamesInFunctions):
* Modules/webgpu/WHLSL/WHLSLNameResolver.h: Copied from Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLFloatLiteralType.h.
(WebCore::WHLSL::NameResolver::setCurrentFunctionDefinition):
* Modules/webgpu/WHLSL/WHLSLProgram.h:
(WebCore::WHLSL::Program::append): The parser needs to add all global declarations to the name context so the
name resolver is ready to go as soon as parsing is finished.
(WebCore::WHLSL::Program::nameContext):
* Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.cpp: Added. Pick the appropriate FunctionDeclaration or
NamedType for a particular CallExpression or TypeReference.
(WebCore::WHLSL::conversionCost):
(WebCore::WHLSL::resolveFunctionOverloadImpl):
(WebCore::WHLSL::resolveTypeOverloadImpl):
* Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.h: Copied from Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLIntegerLiteralType.cpp.
* Modules/webgpu/WHLSL/WHLSLResolvingType.h: Copied from Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLUnsignedIntegerLiteralType.cpp. This describes the two states that a type in the type resolver can be in: either an owned
UnnamedType, or a reference to a ResolvableType. This is because every expression needs to have a type
associated with it, but those types might be the type of a literal (aka a ResolvableType). Multiple
expressions might need to reference the same ResolvableType so when it gets resolved, all the expressions
get the result.
(WebCore::WHLSL::ResolvableTypeReference::ResolvableTypeReference):
(WebCore::WHLSL::ResolvableTypeReference::resolvableType):
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:

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

21 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLFloatLiteralType.cpp
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLFloatLiteralType.h
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLIntegerLiteralType.cpp
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLIntegerLiteralType.h
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLNativeTypeDeclaration.h
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLUnsignedIntegerLiteralType.cpp
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLUnsignedIntegerLiteralType.h
Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.cpp [new file with mode: 0644]
Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.h [new file with mode: 0644]
Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameContext.cpp [new file with mode: 0644]
Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameContext.h [new file with mode: 0644]
Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp [new file with mode: 0644]
Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h [new file with mode: 0644]
Source/WebCore/Modules/webgpu/WHLSL/WHLSLProgram.h
Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.cpp [new file with mode: 0644]
Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.h [new file with mode: 0644]
Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolvingType.h [new file with mode: 0644]
Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.h
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj

index ebdaeeb..356730a 100644 (file)
@@ -1,5 +1,86 @@
 2019-01-11  Myles C. Maxfield  <mmaxfield@apple.com>
 
+        [WHLSL] Implement the NameResolver
+        https://bugs.webkit.org/show_bug.cgi?id=193007
+
+        Reviewed by Dean Jackson.
+
+        This is the base implementation for WHLSL's name resolver. The name resolver matches three kinds of things:
+        1. It matches VariableRefs to VariableDecls
+        2. It matches TypeRefs to NamedTypes
+        3. It matches CallExpressions to FunctionDeclarations
+
+        No new tests because it isn't hooked up yet. Not enough of the compiler exists to have any meaningful sort
+        of test. When enough of the compiler is present, I'll port the reference implementation's test suite.
+
+        * Modules/webgpu/WHLSL/AST/WHLSLFloatLiteralType.cpp: Now that InferTypes.h exists, we can implement these
+        functions.
+        (WebCore::WHLSL::AST::FloatLiteralType::canResolve const):
+        (WebCore::WHLSL::AST::FloatLiteralType::conversionCost const):
+        * Modules/webgpu/WHLSL/AST/WHLSLFloatLiteralType.h: Remove unnecessary function.
+        (WebCore::WHLSL::AST::FloatLiteralType::value const): Deleted.
+        * Modules/webgpu/WHLSL/AST/WHLSLIntegerLiteralType.cpp: Now that InferTypes.h exists, we can implement these
+        functions.
+        (WebCore::WHLSL::AST::IntegerLiteralType::canResolve const):
+        (WebCore::WHLSL::AST::IntegerLiteralType::conversionCost const):
+        * Modules/webgpu/WHLSL/AST/WHLSLIntegerLiteralType.h: Remove unnecessary function.
+        (WebCore::WHLSL::AST::IntegerLiteralType::value const): Deleted.
+        * Modules/webgpu/WHLSL/AST/WHLSLSpecializationConstantSemantic.cpp: Modifying Sources.txt caused the sources
+        to get shuffled around, so the #includes need to be fixed.
+        * Modules/webgpu/WHLSL/AST/WHLSLUnsignedIntegerLiteralType.cpp: Now that InferTypes.h exists, we can implement
+        these functions.
+        (WebCore::WHLSL::AST::UnsignedIntegerLiteralType::canResolve const):
+        (WebCore::WHLSL::AST::UnsignedIntegerLiteralType::conversionCost const):
+        * Modules/webgpu/WHLSL/AST/WHLSLUnsignedIntegerLiteralType.h: Remove unnecessary function.
+        (WebCore::WHLSL::AST::UnsignedIntegerLiteralType::value const): Deleted.
+        * Modules/webgpu/WHLSL/WHLSLInferTypes.cpp: Added. This is the replacement for UnificationContext in the
+        reference compiler. It's much simpler (and we should remove UnificationContext in the reference compiler in
+        favor of this design). It has three sets of functions: Tell if two types are the same, tell if two types are
+        the same and commit the resolvable type, and run the above functions on type references or function arguments.
+        (WebCore::WHLSL::matches):
+        (WebCore::WHLSL::matchAndCommit):
+        (WebCore::WHLSL::commit):
+        (WebCore::WHLSL::inferTypesForTypeArguments):
+        (WebCore::WHLSL::inferTypesForCall):
+        * Modules/webgpu/WHLSL/WHLSLInferTypes.h: Copied from Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLIntegerLiteralType.cpp.
+        * Modules/webgpu/WHLSL/WHLSLNameContext.cpp: Added. This is the data structure that remembers NamedTypes,
+        FunctionDeclarations, and VariableDeclarations so NameResolver can work.
+        (WebCore::WHLSL::NameContext::NameContext):
+        (WebCore::WHLSL::NameContext::add):
+        (WebCore::WHLSL::NameContext::getTypes):
+        (WebCore::WHLSL::NameContext::getFunctions):
+        (WebCore::WHLSL::NameContext::getVariable):
+        (WebCore::WHLSL::NameContext::exists):
+        * Modules/webgpu/WHLSL/WHLSLNameContext.h: Copied from Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLFloatLiteralType.h.
+        * Modules/webgpu/WHLSL/WHLSLNameResolver.cpp: Added. Use the NameContext to match up the three types of names.
+        (WebCore::WHLSL::NameResolver::NameResolver):
+        (WebCore::WHLSL::NameResolver::visit):
+        (WebCore::WHLSL::resolveNamesInTypes):
+        (WebCore::WHLSL::resolveNamesInFunctions):
+        * Modules/webgpu/WHLSL/WHLSLNameResolver.h: Copied from Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLFloatLiteralType.h.
+        (WebCore::WHLSL::NameResolver::setCurrentFunctionDefinition):
+        * Modules/webgpu/WHLSL/WHLSLProgram.h:
+        (WebCore::WHLSL::Program::append): The parser needs to add all global declarations to the name context so the
+        name resolver is ready to go as soon as parsing is finished.
+        (WebCore::WHLSL::Program::nameContext):
+        * Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.cpp: Added. Pick the appropriate FunctionDeclaration or
+        NamedType for a particular CallExpression or TypeReference.
+        (WebCore::WHLSL::conversionCost):
+        (WebCore::WHLSL::resolveFunctionOverloadImpl):
+        (WebCore::WHLSL::resolveTypeOverloadImpl):
+        * Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.h: Copied from Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLIntegerLiteralType.cpp.
+        * Modules/webgpu/WHLSL/WHLSLResolvingType.h: Copied from Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLUnsignedIntegerLiteralType.cpp. This describes the two states that a type in the type resolver can be in: either an owned
+        UnnamedType, or a reference to a ResolvableType. This is because every expression needs to have a type
+        associated with it, but those types might be the type of a literal (aka a ResolvableType). Multiple
+        expressions might need to reference the same ResolvableType so when it gets resolved, all the expressions
+        get the result.
+        (WebCore::WHLSL::ResolvableTypeReference::ResolvableTypeReference):
+        (WebCore::WHLSL::ResolvableTypeReference::resolvableType):
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+
+2019-01-11  Myles C. Maxfield  <mmaxfield@apple.com>
+
         [WHLSL] Add a Visitor class
         https://bugs.webkit.org/show_bug.cgi?id=192826
 
index 4680932..3325cc5 100644 (file)
@@ -28,6 +28,8 @@
 
 #if ENABLE(WEBGPU)
 
+#include "WHLSLInferTypes.h"
+#include "WHLSLNativeTypeDeclaration.h"
 #include "WHLSLTypeReference.h"
 
 namespace WebCore {
@@ -44,16 +46,30 @@ FloatLiteralType::FloatLiteralType(Lexer::Token&& origin, float value)
 
 FloatLiteralType::~FloatLiteralType() = default;
 
-bool FloatLiteralType::canResolve(const Type&) const
+FloatLiteralType::FloatLiteralType(FloatLiteralType&&) = default;
+
+FloatLiteralType& FloatLiteralType::operator=(FloatLiteralType&&) = default;
+
+bool FloatLiteralType::canResolve(const Type& type) const
 {
-    // FIXME: Implement this
+    if (!is<NamedType>(type))
+        return false;
+    auto& namedType = downcast<NamedType>(type);
+    if (!is<NativeTypeDeclaration>(namedType))
+        return false;
+    auto& nativeTypeDeclaration = downcast<NativeTypeDeclaration>(namedType);
+    if (!nativeTypeDeclaration.isFloating())
+        return false;
+    if (!nativeTypeDeclaration.canRepresentFloat()(m_value))
+        return false;
     return true;
 }
 
-unsigned FloatLiteralType::conversionCost(const UnnamedType&) const
+unsigned FloatLiteralType::conversionCost(const UnnamedType& unnamedType) const
 {
-    // FIXME: Implement this
-    return 0;
+    if (matches(unnamedType, static_cast<const TypeReference&>(m_preferredType)))
+        return 0;
+    return 1;
 }
 
 } // namespace AST
index f3a4432..5680643 100644 (file)
@@ -46,10 +46,10 @@ public:
     virtual ~FloatLiteralType();
 
     FloatLiteralType(const FloatLiteralType&) = delete;
-    FloatLiteralType(FloatLiteralType&&) = default;
+    FloatLiteralType(FloatLiteralType&&);
 
     FloatLiteralType& operator=(const FloatLiteralType&) = delete;
-    FloatLiteralType& operator=(FloatLiteralType&&) = default;
+    FloatLiteralType& operator=(FloatLiteralType&&);
 
     bool isFloatLiteralType() const override { return true; }
 
@@ -58,8 +58,6 @@ public:
     bool canResolve(const Type&) const override;
     unsigned conversionCost(const UnnamedType&) const override;
 
-    float value() const { return m_value; }
-
 private:
     float m_value;
     // This is a unique_ptr to resolve a circular dependency between
index 047ee6f..3223641 100644 (file)
@@ -28,6 +28,8 @@
 
 #if ENABLE(WEBGPU)
 
+#include "WHLSLInferTypes.h"
+#include "WHLSLNativeTypeDeclaration.h"
 #include "WHLSLTypeArgument.h"
 #include "WHLSLTypeReference.h"
 
@@ -45,16 +47,30 @@ IntegerLiteralType::IntegerLiteralType(Lexer::Token&& origin, int value)
 
 IntegerLiteralType::~IntegerLiteralType() = default;
 
-bool IntegerLiteralType::canResolve(const Type&) const
+IntegerLiteralType::IntegerLiteralType(IntegerLiteralType&&) = default;
+
+IntegerLiteralType& IntegerLiteralType::operator=(IntegerLiteralType&&) = default;
+
+bool IntegerLiteralType::canResolve(const Type& type) const
 {
-    // FIXME: Implement this
+    if (!is<NamedType>(type))
+        return false;
+    auto& namedType = downcast<NamedType>(type);
+    if (!is<NativeTypeDeclaration>(namedType))
+        return false;
+    auto& nativeTypeDeclaration = downcast<NativeTypeDeclaration>(namedType);
+    if (!nativeTypeDeclaration.isNumber())
+        return false;
+    if (!nativeTypeDeclaration.canRepresentInteger()(m_value))
+        return false;
     return true;
 }
 
-unsigned IntegerLiteralType::conversionCost(const UnnamedType&) const
+unsigned IntegerLiteralType::conversionCost(const UnnamedType& unnamedType) const
 {
-    // FIXME: Implement this
-    return 0;
+    if (matches(unnamedType, static_cast<const TypeReference&>(m_preferredType)))
+        return 0;
+    return 1;
 }
 
 } // namespace AST
index 4e7d0ec..426f0fe 100644 (file)
@@ -46,10 +46,10 @@ public:
     virtual ~IntegerLiteralType();
 
     IntegerLiteralType(const IntegerLiteralType&) = delete;
-    IntegerLiteralType(IntegerLiteralType&&) = default;
+    IntegerLiteralType(IntegerLiteralType&&);
 
     IntegerLiteralType& operator=(const IntegerLiteralType&) = delete;
-    IntegerLiteralType& operator=(IntegerLiteralType&&) = default;
+    IntegerLiteralType& operator=(IntegerLiteralType&&);
 
     bool isIntegerLiteralType() const override { return true; }
 
@@ -58,8 +58,6 @@ public:
     bool canResolve(const Type&) const override;
     unsigned conversionCost(const UnnamedType&) const override;
 
-    int value() const { return m_value; }
-
 private:
     int m_value;
     // This is a unique_ptr to resolve a circular dependency between
index 3dbc504..f651880 100644 (file)
@@ -30,6 +30,7 @@
 #include "WHLSLLexer.h"
 #include "WHLSLNamedType.h"
 #include "WHLSLTypeArgument.h"
+#include "WHLSLTypeReference.h"
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
index 4a9bc03..bf31a3c 100644 (file)
@@ -28,6 +28,8 @@
 
 #if ENABLE(WEBGPU)
 
+#include "WHLSLInferTypes.h"
+#include "WHLSLNativeTypeDeclaration.h"
 #include "WHLSLTypeArgument.h"
 #include "WHLSLTypeReference.h"
 #include <wtf/UniqueRef.h>
@@ -46,16 +48,32 @@ UnsignedIntegerLiteralType::UnsignedIntegerLiteralType(Lexer::Token&& origin, un
 
 UnsignedIntegerLiteralType::~UnsignedIntegerLiteralType() = default;
 
-bool UnsignedIntegerLiteralType::canResolve(const Type&) const
+UnsignedIntegerLiteralType::UnsignedIntegerLiteralType(UnsignedIntegerLiteralType&&) = default;
+
+UnsignedIntegerLiteralType& UnsignedIntegerLiteralType::operator=(UnsignedIntegerLiteralType&&) = default;
+
+bool UnsignedIntegerLiteralType::canResolve(const Type& type) const
 {
-    // FIXME: Implement this
+    if (!is<NamedType>(type))
+        return false;
+    auto& namedType = downcast<NamedType>(type);
+    if (!is<NativeTypeDeclaration>(namedType))
+        return false;
+    auto& nativeTypeDeclaration = downcast<NativeTypeDeclaration>(namedType);
+    if (!nativeTypeDeclaration.isInt())
+        return false;
+    if (!nativeTypeDeclaration.isSigned())
+        return false;
+    if (!nativeTypeDeclaration.canRepresentUnsignedInteger()(m_value))
+        return false;
     return true;
 }
 
-unsigned UnsignedIntegerLiteralType::conversionCost(const UnnamedType&) const
+unsigned UnsignedIntegerLiteralType::conversionCost(const UnnamedType& unnamedType) const
 {
-    // FIXME: Implement this
-    return 0;
+    if (matches(unnamedType, static_cast<const TypeReference&>(m_preferredType)))
+        return 0;
+    return 1;
 }
 
 } // namespace AST
index 52a3b77..362efa9 100644 (file)
@@ -46,10 +46,10 @@ public:
     virtual ~UnsignedIntegerLiteralType();
 
     UnsignedIntegerLiteralType(const UnsignedIntegerLiteralType&) = delete;
-    UnsignedIntegerLiteralType(UnsignedIntegerLiteralType&&) = default;
+    UnsignedIntegerLiteralType(UnsignedIntegerLiteralType&&);
 
     UnsignedIntegerLiteralType& operator=(const UnsignedIntegerLiteralType&) = delete;
-    UnsignedIntegerLiteralType& operator=(UnsignedIntegerLiteralType&&) = default;
+    UnsignedIntegerLiteralType& operator=(UnsignedIntegerLiteralType&&);
 
     bool isUnsignedIntegerLiteralType() const override { return true; }
 
@@ -58,8 +58,6 @@ public:
     bool canResolve(const Type&) const override;
     unsigned conversionCost(const UnnamedType&) const override;
 
-    unsigned value() const { return m_value; }
-
 private:
     unsigned m_value;
     // This is a unique_ptr to resolve a circular dependency between
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.cpp
new file mode 100644 (file)
index 0000000..20e0ef0
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * 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 "WHLSLInferTypes.h"
+
+#if ENABLE(WEBGPU)
+
+#include "WHLSLArrayReferenceType.h"
+#include "WHLSLArrayType.h"
+#include "WHLSLEnumerationDefinition.h"
+#include "WHLSLFunctionDeclaration.h"
+#include "WHLSLNamedType.h"
+#include "WHLSLNativeTypeDeclaration.h"
+#include "WHLSLPointerType.h"
+#include "WHLSLResolvableType.h"
+#include "WHLSLStructureDefinition.h"
+#include "WHLSLTypeDefinition.h"
+#include "WHLSLTypeReference.h"
+
+namespace WebCore {
+
+namespace WHLSL {
+
+static bool matches(const AST::Type& unifyThis, const AST::Type& unifyOther)
+{
+    if (&unifyThis == &unifyOther)
+        return true;
+
+    if (is<AST::NamedType>(unifyThis) && is<AST::NamedType>(unifyOther)) {
+#if !ASSERT_DISABLED
+        auto& namedThis = downcast<AST::NamedType>(unifyThis);
+        auto& namedOther = downcast<AST::NamedType>(unifyOther);
+        ASSERT(!is<AST::TypeDefinition>(namedThis) && !is<AST::TypeDefinition>(namedOther));
+#endif
+        return false;
+    }
+    if (is<AST::UnnamedType>(unifyThis) && is<AST::UnnamedType>(unifyOther)) {
+        auto& unnamedThis = downcast<AST::UnnamedType>(unifyThis);
+        auto& unnamedOther = downcast<AST::UnnamedType>(unifyOther);
+        ASSERT(!is<AST::TypeReference>(unnamedThis) && !is<AST::TypeReference>(unnamedOther));
+        if (is<AST::PointerType>(unnamedThis) && is<AST::PointerType>(unnamedOther)) {
+            auto& pointerThis = downcast<AST::PointerType>(unnamedThis);
+            auto& pointerOther = downcast<AST::PointerType>(unnamedOther);
+            if (pointerThis.addressSpace() != pointerOther.addressSpace())
+                return false;
+            return matches(pointerThis.elementType(), pointerOther.elementType());
+        }
+        if (is<AST::ArrayReferenceType>(unnamedThis) && is<AST::ArrayReferenceType>(unnamedOther)) {
+            auto& arrayReferenceThis = downcast<AST::ArrayReferenceType>(unnamedThis);
+            auto& arrayReferenceOther = downcast<AST::ArrayReferenceType>(unnamedOther);
+            if (arrayReferenceThis.addressSpace() != arrayReferenceOther.addressSpace())
+                return false;
+            return matches(arrayReferenceThis.elementType(), arrayReferenceOther.elementType());
+        }
+        if (is<AST::ArrayType>(unnamedThis) && is<AST::ArrayType>(unnamedOther)) {
+            auto& arrayThis = downcast<AST::ArrayType>(unnamedThis);
+            auto& arrayOther = downcast<AST::ArrayType>(unnamedOther);
+            if (arrayThis.numElements() != arrayOther.numElements())
+                return false;
+            return matches(arrayThis.type(), arrayOther.type());
+        }
+        return false;
+    }
+    return false;
+}
+
+bool matches(const AST::UnnamedType& unnamedType, const AST::UnnamedType& other)
+{
+    return matches(unnamedType.unifyNode(), other.unifyNode());
+}
+
+bool matches(const AST::NamedType& namedType, const AST::NamedType& other)
+{
+    return matches(namedType.unifyNode(), other.unifyNode());
+}
+
+bool matches(const AST::UnnamedType& unnamedType, const AST::NamedType& other)
+{
+    return matches(unnamedType.unifyNode(), other.unifyNode());
+}
+
+static Optional<UniqueRef<AST::UnnamedType>> matchAndCommit(AST::Type& unifyNode, AST::ResolvableType& resolvableType)
+{
+    ASSERT(!resolvableType.resolvedType());
+    if (!resolvableType.canResolve(unifyNode))
+        return WTF::nullopt;
+    if (is<AST::NamedType>(unifyNode)) {
+        auto& namedUnifyNode = downcast<AST::NamedType>(unifyNode);
+        auto result = AST::TypeReference::wrap(Lexer::Token(namedUnifyNode.origin()), namedUnifyNode);
+        resolvableType.resolve(result->clone());
+        return { WTFMove(result) };
+    }
+
+    auto result = downcast<AST::UnnamedType>(unifyNode).clone();
+    resolvableType.resolve(result->clone());
+    return result;
+}
+
+Optional<UniqueRef<AST::UnnamedType>> matchAndCommit(AST::UnnamedType& unnamedType, AST::ResolvableType& resolvableType)
+{
+    return matchAndCommit(unnamedType.unifyNode(), resolvableType);
+}
+
+Optional<UniqueRef<AST::UnnamedType>> matchAndCommit(AST::NamedType& namedType, AST::ResolvableType& resolvableType)
+{
+    return matchAndCommit(namedType.unifyNode(), resolvableType);
+}
+
+Optional<UniqueRef<AST::UnnamedType>> matchAndCommit(AST::ResolvableType& resolvableType1, AST::ResolvableType& resolvableType2)
+{
+    ASSERT(!resolvableType1.resolvedType());
+    ASSERT(!resolvableType2.resolvedType());
+    if (is<AST::FloatLiteralType>(resolvableType1) && is<AST::FloatLiteralType>(resolvableType2)) {
+        resolvableType1.resolve(downcast<AST::FloatLiteralType>(resolvableType1).preferredType().clone());
+        resolvableType2.resolve(downcast<AST::FloatLiteralType>(resolvableType2).preferredType().clone());
+        return downcast<AST::FloatLiteralType>(resolvableType1).preferredType().clone();
+    }
+    if (is<AST::IntegerLiteralType>(resolvableType1) && is<AST::IntegerLiteralType>(resolvableType2)) {
+        resolvableType1.resolve(downcast<AST::IntegerLiteralType>(resolvableType1).preferredType().clone());
+        resolvableType2.resolve(downcast<AST::IntegerLiteralType>(resolvableType2).preferredType().clone());
+        return downcast<AST::IntegerLiteralType>(resolvableType1).preferredType().clone();
+    }
+    if (is<AST::UnsignedIntegerLiteralType>(resolvableType1) && is<AST::UnsignedIntegerLiteralType>(resolvableType2)) {
+        resolvableType1.resolve(downcast<AST::UnsignedIntegerLiteralType>(resolvableType1).preferredType().clone());
+        resolvableType2.resolve(downcast<AST::UnsignedIntegerLiteralType>(resolvableType2).preferredType().clone());
+        return downcast<AST::UnsignedIntegerLiteralType>(resolvableType1).preferredType().clone();
+    }
+    if (is<AST::NullLiteralType>(resolvableType1) && is<AST::NullLiteralType>(resolvableType2)) {
+        // FIXME: Trying to match nullptr and nullptr fails.
+        return WTF::nullopt;
+    }
+    return WTF::nullopt;
+}
+
+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();
+    }
+    if (is<AST::IntegerLiteralType>(resolvableType)) {
+        resolvableType.resolve(downcast<AST::IntegerLiteralType>(resolvableType).preferredType().clone());
+        return downcast<AST::IntegerLiteralType>(resolvableType).preferredType().clone();
+    }
+    if (is<AST::UnsignedIntegerLiteralType>(resolvableType)) {
+        resolvableType.resolve(downcast<AST::UnsignedIntegerLiteralType>(resolvableType).preferredType().clone());
+        return downcast<AST::UnsignedIntegerLiteralType>(resolvableType).preferredType().clone();
+    }
+    if (is<AST::NullLiteralType>(resolvableType)) {
+        // FIXME: Trying to match nullptr and nullptr fails.
+        return WTF::nullopt;
+    }
+    return WTF::nullopt;
+}
+
+bool inferTypesForTypeArguments(AST::NamedType& possibleType, AST::TypeArguments& typeArguments)
+{
+    if (is<AST::TypeDefinition>(possibleType)
+        || is<AST::StructureDefinition>(possibleType)
+        || is<AST::EnumerationDefinition>(possibleType)) {
+        return typeArguments.isEmpty();
+    }
+
+    ASSERT(is<AST::NativeTypeDeclaration>(possibleType));
+    auto& nativeTypeDeclaration = downcast<AST::NativeTypeDeclaration>(possibleType);
+    if (nativeTypeDeclaration.typeArguments().size() != typeArguments.size())
+        return false;
+    for (size_t i = 0; i < nativeTypeDeclaration.typeArguments().size(); ++i) {
+        AST::ConstantExpression* typeArgumentExpression = nullptr;
+        AST::TypeReference* typeArgumentTypeReference = nullptr;
+        AST::ConstantExpression* nativeTypeArgumentExpression = nullptr;
+        AST::TypeReference* nativeTypeArgumentTypeReference = nullptr;
+
+        auto assign = [&](AST::TypeArgument& typeArgument, AST::ConstantExpression*& expression, AST::TypeReference*& typeReference) {
+            WTF::visit(WTF::makeVisitor([&](AST::ConstantExpression& constantExpression) {
+                expression = &constantExpression;
+            }, [&](UniqueRef<AST::TypeReference>& theTypeReference) {
+                typeReference = &static_cast<AST::TypeReference&>(theTypeReference);
+            }), typeArgument);
+        };
+
+        assign(typeArguments[i], typeArgumentExpression, typeArgumentTypeReference);
+        assign(nativeTypeDeclaration.typeArguments()[i], nativeTypeArgumentExpression, nativeTypeArgumentTypeReference);
+
+        if (typeArgumentExpression && nativeTypeArgumentExpression) {
+            if (!typeArgumentExpression->matches(*nativeTypeArgumentExpression))
+                return false;
+        } else if (typeArgumentTypeReference && nativeTypeArgumentTypeReference) {
+            if (!matches(*typeArgumentTypeReference, *nativeTypeArgumentTypeReference))
+                return false;
+        }
+    }
+
+    return true;
+}
+
+bool inferTypesForCall(AST::FunctionDeclaration& possibleFunction, Vector<std::reference_wrapper<ResolvingType>>& argumentTypes, Optional<std::reference_wrapper<AST::NamedType>>& castReturnType)
+{
+    if (possibleFunction.parameters().size() != argumentTypes.size())
+        return false;
+    for (size_t i = 0; i < possibleFunction.parameters().size(); ++i) {
+        auto success = WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& unnamedType) -> bool {
+            return matches(*possibleFunction.parameters()[i].type(), static_cast<AST::UnnamedType&>(unnamedType));
+        }, [&](Ref<ResolvableTypeReference>& resolvableTypeReference) -> bool {
+            return resolvableTypeReference->resolvableType().canResolve(*possibleFunction.parameters()[i].type());
+        }), argumentTypes[i].get());
+        if (!success)
+            return false;
+    }
+    if (castReturnType && !matches(castReturnType->get(), possibleFunction.type()))
+        return false;
+    return true;
+}
+
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.h
new file mode 100644 (file)
index 0000000..dfd4b54
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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 "WHLSLResolvingType.h"
+#include "WHLSLTypeArgument.h"
+#include <memory>
+
+namespace WebCore {
+
+namespace WHLSL {
+
+namespace AST {
+
+class FunctionDeclaration;
+class NamedType;
+class ResolvableType;
+class UnnamedType;
+
+}
+
+bool matches(const AST::UnnamedType&, const AST::UnnamedType&);
+bool matches(const AST::NamedType&, const AST::NamedType&);
+bool matches(const AST::UnnamedType&, const AST::NamedType&);
+// FIXME: Is anyone actually using the return type here?
+Optional<UniqueRef<AST::UnnamedType>> matchAndCommit(AST::UnnamedType&, AST::ResolvableType&);
+Optional<UniqueRef<AST::UnnamedType>> matchAndCommit(AST::NamedType&, AST::ResolvableType&);
+Optional<UniqueRef<AST::UnnamedType>> matchAndCommit(AST::ResolvableType&, AST::ResolvableType&);
+Optional<UniqueRef<AST::UnnamedType>> commit(AST::ResolvableType&);
+bool inferTypesForTypeArguments(AST::NamedType& possibleType, AST::TypeArguments&);
+bool inferTypesForCall(AST::FunctionDeclaration& possibleFunction, Vector<std::reference_wrapper<ResolvingType>>& argumentTypes, Optional<std::reference_wrapper<AST::NamedType>>& castReturnType);
+
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameContext.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameContext.cpp
new file mode 100644 (file)
index 0000000..ca31306
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * 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 "WHLSLNameContext.h"
+
+#if ENABLE(WEBGPU)
+
+#include "WHLSLEnumerationDefinition.h"
+#include "WHLSLFunctionDefinition.h"
+#include "WHLSLNativeFunctionDeclaration.h"
+#include "WHLSLNativeTypeDeclaration.h"
+#include "WHLSLStructureDefinition.h"
+#include "WHLSLTypeDefinition.h"
+#include "WHLSLVariableDeclaration.h"
+
+namespace WebCore {
+
+namespace WHLSL {
+
+NameContext::NameContext(NameContext* parent)
+    : m_parent(parent)
+{
+}
+
+bool NameContext::add(AST::TypeDefinition& typeDefinition)
+{
+    if (exists(typeDefinition.name()))
+        return false;
+    auto result = m_types.add(typeDefinition.name(), Vector<std::reference_wrapper<AST::NamedType>, 1>());
+    if (!result.isNewEntry)
+        return false;
+    result.iterator->value.append(typeDefinition);
+    return true;
+}
+
+bool NameContext::add(AST::StructureDefinition& structureDefinition)
+{
+    if (exists(structureDefinition.name()))
+        return false;
+    auto result = m_types.add(structureDefinition.name(), Vector<std::reference_wrapper<AST::NamedType>, 1>());
+    if (!result.isNewEntry)
+        return false;
+    result.iterator->value.append(structureDefinition);
+    return true;
+}
+
+bool NameContext::add(AST::EnumerationDefinition& enumerationDefinition)
+{
+    if (exists(enumerationDefinition.name()))
+        return false;
+    auto result = m_types.add(enumerationDefinition.name(), Vector<std::reference_wrapper<AST::NamedType>, 1>());
+    if (!result.isNewEntry)
+        return false;
+    result.iterator->value.append(enumerationDefinition);
+    return true;
+}
+
+bool NameContext::add(AST::FunctionDefinition& functionDefinition)
+{
+    if (m_types.find(functionDefinition.name()) != m_types.end()
+        || m_variables.find(functionDefinition.name()) != m_variables.end())
+        return false;
+    auto result = m_functions.add(functionDefinition.name(), Vector<std::reference_wrapper<AST::FunctionDeclaration>, 1>());
+    result.iterator->value.append(functionDefinition);
+    return true;
+}
+
+bool NameContext::add(AST::NativeFunctionDeclaration& nativeFunctionDeclaration)
+{
+    if (m_types.find(nativeFunctionDeclaration.name()) != m_types.end()
+        || m_variables.find(nativeFunctionDeclaration.name()) != m_variables.end())
+        return false;
+    auto result = m_functions.add(nativeFunctionDeclaration.name(), Vector<std::reference_wrapper<AST::FunctionDeclaration>, 1>());
+    result.iterator->value.append(nativeFunctionDeclaration);
+    return true;
+}
+
+bool NameContext::add(AST::NativeTypeDeclaration& nativeTypeDeclaration)
+{
+    if (m_functions.find(nativeTypeDeclaration.name()) != m_functions.end()
+        || m_variables.find(nativeTypeDeclaration.name()) != m_variables.end())
+        return false;
+    auto result = m_types.add(nativeTypeDeclaration.name(), Vector<std::reference_wrapper<AST::NamedType>, 1>());
+    result.iterator->value.append(nativeTypeDeclaration);
+    return true;
+}
+
+bool NameContext::add(AST::VariableDeclaration& variableDeclaration)
+{
+    if (exists(variableDeclaration.name()))
+        return false;
+    auto result = m_variables.add(String(variableDeclaration.name()), &variableDeclaration);
+    return result.isNewEntry;
+}
+
+Vector<std::reference_wrapper<AST::NamedType>, 1>* NameContext::getTypes(const String& name)
+{
+    auto iterator = m_types.find(name);
+    if (iterator == m_types.end()) {
+        if (m_parent)
+            return m_parent->getTypes(name);
+        return nullptr;
+    }
+    return &iterator->value;
+}
+
+Vector<std::reference_wrapper<AST::FunctionDeclaration>, 1>* NameContext::getFunctions(const String& name)
+{
+    auto iterator = m_functions.find(name);
+    if (iterator == m_functions.end()) {
+        if (m_parent)
+            return m_parent->getFunctions(name);
+        return nullptr;
+    }
+    return &iterator->value;
+}
+
+AST::VariableDeclaration* NameContext::getVariable(const String& name)
+{
+    auto iterator = m_variables.find(name);
+    if (iterator == m_variables.end()) {
+        if (m_parent)
+            return m_parent->getVariable(name);
+        return nullptr;
+    }
+    return iterator->value;
+}
+
+bool NameContext::exists(String& name)
+{
+    return m_types.find(name) != m_types.end()
+        || m_functions.find(name) != m_functions.end()
+        || m_variables.find(name) != m_variables.end();
+}
+
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameContext.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameContext.h
new file mode 100644 (file)
index 0000000..a04878a
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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 <functional>
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+namespace WHLSL {
+
+namespace AST {
+
+class NamedType;
+class FunctionDeclaration;
+class TypeDefinition;
+class StructureDefinition;
+class EnumerationDefinition;
+class FunctionDefinition;
+class NativeFunctionDeclaration;
+class NativeTypeDeclaration;
+class VariableDeclaration;
+
+}
+
+class NameContext {
+public:
+    NameContext(NameContext* parent = nullptr);
+
+    bool add(AST::TypeDefinition&);
+    bool add(AST::StructureDefinition&);
+    bool add(AST::EnumerationDefinition&);
+    bool add(AST::FunctionDefinition&);
+    bool add(AST::NativeFunctionDeclaration&);
+    bool add(AST::NativeTypeDeclaration&);
+    bool add(AST::VariableDeclaration&);
+
+    Vector<std::reference_wrapper<AST::NamedType>, 1>* getTypes(const String&);
+    Vector<std::reference_wrapper<AST::FunctionDeclaration>, 1>* getFunctions(const String&);
+    AST::VariableDeclaration* getVariable(const String&);
+
+private:
+    bool exists(String&);
+
+    HashMap<String, Vector<std::reference_wrapper<AST::NamedType>, 1>> m_types;
+    HashMap<String, Vector<std::reference_wrapper<AST::FunctionDeclaration>, 1>> m_functions;
+    HashMap<String, AST::VariableDeclaration*> m_variables;
+    NameContext* m_parent;
+};
+
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp
new file mode 100644 (file)
index 0000000..6bf18e6
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * 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 "WHLSLNameResolver.h"
+
+#if ENABLE(WEBGPU)
+
+#include "WHLSLCallExpression.h"
+#include "WHLSLDoWhileLoop.h"
+#include "WHLSLDotExpression.h"
+#include "WHLSLEnumerationDefinition.h"
+#include "WHLSLEnumerationMemberLiteral.h"
+#include "WHLSLForLoop.h"
+#include "WHLSLFunctionDefinition.h"
+#include "WHLSLIfStatement.h"
+#include "WHLSLNameContext.h"
+#include "WHLSLProgram.h"
+#include "WHLSLPropertyAccessExpression.h"
+#include "WHLSLResolveOverloadImpl.h"
+#include "WHLSLReturn.h"
+#include "WHLSLTypeReference.h"
+#include "WHLSLVariableDeclaration.h"
+#include "WHLSLVariableReference.h"
+#include "WHLSLWhileLoop.h"
+
+namespace WebCore {
+
+namespace WHLSL {
+
+NameResolver::NameResolver(NameContext& nameContext)
+    : m_nameContext(nameContext)
+{
+}
+
+void NameResolver::visit(AST::TypeReference& typeReference)
+{
+    checkErrorAndVisit(typeReference);
+    if (typeReference.resolvedType())
+        return;
+
+    auto* candidates = m_nameContext.getTypes(typeReference.name());
+    if (candidates == nullptr) {
+        setError();
+        return;
+    }
+    if (auto result = resolveTypeOverloadImpl(*candidates, typeReference.typeArguments()))
+        typeReference.setResolvedType(*result);
+    else {
+        setError();
+        return;
+    }
+}
+
+void NameResolver::visit(AST::FunctionDefinition& functionDefinition)
+{
+    NameContext newNameContext(&m_nameContext);
+    NameResolver newNameResolver(newNameContext);
+    checkErrorAndVisit(functionDefinition.type());
+    for (auto& parameter : functionDefinition.parameters()) {
+        newNameResolver.checkErrorAndVisit(parameter);
+        auto success = newNameContext.add(parameter);
+        if (!success) {
+            setError();
+            return;
+        }
+    }
+    newNameResolver.checkErrorAndVisit(functionDefinition.block());
+}
+
+void NameResolver::visit(AST::Block& block)
+{
+    NameContext nameContext(&m_nameContext);
+    NameResolver(nameContext).checkErrorAndVisit(block);
+}
+
+void NameResolver::visit(AST::IfStatement& ifStatement)
+{
+    checkErrorAndVisit(ifStatement.conditional());
+    NameContext nameContext(&m_nameContext);
+    NameResolver(nameContext).checkErrorAndVisit(ifStatement.body());
+    if (ifStatement.elseBody()) {
+        NameContext nameContext(&m_nameContext);
+        NameResolver(nameContext).checkErrorAndVisit(static_cast<AST::Statement&>(*ifStatement.elseBody()));
+    }
+}
+
+void NameResolver::visit(AST::WhileLoop& whileLoop)
+{
+    checkErrorAndVisit(whileLoop.conditional());
+    NameContext nameContext(&m_nameContext);
+    NameResolver(nameContext).checkErrorAndVisit(whileLoop.body());
+}
+
+void NameResolver::visit(AST::DoWhileLoop& whileLoop)
+{
+    NameContext nameContext(&m_nameContext);
+    NameResolver(nameContext).checkErrorAndVisit(whileLoop.body());
+    checkErrorAndVisit(whileLoop.conditional());
+}
+
+void NameResolver::visit(AST::ForLoop& forLoop)
+{
+    NameContext nameContext(&m_nameContext);
+    NameResolver(nameContext).checkErrorAndVisit(forLoop);
+}
+
+void NameResolver::visit(AST::VariableDeclaration& variableDeclaration)
+{
+    m_nameContext.add(variableDeclaration);
+    checkErrorAndVisit(variableDeclaration);
+}
+
+void NameResolver::visit(AST::VariableReference& variableReference)
+{
+    if (variableReference.variable())
+        return;
+
+    if (auto* variable = m_nameContext.getVariable(variableReference.name()))
+        variableReference.setVariable(*variable);
+    else {
+        setError();
+        return;
+    }
+}
+
+void NameResolver::visit(AST::Return& returnStatement)
+{
+    ASSERT(m_currentFunction);
+    returnStatement.setFunction(m_currentFunction);
+    checkErrorAndVisit(returnStatement);
+}
+
+void NameResolver::visit(AST::PropertyAccessExpression& propertyAccessExpression)
+{
+    if (auto* getFunctions = m_nameContext.getFunctions(propertyAccessExpression.getFunctionName()))
+        propertyAccessExpression.setPossibleGetOverloads(*getFunctions);
+    if (auto* setFunctions = m_nameContext.getFunctions(propertyAccessExpression.setFunctionName()))
+        propertyAccessExpression.setPossibleSetOverloads(*setFunctions);
+    if (auto* andFunctions = m_nameContext.getFunctions(propertyAccessExpression.andFunctionName()))
+        propertyAccessExpression.setPossibleAndOverloads(*andFunctions);
+    checkErrorAndVisit(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())) {
+            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())) {
+                    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);
+                    return;
+                }
+                setError();
+                return;
+            }
+        }
+    }
+
+    checkErrorAndVisit(dotExpression);
+}
+
+void NameResolver::visit(AST::CallExpression& callExpression)
+{
+    if (!callExpression.hasOverloads()) {
+        if (auto* functions = m_nameContext.getFunctions(callExpression.name()))
+            callExpression.setOverloads(*functions);
+        else {
+            if (auto* types = m_nameContext.getTypes(callExpression.name())) {
+                if (types->size() == 1) {
+                    if (auto* functions = m_nameContext.getFunctions(String("operator cast", String::ConstructFromLiteral))) {
+                        callExpression.setCastData((*types)[0].get());
+                        callExpression.setOverloads(*functions);
+                    }
+                }
+            }
+        }
+    }
+    if (!callExpression.hasOverloads()) {
+        setError();
+        return;
+    }
+    checkErrorAndVisit(callExpression);
+}
+
+void NameResolver::visit(AST::ConstantExpressionEnumerationMemberReference& constantExpressionEnumerationMemberReference)
+{
+    if (auto enumerationTypes = m_nameContext.getTypes(constantExpressionEnumerationMemberReference.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);
+                return;
+            }
+        }
+    }
+    
+    setError();
+}
+
+// FIXME: Make sure all the names have been resolved.
+
+bool resolveNamesInTypes(Program& program, NameResolver& nameResolver)
+{
+    for (auto& typeDefinition : program.typeDefinitions()) {
+        nameResolver.checkErrorAndVisit(static_cast<AST::TypeDefinition&>(typeDefinition));
+        if (nameResolver.error())
+            return false;
+    }
+    for (auto& structureDefinition : program.structureDefinitions()) {
+        nameResolver.checkErrorAndVisit(static_cast<AST::StructureDefinition&>(structureDefinition));
+        if (nameResolver.error())
+            return false;
+    }
+    for (auto& enumerationDefinition : program.enumerationDefinitions()) {
+        nameResolver.checkErrorAndVisit(static_cast<AST::EnumerationDefinition&>(enumerationDefinition));
+        if (nameResolver.error())
+            return false;
+    }
+    for (auto& nativeTypeDeclaration : program.nativeTypeDeclarations()) {
+        nameResolver.checkErrorAndVisit(static_cast<AST::NativeTypeDeclaration&>(nativeTypeDeclaration));
+        if (nameResolver.error())
+            return false;
+    }
+    return true;
+}
+
+bool resolveNamesInFunctions(Program& program, NameResolver& nameResolver)
+{
+    for (auto& functionDefinition : program.functionDefinitions()) {
+        nameResolver.setCurrentFunctionDefinition(&static_cast<AST::FunctionDefinition&>(functionDefinition));
+        nameResolver.checkErrorAndVisit(static_cast<AST::FunctionDefinition&>(functionDefinition));
+        if (nameResolver.error())
+            return false;
+    }
+    nameResolver.setCurrentFunctionDefinition(nullptr);
+    for (auto& nativeFunctionDeclaration : program.nativeFunctionDeclarations()) {
+        nameResolver.checkErrorAndVisit(static_cast<AST::FunctionDeclaration&>(nativeFunctionDeclaration));
+        if (nameResolver.error())
+            return false;
+    }
+    return true;
+}
+
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h
new file mode 100644 (file)
index 0000000..c72e08e
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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 "WHLSLNameContext.h"
+#include "WHLSLVisitor.h"
+
+namespace WebCore {
+
+namespace WHLSL {
+
+class Program;
+
+class NameResolver : public Visitor {
+public:
+    NameResolver(NameContext&);
+
+    virtual ~NameResolver() = default;
+
+    void visit(AST::FunctionDefinition&) override;
+
+    void setCurrentFunctionDefinition(AST::FunctionDefinition* functionDefinition)
+    {
+        m_currentFunction = functionDefinition;
+    }
+
+private:
+    void visit(AST::TypeReference&) override;
+    void visit(AST::Block&) override;
+    void visit(AST::IfStatement&) override;
+    void visit(AST::WhileLoop&) override;
+    void visit(AST::DoWhileLoop&) override;
+    void visit(AST::ForLoop&) override;
+    void visit(AST::VariableDeclaration&) override;
+    void visit(AST::VariableReference&) override;
+    void visit(AST::Return&) override;
+    void visit(AST::PropertyAccessExpression&) override;
+    void visit(AST::DotExpression&) override;
+    void visit(AST::CallExpression&) override;
+    void visit(AST::ConstantExpressionEnumerationMemberReference&) override;
+
+    NameContext m_nameContext;
+    AST::FunctionDefinition* m_currentFunction { nullptr };
+};
+
+bool resolveNamesInTypes(Program&, NameResolver&);
+bool resolveNamesInFunctions(Program&, NameResolver&);
+
+}
+
+}
+
+#endif
index a69e843..0dcf3f5 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "WHLSLEnumerationDefinition.h"
 #include "WHLSLFunctionDefinition.h"
+#include "WHLSLNameContext.h"
 #include "WHLSLNativeFunctionDeclaration.h"
 #include "WHLSLNativeTypeDeclaration.h"
 #include "WHLSLStructureDefinition.h"
@@ -47,39 +48,40 @@ public:
     bool append(AST::TypeDefinition&& typeDefinition)
     {
         m_typeDefinitions.append(makeUniqueRef<AST::TypeDefinition>(WTFMove(typeDefinition)));
-        return true;
+        return m_nameContext.add(static_cast<AST::TypeDefinition&>(m_typeDefinitions.last()));
     }
 
     bool append(AST::StructureDefinition&& structureDefinition)
     {
         m_structureDefinitions.append(makeUniqueRef<AST::StructureDefinition>(WTFMove(structureDefinition)));
-        return true;
+        return m_nameContext.add(static_cast<AST::StructureDefinition&>(m_structureDefinitions.last()));
     }
 
     bool append(AST::EnumerationDefinition&& enumerationDefinition)
     {
         m_enumerationDefinitions.append(makeUniqueRef<AST::EnumerationDefinition>(WTFMove(enumerationDefinition)));
-        return true;
+        return m_nameContext.add(static_cast<AST::EnumerationDefinition&>(m_enumerationDefinitions.last()));
     }
 
     bool append(AST::FunctionDefinition&& functionDefinition)
     {
         m_functionDefinitions.append(makeUniqueRef<AST::FunctionDefinition>(WTFMove(functionDefinition)));
-        return true;
+        return m_nameContext.add(static_cast<AST::FunctionDefinition&>(m_functionDefinitions.last()));
     }
 
     bool append(AST::NativeFunctionDeclaration&& nativeFunctionDeclaration)
     {
         m_nativeFunctionDeclarations.append(makeUniqueRef<AST::NativeFunctionDeclaration>(WTFMove(nativeFunctionDeclaration)));
-        return true;
+        return m_nameContext.add(static_cast<AST::NativeFunctionDeclaration&>(m_nativeFunctionDeclarations.last()));
     }
 
     bool append(AST::NativeTypeDeclaration&& nativeTypeDeclaration)
     {
         m_nativeTypeDeclarations.append(makeUniqueRef<AST::NativeTypeDeclaration>(WTFMove(nativeTypeDeclaration)));
-        return true;
+        return m_nameContext.add(static_cast<AST::NativeTypeDeclaration&>(m_nativeTypeDeclarations.last()));
     }
 
+    NameContext& nameContext() { return m_nameContext; }
     Vector<UniqueRef<AST::TypeDefinition>>& typeDefinitions() { return m_typeDefinitions; }
     Vector<UniqueRef<AST::StructureDefinition>>& structureDefinitions() { return m_structureDefinitions; }
     Vector<UniqueRef<AST::EnumerationDefinition>>& enumerationDefinitions() { return m_enumerationDefinitions; }
@@ -90,6 +92,7 @@ public:
     Vector<UniqueRef<AST::NativeTypeDeclaration>>& nativeTypeDeclarations() { return m_nativeTypeDeclarations; }
 
 private:
+    NameContext m_nameContext;
     Vector<UniqueRef<AST::TypeDefinition>> m_typeDefinitions;
     Vector<UniqueRef<AST::StructureDefinition>> m_structureDefinitions;
     Vector<UniqueRef<AST::EnumerationDefinition>> m_enumerationDefinitions;
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.cpp
new file mode 100644 (file)
index 0000000..ea1833d
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * 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 "WHLSLResolveOverloadImpl.h"
+
+#if ENABLE(WEBGPU)
+
+#include "WHLSLFunctionDeclaration.h"
+#include "WHLSLFunctionDefinition.h"
+#include "WHLSLInferTypes.h"
+#include <limits>
+
+namespace WebCore {
+
+namespace WHLSL {
+
+static unsigned conversionCost(AST::FunctionDeclaration& candidate, const Vector<std::reference_wrapper<ResolvingType>>& argumentTypes)
+{
+    unsigned conversionCost = 0;
+    for (size_t i = 0; i < candidate.parameters().size(); ++i) {
+        conversionCost += WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>&) -> unsigned {
+            return 0;
+        }, [&](Ref<ResolvableTypeReference>& resolvableTypeReference) -> unsigned {
+            return resolvableTypeReference->resolvableType().conversionCost(*candidate.parameters()[i].type());
+        }), argumentTypes[i].get());
+    }
+    // The return type can never be a literal type, so its conversion cost is always 0.
+    return conversionCost;
+}
+
+AST::FunctionDeclaration* resolveFunctionOverloadImpl(Vector<std::reference_wrapper<AST::FunctionDeclaration>, 1>& possibleFunctions, Vector<std::reference_wrapper<ResolvingType>>& argumentTypes, Optional<std::reference_wrapper<AST::NamedType>>& castReturnType)
+{
+    Vector<std::reference_wrapper<AST::FunctionDeclaration>, 1> candidates;
+    for (auto& possibleFunction : possibleFunctions) {
+        if (possibleFunction.get().entryPointType())
+            continue;
+        if (inferTypesForCall(possibleFunction.get(), argumentTypes, castReturnType))
+            candidates.append(possibleFunction.get());
+    }
+
+    unsigned minimumConversionCost = std::numeric_limits<unsigned>::max();
+    for (auto& candidate : candidates)
+        minimumConversionCost = std::min(minimumConversionCost, conversionCost(candidate.get(), argumentTypes));
+
+    Vector<std::reference_wrapper<AST::FunctionDeclaration>, 1> minimumCostCandidates;
+    for (auto& candidate : candidates) {
+        if (conversionCost(candidate.get(), argumentTypes) == minimumConversionCost)
+            minimumCostCandidates.append(candidate);
+    }
+
+    bool restrictedCandidateExists = false;
+    for (auto& candidate : minimumCostCandidates) {
+        if (is<AST::FunctionDefinition>(candidate.get()) && downcast<AST::FunctionDefinition>(candidate.get()).restricted()) {
+            restrictedCandidateExists = true;
+            break;
+        }
+    }
+
+    candidates.clear();
+    if (restrictedCandidateExists) {
+        for (auto& candidate : minimumCostCandidates) {
+            if (is<AST::FunctionDefinition>(candidate.get()) && downcast<AST::FunctionDefinition>(candidate.get()).restricted())
+                candidates.append(candidate.get());
+        }
+    } else
+        candidates = minimumCostCandidates;
+
+    if (candidates.size() == 1)
+        return &candidates[0].get();
+    return nullptr;
+}
+
+AST::NamedType* resolveTypeOverloadImpl(Vector<std::reference_wrapper<AST::NamedType>, 1>& possibleTypes, AST::TypeArguments& typeArguments)
+{
+    AST::NamedType* result = nullptr;
+    for (auto& possibleType : possibleTypes) {
+        if (inferTypesForTypeArguments(possibleType, typeArguments)) {
+            if (result)
+                return nullptr;
+            result = &static_cast<AST::NamedType&>(possibleType);
+        }
+    }
+
+    return result;
+}
+
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.h
new file mode 100644 (file)
index 0000000..8d9346f
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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 "WHLSLResolvingType.h"
+#include "WHLSLTypeArgument.h"
+#include <functional>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+namespace WHLSL {
+
+namespace AST {
+
+class FunctionDeclaration;
+class NamedType;
+
+}
+
+AST::FunctionDeclaration* resolveFunctionOverloadImpl(Vector<std::reference_wrapper<AST::FunctionDeclaration>, 1>& possibleFunctions, Vector<std::reference_wrapper<ResolvingType>>& argumentTypes, Optional<std::reference_wrapper<AST::NamedType>>& castReturnType);
+AST::NamedType* resolveTypeOverloadImpl(Vector<std::reference_wrapper<AST::NamedType>, 1>&, AST::TypeArguments&);
+
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolvingType.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLResolvingType.h
new file mode 100644 (file)
index 0000000..97c0eba
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 <memory>
+#include <wtf/Ref.h>
+#include <wtf/RefCounted.h>
+#include <wtf/UniqueRef.h>
+#include <wtf/Variant.h>
+
+namespace WebCore {
+
+namespace WHLSL {
+
+namespace AST {
+
+class ResolvableType;
+class UnnamedType;
+
+}
+
+class ResolvableTypeReference : public RefCounted<ResolvableTypeReference> {
+public:
+    ResolvableTypeReference(AST::ResolvableType& resolvableType)
+        : m_resolvableType(&resolvableType)
+    {
+    }
+
+    ResolvableTypeReference(const ResolvableTypeReference&) = delete;
+    ResolvableTypeReference(ResolvableTypeReference&&) = delete;
+
+    AST::ResolvableType& resolvableType() { return *m_resolvableType; }
+
+private:
+    AST::ResolvableType* m_resolvableType;
+};
+
+using ResolvingType = Variant<UniqueRef<AST::UnnamedType>, Ref<ResolvableTypeReference>>;
+
+}
+
+}
+
+#endif
index 5eab34c..a6ae293 100644 (file)
@@ -178,13 +178,13 @@ public:
 
     bool error() const { return m_error; }
 
-protected:
     template<typename T> void checkErrorAndVisit(T& x)
     {
         if (!m_error)
             visit(x);
     }
 
+protected:
     void setError()
     {
         ASSERT(!m_error);
index 29f4d1d..06f32d1 100644 (file)
@@ -306,8 +306,12 @@ Modules/websockets/WebSocketHandshake.cpp
 Modules/websockets/WorkerThreadableWebSocketChannel.cpp
 
 Modules/webgpu/DOMWindowWebGPU.cpp
+Modules/webgpu/WHLSL/WHLSLInferTypes.cpp
 Modules/webgpu/WHLSL/WHLSLLexer.cpp
 Modules/webgpu/WHLSL/WHLSLParser.cpp
+Modules/webgpu/WHLSL/WHLSLNameContext.cpp
+Modules/webgpu/WHLSL/WHLSLNameResolver.cpp
+Modules/webgpu/WHLSL/WHLSLResolveOverloadImpl.cpp
 Modules/webgpu/WHLSL/WHLSLVisitor.cpp
 Modules/webgpu/WHLSL/AST/WHLSLTypeArgument.cpp
 Modules/webgpu/WHLSL/AST/WHLSLBuiltInSemantic.cpp
index f38a3dc..7a9e1df 100644 (file)
                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>"; };
+               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>"; };
+               C234A98E21E88885003C984D /* WHLSLNameContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLNameContext.h; sourceTree = "<group>"; };
+               C234A99721E90F28003C984D /* WHLSLResolveOverloadImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLResolveOverloadImpl.h; sourceTree = "<group>"; };
+               C234A99921E90F29003C984D /* WHLSLResolveOverloadImpl.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLResolveOverloadImpl.cpp; sourceTree = "<group>"; };
+               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>"; };
                        isa = PBXGroup;
                        children = (
                                C21BF6F121CD898D00227979 /* AST */,
+                               C234A99A21E90F56003C984D /* WHLSLInferTypes.cpp */,
+                               C234A99B21E90F57003C984D /* WHLSLInferTypes.h */,
                                C210E91121B4BD1000B7F83D /* WHLSLLexer.cpp */,
                                C210E91221B4BD1000B7F83D /* WHLSLLexer.h */,
+                               C234A98D21E88884003C984D /* WHLSLNameContext.cpp */,
+                               C234A98E21E88885003C984D /* WHLSLNameContext.h */,
+                               C234A98A21E8883E003C984D /* WHLSLNameResolver.cpp */,
+                               C234A98C21E8883E003C984D /* WHLSLNameResolver.h */,
                                C21BF73721CD8A0200227979 /* WHLSLParser.cpp */,
                                C21BF73821CD8A0300227979 /* WHLSLParser.h */,
                                C21BF73A21CD8D7000227979 /* WHLSLProgram.h */,
+                               C234A99921E90F29003C984D /* WHLSLResolveOverloadImpl.cpp */,
+                               C234A99721E90F28003C984D /* WHLSLResolveOverloadImpl.h */,
+                               C234A99D21E910BD003C984D /* WHLSLResolvingType.h */,
                                C21BF74521CD969800227979 /* WHLSLStandardLibrary.txt */,
                                C234A98521E886A9003C984D /* WHLSLVisitor.cpp */,
                                C234A98721E886AD003C984D /* WHLSLVisitor.h */,