1 /*
2 * Copyright 2021 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/ir/SkSLFunctionCall.h"
9
10 #include "include/core/SkSpan.h"
11 #include "include/core/SkTypes.h"
12 #include "include/private/SkSLModifiers.h"
13 #include "include/private/SkSLString.h"
14 #include "include/private/base/SkFloatingPoint.h"
15 #include "include/private/base/SkTArray.h"
16 #include "include/private/base/SkTo.h"
17 #include "include/sksl/DSLCore.h"
18 #include "include/sksl/DSLExpression.h"
19 #include "include/sksl/DSLType.h"
20 #include "include/sksl/SkSLErrorReporter.h"
21 #include "include/sksl/SkSLOperator.h"
22 #include "src/base/SkHalf.h"
23 #include "src/core/SkMatrixInvert.h"
24 #include "src/sksl/SkSLAnalysis.h"
25 #include "src/sksl/SkSLBuiltinTypes.h"
26 #include "src/sksl/SkSLConstantFolder.h"
27 #include "src/sksl/SkSLContext.h"
28 #include "src/sksl/SkSLIntrinsicList.h"
29 #include "src/sksl/SkSLProgramSettings.h"
30 #include "src/sksl/ir/SkSLChildCall.h"
31 #include "src/sksl/ir/SkSLConstructor.h"
32 #include "src/sksl/ir/SkSLConstructorCompound.h"
33 #include "src/sksl/ir/SkSLFunctionDeclaration.h"
34 #include "src/sksl/ir/SkSLFunctionReference.h"
35 #include "src/sksl/ir/SkSLLiteral.h"
36 #include "src/sksl/ir/SkSLMethodReference.h"
37 #include "src/sksl/ir/SkSLType.h"
38 #include "src/sksl/ir/SkSLTypeReference.h"
39 #include "src/sksl/ir/SkSLVariable.h"
40 #include "src/sksl/ir/SkSLVariableReference.h"
41
42 #include <algorithm>
43 #include <array>
44 #include <cmath>
45 #include <cstdint>
46 #include <cstring>
47 #include <optional>
48 #include <string_view>
49 #include <vector>
50
51 namespace SkSL {
52
53 using IntrinsicArguments = std::array<const Expression*, 3>;
54
has_compile_time_constant_arguments(const ExpressionArray & arguments)55 static bool has_compile_time_constant_arguments(const ExpressionArray& arguments) {
56 for (const std::unique_ptr<Expression>& arg : arguments) {
57 const Expression* expr = ConstantFolder::GetConstantValueForVariable(*arg);
58 if (!Analysis::IsCompileTimeConstant(*expr)) {
59 return false;
60 }
61 }
62 return true;
63 }
64
65 template <typename T>
66 static void type_check_expression(const Expression& expr);
67
68 template <>
type_check_expression(const Expression & expr)69 void type_check_expression<float>(const Expression& expr) {
70 SkASSERT(expr.type().componentType().isFloat());
71 }
72
73 template <>
type_check_expression(const Expression & expr)74 void type_check_expression<SKSL_INT>(const Expression& expr) {
75 SkASSERT(expr.type().componentType().isInteger());
76 }
77
78 template <>
type_check_expression(const Expression & expr)79 void type_check_expression<bool>(const Expression& expr) {
80 SkASSERT(expr.type().componentType().isBoolean());
81 }
82
assemble_compound(const Context & context,Position pos,const Type & returnType,double value[])83 static std::unique_ptr<Expression> assemble_compound(const Context& context,
84 Position pos,
85 const Type& returnType,
86 double value[]) {
87 int numSlots = returnType.slotCount();
88 ExpressionArray array;
89 array.reserve_back(numSlots);
90 for (int index = 0; index < numSlots; ++index) {
91 array.push_back(Literal::Make(pos, value[index], &returnType.componentType()));
92 }
93 return ConstructorCompound::Make(context, pos, returnType, std::move(array));
94 }
95
96 using CoalesceFn = double (*)(double, double, double);
97 using FinalizeFn = double (*)(double);
98
coalesce_n_way_vector(const Expression * arg0,const Expression * arg1,double startingState,const Type & returnType,CoalesceFn coalesce,FinalizeFn finalize)99 static std::unique_ptr<Expression> coalesce_n_way_vector(const Expression* arg0,
100 const Expression* arg1,
101 double startingState,
102 const Type& returnType,
103 CoalesceFn coalesce,
104 FinalizeFn finalize) {
105 // Takes up to two vector or scalar arguments and coalesces them in sequence:
106 // scalar = startingState;
107 // scalar = coalesce(scalar, arg0.x, arg1.x);
108 // scalar = coalesce(scalar, arg0.y, arg1.y);
109 // scalar = coalesce(scalar, arg0.z, arg1.z);
110 // scalar = coalesce(scalar, arg0.w, arg1.w);
111 // scalar = finalize(scalar);
112 //
113 // If an argument is null, zero is passed to the coalesce function. If the arguments are a mix
114 // of scalars and vectors, the scalars is interpreted as a vector containing the same value for
115 // every component.
116
117 Position pos = arg0->fPosition;
118 double minimumValue = returnType.componentType().minimumValue();
119 double maximumValue = returnType.componentType().maximumValue();
120
121 const Type& vecType = arg0->type().isVector() ? arg0->type() :
122 (arg1 && arg1->type().isVector()) ? arg1->type() :
123 arg0->type();
124 SkASSERT( arg0->type().componentType().matches(vecType.componentType()));
125 SkASSERT(!arg1 || arg1->type().componentType().matches(vecType.componentType()));
126
127 double value = startingState;
128 int arg0Index = 0;
129 int arg1Index = 0;
130 for (int index = 0; index < vecType.columns(); ++index) {
131 std::optional<double> arg0Value = arg0->getConstantValue(arg0Index);
132 arg0Index += arg0->type().isVector() ? 1 : 0;
133 SkASSERT(arg0Value.has_value());
134
135 std::optional<double> arg1Value = 0.0;
136 if (arg1) {
137 arg1Value = arg1->getConstantValue(arg1Index);
138 arg1Index += arg1->type().isVector() ? 1 : 0;
139 SkASSERT(arg1Value.has_value());
140 }
141
142 value = coalesce(value, *arg0Value, *arg1Value);
143
144 if (value >= minimumValue && value <= maximumValue) {
145 // This result will fit inside the return type.
146 } else {
147 // The value is outside the float range or is NaN (all if-checks fail); do not optimize.
148 return nullptr;
149 }
150 }
151
152 if (finalize) {
153 value = finalize(value);
154 }
155
156 return Literal::Make(pos, value, &returnType);
157 }
158
159 template <typename T>
coalesce_vector(const IntrinsicArguments & arguments,double startingState,const Type & returnType,CoalesceFn coalesce,FinalizeFn finalize)160 static std::unique_ptr<Expression> coalesce_vector(const IntrinsicArguments& arguments,
161 double startingState,
162 const Type& returnType,
163 CoalesceFn coalesce,
164 FinalizeFn finalize) {
165 SkASSERT(arguments[0]);
166 SkASSERT(!arguments[1]);
167 type_check_expression<T>(*arguments[0]);
168
169 return coalesce_n_way_vector(arguments[0], /*arg1=*/nullptr,
170 startingState, returnType, coalesce, finalize);
171 }
172
173 template <typename T>
coalesce_pairwise_vectors(const IntrinsicArguments & arguments,double startingState,const Type & returnType,CoalesceFn coalesce,FinalizeFn finalize)174 static std::unique_ptr<Expression> coalesce_pairwise_vectors(const IntrinsicArguments& arguments,
175 double startingState,
176 const Type& returnType,
177 CoalesceFn coalesce,
178 FinalizeFn finalize) {
179 SkASSERT(arguments[0]);
180 SkASSERT(arguments[1]);
181 SkASSERT(!arguments[2]);
182 type_check_expression<T>(*arguments[0]);
183 type_check_expression<T>(*arguments[1]);
184
185 return coalesce_n_way_vector(arguments[0], arguments[1],
186 startingState, returnType, coalesce, finalize);
187 }
188
189 using CompareFn = bool (*)(double, double);
190
optimize_comparison(const Context & context,const IntrinsicArguments & arguments,CompareFn compare)191 static std::unique_ptr<Expression> optimize_comparison(const Context& context,
192 const IntrinsicArguments& arguments,
193 CompareFn compare) {
194 const Expression* left = arguments[0];
195 const Expression* right = arguments[1];
196 SkASSERT(left);
197 SkASSERT(right);
198 SkASSERT(!arguments[2]);
199
200 const Type& type = left->type();
201 SkASSERT(type.isVector());
202 SkASSERT(type.componentType().isScalar());
203 SkASSERT(type.matches(right->type()));
204
205 double array[4];
206
207 for (int index = 0; index < type.columns(); ++index) {
208 std::optional<double> leftValue = left->getConstantValue(index);
209 std::optional<double> rightValue = right->getConstantValue(index);
210 SkASSERT(leftValue.has_value());
211 SkASSERT(rightValue.has_value());
212 array[index] = compare(*leftValue, *rightValue) ? 1.0 : 0.0;
213 }
214
215 const Type& bvecType = context.fTypes.fBool->toCompound(context, type.columns(), /*rows=*/1);
216 return assemble_compound(context, left->fPosition, bvecType, array);
217 }
218
219 using EvaluateFn = double (*)(double, double, double);
220
evaluate_n_way_intrinsic(const Context & context,const Expression * arg0,const Expression * arg1,const Expression * arg2,const Type & returnType,EvaluateFn eval)221 static std::unique_ptr<Expression> evaluate_n_way_intrinsic(const Context& context,
222 const Expression* arg0,
223 const Expression* arg1,
224 const Expression* arg2,
225 const Type& returnType,
226 EvaluateFn eval) {
227 // Takes up to three arguments and evaluates all of them, left-to-right, in tandem.
228 // Equivalent to constructing a new compound value containing the results from:
229 // eval(arg0.x, arg1.x, arg2.x),
230 // eval(arg0.y, arg1.y, arg2.y),
231 // eval(arg0.z, arg1.z, arg2.z),
232 // eval(arg0.w, arg1.w, arg2.w)
233 //
234 // If an argument is null, zero is passed to the evaluation function. If the arguments are a mix
235 // of scalars and compounds, scalars are interpreted as a compound containing the same value for
236 // every component.
237
238 double minimumValue = returnType.componentType().minimumValue();
239 double maximumValue = returnType.componentType().maximumValue();
240 int slots = returnType.slotCount();
241 double array[16];
242
243 int arg0Index = 0;
244 int arg1Index = 0;
245 int arg2Index = 0;
246 for (int index = 0; index < slots; ++index) {
247 std::optional<double> arg0Value = arg0->getConstantValue(arg0Index);
248 arg0Index += arg0->type().isScalar() ? 0 : 1;
249 SkASSERT(arg0Value.has_value());
250
251 std::optional<double> arg1Value = 0.0;
252 if (arg1) {
253 arg1Value = arg1->getConstantValue(arg1Index);
254 arg1Index += arg1->type().isScalar() ? 0 : 1;
255 SkASSERT(arg1Value.has_value());
256 }
257
258 std::optional<double> arg2Value = 0.0;
259 if (arg2) {
260 arg2Value = arg2->getConstantValue(arg2Index);
261 arg2Index += arg2->type().isScalar() ? 0 : 1;
262 SkASSERT(arg2Value.has_value());
263 }
264
265 array[index] = eval(*arg0Value, *arg1Value, *arg2Value);
266
267 if (array[index] >= minimumValue && array[index] <= maximumValue) {
268 // This result will fit inside the return type.
269 } else {
270 // The value is outside the float range or is NaN (all if-checks fail); do not optimize.
271 return nullptr;
272 }
273 }
274
275 return assemble_compound(context, arg0->fPosition, returnType, array);
276 }
277
278 template <typename T>
evaluate_intrinsic(const Context & context,const IntrinsicArguments & arguments,const Type & returnType,EvaluateFn eval)279 static std::unique_ptr<Expression> evaluate_intrinsic(const Context& context,
280 const IntrinsicArguments& arguments,
281 const Type& returnType,
282 EvaluateFn eval) {
283 SkASSERT(arguments[0]);
284 SkASSERT(!arguments[1]);
285 type_check_expression<T>(*arguments[0]);
286
287 return evaluate_n_way_intrinsic(context, arguments[0], /*arg1=*/nullptr, /*arg2=*/nullptr,
288 returnType, eval);
289 }
290
evaluate_intrinsic_numeric(const Context & context,const IntrinsicArguments & arguments,const Type & returnType,EvaluateFn eval)291 static std::unique_ptr<Expression> evaluate_intrinsic_numeric(const Context& context,
292 const IntrinsicArguments& arguments,
293 const Type& returnType,
294 EvaluateFn eval) {
295 SkASSERT(arguments[0]);
296 SkASSERT(!arguments[1]);
297 const Type& type = arguments[0]->type().componentType();
298
299 if (type.isFloat()) {
300 return evaluate_intrinsic<float>(context, arguments, returnType, eval);
301 }
302 if (type.isInteger()) {
303 return evaluate_intrinsic<SKSL_INT>(context, arguments, returnType, eval);
304 }
305
306 SkDEBUGFAILF("unsupported type %s", type.description().c_str());
307 return nullptr;
308 }
309
evaluate_pairwise_intrinsic(const Context & context,const IntrinsicArguments & arguments,const Type & returnType,EvaluateFn eval)310 static std::unique_ptr<Expression> evaluate_pairwise_intrinsic(const Context& context,
311 const IntrinsicArguments& arguments,
312 const Type& returnType,
313 EvaluateFn eval) {
314 SkASSERT(arguments[0]);
315 SkASSERT(arguments[1]);
316 SkASSERT(!arguments[2]);
317 const Type& type = arguments[0]->type().componentType();
318
319 if (type.isFloat()) {
320 type_check_expression<float>(*arguments[0]);
321 type_check_expression<float>(*arguments[1]);
322 } else if (type.isInteger()) {
323 type_check_expression<SKSL_INT>(*arguments[0]);
324 type_check_expression<SKSL_INT>(*arguments[1]);
325 } else {
326 SkDEBUGFAILF("unsupported type %s", type.description().c_str());
327 return nullptr;
328 }
329
330 return evaluate_n_way_intrinsic(context, arguments[0], arguments[1], /*arg2=*/nullptr,
331 returnType, eval);
332 }
333
evaluate_3_way_intrinsic(const Context & context,const IntrinsicArguments & arguments,const Type & returnType,EvaluateFn eval)334 static std::unique_ptr<Expression> evaluate_3_way_intrinsic(const Context& context,
335 const IntrinsicArguments& arguments,
336 const Type& returnType,
337 EvaluateFn eval) {
338 SkASSERT(arguments[0]);
339 SkASSERT(arguments[1]);
340 SkASSERT(arguments[2]);
341 const Type& type = arguments[0]->type().componentType();
342
343 if (type.isFloat()) {
344 type_check_expression<float>(*arguments[0]);
345 type_check_expression<float>(*arguments[1]);
346 type_check_expression<float>(*arguments[2]);
347 } else if (type.isInteger()) {
348 type_check_expression<SKSL_INT>(*arguments[0]);
349 type_check_expression<SKSL_INT>(*arguments[1]);
350 type_check_expression<SKSL_INT>(*arguments[2]);
351 } else {
352 SkDEBUGFAILF("unsupported type %s", type.description().c_str());
353 return nullptr;
354 }
355
356 return evaluate_n_way_intrinsic(context, arguments[0], arguments[1], arguments[2],
357 returnType, eval);
358 }
359
360 template <typename T1, typename T2>
pun_value(double val)361 static double pun_value(double val) {
362 // Interpret `val` as a value of type T1.
363 static_assert(sizeof(T1) == sizeof(T2));
364 T1 inputValue = (T1)val;
365 // Reinterpret those bits as a value of type T2.
366 T2 outputValue;
367 memcpy(&outputValue, &inputValue, sizeof(T2));
368 // Return the value-of-type-T2 as a double. (Non-finite values will prohibit optimization.)
369 return (double)outputValue;
370 }
371
372 // Helper functions for optimizing all of our intrinsics.
373 namespace Intrinsics {
374 namespace {
375
coalesce_length(double a,double b,double)376 double coalesce_length(double a, double b, double) { return a + (b * b); }
finalize_length(double a)377 double finalize_length(double a) { return std::sqrt(a); }
378
coalesce_distance(double a,double b,double c)379 double coalesce_distance(double a, double b, double c) { b -= c; return a + (b * b); }
finalize_distance(double a)380 double finalize_distance(double a) { return std::sqrt(a); }
381
coalesce_dot(double a,double b,double c)382 double coalesce_dot(double a, double b, double c) { return a + (b * c); }
coalesce_any(double a,double b,double)383 double coalesce_any(double a, double b, double) { return a || b; }
coalesce_all(double a,double b,double)384 double coalesce_all(double a, double b, double) { return a && b; }
385
compare_lessThan(double a,double b)386 bool compare_lessThan(double a, double b) { return a < b; }
compare_lessThanEqual(double a,double b)387 bool compare_lessThanEqual(double a, double b) { return a <= b; }
compare_greaterThan(double a,double b)388 bool compare_greaterThan(double a, double b) { return a > b; }
compare_greaterThanEqual(double a,double b)389 bool compare_greaterThanEqual(double a, double b) { return a >= b; }
compare_equal(double a,double b)390 bool compare_equal(double a, double b) { return a == b; }
compare_notEqual(double a,double b)391 bool compare_notEqual(double a, double b) { return a != b; }
392
evaluate_radians(double a,double,double)393 double evaluate_radians(double a, double, double) { return a * 0.0174532925; }
evaluate_degrees(double a,double,double)394 double evaluate_degrees(double a, double, double) { return a * 57.2957795; }
evaluate_sin(double a,double,double)395 double evaluate_sin(double a, double, double) { return std::sin(a); }
evaluate_cos(double a,double,double)396 double evaluate_cos(double a, double, double) { return std::cos(a); }
evaluate_tan(double a,double,double)397 double evaluate_tan(double a, double, double) { return std::tan(a); }
evaluate_asin(double a,double,double)398 double evaluate_asin(double a, double, double) { return std::asin(a); }
evaluate_acos(double a,double,double)399 double evaluate_acos(double a, double, double) { return std::acos(a); }
evaluate_atan(double a,double,double)400 double evaluate_atan(double a, double, double) { return std::atan(a); }
evaluate_atan2(double a,double b,double)401 double evaluate_atan2(double a, double b, double) { return std::atan2(a, b); }
evaluate_asinh(double a,double,double)402 double evaluate_asinh(double a, double, double) { return std::asinh(a); }
evaluate_acosh(double a,double,double)403 double evaluate_acosh(double a, double, double) { return std::acosh(a); }
evaluate_atanh(double a,double,double)404 double evaluate_atanh(double a, double, double) { return std::atanh(a); }
405
evaluate_pow(double a,double b,double)406 double evaluate_pow(double a, double b, double) { return std::pow(a, b); }
evaluate_exp(double a,double,double)407 double evaluate_exp(double a, double, double) { return std::exp(a); }
evaluate_log(double a,double,double)408 double evaluate_log(double a, double, double) { return std::log(a); }
evaluate_exp2(double a,double,double)409 double evaluate_exp2(double a, double, double) { return std::exp2(a); }
evaluate_log2(double a,double,double)410 double evaluate_log2(double a, double, double) { return std::log2(a); }
evaluate_sqrt(double a,double,double)411 double evaluate_sqrt(double a, double, double) { return std::sqrt(a); }
evaluate_inversesqrt(double a,double,double)412 double evaluate_inversesqrt(double a, double, double) {
413 return sk_ieee_double_divide(1.0, std::sqrt(a));
414 }
415
evaluate_abs(double a,double,double)416 double evaluate_abs(double a, double, double) { return std::abs(a); }
evaluate_sign(double a,double,double)417 double evaluate_sign(double a, double, double) { return (a > 0) - (a < 0); }
evaluate_floor(double a,double,double)418 double evaluate_floor(double a, double, double) { return std::floor(a); }
evaluate_ceil(double a,double,double)419 double evaluate_ceil(double a, double, double) { return std::ceil(a); }
evaluate_fract(double a,double,double)420 double evaluate_fract(double a, double, double) { return a - std::floor(a); }
evaluate_min(double a,double b,double)421 double evaluate_min(double a, double b, double) { return (a < b) ? a : b; }
evaluate_max(double a,double b,double)422 double evaluate_max(double a, double b, double) { return (a > b) ? a : b; }
evaluate_clamp(double x,double l,double h)423 double evaluate_clamp(double x, double l, double h) { return (x < l) ? l : (x > h) ? h : x; }
evaluate_fma(double a,double b,double c)424 double evaluate_fma(double a, double b, double c) { return a * b + c; }
evaluate_saturate(double a,double,double)425 double evaluate_saturate(double a, double, double) { return (a < 0) ? 0 : (a > 1) ? 1 : a; }
evaluate_mix(double x,double y,double a)426 double evaluate_mix(double x, double y, double a) { return x * (1 - a) + y * a; }
evaluate_step(double e,double x,double)427 double evaluate_step(double e, double x, double) { return (x < e) ? 0 : 1; }
evaluate_mod(double a,double b,double)428 double evaluate_mod(double a, double b, double) {
429 return a - b * std::floor(sk_ieee_double_divide(a, b));
430 }
evaluate_smoothstep(double edge0,double edge1,double x)431 double evaluate_smoothstep(double edge0, double edge1, double x) {
432 double t = sk_ieee_double_divide(x - edge0, edge1 - edge0);
433 t = (t < 0) ? 0 : (t > 1) ? 1 : t;
434 return t * t * (3.0 - 2.0 * t);
435 }
436
evaluate_matrixCompMult(double x,double y,double)437 double evaluate_matrixCompMult(double x, double y, double) { return x * y; }
438
evaluate_not(double a,double,double)439 double evaluate_not(double a, double, double) { return !a; }
evaluate_sinh(double a,double,double)440 double evaluate_sinh(double a, double, double) { return std::sinh(a); }
evaluate_cosh(double a,double,double)441 double evaluate_cosh(double a, double, double) { return std::cosh(a); }
evaluate_tanh(double a,double,double)442 double evaluate_tanh(double a, double, double) { return std::tanh(a); }
evaluate_trunc(double a,double,double)443 double evaluate_trunc(double a, double, double) { return std::trunc(a); }
evaluate_round(double a,double,double)444 double evaluate_round(double a, double, double) {
445 // The semantics of std::remainder guarantee a rounded-to-even result here, regardless of the
446 // current float-rounding mode.
447 return a - std::remainder(a, 1.0);
448 }
evaluate_floatBitsToInt(double a,double,double)449 double evaluate_floatBitsToInt(double a, double, double) { return pun_value<float, int32_t> (a); }
evaluate_floatBitsToUint(double a,double,double)450 double evaluate_floatBitsToUint(double a, double, double) { return pun_value<float, uint32_t>(a); }
evaluate_intBitsToFloat(double a,double,double)451 double evaluate_intBitsToFloat(double a, double, double) { return pun_value<int32_t, float>(a); }
evaluate_uintBitsToFloat(double a,double,double)452 double evaluate_uintBitsToFloat(double a, double, double) { return pun_value<uint32_t, float>(a); }
453
454 } // namespace
455 } // namespace Intrinsics
456
extract_matrix(const Expression * expr,float mat[16])457 static void extract_matrix(const Expression* expr, float mat[16]) {
458 size_t numSlots = expr->type().slotCount();
459 for (size_t index = 0; index < numSlots; ++index) {
460 mat[index] = *expr->getConstantValue(index);
461 }
462 }
463
optimize_intrinsic_call(const Context & context,Position pos,IntrinsicKind intrinsic,const ExpressionArray & argArray,const Type & returnType)464 static std::unique_ptr<Expression> optimize_intrinsic_call(const Context& context,
465 Position pos,
466 IntrinsicKind intrinsic,
467 const ExpressionArray& argArray,
468 const Type& returnType) {
469 // Replace constant variables with their literal values.
470 IntrinsicArguments arguments = {};
471 SkASSERT(SkToSizeT(argArray.size()) <= arguments.size());
472 for (int index = 0; index < argArray.size(); ++index) {
473 arguments[index] = ConstantFolder::GetConstantValueForVariable(*argArray[index]);
474 }
475
476 auto Get = [&](int idx, int col) -> float {
477 return *arguments[idx]->getConstantValue(col);
478 };
479
480 using namespace SkSL::dsl;
481 switch (intrinsic) {
482 // 8.1 : Angle and Trigonometry Functions
483 case k_radians_IntrinsicKind:
484 return evaluate_intrinsic<float>(context, arguments, returnType,
485 Intrinsics::evaluate_radians);
486 case k_degrees_IntrinsicKind:
487 return evaluate_intrinsic<float>(context, arguments, returnType,
488 Intrinsics::evaluate_degrees);
489 case k_sin_IntrinsicKind:
490 return evaluate_intrinsic<float>(context, arguments, returnType,
491 Intrinsics::evaluate_sin);
492 case k_cos_IntrinsicKind:
493 return evaluate_intrinsic<float>(context, arguments, returnType,
494 Intrinsics::evaluate_cos);
495 case k_tan_IntrinsicKind:
496 return evaluate_intrinsic<float>(context, arguments, returnType,
497 Intrinsics::evaluate_tan);
498 case k_sinh_IntrinsicKind:
499 return evaluate_intrinsic<float>(context, arguments, returnType,
500 Intrinsics::evaluate_sinh);
501 case k_cosh_IntrinsicKind:
502 return evaluate_intrinsic<float>(context, arguments, returnType,
503 Intrinsics::evaluate_cosh);
504 case k_tanh_IntrinsicKind:
505 return evaluate_intrinsic<float>(context, arguments, returnType,
506 Intrinsics::evaluate_tanh);
507 case k_asin_IntrinsicKind:
508 return evaluate_intrinsic<float>(context, arguments, returnType,
509 Intrinsics::evaluate_asin);
510 case k_acos_IntrinsicKind:
511 return evaluate_intrinsic<float>(context, arguments, returnType,
512 Intrinsics::evaluate_acos);
513 case k_atan_IntrinsicKind:
514 if (argArray.size() == 1) {
515 return evaluate_intrinsic<float>(context, arguments, returnType,
516 Intrinsics::evaluate_atan);
517 } else {
518 return evaluate_pairwise_intrinsic(context, arguments, returnType,
519 Intrinsics::evaluate_atan2);
520 }
521 case k_asinh_IntrinsicKind:
522 return evaluate_intrinsic<float>(context, arguments, returnType,
523 Intrinsics::evaluate_asinh);
524
525 case k_acosh_IntrinsicKind:
526 return evaluate_intrinsic<float>(context, arguments, returnType,
527 Intrinsics::evaluate_acosh);
528 case k_atanh_IntrinsicKind:
529 return evaluate_intrinsic<float>(context, arguments, returnType,
530 Intrinsics::evaluate_atanh);
531 // 8.2 : Exponential Functions
532 case k_pow_IntrinsicKind:
533 return evaluate_pairwise_intrinsic(context, arguments, returnType,
534 Intrinsics::evaluate_pow);
535 case k_exp_IntrinsicKind:
536 return evaluate_intrinsic<float>(context, arguments, returnType,
537 Intrinsics::evaluate_exp);
538 case k_log_IntrinsicKind:
539 return evaluate_intrinsic<float>(context, arguments, returnType,
540 Intrinsics::evaluate_log);
541 case k_exp2_IntrinsicKind:
542 return evaluate_intrinsic<float>(context, arguments, returnType,
543 Intrinsics::evaluate_exp2);
544 case k_log2_IntrinsicKind:
545 return evaluate_intrinsic<float>(context, arguments, returnType,
546 Intrinsics::evaluate_log2);
547 case k_sqrt_IntrinsicKind:
548 return evaluate_intrinsic<float>(context, arguments, returnType,
549 Intrinsics::evaluate_sqrt);
550 case k_inversesqrt_IntrinsicKind:
551 return evaluate_intrinsic<float>(context, arguments, returnType,
552 Intrinsics::evaluate_inversesqrt);
553 // 8.3 : Common Functions
554 case k_abs_IntrinsicKind:
555 return evaluate_intrinsic_numeric(context, arguments, returnType,
556 Intrinsics::evaluate_abs);
557 case k_sign_IntrinsicKind:
558 return evaluate_intrinsic_numeric(context, arguments, returnType,
559 Intrinsics::evaluate_sign);
560 case k_floor_IntrinsicKind:
561 return evaluate_intrinsic<float>(context, arguments, returnType,
562 Intrinsics::evaluate_floor);
563 case k_ceil_IntrinsicKind:
564 return evaluate_intrinsic<float>(context, arguments, returnType,
565 Intrinsics::evaluate_ceil);
566 case k_fract_IntrinsicKind:
567 return evaluate_intrinsic<float>(context, arguments, returnType,
568 Intrinsics::evaluate_fract);
569 case k_mod_IntrinsicKind:
570 return evaluate_pairwise_intrinsic(context, arguments, returnType,
571 Intrinsics::evaluate_mod);
572 case k_min_IntrinsicKind:
573 return evaluate_pairwise_intrinsic(context, arguments, returnType,
574 Intrinsics::evaluate_min);
575 case k_max_IntrinsicKind:
576 return evaluate_pairwise_intrinsic(context, arguments, returnType,
577 Intrinsics::evaluate_max);
578 case k_clamp_IntrinsicKind:
579 return evaluate_3_way_intrinsic(context, arguments, returnType,
580 Intrinsics::evaluate_clamp);
581 case k_fma_IntrinsicKind:
582 return evaluate_3_way_intrinsic(context, arguments, returnType,
583 Intrinsics::evaluate_fma);
584 case k_saturate_IntrinsicKind:
585 return evaluate_intrinsic<float>(context, arguments, returnType,
586 Intrinsics::evaluate_saturate);
587 case k_mix_IntrinsicKind:
588 if (arguments[2]->type().componentType().isBoolean()) {
589 const SkSL::Type& numericType = arguments[0]->type().componentType();
590
591 if (numericType.isFloat()) {
592 type_check_expression<float>(*arguments[0]);
593 type_check_expression<float>(*arguments[1]);
594 } else if (numericType.isInteger()) {
595 type_check_expression<SKSL_INT>(*arguments[0]);
596 type_check_expression<SKSL_INT>(*arguments[1]);
597 } else if (numericType.isBoolean()) {
598 type_check_expression<bool>(*arguments[0]);
599 type_check_expression<bool>(*arguments[1]);
600 } else {
601 SkDEBUGFAILF("unsupported type %s", numericType.description().c_str());
602 return nullptr;
603 }
604 return evaluate_n_way_intrinsic(context, arguments[0], arguments[1], arguments[2],
605 returnType, Intrinsics::evaluate_mix);
606 } else {
607 return evaluate_3_way_intrinsic(context, arguments, returnType,
608 Intrinsics::evaluate_mix);
609 }
610 case k_step_IntrinsicKind:
611 return evaluate_pairwise_intrinsic(context, arguments, returnType,
612 Intrinsics::evaluate_step);
613 case k_smoothstep_IntrinsicKind:
614 return evaluate_3_way_intrinsic(context, arguments, returnType,
615 Intrinsics::evaluate_smoothstep);
616 case k_trunc_IntrinsicKind:
617 return evaluate_intrinsic<float>(context, arguments, returnType,
618 Intrinsics::evaluate_trunc);
619 case k_round_IntrinsicKind: // GLSL `round` documents its rounding mode as unspecified
620 case k_roundEven_IntrinsicKind: // and is allowed to behave identically to `roundEven`.
621 return evaluate_intrinsic<float>(context, arguments, returnType,
622 Intrinsics::evaluate_round);
623 case k_floatBitsToInt_IntrinsicKind:
624 return evaluate_intrinsic<float>(context, arguments, returnType,
625 Intrinsics::evaluate_floatBitsToInt);
626 case k_floatBitsToUint_IntrinsicKind:
627 return evaluate_intrinsic<float>(context, arguments, returnType,
628 Intrinsics::evaluate_floatBitsToUint);
629 case k_intBitsToFloat_IntrinsicKind:
630 return evaluate_intrinsic<SKSL_INT>(context, arguments, returnType,
631 Intrinsics::evaluate_intBitsToFloat);
632 case k_uintBitsToFloat_IntrinsicKind:
633 return evaluate_intrinsic<SKSL_INT>(context, arguments, returnType,
634 Intrinsics::evaluate_uintBitsToFloat);
635 // 8.4 : Floating-Point Pack and Unpack Functions
636 case k_packUnorm2x16_IntrinsicKind: {
637 auto Pack = [&](int n) -> unsigned int {
638 float x = Get(0, n);
639 return (int)std::round(Intrinsics::evaluate_clamp(x, 0.0, 1.0) * 65535.0);
640 };
641 return UInt(((Pack(0) << 0) & 0x0000FFFF) |
642 ((Pack(1) << 16) & 0xFFFF0000)).release();
643 }
644 case k_packSnorm2x16_IntrinsicKind: {
645 auto Pack = [&](int n) -> unsigned int {
646 float x = Get(0, n);
647 return (int)std::round(Intrinsics::evaluate_clamp(x, -1.0, 1.0) * 32767.0);
648 };
649 return UInt(((Pack(0) << 0) & 0x0000FFFF) |
650 ((Pack(1) << 16) & 0xFFFF0000)).release();
651 }
652 case k_packHalf2x16_IntrinsicKind: {
653 auto Pack = [&](int n) -> unsigned int {
654 return SkFloatToHalf(Get(0, n));
655 };
656 return UInt(((Pack(0) << 0) & 0x0000FFFF) |
657 ((Pack(1) << 16) & 0xFFFF0000)).release();
658 }
659 case k_unpackUnorm2x16_IntrinsicKind: {
660 SKSL_INT x = *arguments[0]->getConstantValue(0);
661 uint16_t a = ((x >> 0) & 0x0000FFFF);
662 uint16_t b = ((x >> 16) & 0x0000FFFF);
663 return Float2(double(a) / 65535.0,
664 double(b) / 65535.0).release();
665 }
666 case k_unpackSnorm2x16_IntrinsicKind: {
667 SKSL_INT x = *arguments[0]->getConstantValue(0);
668 int16_t a = ((x >> 0) & 0x0000FFFF);
669 int16_t b = ((x >> 16) & 0x0000FFFF);
670 return Float2(Intrinsics::evaluate_clamp(double(a) / 32767.0, -1.0, 1.0),
671 Intrinsics::evaluate_clamp(double(b) / 32767.0, -1.0, 1.0)).release();
672 }
673 case k_unpackHalf2x16_IntrinsicKind: {
674 SKSL_INT x = *arguments[0]->getConstantValue(0);
675 uint16_t a = ((x >> 0) & 0x0000FFFF);
676 uint16_t b = ((x >> 16) & 0x0000FFFF);
677 return Float2(SkHalfToFloat(a),
678 SkHalfToFloat(b)).release();
679 }
680 // 8.5 : Geometric Functions
681 case k_length_IntrinsicKind:
682 return coalesce_vector<float>(arguments, /*startingState=*/0, returnType,
683 Intrinsics::coalesce_length,
684 Intrinsics::finalize_length);
685 case k_distance_IntrinsicKind:
686 return coalesce_pairwise_vectors<float>(arguments, /*startingState=*/0, returnType,
687 Intrinsics::coalesce_distance,
688 Intrinsics::finalize_distance);
689 case k_dot_IntrinsicKind:
690 return coalesce_pairwise_vectors<float>(arguments, /*startingState=*/0, returnType,
691 Intrinsics::coalesce_dot,
692 /*finalize=*/nullptr);
693 case k_cross_IntrinsicKind: {
694 auto X = [&](int n) -> float { return Get(0, n); };
695 auto Y = [&](int n) -> float { return Get(1, n); };
696 SkASSERT(arguments[0]->type().columns() == 3); // the vec2 form is not a real intrinsic
697
698 double vec[3] = {X(1) * Y(2) - Y(1) * X(2),
699 X(2) * Y(0) - Y(2) * X(0),
700 X(0) * Y(1) - Y(0) * X(1)};
701 return assemble_compound(context, arguments[0]->fPosition, returnType, vec);
702 }
703 case k_normalize_IntrinsicKind: {
704 auto Vec = [&] { return DSLExpression{arguments[0]->clone()}; };
705 return (Vec() / Length(Vec())).release();
706 }
707 case k_faceforward_IntrinsicKind: {
708 auto N = [&] { return DSLExpression{arguments[0]->clone()}; };
709 auto I = [&] { return DSLExpression{arguments[1]->clone()}; };
710 auto NRef = [&] { return DSLExpression{arguments[2]->clone()}; };
711 return (N() * Select(Dot(NRef(), I()) < 0, 1, -1)).release();
712 }
713 case k_reflect_IntrinsicKind: {
714 auto I = [&] { return DSLExpression{arguments[0]->clone()}; };
715 auto N = [&] { return DSLExpression{arguments[1]->clone()}; };
716 return (I() - 2.0 * Dot(N(), I()) * N()).release();
717 }
718 case k_refract_IntrinsicKind: {
719 // Refract uses its arguments out-of-order in such a way that we end up trying to create
720 // an invalid Position range, so we rewrite the arguments' positions to avoid that here.
721 auto clone = [&](const Expression* expr) {
722 return DSLExpression(expr->clone(pos));
723 };
724 auto I = [&] { return clone(arguments[0]); };
725 auto N = [&] { return clone(arguments[1]); };
726 auto Eta = [&] { return clone(arguments[2]); };
727
728 std::unique_ptr<Expression> k =
729 (1 - Pow(Eta(), 2) * (1 - Pow(Dot(N(), I()), 2))).release();
730 if (!k->is<Literal>()) {
731 return nullptr;
732 }
733 double kValue = k->as<Literal>().value();
734 return ((kValue < 0) ?
735 (0 * I()) :
736 (Eta() * I() - (Eta() * Dot(N(), I()) + std::sqrt(kValue)) * N())).release();
737 }
738
739 // 8.6 : Matrix Functions
740 case k_matrixCompMult_IntrinsicKind:
741 return evaluate_pairwise_intrinsic(context, arguments, returnType,
742 Intrinsics::evaluate_matrixCompMult);
743 case k_transpose_IntrinsicKind: {
744 double mat[16];
745 int index = 0;
746 for (int c = 0; c < returnType.columns(); ++c) {
747 for (int r = 0; r < returnType.rows(); ++r) {
748 mat[index++] = Get(0, (returnType.columns() * r) + c);
749 }
750 }
751 return assemble_compound(context, arguments[0]->fPosition, returnType, mat);
752 }
753 case k_outerProduct_IntrinsicKind: {
754 double mat[16];
755 int index = 0;
756 for (int c = 0; c < returnType.columns(); ++c) {
757 for (int r = 0; r < returnType.rows(); ++r) {
758 mat[index++] = Get(0, r) * Get(1, c);
759 }
760 }
761 return assemble_compound(context, arguments[0]->fPosition, returnType, mat);
762 }
763 case k_determinant_IntrinsicKind: {
764 float mat[16];
765 extract_matrix(arguments[0], mat);
766 float determinant;
767 switch (arguments[0]->type().slotCount()) {
768 case 4:
769 determinant = SkInvert2x2Matrix(mat, /*outMatrix=*/nullptr);
770 break;
771 case 9:
772 determinant = SkInvert3x3Matrix(mat, /*outMatrix=*/nullptr);
773 break;
774 case 16:
775 determinant = SkInvert4x4Matrix(mat, /*outMatrix=*/nullptr);
776 break;
777 default:
778 SkDEBUGFAILF("unsupported type %s", arguments[0]->type().description().c_str());
779 return nullptr;
780 }
781 return Literal::MakeFloat(arguments[0]->fPosition, determinant, &returnType);
782 }
783 case k_inverse_IntrinsicKind: {
784 float mat[16] = {};
785 extract_matrix(arguments[0], mat);
786 switch (arguments[0]->type().slotCount()) {
787 case 4:
788 if (SkInvert2x2Matrix(mat, mat) == 0.0f) {
789 return nullptr;
790 }
791 break;
792 case 9:
793 if (SkInvert3x3Matrix(mat, mat) == 0.0f) {
794 return nullptr;
795 }
796 break;
797 case 16:
798 if (SkInvert4x4Matrix(mat, mat) == 0.0f) {
799 return nullptr;
800 }
801 break;
802 default:
803 SkDEBUGFAILF("unsupported type %s", arguments[0]->type().description().c_str());
804 return nullptr;
805 }
806
807 double dmat[16];
808 std::copy(mat, mat + std::size(mat), dmat);
809 return assemble_compound(context, arguments[0]->fPosition, returnType, dmat);
810 }
811 // 8.7 : Vector Relational Functions
812 case k_lessThan_IntrinsicKind:
813 return optimize_comparison(context, arguments, Intrinsics::compare_lessThan);
814
815 case k_lessThanEqual_IntrinsicKind:
816 return optimize_comparison(context, arguments, Intrinsics::compare_lessThanEqual);
817
818 case k_greaterThan_IntrinsicKind:
819 return optimize_comparison(context, arguments, Intrinsics::compare_greaterThan);
820
821 case k_greaterThanEqual_IntrinsicKind:
822 return optimize_comparison(context, arguments, Intrinsics::compare_greaterThanEqual);
823
824 case k_equal_IntrinsicKind:
825 return optimize_comparison(context, arguments, Intrinsics::compare_equal);
826
827 case k_notEqual_IntrinsicKind:
828 return optimize_comparison(context, arguments, Intrinsics::compare_notEqual);
829
830 case k_any_IntrinsicKind:
831 return coalesce_vector<bool>(arguments, /*startingState=*/false, returnType,
832 Intrinsics::coalesce_any,
833 /*finalize=*/nullptr);
834 case k_all_IntrinsicKind:
835 return coalesce_vector<bool>(arguments, /*startingState=*/true, returnType,
836 Intrinsics::coalesce_all,
837 /*finalize=*/nullptr);
838 case k_not_IntrinsicKind:
839 return evaluate_intrinsic<bool>(context, arguments, returnType,
840 Intrinsics::evaluate_not);
841 default:
842 return nullptr;
843 }
844 }
845
clone(Position pos) const846 std::unique_ptr<Expression> FunctionCall::clone(Position pos) const {
847 return std::make_unique<FunctionCall>(pos, &this->type(), &this->function(),
848 this->arguments().clone());
849 }
850
description(OperatorPrecedence) const851 std::string FunctionCall::description(OperatorPrecedence) const {
852 std::string result = std::string(this->function().name()) + "(";
853 auto separator = SkSL::String::Separator();
854 for (const std::unique_ptr<Expression>& arg : this->arguments()) {
855 result += separator();
856 result += arg->description(OperatorPrecedence::kSequence);
857 }
858 result += ")";
859 return result;
860 }
861
862 /**
863 * Determines the cost of coercing the arguments of a function to the required types. Cost has no
864 * particular meaning other than "lower costs are preferred". Returns CoercionCost::Impossible() if
865 * the call is not valid.
866 */
call_cost(const Context & context,const FunctionDeclaration & function,const ExpressionArray & arguments)867 static CoercionCost call_cost(const Context& context,
868 const FunctionDeclaration& function,
869 const ExpressionArray& arguments) {
870 if (context.fConfig->strictES2Mode() &&
871 (function.modifiers().fFlags & Modifiers::kES3_Flag)) {
872 return CoercionCost::Impossible();
873 }
874 if (function.parameters().size() != SkToSizeT(arguments.size())) {
875 return CoercionCost::Impossible();
876 }
877 FunctionDeclaration::ParamTypes types;
878 const Type* ignored;
879 if (!function.determineFinalTypes(arguments, &types, &ignored)) {
880 return CoercionCost::Impossible();
881 }
882 CoercionCost total = CoercionCost::Free();
883 for (int i = 0; i < arguments.size(); i++) {
884 total = total + arguments[i]->coercionCost(*types[i]);
885 }
886 return total;
887 }
888
FindBestFunctionForCall(const Context & context,const FunctionDeclaration * overloadChain,const ExpressionArray & arguments)889 const FunctionDeclaration* FunctionCall::FindBestFunctionForCall(
890 const Context& context,
891 const FunctionDeclaration* overloadChain,
892 const ExpressionArray& arguments) {
893 if (!overloadChain->nextOverload()) {
894 return overloadChain;
895 }
896 CoercionCost bestCost = CoercionCost::Impossible();
897 const FunctionDeclaration* best = nullptr;
898 for (const FunctionDeclaration* f = overloadChain; f != nullptr; f = f->nextOverload()) {
899 CoercionCost cost = call_cost(context, *f, arguments);
900 if (cost <= bestCost) {
901 bestCost = cost;
902 best = f;
903 }
904 }
905 return bestCost.fImpossible ? nullptr : best;
906 }
907
build_argument_type_list(SkSpan<const std::unique_ptr<Expression>> arguments)908 static std::string build_argument_type_list(SkSpan<const std::unique_ptr<Expression>> arguments) {
909 std::string result = "(";
910 auto separator = SkSL::String::Separator();
911 for (const std::unique_ptr<Expression>& arg : arguments) {
912 result += separator();
913 result += arg->type().displayName();
914 }
915 return result + ")";
916 }
917
Convert(const Context & context,Position pos,std::unique_ptr<Expression> functionValue,ExpressionArray arguments)918 std::unique_ptr<Expression> FunctionCall::Convert(const Context& context,
919 Position pos,
920 std::unique_ptr<Expression> functionValue,
921 ExpressionArray arguments) {
922 switch (functionValue->kind()) {
923 case Expression::Kind::kTypeReference:
924 return Constructor::Convert(context,
925 pos,
926 functionValue->as<TypeReference>().value(),
927 std::move(arguments));
928 case Expression::Kind::kFunctionReference: {
929 const FunctionReference& ref = functionValue->as<FunctionReference>();
930 const FunctionDeclaration* best = FindBestFunctionForCall(context, ref.overloadChain(),
931 arguments);
932 if (best) {
933 return FunctionCall::Convert(context, pos, *best, std::move(arguments));
934 }
935 std::string msg = "no match for " + std::string(ref.overloadChain()->name()) +
936 build_argument_type_list(arguments);
937 context.fErrors->error(pos, msg);
938 return nullptr;
939 }
940 case Expression::Kind::kMethodReference: {
941 MethodReference& ref = functionValue->as<MethodReference>();
942 arguments.push_back(std::move(ref.self()));
943
944 const FunctionDeclaration* best = FindBestFunctionForCall(context, ref.overloadChain(),
945 arguments);
946 if (best) {
947 return FunctionCall::Convert(context, pos, *best, std::move(arguments));
948 }
949 std::string msg =
950 "no match for " + arguments.back()->type().displayName() +
951 "::" + std::string(ref.overloadChain()->name().substr(1)) +
952 build_argument_type_list(SkSpan(arguments).first(arguments.size() - 1));
953 context.fErrors->error(pos, msg);
954 return nullptr;
955 }
956 case Expression::Kind::kPoison:
957 functionValue->fPosition = pos;
958 return functionValue;
959 default:
960 context.fErrors->error(pos, "not a function");
961 return nullptr;
962 }
963 }
964
Convert(const Context & context,Position pos,const FunctionDeclaration & function,ExpressionArray arguments)965 std::unique_ptr<Expression> FunctionCall::Convert(const Context& context,
966 Position pos,
967 const FunctionDeclaration& function,
968 ExpressionArray arguments) {
969 // Reject ES3 function calls in strict ES2 mode.
970 if (context.fConfig->strictES2Mode() && (function.modifiers().fFlags & Modifiers::kES3_Flag)) {
971 context.fErrors->error(pos, "call to '" + function.description() + "' is not supported");
972 return nullptr;
973 }
974
975 // Reject function calls with the wrong number of arguments.
976 if (function.parameters().size() != SkToSizeT(arguments.size())) {
977 std::string msg = "call to '" + std::string(function.name()) + "' expected " +
978 std::to_string(function.parameters().size()) + " argument";
979 if (function.parameters().size() != 1) {
980 msg += "s";
981 }
982 msg += ", but found " + std::to_string(arguments.size());
983 context.fErrors->error(pos, msg);
984 return nullptr;
985 }
986
987 // Resolve generic types.
988 FunctionDeclaration::ParamTypes types;
989 const Type* returnType;
990 if (!function.determineFinalTypes(arguments, &types, &returnType)) {
991 std::string msg = "no match for " + std::string(function.name()) +
992 build_argument_type_list(arguments);
993 context.fErrors->error(pos, msg);
994 return nullptr;
995 }
996
997 for (int i = 0; i < arguments.size(); i++) {
998 // Coerce each argument to the proper type.
999 arguments[i] = types[i]->coerceExpression(std::move(arguments[i]), context);
1000 if (!arguments[i]) {
1001 return nullptr;
1002 }
1003 // Update the refKind on out-parameters, and ensure that they are actually assignable.
1004 const Modifiers& paramModifiers = function.parameters()[i]->modifiers();
1005 if (paramModifiers.fFlags & Modifiers::kOut_Flag) {
1006 const VariableRefKind refKind = paramModifiers.fFlags & Modifiers::kIn_Flag
1007 ? VariableReference::RefKind::kReadWrite
1008 : VariableReference::RefKind::kPointer;
1009 if (!Analysis::UpdateVariableRefKind(arguments[i].get(), refKind, context.fErrors)) {
1010 return nullptr;
1011 }
1012 }
1013 // TODO(skia:13609): Make sure that we don't pass writeonly objects to readonly parameters,
1014 // or vice-versa.
1015 }
1016
1017 if (function.isMain()) {
1018 context.fErrors->error(pos, "call to 'main' is not allowed");
1019 return nullptr;
1020 }
1021
1022 if (function.intrinsicKind() == k_eval_IntrinsicKind) {
1023 // This is a method call on an effect child. Translate it into a ChildCall, which simplifies
1024 // handling in the generators and analysis code.
1025 const Variable& child = *arguments.back()->as<VariableReference>().variable();
1026 arguments.pop_back();
1027 return ChildCall::Make(context, pos, returnType, child, std::move(arguments));
1028 }
1029
1030 return Make(context, pos, returnType, function, std::move(arguments));
1031 }
1032
Make(const Context & context,Position pos,const Type * returnType,const FunctionDeclaration & function,ExpressionArray arguments)1033 std::unique_ptr<Expression> FunctionCall::Make(const Context& context,
1034 Position pos,
1035 const Type* returnType,
1036 const FunctionDeclaration& function,
1037 ExpressionArray arguments) {
1038 SkASSERT(function.parameters().size() == SkToSizeT(arguments.size()));
1039
1040 // We might be able to optimize built-in intrinsics.
1041 if (function.isIntrinsic() && has_compile_time_constant_arguments(arguments)) {
1042 // The function is an intrinsic and all inputs are compile-time constants. Optimize it.
1043 if (std::unique_ptr<Expression> expr = optimize_intrinsic_call(context,
1044 pos,
1045 function.intrinsicKind(),
1046 arguments,
1047 *returnType)) {
1048 expr->fPosition = pos;
1049 return expr;
1050 }
1051 }
1052
1053 return std::make_unique<FunctionCall>(pos, returnType, &function, std::move(arguments));
1054 }
1055
1056 } // namespace SkSL
1057