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