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

#include <SkSLFunctionDeclaration.h>

Inheritance diagram for SkSL::FunctionDeclaration:
SkSL::Symbol SkSL::IRNode SkSL::Poolable

Public Types

using ParamTypes = skia_private::STArray< 8, const Type * >
 
- Public Types inherited from SkSL::Symbol
using Kind = SymbolKind
 

Public Member Functions

 FunctionDeclaration (const Context &context, Position pos, ModifierFlags modifierFlags, std::string_view name, skia_private::TArray< Variable * > parameters, const Type *returnType, IntrinsicKind intrinsicKind)
 
ModifierFlags modifierFlags () const
 
void setModifierFlags (ModifierFlags m)
 
const FunctionDefinitiondefinition () const
 
void setDefinition (const FunctionDefinition *definition)
 
void setNextOverload (FunctionDeclaration *overload)
 
SkSpan< Variable *const > parameters () const
 
const TypereturnType () const
 
bool isBuiltin () const
 
bool isMain () const
 
IntrinsicKind intrinsicKind () const
 
bool isIntrinsic () const
 
const FunctionDeclarationnextOverload () const
 
FunctionDeclarationmutableNextOverload () const
 
std::string mangledName () const
 
std::string description () const override
 
bool matches (const FunctionDeclaration &f) const
 
const VariablegetMainCoordsParameter () const
 
const VariablegetMainInputColorParameter () const
 
const VariablegetMainDestColorParameter () const
 
bool determineFinalTypes (const ExpressionArray &arguments, ParamTypes *outParameterTypes, const Type **outReturnType) const
 
- Public Member Functions inherited from SkSL::Symbol
 Symbol (Position pos, Kind kind, std::string_view name, const Type *type=nullptr)
 
 ~Symbol () override
 
std::unique_ptr< Expressioninstantiate (const Context &context, Position pos) const
 
const Typetype () const
 
Kind kind () const
 
std::string_view name () const
 
void setName (std::string_view newName)
 
- 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 FunctionDeclarationConvert (const Context &context, Position pos, const Modifiers &modifiers, std::string_view name, skia_private::TArray< std::unique_ptr< Variable > > parameters, Position returnTypePos, const Type *returnType)
 
- 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::kFunctionDeclaration
 

Additional Inherited Members

- 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 declaration (not a definition – does not contain a body).

Definition at line 36 of file SkSLFunctionDeclaration.h.

Member Typedef Documentation

◆ ParamTypes

Determine the effective types of this function's parameters and return value when called with the given arguments. This is relevant for functions with generic parameter types, where this will collapse the generic types down into specific concrete types.

Returns true if it was able to select a concrete set of types for the generic function, false if there is no possible way this can match the argument types. Note that even a true return does not guarantee that the function can be successfully called with those arguments, merely indicates that an attempt should be made. If false is returned, the state of outParameterTypes and outReturnType are undefined.

This always assumes narrowing conversions are allowed. The calling code needs to verify that each argument can actually be coerced to the final parameter type, respecting the narrowing-conversions flag. This is handled in callCost(), or in convertCall() (via coerce).

Definition at line 147 of file SkSLFunctionDeclaration.h.

Constructor & Destructor Documentation

◆ FunctionDeclaration()

SkSL::FunctionDeclaration::FunctionDeclaration ( const Context context,
Position  pos,
ModifierFlags  modifierFlags,
std::string_view  name,
skia_private::TArray< Variable * >  parameters,
const Type returnType,
IntrinsicKind  intrinsicKind 
)

Definition at line 415 of file SkSLFunctionDeclaration.cpp.

