1 /*
2 * Copyright 2020 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 "include/sksl/DSLExpression.h"
9
10 #include "include/sksl/DSLCore.h"
11 #include "include/sksl/DSLVar.h"
12 #include "src/sksl/SkSLCompiler.h"
13 #include "src/sksl/SkSLThreadContext.h"
14 #include "src/sksl/dsl/priv/DSLWriter.h"
15 #include "src/sksl/ir/SkSLBinaryExpression.h"
16 #include "src/sksl/ir/SkSLFieldAccess.h"
17 #include "src/sksl/ir/SkSLFunctionCall.h"
18 #include "src/sksl/ir/SkSLIndexExpression.h"
19 #include "src/sksl/ir/SkSLLiteral.h"
20 #include "src/sksl/ir/SkSLPoison.h"
21 #include "src/sksl/ir/SkSLPostfixExpression.h"
22 #include "src/sksl/ir/SkSLPrefixExpression.h"
23
24 #include "math.h"
25
26 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
27 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
28 #endif
29
30 namespace SkSL {
31
32 namespace dsl {
33
DSLExpression()34 DSLExpression::DSLExpression() {}
35
DSLExpression(DSLExpression && other)36 DSLExpression::DSLExpression(DSLExpression&& other)
37 : fExpression(std::move(other.fExpression)) {}
38
DSLExpression(std::unique_ptr<SkSL::Expression> expression)39 DSLExpression::DSLExpression(std::unique_ptr<SkSL::Expression> expression)
40 : fExpression(std::move(expression)) {
41 SkASSERT(this->hasValue());
42 }
43
DSLExpression(float value,PositionInfo pos)44 DSLExpression::DSLExpression(float value, PositionInfo pos)
45 : fExpression(SkSL::Literal::MakeFloat(ThreadContext::Context(),
46 pos.line(),
47 value)) {
48 if (!isfinite(value)) {
49 if (isinf(value)) {
50 ThreadContext::ReportError("floating point value is infinite");
51 } else if (isnan(value)) {
52 ThreadContext::ReportError("floating point value is NaN");
53 }
54 }
55 }
56
DSLExpression(int value,PositionInfo pos)57 DSLExpression::DSLExpression(int value, PositionInfo pos)
58 : fExpression(SkSL::Literal::MakeInt(ThreadContext::Context(),
59 pos.line(),
60 value)) {}
61
DSLExpression(int64_t value,PositionInfo pos)62 DSLExpression::DSLExpression(int64_t value, PositionInfo pos)
63 : fExpression(SkSL::Literal::MakeInt(ThreadContext::Context(),
64 pos.line(),
65 value)) {}
66
DSLExpression(unsigned int value,PositionInfo pos)67 DSLExpression::DSLExpression(unsigned int value, PositionInfo pos)
68 : fExpression(SkSL::Literal::MakeInt(ThreadContext::Context(),
69 pos.line(),
70 value)) {}
71
DSLExpression(bool value,PositionInfo pos)72 DSLExpression::DSLExpression(bool value, PositionInfo pos)
73 : fExpression(SkSL::Literal::MakeBool(ThreadContext::Context(),
74 pos.line(),
75 value)) {}
76
DSLExpression(DSLVarBase & var,PositionInfo pos)77 DSLExpression::DSLExpression(DSLVarBase& var, PositionInfo pos) {
78 fExpression = std::make_unique<SkSL::VariableReference>(pos.line(), DSLWriter::Var(var),
79 SkSL::VariableReference::RefKind::kRead);
80 }
81
DSLExpression(DSLVarBase && var,PositionInfo pos)82 DSLExpression::DSLExpression(DSLVarBase&& var, PositionInfo pos)
83 : DSLExpression(var) {}
84
DSLExpression(DSLPossibleExpression expr,PositionInfo pos)85 DSLExpression::DSLExpression(DSLPossibleExpression expr, PositionInfo pos) {
86 ThreadContext::ReportErrors(pos);
87 if (expr.valid()) {
88 fExpression = std::move(expr.fExpression);
89 } else {
90 fExpression = SkSL::Poison::Make(pos.line(), ThreadContext::Context());
91 }
92 }
93
Poison(PositionInfo pos)94 DSLExpression DSLExpression::Poison(PositionInfo pos) {
95 return DSLExpression(SkSL::Poison::Make(pos.line(), ThreadContext::Context()));
96 }
97
~DSLExpression()98 DSLExpression::~DSLExpression() {
99 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
100 if (fExpression && ThreadContext::InFragmentProcessor()) {
101 ThreadContext::CurrentEmitArgs()->fFragBuilder->codeAppend(
102 DSLStatement(this->release()).release());
103 return;
104 }
105 #endif
106 SkASSERTF(!fExpression || !ThreadContext::Settings().fAssertDSLObjectsReleased,
107 "Expression destroyed without being incorporated into program (see "
108 "ProgramSettings::fAssertDSLObjectsReleased)");
109 }
110
isValid() const111 bool DSLExpression::isValid() const {
112 return this->hasValue() && !fExpression->is<SkSL::Poison>();
113 }
114
swap(DSLExpression & other)115 void DSLExpression::swap(DSLExpression& other) {
116 std::swap(fExpression, other.fExpression);
117 }
118
release()119 std::unique_ptr<SkSL::Expression> DSLExpression::release() {
120 SkASSERT(this->hasValue());
121 return std::move(fExpression);
122 }
123
releaseIfPossible()124 std::unique_ptr<SkSL::Expression> DSLExpression::releaseIfPossible() {
125 return std::move(fExpression);
126 }
127
type()128 DSLType DSLExpression::type() {
129 if (!this->hasValue()) {
130 return kVoid_Type;
131 }
132 return &fExpression->type();
133 }
134
x(PositionInfo pos)135 DSLExpression DSLExpression::x(PositionInfo pos) {
136 return Swizzle(std::move(*this), X, pos);
137 }
138
y(PositionInfo pos)139 DSLExpression DSLExpression::y(PositionInfo pos) {
140 return Swizzle(std::move(*this), Y, pos);
141 }
142
z(PositionInfo pos)143 DSLExpression DSLExpression::z(PositionInfo pos) {
144 return Swizzle(std::move(*this), Z, pos);
145 }
146
w(PositionInfo pos)147 DSLExpression DSLExpression::w(PositionInfo pos) {
148 return Swizzle(std::move(*this), W, pos);
149 }
150
r(PositionInfo pos)151 DSLExpression DSLExpression::r(PositionInfo pos) {
152 return Swizzle(std::move(*this), R, pos);
153 }
154
g(PositionInfo pos)155 DSLExpression DSLExpression::g(PositionInfo pos) {
156 return Swizzle(std::move(*this), G, pos);
157 }
158
b(PositionInfo pos)159 DSLExpression DSLExpression::b(PositionInfo pos) {
160 return Swizzle(std::move(*this), B, pos);
161 }
162
a(PositionInfo pos)163 DSLExpression DSLExpression::a(PositionInfo pos) {
164 return Swizzle(std::move(*this), A, pos);
165 }
166
field(skstd::string_view name,PositionInfo pos)167 DSLExpression DSLExpression::field(skstd::string_view name, PositionInfo pos) {
168 return DSLExpression(FieldAccess::Convert(ThreadContext::Context(),
169 *ThreadContext::SymbolTable(), this->release(), name), pos);
170 }
171
operator =(DSLExpression right)172 DSLPossibleExpression DSLExpression::operator=(DSLExpression right) {
173 return BinaryExpression::Convert(ThreadContext::Context(), this->release(),
174 SkSL::Token::Kind::TK_EQ, right.release());
175 }
176
operator [](DSLExpression right)177 DSLPossibleExpression DSLExpression::operator[](DSLExpression right) {
178 return IndexExpression::Convert(ThreadContext::Context(), *ThreadContext::SymbolTable(),
179 this->release(), right.release());
180 }
181
operator ()(SkTArray<DSLWrapper<DSLExpression>> args,PositionInfo pos)182 DSLPossibleExpression DSLExpression::operator()(SkTArray<DSLWrapper<DSLExpression>> args,
183 PositionInfo pos) {
184 ExpressionArray converted;
185 converted.reserve_back(args.count());
186 for (DSLWrapper<DSLExpression>& arg : args) {
187 converted.push_back(arg->release());
188 }
189 return (*this)(std::move(converted), pos);
190 }
191
operator ()(ExpressionArray args,PositionInfo pos)192 DSLPossibleExpression DSLExpression::operator()(ExpressionArray args, PositionInfo pos) {
193 return SkSL::FunctionCall::Convert(ThreadContext::Context(), pos.line(), this->release(),
194 std::move(args));
195 }
196
197 #define OP(op, token) \
198 DSLPossibleExpression operator op(DSLExpression left, DSLExpression right) { \
199 return BinaryExpression::Convert(ThreadContext::Context(), left.release(), \
200 SkSL::Token::Kind::token, right.release()); \
201 }
202
203 #define PREFIXOP(op, token) \
204 DSLPossibleExpression operator op(DSLExpression expr) { \
205 return PrefixExpression::Convert(ThreadContext::Context(), SkSL::Token::Kind::token, \
206 expr.release()); \
207 }
208
209 #define POSTFIXOP(op, token) \
210 DSLPossibleExpression operator op(DSLExpression expr, int) { \
211 return PostfixExpression::Convert(ThreadContext::Context(), expr.release(), \
212 SkSL::Token::Kind::token); \
213 }
214
215 OP(+, TK_PLUS)
216 OP(+=, TK_PLUSEQ)
217 OP(-, TK_MINUS)
218 OP(-=, TK_MINUSEQ)
219 OP(*, TK_STAR)
220 OP(*=, TK_STAREQ)
221 OP(/, TK_SLASH)
222 OP(/=, TK_SLASHEQ)
223 OP(%, TK_PERCENT)
224 OP(%=, TK_PERCENTEQ)
225 OP(<<, TK_SHL)
226 OP(<<=, TK_SHLEQ)
227 OP(>>, TK_SHR)
228 OP(>>=, TK_SHREQ)
229 OP(&&, TK_LOGICALAND)
230 OP(||, TK_LOGICALOR)
231 OP(&, TK_BITWISEAND)
232 OP(&=, TK_BITWISEANDEQ)
233 OP(|, TK_BITWISEOR)
234 OP(|=, TK_BITWISEOREQ)
235 OP(^, TK_BITWISEXOR)
236 OP(^=, TK_BITWISEXOREQ)
LogicalXor(DSLExpression left,DSLExpression right)237 DSLPossibleExpression LogicalXor(DSLExpression left, DSLExpression right) {
238 return BinaryExpression::Convert(ThreadContext::Context(), left.release(),
239 SkSL::Token::Kind::TK_LOGICALXOR, right.release());
240 }
241 OP(==, TK_EQEQ)
242 OP(!=, TK_NEQ)
243 OP(>, TK_GT)
244 OP(<, TK_LT)
245 OP(>=, TK_GTEQ)
246 OP(<=, TK_LTEQ)
247
248 PREFIXOP(+, TK_PLUS)
249 PREFIXOP(-, TK_MINUS)
250 PREFIXOP(!, TK_LOGICALNOT)
251 PREFIXOP(~, TK_BITWISENOT)
252 PREFIXOP(++, TK_PLUSPLUS)
253 POSTFIXOP(++, TK_PLUSPLUS)
254 PREFIXOP(--, TK_MINUSMINUS)
255 POSTFIXOP(--, TK_MINUSMINUS)
256
operator ,(DSLExpression left,DSLExpression right)257 DSLPossibleExpression operator,(DSLExpression left, DSLExpression right) {
258 return BinaryExpression::Convert(ThreadContext::Context(), left.release(),
259 SkSL::Token::Kind::TK_COMMA, right.release());
260 }
261
operator ,(DSLPossibleExpression left,DSLExpression right)262 DSLPossibleExpression operator,(DSLPossibleExpression left, DSLExpression right) {
263 return BinaryExpression::Convert(ThreadContext::Context(),
264 DSLExpression(std::move(left)).release(), SkSL::Token::Kind::TK_COMMA, right.release());
265 }
266
operator ,(DSLExpression left,DSLPossibleExpression right)267 DSLPossibleExpression operator,(DSLExpression left, DSLPossibleExpression right) {
268 return BinaryExpression::Convert(ThreadContext::Context(), left.release(),
269 SkSL::Token::Kind::TK_COMMA, DSLExpression(std::move(right)).release());
270 }
271
operator ,(DSLPossibleExpression left,DSLPossibleExpression right)272 DSLPossibleExpression operator,(DSLPossibleExpression left, DSLPossibleExpression right) {
273 return BinaryExpression::Convert(ThreadContext::Context(),
274 DSLExpression(std::move(left)).release(), SkSL::Token::Kind::TK_COMMA,
275 DSLExpression(std::move(right)).release());
276 }
277
DSLPossibleExpression(std::unique_ptr<SkSL::Expression> expr)278 DSLPossibleExpression::DSLPossibleExpression(std::unique_ptr<SkSL::Expression> expr)
279 : fExpression(std::move(expr)) {}
280
DSLPossibleExpression(DSLPossibleExpression && other)281 DSLPossibleExpression::DSLPossibleExpression(DSLPossibleExpression&& other)
282 : fExpression(std::move(other.fExpression)) {}
283
~DSLPossibleExpression()284 DSLPossibleExpression::~DSLPossibleExpression() {
285 if (fExpression) {
286 // this handles incorporating the expression into the output tree
287 DSLExpression(std::move(fExpression));
288 }
289 }
290
reportErrors(PositionInfo pos)291 void DSLPossibleExpression::reportErrors(PositionInfo pos) {
292 SkASSERT(!this->valid());
293 ThreadContext::ReportErrors(pos);
294 }
295
type()296 DSLType DSLPossibleExpression::type() {
297 if (!this->valid()) {
298 return kVoid_Type;
299 }
300 return &fExpression->type();
301 }
302
x(PositionInfo pos)303 DSLExpression DSLPossibleExpression::x(PositionInfo pos) {
304 return DSLExpression(this->release()).x(pos);
305 }
306
y(PositionInfo pos)307 DSLExpression DSLPossibleExpression::y(PositionInfo pos) {
308 return DSLExpression(this->release()).y(pos);
309 }
310
z(PositionInfo pos)311 DSLExpression DSLPossibleExpression::z(PositionInfo pos) {
312 return DSLExpression(this->release()).z(pos);
313 }
314
w(PositionInfo pos)315 DSLExpression DSLPossibleExpression::w(PositionInfo pos) {
316 return DSLExpression(this->release()).w(pos);
317 }
318
r(PositionInfo pos)319 DSLExpression DSLPossibleExpression::r(PositionInfo pos) {
320 return DSLExpression(this->release()).r(pos);
321 }
322
g(PositionInfo pos)323 DSLExpression DSLPossibleExpression::g(PositionInfo pos) {
324 return DSLExpression(this->release()).g(pos);
325 }
326
b(PositionInfo pos)327 DSLExpression DSLPossibleExpression::b(PositionInfo pos) {
328 return DSLExpression(this->release()).b(pos);
329 }
330
a(PositionInfo pos)331 DSLExpression DSLPossibleExpression::a(PositionInfo pos) {
332 return DSLExpression(this->release()).a(pos);
333 }
334
field(skstd::string_view name,PositionInfo pos)335 DSLExpression DSLPossibleExpression::field(skstd::string_view name, PositionInfo pos) {
336 return DSLExpression(this->release()).field(name, pos);
337 }
338
operator =(DSLExpression expr)339 DSLPossibleExpression DSLPossibleExpression::operator=(DSLExpression expr) {
340 return DSLExpression(this->release()) = std::move(expr);
341 }
342
operator =(int expr)343 DSLPossibleExpression DSLPossibleExpression::operator=(int expr) {
344 return this->operator=(DSLExpression(expr));
345 }
346
operator =(float expr)347 DSLPossibleExpression DSLPossibleExpression::operator=(float expr) {
348 return this->operator=(DSLExpression(expr));
349 }
350
operator =(double expr)351 DSLPossibleExpression DSLPossibleExpression::operator=(double expr) {
352 return this->operator=(DSLExpression(expr));
353 }
354
operator [](DSLExpression index)355 DSLPossibleExpression DSLPossibleExpression::operator[](DSLExpression index) {
356 return DSLExpression(this->release())[std::move(index)];
357 }
358
operator ()(SkTArray<DSLWrapper<DSLExpression>> args,PositionInfo pos)359 DSLPossibleExpression DSLPossibleExpression::operator()(SkTArray<DSLWrapper<DSLExpression>> args,
360 PositionInfo pos) {
361 return DSLExpression(this->release())(std::move(args), pos);
362 }
363
operator ()(ExpressionArray args,PositionInfo pos)364 DSLPossibleExpression DSLPossibleExpression::operator()(ExpressionArray args, PositionInfo pos) {
365 return DSLExpression(this->release())(std::move(args), pos);
366 }
367
operator ++()368 DSLPossibleExpression DSLPossibleExpression::operator++() {
369 return ++DSLExpression(this->release());
370 }
371
operator ++(int)372 DSLPossibleExpression DSLPossibleExpression::operator++(int) {
373 return DSLExpression(this->release())++;
374 }
375
operator --()376 DSLPossibleExpression DSLPossibleExpression::operator--() {
377 return --DSLExpression(this->release());
378 }
379
operator --(int)380 DSLPossibleExpression DSLPossibleExpression::operator--(int) {
381 return DSLExpression(this->release())--;
382 }
383
release(PositionInfo pos)384 std::unique_ptr<SkSL::Expression> DSLPossibleExpression::release(PositionInfo pos) {
385 return DSLExpression(std::move(*this), pos).release();
386 }
387
388 } // namespace dsl
389
390 } // namespace SkSL
391