1 //
2 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #ifndef _TYPES_INCLUDED
8 #define _TYPES_INCLUDED
9
10 #include "common/angleutils.h"
11
12 #include "compiler/translator/BaseTypes.h"
13 #include "compiler/translator/Common.h"
14 #include "compiler/translator/compilerdebug.h"
15
16 struct TPublicType;
17 class TType;
18 class TSymbol;
19
20 class TField
21 {
22 public:
23 POOL_ALLOCATOR_NEW_DELETE();
TField(TType * type,TString * name,const TSourceLoc & line)24 TField(TType *type, TString *name, const TSourceLoc &line)
25 : mType(type),
26 mName(name),
27 mLine(line)
28 {
29 }
30
31 // TODO(alokp): We should only return const type.
32 // Fix it by tweaking grammar.
type()33 TType *type()
34 {
35 return mType;
36 }
type()37 const TType *type() const
38 {
39 return mType;
40 }
41
name()42 const TString &name() const
43 {
44 return *mName;
45 }
line()46 const TSourceLoc &line() const
47 {
48 return mLine;
49 }
50
51 bool equals(const TField &other) const;
52
53 private:
54 DISALLOW_COPY_AND_ASSIGN(TField);
55 TType *mType;
56 TString *mName;
57 TSourceLoc mLine;
58 };
59
60 typedef TVector<TField *> TFieldList;
NewPoolTFieldList()61 inline TFieldList *NewPoolTFieldList()
62 {
63 void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
64 return new(memory) TFieldList;
65 }
66
67 class TFieldListCollection
68 {
69 public:
name()70 const TString &name() const
71 {
72 return *mName;
73 }
fields()74 const TFieldList &fields() const
75 {
76 return *mFields;
77 }
78
mangledName()79 const TString &mangledName() const
80 {
81 if (mMangledName.empty())
82 mMangledName = buildMangledName();
83 return mMangledName;
84 }
objectSize()85 size_t objectSize() const
86 {
87 if (mObjectSize == 0)
88 mObjectSize = calculateObjectSize();
89 return mObjectSize;
90 };
91
92 protected:
TFieldListCollection(const TString * name,TFieldList * fields)93 TFieldListCollection(const TString *name, TFieldList *fields)
94 : mName(name),
95 mFields(fields),
96 mObjectSize(0)
97 {
98 }
99 TString buildMangledName() const;
100 size_t calculateObjectSize() const;
101 virtual TString mangledNamePrefix() const = 0;
102
103 bool equals(const TFieldListCollection &other) const;
104
105 const TString *mName;
106 TFieldList *mFields;
107
108 mutable TString mMangledName;
109 mutable size_t mObjectSize;
110 };
111
112 // May also represent interface blocks
113 class TStructure : public TFieldListCollection
114 {
115 public:
116 POOL_ALLOCATOR_NEW_DELETE();
TStructure(const TString * name,TFieldList * fields)117 TStructure(const TString *name, TFieldList *fields)
118 : TFieldListCollection(name, fields),
119 mDeepestNesting(0),
120 mUniqueId(0)
121 {
122 }
123
deepestNesting()124 int deepestNesting() const
125 {
126 if (mDeepestNesting == 0)
127 mDeepestNesting = calculateDeepestNesting();
128 return mDeepestNesting;
129 }
130 bool containsArrays() const;
131
132 bool equals(const TStructure &other) const;
133
setUniqueId(int uniqueId)134 void setUniqueId(int uniqueId)
135 {
136 mUniqueId = uniqueId;
137 }
138
uniqueId()139 int uniqueId() const
140 {
141 ASSERT(mUniqueId != 0);
142 return mUniqueId;
143 }
144
145 private:
146 DISALLOW_COPY_AND_ASSIGN(TStructure);
mangledNamePrefix()147 virtual TString mangledNamePrefix() const
148 {
149 return "struct-";
150 }
151 int calculateDeepestNesting() const;
152
153 mutable int mDeepestNesting;
154 int mUniqueId;
155 };
156
157 class TInterfaceBlock : public TFieldListCollection
158 {
159 public:
160 POOL_ALLOCATOR_NEW_DELETE();
TInterfaceBlock(const TString * name,TFieldList * fields,const TString * instanceName,int arraySize,const TLayoutQualifier & layoutQualifier)161 TInterfaceBlock(const TString *name, TFieldList *fields, const TString *instanceName,
162 int arraySize, const TLayoutQualifier &layoutQualifier)
163 : TFieldListCollection(name, fields),
164 mInstanceName(instanceName),
165 mArraySize(arraySize),
166 mBlockStorage(layoutQualifier.blockStorage),
167 mMatrixPacking(layoutQualifier.matrixPacking)
168 {
169 }
170
instanceName()171 const TString &instanceName() const
172 {
173 return *mInstanceName;
174 }
hasInstanceName()175 bool hasInstanceName() const
176 {
177 return mInstanceName != NULL;
178 }
isArray()179 bool isArray() const
180 {
181 return mArraySize > 0;
182 }
arraySize()183 int arraySize() const
184 {
185 return mArraySize;
186 }
blockStorage()187 TLayoutBlockStorage blockStorage() const
188 {
189 return mBlockStorage;
190 }
matrixPacking()191 TLayoutMatrixPacking matrixPacking() const
192 {
193 return mMatrixPacking;
194 }
195
196 bool equals(const TInterfaceBlock &other) const;
197
198 private:
199 DISALLOW_COPY_AND_ASSIGN(TInterfaceBlock);
mangledNamePrefix()200 virtual TString mangledNamePrefix() const
201 {
202 return "iblock-";
203 }
204
205 const TString *mInstanceName; // for interface block instance names
206 int mArraySize; // 0 if not an array
207 TLayoutBlockStorage mBlockStorage;
208 TLayoutMatrixPacking mMatrixPacking;
209 };
210
211 //
212 // Base class for things that have a type.
213 //
214 class TType
215 {
216 public:
217 POOL_ALLOCATOR_NEW_DELETE();
TType()218 TType()
219 {
220 }
221 TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1)
type(t)222 : type(t), precision(EbpUndefined), qualifier(EvqGlobal),
223 layoutQualifier(TLayoutQualifier::create()),
224 primarySize(ps), secondarySize(ss), array(false), arraySize(0),
225 interfaceBlock(0), structure(0)
226 {
227 }
228 TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary,
229 unsigned char ps = 1, unsigned char ss = 1, bool a = false)
type(t)230 : type(t), precision(p), qualifier(q),
231 layoutQualifier(TLayoutQualifier::create()),
232 primarySize(ps), secondarySize(ss), array(a), arraySize(0),
233 interfaceBlock(0), structure(0)
234 {
235 }
236 explicit TType(const TPublicType &p);
237 TType(TStructure *userDef, TPrecision p = EbpUndefined)
type(EbtStruct)238 : type(EbtStruct), precision(p), qualifier(EvqTemporary),
239 layoutQualifier(TLayoutQualifier::create()),
240 primarySize(1), secondarySize(1), array(false), arraySize(0),
241 interfaceBlock(0), structure(userDef)
242 {
243 }
TType(TInterfaceBlock * interfaceBlockIn,TQualifier qualifierIn,TLayoutQualifier layoutQualifierIn,int arraySizeIn)244 TType(TInterfaceBlock *interfaceBlockIn, TQualifier qualifierIn,
245 TLayoutQualifier layoutQualifierIn, int arraySizeIn)
246 : type(EbtInterfaceBlock), precision(EbpUndefined), qualifier(qualifierIn),
247 layoutQualifier(layoutQualifierIn),
248 primarySize(1), secondarySize(1), array(arraySizeIn > 0), arraySize(arraySizeIn),
249 interfaceBlock(interfaceBlockIn), structure(0)
250 {
251 }
252
getBasicType()253 TBasicType getBasicType() const
254 {
255 return type;
256 }
setBasicType(TBasicType t)257 void setBasicType(TBasicType t)
258 {
259 type = t;
260 }
261
getPrecision()262 TPrecision getPrecision() const
263 {
264 return precision;
265 }
setPrecision(TPrecision p)266 void setPrecision(TPrecision p)
267 {
268 precision = p;
269 }
270
getQualifier()271 TQualifier getQualifier() const
272 {
273 return qualifier;
274 }
setQualifier(TQualifier q)275 void setQualifier(TQualifier q)
276 {
277 qualifier = q;
278 }
279
getLayoutQualifier()280 TLayoutQualifier getLayoutQualifier() const
281 {
282 return layoutQualifier;
283 }
setLayoutQualifier(TLayoutQualifier lq)284 void setLayoutQualifier(TLayoutQualifier lq)
285 {
286 layoutQualifier = lq;
287 }
288
getNominalSize()289 int getNominalSize() const
290 {
291 return primarySize;
292 }
getSecondarySize()293 int getSecondarySize() const
294 {
295 return secondarySize;
296 }
getCols()297 int getCols() const
298 {
299 ASSERT(isMatrix());
300 return primarySize;
301 }
getRows()302 int getRows() const
303 {
304 ASSERT(isMatrix());
305 return secondarySize;
306 }
setPrimarySize(unsigned char ps)307 void setPrimarySize(unsigned char ps)
308 {
309 primarySize = ps;
310 }
setSecondarySize(unsigned char ss)311 void setSecondarySize(unsigned char ss)
312 {
313 secondarySize = ss;
314 }
315
316 // Full size of single instance of type
317 size_t getObjectSize() const;
318
isMatrix()319 bool isMatrix() const
320 {
321 return primarySize > 1 && secondarySize > 1;
322 }
isArray()323 bool isArray() const
324 {
325 return array ? true : false;
326 }
getArraySize()327 int getArraySize() const
328 {
329 return arraySize;
330 }
setArraySize(int s)331 void setArraySize(int s)
332 {
333 array = true;
334 arraySize = s;
335 }
clearArrayness()336 void clearArrayness()
337 {
338 array = false;
339 arraySize = 0;
340 }
341
getInterfaceBlock()342 TInterfaceBlock *getInterfaceBlock() const
343 {
344 return interfaceBlock;
345 }
setInterfaceBlock(TInterfaceBlock * interfaceBlockIn)346 void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn)
347 {
348 interfaceBlock = interfaceBlockIn;
349 }
isInterfaceBlock()350 bool isInterfaceBlock() const
351 {
352 return type == EbtInterfaceBlock;
353 }
354
isVector()355 bool isVector() const
356 {
357 return primarySize > 1 && secondarySize == 1;
358 }
isScalar()359 bool isScalar() const
360 {
361 return primarySize == 1 && secondarySize == 1 && !structure;
362 }
isScalarInt()363 bool isScalarInt() const
364 {
365 return isScalar() && (type == EbtInt || type == EbtUInt);
366 }
367
getStruct()368 TStructure *getStruct() const
369 {
370 return structure;
371 }
setStruct(TStructure * s)372 void setStruct(TStructure *s)
373 {
374 structure = s;
375 }
376
getMangledName()377 const TString &getMangledName()
378 {
379 if (mangled.empty())
380 {
381 mangled = buildMangledName();
382 mangled += ';';
383 }
384
385 return mangled;
386 }
387
388 // This is different from operator== as we also compare
389 // precision here.
390 bool equals(const TType &other) const;
391
sameElementType(const TType & right)392 bool sameElementType(const TType &right) const
393 {
394 return type == right.type &&
395 primarySize == right.primarySize &&
396 secondarySize == right.secondarySize &&
397 structure == right.structure;
398 }
399 bool operator==(const TType &right) const
400 {
401 return type == right.type &&
402 primarySize == right.primarySize &&
403 secondarySize == right.secondarySize &&
404 array == right.array && (!array || arraySize == right.arraySize) &&
405 structure == right.structure;
406 // don't check the qualifier, it's not ever what's being sought after
407 }
408 bool operator!=(const TType &right) const
409 {
410 return !operator==(right);
411 }
412 bool operator<(const TType &right) const
413 {
414 if (type != right.type)
415 return type < right.type;
416 if (primarySize != right.primarySize)
417 return primarySize < right.primarySize;
418 if (secondarySize != right.secondarySize)
419 return secondarySize < right.secondarySize;
420 if (array != right.array)
421 return array < right.array;
422 if (arraySize != right.arraySize)
423 return arraySize < right.arraySize;
424 if (structure != right.structure)
425 return structure < right.structure;
426
427 return false;
428 }
429
getBasicString()430 const char *getBasicString() const
431 {
432 return ::getBasicString(type);
433 }
getPrecisionString()434 const char *getPrecisionString() const
435 {
436 return ::getPrecisionString(precision);
437 }
getQualifierString()438 const char *getQualifierString() const
439 {
440 return ::getQualifierString(qualifier);
441 }
442 TString getCompleteString() const;
443
444 // If this type is a struct, returns the deepest struct nesting of
445 // any field in the struct. For example:
446 // struct nesting1 {
447 // vec4 position;
448 // };
449 // struct nesting2 {
450 // nesting1 field1;
451 // vec4 field2;
452 // };
453 // For type "nesting2", this method would return 2 -- the number
454 // of structures through which indirection must occur to reach the
455 // deepest field (nesting2.field1.position).
getDeepestStructNesting()456 int getDeepestStructNesting() const
457 {
458 return structure ? structure->deepestNesting() : 0;
459 }
460
isStructureContainingArrays()461 bool isStructureContainingArrays() const
462 {
463 return structure ? structure->containsArrays() : false;
464 }
465
466 protected:
467 TString buildMangledName() const;
468 size_t getStructSize() const;
469 void computeDeepestStructNesting();
470
471 TBasicType type;
472 TPrecision precision;
473 TQualifier qualifier;
474 TLayoutQualifier layoutQualifier;
475 unsigned char primarySize; // size of vector or cols matrix
476 unsigned char secondarySize; // rows of a matrix
477 bool array;
478 int arraySize;
479
480 // 0 unless this is an interface block, or interface block member variable
481 TInterfaceBlock *interfaceBlock;
482
483 // 0 unless this is a struct
484 TStructure *structure;
485
486 mutable TString mangled;
487 };
488
489 //
490 // This is a workaround for a problem with the yacc stack, It can't have
491 // types that it thinks have non-trivial constructors. It should
492 // just be used while recognizing the grammar, not anything else. Pointers
493 // could be used, but also trying to avoid lots of memory management overhead.
494 //
495 // Not as bad as it looks, there is no actual assumption that the fields
496 // match up or are name the same or anything like that.
497 //
498 struct TPublicType
499 {
500 TBasicType type;
501 TLayoutQualifier layoutQualifier;
502 TQualifier qualifier;
503 TPrecision precision;
504 unsigned char primarySize; // size of vector or cols of matrix
505 unsigned char secondarySize; // rows of matrix
506 bool array;
507 int arraySize;
508 TType *userDef;
509 TSourceLoc line;
510
setBasicTPublicType511 void setBasic(TBasicType bt, TQualifier q, const TSourceLoc &ln)
512 {
513 type = bt;
514 layoutQualifier = TLayoutQualifier::create();
515 qualifier = q;
516 precision = EbpUndefined;
517 primarySize = 1;
518 secondarySize = 1;
519 array = false;
520 arraySize = 0;
521 userDef = 0;
522 line = ln;
523 }
524
setAggregateTPublicType525 void setAggregate(unsigned char size)
526 {
527 primarySize = size;
528 }
529
setMatrixTPublicType530 void setMatrix(unsigned char c, unsigned char r)
531 {
532 ASSERT(c > 1 && r > 1 && c <= 4 && r <= 4);
533 primarySize = c;
534 secondarySize = r;
535 }
536
537 void setArray(bool a, int s = 0)
538 {
539 array = a;
540 arraySize = s;
541 }
542
isStructureContainingArraysTPublicType543 bool isStructureContainingArrays() const
544 {
545 if (!userDef)
546 {
547 return false;
548 }
549
550 return userDef->isStructureContainingArrays();
551 }
552
isMatrixTPublicType553 bool isMatrix() const
554 {
555 return primarySize > 1 && secondarySize > 1;
556 }
557
isVectorTPublicType558 bool isVector() const
559 {
560 return primarySize > 1 && secondarySize == 1;
561 }
562
getColsTPublicType563 int getCols() const
564 {
565 ASSERT(isMatrix());
566 return primarySize;
567 }
568
getRowsTPublicType569 int getRows() const
570 {
571 ASSERT(isMatrix());
572 return secondarySize;
573 }
574
getNominalSizeTPublicType575 int getNominalSize() const
576 {
577 return primarySize;
578 }
579
isAggregateTPublicType580 bool isAggregate() const
581 {
582 return array || isMatrix() || isVector();
583 }
584 };
585
586 #endif // _TYPES_INCLUDED_
587