• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 Google LLC.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/sksl/SkSLSectionAndParameterHelper.h"
9 #include "src/sksl/ir/SkSLBinaryExpression.h"
10 #include "src/sksl/ir/SkSLConstructor.h"
11 #include "src/sksl/ir/SkSLDoStatement.h"
12 #include "src/sksl/ir/SkSLExpressionStatement.h"
13 #include "src/sksl/ir/SkSLFieldAccess.h"
14 #include "src/sksl/ir/SkSLForStatement.h"
15 #include "src/sksl/ir/SkSLFunctionCall.h"
16 #include "src/sksl/ir/SkSLIfStatement.h"
17 #include "src/sksl/ir/SkSLIndexExpression.h"
18 #include "src/sksl/ir/SkSLPostfixExpression.h"
19 #include "src/sksl/ir/SkSLPrefixExpression.h"
20 #include "src/sksl/ir/SkSLReturnStatement.h"
21 #include "src/sksl/ir/SkSLSwitchStatement.h"
22 #include "src/sksl/ir/SkSLSwizzle.h"
23 #include "src/sksl/ir/SkSLTernaryExpression.h"
24 #include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
25 #include "src/sksl/ir/SkSLWhileStatement.h"
26 
27 namespace SkSL {
28 
SectionAndParameterHelper(const Program * program,ErrorReporter & errors)29 SectionAndParameterHelper::SectionAndParameterHelper(const Program* program, ErrorReporter& errors)
30     : fProgram(*program) {
31     for (const auto& p : fProgram) {
32         switch (p.fKind) {
33             case ProgramElement::kVar_Kind: {
34                 const VarDeclarations& decls = (const VarDeclarations&) p;
35                 for (const auto& raw : decls.fVars) {
36                     const VarDeclaration& decl = (VarDeclaration&) *raw;
37                     if (IsParameter(*decl.fVar)) {
38                         fParameters.push_back(decl.fVar);
39                     }
40                 }
41                 break;
42             }
43             case ProgramElement::kSection_Kind: {
44                 const Section& s = (const Section&) p;
45                 if (IsSupportedSection(s.fName.c_str())) {
46                     if (SectionRequiresArgument(s.fName.c_str()) && !s.fArgument.size()) {
47                         errors.error(s.fOffset,
48                                      ("section '@" + s.fName +
49                                       "' requires one parameter").c_str());
50                     }
51                     if (!SectionAcceptsArgument(s.fName.c_str()) && s.fArgument.size()) {
52                         errors.error(s.fOffset,
53                                      ("section '@" + s.fName + "' has no parameters").c_str());
54                     }
55                 } else {
56                     errors.error(s.fOffset,
57                                  ("unsupported section '@" + s.fName + "'").c_str());
58                 }
59                 if (!SectionPermitsDuplicates(s.fName.c_str()) &&
60                         fSections.find(s.fName) != fSections.end()) {
61                     errors.error(s.fOffset,
62                                  ("duplicate section '@" + s.fName + "'").c_str());
63                 }
64                 fSections[s.fName].push_back(&s);
65                 break;
66             }
67             default:
68                 break;
69         }
70     }
71 }
72 
hasCoordOverrides(const Variable & fp)73 bool SectionAndParameterHelper::hasCoordOverrides(const Variable& fp) {
74     for (const auto& pe : fProgram) {
75         if (this->hasCoordOverrides(pe, fp)) {
76             return true;
77         }
78     }
79     return false;
80 }
81 
hasCoordOverrides(const ProgramElement & pe,const Variable & fp)82 bool SectionAndParameterHelper::hasCoordOverrides(const ProgramElement& pe, const Variable& fp) {
83     if (pe.fKind == ProgramElement::kFunction_Kind) {
84         return this->hasCoordOverrides(*((const FunctionDefinition&) pe).fBody, fp);
85     }
86     return false;
87 }
88 
hasCoordOverrides(const Expression & e,const Variable & fp)89 bool SectionAndParameterHelper::hasCoordOverrides(const Expression& e, const Variable& fp) {
90     switch (e.fKind) {
91         case Expression::kFunctionCall_Kind: {
92             const FunctionCall& fc = (const FunctionCall&) e;
93             const FunctionDeclaration& f = fc.fFunction;
94             if (f.fBuiltin && f.fName == "sample" && fc.fArguments.size() >= 2 &&
95                 fc.fArguments.back()->fType == *fProgram.fContext->fFloat2_Type &&
96                 fc.fArguments[0]->fKind == Expression::kVariableReference_Kind &&
97                 &((VariableReference&) *fc.fArguments[0]).fVariable == &fp) {
98                 return true;
99             }
100             for (const auto& e : fc.fArguments) {
101                 if (this->hasCoordOverrides(*e, fp)) {
102                     return true;
103                 }
104             }
105             return false;
106         }
107         case Expression::kConstructor_Kind: {
108             const Constructor& c = (const Constructor&) e;
109             for (const auto& e : c.fArguments) {
110                 if (this->hasCoordOverrides(*e, fp)) {
111                     return true;
112                 }
113             }
114             return false;
115         }
116         case Expression::kFieldAccess_Kind: {
117             return this->hasCoordOverrides(*((const FieldAccess&) e).fBase, fp);
118         }
119         case Expression::kSwizzle_Kind:
120             return this->hasCoordOverrides(*((const Swizzle&) e).fBase, fp);
121         case Expression::kBinary_Kind: {
122             const BinaryExpression& b = (const BinaryExpression&) e;
123             return this->hasCoordOverrides(*b.fLeft, fp) ||
124                    this->hasCoordOverrides(*b.fRight, fp);
125         }
126         case Expression::kIndex_Kind: {
127             const IndexExpression& idx = (const IndexExpression&) e;
128             return this->hasCoordOverrides(*idx.fBase, fp) ||
129                    this->hasCoordOverrides(*idx.fIndex, fp);
130         }
131         case Expression::kPrefix_Kind:
132             return this->hasCoordOverrides(*((const PrefixExpression&) e).fOperand, fp);
133         case Expression::kPostfix_Kind:
134             return this->hasCoordOverrides(*((const PostfixExpression&) e).fOperand, fp);
135         case Expression::kTernary_Kind: {
136             const TernaryExpression& t = (const TernaryExpression&) e;
137             return this->hasCoordOverrides(*t.fTest, fp) ||
138                    this->hasCoordOverrides(*t.fIfTrue, fp) ||
139                    this->hasCoordOverrides(*t.fIfFalse, fp);
140         }
141         case Expression::kVariableReference_Kind:
142             return false;
143         case Expression::kBoolLiteral_Kind:
144         case Expression::kDefined_Kind:
145         case Expression::kExternalFunctionCall_Kind:
146         case Expression::kExternalValue_Kind:
147         case Expression::kFloatLiteral_Kind:
148         case Expression::kFunctionReference_Kind:
149         case Expression::kIntLiteral_Kind:
150         case Expression::kNullLiteral_Kind:
151         case Expression::kSetting_Kind:
152         case Expression::kTypeReference_Kind:
153             return false;
154     }
155     SkASSERT(false);
156     return false;
157 }
158 
hasCoordOverrides(const Statement & s,const Variable & fp)159 bool SectionAndParameterHelper::hasCoordOverrides(const Statement& s, const Variable& fp) {
160     switch (s.fKind) {
161         case Statement::kBlock_Kind: {
162             for (const auto& child : ((const Block&) s).fStatements) {
163                 if (this->hasCoordOverrides(*child, fp)) {
164                     return true;
165                 }
166             }
167             return false;
168         }
169         case Statement::kVarDeclaration_Kind: {
170             const VarDeclaration& var = (const VarDeclaration&) s;
171             if (var.fValue) {
172                 return hasCoordOverrides(*var.fValue, fp);
173             }
174             return false;
175         }
176         case Statement::kVarDeclarations_Kind: {
177             const VarDeclarations& decls = *((const VarDeclarationsStatement&) s).fDeclaration;
178             for (const auto& stmt : decls.fVars) {
179                 if (this->hasCoordOverrides(*stmt, fp)) {
180                     return true;
181                 }
182             }
183             return false;
184         }
185         case Statement::kExpression_Kind:
186             return this->hasCoordOverrides(*((const ExpressionStatement&) s).fExpression, fp);
187         case Statement::kReturn_Kind: {
188             const ReturnStatement& r = (const ReturnStatement&) s;
189             if (r.fExpression) {
190                 return this->hasCoordOverrides(*r.fExpression, fp);
191             }
192             return false;
193         }
194         case Statement::kIf_Kind: {
195             const IfStatement& i = (const IfStatement&) s;
196             return this->hasCoordOverrides(*i.fTest, fp) ||
197                    this->hasCoordOverrides(*i.fIfTrue, fp) ||
198                    (i.fIfFalse && this->hasCoordOverrides(*i.fIfFalse, fp));
199         }
200         case Statement::kFor_Kind: {
201             const ForStatement& f = (const ForStatement&) s;
202             return this->hasCoordOverrides(*f.fInitializer, fp) ||
203                    this->hasCoordOverrides(*f.fTest, fp) ||
204                    this->hasCoordOverrides(*f.fNext, fp) ||
205                    this->hasCoordOverrides(*f.fStatement, fp);
206         }
207         case Statement::kWhile_Kind: {
208             const WhileStatement& w = (const WhileStatement&) s;
209             return this->hasCoordOverrides(*w.fTest, fp) ||
210                    this->hasCoordOverrides(*w.fStatement, fp);
211         }
212         case Statement::kDo_Kind: {
213             const DoStatement& d = (const DoStatement&) s;
214             return this->hasCoordOverrides(*d.fTest, fp) ||
215                    this->hasCoordOverrides(*d.fStatement, fp);
216         }
217         case Statement::kSwitch_Kind: {
218             const SwitchStatement& sw = (const SwitchStatement&) s;
219             for (const auto& c : sw.fCases) {
220                 for (const auto& st : c->fStatements) {
221                     if (this->hasCoordOverrides(*st, fp)) {
222                         return true;
223                     }
224                 }
225             }
226             return this->hasCoordOverrides(*sw.fValue, fp);
227         }
228         case Statement::kBreak_Kind:
229         case Statement::kContinue_Kind:
230         case Statement::kDiscard_Kind:
231         case Statement::kGroup_Kind:
232         case Statement::kNop_Kind:
233             return false;
234     }
235     SkASSERT(false);
236     return false;
237 }
238 
239 }
240