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