xref: /aosp_15_r20/external/angle/src/compiler/translator/ConstantUnion.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // ConstantUnion: Constant folding helper class.
7*8975f5c5SAndroid Build Coastguard Worker 
8*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/ConstantUnion.h"
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include "common/mathutil.h"
11*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/Diagnostics.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/util.h"
13*8975f5c5SAndroid Build Coastguard Worker 
14*8975f5c5SAndroid Build Coastguard Worker namespace sh
15*8975f5c5SAndroid Build Coastguard Worker {
16*8975f5c5SAndroid Build Coastguard Worker 
17*8975f5c5SAndroid Build Coastguard Worker namespace
18*8975f5c5SAndroid Build Coastguard Worker {
19*8975f5c5SAndroid Build Coastguard Worker 
CheckedSum(float lhs,float rhs,TDiagnostics * diag,const TSourceLoc & line)20*8975f5c5SAndroid Build Coastguard Worker float CheckedSum(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
21*8975f5c5SAndroid Build Coastguard Worker {
22*8975f5c5SAndroid Build Coastguard Worker     float result = lhs + rhs;
23*8975f5c5SAndroid Build Coastguard Worker     if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
24*8975f5c5SAndroid Build Coastguard Worker     {
25*8975f5c5SAndroid Build Coastguard Worker         diag->warning(line, "Constant folded undefined addition generated NaN", "+");
26*8975f5c5SAndroid Build Coastguard Worker     }
27*8975f5c5SAndroid Build Coastguard Worker     else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
28*8975f5c5SAndroid Build Coastguard Worker     {
29*8975f5c5SAndroid Build Coastguard Worker         diag->warning(line, "Constant folded addition overflowed to infinity", "+");
30*8975f5c5SAndroid Build Coastguard Worker     }
31*8975f5c5SAndroid Build Coastguard Worker     return result;
32*8975f5c5SAndroid Build Coastguard Worker }
33*8975f5c5SAndroid Build Coastguard Worker 
CheckedDiff(float lhs,float rhs,TDiagnostics * diag,const TSourceLoc & line)34*8975f5c5SAndroid Build Coastguard Worker float CheckedDiff(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
35*8975f5c5SAndroid Build Coastguard Worker {
36*8975f5c5SAndroid Build Coastguard Worker     float result = lhs - rhs;
37*8975f5c5SAndroid Build Coastguard Worker     if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
38*8975f5c5SAndroid Build Coastguard Worker     {
39*8975f5c5SAndroid Build Coastguard Worker         diag->warning(line, "Constant folded undefined subtraction generated NaN", "-");
40*8975f5c5SAndroid Build Coastguard Worker     }
41*8975f5c5SAndroid Build Coastguard Worker     else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
42*8975f5c5SAndroid Build Coastguard Worker     {
43*8975f5c5SAndroid Build Coastguard Worker         diag->warning(line, "Constant folded subtraction overflowed to infinity", "-");
44*8975f5c5SAndroid Build Coastguard Worker     }
45*8975f5c5SAndroid Build Coastguard Worker     return result;
46*8975f5c5SAndroid Build Coastguard Worker }
47*8975f5c5SAndroid Build Coastguard Worker 
CheckedMul(float lhs,float rhs,TDiagnostics * diag,const TSourceLoc & line)48*8975f5c5SAndroid Build Coastguard Worker float CheckedMul(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
49*8975f5c5SAndroid Build Coastguard Worker {
50*8975f5c5SAndroid Build Coastguard Worker     float result = lhs * rhs;
51*8975f5c5SAndroid Build Coastguard Worker     if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
52*8975f5c5SAndroid Build Coastguard Worker     {
53*8975f5c5SAndroid Build Coastguard Worker         diag->warning(line, "Constant folded undefined multiplication generated NaN", "*");
54*8975f5c5SAndroid Build Coastguard Worker     }
55*8975f5c5SAndroid Build Coastguard Worker     else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
56*8975f5c5SAndroid Build Coastguard Worker     {
57*8975f5c5SAndroid Build Coastguard Worker         diag->warning(line, "Constant folded multiplication overflowed to infinity", "*");
58*8975f5c5SAndroid Build Coastguard Worker     }
59*8975f5c5SAndroid Build Coastguard Worker     return result;
60*8975f5c5SAndroid Build Coastguard Worker }
61*8975f5c5SAndroid Build Coastguard Worker 
IsValidShiftOffset(const TConstantUnion & rhs)62*8975f5c5SAndroid Build Coastguard Worker bool IsValidShiftOffset(const TConstantUnion &rhs)
63*8975f5c5SAndroid Build Coastguard Worker {
64*8975f5c5SAndroid Build Coastguard Worker     return (rhs.getType() == EbtInt && (rhs.getIConst() >= 0 && rhs.getIConst() <= 31)) ||
65*8975f5c5SAndroid Build Coastguard Worker            (rhs.getType() == EbtUInt && rhs.getUConst() <= 31u);
66*8975f5c5SAndroid Build Coastguard Worker }
67*8975f5c5SAndroid Build Coastguard Worker 
68*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
69*8975f5c5SAndroid Build Coastguard Worker 
TConstantUnion()70*8975f5c5SAndroid Build Coastguard Worker TConstantUnion::TConstantUnion() : iConst(0), type(EbtVoid) {}
71*8975f5c5SAndroid Build Coastguard Worker 
TConstantUnion(int i)72*8975f5c5SAndroid Build Coastguard Worker TConstantUnion::TConstantUnion(int i) : iConst(i), type(EbtInt) {}
73*8975f5c5SAndroid Build Coastguard Worker 
TConstantUnion(unsigned int u)74*8975f5c5SAndroid Build Coastguard Worker TConstantUnion::TConstantUnion(unsigned int u) : uConst(u), type(EbtUInt) {}
75*8975f5c5SAndroid Build Coastguard Worker 
TConstantUnion(float f)76*8975f5c5SAndroid Build Coastguard Worker TConstantUnion::TConstantUnion(float f) : fConst(f), type(EbtFloat) {}
77*8975f5c5SAndroid Build Coastguard Worker 
TConstantUnion(bool b)78*8975f5c5SAndroid Build Coastguard Worker TConstantUnion::TConstantUnion(bool b) : bConst(b), type(EbtBool) {}
79*8975f5c5SAndroid Build Coastguard Worker 
getIConst() const80*8975f5c5SAndroid Build Coastguard Worker int TConstantUnion::getIConst() const
81*8975f5c5SAndroid Build Coastguard Worker {
82*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == EbtInt);
83*8975f5c5SAndroid Build Coastguard Worker     return iConst;
84*8975f5c5SAndroid Build Coastguard Worker }
85*8975f5c5SAndroid Build Coastguard Worker 
getUConst() const86*8975f5c5SAndroid Build Coastguard Worker unsigned int TConstantUnion::getUConst() const
87*8975f5c5SAndroid Build Coastguard Worker {
88*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == EbtUInt);
89*8975f5c5SAndroid Build Coastguard Worker     return uConst;
90*8975f5c5SAndroid Build Coastguard Worker }
91*8975f5c5SAndroid Build Coastguard Worker 
getFConst() const92*8975f5c5SAndroid Build Coastguard Worker float TConstantUnion::getFConst() const
93*8975f5c5SAndroid Build Coastguard Worker {
94*8975f5c5SAndroid Build Coastguard Worker     switch (type)
95*8975f5c5SAndroid Build Coastguard Worker     {
96*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
97*8975f5c5SAndroid Build Coastguard Worker             return static_cast<float>(iConst);
98*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
99*8975f5c5SAndroid Build Coastguard Worker             return static_cast<float>(uConst);
100*8975f5c5SAndroid Build Coastguard Worker         default:
101*8975f5c5SAndroid Build Coastguard Worker             ASSERT(type == EbtFloat);
102*8975f5c5SAndroid Build Coastguard Worker             return fConst;
103*8975f5c5SAndroid Build Coastguard Worker     }
104*8975f5c5SAndroid Build Coastguard Worker }
105*8975f5c5SAndroid Build Coastguard Worker 
getBConst() const106*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::getBConst() const
107*8975f5c5SAndroid Build Coastguard Worker {
108*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == EbtBool);
109*8975f5c5SAndroid Build Coastguard Worker     return bConst;
110*8975f5c5SAndroid Build Coastguard Worker }
111*8975f5c5SAndroid Build Coastguard Worker 
isZero() const112*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::isZero() const
113*8975f5c5SAndroid Build Coastguard Worker {
114*8975f5c5SAndroid Build Coastguard Worker     switch (type)
115*8975f5c5SAndroid Build Coastguard Worker     {
116*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
117*8975f5c5SAndroid Build Coastguard Worker             return getIConst() == 0;
118*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
119*8975f5c5SAndroid Build Coastguard Worker             return getUConst() == 0;
120*8975f5c5SAndroid Build Coastguard Worker         case EbtFloat:
121*8975f5c5SAndroid Build Coastguard Worker             return getFConst() == 0.0f;
122*8975f5c5SAndroid Build Coastguard Worker         case EbtBool:
123*8975f5c5SAndroid Build Coastguard Worker             return getBConst() == false;
124*8975f5c5SAndroid Build Coastguard Worker         default:
125*8975f5c5SAndroid Build Coastguard Worker             return false;
126*8975f5c5SAndroid Build Coastguard Worker     }
127*8975f5c5SAndroid Build Coastguard Worker }
128*8975f5c5SAndroid Build Coastguard Worker 
getYuvCscStandardEXTConst() const129*8975f5c5SAndroid Build Coastguard Worker TYuvCscStandardEXT TConstantUnion::getYuvCscStandardEXTConst() const
130*8975f5c5SAndroid Build Coastguard Worker {
131*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == EbtYuvCscStandardEXT);
132*8975f5c5SAndroid Build Coastguard Worker     return yuvCscStandardEXTConst;
133*8975f5c5SAndroid Build Coastguard Worker }
134*8975f5c5SAndroid Build Coastguard Worker 
cast(TBasicType newType,const TConstantUnion & constant)135*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::cast(TBasicType newType, const TConstantUnion &constant)
136*8975f5c5SAndroid Build Coastguard Worker {
137*8975f5c5SAndroid Build Coastguard Worker     switch (newType)
138*8975f5c5SAndroid Build Coastguard Worker     {
139*8975f5c5SAndroid Build Coastguard Worker         case EbtFloat:
140*8975f5c5SAndroid Build Coastguard Worker             switch (constant.type)
141*8975f5c5SAndroid Build Coastguard Worker             {
142*8975f5c5SAndroid Build Coastguard Worker                 case EbtInt:
143*8975f5c5SAndroid Build Coastguard Worker                     setFConst(static_cast<float>(constant.getIConst()));
144*8975f5c5SAndroid Build Coastguard Worker                     break;
145*8975f5c5SAndroid Build Coastguard Worker                 case EbtUInt:
146*8975f5c5SAndroid Build Coastguard Worker                     setFConst(static_cast<float>(constant.getUConst()));
147*8975f5c5SAndroid Build Coastguard Worker                     break;
148*8975f5c5SAndroid Build Coastguard Worker                 case EbtBool:
149*8975f5c5SAndroid Build Coastguard Worker                     setFConst(static_cast<float>(constant.getBConst()));
150*8975f5c5SAndroid Build Coastguard Worker                     break;
151*8975f5c5SAndroid Build Coastguard Worker                 case EbtFloat:
152*8975f5c5SAndroid Build Coastguard Worker                     setFConst(static_cast<float>(constant.getFConst()));
153*8975f5c5SAndroid Build Coastguard Worker                     break;
154*8975f5c5SAndroid Build Coastguard Worker                 default:
155*8975f5c5SAndroid Build Coastguard Worker                     return false;
156*8975f5c5SAndroid Build Coastguard Worker             }
157*8975f5c5SAndroid Build Coastguard Worker             break;
158*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
159*8975f5c5SAndroid Build Coastguard Worker             switch (constant.type)
160*8975f5c5SAndroid Build Coastguard Worker             {
161*8975f5c5SAndroid Build Coastguard Worker                 case EbtInt:
162*8975f5c5SAndroid Build Coastguard Worker                     setIConst(static_cast<int>(constant.getIConst()));
163*8975f5c5SAndroid Build Coastguard Worker                     break;
164*8975f5c5SAndroid Build Coastguard Worker                 case EbtUInt:
165*8975f5c5SAndroid Build Coastguard Worker                     setIConst(static_cast<int>(constant.getUConst()));
166*8975f5c5SAndroid Build Coastguard Worker                     break;
167*8975f5c5SAndroid Build Coastguard Worker                 case EbtBool:
168*8975f5c5SAndroid Build Coastguard Worker                     setIConst(static_cast<int>(constant.getBConst()));
169*8975f5c5SAndroid Build Coastguard Worker                     break;
170*8975f5c5SAndroid Build Coastguard Worker                 case EbtFloat:
171*8975f5c5SAndroid Build Coastguard Worker                     setIConst(static_cast<int>(constant.getFConst()));
172*8975f5c5SAndroid Build Coastguard Worker                     break;
173*8975f5c5SAndroid Build Coastguard Worker                 default:
174*8975f5c5SAndroid Build Coastguard Worker                     return false;
175*8975f5c5SAndroid Build Coastguard Worker             }
176*8975f5c5SAndroid Build Coastguard Worker             break;
177*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
178*8975f5c5SAndroid Build Coastguard Worker             switch (constant.type)
179*8975f5c5SAndroid Build Coastguard Worker             {
180*8975f5c5SAndroid Build Coastguard Worker                 case EbtInt:
181*8975f5c5SAndroid Build Coastguard Worker                     setUConst(static_cast<unsigned int>(constant.getIConst()));
182*8975f5c5SAndroid Build Coastguard Worker                     break;
183*8975f5c5SAndroid Build Coastguard Worker                 case EbtUInt:
184*8975f5c5SAndroid Build Coastguard Worker                     setUConst(static_cast<unsigned int>(constant.getUConst()));
185*8975f5c5SAndroid Build Coastguard Worker                     break;
186*8975f5c5SAndroid Build Coastguard Worker                 case EbtBool:
187*8975f5c5SAndroid Build Coastguard Worker                     setUConst(static_cast<unsigned int>(constant.getBConst()));
188*8975f5c5SAndroid Build Coastguard Worker                     break;
189*8975f5c5SAndroid Build Coastguard Worker                 case EbtFloat:
190*8975f5c5SAndroid Build Coastguard Worker                     if (constant.getFConst() < 0.0f)
191*8975f5c5SAndroid Build Coastguard Worker                     {
192*8975f5c5SAndroid Build Coastguard Worker                         // Avoid undefined behavior in C++ by first casting to signed int.
193*8975f5c5SAndroid Build Coastguard Worker                         setUConst(
194*8975f5c5SAndroid Build Coastguard Worker                             static_cast<unsigned int>(static_cast<int>(constant.getFConst())));
195*8975f5c5SAndroid Build Coastguard Worker                     }
196*8975f5c5SAndroid Build Coastguard Worker                     else
197*8975f5c5SAndroid Build Coastguard Worker                     {
198*8975f5c5SAndroid Build Coastguard Worker                         setUConst(static_cast<unsigned int>(constant.getFConst()));
199*8975f5c5SAndroid Build Coastguard Worker                     }
200*8975f5c5SAndroid Build Coastguard Worker                     break;
201*8975f5c5SAndroid Build Coastguard Worker                 default:
202*8975f5c5SAndroid Build Coastguard Worker                     return false;
203*8975f5c5SAndroid Build Coastguard Worker             }
204*8975f5c5SAndroid Build Coastguard Worker             break;
205*8975f5c5SAndroid Build Coastguard Worker         case EbtBool:
206*8975f5c5SAndroid Build Coastguard Worker             switch (constant.type)
207*8975f5c5SAndroid Build Coastguard Worker             {
208*8975f5c5SAndroid Build Coastguard Worker                 case EbtInt:
209*8975f5c5SAndroid Build Coastguard Worker                     setBConst(constant.getIConst() != 0);
210*8975f5c5SAndroid Build Coastguard Worker                     break;
211*8975f5c5SAndroid Build Coastguard Worker                 case EbtUInt:
212*8975f5c5SAndroid Build Coastguard Worker                     setBConst(constant.getUConst() != 0);
213*8975f5c5SAndroid Build Coastguard Worker                     break;
214*8975f5c5SAndroid Build Coastguard Worker                 case EbtBool:
215*8975f5c5SAndroid Build Coastguard Worker                     setBConst(constant.getBConst());
216*8975f5c5SAndroid Build Coastguard Worker                     break;
217*8975f5c5SAndroid Build Coastguard Worker                 case EbtFloat:
218*8975f5c5SAndroid Build Coastguard Worker                     setBConst(constant.getFConst() != 0.0f);
219*8975f5c5SAndroid Build Coastguard Worker                     break;
220*8975f5c5SAndroid Build Coastguard Worker                 default:
221*8975f5c5SAndroid Build Coastguard Worker                     return false;
222*8975f5c5SAndroid Build Coastguard Worker             }
223*8975f5c5SAndroid Build Coastguard Worker             break;
224*8975f5c5SAndroid Build Coastguard Worker         case EbtStruct:  // Struct fields don't get cast
225*8975f5c5SAndroid Build Coastguard Worker             switch (constant.type)
226*8975f5c5SAndroid Build Coastguard Worker             {
227*8975f5c5SAndroid Build Coastguard Worker                 case EbtInt:
228*8975f5c5SAndroid Build Coastguard Worker                     setIConst(constant.getIConst());
229*8975f5c5SAndroid Build Coastguard Worker                     break;
230*8975f5c5SAndroid Build Coastguard Worker                 case EbtUInt:
231*8975f5c5SAndroid Build Coastguard Worker                     setUConst(constant.getUConst());
232*8975f5c5SAndroid Build Coastguard Worker                     break;
233*8975f5c5SAndroid Build Coastguard Worker                 case EbtBool:
234*8975f5c5SAndroid Build Coastguard Worker                     setBConst(constant.getBConst());
235*8975f5c5SAndroid Build Coastguard Worker                     break;
236*8975f5c5SAndroid Build Coastguard Worker                 case EbtFloat:
237*8975f5c5SAndroid Build Coastguard Worker                     setFConst(constant.getFConst());
238*8975f5c5SAndroid Build Coastguard Worker                     break;
239*8975f5c5SAndroid Build Coastguard Worker                 default:
240*8975f5c5SAndroid Build Coastguard Worker                     return false;
241*8975f5c5SAndroid Build Coastguard Worker             }
242*8975f5c5SAndroid Build Coastguard Worker             break;
243*8975f5c5SAndroid Build Coastguard Worker         case EbtYuvCscStandardEXT:
244*8975f5c5SAndroid Build Coastguard Worker             switch (constant.type)
245*8975f5c5SAndroid Build Coastguard Worker             {
246*8975f5c5SAndroid Build Coastguard Worker                 case EbtYuvCscStandardEXT:
247*8975f5c5SAndroid Build Coastguard Worker                     setYuvCscStandardEXTConst(constant.getYuvCscStandardEXTConst());
248*8975f5c5SAndroid Build Coastguard Worker                     break;
249*8975f5c5SAndroid Build Coastguard Worker                 default:
250*8975f5c5SAndroid Build Coastguard Worker                     return false;
251*8975f5c5SAndroid Build Coastguard Worker             }
252*8975f5c5SAndroid Build Coastguard Worker             break;
253*8975f5c5SAndroid Build Coastguard Worker         default:
254*8975f5c5SAndroid Build Coastguard Worker             return false;
255*8975f5c5SAndroid Build Coastguard Worker     }
256*8975f5c5SAndroid Build Coastguard Worker 
257*8975f5c5SAndroid Build Coastguard Worker     return true;
258*8975f5c5SAndroid Build Coastguard Worker }
259*8975f5c5SAndroid Build Coastguard Worker 
operator ==(const int i) const260*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::operator==(const int i) const
261*8975f5c5SAndroid Build Coastguard Worker {
262*8975f5c5SAndroid Build Coastguard Worker     switch (type)
263*8975f5c5SAndroid Build Coastguard Worker     {
264*8975f5c5SAndroid Build Coastguard Worker         case EbtFloat:
265*8975f5c5SAndroid Build Coastguard Worker             return static_cast<float>(i) == fConst;
266*8975f5c5SAndroid Build Coastguard Worker         default:
267*8975f5c5SAndroid Build Coastguard Worker             return i == iConst;
268*8975f5c5SAndroid Build Coastguard Worker     }
269*8975f5c5SAndroid Build Coastguard Worker }
270*8975f5c5SAndroid Build Coastguard Worker 
operator ==(const unsigned int u) const271*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::operator==(const unsigned int u) const
272*8975f5c5SAndroid Build Coastguard Worker {
273*8975f5c5SAndroid Build Coastguard Worker     switch (type)
274*8975f5c5SAndroid Build Coastguard Worker     {
275*8975f5c5SAndroid Build Coastguard Worker         case EbtFloat:
276*8975f5c5SAndroid Build Coastguard Worker             return static_cast<float>(u) == fConst;
277*8975f5c5SAndroid Build Coastguard Worker         default:
278*8975f5c5SAndroid Build Coastguard Worker             return u == uConst;
279*8975f5c5SAndroid Build Coastguard Worker     }
280*8975f5c5SAndroid Build Coastguard Worker }
281*8975f5c5SAndroid Build Coastguard Worker 
operator ==(const float f) const282*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::operator==(const float f) const
283*8975f5c5SAndroid Build Coastguard Worker {
284*8975f5c5SAndroid Build Coastguard Worker     switch (type)
285*8975f5c5SAndroid Build Coastguard Worker     {
286*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
287*8975f5c5SAndroid Build Coastguard Worker             return f == static_cast<float>(iConst);
288*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
289*8975f5c5SAndroid Build Coastguard Worker             return f == static_cast<float>(uConst);
290*8975f5c5SAndroid Build Coastguard Worker         default:
291*8975f5c5SAndroid Build Coastguard Worker             return f == fConst;
292*8975f5c5SAndroid Build Coastguard Worker     }
293*8975f5c5SAndroid Build Coastguard Worker }
294*8975f5c5SAndroid Build Coastguard Worker 
operator ==(const bool b) const295*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::operator==(const bool b) const
296*8975f5c5SAndroid Build Coastguard Worker {
297*8975f5c5SAndroid Build Coastguard Worker     return b == bConst;
298*8975f5c5SAndroid Build Coastguard Worker }
299*8975f5c5SAndroid Build Coastguard Worker 
operator ==(const TYuvCscStandardEXT s) const300*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::operator==(const TYuvCscStandardEXT s) const
301*8975f5c5SAndroid Build Coastguard Worker {
302*8975f5c5SAndroid Build Coastguard Worker     return s == yuvCscStandardEXTConst;
303*8975f5c5SAndroid Build Coastguard Worker }
304*8975f5c5SAndroid Build Coastguard Worker 
operator ==(const TConstantUnion & constant) const305*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::operator==(const TConstantUnion &constant) const
306*8975f5c5SAndroid Build Coastguard Worker {
307*8975f5c5SAndroid Build Coastguard Worker     switch (type)
308*8975f5c5SAndroid Build Coastguard Worker     {
309*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
310*8975f5c5SAndroid Build Coastguard Worker             return constant.iConst == iConst;
311*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
312*8975f5c5SAndroid Build Coastguard Worker             return constant.uConst == uConst;
313*8975f5c5SAndroid Build Coastguard Worker         case EbtFloat:
314*8975f5c5SAndroid Build Coastguard Worker             return constant.fConst == fConst;
315*8975f5c5SAndroid Build Coastguard Worker         case EbtBool:
316*8975f5c5SAndroid Build Coastguard Worker             return constant.bConst == bConst;
317*8975f5c5SAndroid Build Coastguard Worker         case EbtYuvCscStandardEXT:
318*8975f5c5SAndroid Build Coastguard Worker             return constant.yuvCscStandardEXTConst == yuvCscStandardEXTConst;
319*8975f5c5SAndroid Build Coastguard Worker         default:
320*8975f5c5SAndroid Build Coastguard Worker             return false;
321*8975f5c5SAndroid Build Coastguard Worker     }
322*8975f5c5SAndroid Build Coastguard Worker }
323*8975f5c5SAndroid Build Coastguard Worker 
operator !=(const int i) const324*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::operator!=(const int i) const
325*8975f5c5SAndroid Build Coastguard Worker {
326*8975f5c5SAndroid Build Coastguard Worker     return !operator==(i);
327*8975f5c5SAndroid Build Coastguard Worker }
328*8975f5c5SAndroid Build Coastguard Worker 
operator !=(const unsigned int u) const329*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::operator!=(const unsigned int u) const
330*8975f5c5SAndroid Build Coastguard Worker {
331*8975f5c5SAndroid Build Coastguard Worker     return !operator==(u);
332*8975f5c5SAndroid Build Coastguard Worker }
333*8975f5c5SAndroid Build Coastguard Worker 
operator !=(const float f) const334*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::operator!=(const float f) const
335*8975f5c5SAndroid Build Coastguard Worker {
336*8975f5c5SAndroid Build Coastguard Worker     return !operator==(f);
337*8975f5c5SAndroid Build Coastguard Worker }
338*8975f5c5SAndroid Build Coastguard Worker 
operator !=(const bool b) const339*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::operator!=(const bool b) const
340*8975f5c5SAndroid Build Coastguard Worker {
341*8975f5c5SAndroid Build Coastguard Worker     return !operator==(b);
342*8975f5c5SAndroid Build Coastguard Worker }
343*8975f5c5SAndroid Build Coastguard Worker 
operator !=(const TYuvCscStandardEXT s) const344*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::operator!=(const TYuvCscStandardEXT s) const
345*8975f5c5SAndroid Build Coastguard Worker {
346*8975f5c5SAndroid Build Coastguard Worker     return !operator==(s);
347*8975f5c5SAndroid Build Coastguard Worker }
348*8975f5c5SAndroid Build Coastguard Worker 
operator !=(const TConstantUnion & constant) const349*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::operator!=(const TConstantUnion &constant) const
350*8975f5c5SAndroid Build Coastguard Worker {
351*8975f5c5SAndroid Build Coastguard Worker     return !operator==(constant);
352*8975f5c5SAndroid Build Coastguard Worker }
353*8975f5c5SAndroid Build Coastguard Worker 
operator >(const TConstantUnion & constant) const354*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::operator>(const TConstantUnion &constant) const
355*8975f5c5SAndroid Build Coastguard Worker {
356*8975f5c5SAndroid Build Coastguard Worker 
357*8975f5c5SAndroid Build Coastguard Worker     switch (type)
358*8975f5c5SAndroid Build Coastguard Worker     {
359*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
360*8975f5c5SAndroid Build Coastguard Worker             return iConst > constant.iConst;
361*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
362*8975f5c5SAndroid Build Coastguard Worker             return uConst > constant.uConst;
363*8975f5c5SAndroid Build Coastguard Worker         case EbtFloat:
364*8975f5c5SAndroid Build Coastguard Worker             return fConst > constant.fConst;
365*8975f5c5SAndroid Build Coastguard Worker         default:
366*8975f5c5SAndroid Build Coastguard Worker             return false;  // Invalid operation, handled at semantic analysis
367*8975f5c5SAndroid Build Coastguard Worker     }
368*8975f5c5SAndroid Build Coastguard Worker }
369*8975f5c5SAndroid Build Coastguard Worker 
operator <(const TConstantUnion & constant) const370*8975f5c5SAndroid Build Coastguard Worker bool TConstantUnion::operator<(const TConstantUnion &constant) const
371*8975f5c5SAndroid Build Coastguard Worker {
372*8975f5c5SAndroid Build Coastguard Worker     switch (type)
373*8975f5c5SAndroid Build Coastguard Worker     {
374*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
375*8975f5c5SAndroid Build Coastguard Worker             return iConst < constant.iConst;
376*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
377*8975f5c5SAndroid Build Coastguard Worker             return uConst < constant.uConst;
378*8975f5c5SAndroid Build Coastguard Worker         case EbtFloat:
379*8975f5c5SAndroid Build Coastguard Worker             return fConst < constant.fConst;
380*8975f5c5SAndroid Build Coastguard Worker         default:
381*8975f5c5SAndroid Build Coastguard Worker             return false;  // Invalid operation, handled at semantic analysis
382*8975f5c5SAndroid Build Coastguard Worker     }
383*8975f5c5SAndroid Build Coastguard Worker }
384*8975f5c5SAndroid Build Coastguard Worker 
385*8975f5c5SAndroid Build Coastguard Worker // static
add(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)386*8975f5c5SAndroid Build Coastguard Worker TConstantUnion TConstantUnion::add(const TConstantUnion &lhs,
387*8975f5c5SAndroid Build Coastguard Worker                                    const TConstantUnion &rhs,
388*8975f5c5SAndroid Build Coastguard Worker                                    TDiagnostics *diag,
389*8975f5c5SAndroid Build Coastguard Worker                                    const TSourceLoc &line)
390*8975f5c5SAndroid Build Coastguard Worker {
391*8975f5c5SAndroid Build Coastguard Worker     TConstantUnion returnValue;
392*8975f5c5SAndroid Build Coastguard Worker 
393*8975f5c5SAndroid Build Coastguard Worker     switch (lhs.type)
394*8975f5c5SAndroid Build Coastguard Worker     {
395*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
396*8975f5c5SAndroid Build Coastguard Worker             returnValue.setIConst(gl::WrappingSum<int>(lhs.iConst, rhs.iConst));
397*8975f5c5SAndroid Build Coastguard Worker             break;
398*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
399*8975f5c5SAndroid Build Coastguard Worker             returnValue.setUConst(gl::WrappingSum<unsigned int>(lhs.uConst, rhs.uConst));
400*8975f5c5SAndroid Build Coastguard Worker             break;
401*8975f5c5SAndroid Build Coastguard Worker         case EbtFloat:
402*8975f5c5SAndroid Build Coastguard Worker             returnValue.setFConst(CheckedSum(lhs.fConst, rhs.fConst, diag, line));
403*8975f5c5SAndroid Build Coastguard Worker             break;
404*8975f5c5SAndroid Build Coastguard Worker         default:
405*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
406*8975f5c5SAndroid Build Coastguard Worker     }
407*8975f5c5SAndroid Build Coastguard Worker 
408*8975f5c5SAndroid Build Coastguard Worker     return returnValue;
409*8975f5c5SAndroid Build Coastguard Worker }
410*8975f5c5SAndroid Build Coastguard Worker 
411*8975f5c5SAndroid Build Coastguard Worker // static
sub(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)412*8975f5c5SAndroid Build Coastguard Worker TConstantUnion TConstantUnion::sub(const TConstantUnion &lhs,
413*8975f5c5SAndroid Build Coastguard Worker                                    const TConstantUnion &rhs,
414*8975f5c5SAndroid Build Coastguard Worker                                    TDiagnostics *diag,
415*8975f5c5SAndroid Build Coastguard Worker                                    const TSourceLoc &line)
416*8975f5c5SAndroid Build Coastguard Worker {
417*8975f5c5SAndroid Build Coastguard Worker     TConstantUnion returnValue;
418*8975f5c5SAndroid Build Coastguard Worker 
419*8975f5c5SAndroid Build Coastguard Worker     switch (lhs.type)
420*8975f5c5SAndroid Build Coastguard Worker     {
421*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
422*8975f5c5SAndroid Build Coastguard Worker             returnValue.setIConst(gl::WrappingDiff<int>(lhs.iConst, rhs.iConst));
423*8975f5c5SAndroid Build Coastguard Worker             break;
424*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
425*8975f5c5SAndroid Build Coastguard Worker             returnValue.setUConst(gl::WrappingDiff<unsigned int>(lhs.uConst, rhs.uConst));
426*8975f5c5SAndroid Build Coastguard Worker             break;
427*8975f5c5SAndroid Build Coastguard Worker         case EbtFloat:
428*8975f5c5SAndroid Build Coastguard Worker             returnValue.setFConst(CheckedDiff(lhs.fConst, rhs.fConst, diag, line));
429*8975f5c5SAndroid Build Coastguard Worker             break;
430*8975f5c5SAndroid Build Coastguard Worker         default:
431*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
432*8975f5c5SAndroid Build Coastguard Worker     }
433*8975f5c5SAndroid Build Coastguard Worker 
434*8975f5c5SAndroid Build Coastguard Worker     return returnValue;
435*8975f5c5SAndroid Build Coastguard Worker }
436*8975f5c5SAndroid Build Coastguard Worker 
437*8975f5c5SAndroid Build Coastguard Worker // static
mul(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)438*8975f5c5SAndroid Build Coastguard Worker TConstantUnion TConstantUnion::mul(const TConstantUnion &lhs,
439*8975f5c5SAndroid Build Coastguard Worker                                    const TConstantUnion &rhs,
440*8975f5c5SAndroid Build Coastguard Worker                                    TDiagnostics *diag,
441*8975f5c5SAndroid Build Coastguard Worker                                    const TSourceLoc &line)
442*8975f5c5SAndroid Build Coastguard Worker {
443*8975f5c5SAndroid Build Coastguard Worker     TConstantUnion returnValue;
444*8975f5c5SAndroid Build Coastguard Worker 
445*8975f5c5SAndroid Build Coastguard Worker     switch (lhs.type)
446*8975f5c5SAndroid Build Coastguard Worker     {
447*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
448*8975f5c5SAndroid Build Coastguard Worker             returnValue.setIConst(gl::WrappingMul(lhs.iConst, rhs.iConst));
449*8975f5c5SAndroid Build Coastguard Worker             break;
450*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
451*8975f5c5SAndroid Build Coastguard Worker             // Unsigned integer math in C++ is defined to be done in modulo 2^n, so we rely
452*8975f5c5SAndroid Build Coastguard Worker             // on that to implement wrapping multiplication.
453*8975f5c5SAndroid Build Coastguard Worker             returnValue.setUConst(lhs.uConst * rhs.uConst);
454*8975f5c5SAndroid Build Coastguard Worker             break;
455*8975f5c5SAndroid Build Coastguard Worker         case EbtFloat:
456*8975f5c5SAndroid Build Coastguard Worker             returnValue.setFConst(CheckedMul(lhs.fConst, rhs.fConst, diag, line));
457*8975f5c5SAndroid Build Coastguard Worker             break;
458*8975f5c5SAndroid Build Coastguard Worker         default:
459*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
460*8975f5c5SAndroid Build Coastguard Worker     }
461*8975f5c5SAndroid Build Coastguard Worker 
462*8975f5c5SAndroid Build Coastguard Worker     return returnValue;
463*8975f5c5SAndroid Build Coastguard Worker }
464*8975f5c5SAndroid Build Coastguard Worker 
operator %(const TConstantUnion & constant) const465*8975f5c5SAndroid Build Coastguard Worker TConstantUnion TConstantUnion::operator%(const TConstantUnion &constant) const
466*8975f5c5SAndroid Build Coastguard Worker {
467*8975f5c5SAndroid Build Coastguard Worker     TConstantUnion returnValue;
468*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == constant.type);
469*8975f5c5SAndroid Build Coastguard Worker     switch (type)
470*8975f5c5SAndroid Build Coastguard Worker     {
471*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
472*8975f5c5SAndroid Build Coastguard Worker             returnValue.setIConst(iConst % constant.iConst);
473*8975f5c5SAndroid Build Coastguard Worker             break;
474*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
475*8975f5c5SAndroid Build Coastguard Worker             returnValue.setUConst(uConst % constant.uConst);
476*8975f5c5SAndroid Build Coastguard Worker             break;
477*8975f5c5SAndroid Build Coastguard Worker         default:
478*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
479*8975f5c5SAndroid Build Coastguard Worker     }
480*8975f5c5SAndroid Build Coastguard Worker 
481*8975f5c5SAndroid Build Coastguard Worker     return returnValue;
482*8975f5c5SAndroid Build Coastguard Worker }
483*8975f5c5SAndroid Build Coastguard Worker 
484*8975f5c5SAndroid Build Coastguard Worker // static
rshift(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)485*8975f5c5SAndroid Build Coastguard Worker TConstantUnion TConstantUnion::rshift(const TConstantUnion &lhs,
486*8975f5c5SAndroid Build Coastguard Worker                                       const TConstantUnion &rhs,
487*8975f5c5SAndroid Build Coastguard Worker                                       TDiagnostics *diag,
488*8975f5c5SAndroid Build Coastguard Worker                                       const TSourceLoc &line)
489*8975f5c5SAndroid Build Coastguard Worker {
490*8975f5c5SAndroid Build Coastguard Worker     TConstantUnion returnValue;
491*8975f5c5SAndroid Build Coastguard Worker     ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt);
492*8975f5c5SAndroid Build Coastguard Worker     ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt);
493*8975f5c5SAndroid Build Coastguard Worker     if (!IsValidShiftOffset(rhs))
494*8975f5c5SAndroid Build Coastguard Worker     {
495*8975f5c5SAndroid Build Coastguard Worker         diag->warning(line, "Undefined shift (operand out of range)", ">>");
496*8975f5c5SAndroid Build Coastguard Worker         switch (lhs.type)
497*8975f5c5SAndroid Build Coastguard Worker         {
498*8975f5c5SAndroid Build Coastguard Worker             case EbtInt:
499*8975f5c5SAndroid Build Coastguard Worker                 returnValue.setIConst(0);
500*8975f5c5SAndroid Build Coastguard Worker                 break;
501*8975f5c5SAndroid Build Coastguard Worker             case EbtUInt:
502*8975f5c5SAndroid Build Coastguard Worker                 returnValue.setUConst(0u);
503*8975f5c5SAndroid Build Coastguard Worker                 break;
504*8975f5c5SAndroid Build Coastguard Worker             default:
505*8975f5c5SAndroid Build Coastguard Worker                 UNREACHABLE();
506*8975f5c5SAndroid Build Coastguard Worker         }
507*8975f5c5SAndroid Build Coastguard Worker         return returnValue;
508*8975f5c5SAndroid Build Coastguard Worker     }
509*8975f5c5SAndroid Build Coastguard Worker 
510*8975f5c5SAndroid Build Coastguard Worker     switch (lhs.type)
511*8975f5c5SAndroid Build Coastguard Worker     {
512*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
513*8975f5c5SAndroid Build Coastguard Worker         {
514*8975f5c5SAndroid Build Coastguard Worker             unsigned int shiftOffset = 0;
515*8975f5c5SAndroid Build Coastguard Worker             switch (rhs.type)
516*8975f5c5SAndroid Build Coastguard Worker             {
517*8975f5c5SAndroid Build Coastguard Worker                 case EbtInt:
518*8975f5c5SAndroid Build Coastguard Worker                     shiftOffset = static_cast<unsigned int>(rhs.iConst);
519*8975f5c5SAndroid Build Coastguard Worker                     break;
520*8975f5c5SAndroid Build Coastguard Worker                 case EbtUInt:
521*8975f5c5SAndroid Build Coastguard Worker                     shiftOffset = rhs.uConst;
522*8975f5c5SAndroid Build Coastguard Worker                     break;
523*8975f5c5SAndroid Build Coastguard Worker                 default:
524*8975f5c5SAndroid Build Coastguard Worker                     UNREACHABLE();
525*8975f5c5SAndroid Build Coastguard Worker             }
526*8975f5c5SAndroid Build Coastguard Worker             if (shiftOffset > 0)
527*8975f5c5SAndroid Build Coastguard Worker             {
528*8975f5c5SAndroid Build Coastguard Worker                 // ESSL 3.00.6 section 5.9: "If E1 is a signed integer, the right-shift will extend
529*8975f5c5SAndroid Build Coastguard Worker                 // the sign bit." In C++ shifting negative integers is undefined, so we implement
530*8975f5c5SAndroid Build Coastguard Worker                 // extending the sign bit manually.
531*8975f5c5SAndroid Build Coastguard Worker                 int lhsSafe = lhs.iConst;
532*8975f5c5SAndroid Build Coastguard Worker                 if (lhsSafe == std::numeric_limits<int>::min())
533*8975f5c5SAndroid Build Coastguard Worker                 {
534*8975f5c5SAndroid Build Coastguard Worker                     // The min integer needs special treatment because only bit it has set is the
535*8975f5c5SAndroid Build Coastguard Worker                     // sign bit, which we clear later to implement safe right shift of negative
536*8975f5c5SAndroid Build Coastguard Worker                     // numbers.
537*8975f5c5SAndroid Build Coastguard Worker                     lhsSafe = -0x40000000;
538*8975f5c5SAndroid Build Coastguard Worker                     --shiftOffset;
539*8975f5c5SAndroid Build Coastguard Worker                 }
540*8975f5c5SAndroid Build Coastguard Worker                 if (shiftOffset > 0)
541*8975f5c5SAndroid Build Coastguard Worker                 {
542*8975f5c5SAndroid Build Coastguard Worker                     bool extendSignBit = false;
543*8975f5c5SAndroid Build Coastguard Worker                     if (lhsSafe < 0)
544*8975f5c5SAndroid Build Coastguard Worker                     {
545*8975f5c5SAndroid Build Coastguard Worker                         extendSignBit = true;
546*8975f5c5SAndroid Build Coastguard Worker                         // Clear the sign bit so that bitshift right is defined in C++.
547*8975f5c5SAndroid Build Coastguard Worker                         lhsSafe &= 0x7fffffff;
548*8975f5c5SAndroid Build Coastguard Worker                         ASSERT(lhsSafe > 0);
549*8975f5c5SAndroid Build Coastguard Worker                     }
550*8975f5c5SAndroid Build Coastguard Worker                     returnValue.setIConst(lhsSafe >> shiftOffset);
551*8975f5c5SAndroid Build Coastguard Worker 
552*8975f5c5SAndroid Build Coastguard Worker                     // Manually fill in the extended sign bit if necessary.
553*8975f5c5SAndroid Build Coastguard Worker                     if (extendSignBit)
554*8975f5c5SAndroid Build Coastguard Worker                     {
555*8975f5c5SAndroid Build Coastguard Worker                         int extendedSignBit = static_cast<int>(0xffffffffu << (31 - shiftOffset));
556*8975f5c5SAndroid Build Coastguard Worker                         returnValue.setIConst(returnValue.getIConst() | extendedSignBit);
557*8975f5c5SAndroid Build Coastguard Worker                     }
558*8975f5c5SAndroid Build Coastguard Worker                 }
559*8975f5c5SAndroid Build Coastguard Worker                 else
560*8975f5c5SAndroid Build Coastguard Worker                 {
561*8975f5c5SAndroid Build Coastguard Worker                     returnValue.setIConst(lhsSafe);
562*8975f5c5SAndroid Build Coastguard Worker                 }
563*8975f5c5SAndroid Build Coastguard Worker             }
564*8975f5c5SAndroid Build Coastguard Worker             else
565*8975f5c5SAndroid Build Coastguard Worker             {
566*8975f5c5SAndroid Build Coastguard Worker                 returnValue.setIConst(lhs.iConst);
567*8975f5c5SAndroid Build Coastguard Worker             }
568*8975f5c5SAndroid Build Coastguard Worker             break;
569*8975f5c5SAndroid Build Coastguard Worker         }
570*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
571*8975f5c5SAndroid Build Coastguard Worker             switch (rhs.type)
572*8975f5c5SAndroid Build Coastguard Worker             {
573*8975f5c5SAndroid Build Coastguard Worker                 case EbtInt:
574*8975f5c5SAndroid Build Coastguard Worker                     returnValue.setUConst(lhs.uConst >> rhs.iConst);
575*8975f5c5SAndroid Build Coastguard Worker                     break;
576*8975f5c5SAndroid Build Coastguard Worker                 case EbtUInt:
577*8975f5c5SAndroid Build Coastguard Worker                     returnValue.setUConst(lhs.uConst >> rhs.uConst);
578*8975f5c5SAndroid Build Coastguard Worker                     break;
579*8975f5c5SAndroid Build Coastguard Worker                 default:
580*8975f5c5SAndroid Build Coastguard Worker                     UNREACHABLE();
581*8975f5c5SAndroid Build Coastguard Worker             }
582*8975f5c5SAndroid Build Coastguard Worker             break;
583*8975f5c5SAndroid Build Coastguard Worker 
584*8975f5c5SAndroid Build Coastguard Worker         default:
585*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
586*8975f5c5SAndroid Build Coastguard Worker     }
587*8975f5c5SAndroid Build Coastguard Worker     return returnValue;
588*8975f5c5SAndroid Build Coastguard Worker }
589*8975f5c5SAndroid Build Coastguard Worker 
590*8975f5c5SAndroid Build Coastguard Worker // static
lshift(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)591*8975f5c5SAndroid Build Coastguard Worker TConstantUnion TConstantUnion::lshift(const TConstantUnion &lhs,
592*8975f5c5SAndroid Build Coastguard Worker                                       const TConstantUnion &rhs,
593*8975f5c5SAndroid Build Coastguard Worker                                       TDiagnostics *diag,
594*8975f5c5SAndroid Build Coastguard Worker                                       const TSourceLoc &line)
595*8975f5c5SAndroid Build Coastguard Worker {
596*8975f5c5SAndroid Build Coastguard Worker     TConstantUnion returnValue;
597*8975f5c5SAndroid Build Coastguard Worker     ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt);
598*8975f5c5SAndroid Build Coastguard Worker     ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt);
599*8975f5c5SAndroid Build Coastguard Worker     if (!IsValidShiftOffset(rhs))
600*8975f5c5SAndroid Build Coastguard Worker     {
601*8975f5c5SAndroid Build Coastguard Worker         diag->warning(line, "Undefined shift (operand out of range)", "<<");
602*8975f5c5SAndroid Build Coastguard Worker         switch (lhs.type)
603*8975f5c5SAndroid Build Coastguard Worker         {
604*8975f5c5SAndroid Build Coastguard Worker             case EbtInt:
605*8975f5c5SAndroid Build Coastguard Worker                 returnValue.setIConst(0);
606*8975f5c5SAndroid Build Coastguard Worker                 break;
607*8975f5c5SAndroid Build Coastguard Worker             case EbtUInt:
608*8975f5c5SAndroid Build Coastguard Worker                 returnValue.setUConst(0u);
609*8975f5c5SAndroid Build Coastguard Worker                 break;
610*8975f5c5SAndroid Build Coastguard Worker             default:
611*8975f5c5SAndroid Build Coastguard Worker                 UNREACHABLE();
612*8975f5c5SAndroid Build Coastguard Worker         }
613*8975f5c5SAndroid Build Coastguard Worker         return returnValue;
614*8975f5c5SAndroid Build Coastguard Worker     }
615*8975f5c5SAndroid Build Coastguard Worker 
616*8975f5c5SAndroid Build Coastguard Worker     switch (lhs.type)
617*8975f5c5SAndroid Build Coastguard Worker     {
618*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
619*8975f5c5SAndroid Build Coastguard Worker             switch (rhs.type)
620*8975f5c5SAndroid Build Coastguard Worker             {
621*8975f5c5SAndroid Build Coastguard Worker                 // Cast to unsigned integer before shifting, since ESSL 3.00.6 section 5.9 says that
622*8975f5c5SAndroid Build Coastguard Worker                 // lhs is "interpreted as a bit pattern". This also avoids the possibility of signed
623*8975f5c5SAndroid Build Coastguard Worker                 // integer overflow or undefined shift of a negative integer.
624*8975f5c5SAndroid Build Coastguard Worker                 case EbtInt:
625*8975f5c5SAndroid Build Coastguard Worker                     returnValue.setIConst(
626*8975f5c5SAndroid Build Coastguard Worker                         static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.iConst));
627*8975f5c5SAndroid Build Coastguard Worker                     break;
628*8975f5c5SAndroid Build Coastguard Worker                 case EbtUInt:
629*8975f5c5SAndroid Build Coastguard Worker                     returnValue.setIConst(
630*8975f5c5SAndroid Build Coastguard Worker                         static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.uConst));
631*8975f5c5SAndroid Build Coastguard Worker                     break;
632*8975f5c5SAndroid Build Coastguard Worker                 default:
633*8975f5c5SAndroid Build Coastguard Worker                     UNREACHABLE();
634*8975f5c5SAndroid Build Coastguard Worker             }
635*8975f5c5SAndroid Build Coastguard Worker             break;
636*8975f5c5SAndroid Build Coastguard Worker 
637*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
638*8975f5c5SAndroid Build Coastguard Worker             switch (rhs.type)
639*8975f5c5SAndroid Build Coastguard Worker             {
640*8975f5c5SAndroid Build Coastguard Worker                 case EbtInt:
641*8975f5c5SAndroid Build Coastguard Worker                     returnValue.setUConst(lhs.uConst << rhs.iConst);
642*8975f5c5SAndroid Build Coastguard Worker                     break;
643*8975f5c5SAndroid Build Coastguard Worker                 case EbtUInt:
644*8975f5c5SAndroid Build Coastguard Worker                     returnValue.setUConst(lhs.uConst << rhs.uConst);
645*8975f5c5SAndroid Build Coastguard Worker                     break;
646*8975f5c5SAndroid Build Coastguard Worker                 default:
647*8975f5c5SAndroid Build Coastguard Worker                     UNREACHABLE();
648*8975f5c5SAndroid Build Coastguard Worker             }
649*8975f5c5SAndroid Build Coastguard Worker             break;
650*8975f5c5SAndroid Build Coastguard Worker 
651*8975f5c5SAndroid Build Coastguard Worker         default:
652*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
653*8975f5c5SAndroid Build Coastguard Worker     }
654*8975f5c5SAndroid Build Coastguard Worker     return returnValue;
655*8975f5c5SAndroid Build Coastguard Worker }
656*8975f5c5SAndroid Build Coastguard Worker 
operator &(const TConstantUnion & constant) const657*8975f5c5SAndroid Build Coastguard Worker TConstantUnion TConstantUnion::operator&(const TConstantUnion &constant) const
658*8975f5c5SAndroid Build Coastguard Worker {
659*8975f5c5SAndroid Build Coastguard Worker     TConstantUnion returnValue;
660*8975f5c5SAndroid Build Coastguard Worker     ASSERT(constant.type == EbtInt || constant.type == EbtUInt);
661*8975f5c5SAndroid Build Coastguard Worker     switch (type)
662*8975f5c5SAndroid Build Coastguard Worker     {
663*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
664*8975f5c5SAndroid Build Coastguard Worker             returnValue.setIConst(iConst & constant.iConst);
665*8975f5c5SAndroid Build Coastguard Worker             break;
666*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
667*8975f5c5SAndroid Build Coastguard Worker             returnValue.setUConst(uConst & constant.uConst);
668*8975f5c5SAndroid Build Coastguard Worker             break;
669*8975f5c5SAndroid Build Coastguard Worker         default:
670*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
671*8975f5c5SAndroid Build Coastguard Worker     }
672*8975f5c5SAndroid Build Coastguard Worker 
673*8975f5c5SAndroid Build Coastguard Worker     return returnValue;
674*8975f5c5SAndroid Build Coastguard Worker }
675*8975f5c5SAndroid Build Coastguard Worker 
operator |(const TConstantUnion & constant) const676*8975f5c5SAndroid Build Coastguard Worker TConstantUnion TConstantUnion::operator|(const TConstantUnion &constant) const
677*8975f5c5SAndroid Build Coastguard Worker {
678*8975f5c5SAndroid Build Coastguard Worker     TConstantUnion returnValue;
679*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == constant.type);
680*8975f5c5SAndroid Build Coastguard Worker     switch (type)
681*8975f5c5SAndroid Build Coastguard Worker     {
682*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
683*8975f5c5SAndroid Build Coastguard Worker             returnValue.setIConst(iConst | constant.iConst);
684*8975f5c5SAndroid Build Coastguard Worker             break;
685*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
686*8975f5c5SAndroid Build Coastguard Worker             returnValue.setUConst(uConst | constant.uConst);
687*8975f5c5SAndroid Build Coastguard Worker             break;
688*8975f5c5SAndroid Build Coastguard Worker         default:
689*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
690*8975f5c5SAndroid Build Coastguard Worker     }
691*8975f5c5SAndroid Build Coastguard Worker 
692*8975f5c5SAndroid Build Coastguard Worker     return returnValue;
693*8975f5c5SAndroid Build Coastguard Worker }
694*8975f5c5SAndroid Build Coastguard Worker 
operator ^(const TConstantUnion & constant) const695*8975f5c5SAndroid Build Coastguard Worker TConstantUnion TConstantUnion::operator^(const TConstantUnion &constant) const
696*8975f5c5SAndroid Build Coastguard Worker {
697*8975f5c5SAndroid Build Coastguard Worker     TConstantUnion returnValue;
698*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == constant.type);
699*8975f5c5SAndroid Build Coastguard Worker     switch (type)
700*8975f5c5SAndroid Build Coastguard Worker     {
701*8975f5c5SAndroid Build Coastguard Worker         case EbtInt:
702*8975f5c5SAndroid Build Coastguard Worker             returnValue.setIConst(iConst ^ constant.iConst);
703*8975f5c5SAndroid Build Coastguard Worker             break;
704*8975f5c5SAndroid Build Coastguard Worker         case EbtUInt:
705*8975f5c5SAndroid Build Coastguard Worker             returnValue.setUConst(uConst ^ constant.uConst);
706*8975f5c5SAndroid Build Coastguard Worker             break;
707*8975f5c5SAndroid Build Coastguard Worker         default:
708*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
709*8975f5c5SAndroid Build Coastguard Worker     }
710*8975f5c5SAndroid Build Coastguard Worker 
711*8975f5c5SAndroid Build Coastguard Worker     return returnValue;
712*8975f5c5SAndroid Build Coastguard Worker }
713*8975f5c5SAndroid Build Coastguard Worker 
operator &&(const TConstantUnion & constant) const714*8975f5c5SAndroid Build Coastguard Worker TConstantUnion TConstantUnion::operator&&(const TConstantUnion &constant) const
715*8975f5c5SAndroid Build Coastguard Worker {
716*8975f5c5SAndroid Build Coastguard Worker     TConstantUnion returnValue;
717*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == constant.type);
718*8975f5c5SAndroid Build Coastguard Worker     switch (type)
719*8975f5c5SAndroid Build Coastguard Worker     {
720*8975f5c5SAndroid Build Coastguard Worker         case EbtBool:
721*8975f5c5SAndroid Build Coastguard Worker             returnValue.setBConst(bConst && constant.bConst);
722*8975f5c5SAndroid Build Coastguard Worker             break;
723*8975f5c5SAndroid Build Coastguard Worker         default:
724*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
725*8975f5c5SAndroid Build Coastguard Worker     }
726*8975f5c5SAndroid Build Coastguard Worker 
727*8975f5c5SAndroid Build Coastguard Worker     return returnValue;
728*8975f5c5SAndroid Build Coastguard Worker }
729*8975f5c5SAndroid Build Coastguard Worker 
operator ||(const TConstantUnion & constant) const730*8975f5c5SAndroid Build Coastguard Worker TConstantUnion TConstantUnion::operator||(const TConstantUnion &constant) const
731*8975f5c5SAndroid Build Coastguard Worker {
732*8975f5c5SAndroid Build Coastguard Worker     TConstantUnion returnValue;
733*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == constant.type);
734*8975f5c5SAndroid Build Coastguard Worker     switch (type)
735*8975f5c5SAndroid Build Coastguard Worker     {
736*8975f5c5SAndroid Build Coastguard Worker         case EbtBool:
737*8975f5c5SAndroid Build Coastguard Worker             returnValue.setBConst(bConst || constant.bConst);
738*8975f5c5SAndroid Build Coastguard Worker             break;
739*8975f5c5SAndroid Build Coastguard Worker         default:
740*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
741*8975f5c5SAndroid Build Coastguard Worker     }
742*8975f5c5SAndroid Build Coastguard Worker 
743*8975f5c5SAndroid Build Coastguard Worker     return returnValue;
744*8975f5c5SAndroid Build Coastguard Worker }
745*8975f5c5SAndroid Build Coastguard Worker 
746*8975f5c5SAndroid Build Coastguard Worker }  // namespace sh
747