Flutter Engine
The Flutter Engine
Public Member Functions | Static Public Member Functions | Static Public Attributes | List of all members
SkSL::FunctionCall Class Referencefinal

#include <SkSLFunctionCall.h>

Inheritance diagram for SkSL::FunctionCall:
SkSL::Expression SkSL::IRNode SkSL::Poolable

Public Member Functions

 FunctionCall (Position pos, const Type *type, const FunctionDeclaration *function, ExpressionArray arguments)
 
const FunctionDeclarationfunction () const
 
ExpressionArrayarguments ()
 
const ExpressionArrayarguments () const
 
std::unique_ptr< Expressionclone (Position pos) const override
 
std::string description (OperatorPrecedence) const override
 
- Public Member Functions inherited from SkSL::Expression
 Expression (Position pos, Kind kind, const Type *type)
 
Kind kind () const
 
const Typetype () const
 
bool isAnyConstructor () const
 
bool isIntLiteral () const
 
bool isFloatLiteral () const
 
bool isBoolLiteral () const
 
AnyConstructorasAnyConstructor ()
 
const AnyConstructorasAnyConstructor () const
 
bool isIncomplete (const Context &context) const
 
virtual ComparisonResult compareConstant (const Expression &other) const
 
CoercionCost coercionCost (const Type &target) const
 
virtual bool supportsConstantValues () const
 
virtual std::optional< double > getConstantValue (int n) const
 
virtual std::unique_ptr< Expressionclone (Position pos) const =0
 
std::unique_ptr< Expressionclone () const
 
std::string description () const final
 
virtual std::string description (OperatorPrecedence parentPrecedence) const =0
 
- Public Member Functions inherited from SkSL::IRNode
virtual ~IRNode ()
 
virtual std::string description () const =0
 
 IRNode (const IRNode &)=delete
 
IRNodeoperator= (const IRNode &)=delete
 
Position position () const
 
void setPosition (Position p)
 
template<typename T >
bool is () const
 
template<typename T >
const Tas () const
 
template<typename T >
Tas ()
 

Static Public Member Functions

static std::unique_ptr< ExpressionConvert (const Context &context, Position pos, const FunctionDeclaration &function, ExpressionArray arguments)
 
static std::unique_ptr< ExpressionConvert (const Context &context, Position pos, std::unique_ptr< Expression > functionValue, ExpressionArray arguments)
 
static std::unique_ptr< ExpressionMake (const Context &context, Position pos, const Type *returnType, const FunctionDeclaration &function, ExpressionArray arguments)
 
static const FunctionDeclarationFindBestFunctionForCall (const Context &context, const FunctionDeclaration *overloads, const ExpressionArray &arguments)
 
- Static Public Member Functions inherited from SkSL::Poolable
static void * operator new (const size_t size)
 
static void operator delete (void *ptr)
 

Static Public Attributes

static constexpr Kind kIRNodeKind = Kind::kFunctionCall
 

Additional Inherited Members

- Public Types inherited from SkSL::Expression
enum class  ComparisonResult { kUnknown = -1 , kNotEqual , kEqual }
 
using Kind = ExpressionKind
 
- Public Attributes inherited from SkSL::IRNode
Position fPosition
 
- Protected Member Functions inherited from SkSL::IRNode
 IRNode (Position position, int kind)
 
- Protected Attributes inherited from SkSL::IRNode
int fKind
 

Detailed Description

A function invocation.

Definition at line 31 of file SkSLFunctionCall.h.

Constructor & Destructor Documentation

◆ FunctionCall()

SkSL::FunctionCall::FunctionCall ( Position  pos,
const Type type,
const FunctionDeclaration function,
ExpressionArray  arguments 
)
inline

Definition at line 35 of file SkSLFunctionCall.h.

37 : INHERITED(pos, kIRNodeKind, type)
38 , fFunction(*function)
39 , fArguments(std::move(arguments)) {}
SkPoint pos
const Type & type() const
static constexpr Kind kIRNodeKind
ExpressionArray & arguments()
const FunctionDeclaration & function() const

Member Function Documentation

◆ arguments() [1/2]

ExpressionArray & SkSL::FunctionCall::arguments ( )
inline

Definition at line 68 of file SkSLFunctionCall.h.

68 {
69 return fArguments;
70 }

◆ arguments() [2/2]

const ExpressionArray & SkSL::FunctionCall::arguments ( ) const
inline

Definition at line 72 of file SkSLFunctionCall.h.

72 {
73 return fArguments;
74 }

◆ clone()

std::unique_ptr< Expression > SkSL::FunctionCall::clone ( Position  pos) const
overridevirtual

Implements SkSL::Expression.

Definition at line 1005 of file SkSLFunctionCall.cpp.

1005 {
1006 return std::make_unique<FunctionCall>(pos, &this->type(), &this->function(),
1007 this->arguments().clone());
1008}
std::unique_ptr< Expression > clone() const

◆ Convert() [1/2]

std::unique_ptr< Expression > SkSL::FunctionCall::Convert ( const Context context,
Position  pos,
const FunctionDeclaration function,
ExpressionArray  arguments 
)
static

