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