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