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