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 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(); } isScalar()240 bool isScalar() const 241 { 242 return primarySize == 1 && secondarySize == 1 && !mStructure && !isArray(); 243 } isScalarArray()244 bool isScalarArray() const 245 { 246 return primarySize == 1 && secondarySize == 1 && !mStructure && isArray(); 247 } isScalarFloat()248 bool isScalarFloat() const { return isScalar() && type == EbtFloat; } isScalarInt()249 bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); } 250 251 bool canBeConstructed() const; 252 getStruct()253 const TStructure *getStruct() const { return mStructure; } 254 GetSizeMangledName(unsigned char primarySize,unsigned char secondarySize)255 static constexpr char GetSizeMangledName(unsigned char primarySize, unsigned char secondarySize) 256 { 257 unsigned int sizeKey = (secondarySize - 1u) * 4u + primarySize - 1u; 258 if (sizeKey < 10u) 259 { 260 return static_cast<char>('0' + sizeKey); 261 } 262 return static_cast<char>('A' + sizeKey - 10); 263 } 264 const char *getMangledName() const; 265 266 bool sameNonArrayType(const TType &right) const; 267 268 // Returns true if arrayType is an array made of this type. 269 bool isElementTypeOf(const TType &arrayType) const; 270 271 bool operator==(const TType &right) const 272 { 273 size_t numArraySizesL = getNumArraySizes(); 274 size_t numArraySizesR = right.getNumArraySizes(); 275 bool arraySizesEqual = numArraySizesL == numArraySizesR && 276 (numArraySizesL == 0 || mArraySizes == right.mArraySizes); 277 return type == right.type && primarySize == right.primarySize && 278 secondarySize == right.secondarySize && arraySizesEqual && 279 mStructure == right.mStructure; 280 // don't check the qualifier, it's not ever what's being sought after 281 } 282 bool operator!=(const TType &right) const { return !operator==(right); } 283 bool operator<(const TType &right) const 284 { 285 if (type != right.type) 286 return type < right.type; 287 if (primarySize != right.primarySize) 288 return primarySize < right.primarySize; 289 if (secondarySize != right.secondarySize) 290 return secondarySize < right.secondarySize; 291 size_t numArraySizesL = getNumArraySizes(); 292 size_t numArraySizesR = right.getNumArraySizes(); 293 if (numArraySizesL != numArraySizesR) 294 return numArraySizesL < numArraySizesR; 295 for (size_t i = 0; i < numArraySizesL; ++i) 296 { 297 if (mArraySizes[i] != right.mArraySizes[i]) 298 return mArraySizes[i] < right.mArraySizes[i]; 299 } 300 if (mStructure != right.mStructure) 301 return mStructure < right.mStructure; 302 303 return false; 304 } 305 getBasicString()306 const char *getBasicString() const { return sh::getBasicString(type); } 307 getPrecisionString()308 const char *getPrecisionString() const { return sh::getPrecisionString(precision); } getQualifierString()309 const char *getQualifierString() const { return sh::getQualifierString(qualifier); } 310 311 const char *getBuiltInTypeNameString() const; 312 313 // If this type is a struct, returns the deepest struct nesting of 314 // any field in the struct. For example: 315 // struct nesting1 { 316 // vec4 position; 317 // }; 318 // struct nesting2 { 319 // nesting1 field1; 320 // vec4 field2; 321 // }; 322 // For type "nesting2", this method would return 2 -- the number 323 // of structures through which indirection must occur to reach the 324 // deepest field (nesting2.field1.position). 325 int getDeepestStructNesting() const; 326 327 bool isNamelessStruct() const; 328 329 bool isStructureContainingArrays() const; 330 bool isStructureContainingMatrices() const; 331 bool isStructureContainingType(TBasicType t) const; 332 bool isStructureContainingSamplers() const; 333 isStructSpecifier()334 bool isStructSpecifier() const { return mIsStructSpecifier; } 335 336 // Return true if variables of this type should be replaced with an inline constant value if 337 // such is available. False will be returned in cases where output doesn't support 338 // TIntermConstantUnion nodes of the type, or if the type contains a lot of fields and creating 339 // several copies of it in the output code is undesirable for performance. 340 bool canReplaceWithConstantUnion() const; 341 342 // The char arrays passed in must be pool allocated or static. 343 void createSamplerSymbols(const ImmutableString &namePrefix, 344 const TString &apiNamePrefix, 345 TVector<const TVariable *> *outputSymbols, 346 TMap<const TVariable *, TString> *outputSymbolsToAPINames, 347 TSymbolTable *symbolTable) const; 348 349 // Initializes all lazily-initialized members. 350 void realize(); 351 isSampler()352 bool isSampler() const { return IsSampler(type); } isSamplerCube()353 bool isSamplerCube() const { return type == EbtSamplerCube; } isAtomicCounter()354 bool isAtomicCounter() const { return IsAtomicCounter(type); } isSamplerVideoWEBGL()355 bool isSamplerVideoWEBGL() const { return type == EbtSamplerVideoWEBGL; } isImage()356 bool isImage() const { return IsImage(type); } 357 358 private: invalidateMangledName()359 constexpr void invalidateMangledName() { mMangledName = nullptr; } 360 const char *buildMangledName() const; onArrayDimensionsChange(const TSpan<const unsigned int> & sizes)361 constexpr void onArrayDimensionsChange(const TSpan<const unsigned int> &sizes) 362 { 363 mArraySizes = sizes; 364 invalidateMangledName(); 365 } 366 367 TBasicType type; 368 TPrecision precision; 369 TQualifier qualifier; 370 bool invariant; 371 bool precise; 372 373 TMemoryQualifier memoryQualifier; 374 TLayoutQualifier layoutQualifier; 375 unsigned char primarySize; // size of vector or cols matrix 376 unsigned char secondarySize; // rows of a matrix 377 378 // Used to make an array type. Outermost array size is stored at the end of the vector. Having 0 379 // in this vector means an unsized array. 380 TSpan<const unsigned int> mArraySizes; 381 // Storage for mArraySizes, if any. This is usually the case, except for constexpr TTypes which 382 // only have a valid mArraySizes (with mArraySizesStorage being nullptr). Therefore, all 383 // modifications to array sizes happen on the storage (and if dimensions change, mArraySizes is 384 // also updated) and all reads are from mArraySizes. 385 TVector<unsigned int> *mArraySizesStorage; 386 387 // This is set only in the following two cases: 388 // 1) Represents an interface block. 389 // 2) Represents the member variable of an unnamed interface block. 390 // It's nullptr also for members of named interface blocks. 391 const TInterfaceBlock *mInterfaceBlock; 392 393 // nullptr unless this is a struct 394 const TStructure *mStructure; 395 bool mIsStructSpecifier; 396 397 // If this is a field of a nameless interface block, this would indicate which member it's 398 // refering to. 399 size_t mInterfaceBlockFieldIndex; 400 401 mutable const char *mMangledName; 402 }; 403 404 // TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the 405 // grammar 406 struct TTypeSpecifierNonArray 407 { 408 TBasicType type; 409 unsigned char primarySize; // size of vector or cols of matrix 410 unsigned char secondarySize; // rows of matrix 411 const TStructure *userDef; 412 TSourceLoc line; 413 414 // true if the type was defined by a struct specifier rather than a reference to a type name. 415 bool isStructSpecifier; 416 initializeTTypeSpecifierNonArray417 void initialize(TBasicType aType, const TSourceLoc &aLine) 418 { 419 ASSERT(aType != EbtStruct); 420 type = aType; 421 primarySize = 1; 422 secondarySize = 1; 423 userDef = nullptr; 424 line = aLine; 425 isStructSpecifier = false; 426 } 427 initializeStructTTypeSpecifierNonArray428 void initializeStruct(const TStructure *aUserDef, 429 bool aIsStructSpecifier, 430 const TSourceLoc &aLine) 431 { 432 type = EbtStruct; 433 primarySize = 1; 434 secondarySize = 1; 435 userDef = aUserDef; 436 line = aLine; 437 isStructSpecifier = aIsStructSpecifier; 438 } 439 setAggregateTTypeSpecifierNonArray440 void setAggregate(unsigned char size) { primarySize = size; } 441 setMatrixTTypeSpecifierNonArray442 void setMatrix(unsigned char columns, unsigned char rows) 443 { 444 ASSERT(columns > 1 && rows > 1 && columns <= 4 && rows <= 4); 445 primarySize = columns; 446 secondarySize = rows; 447 } 448 isMatrixTTypeSpecifierNonArray449 bool isMatrix() const { return primarySize > 1 && secondarySize > 1; } 450 isVectorTTypeSpecifierNonArray451 bool isVector() const { return primarySize > 1 && secondarySize == 1; } 452 }; 453 454 // 455 // This is a workaround for a problem with the yacc stack, It can't have 456 // types that it thinks have non-trivial constructors. It should 457 // just be used while recognizing the grammar, not anything else. Pointers 458 // could be used, but also trying to avoid lots of memory management overhead. 459 // 460 // Not as bad as it looks, there is no actual assumption that the fields 461 // match up or are name the same or anything like that. 462 // 463 struct TPublicType 464 { 465 // Must have a trivial default constructor since it is used in YYSTYPE. 466 TPublicType() = default; 467 468 void initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q); 469 void initializeBasicType(TBasicType basicType); 470 getBasicTypeTPublicType471 TBasicType getBasicType() const { return typeSpecifierNonArray.type; } setBasicTypeTPublicType472 void setBasicType(TBasicType basicType) { typeSpecifierNonArray.type = basicType; } 473 getPrimarySizeTPublicType474 unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; } getSecondarySizeTPublicType475 unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; } 476 getUserDefTPublicType477 const TStructure *getUserDef() const { return typeSpecifierNonArray.userDef; } getLineTPublicType478 const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; } 479 isStructSpecifierTPublicType480 bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; } 481 482 bool isStructureContainingArrays() const; 483 bool isStructureContainingType(TBasicType t) const; 484 void setArraySizes(TVector<unsigned int> *sizes); 485 bool isArray() const; 486 void clearArrayness(); 487 bool isAggregate() const; 488 489 TTypeSpecifierNonArray typeSpecifierNonArray; 490 TLayoutQualifier layoutQualifier; 491 TMemoryQualifier memoryQualifier; 492 TQualifier qualifier; 493 bool invariant; 494 bool precise; 495 TPrecision precision; 496 497 // Either nullptr or empty in case the type is not an array. The last element is the outermost 498 // array size. Note that due to bison restrictions, copies of the public type created by the 499 // copy constructor share the same arraySizes pointer. 500 const TVector<unsigned int> *arraySizes; 501 }; 502 503 } // namespace sh 504 505 #endif // COMPILER_TRANSLATOR_TYPES_H_ 506