• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     TSymbol(TSymbolTable *symbolTable,
35             const ImmutableString &name,
36             SymbolType symbolType,
37             SymbolClass symbolClass,
38             const std::array<TExtension, 3u> &extensions);
39 
40     // Note that we can't have a virtual destructor in order to support constexpr symbols. Data is
41     // either statically allocated or pool allocated.
42     ~TSymbol() = default;
43 
44     // Calling name() for empty symbols (symbolType == SymbolType::Empty) generates a similar name
45     // as for internal variables.
46     ImmutableString name() const;
47     // Don't call getMangledName() for empty symbols (symbolType == SymbolType::Empty).
48     ImmutableString getMangledName() const;
49 
isFunction()50     bool isFunction() const { return mSymbolClass == SymbolClass::Function; }
isVariable()51     bool isVariable() const { return mSymbolClass == SymbolClass::Variable; }
isStruct()52     bool isStruct() const { return mSymbolClass == SymbolClass::Struct; }
isInterfaceBlock()53     bool isInterfaceBlock() const { return mSymbolClass == SymbolClass::InterfaceBlock; }
54 
uniqueId()55     const TSymbolUniqueId &uniqueId() const { return mUniqueId; }
symbolType()56     SymbolType symbolType() const { return mSymbolType; }
extensions()57     const std::array<TExtension, 3u> extensions() const { return mExtensions; }
58 
59     template <size_t ExtensionCount>
CreateExtensionList(const std::array<TExtension,ExtensionCount> & extensions)60     constexpr const std::array<TExtension, 3u> CreateExtensionList(
61         const std::array<TExtension, ExtensionCount> &extensions)
62     {
63         switch (extensions.size())
64         {
65             case 1:
66                 return std::array<TExtension, 3u>{
67                     {extensions[0], TExtension::UNDEFINED, TExtension::UNDEFINED}};
68             case 2:
69                 return std::array<TExtension, 3u>{
70                     {extensions[0], extensions[1], TExtension::UNDEFINED}};
71             case 3:
72                 return std::array<TExtension, 3u>{{extensions[0], extensions[1], extensions[2]}};
73             default:
74                 UNREACHABLE();
75                 return std::array<TExtension, 3u>{
76                     {TExtension::UNDEFINED, TExtension::UNDEFINED, TExtension::UNDEFINED}};
77         }
78     }
79 
80   protected:
81     template <size_t ExtensionCount>
TSymbol(const TSymbolUniqueId & id,const ImmutableString & name,SymbolType symbolType,const std::array<TExtension,ExtensionCount> & extensions,SymbolClass symbolClass)82     constexpr TSymbol(const TSymbolUniqueId &id,
83                       const ImmutableString &name,
84                       SymbolType symbolType,
85                       const std::array<TExtension, ExtensionCount> &extensions,
86                       SymbolClass symbolClass)
87         : mName(name),
88           mUniqueId(id),
89           mExtensions(CreateExtensionList(extensions)),
90           mSymbolType(symbolType),
91           mSymbolClass(symbolClass)
92     {}
93 
94     const ImmutableString mName;
95 
96   private:
97     const TSymbolUniqueId mUniqueId;
98     const std::array<TExtension, 3u> mExtensions;
99     const SymbolType mSymbolType : 4;
100 
101     // We use this instead of having virtual functions for querying the class in order to support
102     // constexpr symbols.
103     const SymbolClass mSymbolClass : 4;
104 };
105 
106 static_assert(sizeof(TSymbol) <= 24, "Size check failed");
107 
108 // Variable.
109 // May store the value of a constant variable of any type (float, int, bool or struct).
110 class TVariable : public TSymbol
111 {
112   public:
113     TVariable(TSymbolTable *symbolTable,
114               const ImmutableString &name,
115               const TType *type,
116               SymbolType symbolType,
117               TExtension ext = TExtension::UNDEFINED);
118 
119     TVariable(TSymbolTable *symbolTable,
120               const ImmutableString &name,
121               const TType *type,
122               SymbolType symbolType,
123               const std::array<TExtension, 3u> &extensions);
124 
getType()125     const TType &getType() const { return *mType; }
126 
getConstPointer()127     const TConstantUnion *getConstPointer() const { return unionArray; }
128 
shareConstPointer(const TConstantUnion * constArray)129     void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; }
130 
131     // 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)132     constexpr TVariable(const TSymbolUniqueId &id,
133                         const ImmutableString &name,
134                         SymbolType symbolType,
135                         TExtension extension,
136                         const TType *type)
137         : TSymbol(id,
138                   name,
139                   symbolType,
140                   std::array<TExtension, 1u>{{extension}},
141                   SymbolClass::Variable),
142           mType(type),
143           unionArray(nullptr)
144     {}
145 
146     template <size_t ExtensionCount>
TVariable(const TSymbolUniqueId & id,const ImmutableString & name,SymbolType symbolType,const std::array<TExtension,ExtensionCount> & extensions,const TType * type)147     constexpr TVariable(const TSymbolUniqueId &id,
148                         const ImmutableString &name,
149                         SymbolType symbolType,
150                         const std::array<TExtension, ExtensionCount> &extensions,
151                         const TType *type)
152         : TSymbol(id, name, symbolType, extensions, SymbolClass::Variable),
153           mType(type),
154           unionArray(nullptr)
155     {}
156 
157   private:
158     const TType *mType;
159     const TConstantUnion *unionArray;
160 };
161 
162 // Struct type.
163 class TStructure : public TSymbol, public TFieldListCollection
164 {
165   public:
166     TStructure(TSymbolTable *symbolTable,
167                const ImmutableString &name,
168                const TFieldList *fields,
169                SymbolType symbolType);
170 
171     // The char arrays passed in must be pool allocated or static.
172     void createSamplerSymbols(const char *namePrefix,
173                               const TString &apiNamePrefix,
174                               TVector<const TVariable *> *outputSymbols,
175                               TMap<const TVariable *, TString> *outputSymbolsToAPINames,
176                               TSymbolTable *symbolTable) const;
177 
setAtGlobalScope(bool atGlobalScope)178     void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; }
atGlobalScope()179     bool atGlobalScope() const { return mAtGlobalScope; }
180 
181   private:
182     friend class TSymbolTable;
183     // For creating built-in structs.
TStructure(const TSymbolUniqueId & id,const ImmutableString & name,TExtension extension,const TFieldList * fields)184     TStructure(const TSymbolUniqueId &id,
185                const ImmutableString &name,
186                TExtension extension,
187                const TFieldList *fields)
188         : TSymbol(id,
189                   name,
190                   SymbolType::BuiltIn,
191                   std::array<TExtension, 1u>{{extension}},
192                   SymbolClass::Struct),
193           TFieldListCollection(fields)
194     {}
195 
196     template <size_t ExtensionCount>
TStructure(const TSymbolUniqueId & id,const ImmutableString & name,const std::array<TExtension,ExtensionCount> & extensions,const TFieldList * fields)197     TStructure(const TSymbolUniqueId &id,
198                const ImmutableString &name,
199                const std::array<TExtension, ExtensionCount> &extensions,
200                const TFieldList *fields)
201         : TSymbol(id, name, SymbolType::BuiltIn, extensions, SymbolClass::Struct),
202           TFieldListCollection(fields)
203     {}
204 
205     // TODO(zmo): Find a way to get rid of the const_cast in function
206     // setName().  At the moment keep this function private so only
207     // friend class RegenerateStructNames may call it.
208     friend class RegenerateStructNamesTraverser;
209     void setName(const ImmutableString &name);
210 
211     bool mAtGlobalScope;
212 };
213 
214 // Interface block. Note that this contains the block name, not the instance name. Interface block
215 // instances are stored as TVariable.
216 class TInterfaceBlock : public TSymbol, public TFieldListCollection
217 {
218   public:
219     TInterfaceBlock(TSymbolTable *symbolTable,
220                     const ImmutableString &name,
221                     const TFieldList *fields,
222                     const TLayoutQualifier &layoutQualifier,
223                     SymbolType symbolType,
224                     TExtension extension = TExtension::UNDEFINED);
225 
226     TInterfaceBlock(TSymbolTable *symbolTable,
227                     const ImmutableString &name,
228                     const TFieldList *fields,
229                     const TLayoutQualifier &layoutQualifier,
230                     SymbolType symbolType,
231                     const std::array<TExtension, 3u> &extensions);
232 
blockStorage()233     TLayoutBlockStorage blockStorage() const { return mBlockStorage; }
blockBinding()234     int blockBinding() const { return mBinding; }
235 
236   private:
237     friend class TSymbolTable;
238     // For creating built-in interface blocks.
TInterfaceBlock(const TSymbolUniqueId & id,const ImmutableString & name,TExtension extension,const TFieldList * fields)239     TInterfaceBlock(const TSymbolUniqueId &id,
240                     const ImmutableString &name,
241                     TExtension extension,
242                     const TFieldList *fields)
243         : TSymbol(id,
244                   name,
245                   SymbolType::BuiltIn,
246                   std::array<TExtension, 1u>{{extension}},
247                   SymbolClass::InterfaceBlock),
248           TFieldListCollection(fields),
249           mBlockStorage(EbsUnspecified),
250           mBinding(0)
251     {}
252 
253     template <size_t ExtensionCount>
TInterfaceBlock(const TSymbolUniqueId & id,const ImmutableString & name,const std::array<TExtension,ExtensionCount> & extensions,const TFieldList * fields)254     TInterfaceBlock(const TSymbolUniqueId &id,
255                     const ImmutableString &name,
256                     const std::array<TExtension, ExtensionCount> &extensions,
257                     const TFieldList *fields)
258         : TSymbol(id, name, SymbolType::BuiltIn, extensions, SymbolClass::InterfaceBlock),
259           TFieldListCollection(fields),
260           mBlockStorage(EbsUnspecified),
261           mBinding(0)
262     {}
263 
264     TLayoutBlockStorage mBlockStorage;
265     int mBinding;
266 
267     // Note that we only record matrix packing on a per-field granularity.
268 };
269 
270 // Parameter class used for parsing user-defined function parameters.
271 struct TParameter
272 {
273     // Destructively converts to TVariable.
274     // This method resets name and type to nullptrs to make sure
275     // their content cannot be modified after the call.
createVariableTParameter276     const TVariable *createVariable(TSymbolTable *symbolTable)
277     {
278         const ImmutableString constName(name);
279         const TType *constType = type;
280         name                   = nullptr;
281         type                   = nullptr;
282         return new TVariable(symbolTable, constName, constType,
283                              constName.empty() ? SymbolType::Empty : SymbolType::UserDefined);
284     }
285 
286     const char *name;  // either pool allocated or static.
287     TType *type;
288 };
289 
290 // The function sub-class of a symbol.
291 class TFunction : public TSymbol
292 {
293   public:
294     // User-defined function
295     TFunction(TSymbolTable *symbolTable,
296               const ImmutableString &name,
297               SymbolType symbolType,
298               const TType *retType,
299               bool knownToNotHaveSideEffects);
300 
301     void addParameter(const TVariable *p);
302     void shareParameters(const TFunction &parametersSource);
303 
getFunctionMangledName()304     ImmutableString getFunctionMangledName() const
305     {
306         ASSERT(symbolType() != SymbolType::BuiltIn);
307         if (mMangledName.empty())
308         {
309             mMangledName = buildMangledName();
310         }
311         return mMangledName;
312     }
313 
getReturnType()314     const TType &getReturnType() const { return *returnType; }
315 
getBuiltInOp()316     TOperator getBuiltInOp() const { return mOp; }
317 
setDefined()318     void setDefined() { defined = true; }
isDefined()319     bool isDefined() const { return defined; }
setHasPrototypeDeclaration()320     void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; }
hasPrototypeDeclaration()321     bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; }
setHasVoidParameter()322     void setHasVoidParameter() { mHasVoidParameter = true; }
hasVoidParameter()323     bool hasVoidParameter() const { return mHasVoidParameter; }
324 
getParamCount()325     size_t getParamCount() const { return mParamCount; }
getParam(size_t i)326     const TVariable *getParam(size_t i) const { return mParameters[i]; }
327 
isKnownToNotHaveSideEffects()328     bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; }
329 
330     bool isMain() const;
331     bool isImageFunction() const;
332     bool isAtomicCounterFunction() const;
333 
334     // 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)335     constexpr TFunction(const TSymbolUniqueId &id,
336                         const ImmutableString &name,
337                         TExtension extension,
338                         const TVariable *const *parameters,
339                         size_t paramCount,
340                         const TType *retType,
341                         TOperator op,
342                         bool knownToNotHaveSideEffects)
343         : TSymbol(id,
344                   name,
345                   SymbolType::BuiltIn,
346                   std::array<TExtension, 1u>{{extension}},
347                   SymbolClass::Function),
348           mParametersVector(nullptr),
349           mParameters(parameters),
350           returnType(retType),
351           mMangledName(nullptr),
352           mParamCount(paramCount),
353           mOp(op),
354           defined(false),
355           mHasPrototypeDeclaration(false),
356           mKnownToNotHaveSideEffects(knownToNotHaveSideEffects),
357           mHasVoidParameter(false)
358     {}
359 
360     template <size_t ExtensionCount>
TFunction(const TSymbolUniqueId & id,const ImmutableString & name,const std::array<TExtension,ExtensionCount> & extensions,const TVariable * const * parameters,size_t paramCount,const TType * retType,TOperator op,bool knownToNotHaveSideEffects)361     constexpr TFunction(const TSymbolUniqueId &id,
362                         const ImmutableString &name,
363                         const std::array<TExtension, ExtensionCount> &extensions,
364                         const TVariable *const *parameters,
365                         size_t paramCount,
366                         const TType *retType,
367                         TOperator op,
368                         bool knownToNotHaveSideEffects)
369         : TSymbol(id, name, SymbolType::BuiltIn, extensions, SymbolClass::Function),
370           mParametersVector(nullptr),
371           mParameters(parameters),
372           returnType(retType),
373           mMangledName(nullptr),
374           mParamCount(paramCount),
375           mOp(op),
376           defined(false),
377           mHasPrototypeDeclaration(false),
378           mKnownToNotHaveSideEffects(knownToNotHaveSideEffects),
379           mHasVoidParameter(false)
380     {}
381 
382   private:
383     ImmutableString buildMangledName() const;
384 
385     typedef TVector<const TVariable *> TParamVector;
386     TParamVector *mParametersVector;
387     const TVariable *const *mParameters;
388     const TType *const returnType;
389     mutable ImmutableString mMangledName;
390     size_t mParamCount : 32;
391     const TOperator mOp;  // Only set for built-ins
392     bool defined : 1;
393     bool mHasPrototypeDeclaration : 1;
394     bool mKnownToNotHaveSideEffects : 1;
395     // Whether the parameter list of the function starts with void.  This is used to generate an
396     // error if any other parameter follows.
397     bool mHasVoidParameter : 1;
398 };
399 
400 }  // namespace sh
401 
402 #endif  // COMPILER_TRANSLATOR_SYMBOL_H_
403