[WHLSL] Standard library is too big to directly include in WebCore
[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     m_isResolvingCalls = parentResolver.m_isResolvingCalls;
65     setCurrentFunctionDefinition(parentResolver.m_currentFunction);
66 }
67
68 NameResolver::~NameResolver()
69 {
70     if (error() && m_parentNameResolver)
71         m_parentNameResolver->setError();
72 }
73
74 void NameResolver::visit(AST::TypeReference& typeReference)
75 {
76     if (m_isResolvingCalls)
77         return;
78
79     ScopedSetAdder<AST::TypeReference*> adder(m_typeReferences, &typeReference);
80     if (!adder.isNewEntry()) {
81         setError();
82         return;
83     }
84
85     Visitor::visit(typeReference);
86     if (error())
87         return;
88     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?
89         return;
90
91     auto* candidates = m_nameContext.getTypes(typeReference.name());
92     if (candidates == nullptr) {
93         setError();
94         return;
95     }
96     for (auto& candidate : *candidates)
97         Visitor::visit(candidate);
98     if (auto result = resolveTypeOverloadImpl(*candidates, typeReference.typeArguments()))
99         typeReference.setResolvedType(*result);
100     else {
101         setError();
102         return;
103     }
104 }
105
106 void NameResolver::visit(AST::FunctionDefinition& functionDefinition)
107 {
108     NameContext newNameContext(&m_nameContext);
109     NameResolver newNameResolver(*this, newNameContext);
110     checkErrorAndVisit(functionDefinition.type());
111     if (error())
112         return;
113     for (auto& parameter : functionDefinition.parameters())
114         newNameResolver.checkErrorAndVisit(parameter);
115     newNameResolver.checkErrorAndVisit(functionDefinition.block());
116 }
117
118 void NameResolver::visit(AST::Block& block)
119 {
120     NameContext nameContext(&m_nameContext);
121     NameResolver newNameResolver(*this, nameContext);
122     newNameResolver.Visitor::visit(block);
123 }
124
125 void NameResolver::visit(AST::IfStatement& ifStatement)
126 {
127     checkErrorAndVisit(ifStatement.conditional());
128     if (error())
129         return;
130
131     {
132         NameContext nameContext(&m_nameContext);
133         NameResolver newNameResolver(*this, nameContext);
134         newNameResolver.checkErrorAndVisit(ifStatement.body());
135     }
136     if (error())
137         return;
138
139     if (ifStatement.elseBody()) {
140         NameContext nameContext(&m_nameContext);
141         NameResolver newNameResolver(*this, nameContext);
142         newNameResolver.checkErrorAndVisit(*ifStatement.elseBody());
143     }
144 }
145
146 void NameResolver::visit(AST::WhileLoop& whileLoop)
147 {
148     checkErrorAndVisit(whileLoop.conditional());
149     if (error())
150         return;
151
152     NameContext nameContext(&m_nameContext);
153     NameResolver newNameResolver(*this, nameContext);
154     newNameResolver.checkErrorAndVisit(whileLoop.body());
155 }
156
157 void NameResolver::visit(AST::DoWhileLoop& whileLoop)
158 {
159     {
160         NameContext nameContext(&m_nameContext);
161         NameResolver newNameResolver(*this, nameContext);
162         newNameResolver.checkErrorAndVisit(whileLoop.body());
163     }
164
165     checkErrorAndVisit(whileLoop.conditional());
166 }
167
168 void NameResolver::visit(AST::ForLoop& forLoop)
169 {
170     NameContext nameContext(&m_nameContext);
171     NameResolver newNameResolver(*this, nameContext);
172     newNameResolver.Visitor::visit(forLoop);
173 }
174
175 void NameResolver::visit(AST::VariableDeclaration& variableDeclaration)
176 {
177     if (!m_nameContext.add(variableDeclaration)) {
178         setError();
179         return;
180     }
181     Visitor::visit(variableDeclaration);
182 }
183
184 void NameResolver::visit(AST::VariableReference& variableReference)
185 {
186     if (variableReference.variable())
187         return;
188
189     if (auto* variable = m_nameContext.getVariable(variableReference.name()))
190         variableReference.setVariable(*variable);
191     else {
192         setError();
193         return;
194     }
195 }
196
197 void NameResolver::visit(AST::Return& returnStatement)
198 {
199     ASSERT(m_currentFunction);
200     returnStatement.setFunction(m_currentFunction);
201     Visitor::visit(returnStatement);
202 }
203
204 void NameResolver::visit(AST::PropertyAccessExpression& propertyAccessExpression)
205 {
206     if (m_isResolvingCalls) {
207         if (auto* getterFunctions = m_nameContext.getFunctions(propertyAccessExpression.getterFunctionName()))
208             propertyAccessExpression.setPossibleGetterOverloads(*getterFunctions);
209         if (auto* setterFunctions = m_nameContext.getFunctions(propertyAccessExpression.setterFunctionName()))
210             propertyAccessExpression.setPossibleSetterOverloads(*setterFunctions);
211         if (auto* anderFunctions = m_nameContext.getFunctions(propertyAccessExpression.anderFunctionName()))
212             propertyAccessExpression.setPossibleAnderOverloads(*anderFunctions);
213     }
214     Visitor::visit(propertyAccessExpression);
215 }
216
217 void NameResolver::visit(AST::DotExpression& dotExpression)
218 {
219     if (is<AST::VariableReference>(dotExpression.base())) {
220         auto baseName = downcast<AST::VariableReference>(dotExpression.base()).name();
221         if (auto enumerationTypes = m_nameContext.getTypes(baseName)) {
222             ASSERT(enumerationTypes->size() == 1);
223             AST::NamedType& type = (*enumerationTypes)[0];
224             if (is<AST::EnumerationDefinition>(type)) {
225                 AST::EnumerationDefinition& enumerationDefinition = downcast<AST::EnumerationDefinition>(type);
226                 auto memberName = dotExpression.fieldName();
227                 if (auto* member = enumerationDefinition.memberByName(memberName)) {
228                     Lexer::Token origin = dotExpression.origin();
229                     auto enumerationMemberLiteral = AST::EnumerationMemberLiteral::wrap(WTFMove(origin), WTFMove(baseName), WTFMove(memberName), enumerationDefinition, *member);
230                     AST::replaceWith<AST::EnumerationMemberLiteral>(dotExpression, WTFMove(enumerationMemberLiteral));
231                     return;
232                 }
233                 setError();
234                 return;
235             }
236         }
237     }
238
239     Visitor::visit(dotExpression);
240 }
241
242 void NameResolver::visit(AST::CallExpression& callExpression)
243 {
244     if (m_isResolvingCalls) {
245         if (!callExpression.hasOverloads()) {
246             if (auto* functions = m_nameContext.getFunctions(callExpression.name()))
247                 callExpression.setOverloads(*functions);
248             else {
249                 if (auto* types = m_nameContext.getTypes(callExpression.name())) {
250                     if (types->size() == 1) {
251                         if (auto* functions = m_nameContext.getFunctions("operator cast"_str)) {
252                             callExpression.setCastData((*types)[0].get());
253                             callExpression.setOverloads(*functions);
254                         }
255                     }
256                 }
257             }
258         }
259         if (!callExpression.hasOverloads()) {
260             setError();
261             return;
262         }
263     }
264     Visitor::visit(callExpression);
265 }
266
267 void NameResolver::visit(AST::EnumerationMemberLiteral& enumerationMemberLiteral)
268 {
269     if (enumerationMemberLiteral.enumerationMember())
270         return;
271
272     if (auto enumerationTypes = m_nameContext.getTypes(enumerationMemberLiteral.left())) {
273         ASSERT(enumerationTypes->size() == 1);
274         AST::NamedType& type = (*enumerationTypes)[0];
275         if (is<AST::EnumerationDefinition>(type)) {
276             AST::EnumerationDefinition& enumerationDefinition = downcast<AST::EnumerationDefinition>(type);
277             if (auto* member = enumerationDefinition.memberByName(enumerationMemberLiteral.right())) {
278                 enumerationMemberLiteral.setEnumerationMember(enumerationDefinition, *member);
279                 return;
280             }
281         }
282     }
283     
284     setError();
285 }
286
287 void NameResolver::visit(AST::NativeFunctionDeclaration& nativeFunctionDeclaration)
288 {
289     NameContext newNameContext(&m_nameContext);
290     NameResolver newNameResolver(newNameContext);
291     newNameResolver.Visitor::visit(nativeFunctionDeclaration);
292 }
293
294 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198167 Make sure all the names have been resolved.
295
296 bool resolveNamesInTypes(Program& program, NameResolver& nameResolver)
297 {
298     for (auto& typeDefinition : program.typeDefinitions()) {
299         nameResolver.checkErrorAndVisit(typeDefinition);
300         if (nameResolver.error())
301             return false;
302     }
303     for (auto& structureDefinition : program.structureDefinitions()) {
304         nameResolver.checkErrorAndVisit(structureDefinition);
305         if (nameResolver.error())
306             return false;
307     }
308     for (auto& enumerationDefinition : program.enumerationDefinitions()) {
309         nameResolver.checkErrorAndVisit(enumerationDefinition);
310         if (nameResolver.error())
311             return false;
312     }
313     for (auto& nativeTypeDeclaration : program.nativeTypeDeclarations()) {
314         nameResolver.checkErrorAndVisit(nativeTypeDeclaration);
315         if (nameResolver.error())
316             return false;
317     }
318     return true;
319 }
320
321 bool resolveTypeNamesInFunctions(Program& program, NameResolver& nameResolver)
322 {
323     for (auto& functionDefinition : program.functionDefinitions()) {
324         nameResolver.setCurrentFunctionDefinition(&functionDefinition);
325         nameResolver.checkErrorAndVisit(functionDefinition);
326         if (nameResolver.error())
327             return false;
328     }
329     nameResolver.setCurrentFunctionDefinition(nullptr);
330     for (auto& nativeFunctionDeclaration : program.nativeFunctionDeclarations()) {
331         nameResolver.checkErrorAndVisit(nativeFunctionDeclaration);
332         if (nameResolver.error())
333             return false;
334     }
335     return true;
336 }
337
338 bool resolveCallsInFunctions(Program& program, NameResolver& nameResolver)
339 {
340     nameResolver.setIsResolvingCalls(true);
341     for (auto& functionDefinition : program.functionDefinitions()) {
342         nameResolver.setCurrentFunctionDefinition(&functionDefinition);
343         nameResolver.checkErrorAndVisit(functionDefinition);
344         if (nameResolver.error())
345             return false;
346     }
347     nameResolver.setCurrentFunctionDefinition(nullptr);
348     nameResolver.setIsResolvingCalls(false);
349     return true;
350 }
351
352 } // namespace WHLSL
353
354 } // namespace WebCore
355
356 #endif // ENABLE(WEBGPU)