• 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 #if defined(_MSC_VER)
8 #    pragma warning(disable : 4718)
9 #endif
10 
11 #include "compiler/translator/Types.h"
12 #include "compiler/translator/ImmutableString.h"
13 #include "compiler/translator/InfoSink.h"
14 #include "compiler/translator/IntermNode.h"
15 #include "compiler/translator/SymbolTable.h"
16 
17 #include <algorithm>
18 #include <climits>
19 
20 namespace sh
21 {
22 
getBasicString(TBasicType t)23 const char *getBasicString(TBasicType t)
24 {
25     switch (t)
26     {
27         case EbtVoid:
28             return "void";
29         case EbtFloat:
30             return "float";
31         case EbtInt:
32             return "int";
33         case EbtUInt:
34             return "uint";
35         case EbtBool:
36             return "bool";
37         case EbtYuvCscStandardEXT:
38             return "yuvCscStandardEXT";
39         case EbtSampler2D:
40             return "sampler2D";
41         case EbtSampler3D:
42             return "sampler3D";
43         case EbtSamplerCube:
44             return "samplerCube";
45         case EbtSamplerExternalOES:
46             return "samplerExternalOES";
47         case EbtSamplerExternal2DY2YEXT:
48             return "__samplerExternal2DY2YEXT";
49         case EbtSampler2DRect:
50             return "sampler2DRect";
51         case EbtSampler2DArray:
52             return "sampler2DArray";
53         case EbtSampler2DMS:
54             return "sampler2DMS";
55         case EbtSampler2DMSArray:
56             return "sampler2DMSArray";
57         case EbtISampler2D:
58             return "isampler2D";
59         case EbtISampler3D:
60             return "isampler3D";
61         case EbtISamplerCube:
62             return "isamplerCube";
63         case EbtISampler2DArray:
64             return "isampler2DArray";
65         case EbtISampler2DMS:
66             return "isampler2DMS";
67         case EbtISampler2DMSArray:
68             return "isampler2DMSArray";
69         case EbtUSampler2D:
70             return "usampler2D";
71         case EbtUSampler3D:
72             return "usampler3D";
73         case EbtUSamplerCube:
74             return "usamplerCube";
75         case EbtUSampler2DArray:
76             return "usampler2DArray";
77         case EbtUSampler2DMS:
78             return "usampler2DMS";
79         case EbtUSampler2DMSArray:
80             return "usampler2DMSArray";
81         case EbtSampler2DShadow:
82             return "sampler2DShadow";
83         case EbtSamplerCubeShadow:
84             return "samplerCubeShadow";
85         case EbtSampler2DArrayShadow:
86             return "sampler2DArrayShadow";
87         case EbtStruct:
88             return "structure";
89         case EbtInterfaceBlock:
90             return "interface block";
91         case EbtImage2D:
92             return "image2D";
93         case EbtIImage2D:
94             return "iimage2D";
95         case EbtUImage2D:
96             return "uimage2D";
97         case EbtImage3D:
98             return "image3D";
99         case EbtIImage3D:
100             return "iimage3D";
101         case EbtUImage3D:
102             return "uimage3D";
103         case EbtImage2DArray:
104             return "image2DArray";
105         case EbtIImage2DArray:
106             return "iimage2DArray";
107         case EbtUImage2DArray:
108             return "uimage2DArray";
109         case EbtImageCube:
110             return "imageCube";
111         case EbtIImageCube:
112             return "iimageCube";
113         case EbtUImageCube:
114             return "uimageCube";
115         case EbtAtomicCounter:
116             return "atomic_uint";
117         case EbtSamplerVideoWEBGL:
118             return "samplerVideoWEBGL";
119         default:
120             UNREACHABLE();
121             return "unknown type";
122     }
123 }
124 
125 // TType implementation.
TType()126 TType::TType() : TType(EbtVoid, 0, 0) {}
127 
TType(TBasicType t,unsigned char ps,unsigned char ss)128 TType::TType(TBasicType t, unsigned char ps, unsigned char ss)
129     : TType(t, EbpUndefined, EvqGlobal, ps, ss)
130 {}
131 
TType(TBasicType t,TPrecision p,TQualifier q,unsigned char ps,unsigned char ss)132 TType::TType(TBasicType t, TPrecision p, TQualifier q, unsigned char ps, unsigned char ss)
133     : TType(t, p, q, ps, ss, TSpan<const unsigned int>(), nullptr)
134 {}
135 
TType(const TPublicType & p)136 TType::TType(const TPublicType &p)
137     : type(p.getBasicType()),
138       precision(p.precision),
139       qualifier(p.qualifier),
140       invariant(p.invariant),
141       precise(p.precise),
142       memoryQualifier(p.memoryQualifier),
143       layoutQualifier(p.layoutQualifier),
144       primarySize(p.getPrimarySize()),
145       secondarySize(p.getSecondarySize()),
146       mArraySizesStorage(nullptr),
147       mInterfaceBlock(nullptr),
148       mStructure(nullptr),
149       mIsStructSpecifier(false),
150       mMangledName(nullptr)
151 {
152     ASSERT(primarySize <= 4);
153     ASSERT(secondarySize <= 4);
154     if (p.isArray())
155     {
156         makeArrays(*p.arraySizes);
157     }
158     if (p.getUserDef())
159     {
160         mStructure         = p.getUserDef();
161         mIsStructSpecifier = p.isStructSpecifier();
162     }
163 }
164 
TType(const TStructure * userDef,bool isStructSpecifier)165 TType::TType(const TStructure *userDef, bool isStructSpecifier)
166     : TType(EbtStruct, EbpUndefined, EvqTemporary, 1, 1)
167 {
168     mStructure         = userDef;
169     mIsStructSpecifier = isStructSpecifier;
170 }
171 
TType(const TInterfaceBlock * interfaceBlockIn,TQualifier qualifierIn,TLayoutQualifier layoutQualifierIn)172 TType::TType(const TInterfaceBlock *interfaceBlockIn,
173              TQualifier qualifierIn,
174              TLayoutQualifier layoutQualifierIn)
175     : TType(EbtInterfaceBlock, EbpUndefined, qualifierIn, 1, 1)
176 {
177     layoutQualifier = layoutQualifierIn;
178     mInterfaceBlock = interfaceBlockIn;
179 }
180 
TType(const TType & t)181 TType::TType(const TType &t)
182 {
183     *this = t;
184 }
185 
operator =(const TType & t)186 TType &TType::operator=(const TType &t)
187 {
188     type               = t.type;
189     precision          = t.precision;
190     qualifier          = t.qualifier;
191     invariant          = t.invariant;
192     precise            = t.precise;
193     memoryQualifier    = t.memoryQualifier;
194     layoutQualifier    = t.layoutQualifier;
195     primarySize        = t.primarySize;
196     secondarySize      = t.secondarySize;
197     mArraySizesStorage = nullptr;
198     mInterfaceBlock    = t.mInterfaceBlock;
199     mStructure         = t.mStructure;
200     mIsStructSpecifier = t.mIsStructSpecifier;
201     mMangledName       = t.mMangledName;
202 
203     if (t.mArraySizesStorage)
204     {
205         // If other type has storage, duplicate the storage and set the view to our own storage.
206         mArraySizesStorage = new TVector<unsigned int>(*t.mArraySizesStorage);
207         mArraySizes        = *mArraySizesStorage;
208     }
209     else
210     {
211         // Otherwise reference the same (constexpr) array sizes as the other type.
212         mArraySizes = t.mArraySizes;
213     }
214 
215     return *this;
216 }
217 
canBeConstructed() const218 bool TType::canBeConstructed() const
219 {
220     switch (type)
221     {
222         case EbtFloat:
223         case EbtInt:
224         case EbtUInt:
225         case EbtBool:
226         case EbtStruct:
227             return true;
228         default:
229             return false;
230     }
231 }
232 
getBuiltInTypeNameString() const233 const char *TType::getBuiltInTypeNameString() const
234 {
235     if (isMatrix())
236     {
237         switch (getCols())
238         {
239             case 2:
240                 switch (getRows())
241                 {
242                     case 2:
243                         return "mat2";
244                     case 3:
245                         return "mat2x3";
246                     case 4:
247                         return "mat2x4";
248                     default:
249                         UNREACHABLE();
250                         return nullptr;
251                 }
252             case 3:
253                 switch (getRows())
254                 {
255                     case 2:
256                         return "mat3x2";
257                     case 3:
258                         return "mat3";
259                     case 4:
260                         return "mat3x4";
261                     default:
262                         UNREACHABLE();
263                         return nullptr;
264                 }
265             case 4:
266                 switch (getRows())
267                 {
268                     case 2:
269                         return "mat4x2";
270                     case 3:
271                         return "mat4x3";
272                     case 4:
273                         return "mat4";
274                     default:
275                         UNREACHABLE();
276                         return nullptr;
277                 }
278             default:
279                 UNREACHABLE();
280                 return nullptr;
281         }
282     }
283     if (isVector())
284     {
285         switch (getBasicType())
286         {
287             case EbtFloat:
288                 switch (getNominalSize())
289                 {
290                     case 2:
291                         return "vec2";
292                     case 3:
293                         return "vec3";
294                     case 4:
295                         return "vec4";
296                     default:
297                         UNREACHABLE();
298                         return nullptr;
299                 }
300             case EbtInt:
301                 switch (getNominalSize())
302                 {
303                     case 2:
304                         return "ivec2";
305                     case 3:
306                         return "ivec3";
307                     case 4:
308                         return "ivec4";
309                     default:
310                         UNREACHABLE();
311                         return nullptr;
312                 }
313             case EbtBool:
314                 switch (getNominalSize())
315                 {
316                     case 2:
317                         return "bvec2";
318                     case 3:
319                         return "bvec3";
320                     case 4:
321                         return "bvec4";
322                     default:
323                         UNREACHABLE();
324                         return nullptr;
325                 }
326             case EbtUInt:
327                 switch (getNominalSize())
328                 {
329                     case 2:
330                         return "uvec2";
331                     case 3:
332                         return "uvec3";
333                     case 4:
334                         return "uvec4";
335                     default:
336                         UNREACHABLE();
337                         return nullptr;
338                 }
339             default:
340                 UNREACHABLE();
341                 return nullptr;
342         }
343     }
344     ASSERT(getBasicType() != EbtStruct);
345     ASSERT(getBasicType() != EbtInterfaceBlock);
346     return getBasicString();
347 }
348 
getDeepestStructNesting() const349 int TType::getDeepestStructNesting() const
350 {
351     return mStructure ? mStructure->deepestNesting() : 0;
352 }
353 
isNamelessStruct() const354 bool TType::isNamelessStruct() const
355 {
356     return mStructure && mStructure->symbolType() == SymbolType::Empty;
357 }
358 
isStructureContainingArrays() const359 bool TType::isStructureContainingArrays() const
360 {
361     return mStructure ? mStructure->containsArrays() : false;
362 }
363 
isStructureContainingMatrices() const364 bool TType::isStructureContainingMatrices() const
365 {
366     return mStructure ? mStructure->containsMatrices() : false;
367 }
368 
isStructureContainingType(TBasicType t) const369 bool TType::isStructureContainingType(TBasicType t) const
370 {
371     return mStructure ? mStructure->containsType(t) : false;
372 }
373 
isStructureContainingSamplers() const374 bool TType::isStructureContainingSamplers() const
375 {
376     return mStructure ? mStructure->containsSamplers() : false;
377 }
378 
canReplaceWithConstantUnion() const379 bool TType::canReplaceWithConstantUnion() const
380 {
381     if (isArray())
382     {
383         return false;
384     }
385     if (!mStructure)
386     {
387         return true;
388     }
389     if (isStructureContainingArrays())
390     {
391         return false;
392     }
393     if (getObjectSize() > 16)
394     {
395         return false;
396     }
397     return true;
398 }
399 
400 //
401 // Recursively generate mangled names.
402 //
buildMangledName() const403 const char *TType::buildMangledName() const
404 {
405     TString mangledName(1, GetSizeMangledName(primarySize, secondarySize));
406 
407     TBasicMangledName typeName(type);
408     char *basicMangledName = typeName.getName();
409     static_assert(TBasicMangledName::mangledNameSize == 2, "Mangled name size is not 2");
410     if (basicMangledName[0] != '{')
411     {
412         mangledName += basicMangledName[0];
413         mangledName += basicMangledName[1];
414     }
415     else
416     {
417         ASSERT(type == EbtStruct || type == EbtInterfaceBlock);
418         switch (type)
419         {
420             case EbtStruct:
421                 mangledName += "{s";
422                 if (mStructure->symbolType() != SymbolType::Empty)
423                 {
424                     mangledName += mStructure->name().data();
425                 }
426                 mangledName += mStructure->mangledFieldList();
427                 mangledName += '}';
428                 break;
429             case EbtInterfaceBlock:
430                 mangledName += "{i";
431                 mangledName += mInterfaceBlock->name().data();
432                 mangledName += mInterfaceBlock->mangledFieldList();
433                 mangledName += '}';
434                 break;
435             default:
436                 UNREACHABLE();
437                 break;
438         }
439     }
440 
441     for (unsigned int arraySize : mArraySizes)
442     {
443         char buf[20];
444         snprintf(buf, sizeof(buf), "%d", arraySize);
445         mangledName += 'x';
446         mangledName += buf;
447     }
448 
449     // Copy string contents into a pool-allocated buffer, so we never need to call delete.
450     return AllocatePoolCharArray(mangledName.c_str(), mangledName.size());
451 }
452 
getObjectSize() const453 size_t TType::getObjectSize() const
454 {
455     size_t totalSize;
456 
457     if (getBasicType() == EbtStruct)
458         totalSize = mStructure->objectSize();
459     else
460         totalSize = primarySize * secondarySize;
461 
462     if (totalSize == 0)
463         return 0;
464 
465     for (size_t arraySize : mArraySizes)
466     {
467         if (arraySize > INT_MAX / totalSize)
468             totalSize = INT_MAX;
469         else
470             totalSize *= arraySize;
471     }
472 
473     return totalSize;
474 }
475 
getLocationCount() const476 int TType::getLocationCount() const
477 {
478     int count = 1;
479 
480     if (getBasicType() == EbtStruct)
481     {
482         count = mStructure->getLocationCount();
483     }
484 
485     if (count == 0)
486     {
487         return 0;
488     }
489 
490     for (unsigned int arraySize : mArraySizes)
491     {
492         if (arraySize > static_cast<unsigned int>(std::numeric_limits<int>::max() / count))
493         {
494             count = std::numeric_limits<int>::max();
495         }
496         else
497         {
498             count *= static_cast<int>(arraySize);
499         }
500     }
501 
502     return count;
503 }
504 
getArraySizeProduct() const505 unsigned int TType::getArraySizeProduct() const
506 {
507     unsigned int product = 1u;
508 
509     for (unsigned int arraySize : mArraySizes)
510     {
511         product *= arraySize;
512     }
513     return product;
514 }
515 
isUnsizedArray() const516 bool TType::isUnsizedArray() const
517 {
518     for (unsigned int arraySize : mArraySizes)
519     {
520         if (arraySize == 0u)
521         {
522             return true;
523         }
524     }
525     return false;
526 }
527 
sameNonArrayType(const TType & right) const528 bool TType::sameNonArrayType(const TType &right) const
529 {
530     return (type == right.type && primarySize == right.primarySize &&
531             secondarySize == right.secondarySize && mStructure == right.mStructure);
532 }
533 
isElementTypeOf(const TType & arrayType) const534 bool TType::isElementTypeOf(const TType &arrayType) const
535 {
536     if (!sameNonArrayType(arrayType))
537     {
538         return false;
539     }
540     if (arrayType.getNumArraySizes() != getNumArraySizes() + 1u)
541     {
542         return false;
543     }
544     for (size_t i = 0; i < mArraySizes.size(); ++i)
545     {
546         if (mArraySizes[i] != arrayType.mArraySizes[i])
547         {
548             return false;
549         }
550     }
551     return true;
552 }
553 
sizeUnsizedArrays(const TSpan<const unsigned int> & newArraySizes)554 void TType::sizeUnsizedArrays(const TSpan<const unsigned int> &newArraySizes)
555 {
556     ASSERT(!isArray() || mArraySizesStorage != nullptr);
557     for (size_t i = 0u; i < getNumArraySizes(); ++i)
558     {
559         if (mArraySizes[i] == 0)
560         {
561             if (i < newArraySizes.size())
562             {
563                 (*mArraySizesStorage)[i] = newArraySizes[i];
564             }
565             else
566             {
567                 (*mArraySizesStorage)[i] = 1u;
568             }
569         }
570     }
571     invalidateMangledName();
572 }
573 
sizeOutermostUnsizedArray(unsigned int arraySize)574 void TType::sizeOutermostUnsizedArray(unsigned int arraySize)
575 {
576     ASSERT(isArray() && mArraySizesStorage != nullptr);
577     ASSERT((*mArraySizesStorage).back() == 0u);
578     (*mArraySizesStorage).back() = arraySize;
579 }
580 
setBasicType(TBasicType t)581 void TType::setBasicType(TBasicType t)
582 {
583     if (type != t)
584     {
585         type = t;
586         invalidateMangledName();
587     }
588 }
589 
setPrimarySize(unsigned char ps)590 void TType::setPrimarySize(unsigned char ps)
591 {
592     if (primarySize != ps)
593     {
594         ASSERT(ps <= 4);
595         primarySize = ps;
596         invalidateMangledName();
597     }
598 }
599 
setSecondarySize(unsigned char ss)600 void TType::setSecondarySize(unsigned char ss)
601 {
602     if (secondarySize != ss)
603     {
604         ASSERT(ss <= 4);
605         secondarySize = ss;
606         invalidateMangledName();
607     }
608 }
609 
makeArray(unsigned int s)610 void TType::makeArray(unsigned int s)
611 {
612     if (mArraySizesStorage == nullptr)
613     {
614         mArraySizesStorage = new TVector<unsigned int>();
615     }
616     // Add a dimension to the current ones.
617     mArraySizesStorage->push_back(s);
618     onArrayDimensionsChange(*mArraySizesStorage);
619 }
620 
makeArrays(const TSpan<const unsigned int> & sizes)621 void TType::makeArrays(const TSpan<const unsigned int> &sizes)
622 {
623     if (mArraySizesStorage == nullptr)
624     {
625         mArraySizesStorage = new TVector<unsigned int>();
626     }
627     // Add dimensions to the current ones.
628     mArraySizesStorage->insert(mArraySizesStorage->end(), sizes.begin(), sizes.end());
629     onArrayDimensionsChange(*mArraySizesStorage);
630 }
631 
setArraySize(size_t arrayDimension,unsigned int s)632 void TType::setArraySize(size_t arrayDimension, unsigned int s)
633 {
634     ASSERT(isArray() && mArraySizesStorage != nullptr);
635     ASSERT(arrayDimension < mArraySizesStorage->size());
636     if (mArraySizes[arrayDimension] != s)
637     {
638         (*mArraySizesStorage)[arrayDimension] = s;
639         invalidateMangledName();
640     }
641 }
642 
toArrayElementType()643 void TType::toArrayElementType()
644 {
645     ASSERT(isArray() && mArraySizesStorage != nullptr);
646     mArraySizesStorage->pop_back();
647     onArrayDimensionsChange(*mArraySizesStorage);
648 }
649 
toArrayBaseType()650 void TType::toArrayBaseType()
651 {
652     if (!isArray())
653     {
654         return;
655     }
656     if (mArraySizesStorage)
657     {
658         mArraySizesStorage->clear();
659     }
660     onArrayDimensionsChange(TSpan<const unsigned int>());
661 }
662 
setInterfaceBlock(const TInterfaceBlock * interfaceBlockIn)663 void TType::setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn)
664 {
665     if (mInterfaceBlock != interfaceBlockIn)
666     {
667         mInterfaceBlock = interfaceBlockIn;
668         invalidateMangledName();
669     }
670 }
671 
getMangledName() const672 const char *TType::getMangledName() const
673 {
674     if (mMangledName == nullptr)
675     {
676         mMangledName = buildMangledName();
677     }
678 
679     return mMangledName;
680 }
681 
realize()682 void TType::realize()
683 {
684     getMangledName();
685 }
686 
createSamplerSymbols(const ImmutableString & namePrefix,const TString & apiNamePrefix,TVector<const TVariable * > * outputSymbols,TMap<const TVariable *,TString> * outputSymbolsToAPINames,TSymbolTable * symbolTable) const687 void TType::createSamplerSymbols(const ImmutableString &namePrefix,
688                                  const TString &apiNamePrefix,
689                                  TVector<const TVariable *> *outputSymbols,
690                                  TMap<const TVariable *, TString> *outputSymbolsToAPINames,
691                                  TSymbolTable *symbolTable) const
692 {
693     if (isStructureContainingSamplers())
694     {
695         if (isArray())
696         {
697             TType elementType(*this);
698             elementType.toArrayElementType();
699             for (unsigned int arrayIndex = 0u; arrayIndex < getOutermostArraySize(); ++arrayIndex)
700             {
701                 std::stringstream elementName = sh::InitializeStream<std::stringstream>();
702                 elementName << namePrefix << "_" << arrayIndex;
703                 TStringStream elementApiName;
704                 elementApiName << apiNamePrefix << "[" << arrayIndex << "]";
705                 elementType.createSamplerSymbols(ImmutableString(elementName.str()),
706                                                  elementApiName.str(), outputSymbols,
707                                                  outputSymbolsToAPINames, symbolTable);
708             }
709         }
710         else
711         {
712             mStructure->createSamplerSymbols(namePrefix.data(), apiNamePrefix, outputSymbols,
713                                              outputSymbolsToAPINames, symbolTable);
714         }
715         return;
716     }
717 
718     ASSERT(IsSampler(type));
719     TVariable *variable =
720         new TVariable(symbolTable, namePrefix, new TType(*this), SymbolType::AngleInternal);
721     outputSymbols->push_back(variable);
722     if (outputSymbolsToAPINames)
723     {
724         (*outputSymbolsToAPINames)[variable] = apiNamePrefix;
725     }
726 }
727 
TFieldListCollection(const TFieldList * fields)728 TFieldListCollection::TFieldListCollection(const TFieldList *fields)
729     : mFields(fields), mObjectSize(0), mDeepestNesting(0)
730 {}
731 
containsArrays() const732 bool TFieldListCollection::containsArrays() const
733 {
734     for (const auto *field : *mFields)
735     {
736         const TType *fieldType = field->type();
737         if (fieldType->isArray() || fieldType->isStructureContainingArrays())
738             return true;
739     }
740     return false;
741 }
742 
containsMatrices() const743 bool TFieldListCollection::containsMatrices() const
744 {
745     for (const auto *field : *mFields)
746     {
747         const TType *fieldType = field->type();
748         if (fieldType->isMatrix() || fieldType->isStructureContainingMatrices())
749             return true;
750     }
751     return false;
752 }
753 
containsType(TBasicType type) const754 bool TFieldListCollection::containsType(TBasicType type) const
755 {
756     for (const auto *field : *mFields)
757     {
758         const TType *fieldType = field->type();
759         if (fieldType->getBasicType() == type || fieldType->isStructureContainingType(type))
760             return true;
761     }
762     return false;
763 }
764 
containsSamplers() const765 bool TFieldListCollection::containsSamplers() const
766 {
767     for (const auto *field : *mFields)
768     {
769         const TType *fieldType = field->type();
770         if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
771             return true;
772     }
773     return false;
774 }
775 
buildMangledFieldList() const776 TString TFieldListCollection::buildMangledFieldList() const
777 {
778     TString mangledName;
779     for (const auto *field : *mFields)
780     {
781         mangledName += field->type()->getMangledName();
782     }
783     return mangledName;
784 }
785 
calculateObjectSize() const786 size_t TFieldListCollection::calculateObjectSize() const
787 {
788     size_t size = 0;
789     for (const TField *field : *mFields)
790     {
791         size_t fieldSize = field->type()->getObjectSize();
792         if (fieldSize > INT_MAX - size)
793             size = INT_MAX;
794         else
795             size += fieldSize;
796     }
797     return size;
798 }
799 
objectSize() const800 size_t TFieldListCollection::objectSize() const
801 {
802     if (mObjectSize == 0)
803         mObjectSize = calculateObjectSize();
804     return mObjectSize;
805 }
806 
getLocationCount() const807 int TFieldListCollection::getLocationCount() const
808 {
809     int count = 0;
810     for (const TField *field : *mFields)
811     {
812         int fieldCount = field->type()->getLocationCount();
813         if (fieldCount > std::numeric_limits<int>::max() - count)
814         {
815             count = std::numeric_limits<int>::max();
816         }
817         else
818         {
819             count += fieldCount;
820         }
821     }
822     return count;
823 }
824 
deepestNesting() const825 int TFieldListCollection::deepestNesting() const
826 {
827     if (mDeepestNesting == 0)
828         mDeepestNesting = calculateDeepestNesting();
829     return mDeepestNesting;
830 }
831 
mangledFieldList() const832 const TString &TFieldListCollection::mangledFieldList() const
833 {
834     if (mMangledFieldList.empty())
835         mMangledFieldList = buildMangledFieldList();
836     return mMangledFieldList;
837 }
838 
calculateDeepestNesting() const839 int TFieldListCollection::calculateDeepestNesting() const
840 {
841     int maxNesting = 0;
842     for (size_t i = 0; i < mFields->size(); ++i)
843         maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
844     return 1 + maxNesting;
845 }
846 
847 // TPublicType implementation.
initialize(const TTypeSpecifierNonArray & typeSpecifier,TQualifier q)848 void TPublicType::initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q)
849 {
850     typeSpecifierNonArray = typeSpecifier;
851     layoutQualifier       = TLayoutQualifier::Create();
852     memoryQualifier       = TMemoryQualifier::Create();
853     qualifier             = q;
854     invariant             = false;
855     precise               = false;
856     precision             = EbpUndefined;
857     arraySizes            = nullptr;
858 }
859 
initializeBasicType(TBasicType basicType)860 void TPublicType::initializeBasicType(TBasicType basicType)
861 {
862     typeSpecifierNonArray.type          = basicType;
863     typeSpecifierNonArray.primarySize   = 1;
864     typeSpecifierNonArray.secondarySize = 1;
865     layoutQualifier                     = TLayoutQualifier::Create();
866     memoryQualifier                     = TMemoryQualifier::Create();
867     qualifier                           = EvqTemporary;
868     invariant                           = false;
869     precise                             = false;
870     precision                           = EbpUndefined;
871     arraySizes                          = nullptr;
872 }
873 
isStructureContainingArrays() const874 bool TPublicType::isStructureContainingArrays() const
875 {
876     if (!typeSpecifierNonArray.userDef)
877     {
878         return false;
879     }
880 
881     return typeSpecifierNonArray.userDef->containsArrays();
882 }
883 
isStructureContainingType(TBasicType t) const884 bool TPublicType::isStructureContainingType(TBasicType t) const
885 {
886     if (!typeSpecifierNonArray.userDef)
887     {
888         return false;
889     }
890 
891     return typeSpecifierNonArray.userDef->containsType(t);
892 }
893 
setArraySizes(TVector<unsigned int> * sizes)894 void TPublicType::setArraySizes(TVector<unsigned int> *sizes)
895 {
896     arraySizes = sizes;
897 }
898 
isArray() const899 bool TPublicType::isArray() const
900 {
901     return arraySizes && !arraySizes->empty();
902 }
903 
clearArrayness()904 void TPublicType::clearArrayness()
905 {
906     arraySizes = nullptr;
907 }
908 
isAggregate() const909 bool TPublicType::isAggregate() const
910 {
911     return isArray() || typeSpecifierNonArray.isMatrix() || typeSpecifierNonArray.isVector();
912 }
913 
914 }  // namespace sh
915