1//
2// Copyright (c) 2002-2014 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 _CONSTANT_UNION_INCLUDED_
8#define _CONSTANT_UNION_INCLUDED_
9
10#include <assert.h>
11
12class ConstantUnion {
13public:
14    POOL_ALLOCATOR_NEW_DELETE();
15    ConstantUnion()
16    {
17        iConst = 0;
18        type = EbtVoid;
19    }
20
21    bool cast(TBasicType newType, const ConstantUnion &constant)
22    {
23        switch (newType)
24        {
25          case EbtFloat:
26            switch (constant.type)
27            {
28              case EbtInt:   setFConst(static_cast<float>(constant.getIConst())); break;
29              case EbtUInt:  setFConst(static_cast<float>(constant.getUConst())); break;
30              case EbtBool:  setFConst(static_cast<float>(constant.getBConst())); break;
31              case EbtFloat: setFConst(static_cast<float>(constant.getFConst())); break;
32              default:       return false;
33            }
34            break;
35          case EbtInt:
36            switch (constant.type)
37            {
38              case EbtInt:   setIConst(static_cast<int>(constant.getIConst())); break;
39              case EbtUInt:  setIConst(static_cast<int>(constant.getUConst())); break;
40              case EbtBool:  setIConst(static_cast<int>(constant.getBConst())); break;
41              case EbtFloat: setIConst(static_cast<int>(constant.getFConst())); break;
42              default:       return false;
43            }
44            break;
45          case EbtUInt:
46            switch (constant.type)
47            {
48              case EbtInt:   setUConst(static_cast<unsigned int>(constant.getIConst())); break;
49              case EbtUInt:  setUConst(static_cast<unsigned int>(constant.getUConst())); break;
50              case EbtBool:  setUConst(static_cast<unsigned int>(constant.getBConst())); break;
51              case EbtFloat: setUConst(static_cast<unsigned int>(constant.getFConst())); break;
52              default:       return false;
53            }
54            break;
55          case EbtBool:
56            switch (constant.type)
57            {
58              case EbtInt:   setBConst(constant.getIConst() != 0);    break;
59              case EbtUInt:  setBConst(constant.getUConst() != 0);    break;
60              case EbtBool:  setBConst(constant.getBConst());         break;
61              case EbtFloat: setBConst(constant.getFConst() != 0.0f); break;
62              default:       return false;
63            }
64            break;
65          case EbtStruct:    // Struct fields don't get cast
66            switch (constant.type)
67            {
68              case EbtInt:   setIConst(constant.getIConst()); break;
69              case EbtUInt:  setUConst(constant.getUConst()); break;
70              case EbtBool:  setBConst(constant.getBConst()); break;
71              case EbtFloat: setFConst(constant.getFConst()); break;
72              default:       return false;
73            }
74            break;
75          default:
76            return false;
77        }
78
79        return true;
80    }
81
82    void setIConst(int i) {iConst = i; type = EbtInt; }
83    void setUConst(unsigned int u) { uConst = u; type = EbtUInt; }
84    void setFConst(float f) {fConst = f; type = EbtFloat; }
85    void setBConst(bool b) {bConst = b; type = EbtBool; }
86
87    int getIConst() const { return iConst; }
88    unsigned int getUConst() const { return uConst; }
89    float getFConst() const { return fConst; }
90    bool getBConst() const { return bConst; }
91
92    bool operator==(const int i) const
93    {
94        return i == iConst;
95    }
96
97    bool operator==(const unsigned int u) const
98    {
99        return u == uConst;
100    }
101
102    bool operator==(const float f) const
103    {
104        return f == fConst;
105    }
106
107    bool operator==(const bool b) const
108    {
109        return b == bConst;
110    }
111
112    bool operator==(const ConstantUnion& constant) const
113    {
114        if (constant.type != type)
115            return false;
116
117        switch (type) {
118        case EbtInt:
119            return constant.iConst == iConst;
120        case EbtUInt:
121            return constant.uConst == uConst;
122        case EbtFloat:
123            return constant.fConst == fConst;
124        case EbtBool:
125            return constant.bConst == bConst;
126        default:
127            return false;
128        }
129    }
130
131    bool operator!=(const int i) const
132    {
133        return !operator==(i);
134    }
135
136    bool operator!=(const unsigned int u) const
137    {
138        return !operator==(u);
139    }
140
141    bool operator!=(const float f) const
142    {
143        return !operator==(f);
144    }
145
146    bool operator!=(const bool b) const
147    {
148        return !operator==(b);
149    }
150
151    bool operator!=(const ConstantUnion& constant) const
152    {
153        return !operator==(constant);
154    }
155
156    bool operator>(const ConstantUnion& constant) const
157    {
158        assert(type == constant.type);
159        switch (type) {
160        case EbtInt:
161            return iConst > constant.iConst;
162        case EbtUInt:
163            return uConst > constant.uConst;
164        case EbtFloat:
165            return fConst > constant.fConst;
166        default:
167            return false;   // Invalid operation, handled at semantic analysis
168        }
169    }
170
171    bool operator<(const ConstantUnion& constant) const
172    {
173        assert(type == constant.type);
174        switch (type) {
175        case EbtInt:
176            return iConst < constant.iConst;
177        case EbtUInt:
178            return uConst < constant.uConst;
179        case EbtFloat:
180            return fConst < constant.fConst;
181        default:
182            return false;   // Invalid operation, handled at semantic analysis
183        }
184    }
185
186    ConstantUnion operator+(const ConstantUnion& constant) const
187    {
188        ConstantUnion returnValue;
189        assert(type == constant.type);
190        switch (type) {
191        case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
192        case EbtUInt: returnValue.setUConst(uConst + constant.uConst); break;
193        case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break;
194        default: assert(false && "Default missing");
195        }
196
197        return returnValue;
198    }
199
200    ConstantUnion operator-(const ConstantUnion& constant) const
201    {
202        ConstantUnion returnValue;
203        assert(type == constant.type);
204        switch (type) {
205        case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
206        case EbtUInt: returnValue.setUConst(uConst - constant.uConst); break;
207        case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break;
208        default: assert(false && "Default missing");
209        }
210
211        return returnValue;
212    }
213
214    ConstantUnion operator*(const ConstantUnion& constant) const
215    {
216        ConstantUnion returnValue;
217        assert(type == constant.type);
218        switch (type) {
219        case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
220        case EbtUInt: returnValue.setUConst(uConst * constant.uConst); break;
221        case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break;
222        default: assert(false && "Default missing");
223        }
224
225        return returnValue;
226    }
227
228    ConstantUnion operator%(const ConstantUnion& constant) const
229    {
230        ConstantUnion returnValue;
231        assert(type == constant.type);
232        switch (type) {
233        case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
234        case EbtUInt: returnValue.setUConst(uConst % constant.uConst); break;
235        default:     assert(false && "Default missing");
236        }
237
238        return returnValue;
239    }
240
241    ConstantUnion operator>>(const ConstantUnion& constant) const
242    {
243        ConstantUnion returnValue;
244        assert(type == constant.type);
245        switch (type) {
246        case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
247        case EbtUInt: returnValue.setUConst(uConst >> constant.uConst); break;
248        default:     assert(false && "Default missing");
249        }
250
251        return returnValue;
252    }
253
254    ConstantUnion operator<<(const ConstantUnion& constant) const
255    {
256        ConstantUnion returnValue;
257        assert(type == constant.type);
258        switch (type) {
259        case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
260        case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break;
261        default:     assert(false && "Default missing");
262        }
263
264        return returnValue;
265    }
266
267    ConstantUnion operator&(const ConstantUnion& constant) const
268    {
269        ConstantUnion returnValue;
270        assert(type == constant.type);
271        switch (type) {
272        case EbtInt:  returnValue.setIConst(iConst & constant.iConst); break;
273        case EbtUInt:  returnValue.setUConst(uConst & constant.uConst); break;
274        default:     assert(false && "Default missing");
275        }
276
277        return returnValue;
278    }
279
280    ConstantUnion operator|(const ConstantUnion& constant) const
281    {
282        ConstantUnion returnValue;
283        assert(type == constant.type);
284        switch (type) {
285        case EbtInt:  returnValue.setIConst(iConst | constant.iConst); break;
286        case EbtUInt:  returnValue.setUConst(uConst | constant.uConst); break;
287        default:     assert(false && "Default missing");
288        }
289
290        return returnValue;
291    }
292
293    ConstantUnion operator^(const ConstantUnion& constant) const
294    {
295        ConstantUnion returnValue;
296        assert(type == constant.type);
297        switch (type) {
298        case EbtInt:  returnValue.setIConst(iConst ^ constant.iConst); break;
299        case EbtUInt:  returnValue.setUConst(uConst ^ constant.uConst); break;
300        default:     assert(false && "Default missing");
301        }
302
303        return returnValue;
304    }
305
306    ConstantUnion operator&&(const ConstantUnion& constant) const
307    {
308        ConstantUnion returnValue;
309        assert(type == constant.type);
310        switch (type) {
311        case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
312        default:     assert(false && "Default missing");
313        }
314
315        return returnValue;
316    }
317
318    ConstantUnion operator||(const ConstantUnion& constant) const
319    {
320        ConstantUnion returnValue;
321        assert(type == constant.type);
322        switch (type) {
323        case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
324        default:     assert(false && "Default missing");
325        }
326
327        return returnValue;
328    }
329
330    TBasicType getType() const { return type; }
331private:
332
333    union  {
334        int iConst;  // used for ivec, scalar ints
335        unsigned int uConst; // used for uvec, scalar uints
336        bool bConst; // used for bvec, scalar bools
337        float fConst;   // used for vec, mat, scalar floats
338    } ;
339
340    TBasicType type;
341};
342
343#endif // _CONSTANT_UNION_INCLUDED_
344