• 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:
30 	POOL_ALLOCATOR_NEW_DELETE();
TField(TType * type,TString * name,const TSourceLoc & line)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:
119 	POOL_ALLOCATOR_NEW_DELETE();
TStructure(const TString * name,TFieldList * fields)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 
setUniqueId(int uniqueId)140 	void setUniqueId(int uniqueId)
141 	{
142 		mUniqueId = uniqueId;
143 	}
144 
uniqueId()145 	int uniqueId() const
146 	{
147 		ASSERT(mUniqueId != 0);
148 		return mUniqueId;
149 	}
150 
setAtGlobalScope(bool atGlobalScope)151 	void setAtGlobalScope(bool atGlobalScope)
152 	{
153 		mAtGlobalScope = atGlobalScope;
154 	}
155 
atGlobalScope()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;
setName(const TString & name)166 	void setName(const TString &name)
167 	{
168 		TString *mutableName = const_cast<TString *>(mName);
169 		*mutableName = name;
170 	}
171 
mangledNamePrefix()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();
TInterfaceBlock(const TString * name,TFieldList * fields,const TString * instanceName,int arraySize,const TLayoutQualifier & layoutQualifier)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 
instanceName()197 	const TString &instanceName() const
198 	{
199 		return *mInstanceName;
200 	}
hasInstanceName()201 	bool hasInstanceName() const
202 	{
203 		return mInstanceName != nullptr;
204 	}
isArray()205 	bool isArray() const
206 	{
207 		return mArraySize > 0;
208 	}
arraySize()209 	int arraySize() const
210 	{
211 		return mArraySize;
212 	}
blockStorage()213 	TLayoutBlockStorage blockStorage() const
214 	{
215 		return mBlockStorage;
216 	}
matrixPacking()217 	TLayoutMatrixPacking matrixPacking() const
218 	{
219 		return mMatrixPacking;
220 	}
221 
222 private:
mangledNamePrefix()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();
TType()241 	TType() {}
242 	TType(TBasicType t, int s0 = 1, int s1 = 1) :
type(t)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) :
type(t)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) :
type(EbtStruct)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 
TType(TInterfaceBlock * interfaceBlockIn,TQualifier qualifierIn,TLayoutQualifier layoutQualifierIn,int arraySizeIn)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 
getBasicType()271 	TBasicType getBasicType() const { return type; }
setBasicType(TBasicType t)272 	void setBasicType(TBasicType t) { type = t; }
273 
getPrecision()274 	TPrecision getPrecision() const { return precision; }
setPrecision(TPrecision p)275 	void setPrecision(TPrecision p) { precision = p; }
276 
getQualifier()277 	TQualifier getQualifier() const { return qualifier; }
setQualifier(TQualifier q)278 	void setQualifier(TQualifier q) { qualifier = q; }
279 
isInvariant()280 	bool isInvariant() const { return invariant; }
281 
getLayoutQualifier()282 	TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; }
setLayoutQualifier(TLayoutQualifier lq)283 	void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; }
284 
285 	// One-dimensional size of single instance type
getNominalSize()286 	int getNominalSize() const { return primarySize; }
setNominalSize(int s)287 	void setNominalSize(int s) { primarySize = s; }
288 	// Full size of single instance of type
getObjectSize()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 
getElementSize()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 
elementRegisterCount()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 
blockRegisterCount()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 
totalRegisterCount()363 	int totalRegisterCount() const
364 	{
365 		if(array)
366 		{
367 			return arraySize * elementRegisterCount();
368 		}
369 		else
370 		{
371 			return elementRegisterCount();
372 		}
373 	}
374 
registerSize()375 	int registerSize() const
376 	{
377 		return isMatrix() ? secondarySize : primarySize;
378 	}
379 
isMatrix()380 	bool isMatrix() const { return secondarySize > 1; }
setSecondarySize(int s1)381 	void setSecondarySize(int s1) { secondarySize = s1; }
getSecondarySize()382 	int getSecondarySize() const { return secondarySize; }
383 
isArray()384 	bool isArray() const  { return array ? true : false; }
isUnsizedArray()385 	bool isUnsizedArray() const { return array && arraySize == 0; }
getArraySize()386 	int getArraySize() const { return arraySize; }
setArraySize(int s)387 	void setArraySize(int s) { array = true; arraySize = s; }
getMaxArraySize()388 	int getMaxArraySize () const { return maxArraySize; }
setMaxArraySize(int s)389 	void setMaxArraySize (int s) { maxArraySize = s; }
clearArrayness()390 	void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; }
setArrayInformationType(TType * t)391 	void setArrayInformationType(TType* t) { arrayInformationType = t; }
getArrayInformationType()392 	TType* getArrayInformationType() const { return arrayInformationType; }
393 
getInterfaceBlock()394 	TInterfaceBlock *getInterfaceBlock() const { return interfaceBlock; }
setInterfaceBlock(TInterfaceBlock * interfaceBlockIn)395 	void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn) { interfaceBlock = interfaceBlockIn; }
isInterfaceBlock()396 	bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
getAsInterfaceBlock()397 	TInterfaceBlock *getAsInterfaceBlock() const { return isInterfaceBlock() ? getInterfaceBlock() : nullptr; }
398 
isVector()399 	bool isVector() const { return primarySize > 1 && !isMatrix(); }
isScalar()400 	bool isScalar() const { return primarySize == 1 && !isMatrix() && !structure && !isInterfaceBlock(); }
isRegister()401 	bool isRegister() const { return !isMatrix() && !structure && !array && !isInterfaceBlock(); }   // Fits in a 4-element register
isStruct()402 	bool isStruct() const { return structure != 0; }
isScalarInt()403 	bool isScalarInt() const { return isScalar() && IsInteger(type); }
404 
getStruct()405 	TStructure* getStruct() const { return structure; }
setStruct(TStructure * s)406 	void setStruct(TStructure* s) { structure = s; computeDeepestStructNesting(); }
407 
getMangledName()408 	TString& getMangledName() {
409 		if (!mangled) {
410 			mangled = NewPoolTString("");
411 			buildMangledName(*mangled);
412 			*mangled += ';' ;
413 		}
414 
415 		return *mangled;
416 	}
417 
sameElementType(const TType & right)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 
getBasicString()446 	const char* getBasicString() const { return ::getBasicString(type); }
getPrecisionString()447 	const char* getPrecisionString() const { return ::getPrecisionString(precision); }
getQualifierString()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).
getDeepestStructNesting()463 	int getDeepestStructNesting() const
464 	{
465 		return structure ? structure->deepestNesting() : 0;
466 	}
467 
isStructureContainingArrays()468 	bool isStructureContainingArrays() const
469 	{
470 		return structure ? structure->containsArrays() : false;
471 	}
472 
isStructureContainingType(TBasicType t)473 	bool isStructureContainingType(TBasicType t) const
474 	{
475 		return structure ? structure->containsType(t) : false;
476 	}
477 
isStructureContainingSamplers()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 
setBasicTPublicType532 	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 
setAggregateTPublicType547 	void setAggregate(int s)
548 	{
549 		primarySize = s;
550 		secondarySize = 1;
551 	}
552 
setMatrixTPublicType553 	void setMatrix(int s0, int s1)
554 	{
555 		primarySize = s0;
556 		secondarySize = s1;
557 	}
558 
isUnsizedArrayTPublicType559 	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 
clearArraynessTPublicType570 	void clearArrayness()
571 	{
572 		array = false;
573 		arraySize = 0;
574 	}
575 
isStructureContainingArraysTPublicType576 	bool isStructureContainingArrays() const
577 	{
578 		if (!userDef)
579 		{
580 			return false;
581 		}
582 
583 		return userDef->isStructureContainingArrays();
584 	}
585 
isStructureContainingTypeTPublicType586 	bool isStructureContainingType(TBasicType t) const
587 	{
588 		if(!userDef)
589 		{
590 			return false;
591 		}
592 
593 		return userDef->isStructureContainingType(t);
594 	}
595 
isMatrixTPublicType596 	bool isMatrix() const
597 	{
598 		return primarySize > 1 && secondarySize > 1;
599 	}
600 
isVectorTPublicType601 	bool isVector() const
602 	{
603 		return primarySize > 1 && secondarySize == 1;
604 	}
605 
getColsTPublicType606 	int getCols() const
607 	{
608 		ASSERT(isMatrix());
609 		return primarySize;
610 	}
611 
getRowsTPublicType612 	int getRows() const
613 	{
614 		ASSERT(isMatrix());
615 		return secondarySize;
616 	}
617 
getNominalSizeTPublicType618 	int getNominalSize() const
619 	{
620 		return primarySize;
621 	}
622 
isAggregateTPublicType623 	bool isAggregate() const
624 	{
625 		return array || isMatrix() || isVector();
626 	}
627 };
628 
629 #endif // _TYPES_INCLUDED_
630