Home | History | Annotate | Download | only in compiler
      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