• 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 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 
toComponentType()716 void TType::toComponentType()
717 {
718     primarySize   = 1;
719     secondarySize = 1;
720     invalidateMangledName();
721 }
722 
setInterfaceBlock(const TInterfaceBlock * interfaceBlockIn)723 void TType::setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn)
724 {
725     if (mInterfaceBlock != interfaceBlockIn)
726     {
727         mInterfaceBlock = interfaceBlockIn;
728         invalidateMangledName();
729     }
730 }
731 
setInterfaceBlockField(const TInterfaceBlock * interfaceBlockIn,size_t fieldIndex)732 void TType::setInterfaceBlockField(const TInterfaceBlock *interfaceBlockIn, size_t fieldIndex)
733 {
734     setInterfaceBlock(interfaceBlockIn);
735     mInterfaceBlockFieldIndex = fieldIndex;
736 }
737 
getMangledName() const738 const char *TType::getMangledName() const
739 {
740     if (mMangledName == nullptr)
741     {
742         mMangledName = buildMangledName();
743     }
744 
745     return mMangledName;
746 }
747 
realize()748 void TType::realize()
749 {
750     getMangledName();
751 }
752 
createSamplerSymbols(const ImmutableString & namePrefix,const TString & apiNamePrefix,TVector<const TVariable * > * outputSymbols,TMap<const TVariable *,TString> * outputSymbolsToAPINames,TSymbolTable * symbolTable) const753 void TType::createSamplerSymbols(const ImmutableString &namePrefix,
754                                  const TString &apiNamePrefix,
755                                  TVector<const TVariable *> *outputSymbols,
756                                  TMap<const TVariable *, TString> *outputSymbolsToAPINames,
757                                  TSymbolTable *symbolTable) const
758 {
759     if (isStructureContainingSamplers())
760     {
761         if (isArray())
762         {
763             TType elementType(*this);
764             elementType.toArrayElementType();
765             for (unsigned int arrayIndex = 0u; arrayIndex < getOutermostArraySize(); ++arrayIndex)
766             {
767                 std::stringstream elementName = sh::InitializeStream<std::stringstream>();
768                 elementName << namePrefix << "_" << arrayIndex;
769                 TStringStream elementApiName;
770                 elementApiName << apiNamePrefix << "[" << arrayIndex << "]";
771                 elementType.createSamplerSymbols(ImmutableString(elementName.str()),
772                                                  elementApiName.str(), outputSymbols,
773                                                  outputSymbolsToAPINames, symbolTable);
774             }
775         }
776         else
777         {
778             mStructure->createSamplerSymbols(namePrefix.data(), apiNamePrefix, outputSymbols,
779                                              outputSymbolsToAPINames, symbolTable);
780         }
781         return;
782     }
783 
784     ASSERT(IsSampler(type));
785     TVariable *variable =
786         new TVariable(symbolTable, namePrefix, new TType(*this), SymbolType::AngleInternal);
787     outputSymbols->push_back(variable);
788     if (outputSymbolsToAPINames)
789     {
790         (*outputSymbolsToAPINames)[variable] = apiNamePrefix;
791     }
792 }
793 
TFieldListCollection(const TFieldList * fields)794 TFieldListCollection::TFieldListCollection(const TFieldList *fields)
795     : mFields(fields), mObjectSize(0), mDeepestNesting(0)
796 {}
797 
containsArrays() const798 bool TFieldListCollection::containsArrays() const
799 {
800     for (const auto *field : *mFields)
801     {
802         const TType *fieldType = field->type();
803         if (fieldType->isArray() || fieldType->isStructureContainingArrays())
804             return true;
805     }
806     return false;
807 }
808 
containsMatrices() const809 bool TFieldListCollection::containsMatrices() const
810 {
811     for (const auto *field : *mFields)
812     {
813         const TType *fieldType = field->type();
814         if (fieldType->isMatrix() || fieldType->isStructureContainingMatrices())
815             return true;
816     }
817     return false;
818 }
819 
containsType(TBasicType type) const820 bool TFieldListCollection::containsType(TBasicType type) const
821 {
822     for (const auto *field : *mFields)
823     {
824         const TType *fieldType = field->type();
825         if (fieldType->getBasicType() == type || fieldType->isStructureContainingType(type))
826             return true;
827     }
828     return false;
829 }
830 
containsSamplers() const831 bool TFieldListCollection::containsSamplers() const
832 {
833     for (const auto *field : *mFields)
834     {
835         const TType *fieldType = field->type();
836         if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
837             return true;
838     }
839     return false;
840 }
841 
buildMangledFieldList() const842 TString TFieldListCollection::buildMangledFieldList() const
843 {
844     TString mangledName;
845     for (const auto *field : *mFields)
846     {
847         mangledName += field->type()->getMangledName();
848     }
849     return mangledName;
850 }
851 
calculateObjectSize() const852 size_t TFieldListCollection::calculateObjectSize() const
853 {
854     size_t size = 0;
855     for (const TField *field : *mFields)
856     {
857         size_t fieldSize = field->type()->getObjectSize();
858         if (fieldSize > INT_MAX - size)
859             size = INT_MAX;
860         else
861             size += fieldSize;
862     }
863     return size;
864 }
865 
objectSize() const866 size_t TFieldListCollection::objectSize() const
867 {
868     if (mObjectSize == 0)
869         mObjectSize = calculateObjectSize();
870     return mObjectSize;
871 }
872 
getLocationCount() const873 int TFieldListCollection::getLocationCount() const
874 {
875     int count = 0;
876     for (const TField *field : *mFields)
877     {
878         int fieldCount = field->type()->getLocationCount();
879         if (fieldCount > std::numeric_limits<int>::max() - count)
880         {
881             count = std::numeric_limits<int>::max();
882         }
883         else
884         {
885             count += fieldCount;
886         }
887     }
888     return count;
889 }
890 
deepestNesting() const891 int TFieldListCollection::deepestNesting() const
892 {
893     if (mDeepestNesting == 0)
894         mDeepestNesting = calculateDeepestNesting();
895     return mDeepestNesting;
896 }
897 
mangledFieldList() const898 const TString &TFieldListCollection::mangledFieldList() const
899 {
900     if (mMangledFieldList.empty())
901         mMangledFieldList = buildMangledFieldList();
902     return mMangledFieldList;
903 }
904 
calculateDeepestNesting() const905 int TFieldListCollection::calculateDeepestNesting() const
906 {
907     int maxNesting = 0;
908     for (size_t i = 0; i < mFields->size(); ++i)
909         maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
910     return 1 + maxNesting;
911 }
912 
913 // TPublicType implementation.
initialize(const TTypeSpecifierNonArray & typeSpecifier,TQualifier q)914 void TPublicType::initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q)
915 {
916     typeSpecifierNonArray = typeSpecifier;
917     layoutQualifier       = TLayoutQualifier::Create();
918     memoryQualifier       = TMemoryQualifier::Create();
919     qualifier             = q;
920     invariant             = false;
921     precise               = false;
922     precision             = EbpUndefined;
923     arraySizes            = nullptr;
924 }
925 
initializeBasicType(TBasicType basicType)926 void TPublicType::initializeBasicType(TBasicType basicType)
927 {
928     typeSpecifierNonArray.type          = basicType;
929     typeSpecifierNonArray.primarySize   = 1;
930     typeSpecifierNonArray.secondarySize = 1;
931     layoutQualifier                     = TLayoutQualifier::Create();
932     memoryQualifier                     = TMemoryQualifier::Create();
933     qualifier                           = EvqTemporary;
934     invariant                           = false;
935     precise                             = false;
936     precision                           = EbpUndefined;
937     arraySizes                          = nullptr;
938 }
939 
isStructureContainingArrays() const940 bool TPublicType::isStructureContainingArrays() const
941 {
942     if (!typeSpecifierNonArray.userDef)
943     {
944         return false;
945     }
946 
947     return typeSpecifierNonArray.userDef->containsArrays();
948 }
949 
isStructureContainingType(TBasicType t) const950 bool TPublicType::isStructureContainingType(TBasicType t) const
951 {
952     if (!typeSpecifierNonArray.userDef)
953     {
954         return false;
955     }
956 
957     return typeSpecifierNonArray.userDef->containsType(t);
958 }
959 
setArraySizes(TVector<unsigned int> * sizes)960 void TPublicType::setArraySizes(TVector<unsigned int> *sizes)
961 {
962     arraySizes = sizes;
963 }
964 
isArray() const965 bool TPublicType::isArray() const
966 {
967     return arraySizes && !arraySizes->empty();
968 }
969 
clearArrayness()970 void TPublicType::clearArrayness()
971 {
972     arraySizes = nullptr;
973 }
974 
isAggregate() const975 bool TPublicType::isAggregate() const
976 {
977     return isArray() || typeSpecifierNonArray.isMatrix() || typeSpecifierNonArray.isVector();
978 }
979 
980 }  // namespace sh
981