1 | // |
2 | // Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. |
3 | // Use of this source code is governed by a BSD-style license that can be |
4 | // found in the LICENSE file. |
5 | // |
6 | // Symbol.h: Symbols representing variables, functions, structures and interface blocks. |
7 | // |
8 | |
9 | #ifndef COMPILER_TRANSLATOR_SYMBOL_H_ |
10 | #define COMPILER_TRANSLATOR_SYMBOL_H_ |
11 | |
12 | #include "common/angleutils.h" |
13 | #include "compiler/translator/ExtensionBehavior.h" |
14 | #include "compiler/translator/ImmutableString.h" |
15 | #include "compiler/translator/IntermNode.h" |
16 | #include "compiler/translator/SymbolUniqueId.h" |
17 | |
18 | namespace sh |
19 | { |
20 | |
21 | class TSymbolTable; |
22 | |
23 | // Symbol base class. (Can build functions or variables out of these...) |
24 | class TSymbol : angle::NonCopyable |
25 | { |
26 | public: |
27 | POOL_ALLOCATOR_NEW_DELETE |
28 | TSymbol(TSymbolTable *symbolTable, |
29 | const ImmutableString &name, |
30 | SymbolType symbolType, |
31 | SymbolClass symbolClass, |
32 | TExtension extension = TExtension::UNDEFINED); |
33 | |
34 | // Note that we can't have a virtual destructor in order to support constexpr symbols. Data is |
35 | // either statically allocated or pool allocated. |
36 | ~TSymbol() = default; |
37 | |
38 | // Calling name() for empty symbols (symbolType == SymbolType::Empty) generates a similar name |
39 | // as for internal variables. |
40 | ImmutableString name() const; |
41 | // Don't call getMangledName() for empty symbols (symbolType == SymbolType::Empty). |
42 | ImmutableString getMangledName() const; |
43 | |
44 | bool isFunction() const { return mSymbolClass == SymbolClass::Function; } |
45 | bool isVariable() const { return mSymbolClass == SymbolClass::Variable; } |
46 | bool isStruct() const { return mSymbolClass == SymbolClass::Struct; } |
47 | bool isInterfaceBlock() const { return mSymbolClass == SymbolClass::InterfaceBlock; } |
48 | |
49 | const TSymbolUniqueId &uniqueId() const { return mUniqueId; } |
50 | SymbolType symbolType() const { return mSymbolType; } |
51 | TExtension extension() const { return mExtension; } |
52 | |
53 | protected: |
54 | constexpr TSymbol(const TSymbolUniqueId &id, |
55 | const ImmutableString &name, |
56 | SymbolType symbolType, |
57 | TExtension extension, |
58 | SymbolClass symbolClass) |
59 | : mName(name), |
60 | mUniqueId(id), |
61 | mSymbolType(symbolType), |
62 | mExtension(extension), |
63 | mSymbolClass(symbolClass) |
64 | {} |
65 | |
66 | const ImmutableString mName; |
67 | |
68 | private: |
69 | const TSymbolUniqueId mUniqueId; |
70 | const SymbolType mSymbolType; |
71 | const TExtension mExtension; |
72 | |
73 | // We use this instead of having virtual functions for querying the class in order to support |
74 | // constexpr symbols. |
75 | const SymbolClass mSymbolClass; |
76 | }; |
77 | |
78 | // Variable. |
79 | // May store the value of a constant variable of any type (float, int, bool or struct). |
80 | class TVariable : public TSymbol |
81 | { |
82 | public: |
83 | TVariable(TSymbolTable *symbolTable, |
84 | const ImmutableString &name, |
85 | const TType *type, |
86 | SymbolType symbolType, |
87 | TExtension ext = TExtension::UNDEFINED); |
88 | |
89 | const TType &getType() const { return *mType; } |
90 | |
91 | const TConstantUnion *getConstPointer() const { return unionArray; } |
92 | |
93 | void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; } |
94 | |
95 | // Note: only to be used for built-in variables with autogenerated ids! |
96 | constexpr TVariable(const TSymbolUniqueId &id, |
97 | const ImmutableString &name, |
98 | SymbolType symbolType, |
99 | TExtension extension, |
100 | const TType *type) |
101 | : TSymbol(id, name, symbolType, extension, SymbolClass::Variable), |
102 | mType(type), |
103 | unionArray(nullptr) |
104 | {} |
105 | |
106 | private: |
107 | const TType *mType; |
108 | const TConstantUnion *unionArray; |
109 | }; |
110 | |
111 | // Struct type. |
112 | class TStructure : public TSymbol, public TFieldListCollection |
113 | { |
114 | public: |
115 | TStructure(TSymbolTable *symbolTable, |
116 | const ImmutableString &name, |
117 | const TFieldList *fields, |
118 | SymbolType symbolType); |
119 | |
120 | // The char arrays passed in must be pool allocated or static. |
121 | void createSamplerSymbols(const char *namePrefix, |
122 | const TString &apiNamePrefix, |
123 | TVector<const TVariable *> *outputSymbols, |
124 | TMap<const TVariable *, TString> *outputSymbolsToAPINames, |
125 | TSymbolTable *symbolTable) const; |
126 | |
127 | void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; } |
128 | bool atGlobalScope() const { return mAtGlobalScope; } |
129 | |
130 | private: |
131 | friend class TSymbolTable; |
132 | // For creating built-in structs. |
133 | TStructure(const TSymbolUniqueId &id, |
134 | const ImmutableString &name, |
135 | TExtension extension, |
136 | const TFieldList *fields); |
137 | |
138 | // TODO(zmo): Find a way to get rid of the const_cast in function |
139 | // setName(). At the moment keep this function private so only |
140 | // friend class RegenerateStructNames may call it. |
141 | friend class RegenerateStructNames; |
142 | void setName(const ImmutableString &name); |
143 | |
144 | bool mAtGlobalScope; |
145 | }; |
146 | |
147 | // Interface block. Note that this contains the block name, not the instance name. Interface block |
148 | // instances are stored as TVariable. |
149 | class TInterfaceBlock : public TSymbol, public TFieldListCollection |
150 | { |
151 | public: |
152 | TInterfaceBlock(TSymbolTable *symbolTable, |
153 | const ImmutableString &name, |
154 | const TFieldList *fields, |
155 | const TLayoutQualifier &layoutQualifier, |
156 | SymbolType symbolType, |
157 | TExtension extension = TExtension::UNDEFINED); |
158 | |
159 | TLayoutBlockStorage blockStorage() const { return mBlockStorage; } |
160 | int blockBinding() const { return mBinding; } |
161 | |
162 | private: |
163 | friend class TSymbolTable; |
164 | // For creating built-in interface blocks. |
165 | TInterfaceBlock(const TSymbolUniqueId &id, |
166 | const ImmutableString &name, |
167 | TExtension extension, |
168 | const TFieldList *fields); |
169 | |
170 | TLayoutBlockStorage mBlockStorage; |
171 | int mBinding; |
172 | |
173 | // Note that we only record matrix packing on a per-field granularity. |
174 | }; |
175 | |
176 | // Parameter class used for parsing user-defined function parameters. |
177 | struct TParameter |
178 | { |
179 | // Destructively converts to TVariable. |
180 | // This method resets name and type to nullptrs to make sure |
181 | // their content cannot be modified after the call. |
182 | const TVariable *createVariable(TSymbolTable *symbolTable) |
183 | { |
184 | const ImmutableString constName(name); |
185 | const TType *constType = type; |
186 | name = nullptr; |
187 | type = nullptr; |
188 | return new TVariable(symbolTable, constName, constType, |
189 | constName.empty() ? SymbolType::Empty : SymbolType::UserDefined); |
190 | } |
191 | |
192 | const char *name; // either pool allocated or static. |
193 | TType *type; |
194 | }; |
195 | |
196 | // The function sub-class of a symbol. |
197 | class TFunction : public TSymbol |
198 | { |
199 | public: |
200 | // User-defined function |
201 | TFunction(TSymbolTable *symbolTable, |
202 | const ImmutableString &name, |
203 | SymbolType symbolType, |
204 | const TType *retType, |
205 | bool knownToNotHaveSideEffects); |
206 | |
207 | void addParameter(const TVariable *p); |
208 | void shareParameters(const TFunction &); |
209 | |
210 | ImmutableString getFunctionMangledName() const |
211 | { |
212 | ASSERT(symbolType() != SymbolType::BuiltIn); |
213 | if (mMangledName.empty()) |
214 | { |
215 | mMangledName = buildMangledName(); |
216 | } |
217 | return mMangledName; |
218 | } |
219 | |
220 | const TType &getReturnType() const { return *returnType; } |
221 | |
222 | TOperator getBuiltInOp() const { return mOp; } |
223 | |
224 | void setDefined() { defined = true; } |
225 | bool isDefined() { return defined; } |
226 | void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; } |
227 | bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; } |
228 | |
229 | size_t getParamCount() const { return mParamCount; } |
230 | const TVariable *getParam(size_t i) const { return mParameters[i]; } |
231 | |
232 | bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; } |
233 | |
234 | bool isMain() const; |
235 | bool isImageFunction() const; |
236 | bool isAtomicCounterFunction() const; |
237 | bool hasSamplerInStructParams() const; |
238 | |
239 | // Note: Only to be used for static built-in functions! |
240 | constexpr TFunction(const TSymbolUniqueId &id, |
241 | const ImmutableString &name, |
242 | TExtension extension, |
243 | const TVariable *const *parameters, |
244 | size_t paramCount, |
245 | const TType *retType, |
246 | TOperator op, |
247 | bool knownToNotHaveSideEffects) |
248 | : TSymbol(id, name, SymbolType::BuiltIn, extension, SymbolClass::Function), |
249 | mParametersVector(nullptr), |
250 | mParameters(parameters), |
251 | mParamCount(paramCount), |
252 | returnType(retType), |
253 | mMangledName(nullptr), |
254 | mOp(op), |
255 | defined(false), |
256 | mHasPrototypeDeclaration(false), |
257 | mKnownToNotHaveSideEffects(knownToNotHaveSideEffects) |
258 | {} |
259 | |
260 | private: |
261 | ImmutableString buildMangledName() const; |
262 | |
263 | typedef TVector<const TVariable *> TParamVector; |
264 | TParamVector *mParametersVector; |
265 | const TVariable *const *mParameters; |
266 | size_t mParamCount; |
267 | const TType *const returnType; |
268 | mutable ImmutableString mMangledName; |
269 | const TOperator mOp; // Only set for built-ins |
270 | bool defined; |
271 | bool mHasPrototypeDeclaration; |
272 | bool mKnownToNotHaveSideEffects; |
273 | }; |
274 | |
275 | } // namespace sh |
276 | |
277 | #endif // COMPILER_TRANSLATOR_SYMBOL_H_ |
278 | |