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