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 containsType(TBasicType type) const; 136 bool containsSamplers() const; 137 138 bool equals(const TStructure &other) const; 139 140 void setMatrixPackingIfUnspecified(TLayoutMatrixPacking matrixPacking); 141 142 void setUniqueId(int uniqueId) 143 { 144 mUniqueId = uniqueId; 145 } 146 147 int uniqueId() const 148 { 149 ASSERT(mUniqueId != 0); 150 return mUniqueId; 151 } 152 153 void setAtGlobalScope(bool atGlobalScope) 154 { 155 mAtGlobalScope = atGlobalScope; 156 } 157 158 bool atGlobalScope() const 159 { 160 return mAtGlobalScope; 161 } 162 163 private: 164 // TODO(zmo): Find a way to get rid of the const_cast in function 165 // setName(). At the moment keep this function private so only 166 // friend class RegenerateStructNames may call it. 167 friend class RegenerateStructNames; 168 void setName(const TString &name) 169 { 170 TString *mutableName = const_cast<TString *>(mName); 171 *mutableName = name; 172 } 173 174 virtual TString mangledNamePrefix() const 175 { 176 return "struct-"; 177 } 178 int calculateDeepestNesting() const; 179 180 mutable int mDeepestNesting; 181 int mUniqueId; 182 bool mAtGlobalScope; 183 }; 184 185 class TInterfaceBlock : public TFieldListCollection 186 { 187 public: 188 POOL_ALLOCATOR_NEW_DELETE(); 189 TInterfaceBlock(const TString *name, TFieldList *fields, const TString *instanceName, 190 int arraySize, const TLayoutQualifier &layoutQualifier) 191 : TFieldListCollection(name, fields), 192 mInstanceName(instanceName), 193 mArraySize(arraySize), 194 mBlockStorage(layoutQualifier.blockStorage), 195 mMatrixPacking(layoutQualifier.matrixPacking) 196 { 197 } 198 199 const TString &instanceName() const 200 { 201 return *mInstanceName; 202 } 203 bool hasInstanceName() const 204 { 205 return mInstanceName != nullptr; 206 } 207 bool isArray() const 208 { 209 return mArraySize > 0; 210 } 211 int arraySize() const 212 { 213 return mArraySize; 214 } 215 TLayoutBlockStorage blockStorage() const 216 { 217 return mBlockStorage; 218 } 219 TLayoutMatrixPacking matrixPacking() const 220 { 221 return mMatrixPacking; 222 } 223 224 private: 225 virtual TString mangledNamePrefix() const 226 { 227 return "iblock-"; 228 } 229 230 const TString *mInstanceName; // for interface block instance names 231 int mArraySize; // 0 if not an array 232 TLayoutBlockStorage mBlockStorage; 233 TLayoutMatrixPacking mMatrixPacking; 234 }; 235 236 // 237 // Base class for things that have a type. 238 // 239 class TType 240 { 241 public: 242 POOL_ALLOCATOR_NEW_DELETE(); 243 244 TType(TBasicType t, int s0 = 1, int s1 = 1) : 245 type(t), precision(EbpUndefined), qualifier(EvqGlobal), 246 primarySize(s0), secondarySize(s1), array(false), arraySize(0), maxArraySize(0), arrayInformationType(0), interfaceBlock(0), layoutQualifier(TLayoutQualifier::create()), 247 structure(0), mangled(0) 248 { 249 } 250 251 TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s0 = 1, int s1 = 1, bool a = false) : 252 type(t), precision(p), qualifier(q), 253 primarySize(s0), secondarySize(s1), array(a), arraySize(0), maxArraySize(0), arrayInformationType(0), interfaceBlock(0), layoutQualifier(TLayoutQualifier::create()), 254 structure(0), mangled(0) 255 { 256 } 257 258 TType(TStructure* userDef, TPrecision p = EbpUndefined) : 259 type(EbtStruct), precision(p), qualifier(EvqTemporary), 260 primarySize(1), secondarySize(1), array(false), arraySize(0), maxArraySize(0), arrayInformationType(0), interfaceBlock(0), layoutQualifier(TLayoutQualifier::create()), 261 structure(userDef), mangled(0) 262 { 263 } 264 265 TType(TInterfaceBlock *interfaceBlockIn, TQualifier qualifierIn, 266 TLayoutQualifier layoutQualifierIn, int arraySizeIn) 267 : type(EbtInterfaceBlock), precision(EbpUndefined), qualifier(qualifierIn), 268 primarySize(1), secondarySize(1), array(arraySizeIn > 0), arraySize(arraySizeIn), maxArraySize(0), arrayInformationType(0), 269 interfaceBlock(interfaceBlockIn), layoutQualifier(layoutQualifierIn), structure(0), mangled(0) 270 { 271 } 272 273 explicit TType(const TPublicType &p); 274 275 TBasicType getBasicType() const { return type; } 276 void setBasicType(TBasicType t) { type = t; } 277 278 TPrecision getPrecision() const { return precision; } 279 void setPrecision(TPrecision p) { precision = p; } 280 281 TQualifier getQualifier() const { return qualifier; } 282 void setQualifier(TQualifier q) { qualifier = q; } 283 284 TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; } 285 void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; } 286 287 void setMatrixPackingIfUnspecified(TLayoutMatrixPacking matrixPacking) 288 { 289 if(isStruct()) 290 { 291 // If the structure's matrix packing is specified, it overrules the block's matrix packing 292 structure->setMatrixPackingIfUnspecified((layoutQualifier.matrixPacking == EmpUnspecified) ? 293 matrixPacking : layoutQualifier.matrixPacking); 294 } 295 // If the member's matrix packing is specified, it overrules any higher level matrix packing 296 if(layoutQualifier.matrixPacking == EmpUnspecified) 297 { 298 layoutQualifier.matrixPacking = matrixPacking; 299 } 300 } 301 302 // One-dimensional size of single instance type 303 int getNominalSize() const { return primarySize; } 304 void setNominalSize(int s) { primarySize = s; } 305 // Full size of single instance of type 306 size_t getObjectSize() const 307 { 308 if(isArray()) 309 { 310 return getElementSize() * std::max(getArraySize(), getMaxArraySize()); 311 } 312 else 313 { 314 return getElementSize(); 315 } 316 } 317 318 size_t getElementSize() const 319 { 320 if(getBasicType() == EbtStruct) 321 { 322 return getStructSize(); 323 } 324 else if(isInterfaceBlock()) 325 { 326 return interfaceBlock->objectSize(); 327 } 328 else if(isMatrix()) 329 { 330 return primarySize * secondarySize; 331 } 332 else // Vector or scalar 333 { 334 return primarySize; 335 } 336 } 337 338 int samplerRegisterCount() const 339 { 340 if(structure) 341 { 342 int registerCount = 0; 343 344 const TFieldList& fields = isInterfaceBlock() ? interfaceBlock->fields() : structure->fields(); 345 for(size_t i = 0; i < fields.size(); i++) 346 { 347 registerCount += fields[i]->type()->totalSamplerRegisterCount(); 348 } 349 350 return registerCount; 351 } 352 353 return IsSampler(getBasicType()) ? 1 : 0; 354 } 355 356 int elementRegisterCount() const 357 { 358 if(structure || isInterfaceBlock()) 359 { 360 int registerCount = 0; 361 362 const TFieldList& fields = isInterfaceBlock() ? interfaceBlock->fields() : structure->fields(); 363 for(size_t i = 0; i < fields.size(); i++) 364 { 365 registerCount += fields[i]->type()->totalRegisterCount(); 366 } 367 368 return registerCount; 369 } 370 else if(isMatrix()) 371 { 372 return getNominalSize(); 373 } 374 else 375 { 376 return 1; 377 } 378 } 379 380 int blockRegisterCount() const 381 { 382 // If this TType object is a block member, return the register count of the parent block 383 // Otherwise, return the register count of the current TType object 384 if(interfaceBlock && !isInterfaceBlock()) 385 { 386 int registerCount = 0; 387 const TFieldList& fieldList = interfaceBlock->fields(); 388 for(size_t i = 0; i < fieldList.size(); i++) 389 { 390 const TType &fieldType = *(fieldList[i]->type()); 391 registerCount += fieldType.totalRegisterCount(); 392 } 393 return registerCount; 394 } 395 return totalRegisterCount(); 396 } 397 398 int totalSamplerRegisterCount() const 399 { 400 if(array) 401 { 402 return arraySize * samplerRegisterCount(); 403 } 404 else 405 { 406 return samplerRegisterCount(); 407 } 408 } 409 410 int totalRegisterCount() const 411 { 412 if(array) 413 { 414 return arraySize * elementRegisterCount(); 415 } 416 else 417 { 418 return elementRegisterCount(); 419 } 420 } 421 422 int registerSize() const 423 { 424 return isMatrix() ? secondarySize : primarySize; 425 } 426 427 bool isMatrix() const { return secondarySize > 1; } 428 void setSecondarySize(int s1) { secondarySize = s1; } 429 int getSecondarySize() const { return secondarySize; } 430 431 bool isArray() const { return array ? true : false; } 432 bool isUnsizedArray() const { return array && arraySize == 0; } 433 int getArraySize() const { return arraySize; } 434 void setArraySize(int s) { array = true; arraySize = s; } 435 int getMaxArraySize () const { return maxArraySize; } 436 void setMaxArraySize (int s) { maxArraySize = s; } 437 void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; } 438 void setArrayInformationType(TType* t) { arrayInformationType = t; } 439 TType* getArrayInformationType() const { return arrayInformationType; } 440 441 TInterfaceBlock *getInterfaceBlock() const { return interfaceBlock; } 442 void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn) { interfaceBlock = interfaceBlockIn; } 443 bool isInterfaceBlock() const { return type == EbtInterfaceBlock; } 444 TInterfaceBlock *getAsInterfaceBlock() const { return isInterfaceBlock() ? getInterfaceBlock() : nullptr; } 445 446 bool isVector() const { return primarySize > 1 && !isMatrix(); } 447 bool isScalar() const { return primarySize == 1 && !isMatrix() && !structure && !isInterfaceBlock(); } 448 bool isRegister() const { return !isMatrix() && !structure && !array && !isInterfaceBlock(); } // Fits in a 4-element register 449 bool isStruct() const { return structure != 0; } 450 bool isScalarInt() const { return isScalar() && IsInteger(type); } 451 452 TStructure* getStruct() const { return structure; } 453 void setStruct(TStructure* s) { structure = s; } 454 455 TString& getMangledName() { 456 if (!mangled) { 457 mangled = NewPoolTString(""); 458 buildMangledName(*mangled); 459 *mangled += ';' ; 460 } 461 462 return *mangled; 463 } 464 465 bool sameElementType(const TType& right) const { 466 return type == right.type && 467 primarySize == right.primarySize && 468 secondarySize == right.secondarySize && 469 structure == right.structure; 470 } 471 bool operator==(const TType& right) const { 472 return type == right.type && 473 primarySize == right.primarySize && 474 secondarySize == right.secondarySize && 475 array == right.array && (!array || arraySize == right.arraySize) && 476 structure == right.structure; 477 // don't check the qualifier, it's not ever what's being sought after 478 } 479 bool operator!=(const TType& right) const { 480 return !operator==(right); 481 } 482 bool operator<(const TType& right) const { 483 if (type != right.type) return type < right.type; 484 if(primarySize != right.primarySize) return (primarySize * secondarySize) < (right.primarySize * right.secondarySize); 485 if(secondarySize != right.secondarySize) return secondarySize < right.secondarySize; 486 if (array != right.array) return array < right.array; 487 if (arraySize != right.arraySize) return arraySize < right.arraySize; 488 if (structure != right.structure) return structure < right.structure; 489 490 return false; 491 } 492 493 const char* getBasicString() const { return ::getBasicString(type); } 494 const char* getPrecisionString() const { return ::getPrecisionString(precision); } 495 const char* getQualifierString() const { return ::getQualifierString(qualifier); } 496 TString getCompleteString() const; 497 498 // If this type is a struct, returns the deepest struct nesting of 499 // any field in the struct. For example: 500 // struct nesting1 { 501 // vec4 position; 502 // }; 503 // struct nesting2 { 504 // nesting1 field1; 505 // vec4 field2; 506 // }; 507 // For type "nesting2", this method would return 2 -- the number 508 // of structures through which indirection must occur to reach the 509 // deepest field (nesting2.field1.position). 510 int getDeepestStructNesting() const 511 { 512 return structure ? structure->deepestNesting() : 0; 513 } 514 515 bool isStructureContainingArrays() const 516 { 517 return structure ? structure->containsArrays() : false; 518 } 519 520 bool isStructureContainingType(TBasicType t) const 521 { 522 return structure ? structure->containsType(t) : false; 523 } 524 525 bool isStructureContainingSamplers() const 526 { 527 return structure ? structure->containsSamplers() : false; 528 } 529 530 protected: 531 void buildMangledName(TString&); 532 size_t getStructSize() const; 533 534 TBasicType type = EbtVoid; 535 TPrecision precision = EbpUndefined; 536 TQualifier qualifier = EvqTemporary; 537 unsigned char primarySize = 0; // size of vector or matrix, not size of array 538 unsigned char secondarySize = 0; // 1 for vectors, > 1 for matrices 539 bool array = false; 540 int arraySize = 0; 541 int maxArraySize = 0; 542 TType *arrayInformationType = nullptr; 543 544 // null unless this is an interface block, or interface block member variable 545 TInterfaceBlock *interfaceBlock = nullptr; 546 TLayoutQualifier layoutQualifier; 547 548 TStructure *structure = nullptr; // null unless this is a struct 549 550 TString *mangled = nullptr; 551 }; 552 553 // 554 // This is a workaround for a problem with the yacc stack, It can't have 555 // types that it thinks have non-trivial constructors. It should 556 // just be used while recognizing the grammar, not anything else. Pointers 557 // could be used, but also trying to avoid lots of memory management overhead. 558 // 559 // Not as bad as it looks, there is no actual assumption that the fields 560 // match up or are name the same or anything like that. 561 // 562 struct TPublicType 563 { 564 TBasicType type; 565 TLayoutQualifier layoutQualifier; 566 TQualifier qualifier; 567 bool invariant; 568 TPrecision precision; 569 int primarySize; // size of vector or matrix, not size of array 570 int secondarySize; // 1 for scalars/vectors, >1 for matrices 571 bool array; 572 int arraySize; 573 TType* userDef; 574 TSourceLoc line; 575 576 void setBasic(TBasicType bt, TQualifier q, const TSourceLoc &ln) 577 { 578 type = bt; 579 layoutQualifier = TLayoutQualifier::create(); 580 qualifier = q; 581 invariant = false; 582 precision = EbpUndefined; 583 primarySize = 1; 584 secondarySize = 1; 585 array = false; 586 arraySize = 0; 587 userDef = 0; 588 line = ln; 589 } 590 591 void setAggregate(int s) 592 { 593 primarySize = s; 594 secondarySize = 1; 595 } 596 597 void setMatrix(int s0, int s1) 598 { 599 primarySize = s0; 600 secondarySize = s1; 601 } 602 603 bool isUnsizedArray() const 604 { 605 return array && arraySize == 0; 606 } 607 608 void setArray(bool a, int s = 0) 609 { 610 array = a; 611 arraySize = s; 612 } 613 614 void clearArrayness() 615 { 616 array = false; 617 arraySize = 0; 618 } 619 620 bool isStructureContainingArrays() const 621 { 622 if (!userDef) 623 { 624 return false; 625 } 626 627 return userDef->isStructureContainingArrays(); 628 } 629 630 bool isStructureContainingType(TBasicType t) const 631 { 632 if(!userDef) 633 { 634 return false; 635 } 636 637 return userDef->isStructureContainingType(t); 638 } 639 640 bool isMatrix() const 641 { 642 return primarySize > 1 && secondarySize > 1; 643 } 644 645 bool isVector() const 646 { 647 return primarySize > 1 && secondarySize == 1; 648 } 649 650 int getCols() const 651 { 652 ASSERT(isMatrix()); 653 return primarySize; 654 } 655 656 int getRows() const 657 { 658 ASSERT(isMatrix()); 659 return secondarySize; 660 } 661 662 int getNominalSize() const 663 { 664 return primarySize; 665 } 666 667 bool isAggregate() const 668 { 669 return array || isMatrix() || isVector(); 670 } 671 }; 672 673 #endif // _TYPES_INCLUDED_ 674