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