1 //
2 // Copyright 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 
isFunction()44     bool isFunction() const { return mSymbolClass == SymbolClass::Function; }
isVariable()45     bool isVariable() const { return mSymbolClass == SymbolClass::Variable; }
isStruct()46     bool isStruct() const { return mSymbolClass == SymbolClass::Struct; }
isInterfaceBlock()47     bool isInterfaceBlock() const { return mSymbolClass == SymbolClass::InterfaceBlock; }
48 
uniqueId()49     const TSymbolUniqueId &uniqueId() const { return mUniqueId; }
symbolType()50     SymbolType symbolType() const { return mSymbolType; }
extension()51     TExtension extension() const { return mExtension; }
52 
53   protected:
TSymbol(const TSymbolUniqueId & id,const ImmutableString & name,SymbolType symbolType,TExtension extension,SymbolClass symbolClass)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 
getType()89     const TType &getType() const { return *mType; }
90 
getConstPointer()91     const TConstantUnion *getConstPointer() const { return unionArray; }
92 
shareConstPointer(const TConstantUnion * constArray)93     void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; }
94 
95     // Note: only to be used for built-in variables with autogenerated ids!
TVariable(const TSymbolUniqueId & id,const ImmutableString & name,SymbolType symbolType,TExtension extension,const TType * type)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 
setAtGlobalScope(bool atGlobalScope)127     void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; }
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 RegenerateStructNamesTraverser;
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 
blockStorage()159     TLayoutBlockStorage blockStorage() const { return mBlockStorage; }
blockBinding()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.
createVariableTParameter182     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 &parametersSource);
209 
getFunctionMangledName()210     ImmutableString getFunctionMangledName() const
211     {
212         ASSERT(symbolType() != SymbolType::BuiltIn);
213         if (mMangledName.empty())
214         {
215             mMangledName = buildMangledName();
216         }
217         return mMangledName;
218     }
219 
getReturnType()220     const TType &getReturnType() const { return *returnType; }
221 
getBuiltInOp()222     TOperator getBuiltInOp() const { return mOp; }
223 
setDefined()224     void setDefined() { defined = true; }
isDefined()225     bool isDefined() { return defined; }
setHasPrototypeDeclaration()226     void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; }
hasPrototypeDeclaration()227     bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; }
228 
getParamCount()229     size_t getParamCount() const { return mParamCount; }
getParam(size_t i)230     const TVariable *getParam(size_t i) const { return mParameters[i]; }
231 
isKnownToNotHaveSideEffects()232     bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; }
233 
234     bool isMain() const;
235     bool isImageFunction() const;
236     bool isAtomicCounterFunction() const;
237     bool hasSamplerInStructOrArrayParams() const;
238     bool hasSamplerInStructOrArrayOfArrayParams() const;
239 
240     // Note: Only to be used for static built-in functions!
TFunction(const TSymbolUniqueId & id,const ImmutableString & name,TExtension extension,const TVariable * const * parameters,size_t paramCount,const TType * retType,TOperator op,bool knownToNotHaveSideEffects)241     constexpr TFunction(const TSymbolUniqueId &id,
242                         const ImmutableString &name,
243                         TExtension extension,
244                         const TVariable *const *parameters,
245                         size_t paramCount,
246                         const TType *retType,
247                         TOperator op,
248                         bool knownToNotHaveSideEffects)
249         : TSymbol(id, name, SymbolType::BuiltIn, extension, SymbolClass::Function),
250           mParametersVector(nullptr),
251           mParameters(parameters),
252           mParamCount(paramCount),
253           returnType(retType),
254           mMangledName(nullptr),
255           mOp(op),
256           defined(false),
257           mHasPrototypeDeclaration(false),
258           mKnownToNotHaveSideEffects(knownToNotHaveSideEffects)
259     {}
260 
261   private:
262     ImmutableString buildMangledName() const;
263 
264     typedef TVector<const TVariable *> TParamVector;
265     TParamVector *mParametersVector;
266     const TVariable *const *mParameters;
267     size_t mParamCount;
268     const TType *const returnType;
269     mutable ImmutableString mMangledName;
270     const TOperator mOp;  // Only set for built-ins
271     bool defined;
272     bool mHasPrototypeDeclaration;
273     bool mKnownToNotHaveSideEffects;
274 };
275 
276 }  // namespace sh
277 
278 #endif  // COMPILER_TRANSLATOR_SYMBOL_H_
279