blob: 042f6104d3ae7fb048169a251abdbd231acc6f6c [file] [log] [blame]
Jamie Madill47cb73a2016-09-09 11:41:44 -04001//
2// Copyright 2016 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// ConstantUnion: Constant folding helper class.
7
8#include "compiler/translator/ConstantUnion.h"
9
10#include "compiler/translator/Diagnostics.h"
11
12TConstantUnion::TConstantUnion()
13{
14 iConst = 0;
15 type = EbtVoid;
16}
17
18bool TConstantUnion::cast(TBasicType newType, const TConstantUnion &constant)
19{
20 switch (newType)
21 {
22 case EbtFloat:
23 switch (constant.type)
24 {
25 case EbtInt:
26 setFConst(static_cast<float>(constant.getIConst()));
27 break;
28 case EbtUInt:
29 setFConst(static_cast<float>(constant.getUConst()));
30 break;
31 case EbtBool:
32 setFConst(static_cast<float>(constant.getBConst()));
33 break;
34 case EbtFloat:
35 setFConst(static_cast<float>(constant.getFConst()));
36 break;
37 default:
38 return false;
39 }
40 break;
41 case EbtInt:
42 switch (constant.type)
43 {
44 case EbtInt:
45 setIConst(static_cast<int>(constant.getIConst()));
46 break;
47 case EbtUInt:
48 setIConst(static_cast<int>(constant.getUConst()));
49 break;
50 case EbtBool:
51 setIConst(static_cast<int>(constant.getBConst()));
52 break;
53 case EbtFloat:
54 setIConst(static_cast<int>(constant.getFConst()));
55 break;
56 default:
57 return false;
58 }
59 break;
60 case EbtUInt:
61 switch (constant.type)
62 {
63 case EbtInt:
64 setUConst(static_cast<unsigned int>(constant.getIConst()));
65 break;
66 case EbtUInt:
67 setUConst(static_cast<unsigned int>(constant.getUConst()));
68 break;
69 case EbtBool:
70 setUConst(static_cast<unsigned int>(constant.getBConst()));
71 break;
72 case EbtFloat:
73 setUConst(static_cast<unsigned int>(constant.getFConst()));
74 break;
75 default:
76 return false;
77 }
78 break;
79 case EbtBool:
80 switch (constant.type)
81 {
82 case EbtInt:
83 setBConst(constant.getIConst() != 0);
84 break;
85 case EbtUInt:
86 setBConst(constant.getUConst() != 0);
87 break;
88 case EbtBool:
89 setBConst(constant.getBConst());
90 break;
91 case EbtFloat:
92 setBConst(constant.getFConst() != 0.0f);
93 break;
94 default:
95 return false;
96 }
97 break;
98 case EbtStruct: // Struct fields don't get cast
99 switch (constant.type)
100 {
101 case EbtInt:
102 setIConst(constant.getIConst());
103 break;
104 case EbtUInt:
105 setUConst(constant.getUConst());
106 break;
107 case EbtBool:
108 setBConst(constant.getBConst());
109 break;
110 case EbtFloat:
111 setFConst(constant.getFConst());
112 break;
113 default:
114 return false;
115 }
116 break;
117 default:
118 return false;
119 }
120
121 return true;
122}
123
124bool TConstantUnion::operator==(const int i) const
125{
126 return i == iConst;
127}
128
129bool TConstantUnion::operator==(const unsigned int u) const
130{
131 return u == uConst;
132}
133
134bool TConstantUnion::operator==(const float f) const
135{
136 return f == fConst;
137}
138
139bool TConstantUnion::operator==(const bool b) const
140{
141 return b == bConst;
142}
143
144bool TConstantUnion::operator==(const TConstantUnion &constant) const
145{
146 if (constant.type != type)
147 return false;
148
149 switch (type)
150 {
151 case EbtInt:
152 return constant.iConst == iConst;
153 case EbtUInt:
154 return constant.uConst == uConst;
155 case EbtFloat:
156 return constant.fConst == fConst;
157 case EbtBool:
158 return constant.bConst == bConst;
159 default:
160 return false;
161 }
162}
163
164bool TConstantUnion::operator!=(const int i) const
165{
166 return !operator==(i);
167}
168
169bool TConstantUnion::operator!=(const unsigned int u) const
170{
171 return !operator==(u);
172}
173
174bool TConstantUnion::operator!=(const float f) const
175{
176 return !operator==(f);
177}
178
179bool TConstantUnion::operator!=(const bool b) const
180{
181 return !operator==(b);
182}
183
184bool TConstantUnion::operator!=(const TConstantUnion &constant) const
185{
186 return !operator==(constant);
187}
188
189bool TConstantUnion::operator>(const TConstantUnion &constant) const
190{
191 ASSERT(type == constant.type);
192 switch (type)
193 {
194 case EbtInt:
195 return iConst > constant.iConst;
196 case EbtUInt:
197 return uConst > constant.uConst;
198 case EbtFloat:
199 return fConst > constant.fConst;
200 default:
201 return false; // Invalid operation, handled at semantic analysis
202 }
203}
204
205bool TConstantUnion::operator<(const TConstantUnion &constant) const
206{
207 ASSERT(type == constant.type);
208 switch (type)
209 {
210 case EbtInt:
211 return iConst < constant.iConst;
212 case EbtUInt:
213 return uConst < constant.uConst;
214 case EbtFloat:
215 return fConst < constant.fConst;
216 default:
217 return false; // Invalid operation, handled at semantic analysis
218 }
219}
220
221// static
222TConstantUnion TConstantUnion::add(const TConstantUnion &lhs,
223 const TConstantUnion &rhs,
224 TDiagnostics *diag)
225{
226 TConstantUnion returnValue;
227 ASSERT(lhs.type == rhs.type);
228 switch (lhs.type)
229 {
230 case EbtInt:
231 returnValue.setIConst(lhs.iConst + rhs.iConst);
232 break;
233 case EbtUInt:
234 returnValue.setUConst(lhs.uConst + rhs.uConst);
235 break;
236 case EbtFloat:
237 returnValue.setFConst(lhs.fConst + rhs.fConst);
238 break;
239 default:
240 UNREACHABLE();
241 }
242
243 return returnValue;
244}
245
246// static
247TConstantUnion TConstantUnion::sub(const TConstantUnion &lhs,
248 const TConstantUnion &rhs,
249 TDiagnostics *diag)
250{
251 TConstantUnion returnValue;
252 ASSERT(lhs.type == rhs.type);
253 switch (lhs.type)
254 {
255 case EbtInt:
256 returnValue.setIConst(lhs.iConst - rhs.iConst);
257 break;
258 case EbtUInt:
259 returnValue.setUConst(lhs.uConst - rhs.uConst);
260 break;
261 case EbtFloat:
262 returnValue.setFConst(lhs.fConst - rhs.fConst);
263 break;
264 default:
265 UNREACHABLE();
266 }
267
268 return returnValue;
269}
270
271// static
272TConstantUnion TConstantUnion::mul(const TConstantUnion &lhs,
273 const TConstantUnion &rhs,
274 TDiagnostics *diag)
275{
276 TConstantUnion returnValue;
277 ASSERT(lhs.type == rhs.type);
278 switch (lhs.type)
279 {
280 case EbtInt:
281 returnValue.setIConst(lhs.iConst * rhs.iConst);
282 break;
283 case EbtUInt:
284 returnValue.setUConst(lhs.uConst * rhs.uConst);
285 break;
286 case EbtFloat:
287 returnValue.setFConst(lhs.fConst * rhs.fConst);
288 break;
289 default:
290 UNREACHABLE();
291 }
292
293 return returnValue;
294}
295
296TConstantUnion TConstantUnion::operator%(const TConstantUnion &constant) const
297{
298 TConstantUnion returnValue;
299 ASSERT(type == constant.type);
300 switch (type)
301 {
302 case EbtInt:
303 returnValue.setIConst(iConst % constant.iConst);
304 break;
305 case EbtUInt:
306 returnValue.setUConst(uConst % constant.uConst);
307 break;
308 default:
309 UNREACHABLE();
310 }
311
312 return returnValue;
313}
314
315TConstantUnion TConstantUnion::operator>>(const TConstantUnion &constant) const
316{
317 TConstantUnion returnValue;
318 ASSERT(type == constant.type);
319 switch (type)
320 {
321 case EbtInt:
322 returnValue.setIConst(iConst >> constant.iConst);
323 break;
324 case EbtUInt:
325 returnValue.setUConst(uConst >> constant.uConst);
326 break;
327 default:
328 UNREACHABLE();
329 }
330
331 return returnValue;
332}
333
334TConstantUnion TConstantUnion::operator<<(const TConstantUnion &constant) const
335{
336 TConstantUnion returnValue;
337 // The signedness of the second parameter might be different, but we
338 // don't care, since the result is undefined if the second parameter is
339 // negative, and aliasing should not be a problem with unions.
340 ASSERT(constant.type == EbtInt || constant.type == EbtUInt);
341 switch (type)
342 {
343 case EbtInt:
344 returnValue.setIConst(iConst << constant.iConst);
345 break;
346 case EbtUInt:
347 returnValue.setUConst(uConst << constant.uConst);
348 break;
349 default:
350 UNREACHABLE();
351 }
352
353 return returnValue;
354}
355
356TConstantUnion TConstantUnion::operator&(const TConstantUnion &constant) const
357{
358 TConstantUnion returnValue;
359 ASSERT(constant.type == EbtInt || constant.type == EbtUInt);
360 switch (type)
361 {
362 case EbtInt:
363 returnValue.setIConst(iConst & constant.iConst);
364 break;
365 case EbtUInt:
366 returnValue.setUConst(uConst & constant.uConst);
367 break;
368 default:
369 UNREACHABLE();
370 }
371
372 return returnValue;
373}
374
375TConstantUnion TConstantUnion::operator|(const TConstantUnion &constant) const
376{
377 TConstantUnion returnValue;
378 ASSERT(type == constant.type);
379 switch (type)
380 {
381 case EbtInt:
382 returnValue.setIConst(iConst | constant.iConst);
383 break;
384 case EbtUInt:
385 returnValue.setUConst(uConst | constant.uConst);
386 break;
387 default:
388 UNREACHABLE();
389 }
390
391 return returnValue;
392}
393
394TConstantUnion TConstantUnion::operator^(const TConstantUnion &constant) const
395{
396 TConstantUnion returnValue;
397 ASSERT(type == constant.type);
398 switch (type)
399 {
400 case EbtInt:
401 returnValue.setIConst(iConst ^ constant.iConst);
402 break;
403 case EbtUInt:
404 returnValue.setUConst(uConst ^ constant.uConst);
405 break;
406 default:
407 UNREACHABLE();
408 }
409
410 return returnValue;
411}
412
413TConstantUnion TConstantUnion::operator&&(const TConstantUnion &constant) const
414{
415 TConstantUnion returnValue;
416 ASSERT(type == constant.type);
417 switch (type)
418 {
419 case EbtBool:
420 returnValue.setBConst(bConst && constant.bConst);
421 break;
422 default:
423 UNREACHABLE();
424 }
425
426 return returnValue;
427}
428
429TConstantUnion TConstantUnion::operator||(const TConstantUnion &constant) const
430{
431 TConstantUnion returnValue;
432 ASSERT(type == constant.type);
433 switch (type)
434 {
435 case EbtBool:
436 returnValue.setBConst(bConst || constant.bConst);
437 break;
438 default:
439 UNREACHABLE();
440 }
441
442 return returnValue;
443}