422 : INHERITED(pos, kIRNodeKind, name, /*type=*/nullptr)
423 , fDefinition(nullptr)
424 , fParameters(std::move(parameters))
425 , fReturnType(returnType)
426 , fModifierFlags(modifierFlags)
427 , fIntrinsicKind(intrinsicKind)
428 , fBuiltin(context.fConfig->fIsBuiltinCode)
429 , fIsMain(name == "main") {
430 int builtinColorIndex = 0;
431 for (const Variable* param : fParameters) {
432 // None of the parameters are allowed to be be null.
433 SkASSERT(param);
434
435 // Keep track of arguments to main for runtime effects.
436 if (fIsMain) {
437 if (ProgramConfig::IsRuntimeShader(context.fConfig->fKind) ||
438 ProgramConfig::IsFragment(context.fConfig->fKind)) {
439 // If this is a runtime shader, a float2 param is supposed to be the coords.
440 // For testing purposes, we have .sksl inputs that are treated as both runtime
441 // effects and fragment shaders. To make that work, fragment shaders are allowed to
442 // have a coords parameter as well.
443 if (type_is_valid_for_coords(param->type())) {
444 fHasMainCoordsParameter = true;
445 }
446 } else if (ProgramConfig::IsRuntimeColorFilter(context.fConfig->fKind) ||
447 ProgramConfig::IsRuntimeBlender(context.fConfig->fKind)) {
448 // If this is a runtime color filter or blender, the params are an input color,
449 // followed by a destination color for blenders.
450 if (type_is_valid_for_color(param->type())) {
451 switch (builtinColorIndex++) {
452 case 0: fHasMainInputColorParameter = true; break;
453 case 1: fHasMainDestColorParameter = true; break;
454 default: /* unknown color parameter */ break;
455 }
456 }
457 }
458 }
459 }
460}
SkPoint pos
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkSpan< Variable *const > parameters() const
static constexpr Kind kIRNodeKind
ModifierFlags modifierFlags() const
IntrinsicKind intrinsicKind() const
std::string_view name() const
Definition: SkSLSymbol.h:51
static bool type_is_valid_for_coords(const Type &type)
static bool type_is_valid_for_color(const Type &type)
static bool IsRuntimeShader(ProgramKind kind)
static bool IsFragment(ProgramKind kind)
static bool IsRuntimeBlender(ProgramKind kind)
static bool IsRuntimeColorFilter(ProgramKind kind)

Member Function Documentation

◆ Convert()

FunctionDeclaration * SkSL::FunctionDeclaration::Convert ( const Context context,
Position  pos,
const Modifiers modifiers,
std::string_view  name,
skia_private::TArray< std::unique_ptr< Variable > >  parameters,
Position  returnTypePos,
const Type returnType 
)
static

Definition at line 462 of file SkSLFunctionDeclaration.cpp.

