xref: /aosp_15_r20/external/skia/src/sksl/ir/SkSLVarDeclarations.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_VARDECLARATIONS
9*c8dee2aaSAndroid Build Coastguard Worker #define SKSL_VARDECLARATIONS
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLExpression.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLIRNode.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLModifierFlags.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLProgramElement.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLStatement.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLVariable.h"
18*c8dee2aaSAndroid Build Coastguard Worker 
19*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
20*c8dee2aaSAndroid Build Coastguard Worker #include <string>
21*c8dee2aaSAndroid Build Coastguard Worker #include <string_view>
22*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
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 struct Layout;
28*c8dee2aaSAndroid Build Coastguard Worker struct Modifiers;
29*c8dee2aaSAndroid Build Coastguard Worker class Position;
30*c8dee2aaSAndroid Build Coastguard Worker class Type;
31*c8dee2aaSAndroid Build Coastguard Worker 
32*c8dee2aaSAndroid Build Coastguard Worker /**
33*c8dee2aaSAndroid Build Coastguard Worker  * A single variable declaration statement. Multiple variables declared together are expanded to
34*c8dee2aaSAndroid Build Coastguard Worker  * separate (sequential) statements. For instance, the SkSL 'int x = 2, y[3];' produces two
35*c8dee2aaSAndroid Build Coastguard Worker  * VarDeclaration instances (wrapped in an unscoped Block).
36*c8dee2aaSAndroid Build Coastguard Worker  */
37*c8dee2aaSAndroid Build Coastguard Worker class VarDeclaration final : public Statement {
38*c8dee2aaSAndroid Build Coastguard Worker public:
39*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr Kind kIRNodeKind = Kind::kVarDeclaration;
40*c8dee2aaSAndroid Build Coastguard Worker 
VarDeclaration(Variable * var,const Type * baseType,int arraySize,std::unique_ptr<Expression> value)41*c8dee2aaSAndroid Build Coastguard Worker     VarDeclaration(Variable* var,
42*c8dee2aaSAndroid Build Coastguard Worker                    const Type* baseType,
43*c8dee2aaSAndroid Build Coastguard Worker                    int arraySize,
44*c8dee2aaSAndroid Build Coastguard Worker                    std::unique_ptr<Expression> value)
45*c8dee2aaSAndroid Build Coastguard Worker             : INHERITED(var->fPosition, kIRNodeKind)
46*c8dee2aaSAndroid Build Coastguard Worker             , fVar(var)
47*c8dee2aaSAndroid Build Coastguard Worker             , fBaseType(*baseType)
48*c8dee2aaSAndroid Build Coastguard Worker             , fArraySize(arraySize)
49*c8dee2aaSAndroid Build Coastguard Worker             , fValue(std::move(value)) {}
50*c8dee2aaSAndroid Build Coastguard Worker 
~VarDeclaration()51*c8dee2aaSAndroid Build Coastguard Worker     ~VarDeclaration() override {
52*c8dee2aaSAndroid Build Coastguard Worker         // Unhook this VarDeclaration from its associated Variable, since we're being deleted.
53*c8dee2aaSAndroid Build Coastguard Worker         if (fVar) {
54*c8dee2aaSAndroid Build Coastguard Worker             fVar->detachDeadVarDeclaration();
55*c8dee2aaSAndroid Build Coastguard Worker         }
56*c8dee2aaSAndroid Build Coastguard Worker     }
57*c8dee2aaSAndroid Build Coastguard Worker 
58*c8dee2aaSAndroid Build Coastguard Worker     // Checks the modifiers, baseType, and storage for compatibility with one another and reports
59*c8dee2aaSAndroid Build Coastguard Worker     // errors if needed. This method is implicitly called during Convert(), but is also explicitly
60*c8dee2aaSAndroid Build Coastguard Worker     // called while processing interface block fields.
61*c8dee2aaSAndroid Build Coastguard Worker     static void ErrorCheck(const Context& context, Position pos, Position modifiersPosition,
62*c8dee2aaSAndroid Build Coastguard Worker                            const Layout& layout, ModifierFlags modifierFlags, const Type* type,
63*c8dee2aaSAndroid Build Coastguard Worker                            const Type* baseType, Variable::Storage storage);
64*c8dee2aaSAndroid Build Coastguard Worker 
65*c8dee2aaSAndroid Build Coastguard Worker     // For use when no Variable yet exists. The newly-created variable will be added to the active
66*c8dee2aaSAndroid Build Coastguard Worker     // symbol table. Performs proper error checking and type coercion; reports errors via
67*c8dee2aaSAndroid Build Coastguard Worker     // ErrorReporter.
68*c8dee2aaSAndroid Build Coastguard Worker     static std::unique_ptr<VarDeclaration> Convert(const Context& context,
69*c8dee2aaSAndroid Build Coastguard Worker                                                    Position overallPos,
70*c8dee2aaSAndroid Build Coastguard Worker                                                    const Modifiers& modifiers,
71*c8dee2aaSAndroid Build Coastguard Worker                                                    const Type& type,
72*c8dee2aaSAndroid Build Coastguard Worker                                                    Position namePos,
73*c8dee2aaSAndroid Build Coastguard Worker                                                    std::string_view name,
74*c8dee2aaSAndroid Build Coastguard Worker                                                    VariableStorage storage,
75*c8dee2aaSAndroid Build Coastguard Worker                                                    std::unique_ptr<Expression> value);
76*c8dee2aaSAndroid Build Coastguard Worker 
77*c8dee2aaSAndroid Build Coastguard Worker     // For use when a Variable already exists. The passed-in variable will be added to the active
78*c8dee2aaSAndroid Build Coastguard Worker     // symbol table. Performs proper error checking and type coercion; reports errors via
79*c8dee2aaSAndroid Build Coastguard Worker     // ErrorReporter.
80*c8dee2aaSAndroid Build Coastguard Worker     static std::unique_ptr<VarDeclaration> Convert(const Context& context,
81*c8dee2aaSAndroid Build Coastguard Worker                                                    std::unique_ptr<Variable> var,
82*c8dee2aaSAndroid Build Coastguard Worker                                                    std::unique_ptr<Expression> value);
83*c8dee2aaSAndroid Build Coastguard Worker 
84*c8dee2aaSAndroid Build Coastguard Worker     // The symbol table is left as-is. Reports errors via ASSERT.
85*c8dee2aaSAndroid Build Coastguard Worker     static std::unique_ptr<VarDeclaration> Make(const Context& context,
86*c8dee2aaSAndroid Build Coastguard Worker                                                 Variable* var,
87*c8dee2aaSAndroid Build Coastguard Worker                                                 const Type* baseType,
88*c8dee2aaSAndroid Build Coastguard Worker                                                 int arraySize,
89*c8dee2aaSAndroid Build Coastguard Worker                                                 std::unique_ptr<Expression> value);
baseType()90*c8dee2aaSAndroid Build Coastguard Worker     const Type& baseType() const {
91*c8dee2aaSAndroid Build Coastguard Worker         return fBaseType;
92*c8dee2aaSAndroid Build Coastguard Worker     }
93*c8dee2aaSAndroid Build Coastguard Worker 
var()94*c8dee2aaSAndroid Build Coastguard Worker     Variable* var() const {
95*c8dee2aaSAndroid Build Coastguard Worker         return fVar;
96*c8dee2aaSAndroid Build Coastguard Worker     }
97*c8dee2aaSAndroid Build Coastguard Worker 
detachDeadVariable()98*c8dee2aaSAndroid Build Coastguard Worker     void detachDeadVariable() {
99*c8dee2aaSAndroid Build Coastguard Worker         fVar = nullptr;
100*c8dee2aaSAndroid Build Coastguard Worker     }
101*c8dee2aaSAndroid Build Coastguard Worker 
arraySize()102*c8dee2aaSAndroid Build Coastguard Worker     int arraySize() const {
103*c8dee2aaSAndroid Build Coastguard Worker         return fArraySize;
104*c8dee2aaSAndroid Build Coastguard Worker     }
105*c8dee2aaSAndroid Build Coastguard Worker 
value()106*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<Expression>& value() {
107*c8dee2aaSAndroid Build Coastguard Worker         return fValue;
108*c8dee2aaSAndroid Build Coastguard Worker     }
109*c8dee2aaSAndroid Build Coastguard Worker 
value()110*c8dee2aaSAndroid Build Coastguard Worker     const std::unique_ptr<Expression>& value() const {
111*c8dee2aaSAndroid Build Coastguard Worker         return fValue;
112*c8dee2aaSAndroid Build Coastguard Worker     }
113*c8dee2aaSAndroid Build Coastguard Worker 
114*c8dee2aaSAndroid Build Coastguard Worker     std::string description() const override;
115*c8dee2aaSAndroid Build Coastguard Worker 
116*c8dee2aaSAndroid Build Coastguard Worker private:
117*c8dee2aaSAndroid Build Coastguard Worker     static bool ErrorCheckAndCoerce(const Context& context,
118*c8dee2aaSAndroid Build Coastguard Worker                                     const Variable& var,
119*c8dee2aaSAndroid Build Coastguard Worker                                     const Type* baseType,
120*c8dee2aaSAndroid Build Coastguard Worker                                     std::unique_ptr<Expression>& value);
121*c8dee2aaSAndroid Build Coastguard Worker 
122*c8dee2aaSAndroid Build Coastguard Worker     Variable* fVar;
123*c8dee2aaSAndroid Build Coastguard Worker     const Type& fBaseType;
124*c8dee2aaSAndroid Build Coastguard Worker     int fArraySize;  // zero means "not an array"
125*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<Expression> fValue;
126*c8dee2aaSAndroid Build Coastguard Worker 
127*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = Statement;
128*c8dee2aaSAndroid Build Coastguard Worker };
129*c8dee2aaSAndroid Build Coastguard Worker 
130*c8dee2aaSAndroid Build Coastguard Worker /**
131*c8dee2aaSAndroid Build Coastguard Worker  * A variable declaration appearing at global scope. A global declaration like 'int x, y;' produces
132*c8dee2aaSAndroid Build Coastguard Worker  * two GlobalVarDeclaration elements, each containing the declaration of one variable.
133*c8dee2aaSAndroid Build Coastguard Worker  */
134*c8dee2aaSAndroid Build Coastguard Worker class GlobalVarDeclaration final : public ProgramElement {
135*c8dee2aaSAndroid Build Coastguard Worker public:
136*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr Kind kIRNodeKind = Kind::kGlobalVar;
137*c8dee2aaSAndroid Build Coastguard Worker 
GlobalVarDeclaration(std::unique_ptr<Statement> decl)138*c8dee2aaSAndroid Build Coastguard Worker     GlobalVarDeclaration(std::unique_ptr<Statement> decl)
139*c8dee2aaSAndroid Build Coastguard Worker             : INHERITED(decl->fPosition, kIRNodeKind)
140*c8dee2aaSAndroid Build Coastguard Worker             , fDeclaration(std::move(decl)) {
141*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->declaration()->is<VarDeclaration>());
142*c8dee2aaSAndroid Build Coastguard Worker         this->varDeclaration().var()->setGlobalVarDeclaration(this);
143*c8dee2aaSAndroid Build Coastguard Worker     }
144*c8dee2aaSAndroid Build Coastguard Worker 
declaration()145*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<Statement>& declaration() {
146*c8dee2aaSAndroid Build Coastguard Worker         return fDeclaration;
147*c8dee2aaSAndroid Build Coastguard Worker     }
148*c8dee2aaSAndroid Build Coastguard Worker 
declaration()149*c8dee2aaSAndroid Build Coastguard Worker     const std::unique_ptr<Statement>& declaration() const {
150*c8dee2aaSAndroid Build Coastguard Worker         return fDeclaration;
151*c8dee2aaSAndroid Build Coastguard Worker     }
152*c8dee2aaSAndroid Build Coastguard Worker 
varDeclaration()153*c8dee2aaSAndroid Build Coastguard Worker     VarDeclaration& varDeclaration() {
154*c8dee2aaSAndroid Build Coastguard Worker         return fDeclaration->as<VarDeclaration>();
155*c8dee2aaSAndroid Build Coastguard Worker     }
156*c8dee2aaSAndroid Build Coastguard Worker 
varDeclaration()157*c8dee2aaSAndroid Build Coastguard Worker     const VarDeclaration& varDeclaration() const {
158*c8dee2aaSAndroid Build Coastguard Worker         return fDeclaration->as<VarDeclaration>();
159*c8dee2aaSAndroid Build Coastguard Worker     }
160*c8dee2aaSAndroid Build Coastguard Worker 
description()161*c8dee2aaSAndroid Build Coastguard Worker     std::string description() const override {
162*c8dee2aaSAndroid Build Coastguard Worker         return this->declaration()->description();
163*c8dee2aaSAndroid Build Coastguard Worker     }
164*c8dee2aaSAndroid Build Coastguard Worker 
165*c8dee2aaSAndroid Build Coastguard Worker private:
166*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<Statement> fDeclaration;
167*c8dee2aaSAndroid Build Coastguard Worker 
168*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = ProgramElement;
169*c8dee2aaSAndroid Build Coastguard Worker };
170*c8dee2aaSAndroid Build Coastguard Worker 
171*c8dee2aaSAndroid Build Coastguard Worker }  // namespace SkSL
172*c8dee2aaSAndroid Build Coastguard Worker 
173*c8dee2aaSAndroid Build Coastguard Worker #endif
174