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