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 #ifndef COMPILER_TRANSLATOR_TYPES_H_ 8 #define COMPILER_TRANSLATOR_TYPES_H_ 9 10 #include "common/angleutils.h" 11 #include "common/debug.h" 12 13 #include "compiler/translator/BaseTypes.h" 14 #include "compiler/translator/Common.h" 15 #include "compiler/translator/ImmutableString.h" 16 #include "compiler/translator/SymbolUniqueId.h" 17 18 namespace sh 19 { 20 21 struct TPublicType; 22 class TType; 23 class TInterfaceBlock; 24 class TStructure; 25 class TSymbol; 26 class TVariable; 27 class TIntermSymbol; 28 class TSymbolTable; 29 30 class TField : angle::NonCopyable 31 { 32 public: 33 POOL_ALLOCATOR_NEW_DELETE TField(TType * type,const ImmutableString & name,const TSourceLoc & line,SymbolType symbolType)34 TField(TType *type, const ImmutableString &name, const TSourceLoc &line, SymbolType symbolType) 35 : mType(type), mName(name), mLine(line), mSymbolType(symbolType) 36 { 37 ASSERT(mSymbolType != SymbolType::Empty); 38 } 39 40 // TODO(alokp): We should only return const type. 41 // Fix it by tweaking grammar. type()42 TType *type() { return mType; } type()43 const TType *type() const { return mType; } name()44 const ImmutableString &name() const { return mName; } line()45 const TSourceLoc &line() const { return mLine; } symbolType()46 SymbolType symbolType() const { return mSymbolType; } 47 48 private: 49 TType *mType; 50 const ImmutableString mName; 51 const TSourceLoc mLine; 52 const SymbolType mSymbolType; 53 }; 54 55 typedef TVector<TField *> TFieldList; 56 57 class TFieldListCollection : angle::NonCopyable 58 { 59 public: fields()60 const TFieldList &fields() const { return *mFields; } 61 62 bool containsArrays() const; 63 bool containsMatrices() const; 64 bool containsType(TBasicType t) const; 65 bool containsSamplers() const; 66 67 size_t objectSize() const; 68 // How many locations the field list consumes as a uniform. 69 int getLocationCount() const; 70 int deepestNesting() const; 71 const TString &mangledFieldList() const; 72 73 protected: 74 TFieldListCollection(const TFieldList *fields); 75 76 const TFieldList *mFields; 77 78 private: 79 size_t calculateObjectSize() const; 80 int calculateDeepestNesting() const; 81 TString buildMangledFieldList() const; 82 83 mutable size_t mObjectSize; 84 mutable int mDeepestNesting; 85 mutable TString mMangledFieldList; 86 }; 87 88 // 89 // Base class for things that have a type. 90 // 91 class TType 92 { 93 public: 94 POOL_ALLOCATOR_NEW_DELETE 95 TType(); 96 explicit TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1); 97 TType(TBasicType t, 98 TPrecision p, 99 TQualifier q = EvqTemporary, 100 unsigned char ps = 1, 101 unsigned char ss = 1); 102 explicit TType(const TPublicType &p); 103 TType(const TStructure *userDef, bool isStructSpecifier); 104 TType(const TInterfaceBlock *interfaceBlockIn, 105 TQualifier qualifierIn, 106 TLayoutQualifier layoutQualifierIn); 107 TType(const TType &t); 108 TType &operator=(const TType &t); 109 TType(TBasicType t,TPrecision p,TQualifier q,unsigned char ps,unsigned char ss,const TSpan<const unsigned int> arraySizes,const char * mangledName)110 constexpr TType(TBasicType t, 111 TPrecision p, 112 TQualifier q, 113 unsigned char ps, 114 unsigned char ss, 115 const TSpan<const unsigned int> arraySizes, 116 const char *mangledName) 117 : type(t), 118 precision(p), 119 qualifier(q), 120 invariant(false), 121 precise(false), 122 memoryQualifier(TMemoryQualifier::Create()), 123 layoutQualifier(TLayoutQualifier::Create()), 124 primarySize(ps), 125 secondarySize(ss), 126 mArraySizes(arraySizes), 127 mArraySizesStorage(nullptr), 128 mInterfaceBlock(nullptr), 129 mStructure(nullptr), 130 mIsStructSpecifier(false), 131 mInterfaceBlockFieldIndex(0), 132 mMangledName(mangledName) 133 {} 134 TType(TType && t)135 constexpr TType(TType &&t) 136 : type(t.type), 137 precision(t.precision), 138 qualifier(t.qualifier), 139 invariant(t.invariant), 140 precise(t.precise), 141 memoryQualifier(t.memoryQualifier), 142 layoutQualifier(t.layoutQualifier), 143 primarySize(t.primarySize), 144 secondarySize(t.secondarySize), 145 mArraySizes(t.mArraySizes), 146 mArraySizesStorage(t.mArraySizesStorage), 147 mInterfaceBlock(t.mInterfaceBlock), 148 mStructure(t.mStructure), 149 mIsStructSpecifier(t.mIsStructSpecifier), 150 mInterfaceBlockFieldIndex(0), 151 mMangledName(t.mMangledName) 152 { 153 t.mArraySizesStorage = nullptr; 154 } 155 getBasicType()156 constexpr TBasicType getBasicType() const { return type; } 157 void setBasicType(TBasicType t); 158 getPrecision()159 TPrecision getPrecision() const { return precision; } setPrecision(TPrecision p)160 void setPrecision(TPrecision p) { precision = p; } 161 getQualifier()162 constexpr TQualifier getQualifier() const { return qualifier; } setQualifier(TQualifier q)163 void setQualifier(TQualifier q) { qualifier = q; } 164 isInvariant()165 bool isInvariant() const { return invariant; } setInvariant(bool i)166 void setInvariant(bool i) { invariant = i; } 167 isPrecise()168 bool isPrecise() const { return precise; } setPrecise(bool i)169 void setPrecise(bool i) { precise = i; } 170 getMemoryQualifier()171 TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; } setMemoryQualifier(const TMemoryQualifier & mq)172 void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; } 173 getLayoutQualifier()174 TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; } setLayoutQualifier(TLayoutQualifier lq)175 void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; } 176 getNominalSize()177 int getNominalSize() const { return primarySize; } getSecondarySize()178 int getSecondarySize() const { return secondarySize; } getCols()179 int getCols() const 180 { 181 ASSERT(isMatrix()); 182 return primarySize; 183 } getRows()184 int getRows() const 185 { 186 ASSERT(isMatrix()); 187 return secondarySize; 188 } 189 void setPrimarySize(unsigned char ps); 190 void setSecondarySize(unsigned char ss); 191 192 // Full size of single instance of type 193 size_t getObjectSize() const; 194 195 // Get how many locations this type consumes as a uniform. 196 int getLocationCount() const; 197 isMatrix()198 bool isMatrix() const { return primarySize > 1 && secondarySize > 1; } isNonSquareMatrix()199 bool isNonSquareMatrix() const { return isMatrix() && primarySize != secondarySize; } isArray()200 bool isArray() const { return !mArraySizes.empty(); } isArrayOfArrays()201 bool isArrayOfArrays() const { return mArraySizes.size() > 1u; } getNumArraySizes()202 size_t getNumArraySizes() const { return mArraySizes.size(); } getArraySizes()203 const TSpan<const unsigned int> &getArraySizes() const { return mArraySizes; } 204 unsigned int getArraySizeProduct() const; 205 bool isUnsizedArray() const; getOutermostArraySize()206 unsigned int getOutermostArraySize() const 207 { 208 ASSERT(isArray()); 209 return mArraySizes.back(); 210 } 211 void makeArray(unsigned int s); 212 213 // sizes contain new outermost array sizes. 214 void makeArrays(const TSpan<const unsigned int> &sizes); 215 // Here, the array dimension value 0 corresponds to the innermost array. 216 void setArraySize(size_t arrayDimension, unsigned int s); 217 218 // Will set unsized array sizes according to newArraySizes. In case there are more 219 // unsized arrays than there are sizes in newArraySizes, defaults to setting any 220 // remaining array sizes to 1. 221 void sizeUnsizedArrays(const TSpan<const unsigned int> &newArraySizes); 222 223 // Will size the outermost array according to arraySize. 224 void sizeOutermostUnsizedArray(unsigned int arraySize); 225 226 // Note that the array element type might still be an array type in GLSL ES version >= 3.10. 227 void toArrayElementType(); 228 // Removes all array sizes. 229 void toArrayBaseType(); 230 // Turns a matrix into a column of it. 231 void toMatrixColumnType(); 232 // Turns a matrix or vector into a component of it. 233 void toComponentType(); 234 getInterfaceBlock()235 const TInterfaceBlock *getInterfaceBlock() const { return mInterfaceBlock; } 236 void setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn); isInterfaceBlock()237 bool isInterfaceBlock() const { return type == EbtInterfaceBlock; } 238 239 void setInterfaceBlockField(const TInterfaceBlock *interfaceBlockIn, size_t fieldIndex); getInterfaceBlockFieldIndex()240 size_t getInterfaceBlockFieldIndex() const { return mInterfaceBlockFieldIndex; } 241 isVector()242 bool isVector() const { return primarySize > 1 && secondarySize == 1; } isVectorArray()243 bool isVectorArray() const { return primarySize > 1 && secondarySize == 1 && isArray(); } isRank0()244 bool isRank0() const { return primarySize == 1 && secondarySize == 1; } isScalar()245 bool isScalar() const 246 { 247 return primarySize == 1 && secondarySize == 1 && !mStructure && !isArray(); 248 } isScalarArray()249 bool isScalarArray() const 250 { 251 return primarySize == 1 && secondarySize == 1 && !mStructure && isArray(); 252 } isScalarFloat()253 bool isScalarFloat() const { return isScalar() && type == EbtFloat; } isScalarInt()254 bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); } 255 256 bool canBeConstructed() const; 257 getStruct()258 const TStructure *getStruct() const { return mStructure; } 259 GetSizeMangledName(unsigned char primarySize,unsigned char secondarySize)260 static constexpr char GetSizeMangledName(unsigned char primarySize, unsigned char secondarySize) 261 { 262 unsigned int sizeKey = (secondarySize - 1u) * 4u + primarySize - 1u; 263 if (sizeKey < 10u) 264 { 265 return static_cast<char>('0' + sizeKey); 266 } 267 return static_cast<char>('A' + sizeKey - 10); 268 } 269 const char *getMangledName() const; 270 271 bool sameNonArrayType(const TType &right) const; 272 273 // Returns true if arrayType is an array made of this type. 274 bool isElementTypeOf(const TType &arrayType) const; 275 276 bool operator==(const TType &right) const 277 { 278 size_t numArraySizesL = getNumArraySizes(); 279 size_t numArraySizesR = right.getNumArraySizes(); 280 bool arraySizesEqual = numArraySizesL == numArraySizesR && 281 (numArraySizesL == 0 || mArraySizes == right.mArraySizes); 282 return type == right.type && primarySize == right.primarySize && 283 secondarySize == right.secondarySize && arraySizesEqual && 284 mStructure == right.mStructure; 285 // don't check the qualifier, it's not ever what's being sought after 286 } 287 bool operator!=(const TType &right) const { return !operator==(right); } 288 bool operator<(const TType &right) const 289 { 290 if (type != right.type) 291 return type < right.type; 292 if (primarySize != right.primarySize) 293 return primarySize < right.primarySize; 294 if (secondarySize != right.secondarySize) 295 return secondarySize < right.secondarySize; 296 size_t numArraySizesL = getNumArraySizes(); 297 size_t numArraySizesR = right.getNumArraySizes(); 298 if (numArraySizesL != numArraySizesR) 299 return numArraySizesL < numArraySizesR; 300 for (size_t i = 0; i < numArraySizesL; ++i) 301 { 302 if (mArraySizes[i] != right.mArraySizes[i]) 303 return mArraySizes[i] < right.mArraySizes[i]; 304 } 305 if (mStructure != right.mStructure) 306 return mStructure < right.mStructure; 307 308 return false; 309 } 310 getBasicString()311 const char *getBasicString() const { return sh::getBasicString(type); } 312 getPrecisionString()313 const char *getPrecisionString() const { return sh::getPrecisionString(precision); } getQualifierString()314 const char *getQualifierString() const { return sh::getQualifierString(qualifier); } 315 316 const char *getBuiltInTypeNameString() const; 317 318 // If this type is a struct, returns the deepest struct nesting of 319 // any field in the struct. For example: 320 // struct nesting1 { 321 // vec4 position; 322 // }; 323 // struct nesting2 { 324 // nesting1 field1; 325 // vec4 field2; 326 // }; 327 // For type "nesting2", this method would return 2 -- the number 328 // of structures through which indirection must occur to reach the 329 // deepest field (nesting2.field1.position). 330 int getDeepestStructNesting() const; 331 332 bool isNamelessStruct() const; 333 334 bool isStructureContainingArrays() const; 335 bool isStructureContainingMatrices() const; 336 bool isStructureContainingType(TBasicType t) const; 337 bool isStructureContainingSamplers() const; 338 bool isInterfaceBlockContainingType(TBasicType t) const; 339 isStructSpecifier()340 bool isStructSpecifier() const { return mIsStructSpecifier; } 341 342 // Return true if variables of this type should be replaced with an inline constant value if 343 // such is available. False will be returned in cases where output doesn't support 344 // TIntermConstantUnion nodes of the type, or if the type contains a lot of fields and creating 345 // several copies of it in the output code is undesirable for performance. 346 bool canReplaceWithConstantUnion() const; 347 348 // The char arrays passed in must be pool allocated or static. 349 void createSamplerSymbols(const ImmutableString &namePrefix, 350 const TString &apiNamePrefix, 351 TVector<const TVariable *> *outputSymbols, 352 TMap<const TVariable *, TString> *outputSymbolsToAPINames, 353 TSymbolTable *symbolTable) const; 354 355 // Initializes all lazily-initialized members. 356 void realize(); 357 isSampler()358 bool isSampler() const { return IsSampler(type); } isSamplerCube()359 bool isSamplerCube() const { return type == EbtSamplerCube; } isAtomicCounter()360 bool isAtomicCounter() const { return IsAtomicCounter(type); } isSamplerVideoWEBGL()361 bool isSamplerVideoWEBGL() const { return type == EbtSamplerVideoWEBGL; } isImage()362 bool isImage() const { return IsImage(type); } 363 364 private: invalidateMangledName()365 constexpr void invalidateMangledName() { mMangledName = nullptr; } 366 const char *buildMangledName() const; onArrayDimensionsChange(const TSpan<const unsigned int> & sizes)367 constexpr void onArrayDimensionsChange(const TSpan<const unsigned int> &sizes) 368 { 369 mArraySizes = sizes; 370 invalidateMangledName(); 371 } 372 373 TBasicType type; 374 TPrecision precision; 375 TQualifier qualifier; 376 bool invariant; 377 bool precise; 378 379 TMemoryQualifier memoryQualifier; 380 TLayoutQualifier layoutQualifier; 381 unsigned char primarySize; // size of vector or cols matrix 382 unsigned char secondarySize; // rows of a matrix 383 384 // Used to make an array type. Outermost array size is stored at the end of the vector. Having 0 385 // in this vector means an unsized array. 386 TSpan<const unsigned int> mArraySizes; 387 // Storage for mArraySizes, if any. This is usually the case, except for constexpr TTypes which 388 // only have a valid mArraySizes (with mArraySizesStorage being nullptr). Therefore, all 389 // modifications to array sizes happen on the storage (and if dimensions change, mArraySizes is 390 // also updated) and all reads are from mArraySizes. 391 TVector<unsigned int> *mArraySizesStorage; 392 393 // This is set only in the following two cases: 394 // 1) Represents an interface block. 395 // 2) Represents the member variable of an unnamed interface block. 396 // It's nullptr also for members of named interface blocks. 397 const TInterfaceBlock *mInterfaceBlock; 398 399 // nullptr unless this is a struct 400 const TStructure *mStructure; 401 bool mIsStructSpecifier; 402 403 // If this is a field of a nameless interface block, this would indicate which member it's 404 // refering to. 405 size_t mInterfaceBlockFieldIndex; 406 407 mutable const char *mMangledName; 408 }; 409 410 // TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the 411 // grammar 412 struct TTypeSpecifierNonArray 413 { 414 TBasicType type; 415 unsigned char primarySize; // size of vector or cols of matrix 416 unsigned char secondarySize; // rows of matrix 417 const TStructure *userDef; 418 TSourceLoc line; 419 420 // true if the type was defined by a struct specifier rather than a reference to a type name. 421 bool isStructSpecifier; 422 initializeTTypeSpecifierNonArray423 void initialize(TBasicType aType, const TSourceLoc &aLine) 424 { 425 ASSERT(aType != EbtStruct); 426 type = aType; 427 primarySize = 1; 428 secondarySize = 1; 429 userDef = nullptr; 430 line = aLine; 431 isStructSpecifier = false; 432 } 433 initializeStructTTypeSpecifierNonArray434 void initializeStruct(const TStructure *aUserDef, 435 bool aIsStructSpecifier, 436 const TSourceLoc &aLine) 437 { 438 type = EbtStruct; 439 primarySize = 1; 440 secondarySize = 1; 441 userDef = aUserDef; 442 line = aLine; 443 isStructSpecifier = aIsStructSpecifier; 444 } 445 setAggregateTTypeSpecifierNonArray446 void setAggregate(unsigned char size) { primarySize = size; } 447 setMatrixTTypeSpecifierNonArray448 void setMatrix(unsigned char columns, unsigned char rows) 449 { 450 ASSERT(columns > 1 && rows > 1 && columns <= 4 && rows <= 4); 451 primarySize = columns; 452 secondarySize = rows; 453 } 454 isMatrixTTypeSpecifierNonArray455 bool isMatrix() const { return primarySize > 1 && secondarySize > 1; } 456 isVectorTTypeSpecifierNonArray457 bool isVector() const { return primarySize > 1 && secondarySize == 1; } 458 }; 459 460 // 461 // This is a workaround for a problem with the yacc stack, It can't have 462 // types that it thinks have non-trivial constructors. It should 463 // just be used while recognizing the grammar, not anything else. Pointers 464 // could be used, but also trying to avoid lots of memory management overhead. 465 // 466 // Not as bad as it looks, there is no actual assumption that the fields 467 // match up or are name the same or anything like that. 468 // 469 struct TPublicType 470 { 471 // Must have a trivial default constructor since it is used in YYSTYPE. 472 TPublicType() = default; 473 474 void initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q); 475 void initializeBasicType(TBasicType basicType); 476 getBasicTypeTPublicType477 TBasicType getBasicType() const { return typeSpecifierNonArray.type; } setBasicTypeTPublicType478 void setBasicType(TBasicType basicType) { typeSpecifierNonArray.type = basicType; } 479 getPrimarySizeTPublicType480 unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; } getSecondarySizeTPublicType481 unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; } 482 getUserDefTPublicType483 const TStructure *getUserDef() const { return typeSpecifierNonArray.userDef; } getLineTPublicType484 const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; } 485 isStructSpecifierTPublicType486 bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; } 487 488 bool isStructureContainingArrays() const; 489 bool isStructureContainingType(TBasicType t) const; 490 void setArraySizes(TVector<unsigned int> *sizes); 491 bool isArray() const; 492 void clearArrayness(); 493 bool isAggregate() const; 494 495 TTypeSpecifierNonArray typeSpecifierNonArray; 496 TLayoutQualifier layoutQualifier; 497 TMemoryQualifier memoryQualifier; 498 TQualifier qualifier; 499 bool invariant; 500 bool precise; 501 TPrecision precision; 502 503 // Either nullptr or empty in case the type is not an array. The last element is the outermost 504 // array size. Note that due to bison restrictions, copies of the public type created by the 505 // copy constructor share the same arraySizes pointer. 506 const TVector<unsigned int> *arraySizes; 507 }; 508 509 } // namespace sh 510 511 #endif // COMPILER_TRANSLATOR_TYPES_H_ 512