1//
2// Copyright (c) 2002-2010 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 "compiler/BaseTypes.h"
11#include "compiler/Common.h"
12#include "compiler/debug.h"
13
14//
15// Need to have association of line numbers to types in a list for building structs.
16//
17class TType;
18struct TTypeLine {
19    TType* type;
20    int line;
21};
22typedef TVector<TTypeLine> TTypeList;
23
24inline TTypeList* NewPoolTTypeList()
25{
26    void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList));
27    return new(memory) TTypeList;
28}
29
30//
31// This is a workaround for a problem with the yacc stack,  It can't have
32// types that it thinks have non-trivial constructors.  It should
33// just be used while recognizing the grammar, not anything else.  Pointers
34// could be used, but also trying to avoid lots of memory management overhead.
35//
36// Not as bad as it looks, there is no actual assumption that the fields
37// match up or are name the same or anything like that.
38//
39class TPublicType {
40public:
41    TBasicType type;
42    TQualifier qualifier;
43    TPrecision precision;
44    int size;          // size of vector or matrix, not size of array
45    bool matrix;
46    bool array;
47    int arraySize;
48    TType* userDef;
49    int line;
50
51    void setBasic(TBasicType bt, TQualifier q, int ln = 0)
52    {
53        type = bt;
54        qualifier = q;
55        precision = EbpUndefined;
56        size = 1;
57        matrix = false;
58        array = false;
59        arraySize = 0;
60        userDef = 0;
61        line = ln;
62    }
63
64    void setAggregate(int s, bool m = false)
65    {
66        size = s;
67        matrix = m;
68    }
69
70    void setArray(bool a, int s = 0)
71    {
72        array = a;
73        arraySize = s;
74    }
75};
76
77typedef TMap<TTypeList*, TTypeList*> TStructureMap;
78typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
79//
80// Base class for things that have a type.
81//
82class TType {
83public:
84    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
85    TType() {}
86    TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
87            type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
88            maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), fieldName(0), mangled(0), typeName(0)
89    {
90    }
91    explicit TType(const TPublicType &p) :
92            type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
93            maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), fieldName(0), mangled(0), typeName(0)
94    {
95        if (p.userDef) {
96            structure = p.userDef->getStruct();
97            typeName = NewPoolTString(p.userDef->getTypeName().c_str());
98        }
99    }
100    TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
101            type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
102            maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), fieldName(0), mangled(0)
103    {
104        typeName = NewPoolTString(n.c_str());
105    }
106
107    void copyType(const TType& copyOf, TStructureMap& remapper)
108    {
109        type = copyOf.type;
110        precision = copyOf.precision;
111        qualifier = copyOf.qualifier;
112        size = copyOf.size;
113        matrix = copyOf.matrix;
114        array = copyOf.array;
115        arraySize = copyOf.arraySize;
116
117        TStructureMapIterator iter;
118        if (copyOf.structure) {
119            if ((iter = remapper.find(structure)) == remapper.end()) {
120                // create the new structure here
121                structure = NewPoolTTypeList();
122                for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
123                    TTypeLine typeLine;
124                    typeLine.line = (*copyOf.structure)[i].line;
125                    typeLine.type = (*copyOf.structure)[i].type->clone(remapper);
126                    structure->push_back(typeLine);
127                }
128            } else {
129                structure = iter->second;
130            }
131        } else
132            structure = 0;
133
134        fieldName = 0;
135        if (copyOf.fieldName)
136            fieldName = NewPoolTString(copyOf.fieldName->c_str());
137        typeName = 0;
138        if (copyOf.typeName)
139            typeName = NewPoolTString(copyOf.typeName->c_str());
140
141        mangled = 0;
142        if (copyOf.mangled)
143            mangled = NewPoolTString(copyOf.mangled->c_str());
144
145        structureSize = copyOf.structureSize;
146        maxArraySize = copyOf.maxArraySize;
147        assert(copyOf.arrayInformationType == 0);
148        arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level
149    }
150
151    TType* clone(TStructureMap& remapper)
152    {
153        TType *newType = new TType();
154        newType->copyType(*this, remapper);
155
156        return newType;
157    }
158
159    TBasicType getBasicType() const { return type; }
160    void setBasicType(TBasicType t) { type = t; }
161
162    TPrecision getPrecision() const { return precision; }
163    void setPrecision(TPrecision p) { precision = p; }
164
165    TQualifier getQualifier() const { return qualifier; }
166    void setQualifier(TQualifier q) { qualifier = q; }
167
168    // One-dimensional size of single instance type
169    int getNominalSize() const { return size; }
170    void setNominalSize(int s) { size = s; }
171    // Full size of single instance of type
172    int getObjectSize() const
173    {
174        int totalSize;
175
176        if (getBasicType() == EbtStruct)
177            totalSize = getStructSize();
178        else if (matrix)
179            totalSize = size * size;
180        else
181            totalSize = size;
182
183        if (isArray())
184            totalSize *= std::max(getArraySize(), getMaxArraySize());
185
186        return totalSize;
187    }
188
189    bool isMatrix() const { return matrix ? true : false; }
190    void setMatrix(bool m) { matrix = m; }
191
192    bool isArray() const  { return array ? true : false; }
193    int getArraySize() const { return arraySize; }
194    void setArraySize(int s) { array = true; arraySize = s; }
195    int getMaxArraySize () const { return maxArraySize; }
196    void setMaxArraySize (int s) { maxArraySize = s; }
197    void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; }
198    void setArrayInformationType(TType* t) { arrayInformationType = t; }
199    TType* getArrayInformationType() const { return arrayInformationType; }
200
201    bool isVector() const { return size > 1 && !matrix; }
202    bool isScalar() const { return size == 1 && !matrix && !structure; }
203
204    TTypeList* getStruct() const { return structure; }
205    void setStruct(TTypeList* s) { structure = s; }
206
207    const TString& getTypeName() const
208    {
209        assert(typeName);
210        return *typeName;
211    }
212    void setTypeName(const TString& n)
213    {
214        typeName = NewPoolTString(n.c_str());
215    }
216
217    bool isField() const { return fieldName != 0; }
218    const TString& getFieldName() const
219    {
220        assert(fieldName);
221        return *fieldName;
222    }
223    void setFieldName(const TString& n)
224    {
225        fieldName = NewPoolTString(n.c_str());
226    }
227
228    TString& getMangledName() {
229        if (!mangled) {
230            mangled = NewPoolTString("");
231            buildMangledName(*mangled);
232            *mangled += ';' ;
233        }
234
235        return *mangled;
236    }
237
238    bool sameElementType(const TType& right) const {
239        return      type == right.type   &&
240                    size == right.size   &&
241                  matrix == right.matrix &&
242               structure == right.structure;
243    }
244    bool operator==(const TType& right) const {
245        return      type == right.type   &&
246                    size == right.size   &&
247                  matrix == right.matrix &&
248                   array == right.array  && (!array || arraySize == right.arraySize) &&
249               structure == right.structure;
250        // don't check the qualifier, it's not ever what's being sought after
251    }
252    bool operator!=(const TType& right) const {
253        return !operator==(right);
254    }
255    bool operator<(const TType& right) const {
256        if (type != right.type) return type < right.type;
257        if (size != right.size) return size < right.size;
258        if (matrix != right.matrix) return matrix < right.matrix;
259        if (array != right.array) return array < right.array;
260        if (arraySize != right.arraySize) return arraySize < right.arraySize;
261        if (structure != right.structure) return structure < right.structure;
262
263        return false;
264    }
265
266    const char* getBasicString() const { return ::getBasicString(type); }
267    const char* getPrecisionString() const { return ::getPrecisionString(precision); }
268    const char* getQualifierString() const { return ::getQualifierString(qualifier); }
269    TString getCompleteString() const;
270
271protected:
272    void buildMangledName(TString&);
273    int getStructSize() const;
274
275    TBasicType type      : 6;
276    TPrecision precision;
277    TQualifier qualifier : 7;
278    int size             : 8; // size of vector or matrix, not size of array
279    unsigned int matrix  : 1;
280    unsigned int array   : 1;
281    int arraySize;
282    int maxArraySize;
283    TType* arrayInformationType;
284
285    TTypeList* structure;      // 0 unless this is a struct
286    mutable int structureSize;
287
288    TString *fieldName;         // for structure field names
289    TString *mangled;
290    TString *typeName;          // for structure field type name
291};
292
293#endif // _TYPES_INCLUDED_
294