/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SKSL_FUNCTIONDECLARATION #define SKSL_FUNCTIONDECLARATION #include "include/core/SkSpan.h" #include "include/core/SkTypes.h" #include "include/private/base/SkTArray.h" #include "src/sksl/SkSLIntrinsicList.h" #include "src/sksl/SkSLModule.h" #include "src/sksl/ir/SkSLIRNode.h" #include "src/sksl/ir/SkSLModifierFlags.h" #include "src/sksl/ir/SkSLSymbol.h" #include #include #include namespace SkSL { class Context; class ExpressionArray; class FunctionDefinition; struct Modifiers; class Position; class Type; class Variable; /** * A function declaration (not a definition -- does not contain a body). */ class FunctionDeclaration final : public Symbol { public: inline static constexpr Kind kIRNodeKind = Kind::kFunctionDeclaration; FunctionDeclaration(const Context& context, Position pos, ModifierFlags modifierFlags, std::string_view name, skia_private::TArray parameters, const Type* returnType, IntrinsicKind intrinsicKind); static FunctionDeclaration* Convert(const Context& context, Position pos, const Modifiers& modifiers, std::string_view name, skia_private::TArray> parameters, Position returnTypePos, const Type* returnType); ModifierFlags modifierFlags() const { return fModifierFlags; } void setModifierFlags(ModifierFlags m) { fModifierFlags = m; } const FunctionDefinition* definition() const { return fDefinition; } void setDefinition(const FunctionDefinition* definition) { fDefinition = definition; fIntrinsicKind = kNotIntrinsic; } void setNextOverload(FunctionDeclaration* overload) { SkASSERT(!overload || overload->name() == this->name()); fNextOverload = overload; } SkSpan parameters() const { return fParameters; } const Type& returnType() const { return *fReturnType; } ModuleType moduleType() const { return fModuleType; } bool isBuiltin() const { return this->moduleType() != ModuleType::program; } bool isMain() const { return fIsMain; } IntrinsicKind intrinsicKind() const { return fIntrinsicKind; } bool isIntrinsic() const { return this->intrinsicKind() != kNotIntrinsic; } const FunctionDeclaration* nextOverload() const { return fNextOverload; } FunctionDeclaration* mutableNextOverload() const { return fNextOverload; } std::string mangledName() const; std::string description() const override; bool matches(const FunctionDeclaration& f) const; /** * 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. */ const Variable* getMainCoordsParameter() const { return fHasMainCoordsParameter ? fParameters[0] : nullptr; } const Variable* getMainInputColorParameter() const { return fHasMainInputColorParameter ? fParameters[0] : nullptr; } const Variable* getMainDestColorParameter() const { return fHasMainDestColorParameter ? fParameters[1] : nullptr; } /** * 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). */ using ParamTypes = skia_private::STArray<8, const Type*>; bool determineFinalTypes(const ExpressionArray& arguments, ParamTypes* outParameterTypes, const Type** outReturnType) const; private: const FunctionDefinition* fDefinition; FunctionDeclaration* fNextOverload = nullptr; skia_private::TArray fParameters; const Type* fReturnType = nullptr; ModifierFlags fModifierFlags; mutable IntrinsicKind fIntrinsicKind = kNotIntrinsic; ModuleType fModuleType = ModuleType::unknown; bool fIsMain = false; bool fHasMainCoordsParameter = false; bool fHasMainInputColorParameter = false; bool fHasMainDestColorParameter = false; using INHERITED = Symbol; }; } // namespace SkSL #endif