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