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     // Turns a matrix into a column of it.
231     void toMatrixColumnType();
232 
getInterfaceBlock()233     const TInterfaceBlock *getInterfaceBlock() const { return mInterfaceBlock; }
234     void setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn);
isInterfaceBlock()235     bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
236 
237     void setInterfaceBlockField(const TInterfaceBlock *interfaceBlockIn, size_t fieldIndex);
getInterfaceBlockFieldIndex()238     size_t getInterfaceBlockFieldIndex() const { return mInterfaceBlockFieldIndex; }
239 
isVector()240     bool isVector() const { return primarySize > 1 && secondarySize == 1; }
isVectorArray()241     bool isVectorArray() const { return primarySize > 1 && secondarySize == 1 && isArray(); }
isRank0()242     bool isRank0() const { return primarySize == 1 && secondarySize == 1; }
isScalar()243     bool isScalar() const
244     {
245         return primarySize == 1 && secondarySize == 1 && !mStructure && !isArray();
246     }
isScalarArray()247     bool isScalarArray() const
248     {
249         return primarySize == 1 && secondarySize == 1 && !mStructure && isArray();
250     }
isScalarFloat()251     bool isScalarFloat() const { return isScalar() && type == EbtFloat; }
isScalarInt()252     bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); }
253 
254     bool canBeConstructed() const;
255 
getStruct()256     const TStructure *getStruct() const { return mStructure; }
257 
GetSizeMangledName(unsigned char primarySize,unsigned char secondarySize)258     static constexpr char GetSizeMangledName(unsigned char primarySize, unsigned char secondarySize)
259     {
260         unsigned int sizeKey = (secondarySize - 1u) * 4u + primarySize - 1u;
261         if (sizeKey < 10u)
262         {
263             return static_cast<char>('0' + sizeKey);
264         }
265         return static_cast<char>('A' + sizeKey - 10);
266     }
267     const char *getMangledName() const;
268 
269     bool sameNonArrayType(const TType &right) const;
270 
271     // Returns true if arrayType is an array made of this type.
272     bool isElementTypeOf(const TType &arrayType) const;
273 
274     bool operator==(const TType &right) const
275     {
276         size_t numArraySizesL = getNumArraySizes();
277         size_t numArraySizesR = right.getNumArraySizes();
278         bool arraySizesEqual  = numArraySizesL == numArraySizesR &&
279                                (numArraySizesL == 0 || mArraySizes == right.mArraySizes);
280         return type == right.type && primarySize == right.primarySize &&
281                secondarySize == right.secondarySize && arraySizesEqual &&
282                mStructure == right.mStructure;
283         // don't check the qualifier, it's not ever what's being sought after
284     }
285     bool operator!=(const TType &right) const { return !operator==(right); }
286     bool operator<(const TType &right) const
287     {
288         if (type != right.type)
289             return type < right.type;
290         if (primarySize != right.primarySize)
291             return primarySize < right.primarySize;
292         if (secondarySize != right.secondarySize)
293             return secondarySize < right.secondarySize;
294         size_t numArraySizesL = getNumArraySizes();
295         size_t numArraySizesR = right.getNumArraySizes();
296         if (numArraySizesL != numArraySizesR)
297             return numArraySizesL < numArraySizesR;
298         for (size_t i = 0; i < numArraySizesL; ++i)
299         {
300             if (mArraySizes[i] != right.mArraySizes[i])
301                 return mArraySizes[i] < right.mArraySizes[i];
302         }
303         if (mStructure != right.mStructure)
304             return mStructure < right.mStructure;
305 
306         return false;
307     }
308 
getBasicString()309     const char *getBasicString() const { return sh::getBasicString(type); }
310 
getPrecisionString()311     const char *getPrecisionString() const { return sh::getPrecisionString(precision); }
getQualifierString()312     const char *getQualifierString() const { return sh::getQualifierString(qualifier); }
313 
314     const char *getBuiltInTypeNameString() const;
315 
316     // If this type is a struct, returns the deepest struct nesting of
317     // any field in the struct. For example:
318     //   struct nesting1 {
319     //     vec4 position;
320     //   };
321     //   struct nesting2 {
322     //     nesting1 field1;
323     //     vec4 field2;
324     //   };
325     // For type "nesting2", this method would return 2 -- the number
326     // of structures through which indirection must occur to reach the
327     // deepest field (nesting2.field1.position).
328     int getDeepestStructNesting() const;
329 
330     bool isNamelessStruct() const;
331 
332     bool isStructureContainingArrays() const;
333     bool isStructureContainingMatrices() const;
334     bool isStructureContainingType(TBasicType t) const;
335     bool isStructureContainingSamplers() const;
336     bool isInterfaceBlockContainingType(TBasicType t) const;
337 
isStructSpecifier()338     bool isStructSpecifier() const { return mIsStructSpecifier; }
339 
340     // Return true if variables of this type should be replaced with an inline constant value if
341     // such is available. False will be returned in cases where output doesn't support
342     // TIntermConstantUnion nodes of the type, or if the type contains a lot of fields and creating
343     // several copies of it in the output code is undesirable for performance.
344     bool canReplaceWithConstantUnion() const;
345 
346     // The char arrays passed in must be pool allocated or static.
347     void createSamplerSymbols(const ImmutableString &namePrefix,
348                               const TString &apiNamePrefix,
349                               TVector<const TVariable *> *outputSymbols,
350                               TMap<const TVariable *, TString> *outputSymbolsToAPINames,
351                               TSymbolTable *symbolTable) const;
352 
353     // Initializes all lazily-initialized members.
354     void realize();
355 
isSampler()356     bool isSampler() const { return IsSampler(type); }
isSamplerCube()357     bool isSamplerCube() const { return type == EbtSamplerCube; }
isAtomicCounter()358     bool isAtomicCounter() const { return IsAtomicCounter(type); }
isSamplerVideoWEBGL()359     bool isSamplerVideoWEBGL() const { return type == EbtSamplerVideoWEBGL; }
isImage()360     bool isImage() const { return IsImage(type); }
361 
362   private:
invalidateMangledName()363     constexpr void invalidateMangledName() { mMangledName = nullptr; }
364     const char *buildMangledName() const;
onArrayDimensionsChange(const TSpan<const unsigned int> & sizes)365     constexpr void onArrayDimensionsChange(const TSpan<const unsigned int> &sizes)
366     {
367         mArraySizes = sizes;
368         invalidateMangledName();
369     }
370 
371     TBasicType type;
372     TPrecision precision;
373     TQualifier qualifier;
374     bool invariant;
375     bool precise;
376 
377     TMemoryQualifier memoryQualifier;
378     TLayoutQualifier layoutQualifier;
379     unsigned char primarySize;    // size of vector or cols matrix
380     unsigned char secondarySize;  // rows of a matrix
381 
382     // Used to make an array type. Outermost array size is stored at the end of the vector. Having 0
383     // in this vector means an unsized array.
384     TSpan<const unsigned int> mArraySizes;
385     // Storage for mArraySizes, if any.  This is usually the case, except for constexpr TTypes which
386     // only have a valid mArraySizes (with mArraySizesStorage being nullptr).  Therefore, all
387     // modifications to array sizes happen on the storage (and if dimensions change, mArraySizes is
388     // also updated) and all reads are from mArraySizes.
389     TVector<unsigned int> *mArraySizesStorage;
390 
391     // This is set only in the following two cases:
392     // 1) Represents an interface block.
393     // 2) Represents the member variable of an unnamed interface block.
394     // It's nullptr also for members of named interface blocks.
395     const TInterfaceBlock *mInterfaceBlock;
396 
397     // nullptr unless this is a struct
398     const TStructure *mStructure;
399     bool mIsStructSpecifier;
400 
401     // If this is a field of a nameless interface block, this would indicate which member it's
402     // refering to.
403     size_t mInterfaceBlockFieldIndex;
404 
405     mutable const char *mMangledName;
406 };
407 
408 // TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the
409 // grammar
410 struct TTypeSpecifierNonArray
411 {
412     TBasicType type;
413     unsigned char primarySize;    // size of vector or cols of matrix
414     unsigned char secondarySize;  // rows of matrix
415     const TStructure *userDef;
416     TSourceLoc line;
417 
418     // true if the type was defined by a struct specifier rather than a reference to a type name.
419     bool isStructSpecifier;
420 
initializeTTypeSpecifierNonArray421     void initialize(TBasicType aType, const TSourceLoc &aLine)
422     {
423         ASSERT(aType != EbtStruct);
424         type              = aType;
425         primarySize       = 1;
426         secondarySize     = 1;
427         userDef           = nullptr;
428         line              = aLine;
429         isStructSpecifier = false;
430     }
431 
initializeStructTTypeSpecifierNonArray432     void initializeStruct(const TStructure *aUserDef,
433                           bool aIsStructSpecifier,
434                           const TSourceLoc &aLine)
435     {
436         type              = EbtStruct;
437         primarySize       = 1;
438         secondarySize     = 1;
439         userDef           = aUserDef;
440         line              = aLine;
441         isStructSpecifier = aIsStructSpecifier;
442     }
443 
setAggregateTTypeSpecifierNonArray444     void setAggregate(unsigned char size) { primarySize = size; }
445 
setMatrixTTypeSpecifierNonArray446     void setMatrix(unsigned char columns, unsigned char rows)
447     {
448         ASSERT(columns > 1 && rows > 1 && columns <= 4 && rows <= 4);
449         primarySize   = columns;
450         secondarySize = rows;
451     }
452 
isMatrixTTypeSpecifierNonArray453     bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
454 
isVectorTTypeSpecifierNonArray455     bool isVector() const { return primarySize > 1 && secondarySize == 1; }
456 };
457 
458 //
459 // This is a workaround for a problem with the yacc stack,  It can't have
460 // types that it thinks have non-trivial constructors.  It should
461 // just be used while recognizing the grammar, not anything else.  Pointers
462 // could be used, but also trying to avoid lots of memory management overhead.
463 //
464 // Not as bad as it looks, there is no actual assumption that the fields
465 // match up or are name the same or anything like that.
466 //
467 struct TPublicType
468 {
469     // Must have a trivial default constructor since it is used in YYSTYPE.
470     TPublicType() = default;
471 
472     void initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q);
473     void initializeBasicType(TBasicType basicType);
474 
getBasicTypeTPublicType475     TBasicType getBasicType() const { return typeSpecifierNonArray.type; }
setBasicTypeTPublicType476     void setBasicType(TBasicType basicType) { typeSpecifierNonArray.type = basicType; }
477 
getPrimarySizeTPublicType478     unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; }
getSecondarySizeTPublicType479     unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; }
480 
getUserDefTPublicType481     const TStructure *getUserDef() const { return typeSpecifierNonArray.userDef; }
getLineTPublicType482     const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; }
483 
isStructSpecifierTPublicType484     bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; }
485 
486     bool isStructureContainingArrays() const;
487     bool isStructureContainingType(TBasicType t) const;
488     void setArraySizes(TVector<unsigned int> *sizes);
489     bool isArray() const;
490     void clearArrayness();
491     bool isAggregate() const;
492 
493     TTypeSpecifierNonArray typeSpecifierNonArray;
494     TLayoutQualifier layoutQualifier;
495     TMemoryQualifier memoryQualifier;
496     TQualifier qualifier;
497     bool invariant;
498     bool precise;
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