1 //
2 // Copyright (c) 2002-2014 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/InfoSink.h"
13 #include "compiler/translator/IntermNode.h"
14 #include "compiler/translator/SymbolTable.h"
15 
16 #include <algorithm>
17 #include <climits>
18 
19 namespace sh
20 {
21 
getBasicString(TBasicType t)22 const char* getBasicString(TBasicType t)
23 {
24     switch (t)
25     {
26         case EbtVoid:                 return "void";
27         case EbtFloat:                return "float";
28         case EbtInt:                  return "int";
29         case EbtUInt:                 return "uint";
30         case EbtBool:                 return "bool";
31         case EbtSampler2D:            return "sampler2D";
32         case EbtSampler3D:            return "sampler3D";
33         case EbtSamplerCube:          return "samplerCube";
34         case EbtSamplerExternalOES:   return "samplerExternalOES";
35         case EbtSampler2DRect:        return "sampler2DRect";
36         case EbtSampler2DArray:       return "sampler2DArray";
37         case EbtISampler2D:           return "isampler2D";
38         case EbtISampler3D:           return "isampler3D";
39         case EbtISamplerCube:         return "isamplerCube";
40         case EbtISampler2DArray:      return "isampler2DArray";
41         case EbtUSampler2D:           return "usampler2D";
42         case EbtUSampler3D:           return "usampler3D";
43         case EbtUSamplerCube:         return "usamplerCube";
44         case EbtUSampler2DArray:      return "usampler2DArray";
45         case EbtSampler2DShadow:      return "sampler2DShadow";
46         case EbtSamplerCubeShadow:    return "samplerCubeShadow";
47         case EbtSampler2DArrayShadow: return "sampler2DArrayShadow";
48         case EbtStruct:               return "structure";
49         case EbtInterfaceBlock:       return "interface block";
50         case EbtImage2D:
51             return "image2D";
52         case EbtIImage2D:
53             return "iimage2D";
54         case EbtUImage2D:
55             return "uimage2D";
56         case EbtImage3D:
57             return "image3D";
58         case EbtIImage3D:
59             return "iimage3D";
60         case EbtUImage3D:
61             return "uimage3D";
62         case EbtImage2DArray:
63             return "image2DArray";
64         case EbtIImage2DArray:
65             return "iimage2DArray";
66         case EbtUImage2DArray:
67             return "uimage2DArray";
68         case EbtImageCube:
69             return "imageCube";
70         case EbtIImageCube:
71             return "iimageCube";
72         case EbtUImageCube:
73             return "uimageCube";
74         default: UNREACHABLE();       return "unknown type";
75     }
76 }
77 
TType(const TPublicType & p)78 TType::TType(const TPublicType &p)
79     : type(p.getBasicType()),
80       precision(p.precision),
81       qualifier(p.qualifier),
82       invariant(p.invariant),
83       memoryQualifier(p.memoryQualifier),
84       layoutQualifier(p.layoutQualifier),
85       primarySize(p.getPrimarySize()),
86       secondarySize(p.getSecondarySize()),
87       array(p.array),
88       arraySize(p.arraySize),
89       interfaceBlock(0),
90       structure(0)
91 {
92     if (p.getUserDef())
93         structure = p.getUserDef()->getStruct();
94 }
95 
equals(const TStructure & other) const96 bool TStructure::equals(const TStructure &other) const
97 {
98     return (uniqueId() == other.uniqueId());
99 }
100 
getBuiltInTypeNameString() const101 const char *TType::getBuiltInTypeNameString() const
102 {
103     if (isMatrix())
104     {
105         switch (getCols())
106         {
107             case 2:
108                 switch (getRows())
109                 {
110                     case 2:
111                         return "mat2";
112                     case 3:
113                         return "mat2x3";
114                     case 4:
115                         return "mat2x4";
116                     default:
117                         UNREACHABLE();
118                         return nullptr;
119                 }
120             case 3:
121                 switch (getRows())
122                 {
123                     case 2:
124                         return "mat3x2";
125                     case 3:
126                         return "mat3";
127                     case 4:
128                         return "mat3x4";
129                     default:
130                         UNREACHABLE();
131                         return nullptr;
132                 }
133             case 4:
134                 switch (getRows())
135                 {
136                     case 2:
137                         return "mat4x2";
138                     case 3:
139                         return "mat4x3";
140                     case 4:
141                         return "mat4";
142                     default:
143                         UNREACHABLE();
144                         return nullptr;
145                 }
146             default:
147                 UNREACHABLE();
148                 return nullptr;
149         }
150     }
151     if (isVector())
152     {
153         switch (getBasicType())
154         {
155             case EbtFloat:
156                 switch (getNominalSize())
157                 {
158                     case 2:
159                         return "vec2";
160                     case 3:
161                         return "vec3";
162                     case 4:
163                         return "vec4";
164                     default:
165                         UNREACHABLE();
166                         return nullptr;
167                 }
168             case EbtInt:
169                 switch (getNominalSize())
170                 {
171                     case 2:
172                         return "ivec2";
173                     case 3:
174                         return "ivec3";
175                     case 4:
176                         return "ivec4";
177                     default:
178                         UNREACHABLE();
179                         return nullptr;
180                 }
181             case EbtBool:
182                 switch (getNominalSize())
183                 {
184                     case 2:
185                         return "bvec2";
186                     case 3:
187                         return "bvec3";
188                     case 4:
189                         return "bvec4";
190                     default:
191                         UNREACHABLE();
192                         return nullptr;
193                 }
194             case EbtUInt:
195                 switch (getNominalSize())
196                 {
197                     case 2:
198                         return "uvec2";
199                     case 3:
200                         return "uvec3";
201                     case 4:
202                         return "uvec4";
203                     default:
204                         UNREACHABLE();
205                         return nullptr;
206                 }
207             default:
208                 UNREACHABLE();
209                 return nullptr;
210         }
211     }
212     ASSERT(getBasicType() != EbtStruct);
213     ASSERT(getBasicType() != EbtInterfaceBlock);
214     return getBasicString();
215 }
216 
getCompleteString() const217 TString TType::getCompleteString() const
218 {
219     TStringStream stream;
220 
221     if (invariant)
222         stream << "invariant ";
223     if (qualifier != EvqTemporary && qualifier != EvqGlobal)
224         stream << getQualifierString() << " ";
225     if (precision != EbpUndefined)
226         stream << getPrecisionString() << " ";
227     if (array)
228         stream << "array[" << getArraySize() << "] of ";
229     if (isMatrix())
230         stream << getCols() << "X" << getRows() << " matrix of ";
231     else if (isVector())
232         stream << getNominalSize() << "-component vector of ";
233 
234     stream << getBasicString();
235     return stream.str();
236 }
237 
238 //
239 // Recursively generate mangled names.
240 //
buildMangledName() const241 TString TType::buildMangledName() const
242 {
243     TString mangledName;
244     if (isMatrix())
245         mangledName += 'm';
246     else if (isVector())
247         mangledName += 'v';
248 
249     switch (type)
250     {
251       case EbtFloat:
252         mangledName += 'f';
253         break;
254       case EbtInt:
255         mangledName += 'i';
256         break;
257       case EbtUInt:
258         mangledName += 'u';
259         break;
260       case EbtBool:
261         mangledName += 'b';
262         break;
263       case EbtSampler2D:
264         mangledName += "s2";
265         break;
266       case EbtSampler3D:
267         mangledName += "s3";
268         break;
269       case EbtSamplerCube:
270         mangledName += "sC";
271         break;
272       case EbtSampler2DArray:
273         mangledName += "s2a";
274         break;
275       case EbtSamplerExternalOES:
276         mangledName += "sext";
277         break;
278       case EbtSampler2DRect:
279         mangledName += "s2r";
280         break;
281       case EbtISampler2D:
282         mangledName += "is2";
283         break;
284       case EbtISampler3D:
285         mangledName += "is3";
286         break;
287       case EbtISamplerCube:
288         mangledName += "isC";
289         break;
290       case EbtISampler2DArray:
291         mangledName += "is2a";
292         break;
293       case EbtUSampler2D:
294         mangledName += "us2";
295         break;
296       case EbtUSampler3D:
297         mangledName += "us3";
298         break;
299       case EbtUSamplerCube:
300         mangledName += "usC";
301         break;
302       case EbtUSampler2DArray:
303         mangledName += "us2a";
304         break;
305       case EbtSampler2DShadow:
306         mangledName += "s2s";
307         break;
308       case EbtSamplerCubeShadow:
309         mangledName += "sCs";
310         break;
311       case EbtSampler2DArrayShadow:
312         mangledName += "s2as";
313         break;
314       case EbtImage2D:
315           mangledName += "im2";
316           break;
317       case EbtIImage2D:
318           mangledName += "iim2";
319           break;
320       case EbtUImage2D:
321           mangledName += "uim2";
322           break;
323       case EbtImage3D:
324           mangledName += "im3";
325           break;
326       case EbtIImage3D:
327           mangledName += "iim3";
328           break;
329       case EbtUImage3D:
330           mangledName += "uim3";
331           break;
332       case EbtImage2DArray:
333           mangledName += "im2a";
334           break;
335       case EbtIImage2DArray:
336           mangledName += "iim2a";
337           break;
338       case EbtUImage2DArray:
339           mangledName += "uim2a";
340           break;
341       case EbtImageCube:
342           mangledName += "imc";
343           break;
344       case EbtIImageCube:
345           mangledName += "iimc";
346           break;
347       case EbtUImageCube:
348           mangledName += "uimc";
349           break;
350       case EbtStruct:
351         mangledName += structure->mangledName();
352         break;
353       case EbtInterfaceBlock:
354         mangledName += interfaceBlock->mangledName();
355         break;
356       default:
357         // EbtVoid, EbtAddress and non types
358         break;
359     }
360 
361     if (isMatrix())
362     {
363         mangledName += static_cast<char>('0' + getCols());
364         mangledName += static_cast<char>('x');
365         mangledName += static_cast<char>('0' + getRows());
366     }
367     else
368     {
369         mangledName += static_cast<char>('0' + getNominalSize());
370     }
371 
372     if (isArray())
373     {
374         char buf[20];
375         snprintf(buf, sizeof(buf), "%d", arraySize);
376         mangledName += '[';
377         mangledName += buf;
378         mangledName += ']';
379     }
380     return mangledName;
381 }
382 
getObjectSize() const383 size_t TType::getObjectSize() const
384 {
385     size_t totalSize;
386 
387     if (getBasicType() == EbtStruct)
388         totalSize = structure->objectSize();
389     else
390         totalSize = primarySize * secondarySize;
391 
392     if (isArray())
393     {
394         if (totalSize == 0)
395             return 0;
396 
397         size_t currentArraySize = getArraySize();
398         if (currentArraySize > INT_MAX / totalSize)
399             totalSize = INT_MAX;
400         else
401             totalSize *= currentArraySize;
402     }
403 
404     return totalSize;
405 }
406 
TStructure(const TString * name,TFieldList * fields)407 TStructure::TStructure(const TString *name, TFieldList *fields)
408     : TFieldListCollection(name, fields),
409       mDeepestNesting(0),
410       mUniqueId(TSymbolTable::nextUniqueId()),
411       mAtGlobalScope(false)
412 {
413 }
414 
containsArrays() const415 bool TStructure::containsArrays() const
416 {
417     for (size_t i = 0; i < mFields->size(); ++i)
418     {
419         const TType *fieldType = (*mFields)[i]->type();
420         if (fieldType->isArray() || fieldType->isStructureContainingArrays())
421             return true;
422     }
423     return false;
424 }
425 
containsType(TBasicType type) const426 bool TStructure::containsType(TBasicType type) const
427 {
428     for (size_t i = 0; i < mFields->size(); ++i)
429     {
430         const TType *fieldType = (*mFields)[i]->type();
431         if (fieldType->getBasicType() == type || fieldType->isStructureContainingType(type))
432             return true;
433     }
434     return false;
435 }
436 
containsSamplers() const437 bool TStructure::containsSamplers() const
438 {
439     for (size_t i = 0; i < mFields->size(); ++i)
440     {
441         const TType *fieldType = (*mFields)[i]->type();
442         if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
443             return true;
444     }
445     return false;
446 }
447 
containsImages() const448 bool TStructure::containsImages() const
449 {
450     for (size_t i = 0; i < mFields->size(); ++i)
451     {
452         const TType *fieldType = (*mFields)[i]->type();
453         if (IsImage(fieldType->getBasicType()) || fieldType->isStructureContainingImages())
454             return true;
455     }
456     return false;
457 }
458 
createSamplerSymbols(const TString & structName,const TString & structAPIName,const unsigned int arrayOfStructsSize,TVector<TIntermSymbol * > * outputSymbols,TMap<TIntermSymbol *,TString> * outputSymbolsToAPINames) const459 void TStructure::createSamplerSymbols(const TString &structName,
460                                       const TString &structAPIName,
461                                       const unsigned int arrayOfStructsSize,
462                                       TVector<TIntermSymbol *> *outputSymbols,
463                                       TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const
464 {
465     for (auto &field : *mFields)
466     {
467         const TType *fieldType = field->type();
468         if (IsSampler(fieldType->getBasicType()))
469         {
470             if (arrayOfStructsSize > 0u)
471             {
472                 for (unsigned int arrayIndex = 0u; arrayIndex < arrayOfStructsSize; ++arrayIndex)
473                 {
474                     TStringStream name;
475                     name << structName << "_" << arrayIndex << "_" << field->name();
476                     TIntermSymbol *symbol = new TIntermSymbol(0, name.str(), *fieldType);
477                     outputSymbols->push_back(symbol);
478 
479                     if (outputSymbolsToAPINames)
480                     {
481                         TStringStream apiName;
482                         apiName << structAPIName << "[" << arrayIndex << "]." << field->name();
483                         (*outputSymbolsToAPINames)[symbol] = apiName.str();
484                     }
485                 }
486             }
487             else
488             {
489                 TString symbolName    = structName + "_" + field->name();
490                 TIntermSymbol *symbol = new TIntermSymbol(0, symbolName, *fieldType);
491                 outputSymbols->push_back(symbol);
492 
493                 if (outputSymbolsToAPINames)
494                 {
495                     TString apiName = structAPIName + "." + field->name();
496                     (*outputSymbolsToAPINames)[symbol] = apiName;
497                 }
498             }
499         }
500         else if (fieldType->isStructureContainingSamplers())
501         {
502             unsigned int nestedArrayOfStructsSize =
503                 fieldType->isArray() ? fieldType->getArraySize() : 0u;
504             if (arrayOfStructsSize > 0)
505             {
506                 for (unsigned int arrayIndex = 0u; arrayIndex < arrayOfStructsSize; ++arrayIndex)
507                 {
508                     TStringStream fieldName;
509                     fieldName << structName << "_" << arrayIndex << "_" << field->name();
510                     TStringStream fieldAPIName;
511                     if (outputSymbolsToAPINames)
512                     {
513                         fieldAPIName << structAPIName << "[" << arrayIndex << "]." << field->name();
514                     }
515                     fieldType->createSamplerSymbols(fieldName.str(), fieldAPIName.str(),
516                                                     nestedArrayOfStructsSize, outputSymbols,
517                                                     outputSymbolsToAPINames);
518                 }
519             }
520             else
521             {
522                 fieldType->createSamplerSymbols(
523                     structName + "_" + field->name(), structAPIName + "." + field->name(),
524                     nestedArrayOfStructsSize, outputSymbols, outputSymbolsToAPINames);
525             }
526         }
527     }
528 }
529 
buildMangledName(const TString & mangledNamePrefix) const530 TString TFieldListCollection::buildMangledName(const TString &mangledNamePrefix) const
531 {
532     TString mangledName(mangledNamePrefix);
533     mangledName += *mName;
534     for (size_t i = 0; i < mFields->size(); ++i)
535     {
536         mangledName += '-';
537         mangledName += (*mFields)[i]->type()->getMangledName();
538     }
539     return mangledName;
540 }
541 
calculateObjectSize() const542 size_t TFieldListCollection::calculateObjectSize() const
543 {
544     size_t size = 0;
545     for (size_t i = 0; i < mFields->size(); ++i)
546     {
547         size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
548         if (fieldSize > INT_MAX - size)
549             size = INT_MAX;
550         else
551             size += fieldSize;
552     }
553     return size;
554 }
555 
calculateDeepestNesting() const556 int TStructure::calculateDeepestNesting() const
557 {
558     int maxNesting = 0;
559     for (size_t i = 0; i < mFields->size(); ++i)
560         maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
561     return 1 + maxNesting;
562 }
563 
564 }  // namespace sh
565