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