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