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           mMangledName(mangledName)
132     {}
133 
TType(TType && t)134     constexpr TType(TType &&t)
135         : type(t.type),
136           precision(t.precision),
137           qualifier(t.qualifier),
138           invariant(t.invariant),
139           precise(t.precise),
140           memoryQualifier(t.memoryQualifier),
141           layoutQualifier(t.layoutQualifier),
142           primarySize(t.primarySize),
143           secondarySize(t.secondarySize),
144           mArraySizes(t.mArraySizes),
145           mArraySizesStorage(t.mArraySizesStorage),
146           mInterfaceBlock(t.mInterfaceBlock),
147           mStructure(t.mStructure),
148           mIsStructSpecifier(t.mIsStructSpecifier),
149           mMangledName(t.mMangledName)
150     {
151         t.mArraySizesStorage = nullptr;
152     }
153 
getBasicType()154     constexpr TBasicType getBasicType() const { return type; }
155     void setBasicType(TBasicType t);
156 
getPrecision()157     TPrecision getPrecision() const { return precision; }
setPrecision(TPrecision p)158     void setPrecision(TPrecision p) { precision = p; }
159 
getQualifier()160     constexpr TQualifier getQualifier() const { return qualifier; }
setQualifier(TQualifier q)161     void setQualifier(TQualifier q) { qualifier = q; }
162 
isInvariant()163     bool isInvariant() const { return invariant; }
setInvariant(bool i)164     void setInvariant(bool i) { invariant = i; }
165 
isPrecise()166     bool isPrecise() const { return precise; }
setPrecise(bool i)167     void setPrecise(bool i) { precise = i; }
168 
getMemoryQualifier()169     TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; }
setMemoryQualifier(const TMemoryQualifier & mq)170     void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; }
171 
getLayoutQualifier()172     TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; }
setLayoutQualifier(TLayoutQualifier lq)173     void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; }
174 
getNominalSize()175     int getNominalSize() const { return primarySize; }
getSecondarySize()176     int getSecondarySize() const { return secondarySize; }
getCols()177     int getCols() const
178     {
179         ASSERT(isMatrix());
180         return primarySize;
181     }
getRows()182     int getRows() const
183     {
184         ASSERT(isMatrix());
185         return secondarySize;
186     }
187     void setPrimarySize(unsigned char ps);
188     void setSecondarySize(unsigned char ss);
189 
190     // Full size of single instance of type
191     size_t getObjectSize() const;
192 
193     // Get how many locations this type consumes as a uniform.
194     int getLocationCount() const;
195 
isMatrix()196     bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
isNonSquareMatrix()197     bool isNonSquareMatrix() const { return isMatrix() && primarySize != secondarySize; }
isArray()198     bool isArray() const { return !mArraySizes.empty(); }
isArrayOfArrays()199     bool isArrayOfArrays() const { return mArraySizes.size() > 1u; }
getNumArraySizes()200     size_t getNumArraySizes() const { return mArraySizes.size(); }
getArraySizes()201     const TSpan<const unsigned int> &getArraySizes() const { return mArraySizes; }
202     unsigned int getArraySizeProduct() const;
203     bool isUnsizedArray() const;
getOutermostArraySize()204     unsigned int getOutermostArraySize() const
205     {
206         ASSERT(isArray());
207         return mArraySizes.back();
208     }
209     void makeArray(unsigned int s);
210 
211     // sizes contain new outermost array sizes.
212     void makeArrays(const TSpan<const unsigned int> &sizes);
213     // Here, the array dimension value 0 corresponds to the innermost array.
214     void setArraySize(size_t arrayDimension, unsigned int s);
215 
216     // Will set unsized array sizes according to newArraySizes. In case there are more
217     // unsized arrays than there are sizes in newArraySizes, defaults to setting any
218     // remaining array sizes to 1.
219     void sizeUnsizedArrays(const TSpan<const unsigned int> &newArraySizes);
220 
221     // Will size the outermost array according to arraySize.
222     void sizeOutermostUnsizedArray(unsigned int arraySize);
223 
224     // Note that the array element type might still be an array type in GLSL ES version >= 3.10.
225     void toArrayElementType();
226     // Removes all array sizes.
227     void toArrayBaseType();
228 
getInterfaceBlock()229     const TInterfaceBlock *getInterfaceBlock() const { return mInterfaceBlock; }
230     void setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn);
isInterfaceBlock()231     bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
232 
isVector()233     bool isVector() const { return primarySize > 1 && secondarySize == 1; }
isScalar()234     bool isScalar() const
235     {
236         return primarySize == 1 && secondarySize == 1 && !mStructure && !isArray();
237     }
isScalarFloat()238     bool isScalarFloat() const { return isScalar() && type == EbtFloat; }
isScalarInt()239     bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); }
240 
241     bool canBeConstructed() const;
242 
getStruct()243     const TStructure *getStruct() const { return mStructure; }
244 
GetSizeMangledName(unsigned char primarySize,unsigned char secondarySize)245     static constexpr char GetSizeMangledName(unsigned char primarySize, unsigned char secondarySize)
246     {
247         unsigned int sizeKey = (secondarySize - 1u) * 4u + primarySize - 1u;
248         if (sizeKey < 10u)
249         {
250             return static_cast<char>('0' + sizeKey);
251         }
252         return static_cast<char>('A' + sizeKey - 10);
253     }
254     const char *getMangledName() const;
255 
256     bool sameNonArrayType(const TType &right) const;
257 
258     // Returns true if arrayType is an array made of this type.
259     bool isElementTypeOf(const TType &arrayType) const;
260 
261     bool operator==(const TType &right) const
262     {
263         size_t numArraySizesL = getNumArraySizes();
264         size_t numArraySizesR = right.getNumArraySizes();
265         bool arraySizesEqual  = numArraySizesL == numArraySizesR &&
266                                (numArraySizesL == 0 || mArraySizes == right.mArraySizes);
267         return type == right.type && primarySize == right.primarySize &&
268                secondarySize == right.secondarySize && arraySizesEqual &&
269                mStructure == right.mStructure;
270         // don't check the qualifier, it's not ever what's being sought after
271     }
272     bool operator!=(const TType &right) const { return !operator==(right); }
273     bool operator<(const TType &right) const
274     {
275         if (type != right.type)
276             return type < right.type;
277         if (primarySize != right.primarySize)
278             return primarySize < right.primarySize;
279         if (secondarySize != right.secondarySize)
280             return secondarySize < right.secondarySize;
281         size_t numArraySizesL = getNumArraySizes();
282         size_t numArraySizesR = right.getNumArraySizes();
283         if (numArraySizesL != numArraySizesR)
284             return numArraySizesL < numArraySizesR;
285         for (size_t i = 0; i < numArraySizesL; ++i)
286         {
287             if (mArraySizes[i] != right.mArraySizes[i])
288                 return mArraySizes[i] < right.mArraySizes[i];
289         }
290         if (mStructure != right.mStructure)
291             return mStructure < right.mStructure;
292 
293         return false;
294     }
295 
getBasicString()296     const char *getBasicString() const { return sh::getBasicString(type); }
297 
getPrecisionString()298     const char *getPrecisionString() const { return sh::getPrecisionString(precision); }
getQualifierString()299     const char *getQualifierString() const { return sh::getQualifierString(qualifier); }
300 
301     const char *getBuiltInTypeNameString() const;
302 
303     // If this type is a struct, returns the deepest struct nesting of
304     // any field in the struct. For example:
305     //   struct nesting1 {
306     //     vec4 position;
307     //   };
308     //   struct nesting2 {
309     //     nesting1 field1;
310     //     vec4 field2;
311     //   };
312     // For type "nesting2", this method would return 2 -- the number
313     // of structures through which indirection must occur to reach the
314     // deepest field (nesting2.field1.position).
315     int getDeepestStructNesting() const;
316 
317     bool isNamelessStruct() const;
318 
319     bool isStructureContainingArrays() const;
320     bool isStructureContainingMatrices() const;
321     bool isStructureContainingType(TBasicType t) const;
322     bool isStructureContainingSamplers() const;
323 
isStructSpecifier()324     bool isStructSpecifier() const { return mIsStructSpecifier; }
325 
326     // Return true if variables of this type should be replaced with an inline constant value if
327     // such is available. False will be returned in cases where output doesn't support
328     // TIntermConstantUnion nodes of the type, or if the type contains a lot of fields and creating
329     // several copies of it in the output code is undesirable for performance.
330     bool canReplaceWithConstantUnion() const;
331 
332     // The char arrays passed in must be pool allocated or static.
333     void createSamplerSymbols(const ImmutableString &namePrefix,
334                               const TString &apiNamePrefix,
335                               TVector<const TVariable *> *outputSymbols,
336                               TMap<const TVariable *, TString> *outputSymbolsToAPINames,
337                               TSymbolTable *symbolTable) const;
338 
339     // Initializes all lazily-initialized members.
340     void realize();
341 
isSampler()342     bool isSampler() const { return IsSampler(type); }
isSamplerCube()343     bool isSamplerCube() const { return type == EbtSamplerCube; }
isAtomicCounter()344     bool isAtomicCounter() const { return IsAtomicCounter(type); }
isSamplerVideoWEBGL()345     bool isSamplerVideoWEBGL() const { return type == EbtSamplerVideoWEBGL; }
346 
347   private:
invalidateMangledName()348     constexpr void invalidateMangledName() { mMangledName = nullptr; }
349     const char *buildMangledName() const;
onArrayDimensionsChange(const TSpan<const unsigned int> & sizes)350     constexpr void onArrayDimensionsChange(const TSpan<const unsigned int> &sizes)
351     {
352         mArraySizes = sizes;
353         invalidateMangledName();
354     }
355 
356     TBasicType type;
357     TPrecision precision;
358     TQualifier qualifier;
359     bool invariant;
360     bool precise;
361 
362     TMemoryQualifier memoryQualifier;
363     TLayoutQualifier layoutQualifier;
364     unsigned char primarySize;    // size of vector or cols matrix
365     unsigned char secondarySize;  // rows of a matrix
366 
367     // Used to make an array type. Outermost array size is stored at the end of the vector. Having 0
368     // in this vector means an unsized array.
369     TSpan<const unsigned int> mArraySizes;
370     // Storage for mArraySizes, if any.  This is usually the case, except for constexpr TTypes which
371     // only have a valid mArraySizes (with mArraySizesStorage being nullptr).  Therefore, all
372     // modifications to array sizes happen on the storage (and if dimensions change, mArraySizes is
373     // also updated) and all reads are from mArraySizes.
374     TVector<unsigned int> *mArraySizesStorage;
375 
376     // This is set only in the following two cases:
377     // 1) Represents an interface block.
378     // 2) Represents the member variable of an unnamed interface block.
379     // It's nullptr also for members of named interface blocks.
380     const TInterfaceBlock *mInterfaceBlock;
381 
382     // nullptr unless this is a struct
383     const TStructure *mStructure;
384     bool mIsStructSpecifier;
385 
386     mutable const char *mMangledName;
387 };
388 
389 // TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the
390 // grammar
391 struct TTypeSpecifierNonArray
392 {
393     TBasicType type;
394     unsigned char primarySize;    // size of vector or cols of matrix
395     unsigned char secondarySize;  // rows of matrix
396     const TStructure *userDef;
397     TSourceLoc line;
398 
399     // true if the type was defined by a struct specifier rather than a reference to a type name.
400     bool isStructSpecifier;
401 
initializeTTypeSpecifierNonArray402     void initialize(TBasicType aType, const TSourceLoc &aLine)
403     {
404         ASSERT(aType != EbtStruct);
405         type              = aType;
406         primarySize       = 1;
407         secondarySize     = 1;
408         userDef           = nullptr;
409         line              = aLine;
410         isStructSpecifier = false;
411     }
412 
initializeStructTTypeSpecifierNonArray413     void initializeStruct(const TStructure *aUserDef,
414                           bool aIsStructSpecifier,
415                           const TSourceLoc &aLine)
416     {
417         type              = EbtStruct;
418         primarySize       = 1;
419         secondarySize     = 1;
420         userDef           = aUserDef;
421         line              = aLine;
422         isStructSpecifier = aIsStructSpecifier;
423     }
424 
setAggregateTTypeSpecifierNonArray425     void setAggregate(unsigned char size) { primarySize = size; }
426 
setMatrixTTypeSpecifierNonArray427     void setMatrix(unsigned char columns, unsigned char rows)
428     {
429         ASSERT(columns > 1 && rows > 1 && columns <= 4 && rows <= 4);
430         primarySize   = columns;
431         secondarySize = rows;
432     }
433 
isMatrixTTypeSpecifierNonArray434     bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
435 
isVectorTTypeSpecifierNonArray436     bool isVector() const { return primarySize > 1 && secondarySize == 1; }
437 };
438 
439 //
440 // This is a workaround for a problem with the yacc stack,  It can't have
441 // types that it thinks have non-trivial constructors.  It should
442 // just be used while recognizing the grammar, not anything else.  Pointers
443 // could be used, but also trying to avoid lots of memory management overhead.
444 //
445 // Not as bad as it looks, there is no actual assumption that the fields
446 // match up or are name the same or anything like that.
447 //
448 struct TPublicType
449 {
450     // Must have a trivial default constructor since it is used in YYSTYPE.
451     TPublicType() = default;
452 
453     void initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q);
454     void initializeBasicType(TBasicType basicType);
455 
getBasicTypeTPublicType456     TBasicType getBasicType() const { return typeSpecifierNonArray.type; }
setBasicTypeTPublicType457     void setBasicType(TBasicType basicType) { typeSpecifierNonArray.type = basicType; }
458 
getPrimarySizeTPublicType459     unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; }
getSecondarySizeTPublicType460     unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; }
461 
getUserDefTPublicType462     const TStructure *getUserDef() const { return typeSpecifierNonArray.userDef; }
getLineTPublicType463     const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; }
464 
isStructSpecifierTPublicType465     bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; }
466 
467     bool isStructureContainingArrays() const;
468     bool isStructureContainingType(TBasicType t) const;
469     void setArraySizes(TVector<unsigned int> *sizes);
470     bool isArray() const;
471     void clearArrayness();
472     bool isAggregate() const;
473 
474     TTypeSpecifierNonArray typeSpecifierNonArray;
475     TLayoutQualifier layoutQualifier;
476     TMemoryQualifier memoryQualifier;
477     TQualifier qualifier;
478     bool invariant;
479     bool precise;
480     TPrecision precision;
481 
482     // Either nullptr or empty in case the type is not an array. The last element is the outermost
483     // array size. Note that due to bison restrictions, copies of the public type created by the
484     // copy constructor share the same arraySizes pointer.
485     const TVector<unsigned int> *arraySizes;
486 };
487 
488 }  // namespace sh
489 
490 #endif  // COMPILER_TRANSLATOR_TYPES_H_
491