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