1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2016 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SKSL_FUNCTIONDECLARATION 9*c8dee2aaSAndroid Build Coastguard Worker #define SKSL_FUNCTIONDECLARATION 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSpan.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLIntrinsicList.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLModule.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLIRNode.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLModifierFlags.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLSymbol.h" 19*c8dee2aaSAndroid Build Coastguard Worker 20*c8dee2aaSAndroid Build Coastguard Worker #include <memory> 21*c8dee2aaSAndroid Build Coastguard Worker #include <string> 22*c8dee2aaSAndroid Build Coastguard Worker #include <string_view> 23*c8dee2aaSAndroid Build Coastguard Worker 24*c8dee2aaSAndroid Build Coastguard Worker namespace SkSL { 25*c8dee2aaSAndroid Build Coastguard Worker 26*c8dee2aaSAndroid Build Coastguard Worker class Context; 27*c8dee2aaSAndroid Build Coastguard Worker class ExpressionArray; 28*c8dee2aaSAndroid Build Coastguard Worker class FunctionDefinition; 29*c8dee2aaSAndroid Build Coastguard Worker struct Modifiers; 30*c8dee2aaSAndroid Build Coastguard Worker class Position; 31*c8dee2aaSAndroid Build Coastguard Worker class Type; 32*c8dee2aaSAndroid Build Coastguard Worker class Variable; 33*c8dee2aaSAndroid Build Coastguard Worker 34*c8dee2aaSAndroid Build Coastguard Worker /** 35*c8dee2aaSAndroid Build Coastguard Worker * A function declaration (not a definition -- does not contain a body). 36*c8dee2aaSAndroid Build Coastguard Worker */ 37*c8dee2aaSAndroid Build Coastguard Worker class FunctionDeclaration final : public Symbol { 38*c8dee2aaSAndroid Build Coastguard Worker public: 39*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr Kind kIRNodeKind = Kind::kFunctionDeclaration; 40*c8dee2aaSAndroid Build Coastguard Worker 41*c8dee2aaSAndroid Build Coastguard Worker FunctionDeclaration(const Context& context, 42*c8dee2aaSAndroid Build Coastguard Worker Position pos, 43*c8dee2aaSAndroid Build Coastguard Worker ModifierFlags modifierFlags, 44*c8dee2aaSAndroid Build Coastguard Worker std::string_view name, 45*c8dee2aaSAndroid Build Coastguard Worker skia_private::TArray<Variable*> parameters, 46*c8dee2aaSAndroid Build Coastguard Worker const Type* returnType, 47*c8dee2aaSAndroid Build Coastguard Worker IntrinsicKind intrinsicKind); 48*c8dee2aaSAndroid Build Coastguard Worker 49*c8dee2aaSAndroid Build Coastguard Worker static FunctionDeclaration* Convert(const Context& context, 50*c8dee2aaSAndroid Build Coastguard Worker Position pos, 51*c8dee2aaSAndroid Build Coastguard Worker const Modifiers& modifiers, 52*c8dee2aaSAndroid Build Coastguard Worker std::string_view name, 53*c8dee2aaSAndroid Build Coastguard Worker skia_private::TArray<std::unique_ptr<Variable>> parameters, 54*c8dee2aaSAndroid Build Coastguard Worker Position returnTypePos, 55*c8dee2aaSAndroid Build Coastguard Worker const Type* returnType); 56*c8dee2aaSAndroid Build Coastguard Worker modifierFlags()57*c8dee2aaSAndroid Build Coastguard Worker ModifierFlags modifierFlags() const { 58*c8dee2aaSAndroid Build Coastguard Worker return fModifierFlags; 59*c8dee2aaSAndroid Build Coastguard Worker } 60*c8dee2aaSAndroid Build Coastguard Worker setModifierFlags(ModifierFlags m)61*c8dee2aaSAndroid Build Coastguard Worker void setModifierFlags(ModifierFlags m) { 62*c8dee2aaSAndroid Build Coastguard Worker fModifierFlags = m; 63*c8dee2aaSAndroid Build Coastguard Worker } 64*c8dee2aaSAndroid Build Coastguard Worker definition()65*c8dee2aaSAndroid Build Coastguard Worker const FunctionDefinition* definition() const { 66*c8dee2aaSAndroid Build Coastguard Worker return fDefinition; 67*c8dee2aaSAndroid Build Coastguard Worker } 68*c8dee2aaSAndroid Build Coastguard Worker setDefinition(const FunctionDefinition * definition)69*c8dee2aaSAndroid Build Coastguard Worker void setDefinition(const FunctionDefinition* definition) { 70*c8dee2aaSAndroid Build Coastguard Worker fDefinition = definition; 71*c8dee2aaSAndroid Build Coastguard Worker fIntrinsicKind = kNotIntrinsic; 72*c8dee2aaSAndroid Build Coastguard Worker } 73*c8dee2aaSAndroid Build Coastguard Worker setNextOverload(FunctionDeclaration * overload)74*c8dee2aaSAndroid Build Coastguard Worker void setNextOverload(FunctionDeclaration* overload) { 75*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!overload || overload->name() == this->name()); 76*c8dee2aaSAndroid Build Coastguard Worker fNextOverload = overload; 77*c8dee2aaSAndroid Build Coastguard Worker } 78*c8dee2aaSAndroid Build Coastguard Worker parameters()79*c8dee2aaSAndroid Build Coastguard Worker SkSpan<Variable* const> parameters() const { 80*c8dee2aaSAndroid Build Coastguard Worker return fParameters; 81*c8dee2aaSAndroid Build Coastguard Worker } 82*c8dee2aaSAndroid Build Coastguard Worker returnType()83*c8dee2aaSAndroid Build Coastguard Worker const Type& returnType() const { 84*c8dee2aaSAndroid Build Coastguard Worker return *fReturnType; 85*c8dee2aaSAndroid Build Coastguard Worker } 86*c8dee2aaSAndroid Build Coastguard Worker moduleType()87*c8dee2aaSAndroid Build Coastguard Worker ModuleType moduleType() const { 88*c8dee2aaSAndroid Build Coastguard Worker return fModuleType; 89*c8dee2aaSAndroid Build Coastguard Worker } 90*c8dee2aaSAndroid Build Coastguard Worker isBuiltin()91*c8dee2aaSAndroid Build Coastguard Worker bool isBuiltin() const { 92*c8dee2aaSAndroid Build Coastguard Worker return this->moduleType() != ModuleType::program; 93*c8dee2aaSAndroid Build Coastguard Worker } 94*c8dee2aaSAndroid Build Coastguard Worker isMain()95*c8dee2aaSAndroid Build Coastguard Worker bool isMain() const { 96*c8dee2aaSAndroid Build Coastguard Worker return fIsMain; 97*c8dee2aaSAndroid Build Coastguard Worker } 98*c8dee2aaSAndroid Build Coastguard Worker intrinsicKind()99*c8dee2aaSAndroid Build Coastguard Worker IntrinsicKind intrinsicKind() const { 100*c8dee2aaSAndroid Build Coastguard Worker return fIntrinsicKind; 101*c8dee2aaSAndroid Build Coastguard Worker } 102*c8dee2aaSAndroid Build Coastguard Worker isIntrinsic()103*c8dee2aaSAndroid Build Coastguard Worker bool isIntrinsic() const { 104*c8dee2aaSAndroid Build Coastguard Worker return this->intrinsicKind() != kNotIntrinsic; 105*c8dee2aaSAndroid Build Coastguard Worker } 106*c8dee2aaSAndroid Build Coastguard Worker nextOverload()107*c8dee2aaSAndroid Build Coastguard Worker const FunctionDeclaration* nextOverload() const { 108*c8dee2aaSAndroid Build Coastguard Worker return fNextOverload; 109*c8dee2aaSAndroid Build Coastguard Worker } 110*c8dee2aaSAndroid Build Coastguard Worker mutableNextOverload()111*c8dee2aaSAndroid Build Coastguard Worker FunctionDeclaration* mutableNextOverload() const { 112*c8dee2aaSAndroid Build Coastguard Worker return fNextOverload; 113*c8dee2aaSAndroid Build Coastguard Worker } 114*c8dee2aaSAndroid Build Coastguard Worker 115*c8dee2aaSAndroid Build Coastguard Worker std::string mangledName() const; 116*c8dee2aaSAndroid Build Coastguard Worker 117*c8dee2aaSAndroid Build Coastguard Worker std::string description() const override; 118*c8dee2aaSAndroid Build Coastguard Worker 119*c8dee2aaSAndroid Build Coastguard Worker bool matches(const FunctionDeclaration& f) const; 120*c8dee2aaSAndroid Build Coastguard Worker 121*c8dee2aaSAndroid Build Coastguard Worker /** 122*c8dee2aaSAndroid Build Coastguard Worker * If this function is main(), and it has the requested parameter, returns that parameter. 123*c8dee2aaSAndroid Build Coastguard Worker * For instance, only a runtime-blend program will have a dest-color parameter, in parameter 1; 124*c8dee2aaSAndroid Build Coastguard Worker * `getMainDestColorParameter` will return that parameter if this is a runtime-blend main() 125*c8dee2aaSAndroid Build Coastguard Worker * function. Otherwise, null is returned. 126*c8dee2aaSAndroid Build Coastguard Worker */ getMainCoordsParameter()127*c8dee2aaSAndroid Build Coastguard Worker const Variable* getMainCoordsParameter() const { 128*c8dee2aaSAndroid Build Coastguard Worker return fHasMainCoordsParameter ? fParameters[0] : nullptr; 129*c8dee2aaSAndroid Build Coastguard Worker } getMainInputColorParameter()130*c8dee2aaSAndroid Build Coastguard Worker const Variable* getMainInputColorParameter() const { 131*c8dee2aaSAndroid Build Coastguard Worker return fHasMainInputColorParameter ? fParameters[0] : nullptr; 132*c8dee2aaSAndroid Build Coastguard Worker } getMainDestColorParameter()133*c8dee2aaSAndroid Build Coastguard Worker const Variable* getMainDestColorParameter() const { 134*c8dee2aaSAndroid Build Coastguard Worker return fHasMainDestColorParameter ? fParameters[1] : nullptr; 135*c8dee2aaSAndroid Build Coastguard Worker } 136*c8dee2aaSAndroid Build Coastguard Worker 137*c8dee2aaSAndroid Build Coastguard Worker /** 138*c8dee2aaSAndroid Build Coastguard Worker * Determine the effective types of this function's parameters and return value when called with 139*c8dee2aaSAndroid Build Coastguard Worker * the given arguments. This is relevant for functions with generic parameter types, where this 140*c8dee2aaSAndroid Build Coastguard Worker * will collapse the generic types down into specific concrete types. 141*c8dee2aaSAndroid Build Coastguard Worker * 142*c8dee2aaSAndroid Build Coastguard Worker * Returns true if it was able to select a concrete set of types for the generic function, false 143*c8dee2aaSAndroid Build Coastguard Worker * if there is no possible way this can match the argument types. Note that even a true return 144*c8dee2aaSAndroid Build Coastguard Worker * does not guarantee that the function can be successfully called with those arguments, merely 145*c8dee2aaSAndroid Build Coastguard Worker * indicates that an attempt should be made. If false is returned, the state of 146*c8dee2aaSAndroid Build Coastguard Worker * outParameterTypes and outReturnType are undefined. 147*c8dee2aaSAndroid Build Coastguard Worker * 148*c8dee2aaSAndroid Build Coastguard Worker * This always assumes narrowing conversions are *allowed*. The calling code needs to verify 149*c8dee2aaSAndroid Build Coastguard Worker * that each argument can actually be coerced to the final parameter type, respecting the 150*c8dee2aaSAndroid Build Coastguard Worker * narrowing-conversions flag. This is handled in callCost(), or in convertCall() (via coerce). 151*c8dee2aaSAndroid Build Coastguard Worker */ 152*c8dee2aaSAndroid Build Coastguard Worker using ParamTypes = skia_private::STArray<8, const Type*>; 153*c8dee2aaSAndroid Build Coastguard Worker bool determineFinalTypes(const ExpressionArray& arguments, 154*c8dee2aaSAndroid Build Coastguard Worker ParamTypes* outParameterTypes, 155*c8dee2aaSAndroid Build Coastguard Worker const Type** outReturnType) const; 156*c8dee2aaSAndroid Build Coastguard Worker 157*c8dee2aaSAndroid Build Coastguard Worker private: 158*c8dee2aaSAndroid Build Coastguard Worker const FunctionDefinition* fDefinition; 159*c8dee2aaSAndroid Build Coastguard Worker FunctionDeclaration* fNextOverload = nullptr; 160*c8dee2aaSAndroid Build Coastguard Worker skia_private::TArray<Variable*> fParameters; 161*c8dee2aaSAndroid Build Coastguard Worker const Type* fReturnType = nullptr; 162*c8dee2aaSAndroid Build Coastguard Worker ModifierFlags fModifierFlags; 163*c8dee2aaSAndroid Build Coastguard Worker mutable IntrinsicKind fIntrinsicKind = kNotIntrinsic; 164*c8dee2aaSAndroid Build Coastguard Worker ModuleType fModuleType = ModuleType::unknown; 165*c8dee2aaSAndroid Build Coastguard Worker bool fIsMain = false; 166*c8dee2aaSAndroid Build Coastguard Worker bool fHasMainCoordsParameter = false; 167*c8dee2aaSAndroid Build Coastguard Worker bool fHasMainInputColorParameter = false; 168*c8dee2aaSAndroid Build Coastguard Worker bool fHasMainDestColorParameter = false; 169*c8dee2aaSAndroid Build Coastguard Worker 170*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = Symbol; 171*c8dee2aaSAndroid Build Coastguard Worker }; 172*c8dee2aaSAndroid Build Coastguard Worker 173*c8dee2aaSAndroid Build Coastguard Worker } // namespace SkSL 174*c8dee2aaSAndroid Build Coastguard Worker 175*c8dee2aaSAndroid Build Coastguard Worker #endif 176