• 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,uint8_t ps,uint8_t ss)166 TType::TType(TBasicType t, uint8_t ps, uint8_t ss) : TType(t, EbpUndefined, EvqGlobal, ps, ss) {}
167 
TType(TBasicType t,TPrecision p,TQualifier q,uint8_t ps,uint8_t ss)168 TType::TType(TBasicType t, TPrecision p, TQualifier q, uint8_t ps, uint8_t ss)
169     : TType(t, p, q, ps, ss, TSpan<const unsigned int>(), nullptr)
170 {}
171 
TType(const TPublicType & p)172 TType::TType(const TPublicType &p)
173     : type(p.getBasicType()),
174       precision(p.precision),
175       qualifier(p.qualifier),
176       invariant(p.invariant),
177       precise(p.precise),
178       memoryQualifier(p.memoryQualifier),
179       layoutQualifier(p.layoutQualifier),
180       primarySize(p.getPrimarySize()),
181       secondarySize(p.getSecondarySize()),
182       mArraySizesStorage(nullptr),
183       mInterfaceBlock(nullptr),
184       mStructure(nullptr),
185       mIsStructSpecifier(false),
186       mInterfaceBlockFieldIndex(0),
187       mMangledName(nullptr)
188 {
189     ASSERT(primarySize <= 4);
190     ASSERT(secondarySize <= 4);
191     if (p.isArray())
192     {
193         makeArrays(*p.arraySizes);
194     }
195     if (p.getUserDef())
196     {
197         mStructure         = p.getUserDef();
198         mIsStructSpecifier = p.isStructSpecifier();
199     }
200 }
201 
TType(const TStructure * userDef,bool isStructSpecifier)202 TType::TType(const TStructure *userDef, bool isStructSpecifier)
203     : TType(EbtStruct, EbpUndefined, EvqTemporary, 1, 1)
204 {
205     mStructure         = userDef;
206     mIsStructSpecifier = isStructSpecifier;
207 }
208 
TType(const TInterfaceBlock * interfaceBlockIn,TQualifier qualifierIn,TLayoutQualifier layoutQualifierIn)209 TType::TType(const TInterfaceBlock *interfaceBlockIn,
210              TQualifier qualifierIn,
211              TLayoutQualifier layoutQualifierIn)
212     : TType(EbtInterfaceBlock, EbpUndefined, qualifierIn, 1, 1)
213 {
214     layoutQualifier = layoutQualifierIn;
215     mInterfaceBlock = interfaceBlockIn;
216 }
217 
TType(const TType & t)218 TType::TType(const TType &t)
219 {
220     *this = t;
221 }
222 
operator =(const TType & t)223 TType &TType::operator=(const TType &t)
224 {
225     type                      = t.type;
226     precision                 = t.precision;
227     qualifier                 = t.qualifier;
228     invariant                 = t.invariant;
229     precise                   = t.precise;
230     memoryQualifier           = t.memoryQualifier;
231     layoutQualifier           = t.layoutQualifier;
232     primarySize               = t.primarySize;
233     secondarySize             = t.secondarySize;
234     mArraySizesStorage        = nullptr;
235     mInterfaceBlock           = t.mInterfaceBlock;
236     mStructure                = t.mStructure;
237     mIsStructSpecifier        = t.mIsStructSpecifier;
238     mInterfaceBlockFieldIndex = t.mInterfaceBlockFieldIndex;
239     mMangledName              = t.mMangledName;
240 
241     if (t.mArraySizesStorage)
242     {
243         // If other type has storage, duplicate the storage and set the view to our own storage.
244         mArraySizesStorage = new TVector<unsigned int>(*t.mArraySizesStorage);
245         mArraySizes        = *mArraySizesStorage;
246     }
247     else
248     {
249         // Otherwise reference the same (constexpr) array sizes as the other type.
250         mArraySizes = t.mArraySizes;
251     }
252 
253     return *this;
254 }
255 
canBeConstructed() const256 bool TType::canBeConstructed() const
257 {
258     switch (type)
259     {
260         case EbtFloat:
261         case EbtInt:
262         case EbtUInt:
263         case EbtBool:
264         case EbtStruct:
265             return true;
266         default:
267             return false;
268     }
269 }
270 
getBuiltInTypeNameString() const271 const char *TType::getBuiltInTypeNameString() const
272 {
273     if (isMatrix())
274     {
275         switch (getCols())
276         {
277             case 2:
278                 switch (getRows())
279                 {
280                     case 2:
281                         return "mat2";
282                     case 3:
283                         return "mat2x3";
284                     case 4:
285                         return "mat2x4";
286                     default:
287                         UNREACHABLE();
288                         return nullptr;
289                 }
290             case 3:
291                 switch (getRows())
292                 {
293                     case 2:
294                         return "mat3x2";
295                     case 3:
296                         return "mat3";
297                     case 4:
298                         return "mat3x4";
299                     default:
300                         UNREACHABLE();
301                         return nullptr;
302                 }
303             case 4:
304                 switch (getRows())
305                 {
306                     case 2:
307                         return "mat4x2";
308                     case 3:
309                         return "mat4x3";
310                     case 4:
311                         return "mat4";
312                     default:
313                         UNREACHABLE();
314                         return nullptr;
315                 }
316             default:
317                 UNREACHABLE();
318                 return nullptr;
319         }
320     }
321     if (isVector())
322     {
323         switch (getBasicType())
324         {
325             case EbtFloat:
326                 switch (getNominalSize())
327                 {
328                     case 2:
329                         return "vec2";
330                     case 3:
331                         return "vec3";
332                     case 4:
333                         return "vec4";
334                     default:
335                         UNREACHABLE();
336                         return nullptr;
337                 }
338             case EbtInt:
339                 switch (getNominalSize())
340                 {
341                     case 2:
342                         return "ivec2";
343                     case 3:
344                         return "ivec3";
345                     case 4:
346                         return "ivec4";
347                     default:
348                         UNREACHABLE();
349                         return nullptr;
350                 }
351             case EbtBool:
352                 switch (getNominalSize())
353                 {
354                     case 2:
355                         return "bvec2";
356                     case 3:
357                         return "bvec3";
358                     case 4:
359                         return "bvec4";
360                     default:
361                         UNREACHABLE();
362                         return nullptr;
363                 }
364             case EbtUInt:
365                 switch (getNominalSize())
366                 {
367                     case 2:
368                         return "uvec2";
369                     case 3:
370                         return "uvec3";
371                     case 4:
372                         return "uvec4";
373                     default:
374                         UNREACHABLE();
375                         return nullptr;
376                 }
377             default:
378                 UNREACHABLE();
379                 return nullptr;
380         }
381     }
382     ASSERT(getBasicType() != EbtStruct);
383     ASSERT(getBasicType() != EbtInterfaceBlock);
384     return getBasicString();
385 }
386 
getDeepestStructNesting() const387 int TType::getDeepestStructNesting() const
388 {
389     return mStructure ? mStructure->deepestNesting() : 0;
390 }
391 
isNamelessStruct() const392 bool TType::isNamelessStruct() const
393 {
394     return mStructure && mStructure->symbolType() == SymbolType::Empty;
395 }
396 
isStructureContainingArrays() const397 bool TType::isStructureContainingArrays() const
398 {
399     return mStructure ? mStructure->containsArrays() : false;
400 }
401 
isStructureContainingMatrices() const402 bool TType::isStructureContainingMatrices() const
403 {
404     return mStructure ? mStructure->containsMatrices() : false;
405 }
406 
isStructureContainingType(TBasicType t) const407 bool TType::isStructureContainingType(TBasicType t) const
408 {
409     return mStructure ? mStructure->containsType(t) : false;
410 }
411 
isStructureContainingSamplers() const412 bool TType::isStructureContainingSamplers() const
413 {
414     return mStructure ? mStructure->containsSamplers() : false;
415 }
416 
isInterfaceBlockContainingType(TBasicType t) const417 bool TType::isInterfaceBlockContainingType(TBasicType t) const
418 {
419     return isInterfaceBlock() ? mInterfaceBlock->containsType(t) : false;
420 }
421 
canReplaceWithConstantUnion() const422 bool TType::canReplaceWithConstantUnion() const
423 {
424     if (isArray())
425     {
426         return false;
427     }
428     if (!mStructure)
429     {
430         return true;
431     }
432     if (isStructureContainingArrays())
433     {
434         return false;
435     }
436     if (getObjectSize() > 16)
437     {
438         return false;
439     }
440     return true;
441 }
442 
443 //
444 // Recursively generate mangled names.
445 //
buildMangledName() const446 const char *TType::buildMangledName() const
447 {
448     TString mangledName(1, GetSizeMangledName(primarySize, secondarySize));
449 
450     TBasicMangledName typeName(type);
451     char *basicMangledName = typeName.getName();
452     static_assert(TBasicMangledName::mangledNameSize == 2, "Mangled name size is not 2");
453     if (basicMangledName[0] != '{')
454     {
455         mangledName += basicMangledName[0];
456         mangledName += basicMangledName[1];
457     }
458     else
459     {
460         ASSERT(type == EbtStruct || type == EbtInterfaceBlock);
461         switch (type)
462         {
463             case EbtStruct:
464                 mangledName += "{s";
465                 if (mStructure->symbolType() != SymbolType::Empty)
466                 {
467                     mangledName += mStructure->name().data();
468                 }
469                 mangledName += mStructure->mangledFieldList();
470                 mangledName += '}';
471                 break;
472             case EbtInterfaceBlock:
473                 mangledName += "{i";
474                 mangledName += mInterfaceBlock->name().data();
475                 mangledName += mInterfaceBlock->mangledFieldList();
476                 mangledName += '}';
477                 break;
478             default:
479                 UNREACHABLE();
480                 break;
481         }
482     }
483 
484     for (unsigned int arraySize : mArraySizes)
485     {
486         char buf[20];
487         snprintf(buf, sizeof(buf), "%d", arraySize);
488         mangledName += 'x';
489         mangledName += buf;
490     }
491 
492     // Copy string contents into a pool-allocated buffer, so we never need to call delete.
493     return AllocatePoolCharArray(mangledName.c_str(), mangledName.size());
494 }
495 
getObjectSize() const496 size_t TType::getObjectSize() const
497 {
498     size_t totalSize;
499 
500     if (getBasicType() == EbtStruct)
501         totalSize = mStructure->objectSize();
502     else
503         totalSize = primarySize * secondarySize;
504 
505     if (totalSize == 0)
506         return 0;
507 
508     for (size_t arraySize : mArraySizes)
509     {
510         if (arraySize > INT_MAX / totalSize)
511             totalSize = INT_MAX;
512         else
513             totalSize *= arraySize;
514     }
515 
516     return totalSize;
517 }
518 
getLocationCount() const519 int TType::getLocationCount() const
520 {
521     int count = 1;
522 
523     if (getBasicType() == EbtStruct)
524     {
525         count = mStructure->getLocationCount();
526     }
527 
528     if (count == 0)
529     {
530         return 0;
531     }
532 
533     for (unsigned int arraySize : mArraySizes)
534     {
535         if (arraySize > static_cast<unsigned int>(std::numeric_limits<int>::max() / count))
536         {
537             count = std::numeric_limits<int>::max();
538         }
539         else
540         {
541             count *= static_cast<int>(arraySize);
542         }
543     }
544 
545     return count;
546 }
547 
getArraySizeProduct() const548 unsigned int TType::getArraySizeProduct() const
549 {
550     unsigned int product = 1u;
551 
552     for (unsigned int arraySize : mArraySizes)
553     {
554         product *= arraySize;
555     }
556     return product;
557 }
558 
isUnsizedArray() const559 bool TType::isUnsizedArray() const
560 {
561     for (unsigned int arraySize : mArraySizes)
562     {
563         if (arraySize == 0u)
564         {
565             return true;
566         }
567     }
568     return false;
569 }
570 
sameNonArrayType(const TType & right) const571 bool TType::sameNonArrayType(const TType &right) const
572 {
573     return (type == right.type && primarySize == right.primarySize &&
574             secondarySize == right.secondarySize && mStructure == right.mStructure);
575 }
576 
isElementTypeOf(const TType & arrayType) const577 bool TType::isElementTypeOf(const TType &arrayType) const
578 {
579     if (!sameNonArrayType(arrayType))
580     {
581         return false;
582     }
583     if (arrayType.getNumArraySizes() != getNumArraySizes() + 1u)
584     {
585         return false;
586     }
587     for (size_t i = 0; i < mArraySizes.size(); ++i)
588     {
589         if (mArraySizes[i] != arrayType.mArraySizes[i])
590         {
591             return false;
592         }
593     }
594     return true;
595 }
596 
sizeUnsizedArrays(const TSpan<const unsigned int> & newArraySizes)597 void TType::sizeUnsizedArrays(const TSpan<const unsigned int> &newArraySizes)
598 {
599     ASSERT(!isArray() || mArraySizesStorage != nullptr);
600     for (size_t i = 0u; i < getNumArraySizes(); ++i)
601     {
602         if (mArraySizes[i] == 0)
603         {
604             if (i < newArraySizes.size())
605             {
606                 (*mArraySizesStorage)[i] = newArraySizes[i];
607             }
608             else
609             {
610                 (*mArraySizesStorage)[i] = 1u;
611             }
612         }
613     }
614     invalidateMangledName();
615 }
616 
sizeOutermostUnsizedArray(unsigned int arraySize)617 void TType::sizeOutermostUnsizedArray(unsigned int arraySize)
618 {
619     ASSERT(isArray() && mArraySizesStorage != nullptr);
620     ASSERT((*mArraySizesStorage).back() == 0u);
621     (*mArraySizesStorage).back() = arraySize;
622 }
623 
setBasicType(TBasicType t)624 void TType::setBasicType(TBasicType t)
625 {
626     if (type != t)
627     {
628         type = t;
629         invalidateMangledName();
630     }
631 }
632 
setPrimarySize(uint8_t ps)633 void TType::setPrimarySize(uint8_t ps)
634 {
635     if (primarySize != ps)
636     {
637         ASSERT(ps <= 4);
638         primarySize = ps;
639         invalidateMangledName();
640     }
641 }
642 
setSecondarySize(uint8_t ss)643 void TType::setSecondarySize(uint8_t ss)
644 {
645     if (secondarySize != ss)
646     {
647         ASSERT(ss <= 4);
648         secondarySize = ss;
649         invalidateMangledName();
650     }
651 }
652 
makeArray(unsigned int s)653 void TType::makeArray(unsigned int s)
654 {
655     if (mArraySizesStorage == nullptr)
656     {
657         mArraySizesStorage = new TVector<unsigned int>();
658     }
659     // Add a dimension to the current ones.
660     mArraySizesStorage->push_back(s);
661     onArrayDimensionsChange(*mArraySizesStorage);
662 }
663 
makeArrays(const TSpan<const unsigned int> & sizes)664 void TType::makeArrays(const TSpan<const unsigned int> &sizes)
665 {
666     if (mArraySizesStorage == nullptr)
667     {
668         mArraySizesStorage = new TVector<unsigned int>();
669     }
670     // Add dimensions to the current ones.
671     mArraySizesStorage->insert(mArraySizesStorage->end(), sizes.begin(), sizes.end());
672     onArrayDimensionsChange(*mArraySizesStorage);
673 }
674 
setArraySize(size_t arrayDimension,unsigned int s)675 void TType::setArraySize(size_t arrayDimension, unsigned int s)
676 {
677     ASSERT(isArray() && mArraySizesStorage != nullptr);
678     ASSERT(arrayDimension < mArraySizesStorage->size());
679     if (mArraySizes[arrayDimension] != s)
680     {
681         (*mArraySizesStorage)[arrayDimension] = s;
682         invalidateMangledName();
683     }
684 }
685 
toArrayElementType()686 void TType::toArrayElementType()
687 {
688     ASSERT(isArray() && mArraySizesStorage != nullptr);
689     mArraySizesStorage->pop_back();
690     onArrayDimensionsChange(*mArraySizesStorage);
691 }
692 
toArrayBaseType()693 void TType::toArrayBaseType()
694 {
695     if (!isArray())
696     {
697         return;
698     }
699     if (mArraySizesStorage)
700     {
701         mArraySizesStorage->clear();
702     }
703     onArrayDimensionsChange(TSpan<const unsigned int>());
704 }
705 
toMatrixColumnType()706 void TType::toMatrixColumnType()
707 {
708     ASSERT(isMatrix());
709     primarySize   = secondarySize;
710     secondarySize = 1;
711     invalidateMangledName();
712 }
713 
toComponentType()714 void TType::toComponentType()
715 {
716     primarySize   = 1;
717     secondarySize = 1;
718     invalidateMangledName();
719 }
720 
setInterfaceBlock(const TInterfaceBlock * interfaceBlockIn)721 void TType::setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn)
722 {
723     if (mInterfaceBlock != interfaceBlockIn)
724     {
725         mInterfaceBlock = interfaceBlockIn;
726         invalidateMangledName();
727     }
728 }
729 
setInterfaceBlockField(const TInterfaceBlock * interfaceBlockIn,size_t fieldIndex)730 void TType::setInterfaceBlockField(const TInterfaceBlock *interfaceBlockIn, size_t fieldIndex)
731 {
732     setInterfaceBlock(interfaceBlockIn);
733     mInterfaceBlockFieldIndex = fieldIndex;
734 }
735 
getMangledName() const736 const char *TType::getMangledName() const
737 {
738     if (mMangledName == nullptr)
739     {
740         mMangledName = buildMangledName();
741     }
742 
743     return mMangledName;
744 }
745 
realize()746 void TType::realize()
747 {
748     getMangledName();
749 }
750 
createSamplerSymbols(const ImmutableString & namePrefix,const TString & apiNamePrefix,TVector<const TVariable * > * outputSymbols,TMap<const TVariable *,TString> * outputSymbolsToAPINames,TSymbolTable * symbolTable) const751 void TType::createSamplerSymbols(const ImmutableString &namePrefix,
752                                  const TString &apiNamePrefix,
753                                  TVector<const TVariable *> *outputSymbols,
754                                  TMap<const TVariable *, TString> *outputSymbolsToAPINames,
755                                  TSymbolTable *symbolTable) const
756 {
757     if (isStructureContainingSamplers())
758     {
759         if (isArray())
760         {
761             TType elementType(*this);
762             elementType.toArrayElementType();
763             for (unsigned int arrayIndex = 0u; arrayIndex < getOutermostArraySize(); ++arrayIndex)
764             {
765                 std::stringstream elementName = sh::InitializeStream<std::stringstream>();
766                 elementName << namePrefix << "_" << arrayIndex;
767                 TStringStream elementApiName;
768                 elementApiName << apiNamePrefix << "[" << arrayIndex << "]";
769                 elementType.createSamplerSymbols(ImmutableString(elementName.str()),
770                                                  elementApiName.str(), outputSymbols,
771                                                  outputSymbolsToAPINames, symbolTable);
772             }
773         }
774         else
775         {
776             mStructure->createSamplerSymbols(namePrefix.data(), apiNamePrefix, outputSymbols,
777                                              outputSymbolsToAPINames, symbolTable);
778         }
779         return;
780     }
781 
782     ASSERT(IsSampler(type));
783     TVariable *variable =
784         new TVariable(symbolTable, namePrefix, new TType(*this), SymbolType::AngleInternal);
785     outputSymbols->push_back(variable);
786     if (outputSymbolsToAPINames)
787     {
788         (*outputSymbolsToAPINames)[variable] = apiNamePrefix;
789     }
790 }
791 
TFieldListCollection(const TFieldList * fields)792 TFieldListCollection::TFieldListCollection(const TFieldList *fields)
793     : mFields(fields), mObjectSize(0), mDeepestNesting(0)
794 {}
795 
containsArrays() const796 bool TFieldListCollection::containsArrays() const
797 {
798     for (const auto *field : *mFields)
799     {
800         const TType *fieldType = field->type();
801         if (fieldType->isArray() || fieldType->isStructureContainingArrays())
802             return true;
803     }
804     return false;
805 }
806 
containsMatrices() const807 bool TFieldListCollection::containsMatrices() const
808 {
809     for (const auto *field : *mFields)
810     {
811         const TType *fieldType = field->type();
812         if (fieldType->isMatrix() || fieldType->isStructureContainingMatrices())
813             return true;
814     }
815     return false;
816 }
817 
containsType(TBasicType type) const818 bool TFieldListCollection::containsType(TBasicType type) const
819 {
820     for (const auto *field : *mFields)
821     {
822         const TType *fieldType = field->type();
823         if (fieldType->getBasicType() == type || fieldType->isStructureContainingType(type))
824             return true;
825     }
826     return false;
827 }
828 
containsSamplers() const829 bool TFieldListCollection::containsSamplers() const
830 {
831     for (const auto *field : *mFields)
832     {
833         const TType *fieldType = field->type();
834         if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
835             return true;
836     }
837     return false;
838 }
839 
buildMangledFieldList() const840 TString TFieldListCollection::buildMangledFieldList() const
841 {
842     TString mangledName;
843     for (const auto *field : *mFields)
844     {
845         mangledName += field->type()->getMangledName();
846     }
847     return mangledName;
848 }
849 
calculateObjectSize() const850 size_t TFieldListCollection::calculateObjectSize() const
851 {
852     size_t size = 0;
853     for (const TField *field : *mFields)
854     {
855         size_t fieldSize = field->type()->getObjectSize();
856         if (fieldSize > INT_MAX - size)
857             size = INT_MAX;
858         else
859             size += fieldSize;
860     }
861     return size;
862 }
863 
objectSize() const864 size_t TFieldListCollection::objectSize() const
865 {
866     if (mObjectSize == 0)
867         mObjectSize = calculateObjectSize();
868     return mObjectSize;
869 }
870 
getLocationCount() const871 int TFieldListCollection::getLocationCount() const
872 {
873     int count = 0;
874     for (const TField *field : *mFields)
875     {
876         int fieldCount = field->type()->getLocationCount();
877         if (fieldCount > std::numeric_limits<int>::max() - count)
878         {
879             count = std::numeric_limits<int>::max();
880         }
881         else
882         {
883             count += fieldCount;
884         }
885     }
886     return count;
887 }
888 
deepestNesting() const889 int TFieldListCollection::deepestNesting() const
890 {
891     if (mDeepestNesting == 0)
892         mDeepestNesting = calculateDeepestNesting();
893     return mDeepestNesting;
894 }
895 
mangledFieldList() const896 const TString &TFieldListCollection::mangledFieldList() const
897 {
898     if (mMangledFieldList.empty())
899         mMangledFieldList = buildMangledFieldList();
900     return mMangledFieldList;
901 }
902 
calculateDeepestNesting() const903 int TFieldListCollection::calculateDeepestNesting() const
904 {
905     int maxNesting = 0;
906     for (size_t i = 0; i < mFields->size(); ++i)
907         maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
908     return 1 + maxNesting;
909 }
910 
911 // TPublicType implementation.
initialize(const TTypeSpecifierNonArray & typeSpecifier,TQualifier q)912 void TPublicType::initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q)
913 {
914     typeSpecifierNonArray = typeSpecifier;
915     layoutQualifier       = TLayoutQualifier::Create();
916     memoryQualifier       = TMemoryQualifier::Create();
917     qualifier             = q;
918     invariant             = false;
919     precise               = false;
920     precision             = EbpUndefined;
921     arraySizes            = nullptr;
922 }
923 
initializeBasicType(TBasicType basicType)924 void TPublicType::initializeBasicType(TBasicType basicType)
925 {
926     typeSpecifierNonArray.type          = basicType;
927     typeSpecifierNonArray.primarySize   = 1;
928     typeSpecifierNonArray.secondarySize = 1;
929     layoutQualifier                     = TLayoutQualifier::Create();
930     memoryQualifier                     = TMemoryQualifier::Create();
931     qualifier                           = EvqTemporary;
932     invariant                           = false;
933     precise                             = false;
934     precision                           = EbpUndefined;
935     arraySizes                          = nullptr;
936 }
937 
isStructureContainingArrays() const938 bool TPublicType::isStructureContainingArrays() const
939 {
940     if (!typeSpecifierNonArray.userDef)
941     {
942         return false;
943     }
944 
945     return typeSpecifierNonArray.userDef->containsArrays();
946 }
947 
isStructureContainingType(TBasicType t) const948 bool TPublicType::isStructureContainingType(TBasicType t) const
949 {
950     if (!typeSpecifierNonArray.userDef)
951     {
952         return false;
953     }
954 
955     return typeSpecifierNonArray.userDef->containsType(t);
956 }
957 
setArraySizes(TVector<unsigned int> * sizes)958 void TPublicType::setArraySizes(TVector<unsigned int> *sizes)
959 {
960     arraySizes = sizes;
961 }
962 
isArray() const963 bool TPublicType::isArray() const
964 {
965     return arraySizes && !arraySizes->empty();
966 }
967 
clearArrayness()968 void TPublicType::clearArrayness()
969 {
970     arraySizes = nullptr;
971 }
972 
isAggregate() const973 bool TPublicType::isAggregate() const
974 {
975     return isArray() || typeSpecifierNonArray.isMatrix() || typeSpecifierNonArray.isVector();
976 }
977 
978 }  // namespace sh
979