1 //
2 // Copyright (c) 2002-2013 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 
7 #ifndef COMPILER_TRANSLATOR_TYPES_H_
8 #define COMPILER_TRANSLATOR_TYPES_H_
9 
10 #include "common/angleutils.h"
11 #include "common/debug.h"
12 
13 #include "compiler/translator/BaseTypes.h"
14 #include "compiler/translator/Common.h"
15 #include "compiler/translator/SymbolUniqueId.h"
16 
17 namespace sh
18 {
19 
20 struct TPublicType;
21 class TType;
22 class TSymbol;
23 class TIntermSymbol;
24 class TSymbolTable;
25 
26 class TField : angle::NonCopyable
27 {
28   public:
29     POOL_ALLOCATOR_NEW_DELETE();
TField(TType * type,TString * name,const TSourceLoc & line)30     TField(TType *type, TString *name, const TSourceLoc &line)
31         : mType(type), mName(name), mLine(line)
32     {
33     }
34 
35     // TODO(alokp): We should only return const type.
36     // Fix it by tweaking grammar.
type()37     TType *type() { return mType; }
type()38     const TType *type() const { return mType; }
39 
name()40     const TString &name() const { return *mName; }
line()41     const TSourceLoc &line() const { return mLine; }
42 
43   private:
44     TType *mType;
45     TString *mName;
46     TSourceLoc mLine;
47 };
48 
49 typedef TVector<TField *> TFieldList;
NewPoolTFieldList()50 inline TFieldList *NewPoolTFieldList()
51 {
52     void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
53     return new (memory) TFieldList;
54 }
55 
56 class TFieldListCollection : angle::NonCopyable
57 {
58   public:
name()59     const TString &name() const { return *mName; }
fields()60     const TFieldList &fields() const { return *mFields; }
61 
objectSize()62     size_t objectSize() const
63     {
64         if (mObjectSize == 0)
65             mObjectSize = calculateObjectSize();
66         return mObjectSize;
67     }
68 
69     // How many locations the field list consumes as a uniform.
70     int getLocationCount() const;
71 
72   protected:
TFieldListCollection(const TString * name,TFieldList * fields)73     TFieldListCollection(const TString *name, TFieldList *fields)
74         : mName(name), mFields(fields), mObjectSize(0)
75     {
76     }
77     TString buildMangledName(const TString &mangledNamePrefix) const;
78     size_t calculateObjectSize() const;
79 
80     const TString *mName;
81     TFieldList *mFields;
82 
83     mutable TString mMangledName;
84     mutable size_t mObjectSize;
85 };
86 
87 // May also represent interface blocks
88 class TStructure : public TFieldListCollection
89 {
90   public:
91     POOL_ALLOCATOR_NEW_DELETE();
92     TStructure(TSymbolTable *symbolTable, const TString *name, TFieldList *fields);
93 
deepestNesting()94     int deepestNesting() const
95     {
96         if (mDeepestNesting == 0)
97             mDeepestNesting = calculateDeepestNesting();
98         return mDeepestNesting;
99     }
100     bool containsArrays() const;
101     bool containsType(TBasicType t) const;
102     bool containsSamplers() const;
103 
104     void createSamplerSymbols(const TString &namePrefix,
105                               const TString &apiNamePrefix,
106                               TVector<TIntermSymbol *> *outputSymbols,
107                               TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
108                               TSymbolTable *symbolTable) const;
109 
110     bool equals(const TStructure &other) const;
111 
uniqueId()112     int uniqueId() const { return mUniqueId.get(); }
113 
setAtGlobalScope(bool atGlobalScope)114     void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; }
115 
atGlobalScope()116     bool atGlobalScope() const { return mAtGlobalScope; }
117 
mangledName()118     const TString &mangledName() const
119     {
120         if (mMangledName.empty())
121             mMangledName = buildMangledName("struct-");
122         return mMangledName;
123     }
124 
125   private:
126     // TODO(zmo): Find a way to get rid of the const_cast in function
127     // setName().  At the moment keep this function private so only
128     // friend class RegenerateStructNames may call it.
129     friend class RegenerateStructNames;
setName(const TString & name)130     void setName(const TString &name)
131     {
132         TString *mutableName = const_cast<TString *>(mName);
133         *mutableName         = name;
134     }
135 
136     int calculateDeepestNesting() const;
137 
138     mutable int mDeepestNesting;
139     const TSymbolUniqueId mUniqueId;
140     bool mAtGlobalScope;
141 };
142 
143 class TInterfaceBlock : public TFieldListCollection
144 {
145   public:
146     POOL_ALLOCATOR_NEW_DELETE();
TInterfaceBlock(const TString * name,TFieldList * fields,const TString * instanceName,const TLayoutQualifier & layoutQualifier)147     TInterfaceBlock(const TString *name,
148                     TFieldList *fields,
149                     const TString *instanceName,
150                     const TLayoutQualifier &layoutQualifier)
151         : TFieldListCollection(name, fields),
152           mInstanceName(instanceName),
153           mBlockStorage(layoutQualifier.blockStorage),
154           mMatrixPacking(layoutQualifier.matrixPacking),
155           mBinding(layoutQualifier.binding)
156     {
157     }
158 
instanceName()159     const TString &instanceName() const { return *mInstanceName; }
hasInstanceName()160     bool hasInstanceName() const { return mInstanceName != nullptr; }
blockStorage()161     TLayoutBlockStorage blockStorage() const { return mBlockStorage; }
matrixPacking()162     TLayoutMatrixPacking matrixPacking() const { return mMatrixPacking; }
blockBinding()163     int blockBinding() const { return mBinding; }
mangledName()164     const TString &mangledName() const
165     {
166         if (mMangledName.empty())
167             mMangledName = buildMangledName("iblock-");
168         return mMangledName;
169     }
170 
171   private:
172     const TString *mInstanceName;  // for interface block instance names
173     TLayoutBlockStorage mBlockStorage;
174     TLayoutMatrixPacking mMatrixPacking;
175     int mBinding;
176 };
177 
178 //
179 // Base class for things that have a type.
180 //
181 class TType
182 {
183   public:
184     POOL_ALLOCATOR_NEW_DELETE();
185     TType();
186     explicit TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1);
187     TType(TBasicType t,
188           TPrecision p,
189           TQualifier q     = EvqTemporary,
190           unsigned char ps = 1,
191           unsigned char ss = 1);
192     explicit TType(const TPublicType &p);
193     explicit TType(TStructure *userDef);
194     TType(TInterfaceBlock *interfaceBlockIn,
195           TQualifier qualifierIn,
196           TLayoutQualifier layoutQualifierIn);
197     TType(const TType &t);
198     TType &operator=(const TType &t);
199 
getBasicType()200     TBasicType getBasicType() const { return type; }
201     void setBasicType(TBasicType t);
202 
getPrecision()203     TPrecision getPrecision() const { return precision; }
setPrecision(TPrecision p)204     void setPrecision(TPrecision p) { precision = p; }
205 
getQualifier()206     TQualifier getQualifier() const { return qualifier; }
setQualifier(TQualifier q)207     void setQualifier(TQualifier q) { qualifier = q; }
208 
isInvariant()209     bool isInvariant() const { return invariant; }
210 
setInvariant(bool i)211     void setInvariant(bool i) { invariant = i; }
212 
getMemoryQualifier()213     TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; }
setMemoryQualifier(const TMemoryQualifier & mq)214     void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; }
215 
getLayoutQualifier()216     TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; }
setLayoutQualifier(TLayoutQualifier lq)217     void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; }
218 
getNominalSize()219     int getNominalSize() const { return primarySize; }
getSecondarySize()220     int getSecondarySize() const { return secondarySize; }
getCols()221     int getCols() const
222     {
223         ASSERT(isMatrix());
224         return primarySize;
225     }
getRows()226     int getRows() const
227     {
228         ASSERT(isMatrix());
229         return secondarySize;
230     }
231     void setPrimarySize(unsigned char ps);
232     void setSecondarySize(unsigned char ss);
233 
234     // Full size of single instance of type
235     size_t getObjectSize() const;
236 
237     // Get how many locations this type consumes as a uniform.
238     int getLocationCount() const;
239 
isMatrix()240     bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
isNonSquareMatrix()241     bool isNonSquareMatrix() const { return isMatrix() && primarySize != secondarySize; }
isArray()242     bool isArray() const { return mArraySizes != nullptr && !mArraySizes->empty(); }
isArrayOfArrays()243     bool isArrayOfArrays() const { return isArray() && mArraySizes->size() > 1u; }
getNumArraySizes()244     size_t getNumArraySizes() const { return isArray() ? mArraySizes->size() : 0; }
getArraySizes()245     const TVector<unsigned int> *getArraySizes() const { return mArraySizes; }
246     unsigned int getArraySizeProduct() const;
247     bool isUnsizedArray() const;
getOutermostArraySize()248     unsigned int getOutermostArraySize() const {
249          ASSERT(isArray());
250          return mArraySizes->back();
251     }
252     void makeArray(unsigned int s);
253 
254     // sizes contain new outermost array sizes.
255     void makeArrays(const TVector<unsigned int> &sizes);
256     // Here, the array dimension value 0 corresponds to the innermost array.
257     void setArraySize(size_t arrayDimension, unsigned int s);
258 
259     // Will set unsized array sizes according to newArraySizes. In case there are more
260     // unsized arrays than there are sizes in newArraySizes, defaults to setting any
261     // remaining array sizes to 1.
262     void sizeUnsizedArrays(const TVector<unsigned int> *newArraySizes);
263 
264     // Will size the outermost array according to arraySize.
265     void sizeOutermostUnsizedArray(unsigned int arraySize);
266 
267     // Note that the array element type might still be an array type in GLSL ES version >= 3.10.
268     void toArrayElementType();
269 
getInterfaceBlock()270     TInterfaceBlock *getInterfaceBlock() const { return mInterfaceBlock; }
271     void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn);
isInterfaceBlock()272     bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
273 
isVector()274     bool isVector() const { return primarySize > 1 && secondarySize == 1; }
isScalar()275     bool isScalar() const
276     {
277         return primarySize == 1 && secondarySize == 1 && !mStructure && !isArray();
278     }
isScalarFloat()279     bool isScalarFloat() const { return isScalar() && type == EbtFloat; }
isScalarInt()280     bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); }
281 
282     bool canBeConstructed() const;
283 
getStruct()284     TStructure *getStruct() { return mStructure; }
getStruct()285     const TStructure *getStruct() const { return mStructure; }
286     void setStruct(TStructure *s);
287 
288     const char *getMangledName() const;
289 
290     bool sameNonArrayType(const TType &right) const;
291 
292     // Returns true if arrayType is an array made of this type.
293     bool isElementTypeOf(const TType &arrayType) const;
294 
295     bool operator==(const TType &right) const
296     {
297         size_t numArraySizesL = getNumArraySizes();
298         size_t numArraySizesR = right.getNumArraySizes();
299         bool arraySizesEqual  = numArraySizesL == numArraySizesR &&
300                                (numArraySizesL == 0 || *mArraySizes == *right.mArraySizes);
301         return type == right.type && primarySize == right.primarySize &&
302                secondarySize == right.secondarySize && arraySizesEqual &&
303                mStructure == right.mStructure;
304         // don't check the qualifier, it's not ever what's being sought after
305     }
306     bool operator!=(const TType &right) const { return !operator==(right); }
307     bool operator<(const TType &right) const
308     {
309         if (type != right.type)
310             return type < right.type;
311         if (primarySize != right.primarySize)
312             return primarySize < right.primarySize;
313         if (secondarySize != right.secondarySize)
314             return secondarySize < right.secondarySize;
315         size_t numArraySizesL = getNumArraySizes();
316         size_t numArraySizesR = right.getNumArraySizes();
317         if (numArraySizesL != numArraySizesR)
318             return numArraySizesL < numArraySizesR;
319         for (size_t i = 0; i < numArraySizesL; ++i)
320         {
321             if ((*mArraySizes)[i] != (*right.mArraySizes)[i])
322                 return (*mArraySizes)[i] < (*right.mArraySizes)[i];
323         }
324         if (mStructure != right.mStructure)
325             return mStructure < right.mStructure;
326 
327         return false;
328     }
329 
getBasicString()330     const char *getBasicString() const { return sh::getBasicString(type); }
331 
getPrecisionString()332     const char *getPrecisionString() const { return sh::getPrecisionString(precision); }
getQualifierString()333     const char *getQualifierString() const { return sh::getQualifierString(qualifier); }
334 
335     const char *getBuiltInTypeNameString() const;
336 
337     TString getCompleteString() const;
338 
339     // If this type is a struct, returns the deepest struct nesting of
340     // any field in the struct. For example:
341     //   struct nesting1 {
342     //     vec4 position;
343     //   };
344     //   struct nesting2 {
345     //     nesting1 field1;
346     //     vec4 field2;
347     //   };
348     // For type "nesting2", this method would return 2 -- the number
349     // of structures through which indirection must occur to reach the
350     // deepest field (nesting2.field1.position).
getDeepestStructNesting()351     int getDeepestStructNesting() const { return mStructure ? mStructure->deepestNesting() : 0; }
352 
isNamelessStruct()353     bool isNamelessStruct() const { return mStructure && mStructure->name() == ""; }
354 
isStructureContainingArrays()355     bool isStructureContainingArrays() const
356     {
357         return mStructure ? mStructure->containsArrays() : false;
358     }
359 
isStructureContainingType(TBasicType t)360     bool isStructureContainingType(TBasicType t) const
361     {
362         return mStructure ? mStructure->containsType(t) : false;
363     }
364 
isStructureContainingSamplers()365     bool isStructureContainingSamplers() const
366     {
367         return mStructure ? mStructure->containsSamplers() : false;
368     }
369 
isStructSpecifier()370     bool isStructSpecifier() const { return mIsStructSpecifier; }
371 
372     void createSamplerSymbols(const TString &namePrefix,
373                               const TString &apiNamePrefix,
374                               TVector<TIntermSymbol *> *outputSymbols,
375                               TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
376                               TSymbolTable *symbolTable) const;
377 
378     // Initializes all lazily-initialized members.
379     void realize();
380 
381   private:
382     void invalidateMangledName();
383     const char *buildMangledName() const;
384 
385     TBasicType type;
386     TPrecision precision;
387     TQualifier qualifier;
388     bool invariant;
389     TMemoryQualifier memoryQualifier;
390     TLayoutQualifier layoutQualifier;
391     unsigned char primarySize;    // size of vector or cols matrix
392     unsigned char secondarySize;  // rows of a matrix
393 
394     // Used to make an array type. Outermost array size is stored at the end of the vector. Having 0
395     // in this vector means an unsized array.
396     TVector<unsigned int> *mArraySizes;
397 
398     // This is set only in the following two cases:
399     // 1) Represents an interface block.
400     // 2) Represents the member variable of an unnamed interface block.
401     // It's nullptr also for members of named interface blocks.
402     TInterfaceBlock *mInterfaceBlock;
403 
404     // 0 unless this is a struct
405     TStructure *mStructure;
406     bool mIsStructSpecifier;
407 
408     mutable const char *mMangledName;
409 };
410 
411 // TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the
412 // grammar
413 struct TTypeSpecifierNonArray
414 {
415     TBasicType type;
416     unsigned char primarySize;    // size of vector or cols of matrix
417     unsigned char secondarySize;  // rows of matrix
418     TStructure *userDef;
419     TSourceLoc line;
420 
421     // true if the type was defined by a struct specifier rather than a reference to a type name.
422     bool isStructSpecifier;
423 
initializeTTypeSpecifierNonArray424     void initialize(TBasicType aType, const TSourceLoc &aLine)
425     {
426         ASSERT(aType != EbtStruct);
427         type              = aType;
428         primarySize       = 1;
429         secondarySize     = 1;
430         userDef           = nullptr;
431         line              = aLine;
432         isStructSpecifier = false;
433     }
434 
initializeStructTTypeSpecifierNonArray435     void initializeStruct(TStructure *aUserDef, bool aIsStructSpecifier, const TSourceLoc &aLine)
436     {
437         type              = EbtStruct;
438         primarySize       = 1;
439         secondarySize     = 1;
440         userDef           = aUserDef;
441         line              = aLine;
442         isStructSpecifier = aIsStructSpecifier;
443     }
444 
setAggregateTTypeSpecifierNonArray445     void setAggregate(unsigned char size) { primarySize = size; }
446 
setMatrixTTypeSpecifierNonArray447     void setMatrix(unsigned char columns, unsigned char rows)
448     {
449         ASSERT(columns > 1 && rows > 1 && columns <= 4 && rows <= 4);
450         primarySize   = columns;
451         secondarySize = rows;
452     }
453 
isMatrixTTypeSpecifierNonArray454     bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
455 
isVectorTTypeSpecifierNonArray456     bool isVector() const { return primarySize > 1 && secondarySize == 1; }
457 };
458 
459 //
460 // This is a workaround for a problem with the yacc stack,  It can't have
461 // types that it thinks have non-trivial constructors.  It should
462 // just be used while recognizing the grammar, not anything else.  Pointers
463 // could be used, but also trying to avoid lots of memory management overhead.
464 //
465 // Not as bad as it looks, there is no actual assumption that the fields
466 // match up or are name the same or anything like that.
467 //
468 struct TPublicType
469 {
470     // Must have a trivial default constructor since it is used in YYSTYPE.
471     TPublicType() = default;
472 
473     void initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q);
474     void initializeBasicType(TBasicType basicType);
475 
getBasicTypeTPublicType476     TBasicType getBasicType() const { return typeSpecifierNonArray.type; }
setBasicTypeTPublicType477     void setBasicType(TBasicType basicType) { typeSpecifierNonArray.type = basicType; }
478 
getPrimarySizeTPublicType479     unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; }
getSecondarySizeTPublicType480     unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; }
481 
getUserDefTPublicType482     TStructure *getUserDef() const { return typeSpecifierNonArray.userDef; }
getLineTPublicType483     const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; }
484 
isStructSpecifierTPublicType485     bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; }
486 
487     bool isStructureContainingArrays() const;
488     bool isStructureContainingType(TBasicType t) const;
489     void setArraySizes(TVector<unsigned int> *sizes);
490     bool isArray() const;
491     void clearArrayness();
492     bool isAggregate() const;
493 
494     TTypeSpecifierNonArray typeSpecifierNonArray;
495     TLayoutQualifier layoutQualifier;
496     TMemoryQualifier memoryQualifier;
497     TQualifier qualifier;
498     bool invariant;
499     TPrecision precision;
500 
501     // Either nullptr or empty in case the type is not an array. The last element is the outermost
502     // array size. Note that due to bison restrictions, copies of the public type created by the
503     // copy constructor share the same arraySizes pointer.
504     const TVector<unsigned int> *arraySizes;
505 };
506 
507 }  // namespace sh
508 
509 #endif  // COMPILER_TRANSLATOR_TYPES_H_
510