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