blob: 08299bbac58bb96a2eeb830d5ea9727872341971 [file] [log] [blame]
Ethan Nicholasd4efe682019-08-29 16:10:13 -04001/*
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
27namespace SkSL {
28
29SectionAndParameterHelper::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
73bool 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
82bool 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
89bool 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::kAppendStage_Kind:
144 case Expression::kBoolLiteral_Kind:
145 case Expression::kDefined_Kind:
146 case Expression::kExternalFunctionCall_Kind:
147 case Expression::kExternalValue_Kind:
148 case Expression::kFloatLiteral_Kind:
149 case Expression::kFunctionReference_Kind:
150 case Expression::kIntLiteral_Kind:
151 case Expression::kNullLiteral_Kind:
152 case Expression::kSetting_Kind:
153 case Expression::kTypeReference_Kind:
154 return false;
155 }
156 SkASSERT(false);
157 return false;
158}
159
160bool SectionAndParameterHelper::hasCoordOverrides(const Statement& s, const Variable& fp) {
161 switch (s.fKind) {
162 case Statement::kBlock_Kind: {
163 for (const auto& child : ((const Block&) s).fStatements) {
164 if (this->hasCoordOverrides(*child, fp)) {
165 return true;
166 }
167 }
168 return false;
169 }
170 case Statement::kVarDeclaration_Kind: {
171 const VarDeclaration& var = (const VarDeclaration&) s;
172 if (var.fValue) {
173 return hasCoordOverrides(*var.fValue, fp);
174 }
175 return false;
176 }
177 case Statement::kVarDeclarations_Kind: {
178 const VarDeclarations& decls = *((const VarDeclarationsStatement&) s).fDeclaration;
179 for (const auto& stmt : decls.fVars) {
180 if (this->hasCoordOverrides(*stmt, fp)) {
181 return true;
182 }
183 }
184 return false;
185 }
186 case Statement::kExpression_Kind:
187 return this->hasCoordOverrides(*((const ExpressionStatement&) s).fExpression, fp);
188 case Statement::kReturn_Kind: {
189 const ReturnStatement& r = (const ReturnStatement&) s;
190 if (r.fExpression) {
191 return this->hasCoordOverrides(*r.fExpression, fp);
192 }
193 return false;
194 }
195 case Statement::kIf_Kind: {
196 const IfStatement& i = (const IfStatement&) s;
197 return this->hasCoordOverrides(*i.fTest, fp) ||
198 this->hasCoordOverrides(*i.fIfTrue, fp) ||
199 (i.fIfFalse && this->hasCoordOverrides(*i.fIfFalse, fp));
200 }
201 case Statement::kFor_Kind: {
202 const ForStatement& f = (const ForStatement&) s;
203 return this->hasCoordOverrides(*f.fInitializer, fp) ||
204 this->hasCoordOverrides(*f.fTest, fp) ||
205 this->hasCoordOverrides(*f.fNext, fp) ||
206 this->hasCoordOverrides(*f.fStatement, fp);
207 }
208 case Statement::kWhile_Kind: {
209 const WhileStatement& w = (const WhileStatement&) s;
210 return this->hasCoordOverrides(*w.fTest, fp) ||
211 this->hasCoordOverrides(*w.fStatement, fp);
212 }
213 case Statement::kDo_Kind: {
214 const DoStatement& d = (const DoStatement&) s;
215 return this->hasCoordOverrides(*d.fTest, fp) ||
216 this->hasCoordOverrides(*d.fStatement, fp);
217 }
218 case Statement::kSwitch_Kind: {
219 const SwitchStatement& sw = (const SwitchStatement&) s;
220 for (const auto& c : sw.fCases) {
221 for (const auto& st : c->fStatements) {
222 if (this->hasCoordOverrides(*st, fp)) {
223 return true;
224 }
225 }
226 }
227 return this->hasCoordOverrides(*sw.fValue, fp);
228 }
229 case Statement::kBreak_Kind:
230 case Statement::kContinue_Kind:
231 case Statement::kDiscard_Kind:
232 case Statement::kGroup_Kind:
233 case Statement::kNop_Kind:
234 return false;
235 }
236 SkASSERT(false);
237 return false;
238}
239
240}