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
18namespace sh
19{
20
21class TSymbolTable;
22
23// Symbol base class. (Can build functions or variables out of these...)
24class 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).
80class 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.
112class 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.
149class 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.
177struct 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.
197class 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 &parametersSource);
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