1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef _CONSTANT_UNION_INCLUDED_
16#define _CONSTANT_UNION_INCLUDED_
17
18#if defined(__ANDROID__) && !defined(ANDROID_HOST_BUILD) && !defined(ANDROID_NDK_BUILD)
19#include "../../Common/DebugAndroid.hpp"
20#else
21#include <assert.h>
22#endif
23
24class ConstantUnion {
25public:
26 POOL_ALLOCATOR_NEW_DELETE()
27 ConstantUnion()
28 {
29 iConst = 0;
30 type = EbtVoid;
31 }
32
33 bool cast(TBasicType newType, const ConstantUnion &constant)
34 {
35 switch (newType)
36 {
37 case EbtFloat:
38 switch (constant.type)
39 {
40 case EbtInt: setFConst(static_cast<float>(constant.getIConst())); break;
41 case EbtUInt: setFConst(static_cast<float>(constant.getUConst())); break;
42 case EbtBool: setFConst(static_cast<float>(constant.getBConst())); break;
43 case EbtFloat: setFConst(static_cast<float>(constant.getFConst())); break;
44 default: return false;
45 }
46 break;
47 case EbtInt:
48 switch (constant.type)
49 {
50 case EbtInt: setIConst(static_cast<int>(constant.getIConst())); break;
51 case EbtUInt: setIConst(static_cast<int>(constant.getUConst())); break;
52 case EbtBool: setIConst(static_cast<int>(constant.getBConst())); break;
53 case EbtFloat: setIConst(static_cast<int>(constant.getFConst())); break;
54 default: return false;
55 }
56 break;
57 case EbtUInt:
58 switch (constant.type)
59 {
60 case EbtInt: setUConst(static_cast<unsigned int>(constant.getIConst())); break;
61 case EbtUInt: setUConst(static_cast<unsigned int>(constant.getUConst())); break;
62 case EbtBool: setUConst(static_cast<unsigned int>(constant.getBConst())); break;
63 case EbtFloat: setUConst(static_cast<unsigned int>(constant.getFConst())); break;
64 default: return false;
65 }
66 break;
67 case EbtBool:
68 switch (constant.type)
69 {
70 case EbtInt: setBConst(constant.getIConst() != 0); break;
71 case EbtUInt: setBConst(constant.getUConst() != 0); break;
72 case EbtBool: setBConst(constant.getBConst()); break;
73 case EbtFloat: setBConst(constant.getFConst() != 0.0f); break;
74 default: return false;
75 }
76 break;
77 case EbtStruct: // Struct fields don't get cast
78 switch (constant.type)
79 {
80 case EbtInt: setIConst(constant.getIConst()); break;
81 case EbtUInt: setUConst(constant.getUConst()); break;
82 case EbtBool: setBConst(constant.getBConst()); break;
83 case EbtFloat: setFConst(constant.getFConst()); break;
84 default: return false;
85 }
86 break;
87 default:
88 return false;
89 }
90
91 return true;
92 }
93
94 void setIConst(int i) {iConst = i; type = EbtInt; }
95 void setUConst(unsigned int u) { uConst = u; type = EbtUInt; }
96 void setFConst(float f) {fConst = f; type = EbtFloat; }
97 void setBConst(bool b) {bConst = b; type = EbtBool; }
98
99 int getIConst() const { return iConst; }
100 unsigned int getUConst() const { return uConst; }
101 float getFConst() const { return fConst; }
102 bool getBConst() const { return bConst; }
103
104 float getAsFloat() const
105 {
106 const int FFFFFFFFh = 0xFFFFFFFF;
107
108 switch(type)
109 {
110 case EbtInt: return reinterpret_cast<const float&>(iConst);
111 case EbtUInt: return reinterpret_cast<const float&>(uConst);
112 case EbtFloat: return fConst;
113 case EbtBool: return (bConst == true) ? reinterpret_cast<const float&>(FFFFFFFFh) : 0;
114 default: return 0;
115 }
116 }
117
118 bool operator==(const int i) const
119 {
120 return i == iConst;
121 }
122
123 bool operator==(const unsigned int u) const
124 {
125 return u == uConst;
126 }
127
128 bool operator==(const float f) const
129 {
130 return f == fConst;
131 }
132
133 bool operator==(const bool b) const
134 {
135 return b == bConst;
136 }
137
138 bool operator==(const ConstantUnion& constant) const
139 {
140 if (constant.type != type)
141 return false;
142
143 switch (type) {
144 case EbtInt:
145 return constant.iConst == iConst;
146 case EbtUInt:
147 return constant.uConst == uConst;
148 case EbtFloat:
149 return constant.fConst == fConst;
150 case EbtBool:
151 return constant.bConst == bConst;
152 default:
153 return false;
154 }
155 }
156
157 bool operator!=(const int i) const
158 {
159 return !operator==(i);
160 }
161
162 bool operator!=(const unsigned int u) const
163 {
164 return !operator==(u);
165 }
166
167 bool operator!=(const float f) const
168 {
169 return !operator==(f);
170 }
171
172 bool operator!=(const bool b) const
173 {
174 return !operator==(b);
175 }
176
177 bool operator!=(const ConstantUnion& constant) const
178 {
179 return !operator==(constant);
180 }
181
182 bool operator>(const ConstantUnion& constant) const
183 {
184 assert(type == constant.type);
185 switch (type) {
186 case EbtInt:
187 return iConst > constant.iConst;
188 case EbtUInt:
189 return uConst > constant.uConst;
190 case EbtFloat:
191 return fConst > constant.fConst;
192 default:
193 return false; // Invalid operation, handled at semantic analysis
194 }
195 }
196
197 bool operator<(const ConstantUnion& constant) const
198 {
199 assert(type == constant.type);
200 switch (type) {
201 case EbtInt:
202 return iConst < constant.iConst;
203 case EbtUInt:
204 return uConst < constant.uConst;
205 case EbtFloat:
206 return fConst < constant.fConst;
207 default:
208 return false; // Invalid operation, handled at semantic analysis
209 }
210 }
211
212 bool operator<=(const ConstantUnion& constant) const
213 {
214 assert(type == constant.type);
215 switch (type) {
216 case EbtInt:
217 return iConst <= constant.iConst;
218 case EbtUInt:
219 return uConst <= constant.uConst;
220 case EbtFloat:
221 return fConst <= constant.fConst;
222 default:
223 return false; // Invalid operation, handled at semantic analysis
224 }
225 }
226
227 bool operator>=(const ConstantUnion& constant) const
228 {
229 assert(type == constant.type);
230 switch (type) {
231 case EbtInt:
232 return iConst >= constant.iConst;
233 case EbtUInt:
234 return uConst >= constant.uConst;
235 case EbtFloat:
236 return fConst >= constant.fConst;
237 default:
238 return false; // Invalid operation, handled at semantic analysis
239 }
240 }
241
242 ConstantUnion operator+(const ConstantUnion& constant) const
243 {
244 ConstantUnion returnValue;
245 assert(type == constant.type);
246 switch (type) {
247 case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
248 case EbtUInt: returnValue.setUConst(uConst + constant.uConst); break;
249 case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break;
250 default: assert(false && "Default missing");
251 }
252
253 return returnValue;
254 }
255
256 ConstantUnion operator-(const ConstantUnion& constant) const
257 {
258 ConstantUnion returnValue;
259 assert(type == constant.type);
260 switch (type) {
261 case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
262 case EbtUInt: returnValue.setUConst(uConst - constant.uConst); break;
263 case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break;
264 default: assert(false && "Default missing");
265 }
266
267 return returnValue;
268 }
269
270 ConstantUnion operator*(const ConstantUnion& constant) const
271 {
272 ConstantUnion returnValue;
273 assert(type == constant.type);
274 switch (type) {
275 case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
276 case EbtUInt: returnValue.setUConst(uConst * constant.uConst); break;
277 case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break;
278 default: assert(false && "Default missing");
279 }
280
281 return returnValue;
282 }
283
284 ConstantUnion operator%(const ConstantUnion& constant) const
285 {
286 ConstantUnion returnValue;
287 assert(type == constant.type);
288 switch (type) {
289 case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
290 case EbtUInt: returnValue.setUConst(uConst % constant.uConst); break;
291 default: assert(false && "Default missing");
292 }
293
294 return returnValue;
295 }
296
297 ConstantUnion operator>>(const ConstantUnion& constant) const
298 {
299 ConstantUnion returnValue;
300 assert(type == constant.type);
301 switch (type) {
302 case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
303 case EbtUInt: returnValue.setUConst(uConst >> constant.uConst); break;
304 default: assert(false && "Default missing");
305 }
306
307 return returnValue;
308 }
309
310 ConstantUnion operator<<(const ConstantUnion& constant) const
311 {
312 ConstantUnion returnValue;
313 // The signedness of the second parameter might be different, but we
314 // don't care, since the result is undefined if the second parameter is
315 // negative, and aliasing should not be a problem with unions.
316 assert(constant.type == EbtInt || constant.type == EbtUInt);
317 switch (type) {
318 case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
319 case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break;
320 default: assert(false && "Default missing");
321 }
322
323 return returnValue;
324 }
325
326 ConstantUnion operator&(const ConstantUnion& constant) const
327 {
328 ConstantUnion returnValue;
329 assert(constant.type == EbtInt || constant.type == EbtUInt);
330 switch (type) {
331 case EbtInt: returnValue.setIConst(iConst & constant.iConst); break;
332 case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break;
333 default: assert(false && "Default missing");
334 }
335
336 return returnValue;
337 }
338
339 ConstantUnion operator|(const ConstantUnion& constant) const
340 {
341 ConstantUnion returnValue;
342 assert(type == constant.type);
343 switch (type) {
344 case EbtInt: returnValue.setIConst(iConst | constant.iConst); break;
345 case EbtUInt: returnValue.setUConst(uConst | constant.uConst); break;
346 default: assert(false && "Default missing");
347 }
348
349 return returnValue;
350 }
351
352 ConstantUnion operator^(const ConstantUnion& constant) const
353 {
354 ConstantUnion returnValue;
355 assert(type == constant.type);
356 switch (type) {
357 case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break;
358 case EbtUInt: returnValue.setUConst(uConst ^ constant.uConst); break;
359 default: assert(false && "Default missing");
360 }
361
362 return returnValue;
363 }
364
365 ConstantUnion operator&&(const ConstantUnion& constant) const
366 {
367 ConstantUnion returnValue;
368 assert(type == constant.type);
369 switch (type) {
370 case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
371 default: assert(false && "Default missing");
372 }
373
374 return returnValue;
375 }
376
377 ConstantUnion operator||(const ConstantUnion& constant) const
378 {
379 ConstantUnion returnValue;
380 assert(type == constant.type);
381 switch (type) {
382 case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
383 default: assert(false && "Default missing");
384 }
385
386 return returnValue;
387 }
388
389 TBasicType getType() const { return type; }
390private:
391
392 union {
393 int iConst; // used for ivec, scalar ints
394 unsigned int uConst; // used for uvec, scalar uints
395 bool bConst; // used for bvec, scalar bools
396 float fConst; // used for vec, mat, scalar floats
397 } ;
398
399 TBasicType type;
400};
401
402#endif // _CONSTANT_UNION_INCLUDED_
403