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