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