2c3a2d742e8277d5e3b2bfcfc7ab2ad70435342e
[WebKit-https.git] / Source / WebCore / Modules / webgpu / WHLSL / WHLSLNameResolver.cpp
1 /*
2  * Copyright (C) 2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WHLSLNameResolver.h"
28
29 #if ENABLE(WEBGPU)
30
31 #include "WHLSLCallExpression.h"
32 #include "WHLSLDoWhileLoop.h"
33 #include "WHLSLDotExpression.h"
34 #include "WHLSLEnumerationDefinition.h"
35 #include "WHLSLEnumerationMemberLiteral.h"
36 #include "WHLSLForLoop.h"
37 #include "WHLSLFunctionDefinition.h"
38 #include "WHLSLIfStatement.h"
39 #include "WHLSLNameContext.h"
40 #include "WHLSLProgram.h"
41 #include "WHLSLPropertyAccessExpression.h"
42 #include "WHLSLReplaceWith.h"
43 #include "WHLSLResolveOverloadImpl.h"
44 #include "WHLSLReturn.h"
45 #include "WHLSLScopedSetAdder.h"
46 #include "WHLSLTypeReference.h"
47 #include "WHLSLVariableDeclaration.h"
48 #include "WHLSLVariableReference.h"
49 #include "WHLSLWhileLoop.h"
50
51 namespace WebCore {
52
53 namespace WHLSL {
54
55 NameResolver::NameResolver(NameContext& nameContext)
56     : m_nameContext(nameContext)
57 {
58 }
59
60 NameResolver::NameResolver(NameResolver& parentResolver, NameContext& nameContext)
61     : m_nameContext(nameContext)
62     , m_parentNameResolver(&parentResolver)
63 {
64     setCurrentFunctionDefinition(parentResolver.m_currentFunction);
65 }
66
67 NameResolver::~NameResolver()
68 {
69     if (error() && m_parentNameResolver)
70         m_parentNameResolver->setError();
71 }
72
73 void NameResolver::visit(AST::TypeReference& typeReference)
74 {
75     ScopedSetAdder<AST::TypeReference*> adder(m_typeReferences, &typeReference);
76     if (!adder.isNewEntry()) {
77         setError();
78         return;
79     }
80
81     Visitor::visit(typeReference);
82     if (error())
83         return;
84     if (typeReference.maybeResolvedType()) // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198161 Shouldn't we know by now whether the type has been resolved or not?
85         return;
86
87     auto* candidates = m_nameContext.getTypes(typeReference.name());
88     if (candidates == nullptr) {
89         setError();
90         return;
91     }
92     for (auto& candidate : *candidates)
93         Visitor::visit(candidate);
94     if (auto result = resolveTypeOverloadImpl(*candidates, typeReference.typeArguments()))
95         typeReference.setResolvedType(*result);
96     else {
97         setError();
98         return;
99     }
100 }
101
102 void NameResolver::visit(AST::FunctionDefinition& functionDefinition)
103 {
104     NameContext newNameContext(&m_nameContext);
105     NameResolver newNameResolver(*this, newNameContext);
106     checkErrorAndVisit(functionDefinition.type());
107     if (error())
108         return;
109     for (auto& parameter : functionDefinition.parameters())
110         newNameResolver.checkErrorAndVisit(parameter);
111     newNameResolver.checkErrorAndVisit(functionDefinition.block());
112 }
113
114 void NameResolver::visit(AST::Block& block)
115 {
116     NameContext nameContext(&m_nameContext);
117     NameResolver newNameResolver(*this, nameContext);
118     newNameResolver.Visitor::visit(block);
119 }
120
121 void NameResolver::visit(AST::IfStatement& ifStatement)
122 {
123     checkErrorAndVisit(ifStatement.conditional());
124     if (error())
125         return;
126
127     {
128         NameContext nameContext(&m_nameContext);
129         NameResolver newNameResolver(*this, nameContext);
130         newNameResolver.checkErrorAndVisit(ifStatement.body());
131     }
132     if (error())
133         return;
134
135     if (ifStatement.elseBody()) {
136         NameContext nameContext(&m_nameContext);
137         NameResolver newNameResolver(*this, nameContext);
138         newNameResolver.checkErrorAndVisit(*ifStatement.elseBody());
139     }
140 }
141
142 void NameResolver::visit(AST::WhileLoop& whileLoop)
143 {
144     checkErrorAndVisit(whileLoop.conditional());
145     if (error())
146         return;
147
148     NameContext nameContext(&m_nameContext);
149     NameResolver newNameResolver(*this, nameContext);
150     newNameResolver.checkErrorAndVisit(whileLoop.body());
151 }
152
153 void NameResolver::visit(AST::DoWhileLoop& whileLoop)
154 {
155     {
156         NameContext nameContext(&m_nameContext);
157         NameResolver newNameResolver(*this, nameContext);
158         newNameResolver.checkErrorAndVisit(whileLoop.body());
159     }
160
161     checkErrorAndVisit(whileLoop.conditional());
162 }
163
164 void NameResolver::visit(AST::ForLoop& forLoop)
165 {
166     NameContext nameContext(&m_nameContext);
167     NameResolver newNameResolver(*this, nameContext);
168     newNameResolver.Visitor::visit(forLoop);
169 }
170
171 void NameResolver::visit(AST::VariableDeclaration& variableDeclaration)
172 {
173     if (!m_nameContext.add(variableDeclaration)) {
174         setError();
175         return;
176     }
177     Visitor::visit(variableDeclaration);
178 }
179
180 void NameResolver::visit(AST::VariableReference& variableReference)
181 {
182     if (variableReference.variable())
183         return;
184
185     if (auto* variable = m_nameContext.getVariable(variableReference.name()))
186         variableReference.setVariable(*variable);
187     else {
188         setError();
189         return;
190     }
191 }
192
193 void NameResolver::visit(AST::Return& returnStatement)
194 {
195     ASSERT(m_currentFunction);
196     returnStatement.setFunction(m_currentFunction);
197     Visitor::visit(returnStatement);
198 }
199
200 void NameResolver::visit(AST::PropertyAccessExpression& propertyAccessExpression)
201 {
202     Visitor::visit(propertyAccessExpression);
203 }
204
205 void NameResolver::visit(AST::DotExpression& dotExpression)
206 {
207     if (is<AST::VariableReference>(dotExpression.base())) {
208         auto baseName = downcast<AST::VariableReference>(dotExpression.base()).name();
209         if (auto enumerationTypes = m_nameContext.getTypes(baseName)) {
210             ASSERT(enumerationTypes->size() == 1);
211             AST::NamedType& type = (*enumerationTypes)[0];
212             if (is<AST::EnumerationDefinition>(type)) {
213                 AST::EnumerationDefinition& enumerationDefinition = downcast<AST::EnumerationDefinition>(type);
214                 auto memberName = dotExpression.fieldName();
215                 if (auto* member = enumerationDefinition.memberByName(memberName)) {
216                     Lexer::Token origin = dotExpression.origin();
217                     auto enumerationMemberLiteral = AST::EnumerationMemberLiteral::wrap(WTFMove(origin), WTFMove(baseName), WTFMove(memberName), enumerationDefinition, *member);
218                     AST::replaceWith<AST::EnumerationMemberLiteral>(dotExpression, WTFMove(enumerationMemberLiteral));
219                     return;
220                 }
221                 setError();
222                 return;
223             }
224         }
225     }
226
227     Visitor::visit(dotExpression);
228 }
229
230 void NameResolver::visit(AST::CallExpression& callExpression)
231 {
232     Visitor::visit(callExpression);
233 }
234
235 void NameResolver::visit(AST::EnumerationMemberLiteral& enumerationMemberLiteral)
236 {
237     if (enumerationMemberLiteral.enumerationMember())
238         return;
239
240     if (auto enumerationTypes = m_nameContext.getTypes(enumerationMemberLiteral.left())) {
241         ASSERT(enumerationTypes->size() == 1);
242         AST::NamedType& type = (*enumerationTypes)[0];
243         if (is<AST::EnumerationDefinition>(type)) {
244             AST::EnumerationDefinition& enumerationDefinition = downcast<AST::EnumerationDefinition>(type);
245             if (auto* member = enumerationDefinition.memberByName(enumerationMemberLiteral.right())) {
246                 enumerationMemberLiteral.setEnumerationMember(enumerationDefinition, *member);
247                 return;
248             }
249         }
250     }
251     
252     setError();
253 }
254
255 void NameResolver::visit(AST::NativeFunctionDeclaration& nativeFunctionDeclaration)
256 {
257     NameContext newNameContext(&m_nameContext);
258     NameResolver newNameResolver(newNameContext);
259     newNameResolver.Visitor::visit(nativeFunctionDeclaration);
260 }
261
262 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198167 Make sure all the names have been resolved.
263
264 bool resolveNamesInTypes(Program& program, NameResolver& nameResolver)
265 {
266     for (auto& typeDefinition : program.typeDefinitions()) {
267         nameResolver.checkErrorAndVisit(typeDefinition);
268         if (nameResolver.error())
269             return false;
270     }
271     for (auto& structureDefinition : program.structureDefinitions()) {
272         nameResolver.checkErrorAndVisit(structureDefinition);
273         if (nameResolver.error())
274             return false;
275     }
276     for (auto& enumerationDefinition : program.enumerationDefinitions()) {
277         nameResolver.checkErrorAndVisit(enumerationDefinition);
278         if (nameResolver.error())
279             return false;
280     }
281     for (auto& nativeTypeDeclaration : program.nativeTypeDeclarations()) {
282         nameResolver.checkErrorAndVisit(nativeTypeDeclaration);
283         if (nameResolver.error())
284             return false;
285     }
286     return true;
287 }
288
289 bool resolveTypeNamesInFunctions(Program& program, NameResolver& nameResolver)
290 {
291     for (auto& functionDefinition : program.functionDefinitions()) {
292         nameResolver.setCurrentFunctionDefinition(&functionDefinition);
293         nameResolver.checkErrorAndVisit(functionDefinition);
294         if (nameResolver.error())
295             return false;
296     }
297     nameResolver.setCurrentFunctionDefinition(nullptr);
298     for (auto& nativeFunctionDeclaration : program.nativeFunctionDeclarations()) {
299         nameResolver.checkErrorAndVisit(nativeFunctionDeclaration);
300         if (nameResolver.error())
301             return false;
302     }
303     return true;
304 }
305
306 } // namespace WHLSL
307
308 } // namespace WebCore
309
310 #endif // ENABLE(WEBGPU)