1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef _TYPES_INCLUDED 16 #define _TYPES_INCLUDED 17 18 #include "BaseTypes.h" 19 #include "Common.h" 20 #include "debug.h" 21 22 #include <algorithm> 23 24 class TType; 25 struct TPublicType; 26 27 class TField 28 { 29 public: 30 POOL_ALLOCATOR_NEW_DELETE(); 31 TField(TType *type, TString *name, const TSourceLoc &line) 32 : mType(type), 33 mName(name), 34 mLine(line) 35 { 36 } 37 38 // TODO(alokp): We should only return const type. 39 // Fix it by tweaking grammar. 40 TType *type() 41 { 42 return mType; 43 } 44 const TType *type() const 45 { 46 return mType; 47 } 48 49 const TString &name() const 50 { 51 return *mName; 52 } 53 const TSourceLoc &line() const 54 { 55 return mLine; 56 } 57 58 private: 59 TType *mType; 60 TString *mName; 61 TSourceLoc mLine; 62 }; 63 64 typedef TVector<TField *> TFieldList; 65 inline TFieldList *NewPoolTFieldList() 66 { 67 void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList)); 68 return new(memory)TFieldList; 69 } 70 71 class TFieldListCollection 72 { 73 public: 74 virtual ~TFieldListCollection() { } 75 const TString &name() const 76 { 77 return *mName; 78 } 79 const TFieldList &fields() const 80 { 81 return *mFields; 82 } 83 84 const TString &mangledName() const 85 { 86 if(mMangledName.empty()) 87 mMangledName = buildMangledName(); 88 return mMangledName; 89 } 90 size_t objectSize() const 91 { 92 if(mObjectSize == 0) 93 mObjectSize = calculateObjectSize(); 94 return mObjectSize; 95 }; 96 97 protected: 98 TFieldListCollection(const TString *name, TFieldList *fields) 99 : mName(name), 100 mFields(fields), 101 mObjectSize(0) 102 { 103 } 104 TString buildMangledName() const; 105 size_t calculateObjectSize() const; 106 virtual TString mangledNamePrefix() const = 0; 107 108 const TString *mName; 109 TFieldList *mFields; 110 111 mutable TString mMangledName; 112 mutable size_t mObjectSize; 113 }; 114 115 // May also represent interface blocks 116 class TStructure : public TFieldListCollection 117 { 118 public: 119 POOL_ALLOCATOR_NEW_DELETE(); 120 TStructure(const TString *name, TFieldList *fields) 121 : TFieldListCollection(name, fields), 122 mDeepestNesting(0), 123 mUniqueId(0), 124 mAtGlobalScope(false) 125 { 126 } 127 128 int deepestNesting() const 129 { 130 if(mDeepestNesting == 0) 131 mDeepestNesting = calculateDeepestNesting(); 132 return mDeepestNesting; 133 } 134 bool containsArrays() const; 135 bool containsSamplers() const; 136 137 bool equals(const TStructure &other) const; 138 139 void setUniqueId(int uniqueId) 140 { 141 mUniqueId = uniqueId; 142 } 143 144 int uniqueId() const 145 { 146 ASSERT(mUniqueId != 0); 147 return mUniqueId; 148 } 149 150 void setAtGlobalScope(bool atGlobalScope) 151 { 152 mAtGlobalScope = atGlobalScope; 153 } 154 155 bool atGlobalScope() const 156 { 157 return mAtGlobalScope; 158 } 159 160 private: 161 // TODO(zmo): Find a way to get rid of the const_cast in function 162 // setName(). At the moment keep this function private so only 163 // friend class RegenerateStructNames may call it. 164 friend class RegenerateStructNames; 165 void setName(const TString &name) 166 { 167 TString *mutableName = const_cast<TString *>(mName); 168 *mutableName = name; 169 } 170 171 virtual TString mangledNamePrefix() const 172 { 173 return "struct-"; 174 } 175 int calculateDeepestNesting() const; 176 177 mutable int mDeepestNesting; 178 int mUniqueId; 179 bool mAtGlobalScope; 180 }; 181 182 class TInterfaceBlock : public TFieldListCollection 183 { 184 public: 185 POOL_ALLOCATOR_NEW_DELETE(); 186 TInterfaceBlock(const TString *name, TFieldList *fields, const TString *instanceName, 187 int arraySize, const TLayoutQualifier &layoutQualifier) 188 : TFieldListCollection(name, fields), 189 mInstanceName(instanceName), 190 mArraySize(arraySize), 191 mBlockStorage(layoutQualifier.blockStorage), 192 mMatrixPacking(layoutQualifier.matrixPacking) 193 { 194 } 195 196 const TString &instanceName() const 197 { 198 return *mInstanceName; 199 } 200 bool hasInstanceName() const 201 { 202 return mInstanceName != nullptr; 203 } 204 bool isArray() const 205 { 206 return mArraySize > 0; 207 } 208 int arraySize() const 209 { 210 return mArraySize; 211 } 212 TLayoutBlockStorage blockStorage() const 213 { 214 return mBlockStorage; 215 } 216 TLayoutMatrixPacking matrixPacking() const 217 { 218 return mMatrixPacking; 219 } 220 221 private: 222 virtual TString mangledNamePrefix() const 223 { 224 return "iblock-"; 225 } 226 227 const TString *mInstanceName; // for interface block instance names 228 int mArraySize; // 0 if not an array 229 TLayoutBlockStorage mBlockStorage; 230 TLayoutMatrixPacking mMatrixPacking; 231 }; 232 233 // 234 // Base class for things that have a type. 235 // 236 class TType 237 { 238 public: 239 POOL_ALLOCATOR_NEW_DELETE(); 240 TType() {} 241 TType(TBasicType t, int s0 = 1, int s1 = 1) : 242 type(t), precision(EbpUndefined), qualifier(EvqGlobal), invariant(false), layoutQualifier(TLayoutQualifier::create()), 243 primarySize(s0), secondarySize(s1), array(false), arraySize(0), maxArraySize(0), arrayInformationType(0), interfaceBlock(0), 244 structure(0), deepestStructNesting(0), mangled(0) 245 { 246 } 247 TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s0 = 1, int s1 = 1, bool a = false) : 248 type(t), precision(p), qualifier(q), invariant(false), layoutQualifier(TLayoutQualifier::create()), 249 primarySize(s0), secondarySize(s1), array(a), arraySize(0), maxArraySize(0), arrayInformationType(0), interfaceBlock(0), 250 structure(0), deepestStructNesting(0), mangled(0) 251 { 252 } 253 explicit TType(const TPublicType &p); 254 TType(TStructure* userDef, TPrecision p = EbpUndefined) : 255 type(EbtStruct), precision(p), qualifier(EvqTemporary), invariant(false), layoutQualifier(TLayoutQualifier::create()), 256 primarySize(1), secondarySize(1), array(false), arraySize(0), maxArraySize(0), arrayInformationType(0), interfaceBlock(0), 257 structure(userDef), deepestStructNesting(0), mangled(0) 258 { 259 } 260 261 TType(TInterfaceBlock *interfaceBlockIn, TQualifier qualifierIn, 262 TLayoutQualifier layoutQualifierIn, int arraySizeIn) 263 : type(EbtInterfaceBlock), precision(EbpUndefined), qualifier(qualifierIn), 264 invariant(false), layoutQualifier(layoutQualifierIn), 265 primarySize(1), secondarySize(1), array(arraySizeIn > 0), arraySize(arraySizeIn), maxArraySize(0), arrayInformationType(0), 266 interfaceBlock(interfaceBlockIn), structure(0), deepestStructNesting(0), mangled(0) 267 { 268 } 269 270 TBasicType getBasicType() const { return type; } 271 void setBasicType(TBasicType t) { type = t; } 272 273 TPrecision getPrecision() const { return precision; } 274 void setPrecision(TPrecision p) { precision = p; } 275 276 TQualifier getQualifier() const { return qualifier; } 277 void setQualifier(TQualifier q) { qualifier = q; } 278 279 bool isInvariant() const { return invariant; } 280 281 TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; } 282 void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; } 283 284 // One-dimensional size of single instance type 285 int getNominalSize() const { return primarySize; } 286 void setNominalSize(int s) { primarySize = s; } 287 // Full size of single instance of type 288 size_t getObjectSize() const 289 { 290 if(isArray()) 291 { 292 return getElementSize() * std::max(getArraySize(), getMaxArraySize()); 293 } 294 else 295 { 296 return getElementSize(); 297 } 298 } 299 300 size_t getElementSize() const 301 { 302 if(getBasicType() == EbtStruct) 303 { 304 return getStructSize(); 305 } 306 else if(isInterfaceBlock()) 307 { 308 return interfaceBlock->objectSize(); 309 } 310 else if(isMatrix()) 311 { 312 return primarySize * secondarySize; 313 } 314 else // Vector or scalar 315 { 316 return primarySize; 317 } 318 } 319 320 int elementRegisterCount() const 321 { 322 if(structure || isInterfaceBlock()) 323 { 324 int registerCount = 0; 325 326 const TFieldList& fields = isInterfaceBlock() ? interfaceBlock->fields() : structure->fields(); 327 for(size_t i = 0; i < fields.size(); i++) 328 { 329 registerCount += fields[i]->type()->totalRegisterCount(); 330 } 331 332 return registerCount; 333 } 334 else if(isMatrix()) 335 { 336 return getNominalSize(); 337 } 338 else 339 { 340 return 1; 341 } 342 } 343 344 int blockRegisterCount() const 345 { 346 // If this TType object is a block member, return the register count of the parent block 347 // Otherwise, return the register count of the current TType object 348 if(interfaceBlock && !isInterfaceBlock()) 349 { 350 int registerCount = 0; 351 const TFieldList& fieldList = interfaceBlock->fields(); 352 for(size_t i = 0; i < fieldList.size(); i++) 353 { 354 const TType &fieldType = *(fieldList[i]->type()); 355 registerCount += fieldType.totalRegisterCount(); 356 } 357 return registerCount; 358 } 359 return totalRegisterCount(); 360 } 361 362 int totalRegisterCount() const 363 { 364 if(array) 365 { 366 return arraySize * elementRegisterCount(); 367 } 368 else 369 { 370 return elementRegisterCount(); 371 } 372 } 373 374 int registerSize() const 375 { 376 return isMatrix() ? secondarySize : primarySize; 377 } 378 379 bool isMatrix() const { return secondarySize > 1; } 380 void setSecondarySize(int s1) { secondarySize = s1; } 381 int getSecondarySize() const { return secondarySize; } 382 383 bool isArray() const { return array ? true : false; } 384 int getArraySize() const { return arraySize; } 385 void setArraySize(int s) { array = true; arraySize = s; } 386 int getMaxArraySize () const { return maxArraySize; } 387 void setMaxArraySize (int s) { maxArraySize = s; } 388 void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; } 389 void setArrayInformationType(TType* t) { arrayInformationType = t; } 390 TType* getArrayInformationType() const { return arrayInformationType; } 391 392 TInterfaceBlock *getInterfaceBlock() const { return interfaceBlock; } 393 void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn) { interfaceBlock = interfaceBlockIn; } 394 bool isInterfaceBlock() const { return type == EbtInterfaceBlock; } 395 TInterfaceBlock *getAsInterfaceBlock() const { return isInterfaceBlock() ? getInterfaceBlock() : nullptr; } 396 397 bool isVector() const { return primarySize > 1 && !isMatrix(); } 398 bool isScalar() const { return primarySize == 1 && !isMatrix() && !structure && !isInterfaceBlock(); } 399 bool isRegister() const { return !isMatrix() && !structure && !array && !isInterfaceBlock(); } // Fits in a 4-element register 400 bool isStruct() const { return structure != 0; } 401 bool isScalarInt() const { return isScalar() && IsInteger(type); } 402 403 TStructure* getStruct() const { return structure; } 404 void setStruct(TStructure* s) { structure = s; computeDeepestStructNesting(); } 405 406 TString& getMangledName() { 407 if (!mangled) { 408 mangled = NewPoolTString(""); 409 buildMangledName(*mangled); 410 *mangled += ';' ; 411 } 412 413 return *mangled; 414 } 415 416 bool sameElementType(const TType& right) const { 417 return type == right.type && 418 primarySize == right.primarySize && 419 secondarySize == right.secondarySize && 420 structure == right.structure; 421 } 422 bool operator==(const TType& right) const { 423 return type == right.type && 424 primarySize == right.primarySize && 425 secondarySize == right.secondarySize && 426 array == right.array && (!array || arraySize == right.arraySize) && 427 structure == right.structure; 428 // don't check the qualifier, it's not ever what's being sought after 429 } 430 bool operator!=(const TType& right) const { 431 return !operator==(right); 432 } 433 bool operator<(const TType& right) const { 434 if (type != right.type) return type < right.type; 435 if(primarySize != right.primarySize) return (primarySize * secondarySize) < (right.primarySize * right.secondarySize); 436 if(secondarySize != right.secondarySize) return secondarySize < right.secondarySize; 437 if (array != right.array) return array < right.array; 438 if (arraySize != right.arraySize) return arraySize < right.arraySize; 439 if (structure != right.structure) return structure < right.structure; 440 441 return false; 442 } 443 444 const char* getBasicString() const { return ::getBasicString(type); } 445 const char* getPrecisionString() const { return ::getPrecisionString(precision); } 446 const char* getQualifierString() const { return ::getQualifierString(qualifier); } 447 TString getCompleteString() const; 448 449 // If this type is a struct, returns the deepest struct nesting of 450 // any field in the struct. For example: 451 // struct nesting1 { 452 // vec4 position; 453 // }; 454 // struct nesting2 { 455 // nesting1 field1; 456 // vec4 field2; 457 // }; 458 // For type "nesting2", this method would return 2 -- the number 459 // of structures through which indirection must occur to reach the 460 // deepest field (nesting2.field1.position). 461 int getDeepestStructNesting() const 462 { 463 return structure ? structure->deepestNesting() : 0; 464 } 465 466 bool isStructureContainingArrays() const 467 { 468 return structure ? structure->containsArrays() : false; 469 } 470 471 bool isStructureContainingSamplers() const 472 { 473 return structure ? structure->containsSamplers() : false; 474 } 475 476 protected: 477 void buildMangledName(TString&); 478 size_t getStructSize() const; 479 void computeDeepestStructNesting(); 480 481 TBasicType type; 482 TPrecision precision; 483 TQualifier qualifier; 484 bool invariant; 485 TLayoutQualifier layoutQualifier; 486 unsigned char primarySize; // size of vector or matrix, not size of array 487 unsigned char secondarySize; // secondarySize: 1 for vectors, >1 for matrices 488 bool array; 489 int arraySize; 490 int maxArraySize; 491 TType *arrayInformationType; 492 493 // 0 unless this is an interface block, or interface block member variable 494 TInterfaceBlock *interfaceBlock; 495 496 TStructure *structure; // 0 unless this is a struct 497 int deepestStructNesting; 498 499 TString *mangled; 500 }; 501 502 // 503 // This is a workaround for a problem with the yacc stack, It can't have 504 // types that it thinks have non-trivial constructors. It should 505 // just be used while recognizing the grammar, not anything else. Pointers 506 // could be used, but also trying to avoid lots of memory management overhead. 507 // 508 // Not as bad as it looks, there is no actual assumption that the fields 509 // match up or are name the same or anything like that. 510 // 511 struct TPublicType 512 { 513 TBasicType type; 514 TLayoutQualifier layoutQualifier; 515 TQualifier qualifier; 516 bool invariant; 517 TPrecision precision; 518 int primarySize; // size of vector or matrix, not size of array 519 int secondarySize; // 1 for scalars/vectors, >1 for matrices 520 bool array; 521 int arraySize; 522 TType* userDef; 523 TSourceLoc line; 524 525 void setBasic(TBasicType bt, TQualifier q, const TSourceLoc &ln) 526 { 527 type = bt; 528 layoutQualifier = TLayoutQualifier::create(); 529 qualifier = q; 530 invariant = false; 531 precision = EbpUndefined; 532 primarySize = 1; 533 secondarySize = 1; 534 array = false; 535 arraySize = 0; 536 userDef = 0; 537 line = ln; 538 } 539 540 void setAggregate(int s) 541 { 542 primarySize = s; 543 secondarySize = 1; 544 } 545 546 void setMatrix(int s0, int s1) 547 { 548 primarySize = s0; 549 secondarySize = s1; 550 } 551 552 bool isUnsizedArray() const 553 { 554 return array && arraySize == 0; 555 } 556 557 void setArray(bool a, int s = 0) 558 { 559 array = a; 560 arraySize = s; 561 } 562 563 void clearArrayness() 564 { 565 array = false; 566 arraySize = 0; 567 } 568 569 bool isStructureContainingArrays() const 570 { 571 if (!userDef) 572 { 573 return false; 574 } 575 576 return userDef->isStructureContainingArrays(); 577 } 578 579 bool isMatrix() const 580 { 581 return primarySize > 1 && secondarySize > 1; 582 } 583 584 bool isVector() const 585 { 586 return primarySize > 1 && secondarySize == 1; 587 } 588 589 int getCols() const 590 { 591 ASSERT(isMatrix()); 592 return primarySize; 593 } 594 595 int getRows() const 596 { 597 ASSERT(isMatrix()); 598 return secondarySize; 599 } 600 601 int getNominalSize() const 602 { 603 return primarySize; 604 } 605 606 bool isAggregate() const 607 { 608 return array || isMatrix() || isVector(); 609 } 610 }; 611 612 #endif // _TYPES_INCLUDED_ 613