Definition at line 1164 of file SkSLFunctionCall.cpp.

1167 {
1168 // Reject ES3 function calls in strict ES2 mode.
1169 if (context.fConfig->strictES2Mode() && function.modifierFlags().isES3()) {
1170 context.fErrors->error(pos, "call to '" + function.description() + "' is not supported");
1171 return nullptr;
1172 }
1173
1174 // Reject function calls with the wrong number of arguments.
1175 if (function.parameters().size() != SkToSizeT(arguments.size())) {
1176 std::string msg = "call to '" + std::string(function.name()) + "' expected " +
1177 std::to_string(function.parameters().size()) + " argument";
1178 if (function.parameters().size() != 1) {
1179 msg += "s";
1180 }
1181 msg += ", but found " + std::to_string(arguments.size());
1182 context.fErrors->error(pos, msg);
1183 return nullptr;
1184 }
1185
1186 // If the arguments do not match the parameter types due to mismatched modifiers, reject the
1187 // function call.
1188 for (int i = 0; i < arguments.size(); i++) {
1189 const Expression& arg = *arguments[i];
1190 const Variable& param = *function.parameters()[i];
1191 if (!argument_and_parameter_flags_match(arg, param)) {
1192 context.fErrors->error(arg.position(), "expected argument of type '" +
1193 param.layout().paddedDescription() +
1194 param.modifierFlags().paddedDescription() +
1195 param.type().description() + "'");
1196 return nullptr;
1197 }
1198 }
1199
1200 // Resolve generic types.
1202 const Type* returnType;
1203 if (!function.determineFinalTypes(arguments, &types, &returnType)) {
1204 std::string msg = "no match for " + std::string(function.name()) +
1206 context.fErrors->error(pos, msg);
1207 return nullptr;
1208 }
1209
1210 for (int i = 0; i < arguments.size(); i++) {
1211 // Coerce each argument to the proper type.
1212 arguments[i] = types[i]->coerceExpression(std::move(arguments[i]), context);
1213 if (!arguments[i]) {
1214 return nullptr;
1215 }
1216 // Update the refKind on out-parameters, and ensure that they are actually assignable.
1217 ModifierFlags paramFlags = function.parameters()[i]->modifierFlags();
1218 if (paramFlags & ModifierFlag::kOut) {
1219 const VariableRefKind refKind = (paramFlags & ModifierFlag::kIn)
1221 : VariableReference::RefKind::kPointer;
1222 if (!Analysis::UpdateVariableRefKind(arguments[i].get(), refKind, context.fErrors)) {
1223 return nullptr;
1224 }
1225 }
1226 }
1227
1228 if (function.isMain()) {
1229 context.fErrors->error(pos, "call to 'main' is not allowed");
1230 return nullptr;
1231 }
1232
1233 if (function.intrinsicKind() == k_eval_IntrinsicKind) {
1234 // This is a method call on an effect child. Translate it into a ChildCall, which simplifies
1235 // handling in the generators and analysis code.
1236 const Variable& child = *arguments.back()->as<VariableReference>().variable();
1238 return ChildCall::Make(context, pos, returnType, child, std::move(arguments));
1239 }
1240
1241 return Make(context, pos, returnType, function, std::move(arguments));
1242}
constexpr size_t SkToSizeT(S x)
Definition: SkTo.h:31
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type *returnType, const Variable &child, ExpressionArray arguments)
Expression(Position pos, Kind kind, const Type *type)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type *returnType, const FunctionDeclaration &function, ExpressionArray arguments)
bool determineFinalTypes(const ExpressionArray &arguments, ParamTypes *outParameterTypes, const Type **outReturnType) const
SkSpan< Variable *const > parameters() const
skia_private::STArray< 8, const Type * > ParamTypes
std::string description() const override
ModifierFlags modifierFlags() const
IntrinsicKind intrinsicKind() const
std::string_view name() const
Definition: SkSLSymbol.h:51
int size() const
Definition: SkTArray.h:421
bool UpdateVariableRefKind(Expression *expr, VariableRefKind kind, ErrorReporter *errors=nullptr)
static std::string build_argument_type_list(SkSpan< const std::unique_ptr< Expression > > arguments)
static bool argument_and_parameter_flags_match(const Expression &argument, const Variable &parameter)
const myers::Point & get(const myers::Segment &)
static SkString to_string(int n)
Definition: nanobench.cpp:119

◆ Convert() [2/2]

std::unique_ptr< Expression > SkSL::FunctionCall::Convert ( const Context context,
Position  pos,
std::unique_ptr< Expression functionValue,
ExpressionArray  arguments 
)
static

Definition at line 1117 of file SkSLFunctionCall.cpp.

