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/DSLCore.h"
9 
10 #include "include/private/SkSLDefines.h"
11 #include "src/sksl/SkSLCompiler.h"
12 #include "src/sksl/SkSLIRGenerator.h"
13 #include "src/sksl/dsl/priv/DSLWriter.h"
14 #include "src/sksl/ir/SkSLBreakStatement.h"
15 #include "src/sksl/ir/SkSLContinueStatement.h"
16 #include "src/sksl/ir/SkSLDiscardStatement.h"
17 #include "src/sksl/ir/SkSLDoStatement.h"
18 #include "src/sksl/ir/SkSLForStatement.h"
19 #include "src/sksl/ir/SkSLIfStatement.h"
20 #include "src/sksl/ir/SkSLReturnStatement.h"
21 #include "src/sksl/ir/SkSLSwizzle.h"
22 #include "src/sksl/ir/SkSLTernaryExpression.h"
23 
24 namespace SkSL {
25 
26 namespace dsl {
27 
Start(SkSL::Compiler * compiler,ProgramKind kind,int flags)28 void Start(SkSL::Compiler* compiler, ProgramKind kind, int flags) {
29     DSLWriter::SetInstance(std::make_unique<DSLWriter>(compiler, kind, flags));
30 }
31 
End()32 void End() {
33     SkASSERTF(!DSLWriter::InFragmentProcessor(),
34               "more calls to StartFragmentProcessor than to EndFragmentProcessor");
35     DSLWriter::SetInstance(nullptr);
36 }
37 
SetErrorHandler(ErrorHandler * errorHandler)38 void SetErrorHandler(ErrorHandler* errorHandler) {
39     DSLWriter::SetErrorHandler(errorHandler);
40 }
41 
42 class DSLCore {
43 public:
sk_FragColor()44     static DSLVar sk_FragColor() {
45         return DSLVar("sk_FragColor");
46     }
47 
sk_FragCoord()48     static DSLVar sk_FragCoord() {
49         return DSLVar("sk_FragCoord");
50     }
51 
52     template <typename... Args>
Call(const char * name,Args...args)53     static DSLPossibleExpression Call(const char* name, Args... args) {
54         SkSL::IRGenerator& ir = DSLWriter::IRGenerator();
55         SkSL::ExpressionArray argArray;
56         argArray.reserve_back(sizeof...(args));
57 
58         // in C++17, we could just do:
59         // (argArray.push_back(args.release()), ...);
60         int unused[] = {0, (static_cast<void>(argArray.push_back(args.release())), 0)...};
61         static_cast<void>(unused);
62 
63         return ir.call(/*offset=*/-1, ir.convertIdentifier(-1, name), std::move(argArray));
64     }
65 
Break()66     static DSLStatement Break() {
67         return SkSL::BreakStatement::Make(/*offset=*/-1);
68     }
69 
Continue()70     static DSLStatement Continue() {
71         return SkSL::ContinueStatement::Make(/*offset=*/-1);
72     }
73 
Declare(DSLVar & var,PositionInfo pos)74     static DSLStatement Declare(DSLVar& var, PositionInfo pos) {
75         if (var.fDeclared) {
76             DSLWriter::ReportError("error: variable has already been declared\n", &pos);
77         }
78         if (var.fStorage == SkSL::Variable::Storage::kGlobal) {
79             DSLWriter::ReportError("error: this variable must be declared with DeclareGlobal\n",
80                                    &pos);
81         }
82         var.fDeclared = true;
83         return DSLWriter::Declaration(var);
84     }
85 
DeclareGlobal(DSLVar & var,PositionInfo pos)86     static void DeclareGlobal(DSLVar& var, PositionInfo pos) {
87         if (var.fDeclared) {
88             DSLWriter::ReportError("error: variable has already been declared\n", &pos);
89         }
90         var.fDeclared = true;
91         var.fStorage = SkSL::Variable::Storage::kGlobal;
92         std::unique_ptr<SkSL::Statement> stmt = DSLWriter::Declaration(var);
93         if (stmt) {
94             DSLWriter::ProgramElements().push_back(std::make_unique<SkSL::GlobalVarDeclaration>(
95                     std::move(stmt)));
96         }
97     }
98 
Discard()99     static DSLStatement Discard() {
100         return SkSL::DiscardStatement::Make(/*offset=*/-1);
101     }
102 
Do(DSLStatement stmt,DSLExpression test)103     static DSLPossibleStatement Do(DSLStatement stmt, DSLExpression test) {
104         return DoStatement::Convert(DSLWriter::Context(), stmt.release(), test.release());
105     }
106 
For(DSLStatement initializer,DSLExpression test,DSLExpression next,DSLStatement stmt,PositionInfo pos)107     static DSLPossibleStatement For(DSLStatement initializer, DSLExpression test,
108                                     DSLExpression next, DSLStatement stmt, PositionInfo pos) {
109         return ForStatement::Convert(DSLWriter::Context(), /*offset=*/-1, initializer.release(),
110                                      test.release(), next.release(), stmt.release(),
111                                      DSLWriter::SymbolTable());
112     }
113 
If(DSLExpression test,DSLStatement ifTrue,DSLStatement ifFalse,bool isStatic)114     static DSLPossibleStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse,
115                                    bool isStatic) {
116         return IfStatement::Convert(DSLWriter::Context(), /*offset=*/-1, isStatic, test.release(),
117                                     ifTrue.release(), ifFalse.release());
118     }
119 
Return(DSLExpression value,PositionInfo pos)120     static DSLPossibleStatement Return(DSLExpression value, PositionInfo pos) {
121         // Note that because Return is called before the function in which it resides exists, at
122         // this point we do not know the function's return type. We therefore do not check for
123         // errors, or coerce the value to the correct type, until the return statement is actually
124         // added to a function. (This is done in IRGenerator::finalizeFunction.)
125         return SkSL::ReturnStatement::Make(/*offset=*/-1, value.release());
126     }
127 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,PositionInfo pos)128     static DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a,
129                                  PositionInfo pos) {
130         return DSLExpression(Swizzle::Convert(DSLWriter::Context(), base.release(),
131                                               ComponentArray{a}),
132                              pos);
133     }
134 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,PositionInfo pos)135     static DSLExpression Swizzle(DSLExpression base,
136                                  SkSL::SwizzleComponent::Type a,
137                                  SkSL::SwizzleComponent::Type b,
138                                  PositionInfo pos) {
139         return DSLExpression(Swizzle::Convert(DSLWriter::Context(), base.release(),
140                                               ComponentArray{a, b}),
141                              pos);
142     }
143 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,SkSL::SwizzleComponent::Type c,PositionInfo pos)144     static DSLExpression Swizzle(DSLExpression base,
145                                  SkSL::SwizzleComponent::Type a,
146                                  SkSL::SwizzleComponent::Type b,
147                                  SkSL::SwizzleComponent::Type c,
148                                  PositionInfo pos) {
149         return DSLExpression(Swizzle::Convert(DSLWriter::Context(), base.release(),
150                                               ComponentArray{a, b, c}),
151                              pos);
152     }
153 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,SkSL::SwizzleComponent::Type c,SkSL::SwizzleComponent::Type d,PositionInfo pos)154     static DSLExpression Swizzle(DSLExpression base,
155                                  SkSL::SwizzleComponent::Type a,
156                                  SkSL::SwizzleComponent::Type b,
157                                  SkSL::SwizzleComponent::Type c,
158                                  SkSL::SwizzleComponent::Type d,
159                                  PositionInfo pos) {
160         return DSLExpression(Swizzle::Convert(DSLWriter::Context(), base.release(),
161                                               ComponentArray{a,b,c,d}),
162                              pos);
163     }
164 
Select(DSLExpression test,DSLExpression ifTrue,DSLExpression ifFalse)165     static DSLPossibleExpression Select(DSLExpression test, DSLExpression ifTrue,
166                                         DSLExpression ifFalse) {
167         return TernaryExpression::Convert(DSLWriter::Context(), test.release(),
168                                           ifTrue.release(), ifFalse.release());
169     }
170 
Switch(DSLExpression value,SkTArray<DSLCase> cases,bool isStatic)171     static DSLPossibleStatement Switch(DSLExpression value, SkTArray<DSLCase> cases,
172                                        bool isStatic) {
173         ExpressionArray values;
174         values.reserve_back(cases.count());
175         SkTArray<StatementArray> statements;
176         statements.reserve_back(cases.count());
177         for (DSLCase& c : cases) {
178             values.push_back(c.fValue.release());
179             statements.push_back(std::move(c.fStatements));
180         }
181         return DSLWriter::ConvertSwitch(value.release(), std::move(values), std::move(statements),
182                                         isStatic);
183     }
184 
While(DSLExpression test,DSLStatement stmt)185     static DSLPossibleStatement While(DSLExpression test, DSLStatement stmt) {
186         return ForStatement::ConvertWhile(DSLWriter::Context(), /*offset=*/-1, test.release(),
187                                           stmt.release(), DSLWriter::SymbolTable());
188     }
189 };
190 
sk_FragColor()191 DSLVar sk_FragColor() {
192     return DSLCore::sk_FragColor();
193 }
194 
sk_FragCoord()195 DSLVar sk_FragCoord() {
196     return DSLCore::sk_FragCoord();
197 }
198 
Break()199 DSLStatement Break() {
200     return DSLCore::Break();
201 }
202 
Continue()203 DSLStatement Continue() {
204     return DSLCore::Continue();
205 }
206 
207 // Logically, we'd want the variable's initial value to appear on here in Declare, since that
208 // matches how we actually write code (and in fact that was what our first attempt looked like).
209 // Unfortunately, C++ doesn't guarantee execution order between arguments, and Declare() can appear
210 // as a function argument in constructs like Block(Declare(x, 0), foo(x)). If these are executed out
211 // of order, we will evaluate the reference to x before we evaluate Declare(x, 0), and thus the
212 // variable's initial value is unknown at the point of reference. There are probably some other
213 // issues with this as well, but it is particularly dangerous when x is const, since SkSL will
214 // expect its value to be known when it is referenced and will end up asserting, dereferencing a
215 // null pointer, or possibly doing something else awful.
216 //
217 // So, we put the initial value onto the Var itself instead of the Declare to guarantee that it is
218 // always executed in the correct order.
Declare(DSLVar & var,PositionInfo pos)219 DSLStatement Declare(DSLVar& var, PositionInfo pos) {
220     return DSLCore::Declare(var, pos);
221 }
222 
DeclareGlobal(DSLVar & var,PositionInfo pos)223 void DeclareGlobal(DSLVar& var, PositionInfo pos) {
224     return DSLCore::DeclareGlobal(var, pos);
225 }
226 
Discard()227 DSLStatement Discard() {
228     return DSLCore::Discard();
229 }
230 
Do(DSLStatement stmt,DSLExpression test,PositionInfo pos)231 DSLStatement Do(DSLStatement stmt, DSLExpression test, PositionInfo pos) {
232     return DSLStatement(DSLCore::Do(std::move(stmt), std::move(test)), pos);
233 }
234 
For(DSLStatement initializer,DSLExpression test,DSLExpression next,DSLStatement stmt,PositionInfo pos)235 DSLStatement For(DSLStatement initializer, DSLExpression test, DSLExpression next,
236                  DSLStatement stmt, PositionInfo pos) {
237     return DSLStatement(DSLCore::For(std::move(initializer), std::move(test), std::move(next),
238                                      std::move(stmt), pos), pos);
239 }
240 
If(DSLExpression test,DSLStatement ifTrue,DSLStatement ifFalse,PositionInfo pos)241 DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse, PositionInfo pos) {
242     return DSLStatement(DSLCore::If(std::move(test), std::move(ifTrue), std::move(ifFalse),
243                                     /*isStatic=*/false),
244                         pos);
245 }
246 
Return(DSLExpression expr,PositionInfo pos)247 DSLStatement Return(DSLExpression expr, PositionInfo pos) {
248     return DSLCore::Return(std::move(expr), pos);
249 }
250 
Select(DSLExpression test,DSLExpression ifTrue,DSLExpression ifFalse,PositionInfo pos)251 DSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse,
252                      PositionInfo pos) {
253     return DSLExpression(DSLCore::Select(std::move(test), std::move(ifTrue), std::move(ifFalse)),
254                          pos);
255 }
256 
StaticIf(DSLExpression test,DSLStatement ifTrue,DSLStatement ifFalse,PositionInfo pos)257 DSLStatement StaticIf(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse,
258                       PositionInfo pos) {
259     return DSLStatement(DSLCore::If(std::move(test), std::move(ifTrue), std::move(ifFalse),
260                                     /*isStatic=*/true),
261                          pos);
262 }
263 
StaticSwitch(DSLExpression value,SkTArray<DSLCase> cases)264 DSLPossibleStatement StaticSwitch(DSLExpression value, SkTArray<DSLCase> cases) {
265     return DSLCore::Switch(std::move(value), std::move(cases), /*isStatic=*/true);
266 }
267 
Switch(DSLExpression value,SkTArray<DSLCase> cases)268 DSLPossibleStatement Switch(DSLExpression value, SkTArray<DSLCase> cases) {
269     return DSLCore::Switch(std::move(value), std::move(cases), /*isStatic=*/false);
270 }
271 
While(DSLExpression test,DSLStatement stmt,PositionInfo pos)272 DSLStatement While(DSLExpression test, DSLStatement stmt, PositionInfo pos) {
273     return DSLStatement(DSLCore::While(std::move(test), std::move(stmt)), pos);
274 }
275 
Abs(DSLExpression x,PositionInfo pos)276 DSLExpression Abs(DSLExpression x, PositionInfo pos) {
277     return DSLExpression(DSLCore::Call("abs", std::move(x)), pos);
278 }
279 
All(DSLExpression x,PositionInfo pos)280 DSLExpression All(DSLExpression x, PositionInfo pos) {
281     return DSLExpression(DSLCore::Call("all", std::move(x)), pos);
282 }
283 
Any(DSLExpression x,PositionInfo pos)284 DSLExpression Any(DSLExpression x, PositionInfo pos) {
285     return DSLExpression(DSLCore::Call("any", std::move(x)), pos);
286 }
287 
Atan(DSLExpression y_over_x,PositionInfo pos)288 DSLExpression Atan(DSLExpression y_over_x, PositionInfo pos) {
289     return DSLExpression(DSLCore::Call("atan", std::move(y_over_x)), pos);
290 }
291 
Atan(DSLExpression y,DSLExpression x,PositionInfo pos)292 DSLExpression Atan(DSLExpression y, DSLExpression x, PositionInfo pos) {
293     return DSLExpression(DSLCore::Call("atan", std::move(y), std::move(x)), pos);
294 }
295 
Ceil(DSLExpression x,PositionInfo pos)296 DSLExpression Ceil(DSLExpression x, PositionInfo pos) {
297     return DSLExpression(DSLCore::Call("ceil", std::move(x)), pos);
298 }
299 
Clamp(DSLExpression x,DSLExpression min,DSLExpression max,PositionInfo pos)300 DSLExpression Clamp(DSLExpression x, DSLExpression min, DSLExpression max, PositionInfo pos) {
301     return DSLExpression(DSLCore::Call("clamp", std::move(x), std::move(min), std::move(max)), pos);
302 }
303 
Cos(DSLExpression x,PositionInfo pos)304 DSLExpression Cos(DSLExpression x, PositionInfo pos) {
305     return DSLExpression(DSLCore::Call("cos", std::move(x)), pos);
306 }
307 
Cross(DSLExpression x,DSLExpression y,PositionInfo pos)308 DSLExpression Cross(DSLExpression x, DSLExpression y, PositionInfo pos) {
309     return DSLExpression(DSLCore::Call("cross", std::move(x), std::move(y)), pos);
310 }
311 
Degrees(DSLExpression x,PositionInfo pos)312 DSLExpression Degrees(DSLExpression x, PositionInfo pos) {
313     return DSLExpression(DSLCore::Call("degrees", std::move(x)), pos);
314 }
315 
Distance(DSLExpression x,DSLExpression y,PositionInfo pos)316 DSLExpression Distance(DSLExpression x, DSLExpression y, PositionInfo pos) {
317     return DSLExpression(DSLCore::Call("distance", std::move(x), std::move(y)), pos);
318 }
319 
Dot(DSLExpression x,DSLExpression y,PositionInfo pos)320 DSLExpression Dot(DSLExpression x, DSLExpression y, PositionInfo pos) {
321     return DSLExpression(DSLCore::Call("dot", std::move(x), std::move(y)), pos);
322 }
323 
Equal(DSLExpression x,DSLExpression y,PositionInfo pos)324 DSLExpression Equal(DSLExpression x, DSLExpression y, PositionInfo pos) {
325     return DSLExpression(DSLCore::Call("equal", std::move(x), std::move(y)), pos);
326 }
327 
Exp(DSLExpression x,PositionInfo pos)328 DSLExpression Exp(DSLExpression x, PositionInfo pos) {
329     return DSLExpression(DSLCore::Call("exp", std::move(x)), pos);
330 }
331 
Exp2(DSLExpression x,PositionInfo pos)332 DSLExpression Exp2(DSLExpression x, PositionInfo pos) {
333     return DSLExpression(DSLCore::Call("exp2", std::move(x)), pos);
334 }
335 
Faceforward(DSLExpression n,DSLExpression i,DSLExpression nref,PositionInfo pos)336 DSLExpression Faceforward(DSLExpression n, DSLExpression i, DSLExpression nref, PositionInfo pos) {
337     return DSLExpression(DSLCore::Call("faceforward", std::move(n), std::move(i), std::move(nref)),
338                          pos);
339 }
340 
Fract(DSLExpression x,PositionInfo pos)341 DSLExpression Fract(DSLExpression x, PositionInfo pos) {
342     return DSLExpression(DSLCore::Call("fract", std::move(x)), pos);
343 }
344 
Floor(DSLExpression x,PositionInfo pos)345 DSLExpression Floor(DSLExpression x, PositionInfo pos) {
346     return DSLExpression(DSLCore::Call("floor", std::move(x)), pos);
347 }
348 
GreaterThan(DSLExpression x,DSLExpression y,PositionInfo pos)349 DSLExpression GreaterThan(DSLExpression x, DSLExpression y, PositionInfo pos) {
350     return DSLExpression(DSLCore::Call("greaterThan", std::move(x), std::move(y)), pos);
351 }
352 
GreaterThanEqual(DSLExpression x,DSLExpression y,PositionInfo pos)353 DSLExpression GreaterThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
354     return DSLExpression(DSLCore::Call("greaterThanEqual", std::move(x), std::move(y)), pos);
355 }
356 
Inverse(DSLExpression x,PositionInfo pos)357 DSLExpression Inverse(DSLExpression x, PositionInfo pos) {
358     return DSLExpression(DSLCore::Call("inverse", std::move(x)), pos);
359 }
360 
Inversesqrt(DSLExpression x,PositionInfo pos)361 DSLExpression Inversesqrt(DSLExpression x, PositionInfo pos) {
362     return DSLExpression(DSLCore::Call("inversesqrt", std::move(x)), pos);
363 }
364 
Length(DSLExpression x,PositionInfo pos)365 DSLExpression Length(DSLExpression x, PositionInfo pos) {
366     return DSLExpression(DSLCore::Call("length", std::move(x)), pos);
367 }
368 
LessThan(DSLExpression x,DSLExpression y,PositionInfo pos)369 DSLExpression LessThan(DSLExpression x, DSLExpression y, PositionInfo pos) {
370     return DSLExpression(DSLCore::Call("lessThan", std::move(x), std::move(y)), pos);
371 }
372 
LessThanEqual(DSLExpression x,DSLExpression y,PositionInfo pos)373 DSLExpression LessThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
374     return DSLExpression(DSLCore::Call("lessThanEqual", std::move(x), std::move(y)), pos);
375 }
376 
Log(DSLExpression x,PositionInfo pos)377 DSLExpression Log(DSLExpression x, PositionInfo pos) {
378     return DSLExpression(DSLCore::Call("log", std::move(x)), pos);
379 }
380 
Log2(DSLExpression x,PositionInfo pos)381 DSLExpression Log2(DSLExpression x, PositionInfo pos) {
382     return DSLExpression(DSLCore::Call("log2", std::move(x)), pos);
383 }
384 
Max(DSLExpression x,DSLExpression y,PositionInfo pos)385 DSLExpression Max(DSLExpression x, DSLExpression y, PositionInfo pos) {
386     return DSLExpression(DSLCore::Call("max", std::move(x), std::move(y)), pos);
387 }
388 
Min(DSLExpression x,DSLExpression y,PositionInfo pos)389 DSLExpression Min(DSLExpression x, DSLExpression y, PositionInfo pos) {
390     return DSLExpression(DSLCore::Call("min", std::move(x), std::move(y)), pos);
391 }
392 
Mix(DSLExpression x,DSLExpression y,DSLExpression a,PositionInfo pos)393 DSLExpression Mix(DSLExpression x, DSLExpression y, DSLExpression a, PositionInfo pos) {
394     return DSLExpression(DSLCore::Call("mix", std::move(x), std::move(y), std::move(a)), pos);
395 }
396 
Mod(DSLExpression x,DSLExpression y,PositionInfo pos)397 DSLExpression Mod(DSLExpression x, DSLExpression y, PositionInfo pos) {
398     return DSLExpression(DSLCore::Call("mod", std::move(x), std::move(y)), pos);
399 }
400 
Normalize(DSLExpression x,PositionInfo pos)401 DSLExpression Normalize(DSLExpression x, PositionInfo pos) {
402     return DSLExpression(DSLCore::Call("normalize", std::move(x)), pos);
403 }
404 
NotEqual(DSLExpression x,DSLExpression y,PositionInfo pos)405 DSLExpression NotEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
406     return DSLExpression(DSLCore::Call("notEqual", std::move(x), std::move(y)), pos);
407 }
408 
Pow(DSLExpression x,DSLExpression y,PositionInfo pos)409 DSLExpression Pow(DSLExpression x, DSLExpression y, PositionInfo pos) {
410     return DSLExpression(DSLCore::Call("pow", std::move(x), std::move(y)), pos);
411 }
412 
Radians(DSLExpression x,PositionInfo pos)413 DSLExpression Radians(DSLExpression x, PositionInfo pos) {
414     return DSLExpression(DSLCore::Call("radians", std::move(x)), pos);
415 }
416 
Reflect(DSLExpression i,DSLExpression n,PositionInfo pos)417 DSLExpression Reflect(DSLExpression i, DSLExpression n, PositionInfo pos) {
418     return DSLExpression(DSLCore::Call("reflect", std::move(i), std::move(n)), pos);
419 }
420 
Refract(DSLExpression i,DSLExpression n,DSLExpression eta,PositionInfo pos)421 DSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta, PositionInfo pos) {
422     return DSLExpression(DSLCore::Call("refract", std::move(i), std::move(n), std::move(eta)), pos);
423 }
424 
Sample(DSLExpression target,PositionInfo pos)425 DSLExpression Sample(DSLExpression target, PositionInfo pos) {
426     return DSLExpression(DSLCore::Call("sample", std::move(target)), pos);
427 }
428 
429 
Sample(DSLExpression target,DSLExpression x,PositionInfo pos)430 DSLExpression Sample(DSLExpression target, DSLExpression x, PositionInfo pos) {
431     return DSLExpression(DSLCore::Call("sample", std::move(target), std::move(x)), pos);
432 }
433 
Sample(DSLExpression target,DSLExpression x,DSLExpression y,PositionInfo pos)434 DSLExpression Sample(DSLExpression target, DSLExpression x, DSLExpression y, PositionInfo pos) {
435     return DSLExpression(DSLCore::Call("sample", std::move(target), std::move(x), std::move(y)),
436                          pos);
437 }
438 
Saturate(DSLExpression x,PositionInfo pos)439 DSLExpression Saturate(DSLExpression x, PositionInfo pos) {
440     return DSLExpression(DSLCore::Call("saturate", std::move(x)), pos);
441 }
442 
Sign(DSLExpression x,PositionInfo pos)443 DSLExpression Sign(DSLExpression x, PositionInfo pos) {
444     return DSLExpression(DSLCore::Call("sign", std::move(x)), pos);
445 }
446 
Sin(DSLExpression x,PositionInfo pos)447 DSLExpression Sin(DSLExpression x, PositionInfo pos) {
448     return DSLExpression(DSLCore::Call("sin", std::move(x)), pos);
449 }
450 
Smoothstep(DSLExpression edge1,DSLExpression edge2,DSLExpression x,PositionInfo pos)451 DSLExpression Smoothstep(DSLExpression edge1, DSLExpression edge2, DSLExpression x,
452                          PositionInfo pos) {
453     return DSLExpression(DSLCore::Call("smoothstep", std::move(edge1), std::move(edge2),
454                                        std::move(x)),
455                          pos);
456 }
457 
Sqrt(DSLExpression x,PositionInfo pos)458 DSLExpression Sqrt(DSLExpression x, PositionInfo pos) {
459     return DSLExpression(DSLCore::Call("sqrt", std::move(x)), pos);
460 }
461 
Step(DSLExpression edge,DSLExpression x,PositionInfo pos)462 DSLExpression Step(DSLExpression edge, DSLExpression x, PositionInfo pos) {
463     return DSLExpression(DSLCore::Call("step", std::move(edge), std::move(x)), pos);
464 }
465 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,PositionInfo pos)466 DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a,
467                       PositionInfo pos) {
468     return DSLCore::Swizzle(std::move(base), a, pos);
469 }
470 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,PositionInfo pos)471 DSLExpression Swizzle(DSLExpression base,
472                       SkSL::SwizzleComponent::Type a,
473                       SkSL::SwizzleComponent::Type b,
474                       PositionInfo pos) {
475     return DSLCore::Swizzle(std::move(base), a, b, pos);
476 }
477 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,SkSL::SwizzleComponent::Type c,PositionInfo pos)478 DSLExpression Swizzle(DSLExpression base,
479                       SkSL::SwizzleComponent::Type a,
480                       SkSL::SwizzleComponent::Type b,
481                       SkSL::SwizzleComponent::Type c,
482                       PositionInfo pos) {
483     return DSLCore::Swizzle(std::move(base), a, b, c, pos);
484 }
485 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,SkSL::SwizzleComponent::Type c,SkSL::SwizzleComponent::Type d,PositionInfo pos)486 DSLExpression Swizzle(DSLExpression base,
487                       SkSL::SwizzleComponent::Type a,
488                       SkSL::SwizzleComponent::Type b,
489                       SkSL::SwizzleComponent::Type c,
490                       SkSL::SwizzleComponent::Type d,
491                       PositionInfo pos) {
492     return DSLCore::Swizzle(std::move(base), a, b, c, d, pos);
493 }
494 
Tan(DSLExpression x,PositionInfo pos)495 DSLExpression Tan(DSLExpression x, PositionInfo pos) {
496     return DSLExpression(DSLCore::Call("tan", std::move(x)), pos);
497 }
498 
Unpremul(DSLExpression x,PositionInfo pos)499 DSLExpression Unpremul(DSLExpression x, PositionInfo pos) {
500     return DSLExpression(DSLCore::Call("unpremul", std::move(x)), pos);
501 }
502 
503 } // namespace dsl
504 
505 } // namespace SkSL
506