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 #ifndef __ANDROID__
19 #include <assert.h>
20 #else
21 #include "../../Common/DebugAndroid.hpp"
22 #endif
23 
24 class ConstantUnion {
25 public:
26 	POOL_ALLOCATOR_NEW_DELETE();
ConstantUnion()27 	ConstantUnion()
28 	{
29 		iConst = 0;
30 		type = EbtVoid;
31 	}
32 
cast(TBasicType newType,const ConstantUnion & constant)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 
setIConst(int i)94 	void setIConst(int i) {iConst = i; type = EbtInt; }
setUConst(unsigned int u)95 	void setUConst(unsigned int u) { uConst = u; type = EbtUInt; }
setFConst(float f)96 	void setFConst(float f) {fConst = f; type = EbtFloat; }
setBConst(bool b)97 	void setBConst(bool b) {bConst = b; type = EbtBool; }
98 
getIConst()99 	int getIConst() const { return iConst; }
getUConst()100 	unsigned int getUConst() const { return uConst; }
getFConst()101 	float getFConst() const { return fConst; }
getBConst()102 	bool getBConst() const { return bConst; }
103 
getAsFloat()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 		return false;
157 	}
158 
159 	bool operator!=(const int i) const
160 	{
161 		return !operator==(i);
162 	}
163 
164 	bool operator!=(const unsigned int u) const
165 	{
166 		return !operator==(u);
167 	}
168 
169 	bool operator!=(const float f) const
170 	{
171 		return !operator==(f);
172 	}
173 
174 	bool operator!=(const bool b) const
175 	{
176 		return !operator==(b);
177 	}
178 
179 	bool operator!=(const ConstantUnion& constant) const
180 	{
181 		return !operator==(constant);
182 	}
183 
184 	bool operator>(const ConstantUnion& constant) const
185 	{
186 		assert(type == constant.type);
187 		switch (type) {
188 		case EbtInt:
189 			return iConst > constant.iConst;
190 		case EbtUInt:
191 			return uConst > constant.uConst;
192 		case EbtFloat:
193 			return fConst > constant.fConst;
194 		default:
195 			return false;   // Invalid operation, handled at semantic analysis
196 		}
197 
198 		return false;
199 	}
200 
201 	bool operator<(const ConstantUnion& constant) const
202 	{
203 		assert(type == constant.type);
204 		switch (type) {
205 		case EbtInt:
206 			return iConst < constant.iConst;
207 		case EbtUInt:
208 			return uConst < constant.uConst;
209 		case EbtFloat:
210 			return fConst < constant.fConst;
211 		default:
212 			return false;   // Invalid operation, handled at semantic analysis
213 		}
214 
215 		return false;
216 	}
217 
218 	bool operator<=(const ConstantUnion& constant) const
219 	{
220 		assert(type == constant.type);
221 		switch (type) {
222 		case EbtInt:
223 			return iConst <= constant.iConst;
224 		case EbtUInt:
225 			return uConst <= constant.uConst;
226 		case EbtFloat:
227 			return fConst <= constant.fConst;
228 		default:
229 			return false;   // Invalid operation, handled at semantic analysis
230 		}
231 
232 		return false;
233 	}
234 
235 	bool operator>=(const ConstantUnion& constant) const
236 	{
237 		assert(type == constant.type);
238 		switch (type) {
239 		case EbtInt:
240 			return iConst >= constant.iConst;
241 		case EbtUInt:
242 			return uConst >= constant.uConst;
243 		case EbtFloat:
244 			return fConst >= constant.fConst;
245 		default:
246 			return false;   // Invalid operation, handled at semantic analysis
247 		}
248 
249 		return false;
250 	}
251 
252 	ConstantUnion operator+(const ConstantUnion& constant) const
253 	{
254 		ConstantUnion returnValue;
255 		assert(type == constant.type);
256 		switch (type) {
257 		case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
258 		case EbtUInt: returnValue.setUConst(uConst + constant.uConst); break;
259 		case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break;
260 		default: assert(false && "Default missing");
261 		}
262 
263 		return returnValue;
264 	}
265 
266 	ConstantUnion operator-(const ConstantUnion& constant) const
267 	{
268 		ConstantUnion returnValue;
269 		assert(type == constant.type);
270 		switch (type) {
271 		case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
272 		case EbtUInt: returnValue.setUConst(uConst - constant.uConst); break;
273 		case EbtFloat: returnValue.setFConst(fConst - constant.fConst); 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 		case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break;
288 		default: assert(false && "Default missing");
289 		}
290 
291 		return returnValue;
292 	}
293 
294 	ConstantUnion operator%(const ConstantUnion& constant) const
295 	{
296 		ConstantUnion returnValue;
297 		assert(type == constant.type);
298 		switch (type) {
299 		case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
300 		case EbtUInt: returnValue.setUConst(uConst % constant.uConst); break;
301 		default:     assert(false && "Default missing");
302 		}
303 
304 		return returnValue;
305 	}
306 
307 	ConstantUnion operator>>(const ConstantUnion& constant) const
308 	{
309 		ConstantUnion returnValue;
310 		assert(type == constant.type);
311 		switch (type) {
312 		case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
313 		case EbtUInt: returnValue.setUConst(uConst >> constant.uConst); break;
314 		default:     assert(false && "Default missing");
315 		}
316 
317 		return returnValue;
318 	}
319 
320 	ConstantUnion operator<<(const ConstantUnion& constant) const
321 	{
322 		ConstantUnion returnValue;
323 		// The signedness of the second parameter might be different, but we
324 		// don't care, since the result is undefined if the second parameter is
325 		// negative, and aliasing should not be a problem with unions.
326 		assert(constant.type == EbtInt || constant.type == EbtUInt);
327 		switch (type) {
328 		case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
329 		case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break;
330 		default:     assert(false && "Default missing");
331 		}
332 
333 		return returnValue;
334 	}
335 
336 	ConstantUnion operator&(const ConstantUnion& constant) const
337 	{
338 		ConstantUnion returnValue;
339 		assert(constant.type == EbtInt || constant.type == EbtUInt);
340 		switch (type) {
341 		case EbtInt:  returnValue.setIConst(iConst & constant.iConst); break;
342 		case EbtUInt:  returnValue.setUConst(uConst & constant.uConst); break;
343 		default:     assert(false && "Default missing");
344 		}
345 
346 		return returnValue;
347 	}
348 
349 	ConstantUnion operator|(const ConstantUnion& constant) const
350 	{
351 		ConstantUnion returnValue;
352 		assert(type == constant.type);
353 		switch (type) {
354 		case EbtInt:  returnValue.setIConst(iConst | constant.iConst); break;
355 		case EbtUInt:  returnValue.setUConst(uConst | constant.uConst); break;
356 		default:     assert(false && "Default missing");
357 		}
358 
359 		return returnValue;
360 	}
361 
362 	ConstantUnion operator^(const ConstantUnion& constant) const
363 	{
364 		ConstantUnion returnValue;
365 		assert(type == constant.type);
366 		switch (type) {
367 		case EbtInt:  returnValue.setIConst(iConst ^ constant.iConst); break;
368 		case EbtUInt:  returnValue.setUConst(uConst ^ constant.uConst); break;
369 		default:     assert(false && "Default missing");
370 		}
371 
372 		return returnValue;
373 	}
374 
375 	ConstantUnion operator&&(const ConstantUnion& constant) const
376 	{
377 		ConstantUnion returnValue;
378 		assert(type == constant.type);
379 		switch (type) {
380 		case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
381 		default:     assert(false && "Default missing");
382 		}
383 
384 		return returnValue;
385 	}
386 
387 	ConstantUnion operator||(const ConstantUnion& constant) const
388 	{
389 		ConstantUnion returnValue;
390 		assert(type == constant.type);
391 		switch (type) {
392 		case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
393 		default:     assert(false && "Default missing");
394 		}
395 
396 		return returnValue;
397 	}
398 
getType()399 	TBasicType getType() const { return type; }
400 private:
401 
402 	union  {
403 		int iConst;  // used for ivec, scalar ints
404 		unsigned int uConst; // used for uvec, scalar uints
405 		bool bConst; // used for bvec, scalar bools
406 		float fConst;   // used for vec, mat, scalar floats
407 	} ;
408 
409 	TBasicType type;
410 };
411 
412 #endif // _CONSTANT_UNION_INCLUDED_
413