468 {
469 // No layout flag is permissible on a function.
470 modifiers.fLayout.checkPermittedLayout(context, pos,
471 /*permittedLayoutFlags=*/LayoutFlag::kNone);
472
473 // If requested, apply the `noinline` modifier to every function. This allows us to test Runtime
474 // Effects without any inlining, even when the code is later added to a paint.
475 ModifierFlags modifierFlags = modifiers.fFlags;
476 if (context.fConfig->fSettings.fForceNoInline) {
477 modifierFlags &= ~ModifierFlag::kInline;
479 }
480
481 bool isMain = (name == "main");
482 IntrinsicKind intrinsicKind = context.fConfig->fIsBuiltinCode ? FindIntrinsicKind(name)
484 FunctionDeclaration* decl = nullptr;
485 if (!check_modifiers(context, modifiers.fPosition, modifierFlags) ||
486 !check_return_type(context, returnTypePos, *returnType) ||
490 returnTypePos, returnType, &decl)) {
491 return nullptr;
492 }
493 TArray<Variable*> finalParameters;
494 finalParameters.reserve_exact(parameters.size());
495 for (std::unique_ptr<Variable>& param : parameters) {
496 finalParameters.push_back(context.fSymbolTable->takeOwnershipOfSymbol(std::move(param)));
497 }
498 if (decl) {
499 return decl;
500 }
501 return context.fSymbolTable->add(
502 context,
503 std::make_unique<FunctionDeclaration>(context,
504 pos,
506 name,
507 std::move(finalParameters),
510}
FunctionDeclaration(const Context &context, Position pos, ModifierFlags modifierFlags, std::string_view name, skia_private::TArray< Variable * > parameters, const Type *returnType, IntrinsicKind intrinsicKind)
void reserve_exact(int n)
Definition: SkTArray.h:181
ModifierFlag
static bool find_existing_declaration(const Context &context, Position pos, ModifierFlags modifierFlags, IntrinsicKind intrinsicKind, std::string_view name, TArray< std::unique_ptr< Variable > > &parameters, Position returnTypePos, const Type *returnType, FunctionDeclaration **outExistingDecl)
static bool check_modifiers(const Context &context, Position pos, ModifierFlags modifierFlags)
static bool check_main_signature(const Context &context, Position pos, const Type &returnType, TArray< std::unique_ptr< Variable > > &parameters)
IntrinsicKind FindIntrinsicKind(std::string_view functionName)
static bool check_return_type(const Context &context, Position pos, const Type &returnType)
static bool check_parameters(const Context &context, TArray< std::unique_ptr< Variable > > &parameters, ModifierFlags modifierFlags, IntrinsicKind intrinsicKind)

◆ definition()

const FunctionDefinition * SkSL::FunctionDeclaration::definition ( ) const
inline

Definition at line 64 of file SkSLFunctionDeclaration.h.

64 {
65 return fDefinition;
66 }

◆ description()

std::string SkSL::FunctionDeclaration::description ( ) const
overridevirtual

Implements SkSL::IRNode.

Definition at line 534 of file SkSLFunctionDeclaration.cpp.

534 {
535 std::string result = (fModifierFlags ? fModifierFlags.description() + " " : std::string()) +
536 this->returnType().displayName() + " " + std::string(this->name()) + "(";
537 auto separator = SkSL::String::Separator();
538 for (const Variable* p : this->parameters()) {
539 result += separator();
540 result += p->description();
541 }
542 result += ")";
543 return result;
544}
std::string description() const
std::string displayName() const
Definition: SkSLType.h:234
GAsyncResult * result
std::string void void auto Separator()
Definition: SkSLString.h:30

◆ determineFinalTypes()

bool SkSL::FunctionDeclaration::determineFinalTypes ( const ExpressionArray arguments,
ParamTypes outParameterTypes,
const Type **  outReturnType 
) const

Definition at line 563 of file SkSLFunctionDeclaration.cpp.

565 {
567 SkASSERT(SkToSizeT(arguments.size()) == parameters.size());
568
569 outParameterTypes->reserve_exact(arguments.size());
570 int genericIndex = -1;
571 for (int i = 0; i < arguments.size(); i++) {
572 // Non-generic parameters are final as-is.
573 const Type& parameterType = parameters[i]->type();
574 if (!parameterType.isGeneric()) {
575 outParameterTypes->push_back(&parameterType);
576 continue;
577 }
578 // We use the first generic parameter we find to lock in the generic index;
579 // e.g. if we find `float3` here, all `$genType`s will be assumed to be `float3`.
580 if (genericIndex == -1) {
581 genericIndex = find_generic_index(arguments[i]->type(), parameterType,
582 /*allowNarrowing=*/true);
583 if (genericIndex == -1) {
584 // The passed-in type wasn't a match for ANY of the generic possibilities.
585 // This function isn't a match at all.
586 return false;
587 }
588 }
589 outParameterTypes->push_back(parameterType.coercibleTypes()[genericIndex]);
590 }
591 // Apply the generic index to our return type.
592 const Type& returnType = this->returnType();
593 if (returnType.isGeneric()) {
594 if (genericIndex == -1) {
595 // We don't support functions with a generic return type and no other generics.
596 return false;
597 }
598 *outReturnType = returnType.coercibleTypes()[genericIndex];
599 } else {
600 *outReturnType = &returnType;
601 }
602 return true;
603}
constexpr size_t SkToSizeT(S x)
Definition: SkTo.h:31
const Type & type() const
Definition: SkSLSymbol.h:42
virtual SkSpan< const Type *const > coercibleTypes() const
Definition: SkSLType.h:476
static int find_generic_index(const Type &concreteType, const Type &genericType, bool allowNarrowing)

◆ getMainCoordsParameter()

const Variable * SkSL::FunctionDeclaration::getMainCoordsParameter ( ) const
inline

If this function is main(), and it has the requested parameter, returns that parameter. For instance, only a runtime-blend program will have a dest-color parameter, in parameter 1; getMainDestColorParameter will return that parameter if this is a runtime-blend main() function. Otherwise, null is returned.

Definition at line 122 of file SkSLFunctionDeclaration.h.

122 {
123 return fHasMainCoordsParameter ? fParameters[0] : nullptr;
124 }

◆ getMainDestColorParameter()

const Variable * SkSL::FunctionDeclaration::getMainDestColorParameter ( ) const
inline

Definition at line 128 of file SkSLFunctionDeclaration.h.

128 {
129 return fHasMainDestColorParameter ? fParameters[1] : nullptr;
130 }

◆ getMainInputColorParameter()

const Variable * SkSL::FunctionDeclaration::getMainInputColorParameter ( ) const
inline

Definition at line 125 of file SkSLFunctionDeclaration.h.

125 {
126 return fHasMainInputColorParameter ? fParameters[0] : nullptr;
127 }

◆ intrinsicKind()

IntrinsicKind SkSL::FunctionDeclaration::intrinsicKind ( ) const
inline

Definition at line 94 of file SkSLFunctionDeclaration.h.

94 {
95 return fIntrinsicKind;
96 }

◆ isBuiltin()

bool SkSL::FunctionDeclaration::isBuiltin ( ) const
inline

Definition at line 86 of file SkSLFunctionDeclaration.h.

86 {
87 return fBuiltin;
88 }

◆ isIntrinsic()

bool SkSL::FunctionDeclaration::isIntrinsic ( ) const
inline

Definition at line 98 of file SkSLFunctionDeclaration.h.

98 {
99 return this->intrinsicKind() != kNotIntrinsic;
100 }

◆ isMain()

bool SkSL::FunctionDeclaration::isMain ( ) const
inline

Definition at line 90 of file SkSLFunctionDeclaration.h.

90 {
91 return fIsMain;
92 }

◆ mangledName()

std::string SkSL::FunctionDeclaration::mangledName ( ) const

Definition at line 512 of file SkSLFunctionDeclaration.cpp.

512 {
513 if ((this->isBuiltin() && !this->definition()) || this->isMain()) {
514 // Builtins without a definition (like `sin` or `sqrt`) must use their real names.
515 return std::string(this->name());
516 }
517 // Built-in functions can have a $ prefix, which will fail to compile in GLSL. Remove the
518 // $ and add a unique mangling specifier, so user code can't conflict with the name.
519 std::string_view name = this->name();
520 const char* builtinMarker = "";
521 if (skstd::starts_with(name, '$')) {
522 name.remove_prefix(1);
523 builtinMarker = "Q"; // a unique, otherwise-unused mangle character
524 }
525 // Rename function to `funcname_returntypeparamtypes`.
526 std::string result = std::string(name) + "_" + builtinMarker +
527 this->returnType().abbreviatedName();
528 for (const Variable* p : this->parameters()) {
529 result += p->type().abbreviatedName();
530 }
531 return result;
532}
const FunctionDefinition * definition() const
const char * abbreviatedName() const
Definition: SkSLType.h:276
constexpr bool starts_with(std::string_view str, std::string_view prefix)
Definition: SkStringView.h:17

◆ matches()

bool SkSL::FunctionDeclaration::matches ( const FunctionDeclaration f) const

Definition at line 546 of file SkSLFunctionDeclaration.cpp.

546 {
547 if (this->name() != f.name()) {
548 return false;
549 }
551 SkSpan<Variable* const> otherParameters = f.parameters();
552 if (parameters.size() != otherParameters.size()) {
553 return false;
554 }
555 for (size_t i = 0; i < parameters.size(); i++) {
556 if (!parameters[i]->type().matches(otherParameters[i]->type())) {
557 return false;
558 }
559 }
560 return true;
561}
bool matches(const FunctionDeclaration &f) const
constexpr size_t size() const
Definition: SkSpan_impl.h:95

◆ modifierFlags()

ModifierFlags SkSL::FunctionDeclaration::modifierFlags ( ) const
inline

Definition at line 56 of file SkSLFunctionDeclaration.h.

56 {
57 return fModifierFlags;
58 }

◆ mutableNextOverload()

FunctionDeclaration * SkSL::FunctionDeclaration::mutableNextOverload ( ) const
inline

Definition at line 106 of file SkSLFunctionDeclaration.h.

106 {
107 return fNextOverload;
108 }

◆ nextOverload()

const FunctionDeclaration * SkSL::FunctionDeclaration::nextOverload ( ) const
inline

Definition at line 102 of file SkSLFunctionDeclaration.h.

102 {
103 return fNextOverload;
104 }

◆ parameters()

SkSpan< Variable *const > SkSL::FunctionDeclaration::parameters ( ) const
inline

Definition at line 78 of file SkSLFunctionDeclaration.h.

78 {
79 return fParameters;
80 }

◆ returnType()

const Type & SkSL::FunctionDeclaration::returnType ( ) const
inline

Definition at line 82 of file SkSLFunctionDeclaration.h.

82 {
83 return *fReturnType;
84 }

◆ setDefinition()

void SkSL::FunctionDeclaration::setDefinition ( const FunctionDefinition definition)
inline

Definition at line 68 of file SkSLFunctionDeclaration.h.

68 {
69 fDefinition = definition;
70 fIntrinsicKind = kNotIntrinsic;
71 }

◆ setModifierFlags()

void SkSL::FunctionDeclaration::setModifierFlags ( ModifierFlags  m)
inline

Definition at line 60 of file SkSLFunctionDeclaration.h.

60 {
61 fModifierFlags = m;
62 }

◆ setNextOverload()

void SkSL::FunctionDeclaration::setNextOverload ( FunctionDeclaration overload)
inline

Definition at line 73 of file SkSLFunctionDeclaration.h.

73 {
74 SkASSERT(!overload || overload->name() == this->name());
75 fNextOverload = overload;
76 }

Member Data Documentation

◆ kIRNodeKind

constexpr Kind SkSL::FunctionDeclaration::kIRNodeKind = Kind::kFunctionDeclaration
inlinestaticconstexpr

Definition at line 38 of file SkSLFunctionDeclaration.h.


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