Line data Source code
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 :
16 : namespace sh
17 : {
18 :
19 : struct TPublicType;
20 : class TType;
21 : class TSymbol;
22 : class TIntermSymbol;
23 :
24 : class TField : angle::NonCopyable
25 : {
26 : public:
27 0 : POOL_ALLOCATOR_NEW_DELETE();
28 0 : TField(TType *type, TString *name, const TSourceLoc &line)
29 0 : : mType(type),
30 : mName(name),
31 0 : mLine(line)
32 : {
33 0 : }
34 :
35 : // TODO(alokp): We should only return const type.
36 : // Fix it by tweaking grammar.
37 0 : TType *type()
38 : {
39 0 : return mType;
40 : }
41 0 : const TType *type() const
42 : {
43 0 : return mType;
44 : }
45 :
46 0 : const TString &name() const
47 : {
48 0 : return *mName;
49 : }
50 0 : const TSourceLoc &line() const
51 : {
52 0 : return mLine;
53 : }
54 :
55 : private:
56 : TType *mType;
57 : TString *mName;
58 : TSourceLoc mLine;
59 : };
60 :
61 : typedef TVector<TField *> TFieldList;
62 0 : inline TFieldList *NewPoolTFieldList()
63 : {
64 0 : void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
65 0 : return new(memory) TFieldList;
66 : }
67 :
68 : class TFieldListCollection : angle::NonCopyable
69 : {
70 : public:
71 0 : const TString &name() const
72 : {
73 0 : return *mName;
74 : }
75 0 : const TFieldList &fields() const
76 : {
77 0 : return *mFields;
78 : }
79 :
80 0 : size_t objectSize() const
81 : {
82 0 : if (mObjectSize == 0)
83 0 : mObjectSize = calculateObjectSize();
84 0 : return mObjectSize;
85 : };
86 :
87 : protected:
88 0 : TFieldListCollection(const TString *name, TFieldList *fields)
89 0 : : mName(name),
90 : mFields(fields),
91 0 : mObjectSize(0)
92 : {
93 0 : }
94 : TString buildMangledName(const TString &mangledNamePrefix) const;
95 : size_t calculateObjectSize() const;
96 :
97 : const TString *mName;
98 : TFieldList *mFields;
99 :
100 : mutable TString mMangledName;
101 : mutable size_t mObjectSize;
102 : };
103 :
104 : // May also represent interface blocks
105 : class TStructure : public TFieldListCollection
106 : {
107 : public:
108 0 : POOL_ALLOCATOR_NEW_DELETE();
109 : TStructure(const TString *name, TFieldList *fields);
110 :
111 0 : int deepestNesting() const
112 : {
113 0 : if (mDeepestNesting == 0)
114 0 : mDeepestNesting = calculateDeepestNesting();
115 0 : return mDeepestNesting;
116 : }
117 : bool containsArrays() const;
118 : bool containsType(TBasicType t) const;
119 : bool containsSamplers() const;
120 : bool containsImages() const;
121 :
122 : void createSamplerSymbols(const TString &structName,
123 : const TString &structAPIName,
124 : const unsigned int arrayOfStructsSize,
125 : TVector<TIntermSymbol *> *outputSymbols,
126 : TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const;
127 :
128 : bool equals(const TStructure &other) const;
129 :
130 : void setUniqueId(int uniqueId)
131 : {
132 : mUniqueId = uniqueId;
133 : }
134 :
135 0 : int uniqueId() const
136 : {
137 0 : ASSERT(mUniqueId != 0);
138 0 : return mUniqueId;
139 : }
140 :
141 0 : void setAtGlobalScope(bool atGlobalScope)
142 : {
143 0 : mAtGlobalScope = atGlobalScope;
144 0 : }
145 :
146 0 : bool atGlobalScope() const
147 : {
148 0 : return mAtGlobalScope;
149 : }
150 :
151 0 : const TString &mangledName() const
152 : {
153 0 : if (mMangledName.empty())
154 0 : mMangledName = buildMangledName("struct-");
155 0 : return mMangledName;
156 : }
157 :
158 : private:
159 : // TODO(zmo): Find a way to get rid of the const_cast in function
160 : // setName(). At the moment keep this function private so only
161 : // friend class RegenerateStructNames may call it.
162 : friend class RegenerateStructNames;
163 0 : void setName(const TString &name)
164 : {
165 0 : TString *mutableName = const_cast<TString *>(mName);
166 0 : *mutableName = name;
167 0 : }
168 :
169 : int calculateDeepestNesting() const;
170 :
171 : mutable int mDeepestNesting;
172 : int mUniqueId;
173 : bool mAtGlobalScope;
174 : };
175 :
176 : class TInterfaceBlock : public TFieldListCollection
177 : {
178 : public:
179 0 : POOL_ALLOCATOR_NEW_DELETE();
180 0 : TInterfaceBlock(const TString *name, TFieldList *fields, const TString *instanceName,
181 : int arraySize, const TLayoutQualifier &layoutQualifier)
182 0 : : TFieldListCollection(name, fields),
183 : mInstanceName(instanceName),
184 : mArraySize(arraySize),
185 0 : mBlockStorage(layoutQualifier.blockStorage),
186 0 : mMatrixPacking(layoutQualifier.matrixPacking)
187 : {
188 0 : }
189 :
190 0 : const TString &instanceName() const
191 : {
192 0 : return *mInstanceName;
193 : }
194 0 : bool hasInstanceName() const
195 : {
196 0 : return mInstanceName != NULL;
197 : }
198 0 : bool isArray() const
199 : {
200 0 : return mArraySize > 0;
201 : }
202 0 : int arraySize() const
203 : {
204 0 : return mArraySize;
205 : }
206 0 : TLayoutBlockStorage blockStorage() const
207 : {
208 0 : return mBlockStorage;
209 : }
210 0 : TLayoutMatrixPacking matrixPacking() const
211 : {
212 0 : return mMatrixPacking;
213 : }
214 0 : const TString &mangledName() const
215 : {
216 0 : if (mMangledName.empty())
217 0 : mMangledName = buildMangledName("iblock-");
218 0 : return mMangledName;
219 : }
220 :
221 : private:
222 : const TString *mInstanceName; // for interface block instance names
223 : int mArraySize; // 0 if not an array
224 : TLayoutBlockStorage mBlockStorage;
225 : TLayoutMatrixPacking mMatrixPacking;
226 : };
227 :
228 : //
229 : // Base class for things that have a type.
230 : //
231 0 : class TType
232 : {
233 : public:
234 0 : POOL_ALLOCATOR_NEW_DELETE();
235 0 : TType()
236 0 : : type(EbtVoid),
237 : precision(EbpUndefined),
238 : qualifier(EvqGlobal),
239 : invariant(false),
240 : memoryQualifier(TMemoryQualifier::create()),
241 : layoutQualifier(TLayoutQualifier::create()),
242 : primarySize(0),
243 : secondarySize(0),
244 : array(false),
245 : arraySize(0),
246 : interfaceBlock(nullptr),
247 0 : structure(nullptr)
248 : {
249 0 : }
250 0 : explicit TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1)
251 0 : : type(t),
252 : precision(EbpUndefined),
253 : qualifier(EvqGlobal),
254 : invariant(false),
255 : memoryQualifier(TMemoryQualifier::create()),
256 : layoutQualifier(TLayoutQualifier::create()),
257 : primarySize(ps),
258 : secondarySize(ss),
259 : array(false),
260 : arraySize(0),
261 : interfaceBlock(0),
262 0 : structure(0)
263 : {
264 0 : }
265 0 : TType(TBasicType t,
266 : TPrecision p,
267 : TQualifier q = EvqTemporary,
268 : unsigned char ps = 1,
269 : unsigned char ss = 1,
270 : bool a = false)
271 0 : : type(t),
272 : precision(p),
273 : qualifier(q),
274 : invariant(false),
275 : memoryQualifier(TMemoryQualifier::create()),
276 : layoutQualifier(TLayoutQualifier::create()),
277 : primarySize(ps),
278 : secondarySize(ss),
279 : array(a),
280 : arraySize(0),
281 : interfaceBlock(0),
282 0 : structure(0)
283 : {
284 0 : }
285 : explicit TType(const TPublicType &p);
286 0 : explicit TType(TStructure *userDef, TPrecision p = EbpUndefined)
287 0 : : type(EbtStruct),
288 : precision(p),
289 : qualifier(EvqTemporary),
290 : invariant(false),
291 : memoryQualifier(TMemoryQualifier::create()),
292 : layoutQualifier(TLayoutQualifier::create()),
293 : primarySize(1),
294 : secondarySize(1),
295 : array(false),
296 : arraySize(0),
297 : interfaceBlock(0),
298 0 : structure(userDef)
299 : {
300 0 : }
301 0 : TType(TInterfaceBlock *interfaceBlockIn,
302 : TQualifier qualifierIn,
303 : TLayoutQualifier layoutQualifierIn,
304 : int arraySizeIn)
305 0 : : type(EbtInterfaceBlock),
306 : precision(EbpUndefined),
307 : qualifier(qualifierIn),
308 : invariant(false),
309 : memoryQualifier(TMemoryQualifier::create()),
310 : layoutQualifier(layoutQualifierIn),
311 : primarySize(1),
312 : secondarySize(1),
313 0 : array(arraySizeIn > 0),
314 : arraySize(arraySizeIn),
315 : interfaceBlock(interfaceBlockIn),
316 0 : structure(0)
317 : {
318 0 : }
319 :
320 0 : TType(const TType &) = default;
321 : TType &operator=(const TType &) = default;
322 :
323 0 : TBasicType getBasicType() const
324 : {
325 0 : return type;
326 : }
327 0 : void setBasicType(TBasicType t)
328 : {
329 0 : if (type != t)
330 : {
331 0 : type = t;
332 0 : invalidateMangledName();
333 : }
334 0 : }
335 :
336 0 : TPrecision getPrecision() const
337 : {
338 0 : return precision;
339 : }
340 0 : void setPrecision(TPrecision p)
341 : {
342 0 : precision = p;
343 0 : }
344 :
345 0 : TQualifier getQualifier() const
346 : {
347 0 : return qualifier;
348 : }
349 0 : void setQualifier(TQualifier q)
350 : {
351 0 : qualifier = q;
352 0 : }
353 :
354 0 : bool isInvariant() const
355 : {
356 0 : return invariant;
357 : }
358 :
359 0 : void setInvariant(bool i) { invariant = i; }
360 :
361 0 : TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; }
362 0 : void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; }
363 :
364 0 : TLayoutQualifier getLayoutQualifier() const
365 : {
366 0 : return layoutQualifier;
367 : }
368 0 : void setLayoutQualifier(TLayoutQualifier lq)
369 : {
370 0 : layoutQualifier = lq;
371 0 : }
372 :
373 0 : int getNominalSize() const
374 : {
375 0 : return primarySize;
376 : }
377 0 : int getSecondarySize() const
378 : {
379 0 : return secondarySize;
380 : }
381 0 : int getCols() const
382 : {
383 0 : ASSERT(isMatrix());
384 0 : return primarySize;
385 : }
386 0 : int getRows() const
387 : {
388 0 : ASSERT(isMatrix());
389 0 : return secondarySize;
390 : }
391 0 : void setPrimarySize(unsigned char ps)
392 : {
393 0 : if (primarySize != ps)
394 : {
395 0 : primarySize = ps;
396 0 : invalidateMangledName();
397 : }
398 0 : }
399 0 : void setSecondarySize(unsigned char ss)
400 : {
401 0 : if (secondarySize != ss)
402 : {
403 0 : secondarySize = ss;
404 0 : invalidateMangledName();
405 : }
406 0 : }
407 :
408 : // Full size of single instance of type
409 : size_t getObjectSize() const;
410 :
411 0 : bool isMatrix() const
412 : {
413 0 : return primarySize > 1 && secondarySize > 1;
414 : }
415 : bool isNonSquareMatrix() const
416 : {
417 : return isMatrix() && primarySize != secondarySize;
418 : }
419 0 : bool isArray() const
420 : {
421 0 : return array;
422 : }
423 0 : bool isUnsizedArray() const
424 : {
425 0 : return array && arraySize == 0u;
426 : }
427 0 : unsigned int getArraySize() const { return arraySize; }
428 0 : void setArraySize(unsigned int s)
429 : {
430 0 : if (!array || arraySize != s)
431 : {
432 0 : array = true;
433 0 : arraySize = s;
434 0 : invalidateMangledName();
435 : }
436 0 : }
437 0 : void clearArrayness()
438 : {
439 0 : if (array)
440 : {
441 0 : array = false;
442 0 : arraySize = 0u;
443 0 : invalidateMangledName();
444 : }
445 0 : }
446 :
447 0 : TInterfaceBlock *getInterfaceBlock() const
448 : {
449 0 : return interfaceBlock;
450 : }
451 0 : void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn)
452 : {
453 0 : if (interfaceBlock != interfaceBlockIn)
454 : {
455 0 : interfaceBlock = interfaceBlockIn;
456 0 : invalidateMangledName();
457 : }
458 0 : }
459 0 : bool isInterfaceBlock() const
460 : {
461 0 : return type == EbtInterfaceBlock;
462 : }
463 :
464 0 : bool isVector() const
465 : {
466 0 : return primarySize > 1 && secondarySize == 1;
467 : }
468 0 : bool isScalar() const
469 : {
470 0 : return primarySize == 1 && secondarySize == 1 && !structure;
471 : }
472 0 : bool isScalarInt() const
473 : {
474 0 : return isScalar() && (type == EbtInt || type == EbtUInt);
475 : }
476 :
477 0 : TStructure *getStruct() const
478 : {
479 0 : return structure;
480 : }
481 0 : void setStruct(TStructure *s)
482 : {
483 0 : if (structure != s)
484 : {
485 0 : structure = s;
486 0 : invalidateMangledName();
487 : }
488 0 : }
489 :
490 0 : const TString &getMangledName() const
491 : {
492 0 : if (mangled.empty())
493 : {
494 0 : mangled = buildMangledName();
495 0 : mangled += ';';
496 : }
497 :
498 0 : return mangled;
499 : }
500 :
501 0 : bool sameElementType(const TType &right) const
502 : {
503 0 : return type == right.type &&
504 0 : primarySize == right.primarySize &&
505 0 : secondarySize == right.secondarySize &&
506 0 : structure == right.structure;
507 : }
508 0 : bool operator==(const TType &right) const
509 : {
510 0 : return type == right.type &&
511 0 : primarySize == right.primarySize &&
512 0 : secondarySize == right.secondarySize &&
513 0 : array == right.array && (!array || arraySize == right.arraySize) &&
514 0 : structure == right.structure;
515 : // don't check the qualifier, it's not ever what's being sought after
516 : }
517 0 : bool operator!=(const TType &right) const
518 : {
519 0 : return !operator==(right);
520 : }
521 0 : bool operator<(const TType &right) const
522 : {
523 0 : if (type != right.type)
524 0 : return type < right.type;
525 0 : if (primarySize != right.primarySize)
526 0 : return primarySize < right.primarySize;
527 0 : if (secondarySize != right.secondarySize)
528 0 : return secondarySize < right.secondarySize;
529 0 : if (array != right.array)
530 0 : return array < right.array;
531 0 : if (arraySize != right.arraySize)
532 0 : return arraySize < right.arraySize;
533 0 : if (structure != right.structure)
534 0 : return structure < right.structure;
535 :
536 0 : return false;
537 : }
538 :
539 0 : const char *getBasicString() const
540 : {
541 0 : return sh::getBasicString(type);
542 : }
543 :
544 0 : const char *getPrecisionString() const
545 : {
546 0 : return sh::getPrecisionString(precision);
547 : }
548 0 : const char *getQualifierString() const
549 : {
550 0 : return sh::getQualifierString(qualifier);
551 : }
552 :
553 : const char *getBuiltInTypeNameString() const;
554 :
555 : TString getCompleteString() const;
556 :
557 : // If this type is a struct, returns the deepest struct nesting of
558 : // any field in the struct. For example:
559 : // struct nesting1 {
560 : // vec4 position;
561 : // };
562 : // struct nesting2 {
563 : // nesting1 field1;
564 : // vec4 field2;
565 : // };
566 : // For type "nesting2", this method would return 2 -- the number
567 : // of structures through which indirection must occur to reach the
568 : // deepest field (nesting2.field1.position).
569 0 : int getDeepestStructNesting() const
570 : {
571 0 : return structure ? structure->deepestNesting() : 0;
572 : }
573 :
574 0 : bool isStructureContainingArrays() const
575 : {
576 0 : return structure ? structure->containsArrays() : false;
577 : }
578 :
579 0 : bool isStructureContainingType(TBasicType t) const
580 : {
581 0 : return structure ? structure->containsType(t) : false;
582 : }
583 :
584 0 : bool isStructureContainingSamplers() const
585 : {
586 0 : return structure ? structure->containsSamplers() : false;
587 : }
588 :
589 0 : bool isStructureContainingImages() const
590 : {
591 0 : return structure ? structure->containsImages() : false;
592 : }
593 :
594 0 : void createSamplerSymbols(const TString &structName,
595 : const TString &structAPIName,
596 : const unsigned int arrayOfStructsSize,
597 : TVector<TIntermSymbol *> *outputSymbols,
598 : TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const
599 : {
600 0 : ASSERT(structure != nullptr && structure->containsSamplers());
601 0 : structure->createSamplerSymbols(structName, structAPIName, arrayOfStructsSize,
602 0 : outputSymbols, outputSymbolsToAPINames);
603 0 : }
604 :
605 : // Initializes all lazily-initialized members.
606 0 : void realize()
607 : {
608 0 : getMangledName();
609 0 : }
610 :
611 : private:
612 0 : void invalidateMangledName() { mangled = ""; }
613 : TString buildMangledName() const;
614 : size_t getStructSize() const;
615 :
616 : TBasicType type;
617 : TPrecision precision;
618 : TQualifier qualifier;
619 : bool invariant;
620 : TMemoryQualifier memoryQualifier;
621 : TLayoutQualifier layoutQualifier;
622 : unsigned char primarySize; // size of vector or cols matrix
623 : unsigned char secondarySize; // rows of a matrix
624 : bool array;
625 : unsigned int arraySize;
626 :
627 : // 0 unless this is an interface block, or interface block member variable
628 : TInterfaceBlock *interfaceBlock;
629 :
630 : // 0 unless this is a struct
631 : TStructure *structure;
632 :
633 : mutable TString mangled;
634 : };
635 :
636 : // TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the
637 : // grammar
638 : struct TTypeSpecifierNonArray
639 : {
640 : TBasicType type;
641 : unsigned char primarySize; // size of vector or cols of matrix
642 : unsigned char secondarySize; // rows of matrix
643 : TType *userDef;
644 : TSourceLoc line;
645 :
646 : // true if the type was defined by a struct specifier rather than a reference to a type name.
647 : bool isStructSpecifier;
648 :
649 0 : void initialize(TBasicType bt, const TSourceLoc &ln)
650 : {
651 0 : type = bt;
652 0 : primarySize = 1;
653 0 : secondarySize = 1;
654 0 : userDef = nullptr;
655 0 : line = ln;
656 0 : isStructSpecifier = false;
657 0 : }
658 :
659 0 : void setAggregate(unsigned char size)
660 : {
661 0 : primarySize = size;
662 0 : }
663 :
664 0 : void setMatrix(unsigned char columns, unsigned char rows)
665 : {
666 0 : ASSERT(columns > 1 && rows > 1 && columns <= 4 && rows <= 4);
667 0 : primarySize = columns;
668 0 : secondarySize = rows;
669 0 : }
670 :
671 0 : bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
672 :
673 0 : bool isVector() const { return primarySize > 1 && secondarySize == 1; }
674 : };
675 :
676 : //
677 : // This is a workaround for a problem with the yacc stack, It can't have
678 : // types that it thinks have non-trivial constructors. It should
679 : // just be used while recognizing the grammar, not anything else. Pointers
680 : // could be used, but also trying to avoid lots of memory management overhead.
681 : //
682 : // Not as bad as it looks, there is no actual assumption that the fields
683 : // match up or are name the same or anything like that.
684 : //
685 : struct TPublicType
686 : {
687 : TTypeSpecifierNonArray typeSpecifierNonArray;
688 : TLayoutQualifier layoutQualifier;
689 : TMemoryQualifier memoryQualifier;
690 : TQualifier qualifier;
691 : bool invariant;
692 : TPrecision precision;
693 : bool array;
694 : int arraySize;
695 :
696 0 : void initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q)
697 : {
698 0 : typeSpecifierNonArray = typeSpecifier;
699 0 : layoutQualifier = TLayoutQualifier::create();
700 0 : memoryQualifier = TMemoryQualifier::create();
701 0 : qualifier = q;
702 0 : invariant = false;
703 0 : precision = EbpUndefined;
704 0 : array = false;
705 0 : arraySize = 0;
706 0 : }
707 :
708 0 : void initializeBasicType(TBasicType basicType)
709 : {
710 0 : typeSpecifierNonArray.type = basicType;
711 0 : typeSpecifierNonArray.primarySize = 1;
712 0 : typeSpecifierNonArray.secondarySize = 1;
713 0 : layoutQualifier = TLayoutQualifier::create();
714 0 : memoryQualifier = TMemoryQualifier::create();
715 0 : qualifier = EvqTemporary;
716 0 : invariant = false;
717 0 : precision = EbpUndefined;
718 0 : array = false;
719 0 : arraySize = 0;
720 0 : }
721 :
722 0 : TBasicType getBasicType() const { return typeSpecifierNonArray.type; }
723 0 : void setBasicType(TBasicType basicType) { typeSpecifierNonArray.type = basicType; }
724 :
725 0 : unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; }
726 0 : unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; }
727 :
728 0 : const TType *getUserDef() const { return typeSpecifierNonArray.userDef; }
729 0 : const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; }
730 :
731 0 : bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; }
732 :
733 0 : bool isStructureContainingArrays() const
734 : {
735 0 : if (!typeSpecifierNonArray.userDef)
736 : {
737 0 : return false;
738 : }
739 :
740 0 : return typeSpecifierNonArray.userDef->isStructureContainingArrays();
741 : }
742 :
743 0 : bool isStructureContainingType(TBasicType t) const
744 : {
745 0 : if (!typeSpecifierNonArray.userDef)
746 : {
747 0 : return false;
748 : }
749 :
750 0 : return typeSpecifierNonArray.userDef->isStructureContainingType(t);
751 : }
752 :
753 0 : bool isUnsizedArray() const { return array && arraySize == 0; }
754 0 : void setArraySize(int s)
755 : {
756 0 : array = true;
757 0 : arraySize = s;
758 0 : }
759 0 : void clearArrayness()
760 : {
761 0 : array = false;
762 0 : arraySize = 0;
763 0 : }
764 :
765 0 : bool isAggregate() const
766 : {
767 0 : return array || typeSpecifierNonArray.isMatrix() || typeSpecifierNonArray.isVector();
768 : }
769 : };
770 :
771 : } // namespace sh
772 :
773 : #endif // COMPILER_TRANSLATOR_TYPES_H_
|