1120 {
1121 switch (functionValue->kind()) {
1122 case Expression::Kind::kTypeReference:
1123 return Constructor::Convert(context,
1124 pos,
1125 functionValue->as<TypeReference>().value(),
1126 std::move(arguments));
1127 case Expression::Kind::kFunctionReference: {
1128 const FunctionReference& ref = functionValue->as<FunctionReference>();
1129 const FunctionDeclaration* best = FindBestFunctionForCall(context, ref.overloadChain(),
1130 arguments);
1131 if (best) {
1132 return FunctionCall::Convert(context, pos, *best, std::move(arguments));
1133 }
1134 std::string msg = "no match for " + std::string(ref.overloadChain()->name()) +
1136 context.fErrors->error(pos, msg);
1137 return nullptr;
1138 }
1139 case Expression::Kind::kMethodReference: {
1140 MethodReference& ref = functionValue->as<MethodReference>();
1141 arguments.push_back(std::move(ref.self()));
1142
1143 const FunctionDeclaration* best = FindBestFunctionForCall(context, ref.overloadChain(),
1144 arguments);
1145 if (best) {
1146 return FunctionCall::Convert(context, pos, *best, std::move(arguments));
1147 }
1148 std::string msg =
1149 "no match for " + arguments.back()->type().displayName() +
1150 "::" + std::string(ref.overloadChain()->name().substr(1)) +
1152 context.fErrors->error(pos, msg);
1153 return nullptr;
1154 }
1155 case Expression::Kind::kPoison:
1156 functionValue->fPosition = pos;
1157 return functionValue;
1158 default:
1159 context.fErrors->error(pos, "not a function");
1160 return nullptr;
1161 }
1162}
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
static std::unique_ptr< Expression > Convert(const Context &context, Position pos, const FunctionDeclaration &function, ExpressionArray arguments)
static const FunctionDeclaration * FindBestFunctionForCall(const Context &context, const FunctionDeclaration *overloads, const ExpressionArray &arguments)
std::unique_ptr< Expression > Convert(const Context &context, Position pos, const Type &type, ExpressionArray args)

◆ description()

std::string SkSL::FunctionCall::description ( OperatorPrecedence  ) const
overridevirtual

Implements SkSL::Expression.

Definition at line 1010 of file SkSLFunctionCall.cpp.

1010 {
1011 std::string result = std::string(this->function().name()) + "(";
1012 auto separator = SkSL::String::Separator();
1013 for (const std::unique_ptr<Expression>& arg : this->arguments()) {
1014 result += separator();
1015 result += arg->description(OperatorPrecedence::kSequence);
1016 }
1017 result += ")";
1018 return result;
1019}
GAsyncResult * result
std::string void void auto Separator()
Definition: SkSLString.h:30
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32

◆ FindBestFunctionForCall()

const FunctionDeclaration * SkSL::FunctionCall::FindBestFunctionForCall ( const Context context,
const FunctionDeclaration overloads,
const ExpressionArray arguments 
)
static

Definition at line 1088 of file SkSLFunctionCall.cpp.

1091 {
1092 if (!overloadChain->nextOverload()) {
1093 return overloadChain;
1094 }
1095 CoercionCost bestCost = CoercionCost::Impossible();
1096 const FunctionDeclaration* best = nullptr;
1097 for (const FunctionDeclaration* f = overloadChain; f != nullptr; f = f->nextOverload()) {
1098 CoercionCost cost = call_cost(context, *f, arguments);
1099 if (cost <= bestCost) {
1100 bestCost = cost;
1101 best = f;
1102 }
1103 }
1104 return bestCost.fImpossible ? nullptr : best;
1105}
static CoercionCost call_cost(const Context &context, const FunctionDeclaration &function, const ExpressionArray &arguments)
static CoercionCost Impossible()
Definition: SkSLType.h:42

◆ function()

const FunctionDeclaration & SkSL::FunctionCall::function ( ) const
inline

Definition at line 64 of file SkSLFunctionCall.h.

64 {
65 return fFunction;
66 }

◆ Make()

std::unique_ptr< Expression > SkSL::FunctionCall::Make ( const Context context,
Position  pos,
const Type returnType,
const FunctionDeclaration function,
ExpressionArray  arguments 
)
static

Definition at line 1244 of file SkSLFunctionCall.cpp.

1248 {
1250
1251 // We might be able to optimize built-in intrinsics.
1253 // The function is an intrinsic and all inputs are compile-time constants. Optimize it.
1254 if (std::unique_ptr<Expression> expr = optimize_intrinsic_call(context,
1255 pos,
1257 arguments,
1258 *returnType)) {
1259 expr->fPosition = pos;
1260 return expr;
1261 }
1262 }
1263
1264 return std::make_unique<FunctionCall>(pos, returnType, &function, std::move(arguments));
1265}
#define SkASSERT(cond)
Definition: SkAssert.h:116
static bool has_compile_time_constant_arguments(const ExpressionArray &arguments)
static std::unique_ptr< Expression > optimize_intrinsic_call(const Context &context, Position pos, IntrinsicKind intrinsic, const ExpressionArray &argArray, const Type &returnType)

Member Data Documentation

◆ kIRNodeKind

constexpr Kind SkSL::FunctionCall::kIRNodeKind = Kind::kFunctionCall
inlinestaticconstexpr

Definition at line 33 of file SkSLFunctionCall.h.


The documentation for this class was generated from the following files: