xref: /aosp_15_r20/external/skia/src/sksl/ir/SkSLFunctionDeclaration.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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