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