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