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
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