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