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