• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_VARIABLE
9 #define SKSL_VARIABLE
10 
11 #include "include/core/SkTypes.h"
12 #include "include/private/SkSLIRNode.h"
13 #include "include/private/SkSLModifiers.h"
14 #include "include/private/SkSLStatement.h"
15 #include "include/private/SkSLSymbol.h"
16 #include "include/sksl/SkSLPosition.h"
17 #include "src/sksl/ir/SkSLType.h"
18 
19 #include <cstdint>
20 #include <memory>
21 #include <string>
22 #include <string_view>
23 
24 namespace SkSL {
25 
26 class Context;
27 class Expression;
28 class GlobalVarDeclaration;
29 class InterfaceBlock;
30 class Mangler;
31 class SymbolTable;
32 class VarDeclaration;
33 
34 enum class VariableStorage : int8_t {
35     kGlobal,
36     kInterfaceBlock,
37     kLocal,
38     kParameter,
39 };
40 
41 /**
42  * Represents a variable, whether local, global, or a function parameter. This represents the
43  * variable itself (the storage location), which is shared between all VariableReferences which
44  * read or write that storage location.
45  */
46 class Variable : public Symbol {
47 public:
48     using Storage = VariableStorage;
49 
50     inline static constexpr Kind kIRNodeKind = Kind::kVariable;
51 
Variable(Position pos,Position modifiersPosition,const Modifiers * modifiers,std::string_view name,const Type * type,bool builtin,Storage storage)52     Variable(Position pos, Position modifiersPosition, const Modifiers* modifiers,
53             std::string_view name, const Type* type, bool builtin, Storage storage)
54     : INHERITED(pos, kIRNodeKind, name, type)
55     , fModifiersPosition(modifiersPosition)
56     , fModifiers(modifiers)
57     , fStorage(storage)
58     , fBuiltin(builtin) {}
59 
60     ~Variable() override;
61 
62     static std::unique_ptr<Variable> Convert(const Context& context, Position pos,
63             Position modifiersPos, const Modifiers& modifiers, const Type* baseType,
64             Position namePos, std::string_view name, bool isArray,
65             std::unique_ptr<Expression> arraySize, Variable::Storage storage);
66 
67     static std::unique_ptr<Variable> Make(const Context& context, Position pos,
68             Position modifiersPos, const Modifiers& modifiers, const Type* baseType,
69             std::string_view name, bool isArray, std::unique_ptr<Expression> arraySize,
70             Variable::Storage storage);
71 
72     /**
73      * Creates a local scratch variable and the associated VarDeclaration statement.
74      * Useful when doing IR rewrites, e.g. inlining a function call.
75      */
76     struct ScratchVariable {
77         const Variable* fVarSymbol;
78         std::unique_ptr<Statement> fVarDecl;
79     };
80     static ScratchVariable MakeScratchVariable(const Context& context,
81                                                Mangler& mangler,
82                                                std::string_view baseName,
83                                                const Type* type,
84                                                const Modifiers& modifiers,
85                                                SymbolTable* symbolTable,
86                                                std::unique_ptr<Expression> initialValue);
modifiers()87     const Modifiers& modifiers() const {
88         return *fModifiers;
89     }
90 
setModifiers(const Modifiers * modifiers)91     void setModifiers(const Modifiers* modifiers) {
92         fModifiers = modifiers;
93     }
94 
modifiersPosition()95     Position modifiersPosition() const {
96         return fModifiersPosition;
97     }
98 
isBuiltin()99     bool isBuiltin() const {
100         return fBuiltin;
101     }
102 
storage()103     Storage storage() const {
104         return fStorage;
105     }
106 
107     const Expression* initialValue() const;
108 
109     VarDeclaration* varDeclaration() const;
110 
111     void setVarDeclaration(VarDeclaration* declaration);
112 
113     GlobalVarDeclaration* globalVarDeclaration() const;
114 
115     void setGlobalVarDeclaration(GlobalVarDeclaration* global);
116 
detachDeadVarDeclaration()117     void detachDeadVarDeclaration() {
118         // The VarDeclaration is being deleted, so our reference to it has become stale.
119         fDeclaringElement = nullptr;
120     }
121 
122     // The interfaceBlock methods are no-op stubs here. They have proper implementations in
123     // InterfaceBlockVariable, declared below this class, which dedicates extra space to store the
124     // pointer back to the InterfaceBlock.
interfaceBlock()125     virtual InterfaceBlock* interfaceBlock() const { return nullptr; }
126 
setInterfaceBlock(InterfaceBlock *)127     virtual void setInterfaceBlock(InterfaceBlock*) { SkUNREACHABLE; }
128 
detachDeadInterfaceBlock()129     virtual void detachDeadInterfaceBlock() {}
130 
description()131     std::string description() const override {
132         return this->modifiers().description() + this->type().displayName() + " " +
133                std::string(this->name());
134     }
135 
136     std::string mangledName() const;
137 
138 private:
139     IRNode* fDeclaringElement = nullptr;
140     // We don't store the position in the Modifiers object itself because they are pooled
141     Position fModifiersPosition;
142     const Modifiers* fModifiers;
143     VariableStorage fStorage;
144     bool fBuiltin;
145 
146     using INHERITED = Symbol;
147 };
148 
149 /**
150  * This represents a Variable associated with an InterfaceBlock. Mostly a normal variable, but also
151  * has an extra pointer back to the InterfaceBlock element that owns it.
152  */
153 class InterfaceBlockVariable final : public Variable {
154 public:
155     using Variable::Variable;
156 
157     ~InterfaceBlockVariable() override;
158 
interfaceBlock()159     InterfaceBlock* interfaceBlock() const override { return fInterfaceBlockElement; }
160 
setInterfaceBlock(InterfaceBlock * elem)161     void setInterfaceBlock(InterfaceBlock* elem) override {
162         SkASSERT(!fInterfaceBlockElement);
163         fInterfaceBlockElement = elem;
164     }
165 
detachDeadInterfaceBlock()166     void detachDeadInterfaceBlock() override {
167         // The InterfaceBlock is being deleted, so our reference to it has become stale.
168         fInterfaceBlockElement = nullptr;
169     }
170 
171 private:
172     InterfaceBlock* fInterfaceBlockElement = nullptr;
173 
174     using INHERITED = Variable;
175 };
176 
177 } // namespace SkSL
178 
179 #endif
180