• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
POOL_ALLOCATOR_NEW_DELETE()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.
type()40 	TType *type()
41 	{
42 		return mType;
43 	}
type()44 	const TType *type() const
45 	{
46 		return mType;
47 	}
48 
name()49 	const TString &name() const
50 	{
51 		return *mName;
52 	}
line()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;
NewPoolTFieldList()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:
~TFieldListCollection()74 	virtual ~TFieldListCollection() { }
name()75 	const TString &name() const
76 	{
77 		return *mName;
78 	}
fields()79 	const TFieldList &fields() const
80 	{
81 		return *mFields;
82 	}
83 
mangledName()84 	const TString &mangledName() const
85 	{
86 		if(mMangledName.empty())
87 			mMangledName = buildMangledName();
88 		return mMangledName;
89 	}
objectSize()90 	size_t objectSize() const
91 	{
92 		if(mObjectSize == 0)
93 			mObjectSize = calculateObjectSize();
94 		return mObjectSize;
95 	}
96 
97 protected:
TFieldListCollection(const TString * name,TFieldList * fields)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:
POOL_ALLOCATOR_NEW_DELETE()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 
deepestNesting()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 
setUniqueId(int uniqueId)142 	void setUniqueId(int uniqueId)
143 	{
144 		mUniqueId = uniqueId;
145 	}
146 
uniqueId()147 	int uniqueId() const
148 	{
149 		ASSERT(mUniqueId != 0);
150 		return mUniqueId;
151 	}
152 
setAtGlobalScope(bool atGlobalScope)153 	void setAtGlobalScope(bool atGlobalScope)
154 	{
155 		mAtGlobalScope = atGlobalScope;
156 	}
157 
atGlobalScope()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;
setName(const TString & name)168 	void setName(const TString &name)
169 	{
170 		TString *mutableName = const_cast<TString *>(mName);
171 		*mutableName = name;
172 	}
173 
mangledNamePrefix()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:
POOL_ALLOCATOR_NEW_DELETE()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 
instanceName()199 	const TString &instanceName() const
200 	{
201 		return *mInstanceName;
202 	}
hasInstanceName()203 	bool hasInstanceName() const
204 	{
205 		return mInstanceName != nullptr;
206 	}
isArray()207 	bool isArray() const
208 	{
209 		return mArraySize > 0;
210 	}
arraySize()211 	int arraySize() const
212 	{
213 		return mArraySize;
214 	}
blockStorage()215 	TLayoutBlockStorage blockStorage() const
216 	{
217 		return mBlockStorage;
218 	}
matrixPacking()219 	TLayoutMatrixPacking matrixPacking() const
220 	{
221 		return mMatrixPacking;
222 	}
223 
224 private:
mangledNamePrefix()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:
POOL_ALLOCATOR_NEW_DELETE()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) :
type(t)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) :
type(EbtStruct)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 
TType(TInterfaceBlock * interfaceBlockIn,TQualifier qualifierIn,TLayoutQualifier layoutQualifierIn,int arraySizeIn)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 
getBasicType()275 	TBasicType getBasicType() const { return type; }
setBasicType(TBasicType t)276 	void setBasicType(TBasicType t) { type = t; }
277 
getPrecision()278 	TPrecision getPrecision() const { return precision; }
setPrecision(TPrecision p)279 	void setPrecision(TPrecision p) { precision = p; }
280 
getQualifier()281 	TQualifier getQualifier() const { return qualifier; }
setQualifier(TQualifier q)282 	void setQualifier(TQualifier q) { qualifier = q; }
283 
getLayoutQualifier()284 	TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; }
setLayoutQualifier(TLayoutQualifier lq)285 	void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; }
286 
setMatrixPackingIfUnspecified(TLayoutMatrixPacking matrixPacking)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
getNominalSize()303 	int getNominalSize() const { return primarySize; }
setNominalSize(int s)304 	void setNominalSize(int s) { primarySize = s; }
305 	// Full size of single instance of type
getObjectSize()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 
getElementSize()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 
samplerRegisterCount()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 
elementRegisterCount()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 
blockRegisterCount()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 
totalSamplerRegisterCount()398 	int totalSamplerRegisterCount() const
399 	{
400 		if(array)
401 		{
402 			return arraySize * samplerRegisterCount();
403 		}
404 		else
405 		{
406 			return samplerRegisterCount();
407 		}
408 	}
409 
totalRegisterCount()410 	int totalRegisterCount() const
411 	{
412 		if(array)
413 		{
414 			return arraySize * elementRegisterCount();
415 		}
416 		else
417 		{
418 			return elementRegisterCount();
419 		}
420 	}
421 
registerSize()422 	int registerSize() const
423 	{
424 		return isMatrix() ? secondarySize : primarySize;
425 	}
426 
isMatrix()427 	bool isMatrix() const { return secondarySize > 1; }
setSecondarySize(int s1)428 	void setSecondarySize(int s1) { secondarySize = s1; }
getSecondarySize()429 	int getSecondarySize() const { return secondarySize; }
430 
isArray()431 	bool isArray() const  { return array ? true : false; }
isUnsizedArray()432 	bool isUnsizedArray() const { return array && arraySize == 0; }
getArraySize()433 	int getArraySize() const { return arraySize; }
setArraySize(int s)434 	void setArraySize(int s) { array = true; arraySize = s; }
getMaxArraySize()435 	int getMaxArraySize () const { return maxArraySize; }
setMaxArraySize(int s)436 	void setMaxArraySize (int s) { maxArraySize = s; }
clearArrayness()437 	void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; }
setArrayInformationType(TType * t)438 	void setArrayInformationType(TType* t) { arrayInformationType = t; }
getArrayInformationType()439 	TType* getArrayInformationType() const { return arrayInformationType; }
440 
getInterfaceBlock()441 	TInterfaceBlock *getInterfaceBlock() const { return interfaceBlock; }
setInterfaceBlock(TInterfaceBlock * interfaceBlockIn)442 	void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn) { interfaceBlock = interfaceBlockIn; }
isInterfaceBlock()443 	bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
getAsInterfaceBlock()444 	TInterfaceBlock *getAsInterfaceBlock() const { return isInterfaceBlock() ? getInterfaceBlock() : nullptr; }
445 
isVector()446 	bool isVector() const { return primarySize > 1 && !isMatrix(); }
isScalar()447 	bool isScalar() const { return primarySize == 1 && !isMatrix() && !structure && !isInterfaceBlock() && !IsSampler(getBasicType()); }
isRegister()448 	bool isRegister() const { return !isMatrix() && !structure && !array && !isInterfaceBlock(); }   // Fits in a 4-element register
isStruct()449 	bool isStruct() const { return structure != 0; }
isScalarInt()450 	bool isScalarInt() const { return isScalar() && IsInteger(type); }
451 
getStruct()452 	TStructure* getStruct() const { return structure; }
setStruct(TStructure * s)453 	void setStruct(TStructure* s) { structure = s; }
454 
getMangledName()455 	TString& getMangledName() {
456 		if (!mangled) {
457 			mangled = NewPoolTString("");
458 			buildMangledName(*mangled);
459 			*mangled += ';' ;
460 		}
461 
462 		return *mangled;
463 	}
464 
sameElementType(const TType & right)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 
getBasicString()493 	const char* getBasicString() const { return ::getBasicString(type); }
getPrecisionString()494 	const char* getPrecisionString() const { return ::getPrecisionString(precision); }
getQualifierString()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).
getDeepestStructNesting()510 	int getDeepestStructNesting() const
511 	{
512 		return structure ? structure->deepestNesting() : 0;
513 	}
514 
isStructureContainingArrays()515 	bool isStructureContainingArrays() const
516 	{
517 		return structure ? structure->containsArrays() : false;
518 	}
519 
isStructureContainingType(TBasicType t)520 	bool isStructureContainingType(TBasicType t) const
521 	{
522 		return structure ? structure->containsType(t) : false;
523 	}
524 
isStructureContainingSamplers()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 
setBasicTPublicType576 	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 
setAggregateTPublicType591 	void setAggregate(int s)
592 	{
593 		primarySize = s;
594 		secondarySize = 1;
595 	}
596 
setMatrixTPublicType597 	void setMatrix(int s0, int s1)
598 	{
599 		primarySize = s0;
600 		secondarySize = s1;
601 	}
602 
isUnsizedArrayTPublicType603 	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 
clearArraynessTPublicType614 	void clearArrayness()
615 	{
616 		array = false;
617 		arraySize = 0;
618 	}
619 
isStructureContainingArraysTPublicType620 	bool isStructureContainingArrays() const
621 	{
622 		if (!userDef)
623 		{
624 			return false;
625 		}
626 
627 		return userDef->isStructureContainingArrays();
628 	}
629 
isStructureContainingTypeTPublicType630 	bool isStructureContainingType(TBasicType t) const
631 	{
632 		if(!userDef)
633 		{
634 			return false;
635 		}
636 
637 		return userDef->isStructureContainingType(t);
638 	}
639 
isMatrixTPublicType640 	bool isMatrix() const
641 	{
642 		return primarySize > 1 && secondarySize > 1;
643 	}
644 
isVectorTPublicType645 	bool isVector() const
646 	{
647 		return primarySize > 1 && secondarySize == 1;
648 	}
649 
getColsTPublicType650 	int getCols() const
651 	{
652 		ASSERT(isMatrix());
653 		return primarySize;
654 	}
655 
getRowsTPublicType656 	int getRows() const
657 	{
658 		ASSERT(isMatrix());
659 		return secondarySize;
660 	}
661 
getNominalSizeTPublicType662 	int getNominalSize() const
663 	{
664 		return primarySize;
665 	}
666 
isAggregateTPublicType667 	bool isAggregate() const
668 	{
669 		return array || isMatrix() || isVector();
670 	}
671 };
672 
673 #endif // _TYPES_INCLUDED_
674