1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2002 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
7*8975f5c5SAndroid Build Coastguard Worker //
8*8975f5c5SAndroid Build Coastguard Worker // Build the intermediate representation.
9*8975f5c5SAndroid Build Coastguard Worker //
10*8975f5c5SAndroid Build Coastguard Worker
11*8975f5c5SAndroid Build Coastguard Worker #include <float.h>
12*8975f5c5SAndroid Build Coastguard Worker #include <limits.h>
13*8975f5c5SAndroid Build Coastguard Worker #include <math.h>
14*8975f5c5SAndroid Build Coastguard Worker #include <stdlib.h>
15*8975f5c5SAndroid Build Coastguard Worker #include <algorithm>
16*8975f5c5SAndroid Build Coastguard Worker #include <vector>
17*8975f5c5SAndroid Build Coastguard Worker
18*8975f5c5SAndroid Build Coastguard Worker #include "common/mathutil.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "common/matrix_utils.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/Diagnostics.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/ImmutableString.h"
23*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/IntermNode.h"
24*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/SymbolTable.h"
25*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/util.h"
26*8975f5c5SAndroid Build Coastguard Worker
27*8975f5c5SAndroid Build Coastguard Worker namespace sh
28*8975f5c5SAndroid Build Coastguard Worker {
29*8975f5c5SAndroid Build Coastguard Worker
30*8975f5c5SAndroid Build Coastguard Worker namespace
31*8975f5c5SAndroid Build Coastguard Worker {
32*8975f5c5SAndroid Build Coastguard Worker
33*8975f5c5SAndroid Build Coastguard Worker const float kPi = 3.14159265358979323846f;
34*8975f5c5SAndroid Build Coastguard Worker const float kDegreesToRadiansMultiplier = kPi / 180.0f;
35*8975f5c5SAndroid Build Coastguard Worker const float kRadiansToDegreesMultiplier = 180.0f / kPi;
36*8975f5c5SAndroid Build Coastguard Worker
GetHigherPrecision(TPrecision left,TPrecision right)37*8975f5c5SAndroid Build Coastguard Worker TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
38*8975f5c5SAndroid Build Coastguard Worker {
39*8975f5c5SAndroid Build Coastguard Worker return left > right ? left : right;
40*8975f5c5SAndroid Build Coastguard Worker }
41*8975f5c5SAndroid Build Coastguard Worker
Vectorize(const TConstantUnion & constant,size_t size)42*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size)
43*8975f5c5SAndroid Build Coastguard Worker {
44*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *constUnion = new TConstantUnion[size];
45*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < size; ++i)
46*8975f5c5SAndroid Build Coastguard Worker constUnion[i] = constant;
47*8975f5c5SAndroid Build Coastguard Worker
48*8975f5c5SAndroid Build Coastguard Worker return constUnion;
49*8975f5c5SAndroid Build Coastguard Worker }
50*8975f5c5SAndroid Build Coastguard Worker
UndefinedConstantFoldingError(const TSourceLoc & loc,const TFunction * function,TBasicType basicType,TDiagnostics * diagnostics,TConstantUnion * result)51*8975f5c5SAndroid Build Coastguard Worker void UndefinedConstantFoldingError(const TSourceLoc &loc,
52*8975f5c5SAndroid Build Coastguard Worker const TFunction *function,
53*8975f5c5SAndroid Build Coastguard Worker TBasicType basicType,
54*8975f5c5SAndroid Build Coastguard Worker TDiagnostics *diagnostics,
55*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *result)
56*8975f5c5SAndroid Build Coastguard Worker {
57*8975f5c5SAndroid Build Coastguard Worker diagnostics->warning(loc, "operation result is undefined for the values passed in",
58*8975f5c5SAndroid Build Coastguard Worker function->name().data());
59*8975f5c5SAndroid Build Coastguard Worker
60*8975f5c5SAndroid Build Coastguard Worker switch (basicType)
61*8975f5c5SAndroid Build Coastguard Worker {
62*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
63*8975f5c5SAndroid Build Coastguard Worker result->setFConst(0.0f);
64*8975f5c5SAndroid Build Coastguard Worker break;
65*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
66*8975f5c5SAndroid Build Coastguard Worker result->setIConst(0);
67*8975f5c5SAndroid Build Coastguard Worker break;
68*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
69*8975f5c5SAndroid Build Coastguard Worker result->setUConst(0u);
70*8975f5c5SAndroid Build Coastguard Worker break;
71*8975f5c5SAndroid Build Coastguard Worker case EbtBool:
72*8975f5c5SAndroid Build Coastguard Worker result->setBConst(false);
73*8975f5c5SAndroid Build Coastguard Worker break;
74*8975f5c5SAndroid Build Coastguard Worker default:
75*8975f5c5SAndroid Build Coastguard Worker break;
76*8975f5c5SAndroid Build Coastguard Worker }
77*8975f5c5SAndroid Build Coastguard Worker }
78*8975f5c5SAndroid Build Coastguard Worker
VectorLength(const TConstantUnion * paramArray,size_t paramArraySize)79*8975f5c5SAndroid Build Coastguard Worker float VectorLength(const TConstantUnion *paramArray, size_t paramArraySize)
80*8975f5c5SAndroid Build Coastguard Worker {
81*8975f5c5SAndroid Build Coastguard Worker float result = 0.0f;
82*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < paramArraySize; i++)
83*8975f5c5SAndroid Build Coastguard Worker {
84*8975f5c5SAndroid Build Coastguard Worker float f = paramArray[i].getFConst();
85*8975f5c5SAndroid Build Coastguard Worker result += f * f;
86*8975f5c5SAndroid Build Coastguard Worker }
87*8975f5c5SAndroid Build Coastguard Worker return sqrtf(result);
88*8975f5c5SAndroid Build Coastguard Worker }
89*8975f5c5SAndroid Build Coastguard Worker
VectorDotProduct(const TConstantUnion * paramArray1,const TConstantUnion * paramArray2,size_t paramArraySize)90*8975f5c5SAndroid Build Coastguard Worker float VectorDotProduct(const TConstantUnion *paramArray1,
91*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *paramArray2,
92*8975f5c5SAndroid Build Coastguard Worker size_t paramArraySize)
93*8975f5c5SAndroid Build Coastguard Worker {
94*8975f5c5SAndroid Build Coastguard Worker float result = 0.0f;
95*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < paramArraySize; i++)
96*8975f5c5SAndroid Build Coastguard Worker result += paramArray1[i].getFConst() * paramArray2[i].getFConst();
97*8975f5c5SAndroid Build Coastguard Worker return result;
98*8975f5c5SAndroid Build Coastguard Worker }
99*8975f5c5SAndroid Build Coastguard Worker
CreateFoldedNode(const TConstantUnion * constArray,const TIntermTyped * originalNode)100*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *CreateFoldedNode(const TConstantUnion *constArray, const TIntermTyped *originalNode)
101*8975f5c5SAndroid Build Coastguard Worker {
102*8975f5c5SAndroid Build Coastguard Worker ASSERT(constArray != nullptr);
103*8975f5c5SAndroid Build Coastguard Worker // Note that we inherit whatever qualifier the folded node had. Nodes may be constant folded
104*8975f5c5SAndroid Build Coastguard Worker // without being qualified as constant.
105*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *folded = new TIntermConstantUnion(constArray, originalNode->getType());
106*8975f5c5SAndroid Build Coastguard Worker folded->setLine(originalNode->getLine());
107*8975f5c5SAndroid Build Coastguard Worker return folded;
108*8975f5c5SAndroid Build Coastguard Worker }
109*8975f5c5SAndroid Build Coastguard Worker
GetMatrix(const TConstantUnion * paramArray,const unsigned int rows,const unsigned int cols)110*8975f5c5SAndroid Build Coastguard Worker angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray,
111*8975f5c5SAndroid Build Coastguard Worker const unsigned int rows,
112*8975f5c5SAndroid Build Coastguard Worker const unsigned int cols)
113*8975f5c5SAndroid Build Coastguard Worker {
114*8975f5c5SAndroid Build Coastguard Worker std::vector<float> elements;
115*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < rows * cols; i++)
116*8975f5c5SAndroid Build Coastguard Worker elements.push_back(paramArray[i].getFConst());
117*8975f5c5SAndroid Build Coastguard Worker // Transpose is used since the Matrix constructor expects arguments in row-major order,
118*8975f5c5SAndroid Build Coastguard Worker // whereas the paramArray is in column-major order. Rows/cols parameters are also flipped below
119*8975f5c5SAndroid Build Coastguard Worker // so that the created matrix will have the expected dimensions after the transpose.
120*8975f5c5SAndroid Build Coastguard Worker return angle::Matrix<float>(elements, cols, rows).transpose();
121*8975f5c5SAndroid Build Coastguard Worker }
122*8975f5c5SAndroid Build Coastguard Worker
GetMatrix(const TConstantUnion * paramArray,const unsigned int size)123*8975f5c5SAndroid Build Coastguard Worker angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray, const unsigned int size)
124*8975f5c5SAndroid Build Coastguard Worker {
125*8975f5c5SAndroid Build Coastguard Worker std::vector<float> elements;
126*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < size * size; i++)
127*8975f5c5SAndroid Build Coastguard Worker elements.push_back(paramArray[i].getFConst());
128*8975f5c5SAndroid Build Coastguard Worker // Transpose is used since the Matrix constructor expects arguments in row-major order,
129*8975f5c5SAndroid Build Coastguard Worker // whereas the paramArray is in column-major order.
130*8975f5c5SAndroid Build Coastguard Worker return angle::Matrix<float>(elements, size).transpose();
131*8975f5c5SAndroid Build Coastguard Worker }
132*8975f5c5SAndroid Build Coastguard Worker
SetUnionArrayFromMatrix(const angle::Matrix<float> & m,TConstantUnion * resultArray)133*8975f5c5SAndroid Build Coastguard Worker void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resultArray)
134*8975f5c5SAndroid Build Coastguard Worker {
135*8975f5c5SAndroid Build Coastguard Worker // Transpose is used since the input Matrix is in row-major order,
136*8975f5c5SAndroid Build Coastguard Worker // whereas the actual result should be in column-major order.
137*8975f5c5SAndroid Build Coastguard Worker angle::Matrix<float> result = m.transpose();
138*8975f5c5SAndroid Build Coastguard Worker std::vector<float> resultElements = result.elements();
139*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < resultElements.size(); i++)
140*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(resultElements[i]);
141*8975f5c5SAndroid Build Coastguard Worker }
142*8975f5c5SAndroid Build Coastguard Worker
CanFoldAggregateBuiltInOp(TOperator op)143*8975f5c5SAndroid Build Coastguard Worker bool CanFoldAggregateBuiltInOp(TOperator op)
144*8975f5c5SAndroid Build Coastguard Worker {
145*8975f5c5SAndroid Build Coastguard Worker switch (op)
146*8975f5c5SAndroid Build Coastguard Worker {
147*8975f5c5SAndroid Build Coastguard Worker case EOpAtan:
148*8975f5c5SAndroid Build Coastguard Worker case EOpPow:
149*8975f5c5SAndroid Build Coastguard Worker case EOpMod:
150*8975f5c5SAndroid Build Coastguard Worker case EOpMin:
151*8975f5c5SAndroid Build Coastguard Worker case EOpMax:
152*8975f5c5SAndroid Build Coastguard Worker case EOpClamp:
153*8975f5c5SAndroid Build Coastguard Worker case EOpMix:
154*8975f5c5SAndroid Build Coastguard Worker case EOpStep:
155*8975f5c5SAndroid Build Coastguard Worker case EOpSmoothstep:
156*8975f5c5SAndroid Build Coastguard Worker case EOpFma:
157*8975f5c5SAndroid Build Coastguard Worker case EOpLdexp:
158*8975f5c5SAndroid Build Coastguard Worker case EOpMatrixCompMult:
159*8975f5c5SAndroid Build Coastguard Worker case EOpOuterProduct:
160*8975f5c5SAndroid Build Coastguard Worker case EOpEqualComponentWise:
161*8975f5c5SAndroid Build Coastguard Worker case EOpNotEqualComponentWise:
162*8975f5c5SAndroid Build Coastguard Worker case EOpLessThanComponentWise:
163*8975f5c5SAndroid Build Coastguard Worker case EOpLessThanEqualComponentWise:
164*8975f5c5SAndroid Build Coastguard Worker case EOpGreaterThanComponentWise:
165*8975f5c5SAndroid Build Coastguard Worker case EOpGreaterThanEqualComponentWise:
166*8975f5c5SAndroid Build Coastguard Worker case EOpDistance:
167*8975f5c5SAndroid Build Coastguard Worker case EOpDot:
168*8975f5c5SAndroid Build Coastguard Worker case EOpCross:
169*8975f5c5SAndroid Build Coastguard Worker case EOpFaceforward:
170*8975f5c5SAndroid Build Coastguard Worker case EOpReflect:
171*8975f5c5SAndroid Build Coastguard Worker case EOpRefract:
172*8975f5c5SAndroid Build Coastguard Worker case EOpBitfieldExtract:
173*8975f5c5SAndroid Build Coastguard Worker case EOpBitfieldInsert:
174*8975f5c5SAndroid Build Coastguard Worker case EOpDFdx:
175*8975f5c5SAndroid Build Coastguard Worker case EOpDFdy:
176*8975f5c5SAndroid Build Coastguard Worker case EOpFwidth:
177*8975f5c5SAndroid Build Coastguard Worker return true;
178*8975f5c5SAndroid Build Coastguard Worker default:
179*8975f5c5SAndroid Build Coastguard Worker return false;
180*8975f5c5SAndroid Build Coastguard Worker }
181*8975f5c5SAndroid Build Coastguard Worker }
182*8975f5c5SAndroid Build Coastguard Worker
PropagatePrecisionIfApplicable(TIntermTyped * node,TPrecision precision)183*8975f5c5SAndroid Build Coastguard Worker void PropagatePrecisionIfApplicable(TIntermTyped *node, TPrecision precision)
184*8975f5c5SAndroid Build Coastguard Worker {
185*8975f5c5SAndroid Build Coastguard Worker if (precision == EbpUndefined || node->getPrecision() != EbpUndefined)
186*8975f5c5SAndroid Build Coastguard Worker {
187*8975f5c5SAndroid Build Coastguard Worker return;
188*8975f5c5SAndroid Build Coastguard Worker }
189*8975f5c5SAndroid Build Coastguard Worker
190*8975f5c5SAndroid Build Coastguard Worker if (IsPrecisionApplicableToType(node->getBasicType()))
191*8975f5c5SAndroid Build Coastguard Worker {
192*8975f5c5SAndroid Build Coastguard Worker node->propagatePrecision(precision);
193*8975f5c5SAndroid Build Coastguard Worker }
194*8975f5c5SAndroid Build Coastguard Worker }
195*8975f5c5SAndroid Build Coastguard Worker
196*8975f5c5SAndroid Build Coastguard Worker } // namespace
197*8975f5c5SAndroid Build Coastguard Worker
198*8975f5c5SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////
199*8975f5c5SAndroid Build Coastguard Worker //
200*8975f5c5SAndroid Build Coastguard Worker // Member functions of the nodes used for building the tree.
201*8975f5c5SAndroid Build Coastguard Worker //
202*8975f5c5SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////
203*8975f5c5SAndroid Build Coastguard Worker
TIntermExpression(const TType & t)204*8975f5c5SAndroid Build Coastguard Worker TIntermExpression::TIntermExpression(const TType &t) : TIntermTyped(), mType(t) {}
205*8975f5c5SAndroid Build Coastguard Worker
206*8975f5c5SAndroid Build Coastguard Worker #define REPLACE_IF_IS(node, conversionFunc, original, replacement) \
207*8975f5c5SAndroid Build Coastguard Worker do \
208*8975f5c5SAndroid Build Coastguard Worker { \
209*8975f5c5SAndroid Build Coastguard Worker if (node == original) \
210*8975f5c5SAndroid Build Coastguard Worker { \
211*8975f5c5SAndroid Build Coastguard Worker if (replacement == nullptr) \
212*8975f5c5SAndroid Build Coastguard Worker { \
213*8975f5c5SAndroid Build Coastguard Worker node = nullptr; \
214*8975f5c5SAndroid Build Coastguard Worker } \
215*8975f5c5SAndroid Build Coastguard Worker else \
216*8975f5c5SAndroid Build Coastguard Worker { \
217*8975f5c5SAndroid Build Coastguard Worker auto replacementCasted = replacement->conversionFunc(); \
218*8975f5c5SAndroid Build Coastguard Worker if (replacementCasted == nullptr) \
219*8975f5c5SAndroid Build Coastguard Worker { \
220*8975f5c5SAndroid Build Coastguard Worker FATAL() << "Replacing a node with a node of invalid type: calling " \
221*8975f5c5SAndroid Build Coastguard Worker "replacement." #conversionFunc "() should not return nullptr."; \
222*8975f5c5SAndroid Build Coastguard Worker return false; \
223*8975f5c5SAndroid Build Coastguard Worker } \
224*8975f5c5SAndroid Build Coastguard Worker node = replacementCasted; \
225*8975f5c5SAndroid Build Coastguard Worker } \
226*8975f5c5SAndroid Build Coastguard Worker return true; \
227*8975f5c5SAndroid Build Coastguard Worker } \
228*8975f5c5SAndroid Build Coastguard Worker } while (0)
229*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const230*8975f5c5SAndroid Build Coastguard Worker size_t TIntermSymbol::getChildCount() const
231*8975f5c5SAndroid Build Coastguard Worker {
232*8975f5c5SAndroid Build Coastguard Worker return 0;
233*8975f5c5SAndroid Build Coastguard Worker }
234*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const235*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermSymbol::getChildNode(size_t index) const
236*8975f5c5SAndroid Build Coastguard Worker {
237*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
238*8975f5c5SAndroid Build Coastguard Worker return nullptr;
239*8975f5c5SAndroid Build Coastguard Worker }
240*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const241*8975f5c5SAndroid Build Coastguard Worker size_t TIntermConstantUnion::getChildCount() const
242*8975f5c5SAndroid Build Coastguard Worker {
243*8975f5c5SAndroid Build Coastguard Worker return 0;
244*8975f5c5SAndroid Build Coastguard Worker }
245*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const246*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermConstantUnion::getChildNode(size_t index) const
247*8975f5c5SAndroid Build Coastguard Worker {
248*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
249*8975f5c5SAndroid Build Coastguard Worker return nullptr;
250*8975f5c5SAndroid Build Coastguard Worker }
251*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const252*8975f5c5SAndroid Build Coastguard Worker size_t TIntermLoop::getChildCount() const
253*8975f5c5SAndroid Build Coastguard Worker {
254*8975f5c5SAndroid Build Coastguard Worker return (mInit ? 1 : 0) + (mCond ? 1 : 0) + (mExpr ? 1 : 0) + 1;
255*8975f5c5SAndroid Build Coastguard Worker }
256*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const257*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermLoop::getChildNode(size_t index) const
258*8975f5c5SAndroid Build Coastguard Worker {
259*8975f5c5SAndroid Build Coastguard Worker TIntermNode *children[4];
260*8975f5c5SAndroid Build Coastguard Worker unsigned int childIndex = 0;
261*8975f5c5SAndroid Build Coastguard Worker if (mInit)
262*8975f5c5SAndroid Build Coastguard Worker {
263*8975f5c5SAndroid Build Coastguard Worker children[childIndex] = mInit;
264*8975f5c5SAndroid Build Coastguard Worker ++childIndex;
265*8975f5c5SAndroid Build Coastguard Worker }
266*8975f5c5SAndroid Build Coastguard Worker if (mCond)
267*8975f5c5SAndroid Build Coastguard Worker {
268*8975f5c5SAndroid Build Coastguard Worker children[childIndex] = mCond;
269*8975f5c5SAndroid Build Coastguard Worker ++childIndex;
270*8975f5c5SAndroid Build Coastguard Worker }
271*8975f5c5SAndroid Build Coastguard Worker if (mExpr)
272*8975f5c5SAndroid Build Coastguard Worker {
273*8975f5c5SAndroid Build Coastguard Worker children[childIndex] = mExpr;
274*8975f5c5SAndroid Build Coastguard Worker ++childIndex;
275*8975f5c5SAndroid Build Coastguard Worker }
276*8975f5c5SAndroid Build Coastguard Worker children[childIndex] = mBody;
277*8975f5c5SAndroid Build Coastguard Worker ++childIndex;
278*8975f5c5SAndroid Build Coastguard Worker
279*8975f5c5SAndroid Build Coastguard Worker ASSERT(index < childIndex);
280*8975f5c5SAndroid Build Coastguard Worker return children[index];
281*8975f5c5SAndroid Build Coastguard Worker }
282*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)283*8975f5c5SAndroid Build Coastguard Worker bool TIntermLoop::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
284*8975f5c5SAndroid Build Coastguard Worker {
285*8975f5c5SAndroid Build Coastguard Worker ASSERT(original != nullptr); // This risks replacing multiple children.
286*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mInit, getAsNode, original, replacement);
287*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mCond, getAsTyped, original, replacement);
288*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mExpr, getAsTyped, original, replacement);
289*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mBody, getAsBlock, original, replacement);
290*8975f5c5SAndroid Build Coastguard Worker return false;
291*8975f5c5SAndroid Build Coastguard Worker }
292*8975f5c5SAndroid Build Coastguard Worker
TIntermBranch(const TIntermBranch & node)293*8975f5c5SAndroid Build Coastguard Worker TIntermBranch::TIntermBranch(const TIntermBranch &node)
294*8975f5c5SAndroid Build Coastguard Worker : TIntermBranch(node.mFlowOp, node.mExpression ? node.mExpression->deepCopy() : nullptr)
295*8975f5c5SAndroid Build Coastguard Worker {}
296*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const297*8975f5c5SAndroid Build Coastguard Worker size_t TIntermBranch::getChildCount() const
298*8975f5c5SAndroid Build Coastguard Worker {
299*8975f5c5SAndroid Build Coastguard Worker return (mExpression ? 1 : 0);
300*8975f5c5SAndroid Build Coastguard Worker }
301*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const302*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermBranch::getChildNode(size_t index) const
303*8975f5c5SAndroid Build Coastguard Worker {
304*8975f5c5SAndroid Build Coastguard Worker ASSERT(mExpression);
305*8975f5c5SAndroid Build Coastguard Worker ASSERT(index == 0);
306*8975f5c5SAndroid Build Coastguard Worker return mExpression;
307*8975f5c5SAndroid Build Coastguard Worker }
308*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)309*8975f5c5SAndroid Build Coastguard Worker bool TIntermBranch::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
310*8975f5c5SAndroid Build Coastguard Worker {
311*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mExpression, getAsTyped, original, replacement);
312*8975f5c5SAndroid Build Coastguard Worker return false;
313*8975f5c5SAndroid Build Coastguard Worker }
314*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const315*8975f5c5SAndroid Build Coastguard Worker size_t TIntermSwizzle::getChildCount() const
316*8975f5c5SAndroid Build Coastguard Worker {
317*8975f5c5SAndroid Build Coastguard Worker return 1;
318*8975f5c5SAndroid Build Coastguard Worker }
319*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const320*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermSwizzle::getChildNode(size_t index) const
321*8975f5c5SAndroid Build Coastguard Worker {
322*8975f5c5SAndroid Build Coastguard Worker ASSERT(mOperand);
323*8975f5c5SAndroid Build Coastguard Worker ASSERT(index == 0);
324*8975f5c5SAndroid Build Coastguard Worker return mOperand;
325*8975f5c5SAndroid Build Coastguard Worker }
326*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)327*8975f5c5SAndroid Build Coastguard Worker bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
328*8975f5c5SAndroid Build Coastguard Worker {
329*8975f5c5SAndroid Build Coastguard Worker ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
330*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mOperand, getAsTyped, original, replacement);
331*8975f5c5SAndroid Build Coastguard Worker return false;
332*8975f5c5SAndroid Build Coastguard Worker }
333*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const334*8975f5c5SAndroid Build Coastguard Worker size_t TIntermBinary::getChildCount() const
335*8975f5c5SAndroid Build Coastguard Worker {
336*8975f5c5SAndroid Build Coastguard Worker return 2;
337*8975f5c5SAndroid Build Coastguard Worker }
338*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const339*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermBinary::getChildNode(size_t index) const
340*8975f5c5SAndroid Build Coastguard Worker {
341*8975f5c5SAndroid Build Coastguard Worker ASSERT(index < 2);
342*8975f5c5SAndroid Build Coastguard Worker if (index == 0)
343*8975f5c5SAndroid Build Coastguard Worker {
344*8975f5c5SAndroid Build Coastguard Worker return mLeft;
345*8975f5c5SAndroid Build Coastguard Worker }
346*8975f5c5SAndroid Build Coastguard Worker return mRight;
347*8975f5c5SAndroid Build Coastguard Worker }
348*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)349*8975f5c5SAndroid Build Coastguard Worker bool TIntermBinary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
350*8975f5c5SAndroid Build Coastguard Worker {
351*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mLeft, getAsTyped, original, replacement);
352*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mRight, getAsTyped, original, replacement);
353*8975f5c5SAndroid Build Coastguard Worker return false;
354*8975f5c5SAndroid Build Coastguard Worker }
355*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const356*8975f5c5SAndroid Build Coastguard Worker size_t TIntermUnary::getChildCount() const
357*8975f5c5SAndroid Build Coastguard Worker {
358*8975f5c5SAndroid Build Coastguard Worker return 1;
359*8975f5c5SAndroid Build Coastguard Worker }
360*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const361*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermUnary::getChildNode(size_t index) const
362*8975f5c5SAndroid Build Coastguard Worker {
363*8975f5c5SAndroid Build Coastguard Worker ASSERT(mOperand);
364*8975f5c5SAndroid Build Coastguard Worker ASSERT(index == 0);
365*8975f5c5SAndroid Build Coastguard Worker return mOperand;
366*8975f5c5SAndroid Build Coastguard Worker }
367*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)368*8975f5c5SAndroid Build Coastguard Worker bool TIntermUnary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
369*8975f5c5SAndroid Build Coastguard Worker {
370*8975f5c5SAndroid Build Coastguard Worker // gl_ClipDistance and gl_CullDistance arrays may be replaced with an adjusted
371*8975f5c5SAndroid Build Coastguard Worker // array size. Allow mismatching types for the length() operation in this case.
372*8975f5c5SAndroid Build Coastguard Worker ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType() ||
373*8975f5c5SAndroid Build Coastguard Worker (mOp == EOpArrayLength && (original->getAsTyped()->getQualifier() == EvqClipDistance ||
374*8975f5c5SAndroid Build Coastguard Worker original->getAsTyped()->getQualifier() == EvqCullDistance)));
375*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mOperand, getAsTyped, original, replacement);
376*8975f5c5SAndroid Build Coastguard Worker return false;
377*8975f5c5SAndroid Build Coastguard Worker }
378*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const379*8975f5c5SAndroid Build Coastguard Worker size_t TIntermGlobalQualifierDeclaration::getChildCount() const
380*8975f5c5SAndroid Build Coastguard Worker {
381*8975f5c5SAndroid Build Coastguard Worker return 1;
382*8975f5c5SAndroid Build Coastguard Worker }
383*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const384*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermGlobalQualifierDeclaration::getChildNode(size_t index) const
385*8975f5c5SAndroid Build Coastguard Worker {
386*8975f5c5SAndroid Build Coastguard Worker ASSERT(mSymbol);
387*8975f5c5SAndroid Build Coastguard Worker ASSERT(index == 0);
388*8975f5c5SAndroid Build Coastguard Worker return mSymbol;
389*8975f5c5SAndroid Build Coastguard Worker }
390*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)391*8975f5c5SAndroid Build Coastguard Worker bool TIntermGlobalQualifierDeclaration::replaceChildNode(TIntermNode *original,
392*8975f5c5SAndroid Build Coastguard Worker TIntermNode *replacement)
393*8975f5c5SAndroid Build Coastguard Worker {
394*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mSymbol, getAsSymbolNode, original, replacement);
395*8975f5c5SAndroid Build Coastguard Worker return false;
396*8975f5c5SAndroid Build Coastguard Worker }
397*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const398*8975f5c5SAndroid Build Coastguard Worker size_t TIntermFunctionDefinition::getChildCount() const
399*8975f5c5SAndroid Build Coastguard Worker {
400*8975f5c5SAndroid Build Coastguard Worker return 2;
401*8975f5c5SAndroid Build Coastguard Worker }
402*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const403*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermFunctionDefinition::getChildNode(size_t index) const
404*8975f5c5SAndroid Build Coastguard Worker {
405*8975f5c5SAndroid Build Coastguard Worker ASSERT(index < 2);
406*8975f5c5SAndroid Build Coastguard Worker if (index == 0)
407*8975f5c5SAndroid Build Coastguard Worker {
408*8975f5c5SAndroid Build Coastguard Worker return mPrototype;
409*8975f5c5SAndroid Build Coastguard Worker }
410*8975f5c5SAndroid Build Coastguard Worker return mBody;
411*8975f5c5SAndroid Build Coastguard Worker }
412*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)413*8975f5c5SAndroid Build Coastguard Worker bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
414*8975f5c5SAndroid Build Coastguard Worker {
415*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mPrototype, getAsFunctionPrototypeNode, original, replacement);
416*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mBody, getAsBlock, original, replacement);
417*8975f5c5SAndroid Build Coastguard Worker return false;
418*8975f5c5SAndroid Build Coastguard Worker }
419*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const420*8975f5c5SAndroid Build Coastguard Worker size_t TIntermAggregate::getChildCount() const
421*8975f5c5SAndroid Build Coastguard Worker {
422*8975f5c5SAndroid Build Coastguard Worker return mArguments.size();
423*8975f5c5SAndroid Build Coastguard Worker }
424*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const425*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermAggregate::getChildNode(size_t index) const
426*8975f5c5SAndroid Build Coastguard Worker {
427*8975f5c5SAndroid Build Coastguard Worker return mArguments[index];
428*8975f5c5SAndroid Build Coastguard Worker }
429*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)430*8975f5c5SAndroid Build Coastguard Worker bool TIntermAggregate::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
431*8975f5c5SAndroid Build Coastguard Worker {
432*8975f5c5SAndroid Build Coastguard Worker return replaceChildNodeInternal(original, replacement);
433*8975f5c5SAndroid Build Coastguard Worker }
434*8975f5c5SAndroid Build Coastguard Worker
TIntermBlock(const TIntermBlock & node)435*8975f5c5SAndroid Build Coastguard Worker TIntermBlock::TIntermBlock(const TIntermBlock &node)
436*8975f5c5SAndroid Build Coastguard Worker {
437*8975f5c5SAndroid Build Coastguard Worker for (TIntermNode *intermNode : node.mStatements)
438*8975f5c5SAndroid Build Coastguard Worker {
439*8975f5c5SAndroid Build Coastguard Worker mStatements.push_back(intermNode->deepCopy());
440*8975f5c5SAndroid Build Coastguard Worker }
441*8975f5c5SAndroid Build Coastguard Worker
442*8975f5c5SAndroid Build Coastguard Worker ASSERT(!node.mIsTreeRoot);
443*8975f5c5SAndroid Build Coastguard Worker mIsTreeRoot = false;
444*8975f5c5SAndroid Build Coastguard Worker }
445*8975f5c5SAndroid Build Coastguard Worker
TIntermBlock(std::initializer_list<TIntermNode * > stmts)446*8975f5c5SAndroid Build Coastguard Worker TIntermBlock::TIntermBlock(std::initializer_list<TIntermNode *> stmts)
447*8975f5c5SAndroid Build Coastguard Worker {
448*8975f5c5SAndroid Build Coastguard Worker for (TIntermNode *stmt : stmts)
449*8975f5c5SAndroid Build Coastguard Worker {
450*8975f5c5SAndroid Build Coastguard Worker appendStatement(stmt);
451*8975f5c5SAndroid Build Coastguard Worker }
452*8975f5c5SAndroid Build Coastguard Worker }
453*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const454*8975f5c5SAndroid Build Coastguard Worker size_t TIntermBlock::getChildCount() const
455*8975f5c5SAndroid Build Coastguard Worker {
456*8975f5c5SAndroid Build Coastguard Worker return mStatements.size();
457*8975f5c5SAndroid Build Coastguard Worker }
458*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const459*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermBlock::getChildNode(size_t index) const
460*8975f5c5SAndroid Build Coastguard Worker {
461*8975f5c5SAndroid Build Coastguard Worker return mStatements[index];
462*8975f5c5SAndroid Build Coastguard Worker }
463*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)464*8975f5c5SAndroid Build Coastguard Worker bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
465*8975f5c5SAndroid Build Coastguard Worker {
466*8975f5c5SAndroid Build Coastguard Worker return replaceChildNodeInternal(original, replacement);
467*8975f5c5SAndroid Build Coastguard Worker }
468*8975f5c5SAndroid Build Coastguard Worker
replaceAllChildren(const TIntermSequence & newStatements)469*8975f5c5SAndroid Build Coastguard Worker void TIntermBlock::replaceAllChildren(const TIntermSequence &newStatements)
470*8975f5c5SAndroid Build Coastguard Worker {
471*8975f5c5SAndroid Build Coastguard Worker mStatements.clear();
472*8975f5c5SAndroid Build Coastguard Worker mStatements.insert(mStatements.begin(), newStatements.begin(), newStatements.end());
473*8975f5c5SAndroid Build Coastguard Worker }
474*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const475*8975f5c5SAndroid Build Coastguard Worker size_t TIntermFunctionPrototype::getChildCount() const
476*8975f5c5SAndroid Build Coastguard Worker {
477*8975f5c5SAndroid Build Coastguard Worker return 0;
478*8975f5c5SAndroid Build Coastguard Worker }
479*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const480*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermFunctionPrototype::getChildNode(size_t index) const
481*8975f5c5SAndroid Build Coastguard Worker {
482*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
483*8975f5c5SAndroid Build Coastguard Worker return nullptr;
484*8975f5c5SAndroid Build Coastguard Worker }
485*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)486*8975f5c5SAndroid Build Coastguard Worker bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
487*8975f5c5SAndroid Build Coastguard Worker {
488*8975f5c5SAndroid Build Coastguard Worker return false;
489*8975f5c5SAndroid Build Coastguard Worker }
490*8975f5c5SAndroid Build Coastguard Worker
TIntermDeclaration(const TVariable * var,TIntermTyped * initExpr)491*8975f5c5SAndroid Build Coastguard Worker TIntermDeclaration::TIntermDeclaration(const TVariable *var, TIntermTyped *initExpr)
492*8975f5c5SAndroid Build Coastguard Worker {
493*8975f5c5SAndroid Build Coastguard Worker if (initExpr)
494*8975f5c5SAndroid Build Coastguard Worker {
495*8975f5c5SAndroid Build Coastguard Worker appendDeclarator(
496*8975f5c5SAndroid Build Coastguard Worker new TIntermBinary(TOperator::EOpInitialize, new TIntermSymbol(var), initExpr));
497*8975f5c5SAndroid Build Coastguard Worker }
498*8975f5c5SAndroid Build Coastguard Worker else
499*8975f5c5SAndroid Build Coastguard Worker {
500*8975f5c5SAndroid Build Coastguard Worker appendDeclarator(new TIntermSymbol(var));
501*8975f5c5SAndroid Build Coastguard Worker }
502*8975f5c5SAndroid Build Coastguard Worker }
503*8975f5c5SAndroid Build Coastguard Worker
TIntermDeclaration(std::initializer_list<const TVariable * > declarators)504*8975f5c5SAndroid Build Coastguard Worker TIntermDeclaration::TIntermDeclaration(std::initializer_list<const TVariable *> declarators)
505*8975f5c5SAndroid Build Coastguard Worker : TIntermDeclaration()
506*8975f5c5SAndroid Build Coastguard Worker {
507*8975f5c5SAndroid Build Coastguard Worker for (const TVariable *d : declarators)
508*8975f5c5SAndroid Build Coastguard Worker {
509*8975f5c5SAndroid Build Coastguard Worker appendDeclarator(new TIntermSymbol(d));
510*8975f5c5SAndroid Build Coastguard Worker }
511*8975f5c5SAndroid Build Coastguard Worker }
512*8975f5c5SAndroid Build Coastguard Worker
TIntermDeclaration(std::initializer_list<TIntermTyped * > declarators)513*8975f5c5SAndroid Build Coastguard Worker TIntermDeclaration::TIntermDeclaration(std::initializer_list<TIntermTyped *> declarators)
514*8975f5c5SAndroid Build Coastguard Worker : TIntermDeclaration()
515*8975f5c5SAndroid Build Coastguard Worker {
516*8975f5c5SAndroid Build Coastguard Worker for (TIntermTyped *d : declarators)
517*8975f5c5SAndroid Build Coastguard Worker {
518*8975f5c5SAndroid Build Coastguard Worker appendDeclarator(d);
519*8975f5c5SAndroid Build Coastguard Worker }
520*8975f5c5SAndroid Build Coastguard Worker }
521*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const522*8975f5c5SAndroid Build Coastguard Worker size_t TIntermDeclaration::getChildCount() const
523*8975f5c5SAndroid Build Coastguard Worker {
524*8975f5c5SAndroid Build Coastguard Worker return mDeclarators.size();
525*8975f5c5SAndroid Build Coastguard Worker }
526*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const527*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermDeclaration::getChildNode(size_t index) const
528*8975f5c5SAndroid Build Coastguard Worker {
529*8975f5c5SAndroid Build Coastguard Worker return mDeclarators[index];
530*8975f5c5SAndroid Build Coastguard Worker }
531*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)532*8975f5c5SAndroid Build Coastguard Worker bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
533*8975f5c5SAndroid Build Coastguard Worker {
534*8975f5c5SAndroid Build Coastguard Worker return replaceChildNodeInternal(original, replacement);
535*8975f5c5SAndroid Build Coastguard Worker }
536*8975f5c5SAndroid Build Coastguard Worker
TIntermDeclaration(const TIntermDeclaration & node)537*8975f5c5SAndroid Build Coastguard Worker TIntermDeclaration::TIntermDeclaration(const TIntermDeclaration &node)
538*8975f5c5SAndroid Build Coastguard Worker {
539*8975f5c5SAndroid Build Coastguard Worker for (TIntermNode *intermNode : node.mDeclarators)
540*8975f5c5SAndroid Build Coastguard Worker {
541*8975f5c5SAndroid Build Coastguard Worker mDeclarators.push_back(intermNode->deepCopy());
542*8975f5c5SAndroid Build Coastguard Worker }
543*8975f5c5SAndroid Build Coastguard Worker }
544*8975f5c5SAndroid Build Coastguard Worker
replaceChildNodeInternal(TIntermNode * original,TIntermNode * replacement)545*8975f5c5SAndroid Build Coastguard Worker bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement)
546*8975f5c5SAndroid Build Coastguard Worker {
547*8975f5c5SAndroid Build Coastguard Worker for (size_t ii = 0; ii < getSequence()->size(); ++ii)
548*8975f5c5SAndroid Build Coastguard Worker {
549*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS((*getSequence())[ii], getAsNode, original, replacement);
550*8975f5c5SAndroid Build Coastguard Worker }
551*8975f5c5SAndroid Build Coastguard Worker return false;
552*8975f5c5SAndroid Build Coastguard Worker }
553*8975f5c5SAndroid Build Coastguard Worker
replaceChildNodeWithMultiple(TIntermNode * original,const TIntermSequence & replacements)554*8975f5c5SAndroid Build Coastguard Worker bool TIntermAggregateBase::replaceChildNodeWithMultiple(TIntermNode *original,
555*8975f5c5SAndroid Build Coastguard Worker const TIntermSequence &replacements)
556*8975f5c5SAndroid Build Coastguard Worker {
557*8975f5c5SAndroid Build Coastguard Worker for (auto it = getSequence()->begin(); it < getSequence()->end(); ++it)
558*8975f5c5SAndroid Build Coastguard Worker {
559*8975f5c5SAndroid Build Coastguard Worker if (*it == original)
560*8975f5c5SAndroid Build Coastguard Worker {
561*8975f5c5SAndroid Build Coastguard Worker it = getSequence()->erase(it);
562*8975f5c5SAndroid Build Coastguard Worker getSequence()->insert(it, replacements.begin(), replacements.end());
563*8975f5c5SAndroid Build Coastguard Worker return true;
564*8975f5c5SAndroid Build Coastguard Worker }
565*8975f5c5SAndroid Build Coastguard Worker }
566*8975f5c5SAndroid Build Coastguard Worker return false;
567*8975f5c5SAndroid Build Coastguard Worker }
568*8975f5c5SAndroid Build Coastguard Worker
insertChildNodes(TIntermSequence::size_type position,const TIntermSequence & insertions)569*8975f5c5SAndroid Build Coastguard Worker bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position,
570*8975f5c5SAndroid Build Coastguard Worker const TIntermSequence &insertions)
571*8975f5c5SAndroid Build Coastguard Worker {
572*8975f5c5SAndroid Build Coastguard Worker if (position > getSequence()->size())
573*8975f5c5SAndroid Build Coastguard Worker {
574*8975f5c5SAndroid Build Coastguard Worker return false;
575*8975f5c5SAndroid Build Coastguard Worker }
576*8975f5c5SAndroid Build Coastguard Worker auto it = getSequence()->begin() + position;
577*8975f5c5SAndroid Build Coastguard Worker getSequence()->insert(it, insertions.begin(), insertions.end());
578*8975f5c5SAndroid Build Coastguard Worker return true;
579*8975f5c5SAndroid Build Coastguard Worker }
580*8975f5c5SAndroid Build Coastguard Worker
TIntermSymbol(const TVariable * variable)581*8975f5c5SAndroid Build Coastguard Worker TIntermSymbol::TIntermSymbol(const TVariable *variable) : TIntermTyped(), mVariable(variable) {}
582*8975f5c5SAndroid Build Coastguard Worker
hasConstantValue() const583*8975f5c5SAndroid Build Coastguard Worker bool TIntermSymbol::hasConstantValue() const
584*8975f5c5SAndroid Build Coastguard Worker {
585*8975f5c5SAndroid Build Coastguard Worker return variable().getConstPointer() != nullptr;
586*8975f5c5SAndroid Build Coastguard Worker }
587*8975f5c5SAndroid Build Coastguard Worker
getConstantValue() const588*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *TIntermSymbol::getConstantValue() const
589*8975f5c5SAndroid Build Coastguard Worker {
590*8975f5c5SAndroid Build Coastguard Worker return variable().getConstPointer();
591*8975f5c5SAndroid Build Coastguard Worker }
592*8975f5c5SAndroid Build Coastguard Worker
uniqueId() const593*8975f5c5SAndroid Build Coastguard Worker const TSymbolUniqueId &TIntermSymbol::uniqueId() const
594*8975f5c5SAndroid Build Coastguard Worker {
595*8975f5c5SAndroid Build Coastguard Worker return mVariable->uniqueId();
596*8975f5c5SAndroid Build Coastguard Worker }
597*8975f5c5SAndroid Build Coastguard Worker
getName() const598*8975f5c5SAndroid Build Coastguard Worker ImmutableString TIntermSymbol::getName() const
599*8975f5c5SAndroid Build Coastguard Worker {
600*8975f5c5SAndroid Build Coastguard Worker return mVariable->name();
601*8975f5c5SAndroid Build Coastguard Worker }
602*8975f5c5SAndroid Build Coastguard Worker
getType() const603*8975f5c5SAndroid Build Coastguard Worker const TType &TIntermSymbol::getType() const
604*8975f5c5SAndroid Build Coastguard Worker {
605*8975f5c5SAndroid Build Coastguard Worker return mVariable->getType();
606*8975f5c5SAndroid Build Coastguard Worker }
607*8975f5c5SAndroid Build Coastguard Worker
propagatePrecision(TPrecision precision)608*8975f5c5SAndroid Build Coastguard Worker void TIntermSymbol::propagatePrecision(TPrecision precision)
609*8975f5c5SAndroid Build Coastguard Worker {
610*8975f5c5SAndroid Build Coastguard Worker // Every declared variable should already have a precision. Some built-ins don't have a defined
611*8975f5c5SAndroid Build Coastguard Worker // precision. This is not asserted however:
612*8975f5c5SAndroid Build Coastguard Worker //
613*8975f5c5SAndroid Build Coastguard Worker // - A shader with no precision specified either globally or on a variable will fail with a
614*8975f5c5SAndroid Build Coastguard Worker // compilation error later on.
615*8975f5c5SAndroid Build Coastguard Worker // - Transformations declaring variables without precision will be caught by AST validation.
616*8975f5c5SAndroid Build Coastguard Worker }
617*8975f5c5SAndroid Build Coastguard Worker
CreateFunctionCall(const TFunction & func,TIntermSequence * arguments)618*8975f5c5SAndroid Build Coastguard Worker TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TFunction &func,
619*8975f5c5SAndroid Build Coastguard Worker TIntermSequence *arguments)
620*8975f5c5SAndroid Build Coastguard Worker {
621*8975f5c5SAndroid Build Coastguard Worker return new TIntermAggregate(&func, func.getReturnType(), EOpCallFunctionInAST, arguments);
622*8975f5c5SAndroid Build Coastguard Worker }
623*8975f5c5SAndroid Build Coastguard Worker
CreateRawFunctionCall(const TFunction & func,TIntermSequence * arguments)624*8975f5c5SAndroid Build Coastguard Worker TIntermAggregate *TIntermAggregate::CreateRawFunctionCall(const TFunction &func,
625*8975f5c5SAndroid Build Coastguard Worker TIntermSequence *arguments)
626*8975f5c5SAndroid Build Coastguard Worker {
627*8975f5c5SAndroid Build Coastguard Worker return new TIntermAggregate(&func, func.getReturnType(), EOpCallInternalRawFunction, arguments);
628*8975f5c5SAndroid Build Coastguard Worker }
629*8975f5c5SAndroid Build Coastguard Worker
CreateBuiltInFunctionCall(const TFunction & func,TIntermSequence * arguments)630*8975f5c5SAndroid Build Coastguard Worker TIntermAggregate *TIntermAggregate::CreateBuiltInFunctionCall(const TFunction &func,
631*8975f5c5SAndroid Build Coastguard Worker TIntermSequence *arguments)
632*8975f5c5SAndroid Build Coastguard Worker {
633*8975f5c5SAndroid Build Coastguard Worker // Every built-in function should have an op.
634*8975f5c5SAndroid Build Coastguard Worker ASSERT(func.getBuiltInOp() != EOpNull);
635*8975f5c5SAndroid Build Coastguard Worker return new TIntermAggregate(&func, func.getReturnType(), func.getBuiltInOp(), arguments);
636*8975f5c5SAndroid Build Coastguard Worker }
637*8975f5c5SAndroid Build Coastguard Worker
CreateConstructor(const TType & type,TIntermSequence * arguments)638*8975f5c5SAndroid Build Coastguard Worker TIntermAggregate *TIntermAggregate::CreateConstructor(const TType &type, TIntermSequence *arguments)
639*8975f5c5SAndroid Build Coastguard Worker {
640*8975f5c5SAndroid Build Coastguard Worker return new TIntermAggregate(nullptr, type, EOpConstruct, arguments);
641*8975f5c5SAndroid Build Coastguard Worker }
642*8975f5c5SAndroid Build Coastguard Worker
CreateConstructor(const TType & type,const std::initializer_list<TIntermNode * > & arguments)643*8975f5c5SAndroid Build Coastguard Worker TIntermAggregate *TIntermAggregate::CreateConstructor(
644*8975f5c5SAndroid Build Coastguard Worker const TType &type,
645*8975f5c5SAndroid Build Coastguard Worker const std::initializer_list<TIntermNode *> &arguments)
646*8975f5c5SAndroid Build Coastguard Worker {
647*8975f5c5SAndroid Build Coastguard Worker TIntermSequence argSequence(arguments);
648*8975f5c5SAndroid Build Coastguard Worker return CreateConstructor(type, &argSequence);
649*8975f5c5SAndroid Build Coastguard Worker }
650*8975f5c5SAndroid Build Coastguard Worker
TIntermAggregate(const TFunction * func,const TType & type,TOperator op,TIntermSequence * arguments)651*8975f5c5SAndroid Build Coastguard Worker TIntermAggregate::TIntermAggregate(const TFunction *func,
652*8975f5c5SAndroid Build Coastguard Worker const TType &type,
653*8975f5c5SAndroid Build Coastguard Worker TOperator op,
654*8975f5c5SAndroid Build Coastguard Worker TIntermSequence *arguments)
655*8975f5c5SAndroid Build Coastguard Worker : TIntermOperator(op, type), mUseEmulatedFunction(false), mFunction(func)
656*8975f5c5SAndroid Build Coastguard Worker {
657*8975f5c5SAndroid Build Coastguard Worker if (arguments != nullptr)
658*8975f5c5SAndroid Build Coastguard Worker {
659*8975f5c5SAndroid Build Coastguard Worker mArguments.swap(*arguments);
660*8975f5c5SAndroid Build Coastguard Worker }
661*8975f5c5SAndroid Build Coastguard Worker ASSERT(mFunction == nullptr || mFunction->symbolType() != SymbolType::Empty);
662*8975f5c5SAndroid Build Coastguard Worker setPrecisionAndQualifier();
663*8975f5c5SAndroid Build Coastguard Worker }
664*8975f5c5SAndroid Build Coastguard Worker
setPrecisionAndQualifier()665*8975f5c5SAndroid Build Coastguard Worker void TIntermAggregate::setPrecisionAndQualifier()
666*8975f5c5SAndroid Build Coastguard Worker {
667*8975f5c5SAndroid Build Coastguard Worker mType.setQualifier(EvqTemporary);
668*8975f5c5SAndroid Build Coastguard Worker if ((!BuiltInGroup::IsBuiltIn(mOp) && !isFunctionCall()) || BuiltInGroup::IsMath(mOp))
669*8975f5c5SAndroid Build Coastguard Worker {
670*8975f5c5SAndroid Build Coastguard Worker if (areChildrenConstQualified())
671*8975f5c5SAndroid Build Coastguard Worker {
672*8975f5c5SAndroid Build Coastguard Worker mType.setQualifier(EvqConst);
673*8975f5c5SAndroid Build Coastguard Worker }
674*8975f5c5SAndroid Build Coastguard Worker }
675*8975f5c5SAndroid Build Coastguard Worker
676*8975f5c5SAndroid Build Coastguard Worker propagatePrecision(derivePrecision());
677*8975f5c5SAndroid Build Coastguard Worker }
678*8975f5c5SAndroid Build Coastguard Worker
areChildrenConstQualified()679*8975f5c5SAndroid Build Coastguard Worker bool TIntermAggregate::areChildrenConstQualified()
680*8975f5c5SAndroid Build Coastguard Worker {
681*8975f5c5SAndroid Build Coastguard Worker for (TIntermNode *arg : mArguments)
682*8975f5c5SAndroid Build Coastguard Worker {
683*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *typedArg = arg->getAsTyped();
684*8975f5c5SAndroid Build Coastguard Worker if (typedArg && typedArg->getQualifier() != EvqConst)
685*8975f5c5SAndroid Build Coastguard Worker {
686*8975f5c5SAndroid Build Coastguard Worker return false;
687*8975f5c5SAndroid Build Coastguard Worker }
688*8975f5c5SAndroid Build Coastguard Worker }
689*8975f5c5SAndroid Build Coastguard Worker return true;
690*8975f5c5SAndroid Build Coastguard Worker }
691*8975f5c5SAndroid Build Coastguard Worker
692*8975f5c5SAndroid Build Coastguard Worker // Derive precision from children nodes
derivePrecision() const693*8975f5c5SAndroid Build Coastguard Worker TPrecision TIntermAggregate::derivePrecision() const
694*8975f5c5SAndroid Build Coastguard Worker {
695*8975f5c5SAndroid Build Coastguard Worker if (getBasicType() == EbtBool || getBasicType() == EbtVoid || getBasicType() == EbtStruct)
696*8975f5c5SAndroid Build Coastguard Worker {
697*8975f5c5SAndroid Build Coastguard Worker return EbpUndefined;
698*8975f5c5SAndroid Build Coastguard Worker }
699*8975f5c5SAndroid Build Coastguard Worker
700*8975f5c5SAndroid Build Coastguard Worker // For AST function calls, take the qualifier from the declared one.
701*8975f5c5SAndroid Build Coastguard Worker if (isFunctionCall())
702*8975f5c5SAndroid Build Coastguard Worker {
703*8975f5c5SAndroid Build Coastguard Worker return mType.getPrecision();
704*8975f5c5SAndroid Build Coastguard Worker }
705*8975f5c5SAndroid Build Coastguard Worker
706*8975f5c5SAndroid Build Coastguard Worker // Some built-ins explicitly specify their precision.
707*8975f5c5SAndroid Build Coastguard Worker switch (mOp)
708*8975f5c5SAndroid Build Coastguard Worker {
709*8975f5c5SAndroid Build Coastguard Worker case EOpBitfieldExtract:
710*8975f5c5SAndroid Build Coastguard Worker return mArguments[0]->getAsTyped()->getPrecision();
711*8975f5c5SAndroid Build Coastguard Worker case EOpBitfieldInsert:
712*8975f5c5SAndroid Build Coastguard Worker return GetHigherPrecision(mArguments[0]->getAsTyped()->getPrecision(),
713*8975f5c5SAndroid Build Coastguard Worker mArguments[1]->getAsTyped()->getPrecision());
714*8975f5c5SAndroid Build Coastguard Worker case EOpTextureSize:
715*8975f5c5SAndroid Build Coastguard Worker case EOpImageSize:
716*8975f5c5SAndroid Build Coastguard Worker case EOpUaddCarry:
717*8975f5c5SAndroid Build Coastguard Worker case EOpUsubBorrow:
718*8975f5c5SAndroid Build Coastguard Worker case EOpUmulExtended:
719*8975f5c5SAndroid Build Coastguard Worker case EOpImulExtended:
720*8975f5c5SAndroid Build Coastguard Worker case EOpFrexp:
721*8975f5c5SAndroid Build Coastguard Worker case EOpLdexp:
722*8975f5c5SAndroid Build Coastguard Worker return EbpHigh;
723*8975f5c5SAndroid Build Coastguard Worker default:
724*8975f5c5SAndroid Build Coastguard Worker break;
725*8975f5c5SAndroid Build Coastguard Worker }
726*8975f5c5SAndroid Build Coastguard Worker
727*8975f5c5SAndroid Build Coastguard Worker // The rest of the math operations and constructors get their precision from their arguments.
728*8975f5c5SAndroid Build Coastguard Worker if (BuiltInGroup::IsMath(mOp) || mOp == EOpConstruct)
729*8975f5c5SAndroid Build Coastguard Worker {
730*8975f5c5SAndroid Build Coastguard Worker TPrecision precision = EbpUndefined;
731*8975f5c5SAndroid Build Coastguard Worker for (TIntermNode *argument : mArguments)
732*8975f5c5SAndroid Build Coastguard Worker {
733*8975f5c5SAndroid Build Coastguard Worker precision = GetHigherPrecision(argument->getAsTyped()->getPrecision(), precision);
734*8975f5c5SAndroid Build Coastguard Worker }
735*8975f5c5SAndroid Build Coastguard Worker return precision;
736*8975f5c5SAndroid Build Coastguard Worker }
737*8975f5c5SAndroid Build Coastguard Worker
738*8975f5c5SAndroid Build Coastguard Worker // Atomic operations return highp.
739*8975f5c5SAndroid Build Coastguard Worker if (BuiltInGroup::IsImageAtomic(mOp) || BuiltInGroup::IsAtomicCounter(mOp) ||
740*8975f5c5SAndroid Build Coastguard Worker BuiltInGroup::IsAtomicMemory(mOp))
741*8975f5c5SAndroid Build Coastguard Worker {
742*8975f5c5SAndroid Build Coastguard Worker return EbpHigh;
743*8975f5c5SAndroid Build Coastguard Worker }
744*8975f5c5SAndroid Build Coastguard Worker
745*8975f5c5SAndroid Build Coastguard Worker // Texture functions return the same precision as that of the sampler (textureSize returns
746*8975f5c5SAndroid Build Coastguard Worker // highp, but that's handled above). imageLoad similar takes the precision of the image. The
747*8975f5c5SAndroid Build Coastguard Worker // same is true for dFd*, interpolateAt* and subpassLoad operations.
748*8975f5c5SAndroid Build Coastguard Worker if (BuiltInGroup::IsTexture(mOp) || BuiltInGroup::IsImageLoad(mOp) ||
749*8975f5c5SAndroid Build Coastguard Worker BuiltInGroup::IsDerivativesFS(mOp) || BuiltInGroup::IsInterpolationFS(mOp) ||
750*8975f5c5SAndroid Build Coastguard Worker mOp == EOpSubpassLoad || mOp == EOpInterpolateAtCenter)
751*8975f5c5SAndroid Build Coastguard Worker {
752*8975f5c5SAndroid Build Coastguard Worker return mArguments[0]->getAsTyped()->getPrecision();
753*8975f5c5SAndroid Build Coastguard Worker }
754*8975f5c5SAndroid Build Coastguard Worker
755*8975f5c5SAndroid Build Coastguard Worker // Every possibility must be explicitly handled.
756*8975f5c5SAndroid Build Coastguard Worker return EbpUndefined;
757*8975f5c5SAndroid Build Coastguard Worker }
758*8975f5c5SAndroid Build Coastguard Worker
759*8975f5c5SAndroid Build Coastguard Worker // Propagate precision to children nodes that don't already have it defined.
propagatePrecision(TPrecision precision)760*8975f5c5SAndroid Build Coastguard Worker void TIntermAggregate::propagatePrecision(TPrecision precision)
761*8975f5c5SAndroid Build Coastguard Worker {
762*8975f5c5SAndroid Build Coastguard Worker mType.setPrecision(precision);
763*8975f5c5SAndroid Build Coastguard Worker
764*8975f5c5SAndroid Build Coastguard Worker // For constructors, propagate precision to arguments.
765*8975f5c5SAndroid Build Coastguard Worker if (isConstructor())
766*8975f5c5SAndroid Build Coastguard Worker {
767*8975f5c5SAndroid Build Coastguard Worker for (TIntermNode *arg : mArguments)
768*8975f5c5SAndroid Build Coastguard Worker {
769*8975f5c5SAndroid Build Coastguard Worker PropagatePrecisionIfApplicable(arg->getAsTyped(), precision);
770*8975f5c5SAndroid Build Coastguard Worker }
771*8975f5c5SAndroid Build Coastguard Worker return;
772*8975f5c5SAndroid Build Coastguard Worker }
773*8975f5c5SAndroid Build Coastguard Worker
774*8975f5c5SAndroid Build Coastguard Worker // For function calls, propagate precision of each parameter to its corresponding argument.
775*8975f5c5SAndroid Build Coastguard Worker if (isFunctionCall())
776*8975f5c5SAndroid Build Coastguard Worker {
777*8975f5c5SAndroid Build Coastguard Worker for (size_t paramIndex = 0; paramIndex < mFunction->getParamCount(); ++paramIndex)
778*8975f5c5SAndroid Build Coastguard Worker {
779*8975f5c5SAndroid Build Coastguard Worker const TVariable *paramVariable = mFunction->getParam(paramIndex);
780*8975f5c5SAndroid Build Coastguard Worker PropagatePrecisionIfApplicable(mArguments[paramIndex]->getAsTyped(),
781*8975f5c5SAndroid Build Coastguard Worker paramVariable->getType().getPrecision());
782*8975f5c5SAndroid Build Coastguard Worker }
783*8975f5c5SAndroid Build Coastguard Worker return;
784*8975f5c5SAndroid Build Coastguard Worker }
785*8975f5c5SAndroid Build Coastguard Worker
786*8975f5c5SAndroid Build Coastguard Worker // Some built-ins explicitly specify the precision of their parameters.
787*8975f5c5SAndroid Build Coastguard Worker switch (mOp)
788*8975f5c5SAndroid Build Coastguard Worker {
789*8975f5c5SAndroid Build Coastguard Worker case EOpUaddCarry:
790*8975f5c5SAndroid Build Coastguard Worker case EOpUsubBorrow:
791*8975f5c5SAndroid Build Coastguard Worker case EOpUmulExtended:
792*8975f5c5SAndroid Build Coastguard Worker case EOpImulExtended:
793*8975f5c5SAndroid Build Coastguard Worker PropagatePrecisionIfApplicable(mArguments[0]->getAsTyped(), EbpHigh);
794*8975f5c5SAndroid Build Coastguard Worker PropagatePrecisionIfApplicable(mArguments[1]->getAsTyped(), EbpHigh);
795*8975f5c5SAndroid Build Coastguard Worker break;
796*8975f5c5SAndroid Build Coastguard Worker case EOpFindMSB:
797*8975f5c5SAndroid Build Coastguard Worker case EOpFrexp:
798*8975f5c5SAndroid Build Coastguard Worker case EOpLdexp:
799*8975f5c5SAndroid Build Coastguard Worker PropagatePrecisionIfApplicable(mArguments[0]->getAsTyped(), EbpHigh);
800*8975f5c5SAndroid Build Coastguard Worker break;
801*8975f5c5SAndroid Build Coastguard Worker default:
802*8975f5c5SAndroid Build Coastguard Worker break;
803*8975f5c5SAndroid Build Coastguard Worker }
804*8975f5c5SAndroid Build Coastguard Worker }
805*8975f5c5SAndroid Build Coastguard Worker
functionName() const806*8975f5c5SAndroid Build Coastguard Worker const char *TIntermAggregate::functionName() const
807*8975f5c5SAndroid Build Coastguard Worker {
808*8975f5c5SAndroid Build Coastguard Worker ASSERT(!isConstructor());
809*8975f5c5SAndroid Build Coastguard Worker switch (mOp)
810*8975f5c5SAndroid Build Coastguard Worker {
811*8975f5c5SAndroid Build Coastguard Worker case EOpCallInternalRawFunction:
812*8975f5c5SAndroid Build Coastguard Worker case EOpCallFunctionInAST:
813*8975f5c5SAndroid Build Coastguard Worker return mFunction->name().data();
814*8975f5c5SAndroid Build Coastguard Worker default:
815*8975f5c5SAndroid Build Coastguard Worker if (BuiltInGroup::IsBuiltIn(mOp))
816*8975f5c5SAndroid Build Coastguard Worker {
817*8975f5c5SAndroid Build Coastguard Worker return mFunction->name().data();
818*8975f5c5SAndroid Build Coastguard Worker }
819*8975f5c5SAndroid Build Coastguard Worker return GetOperatorString(mOp);
820*8975f5c5SAndroid Build Coastguard Worker }
821*8975f5c5SAndroid Build Coastguard Worker }
822*8975f5c5SAndroid Build Coastguard Worker
hasConstantValue() const823*8975f5c5SAndroid Build Coastguard Worker bool TIntermAggregate::hasConstantValue() const
824*8975f5c5SAndroid Build Coastguard Worker {
825*8975f5c5SAndroid Build Coastguard Worker if (!isConstructor())
826*8975f5c5SAndroid Build Coastguard Worker {
827*8975f5c5SAndroid Build Coastguard Worker return false;
828*8975f5c5SAndroid Build Coastguard Worker }
829*8975f5c5SAndroid Build Coastguard Worker for (TIntermNode *constructorArg : mArguments)
830*8975f5c5SAndroid Build Coastguard Worker {
831*8975f5c5SAndroid Build Coastguard Worker if (!constructorArg->getAsTyped()->hasConstantValue())
832*8975f5c5SAndroid Build Coastguard Worker {
833*8975f5c5SAndroid Build Coastguard Worker return false;
834*8975f5c5SAndroid Build Coastguard Worker }
835*8975f5c5SAndroid Build Coastguard Worker }
836*8975f5c5SAndroid Build Coastguard Worker return true;
837*8975f5c5SAndroid Build Coastguard Worker }
838*8975f5c5SAndroid Build Coastguard Worker
isConstantNullValue() const839*8975f5c5SAndroid Build Coastguard Worker bool TIntermAggregate::isConstantNullValue() const
840*8975f5c5SAndroid Build Coastguard Worker {
841*8975f5c5SAndroid Build Coastguard Worker if (!isConstructor())
842*8975f5c5SAndroid Build Coastguard Worker {
843*8975f5c5SAndroid Build Coastguard Worker return false;
844*8975f5c5SAndroid Build Coastguard Worker }
845*8975f5c5SAndroid Build Coastguard Worker for (TIntermNode *constructorArg : mArguments)
846*8975f5c5SAndroid Build Coastguard Worker {
847*8975f5c5SAndroid Build Coastguard Worker if (!constructorArg->getAsTyped()->isConstantNullValue())
848*8975f5c5SAndroid Build Coastguard Worker {
849*8975f5c5SAndroid Build Coastguard Worker return false;
850*8975f5c5SAndroid Build Coastguard Worker }
851*8975f5c5SAndroid Build Coastguard Worker }
852*8975f5c5SAndroid Build Coastguard Worker return true;
853*8975f5c5SAndroid Build Coastguard Worker }
854*8975f5c5SAndroid Build Coastguard Worker
getConstantValue() const855*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *TIntermAggregate::getConstantValue() const
856*8975f5c5SAndroid Build Coastguard Worker {
857*8975f5c5SAndroid Build Coastguard Worker if (!hasConstantValue())
858*8975f5c5SAndroid Build Coastguard Worker {
859*8975f5c5SAndroid Build Coastguard Worker return nullptr;
860*8975f5c5SAndroid Build Coastguard Worker }
861*8975f5c5SAndroid Build Coastguard Worker ASSERT(isConstructor());
862*8975f5c5SAndroid Build Coastguard Worker ASSERT(mArguments.size() > 0u);
863*8975f5c5SAndroid Build Coastguard Worker
864*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *constArray = nullptr;
865*8975f5c5SAndroid Build Coastguard Worker if (isArray())
866*8975f5c5SAndroid Build Coastguard Worker {
867*8975f5c5SAndroid Build Coastguard Worker size_t elementSize = mArguments.front()->getAsTyped()->getType().getObjectSize();
868*8975f5c5SAndroid Build Coastguard Worker constArray = new TConstantUnion[elementSize * getOutermostArraySize()];
869*8975f5c5SAndroid Build Coastguard Worker
870*8975f5c5SAndroid Build Coastguard Worker size_t elementOffset = 0u;
871*8975f5c5SAndroid Build Coastguard Worker for (TIntermNode *constructorArg : mArguments)
872*8975f5c5SAndroid Build Coastguard Worker {
873*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *elementConstArray =
874*8975f5c5SAndroid Build Coastguard Worker constructorArg->getAsTyped()->getConstantValue();
875*8975f5c5SAndroid Build Coastguard Worker ASSERT(elementConstArray);
876*8975f5c5SAndroid Build Coastguard Worker size_t elementSizeBytes = sizeof(TConstantUnion) * elementSize;
877*8975f5c5SAndroid Build Coastguard Worker memcpy(static_cast<void *>(&constArray[elementOffset]),
878*8975f5c5SAndroid Build Coastguard Worker static_cast<const void *>(elementConstArray), elementSizeBytes);
879*8975f5c5SAndroid Build Coastguard Worker elementOffset += elementSize;
880*8975f5c5SAndroid Build Coastguard Worker }
881*8975f5c5SAndroid Build Coastguard Worker return constArray;
882*8975f5c5SAndroid Build Coastguard Worker }
883*8975f5c5SAndroid Build Coastguard Worker
884*8975f5c5SAndroid Build Coastguard Worker size_t resultSize = getType().getObjectSize();
885*8975f5c5SAndroid Build Coastguard Worker constArray = new TConstantUnion[resultSize];
886*8975f5c5SAndroid Build Coastguard Worker TBasicType basicType = getBasicType();
887*8975f5c5SAndroid Build Coastguard Worker
888*8975f5c5SAndroid Build Coastguard Worker size_t resultIndex = 0u;
889*8975f5c5SAndroid Build Coastguard Worker
890*8975f5c5SAndroid Build Coastguard Worker if (mArguments.size() == 1u)
891*8975f5c5SAndroid Build Coastguard Worker {
892*8975f5c5SAndroid Build Coastguard Worker TIntermNode *argument = mArguments.front();
893*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *argumentTyped = argument->getAsTyped();
894*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *argumentConstantValue = argumentTyped->getConstantValue();
895*8975f5c5SAndroid Build Coastguard Worker // Check the special case of constructing a matrix diagonal from a single scalar,
896*8975f5c5SAndroid Build Coastguard Worker // or a vector from a single scalar.
897*8975f5c5SAndroid Build Coastguard Worker if (argumentTyped->getType().getObjectSize() == 1u)
898*8975f5c5SAndroid Build Coastguard Worker {
899*8975f5c5SAndroid Build Coastguard Worker if (isMatrix())
900*8975f5c5SAndroid Build Coastguard Worker {
901*8975f5c5SAndroid Build Coastguard Worker const uint8_t resultCols = getType().getCols();
902*8975f5c5SAndroid Build Coastguard Worker const uint8_t resultRows = getType().getRows();
903*8975f5c5SAndroid Build Coastguard Worker for (uint8_t col = 0; col < resultCols; ++col)
904*8975f5c5SAndroid Build Coastguard Worker {
905*8975f5c5SAndroid Build Coastguard Worker for (uint8_t row = 0; row < resultRows; ++row)
906*8975f5c5SAndroid Build Coastguard Worker {
907*8975f5c5SAndroid Build Coastguard Worker if (col == row)
908*8975f5c5SAndroid Build Coastguard Worker {
909*8975f5c5SAndroid Build Coastguard Worker constArray[resultIndex].cast(basicType, argumentConstantValue[0]);
910*8975f5c5SAndroid Build Coastguard Worker }
911*8975f5c5SAndroid Build Coastguard Worker else
912*8975f5c5SAndroid Build Coastguard Worker {
913*8975f5c5SAndroid Build Coastguard Worker constArray[resultIndex].setFConst(0.0f);
914*8975f5c5SAndroid Build Coastguard Worker }
915*8975f5c5SAndroid Build Coastguard Worker ++resultIndex;
916*8975f5c5SAndroid Build Coastguard Worker }
917*8975f5c5SAndroid Build Coastguard Worker }
918*8975f5c5SAndroid Build Coastguard Worker }
919*8975f5c5SAndroid Build Coastguard Worker else
920*8975f5c5SAndroid Build Coastguard Worker {
921*8975f5c5SAndroid Build Coastguard Worker while (resultIndex < resultSize)
922*8975f5c5SAndroid Build Coastguard Worker {
923*8975f5c5SAndroid Build Coastguard Worker constArray[resultIndex].cast(basicType, argumentConstantValue[0]);
924*8975f5c5SAndroid Build Coastguard Worker ++resultIndex;
925*8975f5c5SAndroid Build Coastguard Worker }
926*8975f5c5SAndroid Build Coastguard Worker }
927*8975f5c5SAndroid Build Coastguard Worker ASSERT(resultIndex == resultSize);
928*8975f5c5SAndroid Build Coastguard Worker return constArray;
929*8975f5c5SAndroid Build Coastguard Worker }
930*8975f5c5SAndroid Build Coastguard Worker else if (isMatrix() && argumentTyped->isMatrix())
931*8975f5c5SAndroid Build Coastguard Worker {
932*8975f5c5SAndroid Build Coastguard Worker // The special case of constructing a matrix from a matrix.
933*8975f5c5SAndroid Build Coastguard Worker const uint8_t argumentCols = argumentTyped->getType().getCols();
934*8975f5c5SAndroid Build Coastguard Worker const uint8_t argumentRows = argumentTyped->getType().getRows();
935*8975f5c5SAndroid Build Coastguard Worker const uint8_t resultCols = getType().getCols();
936*8975f5c5SAndroid Build Coastguard Worker const uint8_t resultRows = getType().getRows();
937*8975f5c5SAndroid Build Coastguard Worker for (uint8_t col = 0; col < resultCols; ++col)
938*8975f5c5SAndroid Build Coastguard Worker {
939*8975f5c5SAndroid Build Coastguard Worker for (uint8_t row = 0; row < resultRows; ++row)
940*8975f5c5SAndroid Build Coastguard Worker {
941*8975f5c5SAndroid Build Coastguard Worker if (col < argumentCols && row < argumentRows)
942*8975f5c5SAndroid Build Coastguard Worker {
943*8975f5c5SAndroid Build Coastguard Worker constArray[resultIndex].cast(
944*8975f5c5SAndroid Build Coastguard Worker basicType, argumentConstantValue[col * argumentRows + row]);
945*8975f5c5SAndroid Build Coastguard Worker }
946*8975f5c5SAndroid Build Coastguard Worker else if (col == row)
947*8975f5c5SAndroid Build Coastguard Worker {
948*8975f5c5SAndroid Build Coastguard Worker constArray[resultIndex].setFConst(1.0f);
949*8975f5c5SAndroid Build Coastguard Worker }
950*8975f5c5SAndroid Build Coastguard Worker else
951*8975f5c5SAndroid Build Coastguard Worker {
952*8975f5c5SAndroid Build Coastguard Worker constArray[resultIndex].setFConst(0.0f);
953*8975f5c5SAndroid Build Coastguard Worker }
954*8975f5c5SAndroid Build Coastguard Worker ++resultIndex;
955*8975f5c5SAndroid Build Coastguard Worker }
956*8975f5c5SAndroid Build Coastguard Worker }
957*8975f5c5SAndroid Build Coastguard Worker ASSERT(resultIndex == resultSize);
958*8975f5c5SAndroid Build Coastguard Worker return constArray;
959*8975f5c5SAndroid Build Coastguard Worker }
960*8975f5c5SAndroid Build Coastguard Worker }
961*8975f5c5SAndroid Build Coastguard Worker
962*8975f5c5SAndroid Build Coastguard Worker for (TIntermNode *argument : mArguments)
963*8975f5c5SAndroid Build Coastguard Worker {
964*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *argumentTyped = argument->getAsTyped();
965*8975f5c5SAndroid Build Coastguard Worker size_t argumentSize = argumentTyped->getType().getObjectSize();
966*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *argumentConstantValue = argumentTyped->getConstantValue();
967*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0u; i < argumentSize; ++i)
968*8975f5c5SAndroid Build Coastguard Worker {
969*8975f5c5SAndroid Build Coastguard Worker if (resultIndex >= resultSize)
970*8975f5c5SAndroid Build Coastguard Worker break;
971*8975f5c5SAndroid Build Coastguard Worker constArray[resultIndex].cast(basicType, argumentConstantValue[i]);
972*8975f5c5SAndroid Build Coastguard Worker ++resultIndex;
973*8975f5c5SAndroid Build Coastguard Worker }
974*8975f5c5SAndroid Build Coastguard Worker }
975*8975f5c5SAndroid Build Coastguard Worker ASSERT(resultIndex == resultSize);
976*8975f5c5SAndroid Build Coastguard Worker return constArray;
977*8975f5c5SAndroid Build Coastguard Worker }
978*8975f5c5SAndroid Build Coastguard Worker
hasSideEffects() const979*8975f5c5SAndroid Build Coastguard Worker bool TIntermAggregate::hasSideEffects() const
980*8975f5c5SAndroid Build Coastguard Worker {
981*8975f5c5SAndroid Build Coastguard Worker if (getQualifier() == EvqConst)
982*8975f5c5SAndroid Build Coastguard Worker {
983*8975f5c5SAndroid Build Coastguard Worker return false;
984*8975f5c5SAndroid Build Coastguard Worker }
985*8975f5c5SAndroid Build Coastguard Worker
986*8975f5c5SAndroid Build Coastguard Worker // If the function itself is known to have a side effect, the expression has a side effect.
987*8975f5c5SAndroid Build Coastguard Worker const bool calledFunctionHasSideEffects =
988*8975f5c5SAndroid Build Coastguard Worker mFunction != nullptr && !mFunction->isKnownToNotHaveSideEffects();
989*8975f5c5SAndroid Build Coastguard Worker
990*8975f5c5SAndroid Build Coastguard Worker if (calledFunctionHasSideEffects)
991*8975f5c5SAndroid Build Coastguard Worker {
992*8975f5c5SAndroid Build Coastguard Worker return true;
993*8975f5c5SAndroid Build Coastguard Worker }
994*8975f5c5SAndroid Build Coastguard Worker
995*8975f5c5SAndroid Build Coastguard Worker // Otherwise it only has a side effect if one of the arguments does.
996*8975f5c5SAndroid Build Coastguard Worker for (TIntermNode *arg : mArguments)
997*8975f5c5SAndroid Build Coastguard Worker {
998*8975f5c5SAndroid Build Coastguard Worker if (arg->getAsTyped()->hasSideEffects())
999*8975f5c5SAndroid Build Coastguard Worker {
1000*8975f5c5SAndroid Build Coastguard Worker return true;
1001*8975f5c5SAndroid Build Coastguard Worker }
1002*8975f5c5SAndroid Build Coastguard Worker }
1003*8975f5c5SAndroid Build Coastguard Worker return false;
1004*8975f5c5SAndroid Build Coastguard Worker }
1005*8975f5c5SAndroid Build Coastguard Worker
appendStatement(TIntermNode * statement)1006*8975f5c5SAndroid Build Coastguard Worker void TIntermBlock::appendStatement(TIntermNode *statement)
1007*8975f5c5SAndroid Build Coastguard Worker {
1008*8975f5c5SAndroid Build Coastguard Worker // Declaration nodes with no children can appear if it was an empty declaration or if all the
1009*8975f5c5SAndroid Build Coastguard Worker // declarators just added constants to the symbol table instead of generating code. We still
1010*8975f5c5SAndroid Build Coastguard Worker // need to add the declaration to the AST in that case because it might be relevant to the
1011*8975f5c5SAndroid Build Coastguard Worker // validity of switch/case.
1012*8975f5c5SAndroid Build Coastguard Worker if (statement != nullptr)
1013*8975f5c5SAndroid Build Coastguard Worker {
1014*8975f5c5SAndroid Build Coastguard Worker mStatements.push_back(statement);
1015*8975f5c5SAndroid Build Coastguard Worker }
1016*8975f5c5SAndroid Build Coastguard Worker }
1017*8975f5c5SAndroid Build Coastguard Worker
insertStatement(size_t insertPosition,TIntermNode * statement)1018*8975f5c5SAndroid Build Coastguard Worker void TIntermBlock::insertStatement(size_t insertPosition, TIntermNode *statement)
1019*8975f5c5SAndroid Build Coastguard Worker {
1020*8975f5c5SAndroid Build Coastguard Worker ASSERT(statement != nullptr);
1021*8975f5c5SAndroid Build Coastguard Worker mStatements.insert(mStatements.begin() + insertPosition, statement);
1022*8975f5c5SAndroid Build Coastguard Worker }
1023*8975f5c5SAndroid Build Coastguard Worker
appendDeclarator(TIntermTyped * declarator)1024*8975f5c5SAndroid Build Coastguard Worker void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator)
1025*8975f5c5SAndroid Build Coastguard Worker {
1026*8975f5c5SAndroid Build Coastguard Worker ASSERT(declarator != nullptr);
1027*8975f5c5SAndroid Build Coastguard Worker ASSERT(declarator->getAsSymbolNode() != nullptr ||
1028*8975f5c5SAndroid Build Coastguard Worker (declarator->getAsBinaryNode() != nullptr &&
1029*8975f5c5SAndroid Build Coastguard Worker declarator->getAsBinaryNode()->getOp() == EOpInitialize));
1030*8975f5c5SAndroid Build Coastguard Worker ASSERT(mDeclarators.empty() ||
1031*8975f5c5SAndroid Build Coastguard Worker declarator->getType().sameNonArrayType(mDeclarators.back()->getAsTyped()->getType()));
1032*8975f5c5SAndroid Build Coastguard Worker mDeclarators.push_back(declarator);
1033*8975f5c5SAndroid Build Coastguard Worker }
1034*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const1035*8975f5c5SAndroid Build Coastguard Worker size_t TIntermTernary::getChildCount() const
1036*8975f5c5SAndroid Build Coastguard Worker {
1037*8975f5c5SAndroid Build Coastguard Worker return 3;
1038*8975f5c5SAndroid Build Coastguard Worker }
1039*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const1040*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermTernary::getChildNode(size_t index) const
1041*8975f5c5SAndroid Build Coastguard Worker {
1042*8975f5c5SAndroid Build Coastguard Worker ASSERT(index < 3);
1043*8975f5c5SAndroid Build Coastguard Worker if (index == 0)
1044*8975f5c5SAndroid Build Coastguard Worker {
1045*8975f5c5SAndroid Build Coastguard Worker return mCondition;
1046*8975f5c5SAndroid Build Coastguard Worker }
1047*8975f5c5SAndroid Build Coastguard Worker if (index == 1)
1048*8975f5c5SAndroid Build Coastguard Worker {
1049*8975f5c5SAndroid Build Coastguard Worker return mTrueExpression;
1050*8975f5c5SAndroid Build Coastguard Worker }
1051*8975f5c5SAndroid Build Coastguard Worker return mFalseExpression;
1052*8975f5c5SAndroid Build Coastguard Worker }
1053*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)1054*8975f5c5SAndroid Build Coastguard Worker bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
1055*8975f5c5SAndroid Build Coastguard Worker {
1056*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mCondition, getAsTyped, original, replacement);
1057*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mTrueExpression, getAsTyped, original, replacement);
1058*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mFalseExpression, getAsTyped, original, replacement);
1059*8975f5c5SAndroid Build Coastguard Worker return false;
1060*8975f5c5SAndroid Build Coastguard Worker }
1061*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const1062*8975f5c5SAndroid Build Coastguard Worker size_t TIntermIfElse::getChildCount() const
1063*8975f5c5SAndroid Build Coastguard Worker {
1064*8975f5c5SAndroid Build Coastguard Worker return 1 + (mTrueBlock ? 1 : 0) + (mFalseBlock ? 1 : 0);
1065*8975f5c5SAndroid Build Coastguard Worker }
1066*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const1067*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermIfElse::getChildNode(size_t index) const
1068*8975f5c5SAndroid Build Coastguard Worker {
1069*8975f5c5SAndroid Build Coastguard Worker if (index == 0)
1070*8975f5c5SAndroid Build Coastguard Worker {
1071*8975f5c5SAndroid Build Coastguard Worker return mCondition;
1072*8975f5c5SAndroid Build Coastguard Worker }
1073*8975f5c5SAndroid Build Coastguard Worker if (mTrueBlock && index == 1)
1074*8975f5c5SAndroid Build Coastguard Worker {
1075*8975f5c5SAndroid Build Coastguard Worker return mTrueBlock;
1076*8975f5c5SAndroid Build Coastguard Worker }
1077*8975f5c5SAndroid Build Coastguard Worker return mFalseBlock;
1078*8975f5c5SAndroid Build Coastguard Worker }
1079*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)1080*8975f5c5SAndroid Build Coastguard Worker bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
1081*8975f5c5SAndroid Build Coastguard Worker {
1082*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mCondition, getAsTyped, original, replacement);
1083*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mTrueBlock, getAsBlock, original, replacement);
1084*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mFalseBlock, getAsBlock, original, replacement);
1085*8975f5c5SAndroid Build Coastguard Worker return false;
1086*8975f5c5SAndroid Build Coastguard Worker }
1087*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const1088*8975f5c5SAndroid Build Coastguard Worker size_t TIntermSwitch::getChildCount() const
1089*8975f5c5SAndroid Build Coastguard Worker {
1090*8975f5c5SAndroid Build Coastguard Worker return 2;
1091*8975f5c5SAndroid Build Coastguard Worker }
1092*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const1093*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermSwitch::getChildNode(size_t index) const
1094*8975f5c5SAndroid Build Coastguard Worker {
1095*8975f5c5SAndroid Build Coastguard Worker ASSERT(index < 2);
1096*8975f5c5SAndroid Build Coastguard Worker if (index == 0)
1097*8975f5c5SAndroid Build Coastguard Worker {
1098*8975f5c5SAndroid Build Coastguard Worker return mInit;
1099*8975f5c5SAndroid Build Coastguard Worker }
1100*8975f5c5SAndroid Build Coastguard Worker return mStatementList;
1101*8975f5c5SAndroid Build Coastguard Worker }
1102*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)1103*8975f5c5SAndroid Build Coastguard Worker bool TIntermSwitch::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
1104*8975f5c5SAndroid Build Coastguard Worker {
1105*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mInit, getAsTyped, original, replacement);
1106*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mStatementList, getAsBlock, original, replacement);
1107*8975f5c5SAndroid Build Coastguard Worker ASSERT(mStatementList);
1108*8975f5c5SAndroid Build Coastguard Worker return false;
1109*8975f5c5SAndroid Build Coastguard Worker }
1110*8975f5c5SAndroid Build Coastguard Worker
TIntermCase(const TIntermCase & node)1111*8975f5c5SAndroid Build Coastguard Worker TIntermCase::TIntermCase(const TIntermCase &node) : TIntermCase(node.mCondition->deepCopy()) {}
1112*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const1113*8975f5c5SAndroid Build Coastguard Worker size_t TIntermCase::getChildCount() const
1114*8975f5c5SAndroid Build Coastguard Worker {
1115*8975f5c5SAndroid Build Coastguard Worker return (mCondition ? 1 : 0);
1116*8975f5c5SAndroid Build Coastguard Worker }
1117*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const1118*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermCase::getChildNode(size_t index) const
1119*8975f5c5SAndroid Build Coastguard Worker {
1120*8975f5c5SAndroid Build Coastguard Worker ASSERT(index == 0);
1121*8975f5c5SAndroid Build Coastguard Worker ASSERT(mCondition);
1122*8975f5c5SAndroid Build Coastguard Worker return mCondition;
1123*8975f5c5SAndroid Build Coastguard Worker }
1124*8975f5c5SAndroid Build Coastguard Worker
replaceChildNode(TIntermNode * original,TIntermNode * replacement)1125*8975f5c5SAndroid Build Coastguard Worker bool TIntermCase::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
1126*8975f5c5SAndroid Build Coastguard Worker {
1127*8975f5c5SAndroid Build Coastguard Worker REPLACE_IF_IS(mCondition, getAsTyped, original, replacement);
1128*8975f5c5SAndroid Build Coastguard Worker return false;
1129*8975f5c5SAndroid Build Coastguard Worker }
1130*8975f5c5SAndroid Build Coastguard Worker
TIntermTyped()1131*8975f5c5SAndroid Build Coastguard Worker TIntermTyped::TIntermTyped() : mIsPrecise(false) {}
TIntermTyped(const TIntermTyped & node)1132*8975f5c5SAndroid Build Coastguard Worker TIntermTyped::TIntermTyped(const TIntermTyped &node) : TIntermTyped()
1133*8975f5c5SAndroid Build Coastguard Worker {
1134*8975f5c5SAndroid Build Coastguard Worker // Copy constructor is disallowed for TIntermNode in order to disallow it for subclasses that
1135*8975f5c5SAndroid Build Coastguard Worker // don't explicitly allow it, so normal TIntermNode constructor is used to construct the copy.
1136*8975f5c5SAndroid Build Coastguard Worker // We need to manually copy any fields of TIntermNode.
1137*8975f5c5SAndroid Build Coastguard Worker mLine = node.mLine;
1138*8975f5c5SAndroid Build Coastguard Worker
1139*8975f5c5SAndroid Build Coastguard Worker // Once deteremined, the tree is not expected to transform.
1140*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mIsPrecise);
1141*8975f5c5SAndroid Build Coastguard Worker }
1142*8975f5c5SAndroid Build Coastguard Worker
hasConstantValue() const1143*8975f5c5SAndroid Build Coastguard Worker bool TIntermTyped::hasConstantValue() const
1144*8975f5c5SAndroid Build Coastguard Worker {
1145*8975f5c5SAndroid Build Coastguard Worker return false;
1146*8975f5c5SAndroid Build Coastguard Worker }
1147*8975f5c5SAndroid Build Coastguard Worker
isConstantNullValue() const1148*8975f5c5SAndroid Build Coastguard Worker bool TIntermTyped::isConstantNullValue() const
1149*8975f5c5SAndroid Build Coastguard Worker {
1150*8975f5c5SAndroid Build Coastguard Worker return false;
1151*8975f5c5SAndroid Build Coastguard Worker }
1152*8975f5c5SAndroid Build Coastguard Worker
getConstantValue() const1153*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *TIntermTyped::getConstantValue() const
1154*8975f5c5SAndroid Build Coastguard Worker {
1155*8975f5c5SAndroid Build Coastguard Worker return nullptr;
1156*8975f5c5SAndroid Build Coastguard Worker }
1157*8975f5c5SAndroid Build Coastguard Worker
derivePrecision() const1158*8975f5c5SAndroid Build Coastguard Worker TPrecision TIntermTyped::derivePrecision() const
1159*8975f5c5SAndroid Build Coastguard Worker {
1160*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
1161*8975f5c5SAndroid Build Coastguard Worker return EbpUndefined;
1162*8975f5c5SAndroid Build Coastguard Worker }
1163*8975f5c5SAndroid Build Coastguard Worker
propagatePrecision(TPrecision precision)1164*8975f5c5SAndroid Build Coastguard Worker void TIntermTyped::propagatePrecision(TPrecision precision)
1165*8975f5c5SAndroid Build Coastguard Worker {
1166*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
1167*8975f5c5SAndroid Build Coastguard Worker }
1168*8975f5c5SAndroid Build Coastguard Worker
TIntermConstantUnion(const TIntermConstantUnion & node)1169*8975f5c5SAndroid Build Coastguard Worker TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node)
1170*8975f5c5SAndroid Build Coastguard Worker : TIntermExpression(node)
1171*8975f5c5SAndroid Build Coastguard Worker {
1172*8975f5c5SAndroid Build Coastguard Worker mUnionArrayPointer = node.mUnionArrayPointer;
1173*8975f5c5SAndroid Build Coastguard Worker }
1174*8975f5c5SAndroid Build Coastguard Worker
TIntermFunctionPrototype(const TFunction * function)1175*8975f5c5SAndroid Build Coastguard Worker TIntermFunctionPrototype::TIntermFunctionPrototype(const TFunction *function)
1176*8975f5c5SAndroid Build Coastguard Worker : TIntermTyped(), mFunction(function)
1177*8975f5c5SAndroid Build Coastguard Worker {
1178*8975f5c5SAndroid Build Coastguard Worker ASSERT(mFunction->symbolType() != SymbolType::Empty);
1179*8975f5c5SAndroid Build Coastguard Worker }
1180*8975f5c5SAndroid Build Coastguard Worker
getType() const1181*8975f5c5SAndroid Build Coastguard Worker const TType &TIntermFunctionPrototype::getType() const
1182*8975f5c5SAndroid Build Coastguard Worker {
1183*8975f5c5SAndroid Build Coastguard Worker return mFunction->getReturnType();
1184*8975f5c5SAndroid Build Coastguard Worker }
1185*8975f5c5SAndroid Build Coastguard Worker
TIntermAggregate(const TIntermAggregate & node)1186*8975f5c5SAndroid Build Coastguard Worker TIntermAggregate::TIntermAggregate(const TIntermAggregate &node)
1187*8975f5c5SAndroid Build Coastguard Worker : TIntermOperator(node),
1188*8975f5c5SAndroid Build Coastguard Worker mUseEmulatedFunction(node.mUseEmulatedFunction),
1189*8975f5c5SAndroid Build Coastguard Worker mFunction(node.mFunction)
1190*8975f5c5SAndroid Build Coastguard Worker {
1191*8975f5c5SAndroid Build Coastguard Worker for (TIntermNode *arg : node.mArguments)
1192*8975f5c5SAndroid Build Coastguard Worker {
1193*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *typedArg = arg->getAsTyped();
1194*8975f5c5SAndroid Build Coastguard Worker ASSERT(typedArg != nullptr);
1195*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *argCopy = typedArg->deepCopy();
1196*8975f5c5SAndroid Build Coastguard Worker mArguments.push_back(argCopy);
1197*8975f5c5SAndroid Build Coastguard Worker }
1198*8975f5c5SAndroid Build Coastguard Worker }
1199*8975f5c5SAndroid Build Coastguard Worker
shallowCopy() const1200*8975f5c5SAndroid Build Coastguard Worker TIntermAggregate *TIntermAggregate::shallowCopy() const
1201*8975f5c5SAndroid Build Coastguard Worker {
1202*8975f5c5SAndroid Build Coastguard Worker TIntermSequence copySeq;
1203*8975f5c5SAndroid Build Coastguard Worker copySeq.insert(copySeq.begin(), getSequence()->begin(), getSequence()->end());
1204*8975f5c5SAndroid Build Coastguard Worker TIntermAggregate *copyNode = new TIntermAggregate(mFunction, mType, mOp, ©Seq);
1205*8975f5c5SAndroid Build Coastguard Worker copyNode->setLine(mLine);
1206*8975f5c5SAndroid Build Coastguard Worker return copyNode;
1207*8975f5c5SAndroid Build Coastguard Worker }
1208*8975f5c5SAndroid Build Coastguard Worker
TIntermSwizzle(const TIntermSwizzle & node)1209*8975f5c5SAndroid Build Coastguard Worker TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermExpression(node)
1210*8975f5c5SAndroid Build Coastguard Worker {
1211*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *operandCopy = node.mOperand->deepCopy();
1212*8975f5c5SAndroid Build Coastguard Worker ASSERT(operandCopy != nullptr);
1213*8975f5c5SAndroid Build Coastguard Worker mOperand = operandCopy;
1214*8975f5c5SAndroid Build Coastguard Worker mSwizzleOffsets = node.mSwizzleOffsets;
1215*8975f5c5SAndroid Build Coastguard Worker mHasFoldedDuplicateOffsets = node.mHasFoldedDuplicateOffsets;
1216*8975f5c5SAndroid Build Coastguard Worker }
1217*8975f5c5SAndroid Build Coastguard Worker
TIntermBinary(const TIntermBinary & node)1218*8975f5c5SAndroid Build Coastguard Worker TIntermBinary::TIntermBinary(const TIntermBinary &node) : TIntermOperator(node)
1219*8975f5c5SAndroid Build Coastguard Worker {
1220*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *leftCopy = node.mLeft->deepCopy();
1221*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *rightCopy = node.mRight->deepCopy();
1222*8975f5c5SAndroid Build Coastguard Worker ASSERT(leftCopy != nullptr && rightCopy != nullptr);
1223*8975f5c5SAndroid Build Coastguard Worker mLeft = leftCopy;
1224*8975f5c5SAndroid Build Coastguard Worker mRight = rightCopy;
1225*8975f5c5SAndroid Build Coastguard Worker }
1226*8975f5c5SAndroid Build Coastguard Worker
TIntermUnary(const TIntermUnary & node)1227*8975f5c5SAndroid Build Coastguard Worker TIntermUnary::TIntermUnary(const TIntermUnary &node)
1228*8975f5c5SAndroid Build Coastguard Worker : TIntermOperator(node),
1229*8975f5c5SAndroid Build Coastguard Worker mUseEmulatedFunction(node.mUseEmulatedFunction),
1230*8975f5c5SAndroid Build Coastguard Worker mFunction(node.mFunction)
1231*8975f5c5SAndroid Build Coastguard Worker {
1232*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *operandCopy = node.mOperand->deepCopy();
1233*8975f5c5SAndroid Build Coastguard Worker ASSERT(operandCopy != nullptr);
1234*8975f5c5SAndroid Build Coastguard Worker mOperand = operandCopy;
1235*8975f5c5SAndroid Build Coastguard Worker }
1236*8975f5c5SAndroid Build Coastguard Worker
TIntermTernary(const TIntermTernary & node)1237*8975f5c5SAndroid Build Coastguard Worker TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermExpression(node)
1238*8975f5c5SAndroid Build Coastguard Worker {
1239*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *conditionCopy = node.mCondition->deepCopy();
1240*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *trueCopy = node.mTrueExpression->deepCopy();
1241*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *falseCopy = node.mFalseExpression->deepCopy();
1242*8975f5c5SAndroid Build Coastguard Worker ASSERT(conditionCopy != nullptr && trueCopy != nullptr && falseCopy != nullptr);
1243*8975f5c5SAndroid Build Coastguard Worker mCondition = conditionCopy;
1244*8975f5c5SAndroid Build Coastguard Worker mTrueExpression = trueCopy;
1245*8975f5c5SAndroid Build Coastguard Worker mFalseExpression = falseCopy;
1246*8975f5c5SAndroid Build Coastguard Worker }
1247*8975f5c5SAndroid Build Coastguard Worker
isAssignment() const1248*8975f5c5SAndroid Build Coastguard Worker bool TIntermOperator::isAssignment() const
1249*8975f5c5SAndroid Build Coastguard Worker {
1250*8975f5c5SAndroid Build Coastguard Worker return IsAssignment(mOp);
1251*8975f5c5SAndroid Build Coastguard Worker }
1252*8975f5c5SAndroid Build Coastguard Worker
isMultiplication() const1253*8975f5c5SAndroid Build Coastguard Worker bool TIntermOperator::isMultiplication() const
1254*8975f5c5SAndroid Build Coastguard Worker {
1255*8975f5c5SAndroid Build Coastguard Worker switch (mOp)
1256*8975f5c5SAndroid Build Coastguard Worker {
1257*8975f5c5SAndroid Build Coastguard Worker case EOpMul:
1258*8975f5c5SAndroid Build Coastguard Worker case EOpMatrixTimesMatrix:
1259*8975f5c5SAndroid Build Coastguard Worker case EOpMatrixTimesVector:
1260*8975f5c5SAndroid Build Coastguard Worker case EOpMatrixTimesScalar:
1261*8975f5c5SAndroid Build Coastguard Worker case EOpVectorTimesMatrix:
1262*8975f5c5SAndroid Build Coastguard Worker case EOpVectorTimesScalar:
1263*8975f5c5SAndroid Build Coastguard Worker return true;
1264*8975f5c5SAndroid Build Coastguard Worker default:
1265*8975f5c5SAndroid Build Coastguard Worker return false;
1266*8975f5c5SAndroid Build Coastguard Worker }
1267*8975f5c5SAndroid Build Coastguard Worker }
1268*8975f5c5SAndroid Build Coastguard Worker
isConstructor() const1269*8975f5c5SAndroid Build Coastguard Worker bool TIntermOperator::isConstructor() const
1270*8975f5c5SAndroid Build Coastguard Worker {
1271*8975f5c5SAndroid Build Coastguard Worker return (mOp == EOpConstruct);
1272*8975f5c5SAndroid Build Coastguard Worker }
1273*8975f5c5SAndroid Build Coastguard Worker
isFunctionCall() const1274*8975f5c5SAndroid Build Coastguard Worker bool TIntermOperator::isFunctionCall() const
1275*8975f5c5SAndroid Build Coastguard Worker {
1276*8975f5c5SAndroid Build Coastguard Worker switch (mOp)
1277*8975f5c5SAndroid Build Coastguard Worker {
1278*8975f5c5SAndroid Build Coastguard Worker case EOpCallFunctionInAST:
1279*8975f5c5SAndroid Build Coastguard Worker case EOpCallInternalRawFunction:
1280*8975f5c5SAndroid Build Coastguard Worker return true;
1281*8975f5c5SAndroid Build Coastguard Worker default:
1282*8975f5c5SAndroid Build Coastguard Worker return false;
1283*8975f5c5SAndroid Build Coastguard Worker }
1284*8975f5c5SAndroid Build Coastguard Worker }
1285*8975f5c5SAndroid Build Coastguard Worker
GetMulOpBasedOnOperands(const TType & left,const TType & right)1286*8975f5c5SAndroid Build Coastguard Worker TOperator TIntermBinary::GetMulOpBasedOnOperands(const TType &left, const TType &right)
1287*8975f5c5SAndroid Build Coastguard Worker {
1288*8975f5c5SAndroid Build Coastguard Worker if (left.isMatrix())
1289*8975f5c5SAndroid Build Coastguard Worker {
1290*8975f5c5SAndroid Build Coastguard Worker if (right.isMatrix())
1291*8975f5c5SAndroid Build Coastguard Worker {
1292*8975f5c5SAndroid Build Coastguard Worker return EOpMatrixTimesMatrix;
1293*8975f5c5SAndroid Build Coastguard Worker }
1294*8975f5c5SAndroid Build Coastguard Worker else
1295*8975f5c5SAndroid Build Coastguard Worker {
1296*8975f5c5SAndroid Build Coastguard Worker if (right.isVector())
1297*8975f5c5SAndroid Build Coastguard Worker {
1298*8975f5c5SAndroid Build Coastguard Worker return EOpMatrixTimesVector;
1299*8975f5c5SAndroid Build Coastguard Worker }
1300*8975f5c5SAndroid Build Coastguard Worker else
1301*8975f5c5SAndroid Build Coastguard Worker {
1302*8975f5c5SAndroid Build Coastguard Worker return EOpMatrixTimesScalar;
1303*8975f5c5SAndroid Build Coastguard Worker }
1304*8975f5c5SAndroid Build Coastguard Worker }
1305*8975f5c5SAndroid Build Coastguard Worker }
1306*8975f5c5SAndroid Build Coastguard Worker else
1307*8975f5c5SAndroid Build Coastguard Worker {
1308*8975f5c5SAndroid Build Coastguard Worker if (right.isMatrix())
1309*8975f5c5SAndroid Build Coastguard Worker {
1310*8975f5c5SAndroid Build Coastguard Worker if (left.isVector())
1311*8975f5c5SAndroid Build Coastguard Worker {
1312*8975f5c5SAndroid Build Coastguard Worker return EOpVectorTimesMatrix;
1313*8975f5c5SAndroid Build Coastguard Worker }
1314*8975f5c5SAndroid Build Coastguard Worker else
1315*8975f5c5SAndroid Build Coastguard Worker {
1316*8975f5c5SAndroid Build Coastguard Worker return EOpMatrixTimesScalar;
1317*8975f5c5SAndroid Build Coastguard Worker }
1318*8975f5c5SAndroid Build Coastguard Worker }
1319*8975f5c5SAndroid Build Coastguard Worker else
1320*8975f5c5SAndroid Build Coastguard Worker {
1321*8975f5c5SAndroid Build Coastguard Worker // Neither operand is a matrix.
1322*8975f5c5SAndroid Build Coastguard Worker if (left.isVector() == right.isVector())
1323*8975f5c5SAndroid Build Coastguard Worker {
1324*8975f5c5SAndroid Build Coastguard Worker // Leave as component product.
1325*8975f5c5SAndroid Build Coastguard Worker return EOpMul;
1326*8975f5c5SAndroid Build Coastguard Worker }
1327*8975f5c5SAndroid Build Coastguard Worker else
1328*8975f5c5SAndroid Build Coastguard Worker {
1329*8975f5c5SAndroid Build Coastguard Worker return EOpVectorTimesScalar;
1330*8975f5c5SAndroid Build Coastguard Worker }
1331*8975f5c5SAndroid Build Coastguard Worker }
1332*8975f5c5SAndroid Build Coastguard Worker }
1333*8975f5c5SAndroid Build Coastguard Worker }
1334*8975f5c5SAndroid Build Coastguard Worker
GetMulAssignOpBasedOnOperands(const TType & left,const TType & right)1335*8975f5c5SAndroid Build Coastguard Worker TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const TType &right)
1336*8975f5c5SAndroid Build Coastguard Worker {
1337*8975f5c5SAndroid Build Coastguard Worker if (left.isMatrix())
1338*8975f5c5SAndroid Build Coastguard Worker {
1339*8975f5c5SAndroid Build Coastguard Worker if (right.isMatrix())
1340*8975f5c5SAndroid Build Coastguard Worker {
1341*8975f5c5SAndroid Build Coastguard Worker return EOpMatrixTimesMatrixAssign;
1342*8975f5c5SAndroid Build Coastguard Worker }
1343*8975f5c5SAndroid Build Coastguard Worker else
1344*8975f5c5SAndroid Build Coastguard Worker {
1345*8975f5c5SAndroid Build Coastguard Worker // right should be scalar, but this may not be validated yet.
1346*8975f5c5SAndroid Build Coastguard Worker return EOpMatrixTimesScalarAssign;
1347*8975f5c5SAndroid Build Coastguard Worker }
1348*8975f5c5SAndroid Build Coastguard Worker }
1349*8975f5c5SAndroid Build Coastguard Worker else
1350*8975f5c5SAndroid Build Coastguard Worker {
1351*8975f5c5SAndroid Build Coastguard Worker if (right.isMatrix())
1352*8975f5c5SAndroid Build Coastguard Worker {
1353*8975f5c5SAndroid Build Coastguard Worker // Left should be a vector, but this may not be validated yet.
1354*8975f5c5SAndroid Build Coastguard Worker return EOpVectorTimesMatrixAssign;
1355*8975f5c5SAndroid Build Coastguard Worker }
1356*8975f5c5SAndroid Build Coastguard Worker else
1357*8975f5c5SAndroid Build Coastguard Worker {
1358*8975f5c5SAndroid Build Coastguard Worker // Neither operand is a matrix.
1359*8975f5c5SAndroid Build Coastguard Worker if (left.isVector() == right.isVector())
1360*8975f5c5SAndroid Build Coastguard Worker {
1361*8975f5c5SAndroid Build Coastguard Worker // Leave as component product.
1362*8975f5c5SAndroid Build Coastguard Worker return EOpMulAssign;
1363*8975f5c5SAndroid Build Coastguard Worker }
1364*8975f5c5SAndroid Build Coastguard Worker else
1365*8975f5c5SAndroid Build Coastguard Worker {
1366*8975f5c5SAndroid Build Coastguard Worker // left should be vector and right should be scalar, but this may not be validated
1367*8975f5c5SAndroid Build Coastguard Worker // yet.
1368*8975f5c5SAndroid Build Coastguard Worker return EOpVectorTimesScalarAssign;
1369*8975f5c5SAndroid Build Coastguard Worker }
1370*8975f5c5SAndroid Build Coastguard Worker }
1371*8975f5c5SAndroid Build Coastguard Worker }
1372*8975f5c5SAndroid Build Coastguard Worker }
1373*8975f5c5SAndroid Build Coastguard Worker
1374*8975f5c5SAndroid Build Coastguard Worker //
1375*8975f5c5SAndroid Build Coastguard Worker // Make sure the type of a unary operator is appropriate for its
1376*8975f5c5SAndroid Build Coastguard Worker // combination of operation and operand type.
1377*8975f5c5SAndroid Build Coastguard Worker //
promote()1378*8975f5c5SAndroid Build Coastguard Worker void TIntermUnary::promote()
1379*8975f5c5SAndroid Build Coastguard Worker {
1380*8975f5c5SAndroid Build Coastguard Worker if (mOp == EOpArrayLength)
1381*8975f5c5SAndroid Build Coastguard Worker {
1382*8975f5c5SAndroid Build Coastguard Worker // Special case: the qualifier of .length() doesn't depend on the operand qualifier.
1383*8975f5c5SAndroid Build Coastguard Worker setType(TType(EbtInt, EbpHigh, EvqConst));
1384*8975f5c5SAndroid Build Coastguard Worker return;
1385*8975f5c5SAndroid Build Coastguard Worker }
1386*8975f5c5SAndroid Build Coastguard Worker
1387*8975f5c5SAndroid Build Coastguard Worker TQualifier resultQualifier = EvqTemporary;
1388*8975f5c5SAndroid Build Coastguard Worker if (mOperand->getQualifier() == EvqConst)
1389*8975f5c5SAndroid Build Coastguard Worker resultQualifier = EvqConst;
1390*8975f5c5SAndroid Build Coastguard Worker
1391*8975f5c5SAndroid Build Coastguard Worker TType resultType = mOperand->getType();
1392*8975f5c5SAndroid Build Coastguard Worker resultType.setQualifier(resultQualifier);
1393*8975f5c5SAndroid Build Coastguard Worker
1394*8975f5c5SAndroid Build Coastguard Worker // Result is an intermediate value, so make sure it's identified as such.
1395*8975f5c5SAndroid Build Coastguard Worker resultType.setInterfaceBlock(nullptr);
1396*8975f5c5SAndroid Build Coastguard Worker
1397*8975f5c5SAndroid Build Coastguard Worker // Override type properties for special built-ins. Precision is determined later by
1398*8975f5c5SAndroid Build Coastguard Worker // |derivePrecision|.
1399*8975f5c5SAndroid Build Coastguard Worker switch (mOp)
1400*8975f5c5SAndroid Build Coastguard Worker {
1401*8975f5c5SAndroid Build Coastguard Worker case EOpFloatBitsToInt:
1402*8975f5c5SAndroid Build Coastguard Worker resultType.setBasicType(EbtInt);
1403*8975f5c5SAndroid Build Coastguard Worker break;
1404*8975f5c5SAndroid Build Coastguard Worker case EOpFloatBitsToUint:
1405*8975f5c5SAndroid Build Coastguard Worker resultType.setBasicType(EbtUInt);
1406*8975f5c5SAndroid Build Coastguard Worker break;
1407*8975f5c5SAndroid Build Coastguard Worker case EOpIntBitsToFloat:
1408*8975f5c5SAndroid Build Coastguard Worker case EOpUintBitsToFloat:
1409*8975f5c5SAndroid Build Coastguard Worker resultType.setBasicType(EbtFloat);
1410*8975f5c5SAndroid Build Coastguard Worker break;
1411*8975f5c5SAndroid Build Coastguard Worker case EOpPackSnorm2x16:
1412*8975f5c5SAndroid Build Coastguard Worker case EOpPackUnorm2x16:
1413*8975f5c5SAndroid Build Coastguard Worker case EOpPackHalf2x16:
1414*8975f5c5SAndroid Build Coastguard Worker case EOpPackUnorm4x8:
1415*8975f5c5SAndroid Build Coastguard Worker case EOpPackSnorm4x8:
1416*8975f5c5SAndroid Build Coastguard Worker resultType.setBasicType(EbtUInt);
1417*8975f5c5SAndroid Build Coastguard Worker resultType.setPrimarySize(1);
1418*8975f5c5SAndroid Build Coastguard Worker break;
1419*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackSnorm2x16:
1420*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackUnorm2x16:
1421*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackHalf2x16:
1422*8975f5c5SAndroid Build Coastguard Worker resultType.setBasicType(EbtFloat);
1423*8975f5c5SAndroid Build Coastguard Worker resultType.setPrimarySize(2);
1424*8975f5c5SAndroid Build Coastguard Worker break;
1425*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackUnorm4x8:
1426*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackSnorm4x8:
1427*8975f5c5SAndroid Build Coastguard Worker resultType.setBasicType(EbtFloat);
1428*8975f5c5SAndroid Build Coastguard Worker resultType.setPrimarySize(4);
1429*8975f5c5SAndroid Build Coastguard Worker break;
1430*8975f5c5SAndroid Build Coastguard Worker case EOpAny:
1431*8975f5c5SAndroid Build Coastguard Worker case EOpAll:
1432*8975f5c5SAndroid Build Coastguard Worker resultType.setBasicType(EbtBool);
1433*8975f5c5SAndroid Build Coastguard Worker resultType.setPrimarySize(1);
1434*8975f5c5SAndroid Build Coastguard Worker break;
1435*8975f5c5SAndroid Build Coastguard Worker case EOpLength:
1436*8975f5c5SAndroid Build Coastguard Worker case EOpDeterminant:
1437*8975f5c5SAndroid Build Coastguard Worker resultType.setBasicType(EbtFloat);
1438*8975f5c5SAndroid Build Coastguard Worker resultType.setPrimarySize(1);
1439*8975f5c5SAndroid Build Coastguard Worker resultType.setSecondarySize(1);
1440*8975f5c5SAndroid Build Coastguard Worker break;
1441*8975f5c5SAndroid Build Coastguard Worker case EOpTranspose:
1442*8975f5c5SAndroid Build Coastguard Worker ASSERT(resultType.getBasicType() == EbtFloat);
1443*8975f5c5SAndroid Build Coastguard Worker resultType.setPrimarySize(mOperand->getType().getRows());
1444*8975f5c5SAndroid Build Coastguard Worker resultType.setSecondarySize(mOperand->getType().getCols());
1445*8975f5c5SAndroid Build Coastguard Worker break;
1446*8975f5c5SAndroid Build Coastguard Worker case EOpIsinf:
1447*8975f5c5SAndroid Build Coastguard Worker case EOpIsnan:
1448*8975f5c5SAndroid Build Coastguard Worker resultType.setBasicType(EbtBool);
1449*8975f5c5SAndroid Build Coastguard Worker break;
1450*8975f5c5SAndroid Build Coastguard Worker case EOpBitCount:
1451*8975f5c5SAndroid Build Coastguard Worker case EOpFindLSB:
1452*8975f5c5SAndroid Build Coastguard Worker case EOpFindMSB:
1453*8975f5c5SAndroid Build Coastguard Worker resultType.setBasicType(EbtInt);
1454*8975f5c5SAndroid Build Coastguard Worker break;
1455*8975f5c5SAndroid Build Coastguard Worker default:
1456*8975f5c5SAndroid Build Coastguard Worker break;
1457*8975f5c5SAndroid Build Coastguard Worker }
1458*8975f5c5SAndroid Build Coastguard Worker
1459*8975f5c5SAndroid Build Coastguard Worker setType(resultType);
1460*8975f5c5SAndroid Build Coastguard Worker propagatePrecision(derivePrecision());
1461*8975f5c5SAndroid Build Coastguard Worker }
1462*8975f5c5SAndroid Build Coastguard Worker
1463*8975f5c5SAndroid Build Coastguard Worker // Derive precision from children nodes
derivePrecision() const1464*8975f5c5SAndroid Build Coastguard Worker TPrecision TIntermUnary::derivePrecision() const
1465*8975f5c5SAndroid Build Coastguard Worker {
1466*8975f5c5SAndroid Build Coastguard Worker // Unary operators generally derive their precision from their operand, except for a few
1467*8975f5c5SAndroid Build Coastguard Worker // built-ins where this is overriden.
1468*8975f5c5SAndroid Build Coastguard Worker switch (mOp)
1469*8975f5c5SAndroid Build Coastguard Worker {
1470*8975f5c5SAndroid Build Coastguard Worker case EOpArrayLength:
1471*8975f5c5SAndroid Build Coastguard Worker case EOpFloatBitsToInt:
1472*8975f5c5SAndroid Build Coastguard Worker case EOpFloatBitsToUint:
1473*8975f5c5SAndroid Build Coastguard Worker case EOpIntBitsToFloat:
1474*8975f5c5SAndroid Build Coastguard Worker case EOpUintBitsToFloat:
1475*8975f5c5SAndroid Build Coastguard Worker case EOpPackSnorm2x16:
1476*8975f5c5SAndroid Build Coastguard Worker case EOpPackUnorm2x16:
1477*8975f5c5SAndroid Build Coastguard Worker case EOpPackHalf2x16:
1478*8975f5c5SAndroid Build Coastguard Worker case EOpPackUnorm4x8:
1479*8975f5c5SAndroid Build Coastguard Worker case EOpPackSnorm4x8:
1480*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackSnorm2x16:
1481*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackUnorm2x16:
1482*8975f5c5SAndroid Build Coastguard Worker case EOpBitfieldReverse:
1483*8975f5c5SAndroid Build Coastguard Worker return EbpHigh;
1484*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackHalf2x16:
1485*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackUnorm4x8:
1486*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackSnorm4x8:
1487*8975f5c5SAndroid Build Coastguard Worker return EbpMedium;
1488*8975f5c5SAndroid Build Coastguard Worker case EOpBitCount:
1489*8975f5c5SAndroid Build Coastguard Worker case EOpFindLSB:
1490*8975f5c5SAndroid Build Coastguard Worker case EOpFindMSB:
1491*8975f5c5SAndroid Build Coastguard Worker return EbpLow;
1492*8975f5c5SAndroid Build Coastguard Worker case EOpAny:
1493*8975f5c5SAndroid Build Coastguard Worker case EOpAll:
1494*8975f5c5SAndroid Build Coastguard Worker case EOpIsinf:
1495*8975f5c5SAndroid Build Coastguard Worker case EOpIsnan:
1496*8975f5c5SAndroid Build Coastguard Worker return EbpUndefined;
1497*8975f5c5SAndroid Build Coastguard Worker default:
1498*8975f5c5SAndroid Build Coastguard Worker return mOperand->getPrecision();
1499*8975f5c5SAndroid Build Coastguard Worker }
1500*8975f5c5SAndroid Build Coastguard Worker }
1501*8975f5c5SAndroid Build Coastguard Worker
propagatePrecision(TPrecision precision)1502*8975f5c5SAndroid Build Coastguard Worker void TIntermUnary::propagatePrecision(TPrecision precision)
1503*8975f5c5SAndroid Build Coastguard Worker {
1504*8975f5c5SAndroid Build Coastguard Worker mType.setPrecision(precision);
1505*8975f5c5SAndroid Build Coastguard Worker
1506*8975f5c5SAndroid Build Coastguard Worker // Generally precision of the operand and the precision of the result match. A few built-ins
1507*8975f5c5SAndroid Build Coastguard Worker // are exceptional.
1508*8975f5c5SAndroid Build Coastguard Worker switch (mOp)
1509*8975f5c5SAndroid Build Coastguard Worker {
1510*8975f5c5SAndroid Build Coastguard Worker case EOpArrayLength:
1511*8975f5c5SAndroid Build Coastguard Worker case EOpPackSnorm2x16:
1512*8975f5c5SAndroid Build Coastguard Worker case EOpPackUnorm2x16:
1513*8975f5c5SAndroid Build Coastguard Worker case EOpPackUnorm4x8:
1514*8975f5c5SAndroid Build Coastguard Worker case EOpPackSnorm4x8:
1515*8975f5c5SAndroid Build Coastguard Worker case EOpPackHalf2x16:
1516*8975f5c5SAndroid Build Coastguard Worker case EOpBitCount:
1517*8975f5c5SAndroid Build Coastguard Worker case EOpFindLSB:
1518*8975f5c5SAndroid Build Coastguard Worker case EOpFindMSB:
1519*8975f5c5SAndroid Build Coastguard Worker case EOpIsinf:
1520*8975f5c5SAndroid Build Coastguard Worker case EOpIsnan:
1521*8975f5c5SAndroid Build Coastguard Worker // Precision of result does not affect the operand in any way.
1522*8975f5c5SAndroid Build Coastguard Worker break;
1523*8975f5c5SAndroid Build Coastguard Worker case EOpFloatBitsToInt:
1524*8975f5c5SAndroid Build Coastguard Worker case EOpFloatBitsToUint:
1525*8975f5c5SAndroid Build Coastguard Worker case EOpIntBitsToFloat:
1526*8975f5c5SAndroid Build Coastguard Worker case EOpUintBitsToFloat:
1527*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackSnorm2x16:
1528*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackUnorm2x16:
1529*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackUnorm4x8:
1530*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackSnorm4x8:
1531*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackHalf2x16:
1532*8975f5c5SAndroid Build Coastguard Worker case EOpBitfieldReverse:
1533*8975f5c5SAndroid Build Coastguard Worker PropagatePrecisionIfApplicable(mOperand, EbpHigh);
1534*8975f5c5SAndroid Build Coastguard Worker break;
1535*8975f5c5SAndroid Build Coastguard Worker default:
1536*8975f5c5SAndroid Build Coastguard Worker PropagatePrecisionIfApplicable(mOperand, precision);
1537*8975f5c5SAndroid Build Coastguard Worker }
1538*8975f5c5SAndroid Build Coastguard Worker }
1539*8975f5c5SAndroid Build Coastguard Worker
TIntermSwizzle(TIntermTyped * operand,const TVector<int> & swizzleOffsets)1540*8975f5c5SAndroid Build Coastguard Worker TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets)
1541*8975f5c5SAndroid Build Coastguard Worker : TIntermExpression(TType(EbtFloat, EbpUndefined)),
1542*8975f5c5SAndroid Build Coastguard Worker mOperand(operand),
1543*8975f5c5SAndroid Build Coastguard Worker mSwizzleOffsets(swizzleOffsets),
1544*8975f5c5SAndroid Build Coastguard Worker mHasFoldedDuplicateOffsets(false)
1545*8975f5c5SAndroid Build Coastguard Worker {
1546*8975f5c5SAndroid Build Coastguard Worker ASSERT(mOperand);
1547*8975f5c5SAndroid Build Coastguard Worker ASSERT(mOperand->getType().isVector());
1548*8975f5c5SAndroid Build Coastguard Worker ASSERT(mSwizzleOffsets.size() <= 4);
1549*8975f5c5SAndroid Build Coastguard Worker promote();
1550*8975f5c5SAndroid Build Coastguard Worker }
1551*8975f5c5SAndroid Build Coastguard Worker
TIntermUnary(TOperator op,TIntermTyped * operand,const TFunction * function)1552*8975f5c5SAndroid Build Coastguard Worker TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function)
1553*8975f5c5SAndroid Build Coastguard Worker : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false), mFunction(function)
1554*8975f5c5SAndroid Build Coastguard Worker {
1555*8975f5c5SAndroid Build Coastguard Worker ASSERT(mOperand);
1556*8975f5c5SAndroid Build Coastguard Worker ASSERT(!BuiltInGroup::IsBuiltIn(op) || (function != nullptr && function->getBuiltInOp() == op));
1557*8975f5c5SAndroid Build Coastguard Worker promote();
1558*8975f5c5SAndroid Build Coastguard Worker }
1559*8975f5c5SAndroid Build Coastguard Worker
TIntermBinary(TOperator op,TIntermTyped * left,TIntermTyped * right)1560*8975f5c5SAndroid Build Coastguard Worker TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right)
1561*8975f5c5SAndroid Build Coastguard Worker : TIntermOperator(op), mLeft(left), mRight(right)
1562*8975f5c5SAndroid Build Coastguard Worker {
1563*8975f5c5SAndroid Build Coastguard Worker ASSERT(mLeft);
1564*8975f5c5SAndroid Build Coastguard Worker ASSERT(mRight);
1565*8975f5c5SAndroid Build Coastguard Worker promote();
1566*8975f5c5SAndroid Build Coastguard Worker }
1567*8975f5c5SAndroid Build Coastguard Worker
CreateComma(TIntermTyped * left,TIntermTyped * right,int shaderVersion)1568*8975f5c5SAndroid Build Coastguard Worker TIntermBinary *TIntermBinary::CreateComma(TIntermTyped *left,
1569*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *right,
1570*8975f5c5SAndroid Build Coastguard Worker int shaderVersion)
1571*8975f5c5SAndroid Build Coastguard Worker {
1572*8975f5c5SAndroid Build Coastguard Worker TIntermBinary *node = new TIntermBinary(EOpComma, left, right);
1573*8975f5c5SAndroid Build Coastguard Worker node->getTypePointer()->setQualifier(GetCommaQualifier(shaderVersion, left, right));
1574*8975f5c5SAndroid Build Coastguard Worker return node;
1575*8975f5c5SAndroid Build Coastguard Worker }
1576*8975f5c5SAndroid Build Coastguard Worker
TIntermGlobalQualifierDeclaration(TIntermSymbol * symbol,bool isPrecise,const TSourceLoc & line)1577*8975f5c5SAndroid Build Coastguard Worker TIntermGlobalQualifierDeclaration::TIntermGlobalQualifierDeclaration(TIntermSymbol *symbol,
1578*8975f5c5SAndroid Build Coastguard Worker bool isPrecise,
1579*8975f5c5SAndroid Build Coastguard Worker const TSourceLoc &line)
1580*8975f5c5SAndroid Build Coastguard Worker : TIntermNode(), mSymbol(symbol), mIsPrecise(isPrecise)
1581*8975f5c5SAndroid Build Coastguard Worker {
1582*8975f5c5SAndroid Build Coastguard Worker ASSERT(symbol);
1583*8975f5c5SAndroid Build Coastguard Worker setLine(line);
1584*8975f5c5SAndroid Build Coastguard Worker }
1585*8975f5c5SAndroid Build Coastguard Worker
TIntermGlobalQualifierDeclaration(const TIntermGlobalQualifierDeclaration & node)1586*8975f5c5SAndroid Build Coastguard Worker TIntermGlobalQualifierDeclaration::TIntermGlobalQualifierDeclaration(
1587*8975f5c5SAndroid Build Coastguard Worker const TIntermGlobalQualifierDeclaration &node)
1588*8975f5c5SAndroid Build Coastguard Worker : TIntermGlobalQualifierDeclaration(static_cast<TIntermSymbol *>(node.mSymbol->deepCopy()),
1589*8975f5c5SAndroid Build Coastguard Worker node.mIsPrecise,
1590*8975f5c5SAndroid Build Coastguard Worker node.mLine)
1591*8975f5c5SAndroid Build Coastguard Worker {}
1592*8975f5c5SAndroid Build Coastguard Worker
TIntermTernary(TIntermTyped * cond,TIntermTyped * trueExpression,TIntermTyped * falseExpression)1593*8975f5c5SAndroid Build Coastguard Worker TIntermTernary::TIntermTernary(TIntermTyped *cond,
1594*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *trueExpression,
1595*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *falseExpression)
1596*8975f5c5SAndroid Build Coastguard Worker : TIntermExpression(trueExpression->getType()),
1597*8975f5c5SAndroid Build Coastguard Worker mCondition(cond),
1598*8975f5c5SAndroid Build Coastguard Worker mTrueExpression(trueExpression),
1599*8975f5c5SAndroid Build Coastguard Worker mFalseExpression(falseExpression)
1600*8975f5c5SAndroid Build Coastguard Worker {
1601*8975f5c5SAndroid Build Coastguard Worker ASSERT(mCondition);
1602*8975f5c5SAndroid Build Coastguard Worker ASSERT(mTrueExpression);
1603*8975f5c5SAndroid Build Coastguard Worker ASSERT(mFalseExpression);
1604*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setQualifier(
1605*8975f5c5SAndroid Build Coastguard Worker TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression));
1606*8975f5c5SAndroid Build Coastguard Worker
1607*8975f5c5SAndroid Build Coastguard Worker propagatePrecision(derivePrecision());
1608*8975f5c5SAndroid Build Coastguard Worker }
1609*8975f5c5SAndroid Build Coastguard Worker
TIntermLoop(TLoopType type,TIntermNode * init,TIntermTyped * cond,TIntermTyped * expr,TIntermBlock * body)1610*8975f5c5SAndroid Build Coastguard Worker TIntermLoop::TIntermLoop(TLoopType type,
1611*8975f5c5SAndroid Build Coastguard Worker TIntermNode *init,
1612*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *cond,
1613*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *expr,
1614*8975f5c5SAndroid Build Coastguard Worker TIntermBlock *body)
1615*8975f5c5SAndroid Build Coastguard Worker : mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(EnsureBody(body))
1616*8975f5c5SAndroid Build Coastguard Worker {
1617*8975f5c5SAndroid Build Coastguard Worker // Declaration nodes with no children can appear if all the declarators just added constants to
1618*8975f5c5SAndroid Build Coastguard Worker // the symbol table instead of generating code. They're no-ops so don't add them to the tree.
1619*8975f5c5SAndroid Build Coastguard Worker if (mInit && mInit->getAsDeclarationNode() &&
1620*8975f5c5SAndroid Build Coastguard Worker mInit->getAsDeclarationNode()->getSequence()->empty())
1621*8975f5c5SAndroid Build Coastguard Worker {
1622*8975f5c5SAndroid Build Coastguard Worker mInit = nullptr;
1623*8975f5c5SAndroid Build Coastguard Worker }
1624*8975f5c5SAndroid Build Coastguard Worker }
1625*8975f5c5SAndroid Build Coastguard Worker
TIntermLoop(const TIntermLoop & node)1626*8975f5c5SAndroid Build Coastguard Worker TIntermLoop::TIntermLoop(const TIntermLoop &node)
1627*8975f5c5SAndroid Build Coastguard Worker : TIntermLoop(node.mType,
1628*8975f5c5SAndroid Build Coastguard Worker node.mInit ? node.mInit->deepCopy() : nullptr,
1629*8975f5c5SAndroid Build Coastguard Worker node.mCond ? node.mCond->deepCopy() : nullptr,
1630*8975f5c5SAndroid Build Coastguard Worker node.mExpr ? node.mExpr->deepCopy() : nullptr,
1631*8975f5c5SAndroid Build Coastguard Worker node.mBody->deepCopy())
1632*8975f5c5SAndroid Build Coastguard Worker {}
1633*8975f5c5SAndroid Build Coastguard Worker
TIntermIfElse(TIntermTyped * cond,TIntermBlock * trueB,TIntermBlock * falseB)1634*8975f5c5SAndroid Build Coastguard Worker TIntermIfElse::TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB)
1635*8975f5c5SAndroid Build Coastguard Worker : TIntermNode(), mCondition(cond), mTrueBlock(trueB), mFalseBlock(falseB)
1636*8975f5c5SAndroid Build Coastguard Worker {
1637*8975f5c5SAndroid Build Coastguard Worker ASSERT(mCondition);
1638*8975f5c5SAndroid Build Coastguard Worker // Prune empty false blocks so that there won't be unnecessary operations done on it.
1639*8975f5c5SAndroid Build Coastguard Worker if (mFalseBlock && mFalseBlock->getSequence()->empty())
1640*8975f5c5SAndroid Build Coastguard Worker {
1641*8975f5c5SAndroid Build Coastguard Worker mFalseBlock = nullptr;
1642*8975f5c5SAndroid Build Coastguard Worker }
1643*8975f5c5SAndroid Build Coastguard Worker }
1644*8975f5c5SAndroid Build Coastguard Worker
TIntermIfElse(const TIntermIfElse & node)1645*8975f5c5SAndroid Build Coastguard Worker TIntermIfElse::TIntermIfElse(const TIntermIfElse &node)
1646*8975f5c5SAndroid Build Coastguard Worker : TIntermIfElse(node.mCondition->deepCopy(),
1647*8975f5c5SAndroid Build Coastguard Worker node.mTrueBlock->deepCopy(),
1648*8975f5c5SAndroid Build Coastguard Worker node.mFalseBlock ? node.mFalseBlock->deepCopy() : nullptr)
1649*8975f5c5SAndroid Build Coastguard Worker {}
1650*8975f5c5SAndroid Build Coastguard Worker
TIntermSwitch(TIntermTyped * init,TIntermBlock * statementList)1651*8975f5c5SAndroid Build Coastguard Worker TIntermSwitch::TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList)
1652*8975f5c5SAndroid Build Coastguard Worker : TIntermNode(), mInit(init), mStatementList(statementList)
1653*8975f5c5SAndroid Build Coastguard Worker {
1654*8975f5c5SAndroid Build Coastguard Worker ASSERT(mInit);
1655*8975f5c5SAndroid Build Coastguard Worker ASSERT(mStatementList);
1656*8975f5c5SAndroid Build Coastguard Worker }
1657*8975f5c5SAndroid Build Coastguard Worker
TIntermSwitch(const TIntermSwitch & node)1658*8975f5c5SAndroid Build Coastguard Worker TIntermSwitch::TIntermSwitch(const TIntermSwitch &node)
1659*8975f5c5SAndroid Build Coastguard Worker : TIntermSwitch(node.mInit->deepCopy(), node.mStatementList->deepCopy())
1660*8975f5c5SAndroid Build Coastguard Worker {}
1661*8975f5c5SAndroid Build Coastguard Worker
setStatementList(TIntermBlock * statementList)1662*8975f5c5SAndroid Build Coastguard Worker void TIntermSwitch::setStatementList(TIntermBlock *statementList)
1663*8975f5c5SAndroid Build Coastguard Worker {
1664*8975f5c5SAndroid Build Coastguard Worker ASSERT(statementList);
1665*8975f5c5SAndroid Build Coastguard Worker mStatementList = statementList;
1666*8975f5c5SAndroid Build Coastguard Worker }
1667*8975f5c5SAndroid Build Coastguard Worker
1668*8975f5c5SAndroid Build Coastguard Worker // static
DetermineQualifier(TIntermTyped * cond,TIntermTyped * trueExpression,TIntermTyped * falseExpression)1669*8975f5c5SAndroid Build Coastguard Worker TQualifier TIntermTernary::DetermineQualifier(TIntermTyped *cond,
1670*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *trueExpression,
1671*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *falseExpression)
1672*8975f5c5SAndroid Build Coastguard Worker {
1673*8975f5c5SAndroid Build Coastguard Worker if (cond->getQualifier() == EvqConst && trueExpression->getQualifier() == EvqConst &&
1674*8975f5c5SAndroid Build Coastguard Worker falseExpression->getQualifier() == EvqConst)
1675*8975f5c5SAndroid Build Coastguard Worker {
1676*8975f5c5SAndroid Build Coastguard Worker return EvqConst;
1677*8975f5c5SAndroid Build Coastguard Worker }
1678*8975f5c5SAndroid Build Coastguard Worker return EvqTemporary;
1679*8975f5c5SAndroid Build Coastguard Worker }
1680*8975f5c5SAndroid Build Coastguard Worker
1681*8975f5c5SAndroid Build Coastguard Worker // Derive precision from children nodes
derivePrecision() const1682*8975f5c5SAndroid Build Coastguard Worker TPrecision TIntermTernary::derivePrecision() const
1683*8975f5c5SAndroid Build Coastguard Worker {
1684*8975f5c5SAndroid Build Coastguard Worker return GetHigherPrecision(mTrueExpression->getPrecision(), mFalseExpression->getPrecision());
1685*8975f5c5SAndroid Build Coastguard Worker }
1686*8975f5c5SAndroid Build Coastguard Worker
propagatePrecision(TPrecision precision)1687*8975f5c5SAndroid Build Coastguard Worker void TIntermTernary::propagatePrecision(TPrecision precision)
1688*8975f5c5SAndroid Build Coastguard Worker {
1689*8975f5c5SAndroid Build Coastguard Worker mType.setPrecision(precision);
1690*8975f5c5SAndroid Build Coastguard Worker
1691*8975f5c5SAndroid Build Coastguard Worker PropagatePrecisionIfApplicable(mTrueExpression, precision);
1692*8975f5c5SAndroid Build Coastguard Worker PropagatePrecisionIfApplicable(mFalseExpression, precision);
1693*8975f5c5SAndroid Build Coastguard Worker }
1694*8975f5c5SAndroid Build Coastguard Worker
fold(TDiagnostics *)1695*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TIntermTernary::fold(TDiagnostics * /* diagnostics */)
1696*8975f5c5SAndroid Build Coastguard Worker {
1697*8975f5c5SAndroid Build Coastguard Worker if (mCondition->getAsConstantUnion())
1698*8975f5c5SAndroid Build Coastguard Worker {
1699*8975f5c5SAndroid Build Coastguard Worker if (mCondition->getAsConstantUnion()->getBConst(0))
1700*8975f5c5SAndroid Build Coastguard Worker {
1701*8975f5c5SAndroid Build Coastguard Worker return mTrueExpression;
1702*8975f5c5SAndroid Build Coastguard Worker }
1703*8975f5c5SAndroid Build Coastguard Worker else
1704*8975f5c5SAndroid Build Coastguard Worker {
1705*8975f5c5SAndroid Build Coastguard Worker return mFalseExpression;
1706*8975f5c5SAndroid Build Coastguard Worker }
1707*8975f5c5SAndroid Build Coastguard Worker }
1708*8975f5c5SAndroid Build Coastguard Worker return this;
1709*8975f5c5SAndroid Build Coastguard Worker }
1710*8975f5c5SAndroid Build Coastguard Worker
promote()1711*8975f5c5SAndroid Build Coastguard Worker void TIntermSwizzle::promote()
1712*8975f5c5SAndroid Build Coastguard Worker {
1713*8975f5c5SAndroid Build Coastguard Worker TQualifier resultQualifier = EvqTemporary;
1714*8975f5c5SAndroid Build Coastguard Worker if (mOperand->getQualifier() == EvqConst)
1715*8975f5c5SAndroid Build Coastguard Worker resultQualifier = EvqConst;
1716*8975f5c5SAndroid Build Coastguard Worker
1717*8975f5c5SAndroid Build Coastguard Worker size_t numFields = mSwizzleOffsets.size();
1718*8975f5c5SAndroid Build Coastguard Worker setType(TType(mOperand->getBasicType(), EbpUndefined, resultQualifier,
1719*8975f5c5SAndroid Build Coastguard Worker static_cast<uint8_t>(numFields)));
1720*8975f5c5SAndroid Build Coastguard Worker propagatePrecision(derivePrecision());
1721*8975f5c5SAndroid Build Coastguard Worker }
1722*8975f5c5SAndroid Build Coastguard Worker
1723*8975f5c5SAndroid Build Coastguard Worker // Derive precision from children nodes
derivePrecision() const1724*8975f5c5SAndroid Build Coastguard Worker TPrecision TIntermSwizzle::derivePrecision() const
1725*8975f5c5SAndroid Build Coastguard Worker {
1726*8975f5c5SAndroid Build Coastguard Worker return mOperand->getPrecision();
1727*8975f5c5SAndroid Build Coastguard Worker }
1728*8975f5c5SAndroid Build Coastguard Worker
propagatePrecision(TPrecision precision)1729*8975f5c5SAndroid Build Coastguard Worker void TIntermSwizzle::propagatePrecision(TPrecision precision)
1730*8975f5c5SAndroid Build Coastguard Worker {
1731*8975f5c5SAndroid Build Coastguard Worker mType.setPrecision(precision);
1732*8975f5c5SAndroid Build Coastguard Worker
1733*8975f5c5SAndroid Build Coastguard Worker PropagatePrecisionIfApplicable(mOperand, precision);
1734*8975f5c5SAndroid Build Coastguard Worker }
1735*8975f5c5SAndroid Build Coastguard Worker
hasDuplicateOffsets() const1736*8975f5c5SAndroid Build Coastguard Worker bool TIntermSwizzle::hasDuplicateOffsets() const
1737*8975f5c5SAndroid Build Coastguard Worker {
1738*8975f5c5SAndroid Build Coastguard Worker if (mHasFoldedDuplicateOffsets)
1739*8975f5c5SAndroid Build Coastguard Worker {
1740*8975f5c5SAndroid Build Coastguard Worker return true;
1741*8975f5c5SAndroid Build Coastguard Worker }
1742*8975f5c5SAndroid Build Coastguard Worker int offsetCount[4] = {0u, 0u, 0u, 0u};
1743*8975f5c5SAndroid Build Coastguard Worker for (const auto offset : mSwizzleOffsets)
1744*8975f5c5SAndroid Build Coastguard Worker {
1745*8975f5c5SAndroid Build Coastguard Worker offsetCount[offset]++;
1746*8975f5c5SAndroid Build Coastguard Worker if (offsetCount[offset] > 1)
1747*8975f5c5SAndroid Build Coastguard Worker {
1748*8975f5c5SAndroid Build Coastguard Worker return true;
1749*8975f5c5SAndroid Build Coastguard Worker }
1750*8975f5c5SAndroid Build Coastguard Worker }
1751*8975f5c5SAndroid Build Coastguard Worker return false;
1752*8975f5c5SAndroid Build Coastguard Worker }
1753*8975f5c5SAndroid Build Coastguard Worker
setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets)1754*8975f5c5SAndroid Build Coastguard Worker void TIntermSwizzle::setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets)
1755*8975f5c5SAndroid Build Coastguard Worker {
1756*8975f5c5SAndroid Build Coastguard Worker mHasFoldedDuplicateOffsets = hasFoldedDuplicateOffsets;
1757*8975f5c5SAndroid Build Coastguard Worker }
1758*8975f5c5SAndroid Build Coastguard Worker
offsetsMatch(int offset) const1759*8975f5c5SAndroid Build Coastguard Worker bool TIntermSwizzle::offsetsMatch(int offset) const
1760*8975f5c5SAndroid Build Coastguard Worker {
1761*8975f5c5SAndroid Build Coastguard Worker return mSwizzleOffsets.size() == 1 && mSwizzleOffsets[0] == offset;
1762*8975f5c5SAndroid Build Coastguard Worker }
1763*8975f5c5SAndroid Build Coastguard Worker
writeOffsetsAsXYZW(TInfoSinkBase * out) const1764*8975f5c5SAndroid Build Coastguard Worker void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const
1765*8975f5c5SAndroid Build Coastguard Worker {
1766*8975f5c5SAndroid Build Coastguard Worker for (const int offset : mSwizzleOffsets)
1767*8975f5c5SAndroid Build Coastguard Worker {
1768*8975f5c5SAndroid Build Coastguard Worker switch (offset)
1769*8975f5c5SAndroid Build Coastguard Worker {
1770*8975f5c5SAndroid Build Coastguard Worker case 0:
1771*8975f5c5SAndroid Build Coastguard Worker *out << "x";
1772*8975f5c5SAndroid Build Coastguard Worker break;
1773*8975f5c5SAndroid Build Coastguard Worker case 1:
1774*8975f5c5SAndroid Build Coastguard Worker *out << "y";
1775*8975f5c5SAndroid Build Coastguard Worker break;
1776*8975f5c5SAndroid Build Coastguard Worker case 2:
1777*8975f5c5SAndroid Build Coastguard Worker *out << "z";
1778*8975f5c5SAndroid Build Coastguard Worker break;
1779*8975f5c5SAndroid Build Coastguard Worker case 3:
1780*8975f5c5SAndroid Build Coastguard Worker *out << "w";
1781*8975f5c5SAndroid Build Coastguard Worker break;
1782*8975f5c5SAndroid Build Coastguard Worker default:
1783*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
1784*8975f5c5SAndroid Build Coastguard Worker }
1785*8975f5c5SAndroid Build Coastguard Worker }
1786*8975f5c5SAndroid Build Coastguard Worker }
1787*8975f5c5SAndroid Build Coastguard Worker
GetCommaQualifier(int shaderVersion,const TIntermTyped * left,const TIntermTyped * right)1788*8975f5c5SAndroid Build Coastguard Worker TQualifier TIntermBinary::GetCommaQualifier(int shaderVersion,
1789*8975f5c5SAndroid Build Coastguard Worker const TIntermTyped *left,
1790*8975f5c5SAndroid Build Coastguard Worker const TIntermTyped *right)
1791*8975f5c5SAndroid Build Coastguard Worker {
1792*8975f5c5SAndroid Build Coastguard Worker // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
1793*8975f5c5SAndroid Build Coastguard Worker if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
1794*8975f5c5SAndroid Build Coastguard Worker right->getQualifier() != EvqConst)
1795*8975f5c5SAndroid Build Coastguard Worker {
1796*8975f5c5SAndroid Build Coastguard Worker return EvqTemporary;
1797*8975f5c5SAndroid Build Coastguard Worker }
1798*8975f5c5SAndroid Build Coastguard Worker return EvqConst;
1799*8975f5c5SAndroid Build Coastguard Worker }
1800*8975f5c5SAndroid Build Coastguard Worker
1801*8975f5c5SAndroid Build Coastguard Worker // Establishes the type of the result of the binary operation.
promote()1802*8975f5c5SAndroid Build Coastguard Worker void TIntermBinary::promote()
1803*8975f5c5SAndroid Build Coastguard Worker {
1804*8975f5c5SAndroid Build Coastguard Worker ASSERT(!isMultiplication() ||
1805*8975f5c5SAndroid Build Coastguard Worker mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType()));
1806*8975f5c5SAndroid Build Coastguard Worker
1807*8975f5c5SAndroid Build Coastguard Worker // Comma is handled as a special case. Note that the comma node qualifier depends on the shader
1808*8975f5c5SAndroid Build Coastguard Worker // version and so is not being set here.
1809*8975f5c5SAndroid Build Coastguard Worker if (mOp == EOpComma)
1810*8975f5c5SAndroid Build Coastguard Worker {
1811*8975f5c5SAndroid Build Coastguard Worker setType(mRight->getType());
1812*8975f5c5SAndroid Build Coastguard Worker return;
1813*8975f5c5SAndroid Build Coastguard Worker }
1814*8975f5c5SAndroid Build Coastguard Worker
1815*8975f5c5SAndroid Build Coastguard Worker // Base assumption: just make the type the same as the left
1816*8975f5c5SAndroid Build Coastguard Worker // operand. Then only deviations from this need be coded.
1817*8975f5c5SAndroid Build Coastguard Worker setType(mLeft->getType());
1818*8975f5c5SAndroid Build Coastguard Worker
1819*8975f5c5SAndroid Build Coastguard Worker TQualifier resultQualifier = EvqConst;
1820*8975f5c5SAndroid Build Coastguard Worker // Binary operations results in temporary variables unless both
1821*8975f5c5SAndroid Build Coastguard Worker // operands are const. If initializing a specialization constant, make the declarator also
1822*8975f5c5SAndroid Build Coastguard Worker // EvqSpecConst.
1823*8975f5c5SAndroid Build Coastguard Worker const bool isSpecConstInit = mOp == EOpInitialize && mLeft->getQualifier() == EvqSpecConst;
1824*8975f5c5SAndroid Build Coastguard Worker const bool isEitherNonConst =
1825*8975f5c5SAndroid Build Coastguard Worker mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst;
1826*8975f5c5SAndroid Build Coastguard Worker if (!isSpecConstInit && isEitherNonConst)
1827*8975f5c5SAndroid Build Coastguard Worker {
1828*8975f5c5SAndroid Build Coastguard Worker resultQualifier = EvqTemporary;
1829*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setQualifier(EvqTemporary);
1830*8975f5c5SAndroid Build Coastguard Worker }
1831*8975f5c5SAndroid Build Coastguard Worker
1832*8975f5c5SAndroid Build Coastguard Worker // Result is an intermediate value, so make sure it's identified as such. That's not true for
1833*8975f5c5SAndroid Build Coastguard Worker // interface block arrays being indexed.
1834*8975f5c5SAndroid Build Coastguard Worker if (mOp != EOpIndexDirect && mOp != EOpIndexIndirect)
1835*8975f5c5SAndroid Build Coastguard Worker {
1836*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setInterfaceBlock(nullptr);
1837*8975f5c5SAndroid Build Coastguard Worker }
1838*8975f5c5SAndroid Build Coastguard Worker
1839*8975f5c5SAndroid Build Coastguard Worker // Handle indexing ops.
1840*8975f5c5SAndroid Build Coastguard Worker switch (mOp)
1841*8975f5c5SAndroid Build Coastguard Worker {
1842*8975f5c5SAndroid Build Coastguard Worker case EOpIndexDirect:
1843*8975f5c5SAndroid Build Coastguard Worker case EOpIndexIndirect:
1844*8975f5c5SAndroid Build Coastguard Worker if (mLeft->isArray())
1845*8975f5c5SAndroid Build Coastguard Worker {
1846*8975f5c5SAndroid Build Coastguard Worker mType.toArrayElementType();
1847*8975f5c5SAndroid Build Coastguard Worker }
1848*8975f5c5SAndroid Build Coastguard Worker else if (mLeft->isMatrix())
1849*8975f5c5SAndroid Build Coastguard Worker {
1850*8975f5c5SAndroid Build Coastguard Worker mType.toMatrixColumnType();
1851*8975f5c5SAndroid Build Coastguard Worker }
1852*8975f5c5SAndroid Build Coastguard Worker else if (mLeft->isVector())
1853*8975f5c5SAndroid Build Coastguard Worker {
1854*8975f5c5SAndroid Build Coastguard Worker mType.toComponentType();
1855*8975f5c5SAndroid Build Coastguard Worker }
1856*8975f5c5SAndroid Build Coastguard Worker else
1857*8975f5c5SAndroid Build Coastguard Worker {
1858*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
1859*8975f5c5SAndroid Build Coastguard Worker }
1860*8975f5c5SAndroid Build Coastguard Worker return;
1861*8975f5c5SAndroid Build Coastguard Worker case EOpIndexDirectStruct:
1862*8975f5c5SAndroid Build Coastguard Worker {
1863*8975f5c5SAndroid Build Coastguard Worker const TFieldList &fields = mLeft->getType().getStruct()->fields();
1864*8975f5c5SAndroid Build Coastguard Worker const int fieldIndex = mRight->getAsConstantUnion()->getIConst(0);
1865*8975f5c5SAndroid Build Coastguard Worker setType(*fields[fieldIndex]->type());
1866*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setQualifier(resultQualifier);
1867*8975f5c5SAndroid Build Coastguard Worker return;
1868*8975f5c5SAndroid Build Coastguard Worker }
1869*8975f5c5SAndroid Build Coastguard Worker case EOpIndexDirectInterfaceBlock:
1870*8975f5c5SAndroid Build Coastguard Worker {
1871*8975f5c5SAndroid Build Coastguard Worker const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields();
1872*8975f5c5SAndroid Build Coastguard Worker const int fieldIndex = mRight->getAsConstantUnion()->getIConst(0);
1873*8975f5c5SAndroid Build Coastguard Worker setType(*fields[fieldIndex]->type());
1874*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setQualifier(resultQualifier);
1875*8975f5c5SAndroid Build Coastguard Worker return;
1876*8975f5c5SAndroid Build Coastguard Worker }
1877*8975f5c5SAndroid Build Coastguard Worker default:
1878*8975f5c5SAndroid Build Coastguard Worker break;
1879*8975f5c5SAndroid Build Coastguard Worker }
1880*8975f5c5SAndroid Build Coastguard Worker
1881*8975f5c5SAndroid Build Coastguard Worker ASSERT(mLeft->isArray() == mRight->isArray());
1882*8975f5c5SAndroid Build Coastguard Worker
1883*8975f5c5SAndroid Build Coastguard Worker const uint8_t nominalSize = std::max(mLeft->getNominalSize(), mRight->getNominalSize());
1884*8975f5c5SAndroid Build Coastguard Worker
1885*8975f5c5SAndroid Build Coastguard Worker switch (mOp)
1886*8975f5c5SAndroid Build Coastguard Worker {
1887*8975f5c5SAndroid Build Coastguard Worker case EOpMul:
1888*8975f5c5SAndroid Build Coastguard Worker break;
1889*8975f5c5SAndroid Build Coastguard Worker case EOpMatrixTimesScalar:
1890*8975f5c5SAndroid Build Coastguard Worker if (mRight->isMatrix())
1891*8975f5c5SAndroid Build Coastguard Worker {
1892*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setPrimarySize(mRight->getCols());
1893*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setSecondarySize(mRight->getRows());
1894*8975f5c5SAndroid Build Coastguard Worker }
1895*8975f5c5SAndroid Build Coastguard Worker break;
1896*8975f5c5SAndroid Build Coastguard Worker case EOpMatrixTimesVector:
1897*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setPrimarySize(mLeft->getRows());
1898*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setSecondarySize(1);
1899*8975f5c5SAndroid Build Coastguard Worker break;
1900*8975f5c5SAndroid Build Coastguard Worker case EOpMatrixTimesMatrix:
1901*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setPrimarySize(mRight->getCols());
1902*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setSecondarySize(mLeft->getRows());
1903*8975f5c5SAndroid Build Coastguard Worker break;
1904*8975f5c5SAndroid Build Coastguard Worker case EOpVectorTimesScalar:
1905*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setPrimarySize(nominalSize);
1906*8975f5c5SAndroid Build Coastguard Worker break;
1907*8975f5c5SAndroid Build Coastguard Worker case EOpVectorTimesMatrix:
1908*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setPrimarySize(mRight->getCols());
1909*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getSecondarySize() == 1);
1910*8975f5c5SAndroid Build Coastguard Worker break;
1911*8975f5c5SAndroid Build Coastguard Worker case EOpMulAssign:
1912*8975f5c5SAndroid Build Coastguard Worker case EOpVectorTimesScalarAssign:
1913*8975f5c5SAndroid Build Coastguard Worker case EOpVectorTimesMatrixAssign:
1914*8975f5c5SAndroid Build Coastguard Worker case EOpMatrixTimesScalarAssign:
1915*8975f5c5SAndroid Build Coastguard Worker case EOpMatrixTimesMatrixAssign:
1916*8975f5c5SAndroid Build Coastguard Worker ASSERT(mOp == GetMulAssignOpBasedOnOperands(mLeft->getType(), mRight->getType()));
1917*8975f5c5SAndroid Build Coastguard Worker break;
1918*8975f5c5SAndroid Build Coastguard Worker case EOpAssign:
1919*8975f5c5SAndroid Build Coastguard Worker case EOpInitialize:
1920*8975f5c5SAndroid Build Coastguard Worker ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
1921*8975f5c5SAndroid Build Coastguard Worker (mLeft->getSecondarySize() == mRight->getSecondarySize()));
1922*8975f5c5SAndroid Build Coastguard Worker break;
1923*8975f5c5SAndroid Build Coastguard Worker case EOpAdd:
1924*8975f5c5SAndroid Build Coastguard Worker case EOpSub:
1925*8975f5c5SAndroid Build Coastguard Worker case EOpDiv:
1926*8975f5c5SAndroid Build Coastguard Worker case EOpIMod:
1927*8975f5c5SAndroid Build Coastguard Worker case EOpBitShiftLeft:
1928*8975f5c5SAndroid Build Coastguard Worker case EOpBitShiftRight:
1929*8975f5c5SAndroid Build Coastguard Worker case EOpBitwiseAnd:
1930*8975f5c5SAndroid Build Coastguard Worker case EOpBitwiseXor:
1931*8975f5c5SAndroid Build Coastguard Worker case EOpBitwiseOr:
1932*8975f5c5SAndroid Build Coastguard Worker case EOpAddAssign:
1933*8975f5c5SAndroid Build Coastguard Worker case EOpSubAssign:
1934*8975f5c5SAndroid Build Coastguard Worker case EOpDivAssign:
1935*8975f5c5SAndroid Build Coastguard Worker case EOpIModAssign:
1936*8975f5c5SAndroid Build Coastguard Worker case EOpBitShiftLeftAssign:
1937*8975f5c5SAndroid Build Coastguard Worker case EOpBitShiftRightAssign:
1938*8975f5c5SAndroid Build Coastguard Worker case EOpBitwiseAndAssign:
1939*8975f5c5SAndroid Build Coastguard Worker case EOpBitwiseXorAssign:
1940*8975f5c5SAndroid Build Coastguard Worker case EOpBitwiseOrAssign:
1941*8975f5c5SAndroid Build Coastguard Worker {
1942*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mLeft->isArray() && !mRight->isArray());
1943*8975f5c5SAndroid Build Coastguard Worker const uint8_t secondarySize =
1944*8975f5c5SAndroid Build Coastguard Worker std::max(mLeft->getSecondarySize(), mRight->getSecondarySize());
1945*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setPrimarySize(nominalSize);
1946*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setSecondarySize(secondarySize);
1947*8975f5c5SAndroid Build Coastguard Worker break;
1948*8975f5c5SAndroid Build Coastguard Worker }
1949*8975f5c5SAndroid Build Coastguard Worker case EOpEqual:
1950*8975f5c5SAndroid Build Coastguard Worker case EOpNotEqual:
1951*8975f5c5SAndroid Build Coastguard Worker case EOpLessThan:
1952*8975f5c5SAndroid Build Coastguard Worker case EOpGreaterThan:
1953*8975f5c5SAndroid Build Coastguard Worker case EOpLessThanEqual:
1954*8975f5c5SAndroid Build Coastguard Worker case EOpGreaterThanEqual:
1955*8975f5c5SAndroid Build Coastguard Worker ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
1956*8975f5c5SAndroid Build Coastguard Worker (mLeft->getSecondarySize() == mRight->getSecondarySize()));
1957*8975f5c5SAndroid Build Coastguard Worker setType(TType(EbtBool, EbpUndefined, resultQualifier));
1958*8975f5c5SAndroid Build Coastguard Worker break;
1959*8975f5c5SAndroid Build Coastguard Worker
1960*8975f5c5SAndroid Build Coastguard Worker //
1961*8975f5c5SAndroid Build Coastguard Worker // And and Or operate on conditionals
1962*8975f5c5SAndroid Build Coastguard Worker //
1963*8975f5c5SAndroid Build Coastguard Worker case EOpLogicalAnd:
1964*8975f5c5SAndroid Build Coastguard Worker case EOpLogicalXor:
1965*8975f5c5SAndroid Build Coastguard Worker case EOpLogicalOr:
1966*8975f5c5SAndroid Build Coastguard Worker ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool);
1967*8975f5c5SAndroid Build Coastguard Worker break;
1968*8975f5c5SAndroid Build Coastguard Worker
1969*8975f5c5SAndroid Build Coastguard Worker case EOpIndexDirect:
1970*8975f5c5SAndroid Build Coastguard Worker case EOpIndexIndirect:
1971*8975f5c5SAndroid Build Coastguard Worker case EOpIndexDirectInterfaceBlock:
1972*8975f5c5SAndroid Build Coastguard Worker case EOpIndexDirectStruct:
1973*8975f5c5SAndroid Build Coastguard Worker // These ops should be already fully handled.
1974*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
1975*8975f5c5SAndroid Build Coastguard Worker break;
1976*8975f5c5SAndroid Build Coastguard Worker default:
1977*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
1978*8975f5c5SAndroid Build Coastguard Worker break;
1979*8975f5c5SAndroid Build Coastguard Worker }
1980*8975f5c5SAndroid Build Coastguard Worker
1981*8975f5c5SAndroid Build Coastguard Worker propagatePrecision(derivePrecision());
1982*8975f5c5SAndroid Build Coastguard Worker }
1983*8975f5c5SAndroid Build Coastguard Worker
1984*8975f5c5SAndroid Build Coastguard Worker // Derive precision from children nodes
derivePrecision() const1985*8975f5c5SAndroid Build Coastguard Worker TPrecision TIntermBinary::derivePrecision() const
1986*8975f5c5SAndroid Build Coastguard Worker {
1987*8975f5c5SAndroid Build Coastguard Worker // Assignments use the type and precision of the lvalue-expression
1988*8975f5c5SAndroid Build Coastguard Worker // GLSL ES spec section 5.8: Assignments
1989*8975f5c5SAndroid Build Coastguard Worker // "The assignment operator stores the value of rvalue-expression into the l-value and returns
1990*8975f5c5SAndroid Build Coastguard Worker // an r-value with the type and precision of lvalue-expression."
1991*8975f5c5SAndroid Build Coastguard Worker if (IsAssignment(mOp))
1992*8975f5c5SAndroid Build Coastguard Worker {
1993*8975f5c5SAndroid Build Coastguard Worker return mLeft->getPrecision();
1994*8975f5c5SAndroid Build Coastguard Worker }
1995*8975f5c5SAndroid Build Coastguard Worker
1996*8975f5c5SAndroid Build Coastguard Worker const TPrecision higherPrecision =
1997*8975f5c5SAndroid Build Coastguard Worker GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision());
1998*8975f5c5SAndroid Build Coastguard Worker
1999*8975f5c5SAndroid Build Coastguard Worker switch (mOp)
2000*8975f5c5SAndroid Build Coastguard Worker {
2001*8975f5c5SAndroid Build Coastguard Worker case EOpComma:
2002*8975f5c5SAndroid Build Coastguard Worker // Comma takes the right node's value.
2003*8975f5c5SAndroid Build Coastguard Worker return mRight->getPrecision();
2004*8975f5c5SAndroid Build Coastguard Worker
2005*8975f5c5SAndroid Build Coastguard Worker case EOpIndexDirect:
2006*8975f5c5SAndroid Build Coastguard Worker case EOpIndexIndirect:
2007*8975f5c5SAndroid Build Coastguard Worker case EOpBitShiftLeft:
2008*8975f5c5SAndroid Build Coastguard Worker case EOpBitShiftRight:
2009*8975f5c5SAndroid Build Coastguard Worker // When indexing an array, the precision of the array is preserved (which is the left
2010*8975f5c5SAndroid Build Coastguard Worker // node).
2011*8975f5c5SAndroid Build Coastguard Worker // For shift operations, the precision is derived from the expression being shifted
2012*8975f5c5SAndroid Build Coastguard Worker // (which is also the left node).
2013*8975f5c5SAndroid Build Coastguard Worker return mLeft->getPrecision();
2014*8975f5c5SAndroid Build Coastguard Worker
2015*8975f5c5SAndroid Build Coastguard Worker case EOpIndexDirectStruct:
2016*8975f5c5SAndroid Build Coastguard Worker case EOpIndexDirectInterfaceBlock:
2017*8975f5c5SAndroid Build Coastguard Worker {
2018*8975f5c5SAndroid Build Coastguard Worker // When selecting the field of a block, the precision is taken from the field's
2019*8975f5c5SAndroid Build Coastguard Worker // declaration.
2020*8975f5c5SAndroid Build Coastguard Worker const TFieldList &fields = mOp == EOpIndexDirectStruct
2021*8975f5c5SAndroid Build Coastguard Worker ? mLeft->getType().getStruct()->fields()
2022*8975f5c5SAndroid Build Coastguard Worker : mLeft->getType().getInterfaceBlock()->fields();
2023*8975f5c5SAndroid Build Coastguard Worker const int fieldIndex = mRight->getAsConstantUnion()->getIConst(0);
2024*8975f5c5SAndroid Build Coastguard Worker return fields[fieldIndex]->type()->getPrecision();
2025*8975f5c5SAndroid Build Coastguard Worker }
2026*8975f5c5SAndroid Build Coastguard Worker
2027*8975f5c5SAndroid Build Coastguard Worker case EOpEqual:
2028*8975f5c5SAndroid Build Coastguard Worker case EOpNotEqual:
2029*8975f5c5SAndroid Build Coastguard Worker case EOpLessThan:
2030*8975f5c5SAndroid Build Coastguard Worker case EOpGreaterThan:
2031*8975f5c5SAndroid Build Coastguard Worker case EOpLessThanEqual:
2032*8975f5c5SAndroid Build Coastguard Worker case EOpGreaterThanEqual:
2033*8975f5c5SAndroid Build Coastguard Worker case EOpLogicalAnd:
2034*8975f5c5SAndroid Build Coastguard Worker case EOpLogicalXor:
2035*8975f5c5SAndroid Build Coastguard Worker case EOpLogicalOr:
2036*8975f5c5SAndroid Build Coastguard Worker // No precision specified on bool results.
2037*8975f5c5SAndroid Build Coastguard Worker return EbpUndefined;
2038*8975f5c5SAndroid Build Coastguard Worker
2039*8975f5c5SAndroid Build Coastguard Worker default:
2040*8975f5c5SAndroid Build Coastguard Worker // All other operations are evaluated at the higher of the two operands' precisions.
2041*8975f5c5SAndroid Build Coastguard Worker return higherPrecision;
2042*8975f5c5SAndroid Build Coastguard Worker }
2043*8975f5c5SAndroid Build Coastguard Worker }
2044*8975f5c5SAndroid Build Coastguard Worker
propagatePrecision(TPrecision precision)2045*8975f5c5SAndroid Build Coastguard Worker void TIntermBinary::propagatePrecision(TPrecision precision)
2046*8975f5c5SAndroid Build Coastguard Worker {
2047*8975f5c5SAndroid Build Coastguard Worker getTypePointer()->setPrecision(precision);
2048*8975f5c5SAndroid Build Coastguard Worker
2049*8975f5c5SAndroid Build Coastguard Worker if (mOp != EOpComma)
2050*8975f5c5SAndroid Build Coastguard Worker {
2051*8975f5c5SAndroid Build Coastguard Worker PropagatePrecisionIfApplicable(mLeft, precision);
2052*8975f5c5SAndroid Build Coastguard Worker }
2053*8975f5c5SAndroid Build Coastguard Worker
2054*8975f5c5SAndroid Build Coastguard Worker if (mOp != EOpIndexDirect && mOp != EOpIndexIndirect && mOp != EOpIndexDirectStruct &&
2055*8975f5c5SAndroid Build Coastguard Worker mOp != EOpIndexDirectInterfaceBlock)
2056*8975f5c5SAndroid Build Coastguard Worker {
2057*8975f5c5SAndroid Build Coastguard Worker PropagatePrecisionIfApplicable(mRight, precision);
2058*8975f5c5SAndroid Build Coastguard Worker }
2059*8975f5c5SAndroid Build Coastguard Worker
2060*8975f5c5SAndroid Build Coastguard Worker // For indices, always apply highp. This is purely for the purpose of making sure constant and
2061*8975f5c5SAndroid Build Coastguard Worker // constructor nodes are also given a precision, so if they are hoisted to a temp variable,
2062*8975f5c5SAndroid Build Coastguard Worker // there would be a precision to apply to that variable.
2063*8975f5c5SAndroid Build Coastguard Worker if (mOp == EOpIndexDirect || mOp == EOpIndexIndirect)
2064*8975f5c5SAndroid Build Coastguard Worker {
2065*8975f5c5SAndroid Build Coastguard Worker PropagatePrecisionIfApplicable(mRight, EbpHigh);
2066*8975f5c5SAndroid Build Coastguard Worker }
2067*8975f5c5SAndroid Build Coastguard Worker }
2068*8975f5c5SAndroid Build Coastguard Worker
hasConstantValue() const2069*8975f5c5SAndroid Build Coastguard Worker bool TIntermConstantUnion::hasConstantValue() const
2070*8975f5c5SAndroid Build Coastguard Worker {
2071*8975f5c5SAndroid Build Coastguard Worker return true;
2072*8975f5c5SAndroid Build Coastguard Worker }
2073*8975f5c5SAndroid Build Coastguard Worker
isConstantNullValue() const2074*8975f5c5SAndroid Build Coastguard Worker bool TIntermConstantUnion::isConstantNullValue() const
2075*8975f5c5SAndroid Build Coastguard Worker {
2076*8975f5c5SAndroid Build Coastguard Worker const size_t size = mType.getObjectSize();
2077*8975f5c5SAndroid Build Coastguard Worker for (size_t index = 0; index < size; ++index)
2078*8975f5c5SAndroid Build Coastguard Worker {
2079*8975f5c5SAndroid Build Coastguard Worker if (!mUnionArrayPointer[index].isZero())
2080*8975f5c5SAndroid Build Coastguard Worker {
2081*8975f5c5SAndroid Build Coastguard Worker return false;
2082*8975f5c5SAndroid Build Coastguard Worker }
2083*8975f5c5SAndroid Build Coastguard Worker }
2084*8975f5c5SAndroid Build Coastguard Worker return true;
2085*8975f5c5SAndroid Build Coastguard Worker }
2086*8975f5c5SAndroid Build Coastguard Worker
getConstantValue() const2087*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *TIntermConstantUnion::getConstantValue() const
2088*8975f5c5SAndroid Build Coastguard Worker {
2089*8975f5c5SAndroid Build Coastguard Worker return mUnionArrayPointer;
2090*8975f5c5SAndroid Build Coastguard Worker }
2091*8975f5c5SAndroid Build Coastguard Worker
FoldIndexing(const TType & type,const TConstantUnion * constArray,int index)2092*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *TIntermConstantUnion::FoldIndexing(const TType &type,
2093*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *constArray,
2094*8975f5c5SAndroid Build Coastguard Worker int index)
2095*8975f5c5SAndroid Build Coastguard Worker {
2096*8975f5c5SAndroid Build Coastguard Worker if (type.isArray())
2097*8975f5c5SAndroid Build Coastguard Worker {
2098*8975f5c5SAndroid Build Coastguard Worker ASSERT(index < static_cast<int>(type.getOutermostArraySize()));
2099*8975f5c5SAndroid Build Coastguard Worker TType arrayElementType(type);
2100*8975f5c5SAndroid Build Coastguard Worker arrayElementType.toArrayElementType();
2101*8975f5c5SAndroid Build Coastguard Worker size_t arrayElementSize = arrayElementType.getObjectSize();
2102*8975f5c5SAndroid Build Coastguard Worker return &constArray[arrayElementSize * index];
2103*8975f5c5SAndroid Build Coastguard Worker }
2104*8975f5c5SAndroid Build Coastguard Worker else if (type.isMatrix())
2105*8975f5c5SAndroid Build Coastguard Worker {
2106*8975f5c5SAndroid Build Coastguard Worker ASSERT(index < type.getCols());
2107*8975f5c5SAndroid Build Coastguard Worker const uint8_t size = type.getRows();
2108*8975f5c5SAndroid Build Coastguard Worker return &constArray[size * index];
2109*8975f5c5SAndroid Build Coastguard Worker }
2110*8975f5c5SAndroid Build Coastguard Worker else if (type.isVector())
2111*8975f5c5SAndroid Build Coastguard Worker {
2112*8975f5c5SAndroid Build Coastguard Worker ASSERT(index < type.getNominalSize());
2113*8975f5c5SAndroid Build Coastguard Worker return &constArray[index];
2114*8975f5c5SAndroid Build Coastguard Worker }
2115*8975f5c5SAndroid Build Coastguard Worker else
2116*8975f5c5SAndroid Build Coastguard Worker {
2117*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
2118*8975f5c5SAndroid Build Coastguard Worker return nullptr;
2119*8975f5c5SAndroid Build Coastguard Worker }
2120*8975f5c5SAndroid Build Coastguard Worker }
2121*8975f5c5SAndroid Build Coastguard Worker
fold(TDiagnostics *)2122*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TIntermSwizzle::fold(TDiagnostics * /* diagnostics */)
2123*8975f5c5SAndroid Build Coastguard Worker {
2124*8975f5c5SAndroid Build Coastguard Worker TIntermSwizzle *operandSwizzle = mOperand->getAsSwizzleNode();
2125*8975f5c5SAndroid Build Coastguard Worker if (operandSwizzle)
2126*8975f5c5SAndroid Build Coastguard Worker {
2127*8975f5c5SAndroid Build Coastguard Worker // We need to fold the two swizzles into one, so that repeated swizzling can't cause stack
2128*8975f5c5SAndroid Build Coastguard Worker // overflow in ParseContext::checkCanBeLValue().
2129*8975f5c5SAndroid Build Coastguard Worker bool hadDuplicateOffsets = operandSwizzle->hasDuplicateOffsets();
2130*8975f5c5SAndroid Build Coastguard Worker TVector<int> foldedOffsets;
2131*8975f5c5SAndroid Build Coastguard Worker for (int offset : mSwizzleOffsets)
2132*8975f5c5SAndroid Build Coastguard Worker {
2133*8975f5c5SAndroid Build Coastguard Worker // Offset should already be validated.
2134*8975f5c5SAndroid Build Coastguard Worker ASSERT(static_cast<size_t>(offset) < operandSwizzle->mSwizzleOffsets.size());
2135*8975f5c5SAndroid Build Coastguard Worker foldedOffsets.push_back(operandSwizzle->mSwizzleOffsets[offset]);
2136*8975f5c5SAndroid Build Coastguard Worker }
2137*8975f5c5SAndroid Build Coastguard Worker operandSwizzle->mSwizzleOffsets = foldedOffsets;
2138*8975f5c5SAndroid Build Coastguard Worker operandSwizzle->setType(getType());
2139*8975f5c5SAndroid Build Coastguard Worker operandSwizzle->setHasFoldedDuplicateOffsets(hadDuplicateOffsets);
2140*8975f5c5SAndroid Build Coastguard Worker return operandSwizzle;
2141*8975f5c5SAndroid Build Coastguard Worker }
2142*8975f5c5SAndroid Build Coastguard Worker TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
2143*8975f5c5SAndroid Build Coastguard Worker if (operandConstant == nullptr)
2144*8975f5c5SAndroid Build Coastguard Worker {
2145*8975f5c5SAndroid Build Coastguard Worker return this;
2146*8975f5c5SAndroid Build Coastguard Worker }
2147*8975f5c5SAndroid Build Coastguard Worker
2148*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *constArray = new TConstantUnion[mSwizzleOffsets.size()];
2149*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < mSwizzleOffsets.size(); ++i)
2150*8975f5c5SAndroid Build Coastguard Worker {
2151*8975f5c5SAndroid Build Coastguard Worker constArray[i] = *TIntermConstantUnion::FoldIndexing(
2152*8975f5c5SAndroid Build Coastguard Worker operandConstant->getType(), operandConstant->getConstantValue(), mSwizzleOffsets.at(i));
2153*8975f5c5SAndroid Build Coastguard Worker }
2154*8975f5c5SAndroid Build Coastguard Worker return CreateFoldedNode(constArray, this);
2155*8975f5c5SAndroid Build Coastguard Worker }
2156*8975f5c5SAndroid Build Coastguard Worker
fold(TDiagnostics * diagnostics)2157*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
2158*8975f5c5SAndroid Build Coastguard Worker {
2159*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *rightConstant = mRight->getConstantValue();
2160*8975f5c5SAndroid Build Coastguard Worker switch (mOp)
2161*8975f5c5SAndroid Build Coastguard Worker {
2162*8975f5c5SAndroid Build Coastguard Worker case EOpComma:
2163*8975f5c5SAndroid Build Coastguard Worker {
2164*8975f5c5SAndroid Build Coastguard Worker if (mLeft->hasSideEffects())
2165*8975f5c5SAndroid Build Coastguard Worker {
2166*8975f5c5SAndroid Build Coastguard Worker return this;
2167*8975f5c5SAndroid Build Coastguard Worker }
2168*8975f5c5SAndroid Build Coastguard Worker return mRight;
2169*8975f5c5SAndroid Build Coastguard Worker }
2170*8975f5c5SAndroid Build Coastguard Worker case EOpIndexDirect:
2171*8975f5c5SAndroid Build Coastguard Worker case EOpIndexDirectStruct:
2172*8975f5c5SAndroid Build Coastguard Worker {
2173*8975f5c5SAndroid Build Coastguard Worker if (rightConstant == nullptr)
2174*8975f5c5SAndroid Build Coastguard Worker {
2175*8975f5c5SAndroid Build Coastguard Worker return this;
2176*8975f5c5SAndroid Build Coastguard Worker }
2177*8975f5c5SAndroid Build Coastguard Worker size_t index = static_cast<size_t>(rightConstant->getIConst());
2178*8975f5c5SAndroid Build Coastguard Worker TIntermAggregate *leftAggregate = mLeft->getAsAggregate();
2179*8975f5c5SAndroid Build Coastguard Worker if (leftAggregate && leftAggregate->isConstructor() && leftAggregate->isArray() &&
2180*8975f5c5SAndroid Build Coastguard Worker !leftAggregate->hasSideEffects())
2181*8975f5c5SAndroid Build Coastguard Worker {
2182*8975f5c5SAndroid Build Coastguard Worker ASSERT(index < leftAggregate->getSequence()->size());
2183*8975f5c5SAndroid Build Coastguard Worker // This transformation can't add complexity as we're eliminating the constructor
2184*8975f5c5SAndroid Build Coastguard Worker // entirely.
2185*8975f5c5SAndroid Build Coastguard Worker return leftAggregate->getSequence()->at(index)->getAsTyped();
2186*8975f5c5SAndroid Build Coastguard Worker }
2187*8975f5c5SAndroid Build Coastguard Worker
2188*8975f5c5SAndroid Build Coastguard Worker // If the indexed value is already a constant union, we can't increase duplication of
2189*8975f5c5SAndroid Build Coastguard Worker // data by folding the indexing. Also fold the node in case it's generally beneficial to
2190*8975f5c5SAndroid Build Coastguard Worker // replace this type of node with a constant union even if that would mean duplicating
2191*8975f5c5SAndroid Build Coastguard Worker // data.
2192*8975f5c5SAndroid Build Coastguard Worker if (mLeft->getAsConstantUnion() || getType().canReplaceWithConstantUnion())
2193*8975f5c5SAndroid Build Coastguard Worker {
2194*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *constantValue = getConstantValue();
2195*8975f5c5SAndroid Build Coastguard Worker if (constantValue != nullptr)
2196*8975f5c5SAndroid Build Coastguard Worker {
2197*8975f5c5SAndroid Build Coastguard Worker return CreateFoldedNode(constantValue, this);
2198*8975f5c5SAndroid Build Coastguard Worker }
2199*8975f5c5SAndroid Build Coastguard Worker }
2200*8975f5c5SAndroid Build Coastguard Worker
2201*8975f5c5SAndroid Build Coastguard Worker // If the indexed value is a swizzle, then the swizzle can be adjusted instead.
2202*8975f5c5SAndroid Build Coastguard Worker TIntermSwizzle *leftSwizzle = mLeft->getAsSwizzleNode();
2203*8975f5c5SAndroid Build Coastguard Worker if (leftSwizzle != nullptr)
2204*8975f5c5SAndroid Build Coastguard Worker {
2205*8975f5c5SAndroid Build Coastguard Worker const TVector<int> &swizzleOffsets = leftSwizzle->getSwizzleOffsets();
2206*8975f5c5SAndroid Build Coastguard Worker ASSERT(index < swizzleOffsets.size());
2207*8975f5c5SAndroid Build Coastguard Worker
2208*8975f5c5SAndroid Build Coastguard Worker int remappedIndex = swizzleOffsets[index];
2209*8975f5c5SAndroid Build Coastguard Worker return new TIntermSwizzle(leftSwizzle->getOperand(), {remappedIndex});
2210*8975f5c5SAndroid Build Coastguard Worker }
2211*8975f5c5SAndroid Build Coastguard Worker
2212*8975f5c5SAndroid Build Coastguard Worker return this;
2213*8975f5c5SAndroid Build Coastguard Worker }
2214*8975f5c5SAndroid Build Coastguard Worker case EOpIndexIndirect:
2215*8975f5c5SAndroid Build Coastguard Worker case EOpIndexDirectInterfaceBlock:
2216*8975f5c5SAndroid Build Coastguard Worker case EOpInitialize:
2217*8975f5c5SAndroid Build Coastguard Worker // Can never be constant folded.
2218*8975f5c5SAndroid Build Coastguard Worker return this;
2219*8975f5c5SAndroid Build Coastguard Worker default:
2220*8975f5c5SAndroid Build Coastguard Worker {
2221*8975f5c5SAndroid Build Coastguard Worker if (rightConstant == nullptr)
2222*8975f5c5SAndroid Build Coastguard Worker {
2223*8975f5c5SAndroid Build Coastguard Worker return this;
2224*8975f5c5SAndroid Build Coastguard Worker }
2225*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *leftConstant = mLeft->getConstantValue();
2226*8975f5c5SAndroid Build Coastguard Worker if (leftConstant == nullptr)
2227*8975f5c5SAndroid Build Coastguard Worker {
2228*8975f5c5SAndroid Build Coastguard Worker return this;
2229*8975f5c5SAndroid Build Coastguard Worker }
2230*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *constArray =
2231*8975f5c5SAndroid Build Coastguard Worker TIntermConstantUnion::FoldBinary(mOp, leftConstant, mLeft->getType(), rightConstant,
2232*8975f5c5SAndroid Build Coastguard Worker mRight->getType(), diagnostics, mLeft->getLine());
2233*8975f5c5SAndroid Build Coastguard Worker if (!constArray)
2234*8975f5c5SAndroid Build Coastguard Worker {
2235*8975f5c5SAndroid Build Coastguard Worker return this;
2236*8975f5c5SAndroid Build Coastguard Worker }
2237*8975f5c5SAndroid Build Coastguard Worker return CreateFoldedNode(constArray, this);
2238*8975f5c5SAndroid Build Coastguard Worker }
2239*8975f5c5SAndroid Build Coastguard Worker }
2240*8975f5c5SAndroid Build Coastguard Worker }
2241*8975f5c5SAndroid Build Coastguard Worker
hasConstantValue() const2242*8975f5c5SAndroid Build Coastguard Worker bool TIntermBinary::hasConstantValue() const
2243*8975f5c5SAndroid Build Coastguard Worker {
2244*8975f5c5SAndroid Build Coastguard Worker switch (mOp)
2245*8975f5c5SAndroid Build Coastguard Worker {
2246*8975f5c5SAndroid Build Coastguard Worker case EOpIndexDirect:
2247*8975f5c5SAndroid Build Coastguard Worker case EOpIndexDirectStruct:
2248*8975f5c5SAndroid Build Coastguard Worker {
2249*8975f5c5SAndroid Build Coastguard Worker if (mLeft->hasConstantValue() && mRight->hasConstantValue())
2250*8975f5c5SAndroid Build Coastguard Worker {
2251*8975f5c5SAndroid Build Coastguard Worker return true;
2252*8975f5c5SAndroid Build Coastguard Worker }
2253*8975f5c5SAndroid Build Coastguard Worker break;
2254*8975f5c5SAndroid Build Coastguard Worker }
2255*8975f5c5SAndroid Build Coastguard Worker default:
2256*8975f5c5SAndroid Build Coastguard Worker break;
2257*8975f5c5SAndroid Build Coastguard Worker }
2258*8975f5c5SAndroid Build Coastguard Worker return false;
2259*8975f5c5SAndroid Build Coastguard Worker }
2260*8975f5c5SAndroid Build Coastguard Worker
getConstantValue() const2261*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *TIntermBinary::getConstantValue() const
2262*8975f5c5SAndroid Build Coastguard Worker {
2263*8975f5c5SAndroid Build Coastguard Worker if (!hasConstantValue())
2264*8975f5c5SAndroid Build Coastguard Worker {
2265*8975f5c5SAndroid Build Coastguard Worker return nullptr;
2266*8975f5c5SAndroid Build Coastguard Worker }
2267*8975f5c5SAndroid Build Coastguard Worker
2268*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *leftConstantValue = mLeft->getConstantValue();
2269*8975f5c5SAndroid Build Coastguard Worker int index = mRight->getConstantValue()->getIConst();
2270*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *constIndexingResult = nullptr;
2271*8975f5c5SAndroid Build Coastguard Worker if (mOp == EOpIndexDirect)
2272*8975f5c5SAndroid Build Coastguard Worker {
2273*8975f5c5SAndroid Build Coastguard Worker constIndexingResult =
2274*8975f5c5SAndroid Build Coastguard Worker TIntermConstantUnion::FoldIndexing(mLeft->getType(), leftConstantValue, index);
2275*8975f5c5SAndroid Build Coastguard Worker }
2276*8975f5c5SAndroid Build Coastguard Worker else
2277*8975f5c5SAndroid Build Coastguard Worker {
2278*8975f5c5SAndroid Build Coastguard Worker ASSERT(mOp == EOpIndexDirectStruct);
2279*8975f5c5SAndroid Build Coastguard Worker const TFieldList &fields = mLeft->getType().getStruct()->fields();
2280*8975f5c5SAndroid Build Coastguard Worker
2281*8975f5c5SAndroid Build Coastguard Worker size_t previousFieldsSize = 0;
2282*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < index; ++i)
2283*8975f5c5SAndroid Build Coastguard Worker {
2284*8975f5c5SAndroid Build Coastguard Worker previousFieldsSize += fields[i]->type()->getObjectSize();
2285*8975f5c5SAndroid Build Coastguard Worker }
2286*8975f5c5SAndroid Build Coastguard Worker constIndexingResult = leftConstantValue + previousFieldsSize;
2287*8975f5c5SAndroid Build Coastguard Worker }
2288*8975f5c5SAndroid Build Coastguard Worker return constIndexingResult;
2289*8975f5c5SAndroid Build Coastguard Worker }
2290*8975f5c5SAndroid Build Coastguard Worker
getIndexStructFieldName() const2291*8975f5c5SAndroid Build Coastguard Worker const ImmutableString &TIntermBinary::getIndexStructFieldName() const
2292*8975f5c5SAndroid Build Coastguard Worker {
2293*8975f5c5SAndroid Build Coastguard Worker ASSERT(mOp == EOpIndexDirectStruct);
2294*8975f5c5SAndroid Build Coastguard Worker
2295*8975f5c5SAndroid Build Coastguard Worker const TType &lhsType = mLeft->getType();
2296*8975f5c5SAndroid Build Coastguard Worker const TStructure *structure = lhsType.getStruct();
2297*8975f5c5SAndroid Build Coastguard Worker const int index = mRight->getAsConstantUnion()->getIConst(0);
2298*8975f5c5SAndroid Build Coastguard Worker
2299*8975f5c5SAndroid Build Coastguard Worker return structure->fields()[index]->name();
2300*8975f5c5SAndroid Build Coastguard Worker }
2301*8975f5c5SAndroid Build Coastguard Worker
fold(TDiagnostics * diagnostics)2302*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
2303*8975f5c5SAndroid Build Coastguard Worker {
2304*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *constArray = nullptr;
2305*8975f5c5SAndroid Build Coastguard Worker
2306*8975f5c5SAndroid Build Coastguard Worker if (mOp == EOpArrayLength)
2307*8975f5c5SAndroid Build Coastguard Worker {
2308*8975f5c5SAndroid Build Coastguard Worker // The size of runtime-sized arrays may only be determined at runtime.
2309*8975f5c5SAndroid Build Coastguard Worker // This operation is folded for clip/cull distance arrays in RemoveArrayLengthMethod.
2310*8975f5c5SAndroid Build Coastguard Worker if (mOperand->hasSideEffects() || mOperand->getType().isUnsizedArray() ||
2311*8975f5c5SAndroid Build Coastguard Worker mOperand->getQualifier() == EvqClipDistance ||
2312*8975f5c5SAndroid Build Coastguard Worker mOperand->getQualifier() == EvqCullDistance)
2313*8975f5c5SAndroid Build Coastguard Worker {
2314*8975f5c5SAndroid Build Coastguard Worker return this;
2315*8975f5c5SAndroid Build Coastguard Worker }
2316*8975f5c5SAndroid Build Coastguard Worker constArray = new TConstantUnion[1];
2317*8975f5c5SAndroid Build Coastguard Worker constArray->setIConst(mOperand->getOutermostArraySize());
2318*8975f5c5SAndroid Build Coastguard Worker }
2319*8975f5c5SAndroid Build Coastguard Worker else
2320*8975f5c5SAndroid Build Coastguard Worker {
2321*8975f5c5SAndroid Build Coastguard Worker TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
2322*8975f5c5SAndroid Build Coastguard Worker if (operandConstant == nullptr)
2323*8975f5c5SAndroid Build Coastguard Worker {
2324*8975f5c5SAndroid Build Coastguard Worker return this;
2325*8975f5c5SAndroid Build Coastguard Worker }
2326*8975f5c5SAndroid Build Coastguard Worker
2327*8975f5c5SAndroid Build Coastguard Worker switch (mOp)
2328*8975f5c5SAndroid Build Coastguard Worker {
2329*8975f5c5SAndroid Build Coastguard Worker case EOpAny:
2330*8975f5c5SAndroid Build Coastguard Worker case EOpAll:
2331*8975f5c5SAndroid Build Coastguard Worker case EOpLength:
2332*8975f5c5SAndroid Build Coastguard Worker case EOpTranspose:
2333*8975f5c5SAndroid Build Coastguard Worker case EOpDeterminant:
2334*8975f5c5SAndroid Build Coastguard Worker case EOpInverse:
2335*8975f5c5SAndroid Build Coastguard Worker case EOpPackSnorm2x16:
2336*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackSnorm2x16:
2337*8975f5c5SAndroid Build Coastguard Worker case EOpPackUnorm2x16:
2338*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackUnorm2x16:
2339*8975f5c5SAndroid Build Coastguard Worker case EOpPackHalf2x16:
2340*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackHalf2x16:
2341*8975f5c5SAndroid Build Coastguard Worker case EOpPackUnorm4x8:
2342*8975f5c5SAndroid Build Coastguard Worker case EOpPackSnorm4x8:
2343*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackUnorm4x8:
2344*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackSnorm4x8:
2345*8975f5c5SAndroid Build Coastguard Worker constArray = operandConstant->foldUnaryNonComponentWise(mOp);
2346*8975f5c5SAndroid Build Coastguard Worker break;
2347*8975f5c5SAndroid Build Coastguard Worker default:
2348*8975f5c5SAndroid Build Coastguard Worker constArray = operandConstant->foldUnaryComponentWise(mOp, mFunction, diagnostics);
2349*8975f5c5SAndroid Build Coastguard Worker break;
2350*8975f5c5SAndroid Build Coastguard Worker }
2351*8975f5c5SAndroid Build Coastguard Worker }
2352*8975f5c5SAndroid Build Coastguard Worker if (constArray == nullptr)
2353*8975f5c5SAndroid Build Coastguard Worker {
2354*8975f5c5SAndroid Build Coastguard Worker return this;
2355*8975f5c5SAndroid Build Coastguard Worker }
2356*8975f5c5SAndroid Build Coastguard Worker return CreateFoldedNode(constArray, this);
2357*8975f5c5SAndroid Build Coastguard Worker }
2358*8975f5c5SAndroid Build Coastguard Worker
fold(TDiagnostics * diagnostics)2359*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics)
2360*8975f5c5SAndroid Build Coastguard Worker {
2361*8975f5c5SAndroid Build Coastguard Worker // Make sure that all params are constant before actual constant folding.
2362*8975f5c5SAndroid Build Coastguard Worker for (auto *param : *getSequence())
2363*8975f5c5SAndroid Build Coastguard Worker {
2364*8975f5c5SAndroid Build Coastguard Worker if (param->getAsConstantUnion() == nullptr)
2365*8975f5c5SAndroid Build Coastguard Worker {
2366*8975f5c5SAndroid Build Coastguard Worker return this;
2367*8975f5c5SAndroid Build Coastguard Worker }
2368*8975f5c5SAndroid Build Coastguard Worker }
2369*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *constArray = nullptr;
2370*8975f5c5SAndroid Build Coastguard Worker if (isConstructor())
2371*8975f5c5SAndroid Build Coastguard Worker {
2372*8975f5c5SAndroid Build Coastguard Worker if (mType.canReplaceWithConstantUnion())
2373*8975f5c5SAndroid Build Coastguard Worker {
2374*8975f5c5SAndroid Build Coastguard Worker constArray = getConstantValue();
2375*8975f5c5SAndroid Build Coastguard Worker if (constArray && mType.getBasicType() == EbtUInt)
2376*8975f5c5SAndroid Build Coastguard Worker {
2377*8975f5c5SAndroid Build Coastguard Worker // Check if we converted a negative float to uint and issue a warning in that case.
2378*8975f5c5SAndroid Build Coastguard Worker size_t sizeRemaining = mType.getObjectSize();
2379*8975f5c5SAndroid Build Coastguard Worker for (TIntermNode *arg : mArguments)
2380*8975f5c5SAndroid Build Coastguard Worker {
2381*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *typedArg = arg->getAsTyped();
2382*8975f5c5SAndroid Build Coastguard Worker if (typedArg->getBasicType() == EbtFloat)
2383*8975f5c5SAndroid Build Coastguard Worker {
2384*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *argValue = typedArg->getConstantValue();
2385*8975f5c5SAndroid Build Coastguard Worker size_t castSize =
2386*8975f5c5SAndroid Build Coastguard Worker std::min(typedArg->getType().getObjectSize(), sizeRemaining);
2387*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < castSize; ++i)
2388*8975f5c5SAndroid Build Coastguard Worker {
2389*8975f5c5SAndroid Build Coastguard Worker if (argValue[i].getFConst() < 0.0f)
2390*8975f5c5SAndroid Build Coastguard Worker {
2391*8975f5c5SAndroid Build Coastguard Worker // ESSL 3.00.6 section 5.4.1.
2392*8975f5c5SAndroid Build Coastguard Worker diagnostics->warning(
2393*8975f5c5SAndroid Build Coastguard Worker mLine, "casting a negative float to uint is undefined",
2394*8975f5c5SAndroid Build Coastguard Worker mType.getBuiltInTypeNameString());
2395*8975f5c5SAndroid Build Coastguard Worker }
2396*8975f5c5SAndroid Build Coastguard Worker }
2397*8975f5c5SAndroid Build Coastguard Worker }
2398*8975f5c5SAndroid Build Coastguard Worker sizeRemaining -= typedArg->getType().getObjectSize();
2399*8975f5c5SAndroid Build Coastguard Worker }
2400*8975f5c5SAndroid Build Coastguard Worker }
2401*8975f5c5SAndroid Build Coastguard Worker }
2402*8975f5c5SAndroid Build Coastguard Worker }
2403*8975f5c5SAndroid Build Coastguard Worker else if (CanFoldAggregateBuiltInOp(mOp))
2404*8975f5c5SAndroid Build Coastguard Worker {
2405*8975f5c5SAndroid Build Coastguard Worker constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics);
2406*8975f5c5SAndroid Build Coastguard Worker }
2407*8975f5c5SAndroid Build Coastguard Worker if (constArray == nullptr)
2408*8975f5c5SAndroid Build Coastguard Worker {
2409*8975f5c5SAndroid Build Coastguard Worker return this;
2410*8975f5c5SAndroid Build Coastguard Worker }
2411*8975f5c5SAndroid Build Coastguard Worker return CreateFoldedNode(constArray, this);
2412*8975f5c5SAndroid Build Coastguard Worker }
2413*8975f5c5SAndroid Build Coastguard Worker
2414*8975f5c5SAndroid Build Coastguard Worker //
2415*8975f5c5SAndroid Build Coastguard Worker // The fold functions see if an operation on a constant can be done in place,
2416*8975f5c5SAndroid Build Coastguard Worker // without generating run-time code.
2417*8975f5c5SAndroid Build Coastguard Worker //
2418*8975f5c5SAndroid Build Coastguard Worker // Returns the constant value to keep using or nullptr.
2419*8975f5c5SAndroid Build Coastguard Worker //
FoldBinary(TOperator op,const TConstantUnion * leftArray,const TType & leftType,const TConstantUnion * rightArray,const TType & rightType,TDiagnostics * diagnostics,const TSourceLoc & line)2420*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *TIntermConstantUnion::FoldBinary(TOperator op,
2421*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *leftArray,
2422*8975f5c5SAndroid Build Coastguard Worker const TType &leftType,
2423*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *rightArray,
2424*8975f5c5SAndroid Build Coastguard Worker const TType &rightType,
2425*8975f5c5SAndroid Build Coastguard Worker TDiagnostics *diagnostics,
2426*8975f5c5SAndroid Build Coastguard Worker const TSourceLoc &line)
2427*8975f5c5SAndroid Build Coastguard Worker {
2428*8975f5c5SAndroid Build Coastguard Worker ASSERT(leftArray && rightArray);
2429*8975f5c5SAndroid Build Coastguard Worker
2430*8975f5c5SAndroid Build Coastguard Worker size_t objectSize = leftType.getObjectSize();
2431*8975f5c5SAndroid Build Coastguard Worker
2432*8975f5c5SAndroid Build Coastguard Worker // for a case like float f = vec4(2, 3, 4, 5) + 1.2;
2433*8975f5c5SAndroid Build Coastguard Worker if (rightType.getObjectSize() == 1 && objectSize > 1)
2434*8975f5c5SAndroid Build Coastguard Worker {
2435*8975f5c5SAndroid Build Coastguard Worker rightArray = Vectorize(*rightArray, objectSize);
2436*8975f5c5SAndroid Build Coastguard Worker }
2437*8975f5c5SAndroid Build Coastguard Worker else if (rightType.getObjectSize() > 1 && objectSize == 1)
2438*8975f5c5SAndroid Build Coastguard Worker {
2439*8975f5c5SAndroid Build Coastguard Worker // for a case like float f = 1.2 + vec4(2, 3, 4, 5);
2440*8975f5c5SAndroid Build Coastguard Worker leftArray = Vectorize(*leftArray, rightType.getObjectSize());
2441*8975f5c5SAndroid Build Coastguard Worker objectSize = rightType.getObjectSize();
2442*8975f5c5SAndroid Build Coastguard Worker }
2443*8975f5c5SAndroid Build Coastguard Worker
2444*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *resultArray = nullptr;
2445*8975f5c5SAndroid Build Coastguard Worker
2446*8975f5c5SAndroid Build Coastguard Worker switch (op)
2447*8975f5c5SAndroid Build Coastguard Worker {
2448*8975f5c5SAndroid Build Coastguard Worker case EOpAdd:
2449*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[objectSize];
2450*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2451*8975f5c5SAndroid Build Coastguard Worker resultArray[i] =
2452*8975f5c5SAndroid Build Coastguard Worker TConstantUnion::add(leftArray[i], rightArray[i], diagnostics, line);
2453*8975f5c5SAndroid Build Coastguard Worker break;
2454*8975f5c5SAndroid Build Coastguard Worker case EOpSub:
2455*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[objectSize];
2456*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2457*8975f5c5SAndroid Build Coastguard Worker resultArray[i] =
2458*8975f5c5SAndroid Build Coastguard Worker TConstantUnion::sub(leftArray[i], rightArray[i], diagnostics, line);
2459*8975f5c5SAndroid Build Coastguard Worker break;
2460*8975f5c5SAndroid Build Coastguard Worker
2461*8975f5c5SAndroid Build Coastguard Worker case EOpMul:
2462*8975f5c5SAndroid Build Coastguard Worker case EOpVectorTimesScalar:
2463*8975f5c5SAndroid Build Coastguard Worker case EOpMatrixTimesScalar:
2464*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[objectSize];
2465*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2466*8975f5c5SAndroid Build Coastguard Worker resultArray[i] =
2467*8975f5c5SAndroid Build Coastguard Worker TConstantUnion::mul(leftArray[i], rightArray[i], diagnostics, line);
2468*8975f5c5SAndroid Build Coastguard Worker break;
2469*8975f5c5SAndroid Build Coastguard Worker
2470*8975f5c5SAndroid Build Coastguard Worker case EOpMatrixTimesMatrix:
2471*8975f5c5SAndroid Build Coastguard Worker {
2472*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadll): This code should check for overflows.
2473*8975f5c5SAndroid Build Coastguard Worker ASSERT(leftType.getBasicType() == EbtFloat && rightType.getBasicType() == EbtFloat);
2474*8975f5c5SAndroid Build Coastguard Worker
2475*8975f5c5SAndroid Build Coastguard Worker const uint8_t leftCols = leftType.getCols();
2476*8975f5c5SAndroid Build Coastguard Worker const uint8_t leftRows = leftType.getRows();
2477*8975f5c5SAndroid Build Coastguard Worker const uint8_t rightCols = rightType.getCols();
2478*8975f5c5SAndroid Build Coastguard Worker const uint8_t rightRows = rightType.getRows();
2479*8975f5c5SAndroid Build Coastguard Worker const uint8_t resultCols = rightCols;
2480*8975f5c5SAndroid Build Coastguard Worker const uint8_t resultRows = leftRows;
2481*8975f5c5SAndroid Build Coastguard Worker
2482*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[resultCols * resultRows];
2483*8975f5c5SAndroid Build Coastguard Worker for (uint8_t row = 0; row < resultRows; row++)
2484*8975f5c5SAndroid Build Coastguard Worker {
2485*8975f5c5SAndroid Build Coastguard Worker for (uint8_t column = 0; column < resultCols; column++)
2486*8975f5c5SAndroid Build Coastguard Worker {
2487*8975f5c5SAndroid Build Coastguard Worker resultArray[resultRows * column + row].setFConst(0.0f);
2488*8975f5c5SAndroid Build Coastguard Worker for (uint8_t i = 0; i < leftCols; i++)
2489*8975f5c5SAndroid Build Coastguard Worker {
2490*8975f5c5SAndroid Build Coastguard Worker resultArray[resultRows * column + row].setFConst(
2491*8975f5c5SAndroid Build Coastguard Worker resultArray[resultRows * column + row].getFConst() +
2492*8975f5c5SAndroid Build Coastguard Worker leftArray[i * leftRows + row].getFConst() *
2493*8975f5c5SAndroid Build Coastguard Worker rightArray[column * rightRows + i].getFConst());
2494*8975f5c5SAndroid Build Coastguard Worker }
2495*8975f5c5SAndroid Build Coastguard Worker }
2496*8975f5c5SAndroid Build Coastguard Worker }
2497*8975f5c5SAndroid Build Coastguard Worker }
2498*8975f5c5SAndroid Build Coastguard Worker break;
2499*8975f5c5SAndroid Build Coastguard Worker
2500*8975f5c5SAndroid Build Coastguard Worker case EOpDiv:
2501*8975f5c5SAndroid Build Coastguard Worker case EOpIMod:
2502*8975f5c5SAndroid Build Coastguard Worker {
2503*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[objectSize];
2504*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2505*8975f5c5SAndroid Build Coastguard Worker {
2506*8975f5c5SAndroid Build Coastguard Worker if (leftType.getBasicType() == EbtFloat)
2507*8975f5c5SAndroid Build Coastguard Worker {
2508*8975f5c5SAndroid Build Coastguard Worker // Float division requested, possibly with implicit conversion
2509*8975f5c5SAndroid Build Coastguard Worker ASSERT(op == EOpDiv);
2510*8975f5c5SAndroid Build Coastguard Worker float dividend = leftArray[i].getFConst();
2511*8975f5c5SAndroid Build Coastguard Worker float divisor = rightArray[i].getFConst();
2512*8975f5c5SAndroid Build Coastguard Worker
2513*8975f5c5SAndroid Build Coastguard Worker if (divisor == 0.0f)
2514*8975f5c5SAndroid Build Coastguard Worker {
2515*8975f5c5SAndroid Build Coastguard Worker if (dividend == 0.0f)
2516*8975f5c5SAndroid Build Coastguard Worker {
2517*8975f5c5SAndroid Build Coastguard Worker diagnostics->warning(line,
2518*8975f5c5SAndroid Build Coastguard Worker "Zero divided by zero during constant "
2519*8975f5c5SAndroid Build Coastguard Worker "folding generated NaN",
2520*8975f5c5SAndroid Build Coastguard Worker "/");
2521*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
2522*8975f5c5SAndroid Build Coastguard Worker }
2523*8975f5c5SAndroid Build Coastguard Worker else
2524*8975f5c5SAndroid Build Coastguard Worker {
2525*8975f5c5SAndroid Build Coastguard Worker diagnostics->warning(line, "Divide by zero during constant folding",
2526*8975f5c5SAndroid Build Coastguard Worker "/");
2527*8975f5c5SAndroid Build Coastguard Worker bool negativeResult = std::signbit(dividend) != std::signbit(divisor);
2528*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(negativeResult
2529*8975f5c5SAndroid Build Coastguard Worker ? -std::numeric_limits<float>::infinity()
2530*8975f5c5SAndroid Build Coastguard Worker : std::numeric_limits<float>::infinity());
2531*8975f5c5SAndroid Build Coastguard Worker }
2532*8975f5c5SAndroid Build Coastguard Worker }
2533*8975f5c5SAndroid Build Coastguard Worker else if (gl::isInf(dividend) && gl::isInf(divisor))
2534*8975f5c5SAndroid Build Coastguard Worker {
2535*8975f5c5SAndroid Build Coastguard Worker diagnostics->warning(line,
2536*8975f5c5SAndroid Build Coastguard Worker "Infinity divided by infinity during constant "
2537*8975f5c5SAndroid Build Coastguard Worker "folding generated NaN",
2538*8975f5c5SAndroid Build Coastguard Worker "/");
2539*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
2540*8975f5c5SAndroid Build Coastguard Worker }
2541*8975f5c5SAndroid Build Coastguard Worker else
2542*8975f5c5SAndroid Build Coastguard Worker {
2543*8975f5c5SAndroid Build Coastguard Worker float result = dividend / divisor;
2544*8975f5c5SAndroid Build Coastguard Worker if (!gl::isInf(dividend) && gl::isInf(result))
2545*8975f5c5SAndroid Build Coastguard Worker {
2546*8975f5c5SAndroid Build Coastguard Worker diagnostics->warning(
2547*8975f5c5SAndroid Build Coastguard Worker line, "Constant folded division overflowed to infinity", "/");
2548*8975f5c5SAndroid Build Coastguard Worker }
2549*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(result);
2550*8975f5c5SAndroid Build Coastguard Worker }
2551*8975f5c5SAndroid Build Coastguard Worker }
2552*8975f5c5SAndroid Build Coastguard Worker else
2553*8975f5c5SAndroid Build Coastguard Worker {
2554*8975f5c5SAndroid Build Coastguard Worker // Types are either both int or both uint
2555*8975f5c5SAndroid Build Coastguard Worker switch (leftType.getBasicType())
2556*8975f5c5SAndroid Build Coastguard Worker {
2557*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
2558*8975f5c5SAndroid Build Coastguard Worker {
2559*8975f5c5SAndroid Build Coastguard Worker if (rightArray[i] == 0)
2560*8975f5c5SAndroid Build Coastguard Worker {
2561*8975f5c5SAndroid Build Coastguard Worker diagnostics->warning(
2562*8975f5c5SAndroid Build Coastguard Worker line, "Divide by zero error during constant folding", "/");
2563*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(INT_MAX);
2564*8975f5c5SAndroid Build Coastguard Worker }
2565*8975f5c5SAndroid Build Coastguard Worker else
2566*8975f5c5SAndroid Build Coastguard Worker {
2567*8975f5c5SAndroid Build Coastguard Worker int lhs = leftArray[i].getIConst();
2568*8975f5c5SAndroid Build Coastguard Worker int divisor = rightArray[i].getIConst();
2569*8975f5c5SAndroid Build Coastguard Worker if (op == EOpDiv)
2570*8975f5c5SAndroid Build Coastguard Worker {
2571*8975f5c5SAndroid Build Coastguard Worker // Check for the special case where the minimum
2572*8975f5c5SAndroid Build Coastguard Worker // representable number is divided by -1. If left alone this
2573*8975f5c5SAndroid Build Coastguard Worker // leads to integer overflow in C++. ESSL 3.00.6
2574*8975f5c5SAndroid Build Coastguard Worker // section 4.1.3 Integers: "However, for the case where the
2575*8975f5c5SAndroid Build Coastguard Worker // minimum representable value is divided by -1, it is
2576*8975f5c5SAndroid Build Coastguard Worker // allowed to return either the minimum representable value
2577*8975f5c5SAndroid Build Coastguard Worker // or the maximum representable value."
2578*8975f5c5SAndroid Build Coastguard Worker if (lhs == -0x7fffffff - 1 && divisor == -1)
2579*8975f5c5SAndroid Build Coastguard Worker {
2580*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(0x7fffffff);
2581*8975f5c5SAndroid Build Coastguard Worker }
2582*8975f5c5SAndroid Build Coastguard Worker else
2583*8975f5c5SAndroid Build Coastguard Worker {
2584*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(lhs / divisor);
2585*8975f5c5SAndroid Build Coastguard Worker }
2586*8975f5c5SAndroid Build Coastguard Worker }
2587*8975f5c5SAndroid Build Coastguard Worker else
2588*8975f5c5SAndroid Build Coastguard Worker {
2589*8975f5c5SAndroid Build Coastguard Worker ASSERT(op == EOpIMod);
2590*8975f5c5SAndroid Build Coastguard Worker if (lhs < 0 || divisor < 0)
2591*8975f5c5SAndroid Build Coastguard Worker {
2592*8975f5c5SAndroid Build Coastguard Worker // ESSL 3.00.6 section 5.9: Results of modulus are
2593*8975f5c5SAndroid Build Coastguard Worker // undefined when either one of the operands is
2594*8975f5c5SAndroid Build Coastguard Worker // negative.
2595*8975f5c5SAndroid Build Coastguard Worker diagnostics->warning(line,
2596*8975f5c5SAndroid Build Coastguard Worker "Negative modulus operator operand "
2597*8975f5c5SAndroid Build Coastguard Worker "encountered during constant folding. "
2598*8975f5c5SAndroid Build Coastguard Worker "Results are undefined.",
2599*8975f5c5SAndroid Build Coastguard Worker "%");
2600*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(0);
2601*8975f5c5SAndroid Build Coastguard Worker }
2602*8975f5c5SAndroid Build Coastguard Worker else
2603*8975f5c5SAndroid Build Coastguard Worker {
2604*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(lhs % divisor);
2605*8975f5c5SAndroid Build Coastguard Worker }
2606*8975f5c5SAndroid Build Coastguard Worker }
2607*8975f5c5SAndroid Build Coastguard Worker }
2608*8975f5c5SAndroid Build Coastguard Worker break;
2609*8975f5c5SAndroid Build Coastguard Worker }
2610*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
2611*8975f5c5SAndroid Build Coastguard Worker {
2612*8975f5c5SAndroid Build Coastguard Worker if (rightArray[i] == 0)
2613*8975f5c5SAndroid Build Coastguard Worker {
2614*8975f5c5SAndroid Build Coastguard Worker diagnostics->warning(
2615*8975f5c5SAndroid Build Coastguard Worker line, "Divide by zero error during constant folding", "/");
2616*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(UINT_MAX);
2617*8975f5c5SAndroid Build Coastguard Worker }
2618*8975f5c5SAndroid Build Coastguard Worker else
2619*8975f5c5SAndroid Build Coastguard Worker {
2620*8975f5c5SAndroid Build Coastguard Worker if (op == EOpDiv)
2621*8975f5c5SAndroid Build Coastguard Worker {
2622*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(leftArray[i].getUConst() /
2623*8975f5c5SAndroid Build Coastguard Worker rightArray[i].getUConst());
2624*8975f5c5SAndroid Build Coastguard Worker }
2625*8975f5c5SAndroid Build Coastguard Worker else
2626*8975f5c5SAndroid Build Coastguard Worker {
2627*8975f5c5SAndroid Build Coastguard Worker ASSERT(op == EOpIMod);
2628*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(leftArray[i].getUConst() %
2629*8975f5c5SAndroid Build Coastguard Worker rightArray[i].getUConst());
2630*8975f5c5SAndroid Build Coastguard Worker }
2631*8975f5c5SAndroid Build Coastguard Worker }
2632*8975f5c5SAndroid Build Coastguard Worker break;
2633*8975f5c5SAndroid Build Coastguard Worker }
2634*8975f5c5SAndroid Build Coastguard Worker default:
2635*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
2636*8975f5c5SAndroid Build Coastguard Worker return nullptr;
2637*8975f5c5SAndroid Build Coastguard Worker }
2638*8975f5c5SAndroid Build Coastguard Worker }
2639*8975f5c5SAndroid Build Coastguard Worker }
2640*8975f5c5SAndroid Build Coastguard Worker }
2641*8975f5c5SAndroid Build Coastguard Worker break;
2642*8975f5c5SAndroid Build Coastguard Worker
2643*8975f5c5SAndroid Build Coastguard Worker case EOpMatrixTimesVector:
2644*8975f5c5SAndroid Build Coastguard Worker {
2645*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadll): This code should check for overflows.
2646*8975f5c5SAndroid Build Coastguard Worker ASSERT(rightType.getBasicType() == EbtFloat);
2647*8975f5c5SAndroid Build Coastguard Worker
2648*8975f5c5SAndroid Build Coastguard Worker const uint8_t matrixCols = leftType.getCols();
2649*8975f5c5SAndroid Build Coastguard Worker const uint8_t matrixRows = leftType.getRows();
2650*8975f5c5SAndroid Build Coastguard Worker
2651*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[matrixRows];
2652*8975f5c5SAndroid Build Coastguard Worker
2653*8975f5c5SAndroid Build Coastguard Worker for (uint8_t matrixRow = 0; matrixRow < matrixRows; matrixRow++)
2654*8975f5c5SAndroid Build Coastguard Worker {
2655*8975f5c5SAndroid Build Coastguard Worker resultArray[matrixRow].setFConst(0.0f);
2656*8975f5c5SAndroid Build Coastguard Worker for (uint8_t col = 0; col < matrixCols; col++)
2657*8975f5c5SAndroid Build Coastguard Worker {
2658*8975f5c5SAndroid Build Coastguard Worker resultArray[matrixRow].setFConst(
2659*8975f5c5SAndroid Build Coastguard Worker resultArray[matrixRow].getFConst() +
2660*8975f5c5SAndroid Build Coastguard Worker leftArray[col * matrixRows + matrixRow].getFConst() *
2661*8975f5c5SAndroid Build Coastguard Worker rightArray[col].getFConst());
2662*8975f5c5SAndroid Build Coastguard Worker }
2663*8975f5c5SAndroid Build Coastguard Worker }
2664*8975f5c5SAndroid Build Coastguard Worker }
2665*8975f5c5SAndroid Build Coastguard Worker break;
2666*8975f5c5SAndroid Build Coastguard Worker
2667*8975f5c5SAndroid Build Coastguard Worker case EOpVectorTimesMatrix:
2668*8975f5c5SAndroid Build Coastguard Worker {
2669*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadll): This code should check for overflows.
2670*8975f5c5SAndroid Build Coastguard Worker ASSERT(leftType.getBasicType() == EbtFloat);
2671*8975f5c5SAndroid Build Coastguard Worker
2672*8975f5c5SAndroid Build Coastguard Worker const uint8_t matrixCols = rightType.getCols();
2673*8975f5c5SAndroid Build Coastguard Worker const uint8_t matrixRows = rightType.getRows();
2674*8975f5c5SAndroid Build Coastguard Worker
2675*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[matrixCols];
2676*8975f5c5SAndroid Build Coastguard Worker
2677*8975f5c5SAndroid Build Coastguard Worker for (uint8_t matrixCol = 0; matrixCol < matrixCols; matrixCol++)
2678*8975f5c5SAndroid Build Coastguard Worker {
2679*8975f5c5SAndroid Build Coastguard Worker resultArray[matrixCol].setFConst(0.0f);
2680*8975f5c5SAndroid Build Coastguard Worker for (uint8_t matrixRow = 0; matrixRow < matrixRows; matrixRow++)
2681*8975f5c5SAndroid Build Coastguard Worker {
2682*8975f5c5SAndroid Build Coastguard Worker resultArray[matrixCol].setFConst(
2683*8975f5c5SAndroid Build Coastguard Worker resultArray[matrixCol].getFConst() +
2684*8975f5c5SAndroid Build Coastguard Worker leftArray[matrixRow].getFConst() *
2685*8975f5c5SAndroid Build Coastguard Worker rightArray[matrixCol * matrixRows + matrixRow].getFConst());
2686*8975f5c5SAndroid Build Coastguard Worker }
2687*8975f5c5SAndroid Build Coastguard Worker }
2688*8975f5c5SAndroid Build Coastguard Worker }
2689*8975f5c5SAndroid Build Coastguard Worker break;
2690*8975f5c5SAndroid Build Coastguard Worker
2691*8975f5c5SAndroid Build Coastguard Worker case EOpLogicalAnd:
2692*8975f5c5SAndroid Build Coastguard Worker {
2693*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[objectSize];
2694*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2695*8975f5c5SAndroid Build Coastguard Worker {
2696*8975f5c5SAndroid Build Coastguard Worker resultArray[i] = leftArray[i] && rightArray[i];
2697*8975f5c5SAndroid Build Coastguard Worker }
2698*8975f5c5SAndroid Build Coastguard Worker }
2699*8975f5c5SAndroid Build Coastguard Worker break;
2700*8975f5c5SAndroid Build Coastguard Worker
2701*8975f5c5SAndroid Build Coastguard Worker case EOpLogicalOr:
2702*8975f5c5SAndroid Build Coastguard Worker {
2703*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[objectSize];
2704*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2705*8975f5c5SAndroid Build Coastguard Worker {
2706*8975f5c5SAndroid Build Coastguard Worker resultArray[i] = leftArray[i] || rightArray[i];
2707*8975f5c5SAndroid Build Coastguard Worker }
2708*8975f5c5SAndroid Build Coastguard Worker }
2709*8975f5c5SAndroid Build Coastguard Worker break;
2710*8975f5c5SAndroid Build Coastguard Worker
2711*8975f5c5SAndroid Build Coastguard Worker case EOpLogicalXor:
2712*8975f5c5SAndroid Build Coastguard Worker {
2713*8975f5c5SAndroid Build Coastguard Worker ASSERT(leftType.getBasicType() == EbtBool);
2714*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[objectSize];
2715*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2716*8975f5c5SAndroid Build Coastguard Worker {
2717*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(leftArray[i] != rightArray[i]);
2718*8975f5c5SAndroid Build Coastguard Worker }
2719*8975f5c5SAndroid Build Coastguard Worker }
2720*8975f5c5SAndroid Build Coastguard Worker break;
2721*8975f5c5SAndroid Build Coastguard Worker
2722*8975f5c5SAndroid Build Coastguard Worker case EOpBitwiseAnd:
2723*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[objectSize];
2724*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2725*8975f5c5SAndroid Build Coastguard Worker resultArray[i] = leftArray[i] & rightArray[i];
2726*8975f5c5SAndroid Build Coastguard Worker break;
2727*8975f5c5SAndroid Build Coastguard Worker case EOpBitwiseXor:
2728*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[objectSize];
2729*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2730*8975f5c5SAndroid Build Coastguard Worker resultArray[i] = leftArray[i] ^ rightArray[i];
2731*8975f5c5SAndroid Build Coastguard Worker break;
2732*8975f5c5SAndroid Build Coastguard Worker case EOpBitwiseOr:
2733*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[objectSize];
2734*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2735*8975f5c5SAndroid Build Coastguard Worker resultArray[i] = leftArray[i] | rightArray[i];
2736*8975f5c5SAndroid Build Coastguard Worker break;
2737*8975f5c5SAndroid Build Coastguard Worker case EOpBitShiftLeft:
2738*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[objectSize];
2739*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2740*8975f5c5SAndroid Build Coastguard Worker resultArray[i] =
2741*8975f5c5SAndroid Build Coastguard Worker TConstantUnion::lshift(leftArray[i], rightArray[i], diagnostics, line);
2742*8975f5c5SAndroid Build Coastguard Worker break;
2743*8975f5c5SAndroid Build Coastguard Worker case EOpBitShiftRight:
2744*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[objectSize];
2745*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2746*8975f5c5SAndroid Build Coastguard Worker resultArray[i] =
2747*8975f5c5SAndroid Build Coastguard Worker TConstantUnion::rshift(leftArray[i], rightArray[i], diagnostics, line);
2748*8975f5c5SAndroid Build Coastguard Worker break;
2749*8975f5c5SAndroid Build Coastguard Worker
2750*8975f5c5SAndroid Build Coastguard Worker case EOpLessThan:
2751*8975f5c5SAndroid Build Coastguard Worker ASSERT(objectSize == 1);
2752*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[1];
2753*8975f5c5SAndroid Build Coastguard Worker resultArray->setBConst(*leftArray < *rightArray);
2754*8975f5c5SAndroid Build Coastguard Worker break;
2755*8975f5c5SAndroid Build Coastguard Worker
2756*8975f5c5SAndroid Build Coastguard Worker case EOpGreaterThan:
2757*8975f5c5SAndroid Build Coastguard Worker ASSERT(objectSize == 1);
2758*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[1];
2759*8975f5c5SAndroid Build Coastguard Worker resultArray->setBConst(*leftArray > *rightArray);
2760*8975f5c5SAndroid Build Coastguard Worker break;
2761*8975f5c5SAndroid Build Coastguard Worker
2762*8975f5c5SAndroid Build Coastguard Worker case EOpLessThanEqual:
2763*8975f5c5SAndroid Build Coastguard Worker ASSERT(objectSize == 1);
2764*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[1];
2765*8975f5c5SAndroid Build Coastguard Worker resultArray->setBConst(!(*leftArray > *rightArray));
2766*8975f5c5SAndroid Build Coastguard Worker break;
2767*8975f5c5SAndroid Build Coastguard Worker
2768*8975f5c5SAndroid Build Coastguard Worker case EOpGreaterThanEqual:
2769*8975f5c5SAndroid Build Coastguard Worker ASSERT(objectSize == 1);
2770*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[1];
2771*8975f5c5SAndroid Build Coastguard Worker resultArray->setBConst(!(*leftArray < *rightArray));
2772*8975f5c5SAndroid Build Coastguard Worker break;
2773*8975f5c5SAndroid Build Coastguard Worker
2774*8975f5c5SAndroid Build Coastguard Worker case EOpEqual:
2775*8975f5c5SAndroid Build Coastguard Worker case EOpNotEqual:
2776*8975f5c5SAndroid Build Coastguard Worker {
2777*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[1];
2778*8975f5c5SAndroid Build Coastguard Worker bool equal = true;
2779*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2780*8975f5c5SAndroid Build Coastguard Worker {
2781*8975f5c5SAndroid Build Coastguard Worker if (leftArray[i] != rightArray[i])
2782*8975f5c5SAndroid Build Coastguard Worker {
2783*8975f5c5SAndroid Build Coastguard Worker equal = false;
2784*8975f5c5SAndroid Build Coastguard Worker break; // break out of for loop
2785*8975f5c5SAndroid Build Coastguard Worker }
2786*8975f5c5SAndroid Build Coastguard Worker }
2787*8975f5c5SAndroid Build Coastguard Worker if (op == EOpEqual)
2788*8975f5c5SAndroid Build Coastguard Worker {
2789*8975f5c5SAndroid Build Coastguard Worker resultArray->setBConst(equal);
2790*8975f5c5SAndroid Build Coastguard Worker }
2791*8975f5c5SAndroid Build Coastguard Worker else
2792*8975f5c5SAndroid Build Coastguard Worker {
2793*8975f5c5SAndroid Build Coastguard Worker resultArray->setBConst(!equal);
2794*8975f5c5SAndroid Build Coastguard Worker }
2795*8975f5c5SAndroid Build Coastguard Worker }
2796*8975f5c5SAndroid Build Coastguard Worker break;
2797*8975f5c5SAndroid Build Coastguard Worker
2798*8975f5c5SAndroid Build Coastguard Worker default:
2799*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
2800*8975f5c5SAndroid Build Coastguard Worker return nullptr;
2801*8975f5c5SAndroid Build Coastguard Worker }
2802*8975f5c5SAndroid Build Coastguard Worker return resultArray;
2803*8975f5c5SAndroid Build Coastguard Worker }
2804*8975f5c5SAndroid Build Coastguard Worker
2805*8975f5c5SAndroid Build Coastguard Worker // The fold functions do operations on a constant at GLSL compile time, without generating run-time
2806*8975f5c5SAndroid Build Coastguard Worker // code. Returns the constant value to keep using. Nullptr should not be returned.
foldUnaryNonComponentWise(TOperator op)2807*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op)
2808*8975f5c5SAndroid Build Coastguard Worker {
2809*8975f5c5SAndroid Build Coastguard Worker // Do operations where the return type may have a different number of components compared to the
2810*8975f5c5SAndroid Build Coastguard Worker // operand type.
2811*8975f5c5SAndroid Build Coastguard Worker
2812*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *operandArray = getConstantValue();
2813*8975f5c5SAndroid Build Coastguard Worker ASSERT(operandArray);
2814*8975f5c5SAndroid Build Coastguard Worker
2815*8975f5c5SAndroid Build Coastguard Worker size_t objectSize = getType().getObjectSize();
2816*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *resultArray = nullptr;
2817*8975f5c5SAndroid Build Coastguard Worker switch (op)
2818*8975f5c5SAndroid Build Coastguard Worker {
2819*8975f5c5SAndroid Build Coastguard Worker case EOpAny:
2820*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtBool);
2821*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion();
2822*8975f5c5SAndroid Build Coastguard Worker resultArray->setBConst(false);
2823*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2824*8975f5c5SAndroid Build Coastguard Worker {
2825*8975f5c5SAndroid Build Coastguard Worker if (operandArray[i].getBConst())
2826*8975f5c5SAndroid Build Coastguard Worker {
2827*8975f5c5SAndroid Build Coastguard Worker resultArray->setBConst(true);
2828*8975f5c5SAndroid Build Coastguard Worker break;
2829*8975f5c5SAndroid Build Coastguard Worker }
2830*8975f5c5SAndroid Build Coastguard Worker }
2831*8975f5c5SAndroid Build Coastguard Worker break;
2832*8975f5c5SAndroid Build Coastguard Worker
2833*8975f5c5SAndroid Build Coastguard Worker case EOpAll:
2834*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtBool);
2835*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion();
2836*8975f5c5SAndroid Build Coastguard Worker resultArray->setBConst(true);
2837*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
2838*8975f5c5SAndroid Build Coastguard Worker {
2839*8975f5c5SAndroid Build Coastguard Worker if (!operandArray[i].getBConst())
2840*8975f5c5SAndroid Build Coastguard Worker {
2841*8975f5c5SAndroid Build Coastguard Worker resultArray->setBConst(false);
2842*8975f5c5SAndroid Build Coastguard Worker break;
2843*8975f5c5SAndroid Build Coastguard Worker }
2844*8975f5c5SAndroid Build Coastguard Worker }
2845*8975f5c5SAndroid Build Coastguard Worker break;
2846*8975f5c5SAndroid Build Coastguard Worker
2847*8975f5c5SAndroid Build Coastguard Worker case EOpLength:
2848*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
2849*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion();
2850*8975f5c5SAndroid Build Coastguard Worker resultArray->setFConst(VectorLength(operandArray, objectSize));
2851*8975f5c5SAndroid Build Coastguard Worker break;
2852*8975f5c5SAndroid Build Coastguard Worker
2853*8975f5c5SAndroid Build Coastguard Worker case EOpTranspose:
2854*8975f5c5SAndroid Build Coastguard Worker {
2855*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
2856*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[objectSize];
2857*8975f5c5SAndroid Build Coastguard Worker angle::Matrix<float> result =
2858*8975f5c5SAndroid Build Coastguard Worker GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose();
2859*8975f5c5SAndroid Build Coastguard Worker SetUnionArrayFromMatrix(result, resultArray);
2860*8975f5c5SAndroid Build Coastguard Worker break;
2861*8975f5c5SAndroid Build Coastguard Worker }
2862*8975f5c5SAndroid Build Coastguard Worker
2863*8975f5c5SAndroid Build Coastguard Worker case EOpDeterminant:
2864*8975f5c5SAndroid Build Coastguard Worker {
2865*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
2866*8975f5c5SAndroid Build Coastguard Worker const uint8_t size = getType().getNominalSize();
2867*8975f5c5SAndroid Build Coastguard Worker ASSERT(size >= 2 && size <= 4);
2868*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion();
2869*8975f5c5SAndroid Build Coastguard Worker resultArray->setFConst(GetMatrix(operandArray, size).determinant());
2870*8975f5c5SAndroid Build Coastguard Worker break;
2871*8975f5c5SAndroid Build Coastguard Worker }
2872*8975f5c5SAndroid Build Coastguard Worker
2873*8975f5c5SAndroid Build Coastguard Worker case EOpInverse:
2874*8975f5c5SAndroid Build Coastguard Worker {
2875*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
2876*8975f5c5SAndroid Build Coastguard Worker const uint8_t size = getType().getNominalSize();
2877*8975f5c5SAndroid Build Coastguard Worker ASSERT(size >= 2 && size <= 4);
2878*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[objectSize];
2879*8975f5c5SAndroid Build Coastguard Worker angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
2880*8975f5c5SAndroid Build Coastguard Worker SetUnionArrayFromMatrix(result, resultArray);
2881*8975f5c5SAndroid Build Coastguard Worker break;
2882*8975f5c5SAndroid Build Coastguard Worker }
2883*8975f5c5SAndroid Build Coastguard Worker
2884*8975f5c5SAndroid Build Coastguard Worker case EOpPackSnorm2x16:
2885*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
2886*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getNominalSize() == 2);
2887*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion();
2888*8975f5c5SAndroid Build Coastguard Worker resultArray->setUConst(
2889*8975f5c5SAndroid Build Coastguard Worker gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
2890*8975f5c5SAndroid Build Coastguard Worker break;
2891*8975f5c5SAndroid Build Coastguard Worker
2892*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackSnorm2x16:
2893*8975f5c5SAndroid Build Coastguard Worker {
2894*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtUInt);
2895*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[2];
2896*8975f5c5SAndroid Build Coastguard Worker float f1, f2;
2897*8975f5c5SAndroid Build Coastguard Worker gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
2898*8975f5c5SAndroid Build Coastguard Worker resultArray[0].setFConst(f1);
2899*8975f5c5SAndroid Build Coastguard Worker resultArray[1].setFConst(f2);
2900*8975f5c5SAndroid Build Coastguard Worker break;
2901*8975f5c5SAndroid Build Coastguard Worker }
2902*8975f5c5SAndroid Build Coastguard Worker
2903*8975f5c5SAndroid Build Coastguard Worker case EOpPackUnorm2x16:
2904*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
2905*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getNominalSize() == 2);
2906*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion();
2907*8975f5c5SAndroid Build Coastguard Worker resultArray->setUConst(
2908*8975f5c5SAndroid Build Coastguard Worker gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
2909*8975f5c5SAndroid Build Coastguard Worker break;
2910*8975f5c5SAndroid Build Coastguard Worker
2911*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackUnorm2x16:
2912*8975f5c5SAndroid Build Coastguard Worker {
2913*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtUInt);
2914*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[2];
2915*8975f5c5SAndroid Build Coastguard Worker float f1, f2;
2916*8975f5c5SAndroid Build Coastguard Worker gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
2917*8975f5c5SAndroid Build Coastguard Worker resultArray[0].setFConst(f1);
2918*8975f5c5SAndroid Build Coastguard Worker resultArray[1].setFConst(f2);
2919*8975f5c5SAndroid Build Coastguard Worker break;
2920*8975f5c5SAndroid Build Coastguard Worker }
2921*8975f5c5SAndroid Build Coastguard Worker
2922*8975f5c5SAndroid Build Coastguard Worker case EOpPackHalf2x16:
2923*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
2924*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getNominalSize() == 2);
2925*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion();
2926*8975f5c5SAndroid Build Coastguard Worker resultArray->setUConst(
2927*8975f5c5SAndroid Build Coastguard Worker gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
2928*8975f5c5SAndroid Build Coastguard Worker break;
2929*8975f5c5SAndroid Build Coastguard Worker
2930*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackHalf2x16:
2931*8975f5c5SAndroid Build Coastguard Worker {
2932*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtUInt);
2933*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[2];
2934*8975f5c5SAndroid Build Coastguard Worker float f1, f2;
2935*8975f5c5SAndroid Build Coastguard Worker gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2);
2936*8975f5c5SAndroid Build Coastguard Worker resultArray[0].setFConst(f1);
2937*8975f5c5SAndroid Build Coastguard Worker resultArray[1].setFConst(f2);
2938*8975f5c5SAndroid Build Coastguard Worker break;
2939*8975f5c5SAndroid Build Coastguard Worker }
2940*8975f5c5SAndroid Build Coastguard Worker
2941*8975f5c5SAndroid Build Coastguard Worker case EOpPackUnorm4x8:
2942*8975f5c5SAndroid Build Coastguard Worker {
2943*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
2944*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion();
2945*8975f5c5SAndroid Build Coastguard Worker resultArray->setUConst(
2946*8975f5c5SAndroid Build Coastguard Worker gl::PackUnorm4x8(operandArray[0].getFConst(), operandArray[1].getFConst(),
2947*8975f5c5SAndroid Build Coastguard Worker operandArray[2].getFConst(), operandArray[3].getFConst()));
2948*8975f5c5SAndroid Build Coastguard Worker break;
2949*8975f5c5SAndroid Build Coastguard Worker }
2950*8975f5c5SAndroid Build Coastguard Worker case EOpPackSnorm4x8:
2951*8975f5c5SAndroid Build Coastguard Worker {
2952*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
2953*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion();
2954*8975f5c5SAndroid Build Coastguard Worker resultArray->setUConst(
2955*8975f5c5SAndroid Build Coastguard Worker gl::PackSnorm4x8(operandArray[0].getFConst(), operandArray[1].getFConst(),
2956*8975f5c5SAndroid Build Coastguard Worker operandArray[2].getFConst(), operandArray[3].getFConst()));
2957*8975f5c5SAndroid Build Coastguard Worker break;
2958*8975f5c5SAndroid Build Coastguard Worker }
2959*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackUnorm4x8:
2960*8975f5c5SAndroid Build Coastguard Worker {
2961*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtUInt);
2962*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[4];
2963*8975f5c5SAndroid Build Coastguard Worker float f[4];
2964*8975f5c5SAndroid Build Coastguard Worker gl::UnpackUnorm4x8(operandArray[0].getUConst(), f);
2965*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < 4; ++i)
2966*8975f5c5SAndroid Build Coastguard Worker {
2967*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(f[i]);
2968*8975f5c5SAndroid Build Coastguard Worker }
2969*8975f5c5SAndroid Build Coastguard Worker break;
2970*8975f5c5SAndroid Build Coastguard Worker }
2971*8975f5c5SAndroid Build Coastguard Worker case EOpUnpackSnorm4x8:
2972*8975f5c5SAndroid Build Coastguard Worker {
2973*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtUInt);
2974*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[4];
2975*8975f5c5SAndroid Build Coastguard Worker float f[4];
2976*8975f5c5SAndroid Build Coastguard Worker gl::UnpackSnorm4x8(operandArray[0].getUConst(), f);
2977*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < 4; ++i)
2978*8975f5c5SAndroid Build Coastguard Worker {
2979*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(f[i]);
2980*8975f5c5SAndroid Build Coastguard Worker }
2981*8975f5c5SAndroid Build Coastguard Worker break;
2982*8975f5c5SAndroid Build Coastguard Worker }
2983*8975f5c5SAndroid Build Coastguard Worker
2984*8975f5c5SAndroid Build Coastguard Worker default:
2985*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
2986*8975f5c5SAndroid Build Coastguard Worker break;
2987*8975f5c5SAndroid Build Coastguard Worker }
2988*8975f5c5SAndroid Build Coastguard Worker
2989*8975f5c5SAndroid Build Coastguard Worker return resultArray;
2990*8975f5c5SAndroid Build Coastguard Worker }
2991*8975f5c5SAndroid Build Coastguard Worker
foldUnaryComponentWise(TOperator op,const TFunction * function,TDiagnostics * diagnostics)2992*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op,
2993*8975f5c5SAndroid Build Coastguard Worker const TFunction *function,
2994*8975f5c5SAndroid Build Coastguard Worker TDiagnostics *diagnostics)
2995*8975f5c5SAndroid Build Coastguard Worker {
2996*8975f5c5SAndroid Build Coastguard Worker // Do unary operations where each component of the result is computed based on the corresponding
2997*8975f5c5SAndroid Build Coastguard Worker // component of the operand. Also folds normalize, though the divisor in that case takes all
2998*8975f5c5SAndroid Build Coastguard Worker // components into account.
2999*8975f5c5SAndroid Build Coastguard Worker
3000*8975f5c5SAndroid Build Coastguard Worker const TConstantUnion *operandArray = getConstantValue();
3001*8975f5c5SAndroid Build Coastguard Worker ASSERT(operandArray);
3002*8975f5c5SAndroid Build Coastguard Worker
3003*8975f5c5SAndroid Build Coastguard Worker size_t objectSize = getType().getObjectSize();
3004*8975f5c5SAndroid Build Coastguard Worker
3005*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *resultArray = new TConstantUnion[objectSize];
3006*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < objectSize; i++)
3007*8975f5c5SAndroid Build Coastguard Worker {
3008*8975f5c5SAndroid Build Coastguard Worker switch (op)
3009*8975f5c5SAndroid Build Coastguard Worker {
3010*8975f5c5SAndroid Build Coastguard Worker case EOpNegative:
3011*8975f5c5SAndroid Build Coastguard Worker switch (getType().getBasicType())
3012*8975f5c5SAndroid Build Coastguard Worker {
3013*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
3014*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(-operandArray[i].getFConst());
3015*8975f5c5SAndroid Build Coastguard Worker break;
3016*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3017*8975f5c5SAndroid Build Coastguard Worker if (operandArray[i] == std::numeric_limits<int>::min())
3018*8975f5c5SAndroid Build Coastguard Worker {
3019*8975f5c5SAndroid Build Coastguard Worker // The minimum representable integer doesn't have a positive
3020*8975f5c5SAndroid Build Coastguard Worker // counterpart, rather the negation overflows and in ESSL is supposed to
3021*8975f5c5SAndroid Build Coastguard Worker // wrap back to the minimum representable integer. Make sure that we
3022*8975f5c5SAndroid Build Coastguard Worker // don't actually let the negation overflow, which has undefined
3023*8975f5c5SAndroid Build Coastguard Worker // behavior in C++.
3024*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(std::numeric_limits<int>::min());
3025*8975f5c5SAndroid Build Coastguard Worker }
3026*8975f5c5SAndroid Build Coastguard Worker else
3027*8975f5c5SAndroid Build Coastguard Worker {
3028*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(-operandArray[i].getIConst());
3029*8975f5c5SAndroid Build Coastguard Worker }
3030*8975f5c5SAndroid Build Coastguard Worker break;
3031*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
3032*8975f5c5SAndroid Build Coastguard Worker if (operandArray[i] == 0x80000000u)
3033*8975f5c5SAndroid Build Coastguard Worker {
3034*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(0x80000000u);
3035*8975f5c5SAndroid Build Coastguard Worker }
3036*8975f5c5SAndroid Build Coastguard Worker else
3037*8975f5c5SAndroid Build Coastguard Worker {
3038*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(static_cast<unsigned int>(
3039*8975f5c5SAndroid Build Coastguard Worker -static_cast<int>(operandArray[i].getUConst())));
3040*8975f5c5SAndroid Build Coastguard Worker }
3041*8975f5c5SAndroid Build Coastguard Worker break;
3042*8975f5c5SAndroid Build Coastguard Worker default:
3043*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3044*8975f5c5SAndroid Build Coastguard Worker return nullptr;
3045*8975f5c5SAndroid Build Coastguard Worker }
3046*8975f5c5SAndroid Build Coastguard Worker break;
3047*8975f5c5SAndroid Build Coastguard Worker
3048*8975f5c5SAndroid Build Coastguard Worker case EOpPositive:
3049*8975f5c5SAndroid Build Coastguard Worker switch (getType().getBasicType())
3050*8975f5c5SAndroid Build Coastguard Worker {
3051*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
3052*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(operandArray[i].getFConst());
3053*8975f5c5SAndroid Build Coastguard Worker break;
3054*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3055*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(operandArray[i].getIConst());
3056*8975f5c5SAndroid Build Coastguard Worker break;
3057*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
3058*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(static_cast<unsigned int>(
3059*8975f5c5SAndroid Build Coastguard Worker static_cast<int>(operandArray[i].getUConst())));
3060*8975f5c5SAndroid Build Coastguard Worker break;
3061*8975f5c5SAndroid Build Coastguard Worker default:
3062*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3063*8975f5c5SAndroid Build Coastguard Worker return nullptr;
3064*8975f5c5SAndroid Build Coastguard Worker }
3065*8975f5c5SAndroid Build Coastguard Worker break;
3066*8975f5c5SAndroid Build Coastguard Worker
3067*8975f5c5SAndroid Build Coastguard Worker case EOpLogicalNot:
3068*8975f5c5SAndroid Build Coastguard Worker switch (getType().getBasicType())
3069*8975f5c5SAndroid Build Coastguard Worker {
3070*8975f5c5SAndroid Build Coastguard Worker case EbtBool:
3071*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(!operandArray[i].getBConst());
3072*8975f5c5SAndroid Build Coastguard Worker break;
3073*8975f5c5SAndroid Build Coastguard Worker default:
3074*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3075*8975f5c5SAndroid Build Coastguard Worker return nullptr;
3076*8975f5c5SAndroid Build Coastguard Worker }
3077*8975f5c5SAndroid Build Coastguard Worker break;
3078*8975f5c5SAndroid Build Coastguard Worker
3079*8975f5c5SAndroid Build Coastguard Worker case EOpBitwiseNot:
3080*8975f5c5SAndroid Build Coastguard Worker switch (getType().getBasicType())
3081*8975f5c5SAndroid Build Coastguard Worker {
3082*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3083*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(~operandArray[i].getIConst());
3084*8975f5c5SAndroid Build Coastguard Worker break;
3085*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
3086*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(~operandArray[i].getUConst());
3087*8975f5c5SAndroid Build Coastguard Worker break;
3088*8975f5c5SAndroid Build Coastguard Worker default:
3089*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3090*8975f5c5SAndroid Build Coastguard Worker return nullptr;
3091*8975f5c5SAndroid Build Coastguard Worker }
3092*8975f5c5SAndroid Build Coastguard Worker break;
3093*8975f5c5SAndroid Build Coastguard Worker
3094*8975f5c5SAndroid Build Coastguard Worker case EOpRadians:
3095*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
3096*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
3097*8975f5c5SAndroid Build Coastguard Worker break;
3098*8975f5c5SAndroid Build Coastguard Worker
3099*8975f5c5SAndroid Build Coastguard Worker case EOpDegrees:
3100*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
3101*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
3102*8975f5c5SAndroid Build Coastguard Worker break;
3103*8975f5c5SAndroid Build Coastguard Worker
3104*8975f5c5SAndroid Build Coastguard Worker case EOpSin:
3105*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]);
3106*8975f5c5SAndroid Build Coastguard Worker break;
3107*8975f5c5SAndroid Build Coastguard Worker
3108*8975f5c5SAndroid Build Coastguard Worker case EOpCos:
3109*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]);
3110*8975f5c5SAndroid Build Coastguard Worker break;
3111*8975f5c5SAndroid Build Coastguard Worker
3112*8975f5c5SAndroid Build Coastguard Worker case EOpTan:
3113*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]);
3114*8975f5c5SAndroid Build Coastguard Worker break;
3115*8975f5c5SAndroid Build Coastguard Worker
3116*8975f5c5SAndroid Build Coastguard Worker case EOpAsin:
3117*8975f5c5SAndroid Build Coastguard Worker // For asin(x), results are undefined if |x| > 1, we are choosing to set result to
3118*8975f5c5SAndroid Build Coastguard Worker // 0.
3119*8975f5c5SAndroid Build Coastguard Worker if (fabsf(operandArray[i].getFConst()) > 1.0f)
3120*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(),
3121*8975f5c5SAndroid Build Coastguard Worker diagnostics, &resultArray[i]);
3122*8975f5c5SAndroid Build Coastguard Worker else
3123*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]);
3124*8975f5c5SAndroid Build Coastguard Worker break;
3125*8975f5c5SAndroid Build Coastguard Worker
3126*8975f5c5SAndroid Build Coastguard Worker case EOpAcos:
3127*8975f5c5SAndroid Build Coastguard Worker // For acos(x), results are undefined if |x| > 1, we are choosing to set result to
3128*8975f5c5SAndroid Build Coastguard Worker // 0.
3129*8975f5c5SAndroid Build Coastguard Worker if (fabsf(operandArray[i].getFConst()) > 1.0f)
3130*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(),
3131*8975f5c5SAndroid Build Coastguard Worker diagnostics, &resultArray[i]);
3132*8975f5c5SAndroid Build Coastguard Worker else
3133*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]);
3134*8975f5c5SAndroid Build Coastguard Worker break;
3135*8975f5c5SAndroid Build Coastguard Worker
3136*8975f5c5SAndroid Build Coastguard Worker case EOpAtan:
3137*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]);
3138*8975f5c5SAndroid Build Coastguard Worker break;
3139*8975f5c5SAndroid Build Coastguard Worker
3140*8975f5c5SAndroid Build Coastguard Worker case EOpSinh:
3141*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]);
3142*8975f5c5SAndroid Build Coastguard Worker break;
3143*8975f5c5SAndroid Build Coastguard Worker
3144*8975f5c5SAndroid Build Coastguard Worker case EOpCosh:
3145*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]);
3146*8975f5c5SAndroid Build Coastguard Worker break;
3147*8975f5c5SAndroid Build Coastguard Worker
3148*8975f5c5SAndroid Build Coastguard Worker case EOpTanh:
3149*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]);
3150*8975f5c5SAndroid Build Coastguard Worker break;
3151*8975f5c5SAndroid Build Coastguard Worker
3152*8975f5c5SAndroid Build Coastguard Worker case EOpAsinh:
3153*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]);
3154*8975f5c5SAndroid Build Coastguard Worker break;
3155*8975f5c5SAndroid Build Coastguard Worker
3156*8975f5c5SAndroid Build Coastguard Worker case EOpAcosh:
3157*8975f5c5SAndroid Build Coastguard Worker // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
3158*8975f5c5SAndroid Build Coastguard Worker if (operandArray[i].getFConst() < 1.0f)
3159*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(),
3160*8975f5c5SAndroid Build Coastguard Worker diagnostics, &resultArray[i]);
3161*8975f5c5SAndroid Build Coastguard Worker else
3162*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]);
3163*8975f5c5SAndroid Build Coastguard Worker break;
3164*8975f5c5SAndroid Build Coastguard Worker
3165*8975f5c5SAndroid Build Coastguard Worker case EOpAtanh:
3166*8975f5c5SAndroid Build Coastguard Worker // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to
3167*8975f5c5SAndroid Build Coastguard Worker // 0.
3168*8975f5c5SAndroid Build Coastguard Worker if (fabsf(operandArray[i].getFConst()) >= 1.0f)
3169*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(),
3170*8975f5c5SAndroid Build Coastguard Worker diagnostics, &resultArray[i]);
3171*8975f5c5SAndroid Build Coastguard Worker else
3172*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]);
3173*8975f5c5SAndroid Build Coastguard Worker break;
3174*8975f5c5SAndroid Build Coastguard Worker
3175*8975f5c5SAndroid Build Coastguard Worker case EOpAbs:
3176*8975f5c5SAndroid Build Coastguard Worker switch (getType().getBasicType())
3177*8975f5c5SAndroid Build Coastguard Worker {
3178*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
3179*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
3180*8975f5c5SAndroid Build Coastguard Worker break;
3181*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3182*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(abs(operandArray[i].getIConst()));
3183*8975f5c5SAndroid Build Coastguard Worker break;
3184*8975f5c5SAndroid Build Coastguard Worker default:
3185*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3186*8975f5c5SAndroid Build Coastguard Worker return nullptr;
3187*8975f5c5SAndroid Build Coastguard Worker }
3188*8975f5c5SAndroid Build Coastguard Worker break;
3189*8975f5c5SAndroid Build Coastguard Worker
3190*8975f5c5SAndroid Build Coastguard Worker case EOpSign:
3191*8975f5c5SAndroid Build Coastguard Worker switch (getType().getBasicType())
3192*8975f5c5SAndroid Build Coastguard Worker {
3193*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
3194*8975f5c5SAndroid Build Coastguard Worker {
3195*8975f5c5SAndroid Build Coastguard Worker float fConst = operandArray[i].getFConst();
3196*8975f5c5SAndroid Build Coastguard Worker float fResult = 0.0f;
3197*8975f5c5SAndroid Build Coastguard Worker if (fConst > 0.0f)
3198*8975f5c5SAndroid Build Coastguard Worker fResult = 1.0f;
3199*8975f5c5SAndroid Build Coastguard Worker else if (fConst < 0.0f)
3200*8975f5c5SAndroid Build Coastguard Worker fResult = -1.0f;
3201*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(fResult);
3202*8975f5c5SAndroid Build Coastguard Worker break;
3203*8975f5c5SAndroid Build Coastguard Worker }
3204*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3205*8975f5c5SAndroid Build Coastguard Worker {
3206*8975f5c5SAndroid Build Coastguard Worker int iConst = operandArray[i].getIConst();
3207*8975f5c5SAndroid Build Coastguard Worker int iResult = 0;
3208*8975f5c5SAndroid Build Coastguard Worker if (iConst > 0)
3209*8975f5c5SAndroid Build Coastguard Worker iResult = 1;
3210*8975f5c5SAndroid Build Coastguard Worker else if (iConst < 0)
3211*8975f5c5SAndroid Build Coastguard Worker iResult = -1;
3212*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(iResult);
3213*8975f5c5SAndroid Build Coastguard Worker break;
3214*8975f5c5SAndroid Build Coastguard Worker }
3215*8975f5c5SAndroid Build Coastguard Worker default:
3216*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3217*8975f5c5SAndroid Build Coastguard Worker return nullptr;
3218*8975f5c5SAndroid Build Coastguard Worker }
3219*8975f5c5SAndroid Build Coastguard Worker break;
3220*8975f5c5SAndroid Build Coastguard Worker
3221*8975f5c5SAndroid Build Coastguard Worker case EOpFloor:
3222*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]);
3223*8975f5c5SAndroid Build Coastguard Worker break;
3224*8975f5c5SAndroid Build Coastguard Worker
3225*8975f5c5SAndroid Build Coastguard Worker case EOpTrunc:
3226*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]);
3227*8975f5c5SAndroid Build Coastguard Worker break;
3228*8975f5c5SAndroid Build Coastguard Worker
3229*8975f5c5SAndroid Build Coastguard Worker case EOpRound:
3230*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]);
3231*8975f5c5SAndroid Build Coastguard Worker break;
3232*8975f5c5SAndroid Build Coastguard Worker
3233*8975f5c5SAndroid Build Coastguard Worker case EOpRoundEven:
3234*8975f5c5SAndroid Build Coastguard Worker {
3235*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
3236*8975f5c5SAndroid Build Coastguard Worker float x = operandArray[i].getFConst();
3237*8975f5c5SAndroid Build Coastguard Worker float result;
3238*8975f5c5SAndroid Build Coastguard Worker float fractPart = modff(x, &result);
3239*8975f5c5SAndroid Build Coastguard Worker if (fabsf(fractPart) == 0.5f)
3240*8975f5c5SAndroid Build Coastguard Worker result = 2.0f * roundf(x / 2.0f);
3241*8975f5c5SAndroid Build Coastguard Worker else
3242*8975f5c5SAndroid Build Coastguard Worker result = roundf(x);
3243*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(result);
3244*8975f5c5SAndroid Build Coastguard Worker break;
3245*8975f5c5SAndroid Build Coastguard Worker }
3246*8975f5c5SAndroid Build Coastguard Worker
3247*8975f5c5SAndroid Build Coastguard Worker case EOpCeil:
3248*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]);
3249*8975f5c5SAndroid Build Coastguard Worker break;
3250*8975f5c5SAndroid Build Coastguard Worker
3251*8975f5c5SAndroid Build Coastguard Worker case EOpFract:
3252*8975f5c5SAndroid Build Coastguard Worker {
3253*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
3254*8975f5c5SAndroid Build Coastguard Worker float x = operandArray[i].getFConst();
3255*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(x - floorf(x));
3256*8975f5c5SAndroid Build Coastguard Worker break;
3257*8975f5c5SAndroid Build Coastguard Worker }
3258*8975f5c5SAndroid Build Coastguard Worker
3259*8975f5c5SAndroid Build Coastguard Worker case EOpIsnan:
3260*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
3261*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(gl::isNaN(operandArray[i].getFConst()));
3262*8975f5c5SAndroid Build Coastguard Worker break;
3263*8975f5c5SAndroid Build Coastguard Worker
3264*8975f5c5SAndroid Build Coastguard Worker case EOpIsinf:
3265*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
3266*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(gl::isInf(operandArray[i].getFConst()));
3267*8975f5c5SAndroid Build Coastguard Worker break;
3268*8975f5c5SAndroid Build Coastguard Worker
3269*8975f5c5SAndroid Build Coastguard Worker case EOpFloatBitsToInt:
3270*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
3271*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(gl::bitCast<int32_t>(operandArray[i].getFConst()));
3272*8975f5c5SAndroid Build Coastguard Worker break;
3273*8975f5c5SAndroid Build Coastguard Worker
3274*8975f5c5SAndroid Build Coastguard Worker case EOpFloatBitsToUint:
3275*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
3276*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(gl::bitCast<uint32_t>(operandArray[i].getFConst()));
3277*8975f5c5SAndroid Build Coastguard Worker break;
3278*8975f5c5SAndroid Build Coastguard Worker
3279*8975f5c5SAndroid Build Coastguard Worker case EOpIntBitsToFloat:
3280*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtInt);
3281*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(gl::bitCast<float>(operandArray[i].getIConst()));
3282*8975f5c5SAndroid Build Coastguard Worker break;
3283*8975f5c5SAndroid Build Coastguard Worker
3284*8975f5c5SAndroid Build Coastguard Worker case EOpUintBitsToFloat:
3285*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtUInt);
3286*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(gl::bitCast<float>(operandArray[i].getUConst()));
3287*8975f5c5SAndroid Build Coastguard Worker break;
3288*8975f5c5SAndroid Build Coastguard Worker
3289*8975f5c5SAndroid Build Coastguard Worker case EOpExp:
3290*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]);
3291*8975f5c5SAndroid Build Coastguard Worker break;
3292*8975f5c5SAndroid Build Coastguard Worker
3293*8975f5c5SAndroid Build Coastguard Worker case EOpLog:
3294*8975f5c5SAndroid Build Coastguard Worker // For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
3295*8975f5c5SAndroid Build Coastguard Worker if (operandArray[i].getFConst() <= 0.0f)
3296*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(),
3297*8975f5c5SAndroid Build Coastguard Worker diagnostics, &resultArray[i]);
3298*8975f5c5SAndroid Build Coastguard Worker else
3299*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
3300*8975f5c5SAndroid Build Coastguard Worker break;
3301*8975f5c5SAndroid Build Coastguard Worker
3302*8975f5c5SAndroid Build Coastguard Worker case EOpExp2:
3303*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]);
3304*8975f5c5SAndroid Build Coastguard Worker break;
3305*8975f5c5SAndroid Build Coastguard Worker
3306*8975f5c5SAndroid Build Coastguard Worker case EOpLog2:
3307*8975f5c5SAndroid Build Coastguard Worker // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
3308*8975f5c5SAndroid Build Coastguard Worker // And log2f is not available on some plarforms like old android, so just using
3309*8975f5c5SAndroid Build Coastguard Worker // log(x)/log(2) here.
3310*8975f5c5SAndroid Build Coastguard Worker if (operandArray[i].getFConst() <= 0.0f)
3311*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(),
3312*8975f5c5SAndroid Build Coastguard Worker diagnostics, &resultArray[i]);
3313*8975f5c5SAndroid Build Coastguard Worker else
3314*8975f5c5SAndroid Build Coastguard Worker {
3315*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
3316*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
3317*8975f5c5SAndroid Build Coastguard Worker }
3318*8975f5c5SAndroid Build Coastguard Worker break;
3319*8975f5c5SAndroid Build Coastguard Worker
3320*8975f5c5SAndroid Build Coastguard Worker case EOpSqrt:
3321*8975f5c5SAndroid Build Coastguard Worker // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
3322*8975f5c5SAndroid Build Coastguard Worker if (operandArray[i].getFConst() < 0.0f)
3323*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(),
3324*8975f5c5SAndroid Build Coastguard Worker diagnostics, &resultArray[i]);
3325*8975f5c5SAndroid Build Coastguard Worker else
3326*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
3327*8975f5c5SAndroid Build Coastguard Worker break;
3328*8975f5c5SAndroid Build Coastguard Worker
3329*8975f5c5SAndroid Build Coastguard Worker case EOpInversesqrt:
3330*8975f5c5SAndroid Build Coastguard Worker // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
3331*8975f5c5SAndroid Build Coastguard Worker // so getting the square root first using builtin function sqrt() and then taking
3332*8975f5c5SAndroid Build Coastguard Worker // its inverse.
3333*8975f5c5SAndroid Build Coastguard Worker // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set
3334*8975f5c5SAndroid Build Coastguard Worker // result to 0.
3335*8975f5c5SAndroid Build Coastguard Worker if (operandArray[i].getFConst() <= 0.0f)
3336*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(),
3337*8975f5c5SAndroid Build Coastguard Worker diagnostics, &resultArray[i]);
3338*8975f5c5SAndroid Build Coastguard Worker else
3339*8975f5c5SAndroid Build Coastguard Worker {
3340*8975f5c5SAndroid Build Coastguard Worker foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
3341*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
3342*8975f5c5SAndroid Build Coastguard Worker }
3343*8975f5c5SAndroid Build Coastguard Worker break;
3344*8975f5c5SAndroid Build Coastguard Worker
3345*8975f5c5SAndroid Build Coastguard Worker case EOpNotComponentWise:
3346*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtBool);
3347*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(!operandArray[i].getBConst());
3348*8975f5c5SAndroid Build Coastguard Worker break;
3349*8975f5c5SAndroid Build Coastguard Worker
3350*8975f5c5SAndroid Build Coastguard Worker case EOpNormalize:
3351*8975f5c5SAndroid Build Coastguard Worker {
3352*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
3353*8975f5c5SAndroid Build Coastguard Worker float x = operandArray[i].getFConst();
3354*8975f5c5SAndroid Build Coastguard Worker float length = VectorLength(operandArray, objectSize);
3355*8975f5c5SAndroid Build Coastguard Worker if (length != 0.0f)
3356*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(x / length);
3357*8975f5c5SAndroid Build Coastguard Worker else
3358*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(),
3359*8975f5c5SAndroid Build Coastguard Worker diagnostics, &resultArray[i]);
3360*8975f5c5SAndroid Build Coastguard Worker break;
3361*8975f5c5SAndroid Build Coastguard Worker }
3362*8975f5c5SAndroid Build Coastguard Worker case EOpBitfieldReverse:
3363*8975f5c5SAndroid Build Coastguard Worker {
3364*8975f5c5SAndroid Build Coastguard Worker uint32_t value;
3365*8975f5c5SAndroid Build Coastguard Worker if (getType().getBasicType() == EbtInt)
3366*8975f5c5SAndroid Build Coastguard Worker {
3367*8975f5c5SAndroid Build Coastguard Worker value = static_cast<uint32_t>(operandArray[i].getIConst());
3368*8975f5c5SAndroid Build Coastguard Worker }
3369*8975f5c5SAndroid Build Coastguard Worker else
3370*8975f5c5SAndroid Build Coastguard Worker {
3371*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtUInt);
3372*8975f5c5SAndroid Build Coastguard Worker value = operandArray[i].getUConst();
3373*8975f5c5SAndroid Build Coastguard Worker }
3374*8975f5c5SAndroid Build Coastguard Worker uint32_t result = gl::BitfieldReverse(value);
3375*8975f5c5SAndroid Build Coastguard Worker if (getType().getBasicType() == EbtInt)
3376*8975f5c5SAndroid Build Coastguard Worker {
3377*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(static_cast<int32_t>(result));
3378*8975f5c5SAndroid Build Coastguard Worker }
3379*8975f5c5SAndroid Build Coastguard Worker else
3380*8975f5c5SAndroid Build Coastguard Worker {
3381*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(result);
3382*8975f5c5SAndroid Build Coastguard Worker }
3383*8975f5c5SAndroid Build Coastguard Worker break;
3384*8975f5c5SAndroid Build Coastguard Worker }
3385*8975f5c5SAndroid Build Coastguard Worker case EOpBitCount:
3386*8975f5c5SAndroid Build Coastguard Worker {
3387*8975f5c5SAndroid Build Coastguard Worker uint32_t value;
3388*8975f5c5SAndroid Build Coastguard Worker if (getType().getBasicType() == EbtInt)
3389*8975f5c5SAndroid Build Coastguard Worker {
3390*8975f5c5SAndroid Build Coastguard Worker value = static_cast<uint32_t>(operandArray[i].getIConst());
3391*8975f5c5SAndroid Build Coastguard Worker }
3392*8975f5c5SAndroid Build Coastguard Worker else
3393*8975f5c5SAndroid Build Coastguard Worker {
3394*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtUInt);
3395*8975f5c5SAndroid Build Coastguard Worker value = operandArray[i].getUConst();
3396*8975f5c5SAndroid Build Coastguard Worker }
3397*8975f5c5SAndroid Build Coastguard Worker int result = gl::BitCount(value);
3398*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(result);
3399*8975f5c5SAndroid Build Coastguard Worker break;
3400*8975f5c5SAndroid Build Coastguard Worker }
3401*8975f5c5SAndroid Build Coastguard Worker case EOpFindLSB:
3402*8975f5c5SAndroid Build Coastguard Worker {
3403*8975f5c5SAndroid Build Coastguard Worker uint32_t value;
3404*8975f5c5SAndroid Build Coastguard Worker if (getType().getBasicType() == EbtInt)
3405*8975f5c5SAndroid Build Coastguard Worker {
3406*8975f5c5SAndroid Build Coastguard Worker value = static_cast<uint32_t>(operandArray[i].getIConst());
3407*8975f5c5SAndroid Build Coastguard Worker }
3408*8975f5c5SAndroid Build Coastguard Worker else
3409*8975f5c5SAndroid Build Coastguard Worker {
3410*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtUInt);
3411*8975f5c5SAndroid Build Coastguard Worker value = operandArray[i].getUConst();
3412*8975f5c5SAndroid Build Coastguard Worker }
3413*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(gl::FindLSB(value));
3414*8975f5c5SAndroid Build Coastguard Worker break;
3415*8975f5c5SAndroid Build Coastguard Worker }
3416*8975f5c5SAndroid Build Coastguard Worker case EOpFindMSB:
3417*8975f5c5SAndroid Build Coastguard Worker {
3418*8975f5c5SAndroid Build Coastguard Worker uint32_t value;
3419*8975f5c5SAndroid Build Coastguard Worker if (getType().getBasicType() == EbtInt)
3420*8975f5c5SAndroid Build Coastguard Worker {
3421*8975f5c5SAndroid Build Coastguard Worker int intValue = operandArray[i].getIConst();
3422*8975f5c5SAndroid Build Coastguard Worker value = static_cast<uint32_t>(intValue);
3423*8975f5c5SAndroid Build Coastguard Worker if (intValue < 0)
3424*8975f5c5SAndroid Build Coastguard Worker {
3425*8975f5c5SAndroid Build Coastguard Worker // Look for zero instead of one in value. This also handles the intValue ==
3426*8975f5c5SAndroid Build Coastguard Worker // -1 special case, where the return value needs to be -1.
3427*8975f5c5SAndroid Build Coastguard Worker value = ~value;
3428*8975f5c5SAndroid Build Coastguard Worker }
3429*8975f5c5SAndroid Build Coastguard Worker }
3430*8975f5c5SAndroid Build Coastguard Worker else
3431*8975f5c5SAndroid Build Coastguard Worker {
3432*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtUInt);
3433*8975f5c5SAndroid Build Coastguard Worker value = operandArray[i].getUConst();
3434*8975f5c5SAndroid Build Coastguard Worker }
3435*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(gl::FindMSB(value));
3436*8975f5c5SAndroid Build Coastguard Worker break;
3437*8975f5c5SAndroid Build Coastguard Worker }
3438*8975f5c5SAndroid Build Coastguard Worker
3439*8975f5c5SAndroid Build Coastguard Worker default:
3440*8975f5c5SAndroid Build Coastguard Worker return nullptr;
3441*8975f5c5SAndroid Build Coastguard Worker }
3442*8975f5c5SAndroid Build Coastguard Worker }
3443*8975f5c5SAndroid Build Coastguard Worker
3444*8975f5c5SAndroid Build Coastguard Worker return resultArray;
3445*8975f5c5SAndroid Build Coastguard Worker }
3446*8975f5c5SAndroid Build Coastguard Worker
foldFloatTypeUnary(const TConstantUnion & parameter,FloatTypeUnaryFunc builtinFunc,TConstantUnion * result) const3447*8975f5c5SAndroid Build Coastguard Worker void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion ¶meter,
3448*8975f5c5SAndroid Build Coastguard Worker FloatTypeUnaryFunc builtinFunc,
3449*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *result) const
3450*8975f5c5SAndroid Build Coastguard Worker {
3451*8975f5c5SAndroid Build Coastguard Worker ASSERT(builtinFunc);
3452*8975f5c5SAndroid Build Coastguard Worker
3453*8975f5c5SAndroid Build Coastguard Worker ASSERT(getType().getBasicType() == EbtFloat);
3454*8975f5c5SAndroid Build Coastguard Worker result->setFConst(builtinFunc(parameter.getFConst()));
3455*8975f5c5SAndroid Build Coastguard Worker }
3456*8975f5c5SAndroid Build Coastguard Worker
propagatePrecision(TPrecision precision)3457*8975f5c5SAndroid Build Coastguard Worker void TIntermConstantUnion::propagatePrecision(TPrecision precision)
3458*8975f5c5SAndroid Build Coastguard Worker {
3459*8975f5c5SAndroid Build Coastguard Worker mType.setPrecision(precision);
3460*8975f5c5SAndroid Build Coastguard Worker }
3461*8975f5c5SAndroid Build Coastguard Worker
3462*8975f5c5SAndroid Build Coastguard Worker // static
FoldAggregateBuiltIn(TIntermAggregate * aggregate,TDiagnostics * diagnostics)3463*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate,
3464*8975f5c5SAndroid Build Coastguard Worker TDiagnostics *diagnostics)
3465*8975f5c5SAndroid Build Coastguard Worker {
3466*8975f5c5SAndroid Build Coastguard Worker const TOperator op = aggregate->getOp();
3467*8975f5c5SAndroid Build Coastguard Worker const TFunction *function = aggregate->getFunction();
3468*8975f5c5SAndroid Build Coastguard Worker TIntermSequence *arguments = aggregate->getSequence();
3469*8975f5c5SAndroid Build Coastguard Worker unsigned int argsCount = static_cast<unsigned int>(arguments->size());
3470*8975f5c5SAndroid Build Coastguard Worker std::vector<const TConstantUnion *> unionArrays(argsCount);
3471*8975f5c5SAndroid Build Coastguard Worker std::vector<size_t> objectSizes(argsCount);
3472*8975f5c5SAndroid Build Coastguard Worker size_t maxObjectSize = 0;
3473*8975f5c5SAndroid Build Coastguard Worker TBasicType basicType = EbtVoid;
3474*8975f5c5SAndroid Build Coastguard Worker TSourceLoc loc;
3475*8975f5c5SAndroid Build Coastguard Worker for (unsigned int i = 0; i < argsCount; i++)
3476*8975f5c5SAndroid Build Coastguard Worker {
3477*8975f5c5SAndroid Build Coastguard Worker TIntermConstantUnion *argConstant = (*arguments)[i]->getAsConstantUnion();
3478*8975f5c5SAndroid Build Coastguard Worker ASSERT(argConstant != nullptr); // Should be checked already.
3479*8975f5c5SAndroid Build Coastguard Worker
3480*8975f5c5SAndroid Build Coastguard Worker if (i == 0)
3481*8975f5c5SAndroid Build Coastguard Worker {
3482*8975f5c5SAndroid Build Coastguard Worker basicType = argConstant->getType().getBasicType();
3483*8975f5c5SAndroid Build Coastguard Worker loc = argConstant->getLine();
3484*8975f5c5SAndroid Build Coastguard Worker }
3485*8975f5c5SAndroid Build Coastguard Worker unionArrays[i] = argConstant->getConstantValue();
3486*8975f5c5SAndroid Build Coastguard Worker objectSizes[i] = argConstant->getType().getObjectSize();
3487*8975f5c5SAndroid Build Coastguard Worker if (objectSizes[i] > maxObjectSize)
3488*8975f5c5SAndroid Build Coastguard Worker maxObjectSize = objectSizes[i];
3489*8975f5c5SAndroid Build Coastguard Worker }
3490*8975f5c5SAndroid Build Coastguard Worker
3491*8975f5c5SAndroid Build Coastguard Worker if (!(*arguments)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct)
3492*8975f5c5SAndroid Build Coastguard Worker {
3493*8975f5c5SAndroid Build Coastguard Worker for (unsigned int i = 0; i < argsCount; i++)
3494*8975f5c5SAndroid Build Coastguard Worker if (objectSizes[i] != maxObjectSize)
3495*8975f5c5SAndroid Build Coastguard Worker unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize);
3496*8975f5c5SAndroid Build Coastguard Worker }
3497*8975f5c5SAndroid Build Coastguard Worker
3498*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *resultArray = nullptr;
3499*8975f5c5SAndroid Build Coastguard Worker
3500*8975f5c5SAndroid Build Coastguard Worker switch (op)
3501*8975f5c5SAndroid Build Coastguard Worker {
3502*8975f5c5SAndroid Build Coastguard Worker case EOpAtan:
3503*8975f5c5SAndroid Build Coastguard Worker {
3504*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat);
3505*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3506*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3507*8975f5c5SAndroid Build Coastguard Worker {
3508*8975f5c5SAndroid Build Coastguard Worker float y = unionArrays[0][i].getFConst();
3509*8975f5c5SAndroid Build Coastguard Worker float x = unionArrays[1][i].getFConst();
3510*8975f5c5SAndroid Build Coastguard Worker // Results are undefined if x and y are both 0.
3511*8975f5c5SAndroid Build Coastguard Worker if (x == 0.0f && y == 0.0f)
3512*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(loc, function, basicType, diagnostics,
3513*8975f5c5SAndroid Build Coastguard Worker &resultArray[i]);
3514*8975f5c5SAndroid Build Coastguard Worker else
3515*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(atan2f(y, x));
3516*8975f5c5SAndroid Build Coastguard Worker }
3517*8975f5c5SAndroid Build Coastguard Worker break;
3518*8975f5c5SAndroid Build Coastguard Worker }
3519*8975f5c5SAndroid Build Coastguard Worker
3520*8975f5c5SAndroid Build Coastguard Worker case EOpPow:
3521*8975f5c5SAndroid Build Coastguard Worker {
3522*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat);
3523*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3524*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3525*8975f5c5SAndroid Build Coastguard Worker {
3526*8975f5c5SAndroid Build Coastguard Worker float x = unionArrays[0][i].getFConst();
3527*8975f5c5SAndroid Build Coastguard Worker float y = unionArrays[1][i].getFConst();
3528*8975f5c5SAndroid Build Coastguard Worker // Results are undefined if x < 0.
3529*8975f5c5SAndroid Build Coastguard Worker // Results are undefined if x = 0 and y <= 0.
3530*8975f5c5SAndroid Build Coastguard Worker if (x < 0.0f)
3531*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(loc, function, basicType, diagnostics,
3532*8975f5c5SAndroid Build Coastguard Worker &resultArray[i]);
3533*8975f5c5SAndroid Build Coastguard Worker else if (x == 0.0f && y <= 0.0f)
3534*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(loc, function, basicType, diagnostics,
3535*8975f5c5SAndroid Build Coastguard Worker &resultArray[i]);
3536*8975f5c5SAndroid Build Coastguard Worker else
3537*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(powf(x, y));
3538*8975f5c5SAndroid Build Coastguard Worker }
3539*8975f5c5SAndroid Build Coastguard Worker break;
3540*8975f5c5SAndroid Build Coastguard Worker }
3541*8975f5c5SAndroid Build Coastguard Worker
3542*8975f5c5SAndroid Build Coastguard Worker case EOpMod:
3543*8975f5c5SAndroid Build Coastguard Worker {
3544*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat);
3545*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3546*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3547*8975f5c5SAndroid Build Coastguard Worker {
3548*8975f5c5SAndroid Build Coastguard Worker float x = unionArrays[0][i].getFConst();
3549*8975f5c5SAndroid Build Coastguard Worker float y = unionArrays[1][i].getFConst();
3550*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(x - y * floorf(x / y));
3551*8975f5c5SAndroid Build Coastguard Worker }
3552*8975f5c5SAndroid Build Coastguard Worker break;
3553*8975f5c5SAndroid Build Coastguard Worker }
3554*8975f5c5SAndroid Build Coastguard Worker
3555*8975f5c5SAndroid Build Coastguard Worker case EOpMin:
3556*8975f5c5SAndroid Build Coastguard Worker {
3557*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3558*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3559*8975f5c5SAndroid Build Coastguard Worker {
3560*8975f5c5SAndroid Build Coastguard Worker switch (basicType)
3561*8975f5c5SAndroid Build Coastguard Worker {
3562*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
3563*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(
3564*8975f5c5SAndroid Build Coastguard Worker std::min(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
3565*8975f5c5SAndroid Build Coastguard Worker break;
3566*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3567*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(
3568*8975f5c5SAndroid Build Coastguard Worker std::min(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
3569*8975f5c5SAndroid Build Coastguard Worker break;
3570*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
3571*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(
3572*8975f5c5SAndroid Build Coastguard Worker std::min(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
3573*8975f5c5SAndroid Build Coastguard Worker break;
3574*8975f5c5SAndroid Build Coastguard Worker default:
3575*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3576*8975f5c5SAndroid Build Coastguard Worker break;
3577*8975f5c5SAndroid Build Coastguard Worker }
3578*8975f5c5SAndroid Build Coastguard Worker }
3579*8975f5c5SAndroid Build Coastguard Worker break;
3580*8975f5c5SAndroid Build Coastguard Worker }
3581*8975f5c5SAndroid Build Coastguard Worker
3582*8975f5c5SAndroid Build Coastguard Worker case EOpMax:
3583*8975f5c5SAndroid Build Coastguard Worker {
3584*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3585*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3586*8975f5c5SAndroid Build Coastguard Worker {
3587*8975f5c5SAndroid Build Coastguard Worker switch (basicType)
3588*8975f5c5SAndroid Build Coastguard Worker {
3589*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
3590*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(
3591*8975f5c5SAndroid Build Coastguard Worker std::max(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
3592*8975f5c5SAndroid Build Coastguard Worker break;
3593*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3594*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(
3595*8975f5c5SAndroid Build Coastguard Worker std::max(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
3596*8975f5c5SAndroid Build Coastguard Worker break;
3597*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
3598*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(
3599*8975f5c5SAndroid Build Coastguard Worker std::max(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
3600*8975f5c5SAndroid Build Coastguard Worker break;
3601*8975f5c5SAndroid Build Coastguard Worker default:
3602*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3603*8975f5c5SAndroid Build Coastguard Worker break;
3604*8975f5c5SAndroid Build Coastguard Worker }
3605*8975f5c5SAndroid Build Coastguard Worker }
3606*8975f5c5SAndroid Build Coastguard Worker break;
3607*8975f5c5SAndroid Build Coastguard Worker }
3608*8975f5c5SAndroid Build Coastguard Worker
3609*8975f5c5SAndroid Build Coastguard Worker case EOpStep:
3610*8975f5c5SAndroid Build Coastguard Worker {
3611*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat);
3612*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3613*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3614*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(
3615*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f : 1.0f);
3616*8975f5c5SAndroid Build Coastguard Worker break;
3617*8975f5c5SAndroid Build Coastguard Worker }
3618*8975f5c5SAndroid Build Coastguard Worker
3619*8975f5c5SAndroid Build Coastguard Worker case EOpLessThanComponentWise:
3620*8975f5c5SAndroid Build Coastguard Worker {
3621*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3622*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3623*8975f5c5SAndroid Build Coastguard Worker {
3624*8975f5c5SAndroid Build Coastguard Worker switch (basicType)
3625*8975f5c5SAndroid Build Coastguard Worker {
3626*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
3627*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getFConst() <
3628*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getFConst());
3629*8975f5c5SAndroid Build Coastguard Worker break;
3630*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3631*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getIConst() <
3632*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getIConst());
3633*8975f5c5SAndroid Build Coastguard Worker break;
3634*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
3635*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getUConst() <
3636*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getUConst());
3637*8975f5c5SAndroid Build Coastguard Worker break;
3638*8975f5c5SAndroid Build Coastguard Worker default:
3639*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3640*8975f5c5SAndroid Build Coastguard Worker break;
3641*8975f5c5SAndroid Build Coastguard Worker }
3642*8975f5c5SAndroid Build Coastguard Worker }
3643*8975f5c5SAndroid Build Coastguard Worker break;
3644*8975f5c5SAndroid Build Coastguard Worker }
3645*8975f5c5SAndroid Build Coastguard Worker
3646*8975f5c5SAndroid Build Coastguard Worker case EOpLessThanEqualComponentWise:
3647*8975f5c5SAndroid Build Coastguard Worker {
3648*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3649*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3650*8975f5c5SAndroid Build Coastguard Worker {
3651*8975f5c5SAndroid Build Coastguard Worker switch (basicType)
3652*8975f5c5SAndroid Build Coastguard Worker {
3653*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
3654*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getFConst() <=
3655*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getFConst());
3656*8975f5c5SAndroid Build Coastguard Worker break;
3657*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3658*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getIConst() <=
3659*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getIConst());
3660*8975f5c5SAndroid Build Coastguard Worker break;
3661*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
3662*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getUConst() <=
3663*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getUConst());
3664*8975f5c5SAndroid Build Coastguard Worker break;
3665*8975f5c5SAndroid Build Coastguard Worker default:
3666*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3667*8975f5c5SAndroid Build Coastguard Worker break;
3668*8975f5c5SAndroid Build Coastguard Worker }
3669*8975f5c5SAndroid Build Coastguard Worker }
3670*8975f5c5SAndroid Build Coastguard Worker break;
3671*8975f5c5SAndroid Build Coastguard Worker }
3672*8975f5c5SAndroid Build Coastguard Worker
3673*8975f5c5SAndroid Build Coastguard Worker case EOpGreaterThanComponentWise:
3674*8975f5c5SAndroid Build Coastguard Worker {
3675*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3676*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3677*8975f5c5SAndroid Build Coastguard Worker {
3678*8975f5c5SAndroid Build Coastguard Worker switch (basicType)
3679*8975f5c5SAndroid Build Coastguard Worker {
3680*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
3681*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getFConst() >
3682*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getFConst());
3683*8975f5c5SAndroid Build Coastguard Worker break;
3684*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3685*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getIConst() >
3686*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getIConst());
3687*8975f5c5SAndroid Build Coastguard Worker break;
3688*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
3689*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getUConst() >
3690*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getUConst());
3691*8975f5c5SAndroid Build Coastguard Worker break;
3692*8975f5c5SAndroid Build Coastguard Worker default:
3693*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3694*8975f5c5SAndroid Build Coastguard Worker break;
3695*8975f5c5SAndroid Build Coastguard Worker }
3696*8975f5c5SAndroid Build Coastguard Worker }
3697*8975f5c5SAndroid Build Coastguard Worker break;
3698*8975f5c5SAndroid Build Coastguard Worker }
3699*8975f5c5SAndroid Build Coastguard Worker case EOpGreaterThanEqualComponentWise:
3700*8975f5c5SAndroid Build Coastguard Worker {
3701*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3702*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3703*8975f5c5SAndroid Build Coastguard Worker {
3704*8975f5c5SAndroid Build Coastguard Worker switch (basicType)
3705*8975f5c5SAndroid Build Coastguard Worker {
3706*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
3707*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getFConst() >=
3708*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getFConst());
3709*8975f5c5SAndroid Build Coastguard Worker break;
3710*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3711*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getIConst() >=
3712*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getIConst());
3713*8975f5c5SAndroid Build Coastguard Worker break;
3714*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
3715*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getUConst() >=
3716*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getUConst());
3717*8975f5c5SAndroid Build Coastguard Worker break;
3718*8975f5c5SAndroid Build Coastguard Worker default:
3719*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3720*8975f5c5SAndroid Build Coastguard Worker break;
3721*8975f5c5SAndroid Build Coastguard Worker }
3722*8975f5c5SAndroid Build Coastguard Worker }
3723*8975f5c5SAndroid Build Coastguard Worker }
3724*8975f5c5SAndroid Build Coastguard Worker break;
3725*8975f5c5SAndroid Build Coastguard Worker
3726*8975f5c5SAndroid Build Coastguard Worker case EOpEqualComponentWise:
3727*8975f5c5SAndroid Build Coastguard Worker {
3728*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3729*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3730*8975f5c5SAndroid Build Coastguard Worker {
3731*8975f5c5SAndroid Build Coastguard Worker switch (basicType)
3732*8975f5c5SAndroid Build Coastguard Worker {
3733*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
3734*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getFConst() ==
3735*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getFConst());
3736*8975f5c5SAndroid Build Coastguard Worker break;
3737*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3738*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getIConst() ==
3739*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getIConst());
3740*8975f5c5SAndroid Build Coastguard Worker break;
3741*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
3742*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getUConst() ==
3743*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getUConst());
3744*8975f5c5SAndroid Build Coastguard Worker break;
3745*8975f5c5SAndroid Build Coastguard Worker case EbtBool:
3746*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getBConst() ==
3747*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getBConst());
3748*8975f5c5SAndroid Build Coastguard Worker break;
3749*8975f5c5SAndroid Build Coastguard Worker default:
3750*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3751*8975f5c5SAndroid Build Coastguard Worker break;
3752*8975f5c5SAndroid Build Coastguard Worker }
3753*8975f5c5SAndroid Build Coastguard Worker }
3754*8975f5c5SAndroid Build Coastguard Worker break;
3755*8975f5c5SAndroid Build Coastguard Worker }
3756*8975f5c5SAndroid Build Coastguard Worker
3757*8975f5c5SAndroid Build Coastguard Worker case EOpNotEqualComponentWise:
3758*8975f5c5SAndroid Build Coastguard Worker {
3759*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3760*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3761*8975f5c5SAndroid Build Coastguard Worker {
3762*8975f5c5SAndroid Build Coastguard Worker switch (basicType)
3763*8975f5c5SAndroid Build Coastguard Worker {
3764*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
3765*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getFConst() !=
3766*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getFConst());
3767*8975f5c5SAndroid Build Coastguard Worker break;
3768*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3769*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getIConst() !=
3770*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getIConst());
3771*8975f5c5SAndroid Build Coastguard Worker break;
3772*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
3773*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getUConst() !=
3774*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getUConst());
3775*8975f5c5SAndroid Build Coastguard Worker break;
3776*8975f5c5SAndroid Build Coastguard Worker case EbtBool:
3777*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(unionArrays[0][i].getBConst() !=
3778*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getBConst());
3779*8975f5c5SAndroid Build Coastguard Worker break;
3780*8975f5c5SAndroid Build Coastguard Worker default:
3781*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3782*8975f5c5SAndroid Build Coastguard Worker break;
3783*8975f5c5SAndroid Build Coastguard Worker }
3784*8975f5c5SAndroid Build Coastguard Worker }
3785*8975f5c5SAndroid Build Coastguard Worker break;
3786*8975f5c5SAndroid Build Coastguard Worker }
3787*8975f5c5SAndroid Build Coastguard Worker
3788*8975f5c5SAndroid Build Coastguard Worker case EOpDistance:
3789*8975f5c5SAndroid Build Coastguard Worker {
3790*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat);
3791*8975f5c5SAndroid Build Coastguard Worker TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize];
3792*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion();
3793*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3794*8975f5c5SAndroid Build Coastguard Worker {
3795*8975f5c5SAndroid Build Coastguard Worker float x = unionArrays[0][i].getFConst();
3796*8975f5c5SAndroid Build Coastguard Worker float y = unionArrays[1][i].getFConst();
3797*8975f5c5SAndroid Build Coastguard Worker distanceArray[i].setFConst(x - y);
3798*8975f5c5SAndroid Build Coastguard Worker }
3799*8975f5c5SAndroid Build Coastguard Worker resultArray->setFConst(VectorLength(distanceArray, maxObjectSize));
3800*8975f5c5SAndroid Build Coastguard Worker break;
3801*8975f5c5SAndroid Build Coastguard Worker }
3802*8975f5c5SAndroid Build Coastguard Worker
3803*8975f5c5SAndroid Build Coastguard Worker case EOpDot:
3804*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat);
3805*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion();
3806*8975f5c5SAndroid Build Coastguard Worker resultArray->setFConst(VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize));
3807*8975f5c5SAndroid Build Coastguard Worker break;
3808*8975f5c5SAndroid Build Coastguard Worker
3809*8975f5c5SAndroid Build Coastguard Worker case EOpCross:
3810*8975f5c5SAndroid Build Coastguard Worker {
3811*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat && maxObjectSize == 3);
3812*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3813*8975f5c5SAndroid Build Coastguard Worker float x0 = unionArrays[0][0].getFConst();
3814*8975f5c5SAndroid Build Coastguard Worker float x1 = unionArrays[0][1].getFConst();
3815*8975f5c5SAndroid Build Coastguard Worker float x2 = unionArrays[0][2].getFConst();
3816*8975f5c5SAndroid Build Coastguard Worker float y0 = unionArrays[1][0].getFConst();
3817*8975f5c5SAndroid Build Coastguard Worker float y1 = unionArrays[1][1].getFConst();
3818*8975f5c5SAndroid Build Coastguard Worker float y2 = unionArrays[1][2].getFConst();
3819*8975f5c5SAndroid Build Coastguard Worker resultArray[0].setFConst(x1 * y2 - y1 * x2);
3820*8975f5c5SAndroid Build Coastguard Worker resultArray[1].setFConst(x2 * y0 - y2 * x0);
3821*8975f5c5SAndroid Build Coastguard Worker resultArray[2].setFConst(x0 * y1 - y0 * x1);
3822*8975f5c5SAndroid Build Coastguard Worker break;
3823*8975f5c5SAndroid Build Coastguard Worker }
3824*8975f5c5SAndroid Build Coastguard Worker
3825*8975f5c5SAndroid Build Coastguard Worker case EOpReflect:
3826*8975f5c5SAndroid Build Coastguard Worker {
3827*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat);
3828*8975f5c5SAndroid Build Coastguard Worker // genType reflect (genType I, genType N) :
3829*8975f5c5SAndroid Build Coastguard Worker // For the incident vector I and surface orientation N, returns the reflection
3830*8975f5c5SAndroid Build Coastguard Worker // direction:
3831*8975f5c5SAndroid Build Coastguard Worker // I - 2 * dot(N, I) * N.
3832*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3833*8975f5c5SAndroid Build Coastguard Worker float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
3834*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3835*8975f5c5SAndroid Build Coastguard Worker {
3836*8975f5c5SAndroid Build Coastguard Worker float result = unionArrays[0][i].getFConst() -
3837*8975f5c5SAndroid Build Coastguard Worker 2.0f * dotProduct * unionArrays[1][i].getFConst();
3838*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(result);
3839*8975f5c5SAndroid Build Coastguard Worker }
3840*8975f5c5SAndroid Build Coastguard Worker break;
3841*8975f5c5SAndroid Build Coastguard Worker }
3842*8975f5c5SAndroid Build Coastguard Worker
3843*8975f5c5SAndroid Build Coastguard Worker case EOpMatrixCompMult:
3844*8975f5c5SAndroid Build Coastguard Worker {
3845*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat && (*arguments)[0]->getAsTyped()->isMatrix() &&
3846*8975f5c5SAndroid Build Coastguard Worker (*arguments)[1]->getAsTyped()->isMatrix());
3847*8975f5c5SAndroid Build Coastguard Worker // Perform component-wise matrix multiplication.
3848*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3849*8975f5c5SAndroid Build Coastguard Worker const uint8_t rows = (*arguments)[0]->getAsTyped()->getRows();
3850*8975f5c5SAndroid Build Coastguard Worker const uint8_t cols = (*arguments)[0]->getAsTyped()->getCols();
3851*8975f5c5SAndroid Build Coastguard Worker angle::Matrix<float> lhs = GetMatrix(unionArrays[0], rows, cols);
3852*8975f5c5SAndroid Build Coastguard Worker angle::Matrix<float> rhs = GetMatrix(unionArrays[1], rows, cols);
3853*8975f5c5SAndroid Build Coastguard Worker angle::Matrix<float> result = lhs.compMult(rhs);
3854*8975f5c5SAndroid Build Coastguard Worker SetUnionArrayFromMatrix(result, resultArray);
3855*8975f5c5SAndroid Build Coastguard Worker break;
3856*8975f5c5SAndroid Build Coastguard Worker }
3857*8975f5c5SAndroid Build Coastguard Worker
3858*8975f5c5SAndroid Build Coastguard Worker case EOpOuterProduct:
3859*8975f5c5SAndroid Build Coastguard Worker {
3860*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat);
3861*8975f5c5SAndroid Build Coastguard Worker size_t numRows = (*arguments)[0]->getAsTyped()->getType().getObjectSize();
3862*8975f5c5SAndroid Build Coastguard Worker size_t numCols = (*arguments)[1]->getAsTyped()->getType().getObjectSize();
3863*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[numRows * numCols];
3864*8975f5c5SAndroid Build Coastguard Worker angle::Matrix<float> result =
3865*8975f5c5SAndroid Build Coastguard Worker GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
3866*8975f5c5SAndroid Build Coastguard Worker .outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols)));
3867*8975f5c5SAndroid Build Coastguard Worker SetUnionArrayFromMatrix(result, resultArray);
3868*8975f5c5SAndroid Build Coastguard Worker break;
3869*8975f5c5SAndroid Build Coastguard Worker }
3870*8975f5c5SAndroid Build Coastguard Worker
3871*8975f5c5SAndroid Build Coastguard Worker case EOpClamp:
3872*8975f5c5SAndroid Build Coastguard Worker {
3873*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3874*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3875*8975f5c5SAndroid Build Coastguard Worker {
3876*8975f5c5SAndroid Build Coastguard Worker switch (basicType)
3877*8975f5c5SAndroid Build Coastguard Worker {
3878*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
3879*8975f5c5SAndroid Build Coastguard Worker {
3880*8975f5c5SAndroid Build Coastguard Worker float x = unionArrays[0][i].getFConst();
3881*8975f5c5SAndroid Build Coastguard Worker float min = unionArrays[1][i].getFConst();
3882*8975f5c5SAndroid Build Coastguard Worker float max = unionArrays[2][i].getFConst();
3883*8975f5c5SAndroid Build Coastguard Worker // Results are undefined if min > max.
3884*8975f5c5SAndroid Build Coastguard Worker if (min > max)
3885*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(loc, function, basicType, diagnostics,
3886*8975f5c5SAndroid Build Coastguard Worker &resultArray[i]);
3887*8975f5c5SAndroid Build Coastguard Worker else
3888*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(gl::clamp(x, min, max));
3889*8975f5c5SAndroid Build Coastguard Worker break;
3890*8975f5c5SAndroid Build Coastguard Worker }
3891*8975f5c5SAndroid Build Coastguard Worker
3892*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3893*8975f5c5SAndroid Build Coastguard Worker {
3894*8975f5c5SAndroid Build Coastguard Worker int x = unionArrays[0][i].getIConst();
3895*8975f5c5SAndroid Build Coastguard Worker int min = unionArrays[1][i].getIConst();
3896*8975f5c5SAndroid Build Coastguard Worker int max = unionArrays[2][i].getIConst();
3897*8975f5c5SAndroid Build Coastguard Worker // Results are undefined if min > max.
3898*8975f5c5SAndroid Build Coastguard Worker if (min > max)
3899*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(loc, function, basicType, diagnostics,
3900*8975f5c5SAndroid Build Coastguard Worker &resultArray[i]);
3901*8975f5c5SAndroid Build Coastguard Worker else
3902*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(gl::clamp(x, min, max));
3903*8975f5c5SAndroid Build Coastguard Worker break;
3904*8975f5c5SAndroid Build Coastguard Worker }
3905*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
3906*8975f5c5SAndroid Build Coastguard Worker {
3907*8975f5c5SAndroid Build Coastguard Worker unsigned int x = unionArrays[0][i].getUConst();
3908*8975f5c5SAndroid Build Coastguard Worker unsigned int min = unionArrays[1][i].getUConst();
3909*8975f5c5SAndroid Build Coastguard Worker unsigned int max = unionArrays[2][i].getUConst();
3910*8975f5c5SAndroid Build Coastguard Worker // Results are undefined if min > max.
3911*8975f5c5SAndroid Build Coastguard Worker if (min > max)
3912*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(loc, function, basicType, diagnostics,
3913*8975f5c5SAndroid Build Coastguard Worker &resultArray[i]);
3914*8975f5c5SAndroid Build Coastguard Worker else
3915*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(gl::clamp(x, min, max));
3916*8975f5c5SAndroid Build Coastguard Worker break;
3917*8975f5c5SAndroid Build Coastguard Worker }
3918*8975f5c5SAndroid Build Coastguard Worker default:
3919*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3920*8975f5c5SAndroid Build Coastguard Worker break;
3921*8975f5c5SAndroid Build Coastguard Worker }
3922*8975f5c5SAndroid Build Coastguard Worker }
3923*8975f5c5SAndroid Build Coastguard Worker break;
3924*8975f5c5SAndroid Build Coastguard Worker }
3925*8975f5c5SAndroid Build Coastguard Worker
3926*8975f5c5SAndroid Build Coastguard Worker case EOpMix:
3927*8975f5c5SAndroid Build Coastguard Worker {
3928*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3929*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3930*8975f5c5SAndroid Build Coastguard Worker {
3931*8975f5c5SAndroid Build Coastguard Worker TBasicType type = (*arguments)[2]->getAsTyped()->getType().getBasicType();
3932*8975f5c5SAndroid Build Coastguard Worker if (type == EbtFloat)
3933*8975f5c5SAndroid Build Coastguard Worker {
3934*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat);
3935*8975f5c5SAndroid Build Coastguard Worker float x = unionArrays[0][i].getFConst();
3936*8975f5c5SAndroid Build Coastguard Worker float y = unionArrays[1][i].getFConst();
3937*8975f5c5SAndroid Build Coastguard Worker
3938*8975f5c5SAndroid Build Coastguard Worker // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
3939*8975f5c5SAndroid Build Coastguard Worker float a = unionArrays[2][i].getFConst();
3940*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(x * (1.0f - a) + y * a);
3941*8975f5c5SAndroid Build Coastguard Worker }
3942*8975f5c5SAndroid Build Coastguard Worker else // 3rd parameter is EbtBool
3943*8975f5c5SAndroid Build Coastguard Worker {
3944*8975f5c5SAndroid Build Coastguard Worker ASSERT(type == EbtBool);
3945*8975f5c5SAndroid Build Coastguard Worker // Selects which vector each returned component comes from.
3946*8975f5c5SAndroid Build Coastguard Worker // For a component of a that is false, the corresponding component of x is
3947*8975f5c5SAndroid Build Coastguard Worker // returned.
3948*8975f5c5SAndroid Build Coastguard Worker // For a component of a that is true, the corresponding component of y is
3949*8975f5c5SAndroid Build Coastguard Worker // returned.
3950*8975f5c5SAndroid Build Coastguard Worker bool a = unionArrays[2][i].getBConst();
3951*8975f5c5SAndroid Build Coastguard Worker switch (basicType)
3952*8975f5c5SAndroid Build Coastguard Worker {
3953*8975f5c5SAndroid Build Coastguard Worker case EbtFloat:
3954*8975f5c5SAndroid Build Coastguard Worker {
3955*8975f5c5SAndroid Build Coastguard Worker float x = unionArrays[0][i].getFConst();
3956*8975f5c5SAndroid Build Coastguard Worker float y = unionArrays[1][i].getFConst();
3957*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(a ? y : x);
3958*8975f5c5SAndroid Build Coastguard Worker }
3959*8975f5c5SAndroid Build Coastguard Worker break;
3960*8975f5c5SAndroid Build Coastguard Worker case EbtInt:
3961*8975f5c5SAndroid Build Coastguard Worker {
3962*8975f5c5SAndroid Build Coastguard Worker int x = unionArrays[0][i].getIConst();
3963*8975f5c5SAndroid Build Coastguard Worker int y = unionArrays[1][i].getIConst();
3964*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(a ? y : x);
3965*8975f5c5SAndroid Build Coastguard Worker }
3966*8975f5c5SAndroid Build Coastguard Worker break;
3967*8975f5c5SAndroid Build Coastguard Worker case EbtUInt:
3968*8975f5c5SAndroid Build Coastguard Worker {
3969*8975f5c5SAndroid Build Coastguard Worker unsigned int x = unionArrays[0][i].getUConst();
3970*8975f5c5SAndroid Build Coastguard Worker unsigned int y = unionArrays[1][i].getUConst();
3971*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(a ? y : x);
3972*8975f5c5SAndroid Build Coastguard Worker }
3973*8975f5c5SAndroid Build Coastguard Worker break;
3974*8975f5c5SAndroid Build Coastguard Worker case EbtBool:
3975*8975f5c5SAndroid Build Coastguard Worker {
3976*8975f5c5SAndroid Build Coastguard Worker bool x = unionArrays[0][i].getBConst();
3977*8975f5c5SAndroid Build Coastguard Worker bool y = unionArrays[1][i].getBConst();
3978*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setBConst(a ? y : x);
3979*8975f5c5SAndroid Build Coastguard Worker }
3980*8975f5c5SAndroid Build Coastguard Worker break;
3981*8975f5c5SAndroid Build Coastguard Worker default:
3982*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3983*8975f5c5SAndroid Build Coastguard Worker break;
3984*8975f5c5SAndroid Build Coastguard Worker }
3985*8975f5c5SAndroid Build Coastguard Worker }
3986*8975f5c5SAndroid Build Coastguard Worker }
3987*8975f5c5SAndroid Build Coastguard Worker break;
3988*8975f5c5SAndroid Build Coastguard Worker }
3989*8975f5c5SAndroid Build Coastguard Worker
3990*8975f5c5SAndroid Build Coastguard Worker case EOpSmoothstep:
3991*8975f5c5SAndroid Build Coastguard Worker {
3992*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat);
3993*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
3994*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
3995*8975f5c5SAndroid Build Coastguard Worker {
3996*8975f5c5SAndroid Build Coastguard Worker float edge0 = unionArrays[0][i].getFConst();
3997*8975f5c5SAndroid Build Coastguard Worker float edge1 = unionArrays[1][i].getFConst();
3998*8975f5c5SAndroid Build Coastguard Worker float x = unionArrays[2][i].getFConst();
3999*8975f5c5SAndroid Build Coastguard Worker // Results are undefined if edge0 >= edge1.
4000*8975f5c5SAndroid Build Coastguard Worker if (edge0 >= edge1)
4001*8975f5c5SAndroid Build Coastguard Worker {
4002*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(loc, function, basicType, diagnostics,
4003*8975f5c5SAndroid Build Coastguard Worker &resultArray[i]);
4004*8975f5c5SAndroid Build Coastguard Worker }
4005*8975f5c5SAndroid Build Coastguard Worker else
4006*8975f5c5SAndroid Build Coastguard Worker {
4007*8975f5c5SAndroid Build Coastguard Worker // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth
4008*8975f5c5SAndroid Build Coastguard Worker // Hermite interpolation between 0 and 1 when edge0 < x < edge1.
4009*8975f5c5SAndroid Build Coastguard Worker float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
4010*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(t * t * (3.0f - 2.0f * t));
4011*8975f5c5SAndroid Build Coastguard Worker }
4012*8975f5c5SAndroid Build Coastguard Worker }
4013*8975f5c5SAndroid Build Coastguard Worker break;
4014*8975f5c5SAndroid Build Coastguard Worker }
4015*8975f5c5SAndroid Build Coastguard Worker
4016*8975f5c5SAndroid Build Coastguard Worker case EOpFma:
4017*8975f5c5SAndroid Build Coastguard Worker {
4018*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat);
4019*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
4020*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
4021*8975f5c5SAndroid Build Coastguard Worker {
4022*8975f5c5SAndroid Build Coastguard Worker float a = unionArrays[0][i].getFConst();
4023*8975f5c5SAndroid Build Coastguard Worker float b = unionArrays[1][i].getFConst();
4024*8975f5c5SAndroid Build Coastguard Worker float c = unionArrays[2][i].getFConst();
4025*8975f5c5SAndroid Build Coastguard Worker
4026*8975f5c5SAndroid Build Coastguard Worker // Returns a * b + c.
4027*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(a * b + c);
4028*8975f5c5SAndroid Build Coastguard Worker }
4029*8975f5c5SAndroid Build Coastguard Worker break;
4030*8975f5c5SAndroid Build Coastguard Worker }
4031*8975f5c5SAndroid Build Coastguard Worker
4032*8975f5c5SAndroid Build Coastguard Worker case EOpLdexp:
4033*8975f5c5SAndroid Build Coastguard Worker {
4034*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
4035*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
4036*8975f5c5SAndroid Build Coastguard Worker {
4037*8975f5c5SAndroid Build Coastguard Worker float x = unionArrays[0][i].getFConst();
4038*8975f5c5SAndroid Build Coastguard Worker int exp = unionArrays[1][i].getIConst();
4039*8975f5c5SAndroid Build Coastguard Worker if (exp > 128)
4040*8975f5c5SAndroid Build Coastguard Worker {
4041*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(loc, function, basicType, diagnostics,
4042*8975f5c5SAndroid Build Coastguard Worker &resultArray[i]);
4043*8975f5c5SAndroid Build Coastguard Worker }
4044*8975f5c5SAndroid Build Coastguard Worker else
4045*8975f5c5SAndroid Build Coastguard Worker {
4046*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(gl::Ldexp(x, exp));
4047*8975f5c5SAndroid Build Coastguard Worker }
4048*8975f5c5SAndroid Build Coastguard Worker }
4049*8975f5c5SAndroid Build Coastguard Worker break;
4050*8975f5c5SAndroid Build Coastguard Worker }
4051*8975f5c5SAndroid Build Coastguard Worker
4052*8975f5c5SAndroid Build Coastguard Worker case EOpFaceforward:
4053*8975f5c5SAndroid Build Coastguard Worker {
4054*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat);
4055*8975f5c5SAndroid Build Coastguard Worker // genType faceforward(genType N, genType I, genType Nref) :
4056*8975f5c5SAndroid Build Coastguard Worker // If dot(Nref, I) < 0 return N, otherwise return -N.
4057*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
4058*8975f5c5SAndroid Build Coastguard Worker float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize);
4059*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
4060*8975f5c5SAndroid Build Coastguard Worker {
4061*8975f5c5SAndroid Build Coastguard Worker if (dotProduct < 0)
4062*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(unionArrays[0][i].getFConst());
4063*8975f5c5SAndroid Build Coastguard Worker else
4064*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(-unionArrays[0][i].getFConst());
4065*8975f5c5SAndroid Build Coastguard Worker }
4066*8975f5c5SAndroid Build Coastguard Worker break;
4067*8975f5c5SAndroid Build Coastguard Worker }
4068*8975f5c5SAndroid Build Coastguard Worker
4069*8975f5c5SAndroid Build Coastguard Worker case EOpRefract:
4070*8975f5c5SAndroid Build Coastguard Worker {
4071*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat);
4072*8975f5c5SAndroid Build Coastguard Worker // genType refract(genType I, genType N, float eta) :
4073*8975f5c5SAndroid Build Coastguard Worker // For the incident vector I and surface normal N, and the ratio of indices of
4074*8975f5c5SAndroid Build Coastguard Worker // refraction eta,
4075*8975f5c5SAndroid Build Coastguard Worker // return the refraction vector. The result is computed by
4076*8975f5c5SAndroid Build Coastguard Worker // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
4077*8975f5c5SAndroid Build Coastguard Worker // if (k < 0.0)
4078*8975f5c5SAndroid Build Coastguard Worker // return genType(0.0)
4079*8975f5c5SAndroid Build Coastguard Worker // else
4080*8975f5c5SAndroid Build Coastguard Worker // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
4081*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
4082*8975f5c5SAndroid Build Coastguard Worker float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
4083*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
4084*8975f5c5SAndroid Build Coastguard Worker {
4085*8975f5c5SAndroid Build Coastguard Worker float eta = unionArrays[2][i].getFConst();
4086*8975f5c5SAndroid Build Coastguard Worker float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct);
4087*8975f5c5SAndroid Build Coastguard Worker if (k < 0.0f)
4088*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(0.0f);
4089*8975f5c5SAndroid Build Coastguard Worker else
4090*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() -
4091*8975f5c5SAndroid Build Coastguard Worker (eta * dotProduct + sqrtf(k)) *
4092*8975f5c5SAndroid Build Coastguard Worker unionArrays[1][i].getFConst());
4093*8975f5c5SAndroid Build Coastguard Worker }
4094*8975f5c5SAndroid Build Coastguard Worker break;
4095*8975f5c5SAndroid Build Coastguard Worker }
4096*8975f5c5SAndroid Build Coastguard Worker case EOpBitfieldExtract:
4097*8975f5c5SAndroid Build Coastguard Worker {
4098*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
4099*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; ++i)
4100*8975f5c5SAndroid Build Coastguard Worker {
4101*8975f5c5SAndroid Build Coastguard Worker int offset = unionArrays[1][0].getIConst();
4102*8975f5c5SAndroid Build Coastguard Worker int bits = unionArrays[2][0].getIConst();
4103*8975f5c5SAndroid Build Coastguard Worker if (bits == 0)
4104*8975f5c5SAndroid Build Coastguard Worker {
4105*8975f5c5SAndroid Build Coastguard Worker if (aggregate->getBasicType() == EbtInt)
4106*8975f5c5SAndroid Build Coastguard Worker {
4107*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(0);
4108*8975f5c5SAndroid Build Coastguard Worker }
4109*8975f5c5SAndroid Build Coastguard Worker else
4110*8975f5c5SAndroid Build Coastguard Worker {
4111*8975f5c5SAndroid Build Coastguard Worker ASSERT(aggregate->getBasicType() == EbtUInt);
4112*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(0);
4113*8975f5c5SAndroid Build Coastguard Worker }
4114*8975f5c5SAndroid Build Coastguard Worker }
4115*8975f5c5SAndroid Build Coastguard Worker else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32)
4116*8975f5c5SAndroid Build Coastguard Worker {
4117*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(loc, function, aggregate->getBasicType(),
4118*8975f5c5SAndroid Build Coastguard Worker diagnostics, &resultArray[i]);
4119*8975f5c5SAndroid Build Coastguard Worker }
4120*8975f5c5SAndroid Build Coastguard Worker else
4121*8975f5c5SAndroid Build Coastguard Worker {
4122*8975f5c5SAndroid Build Coastguard Worker // bits can be 32 here, so we need to avoid bit shift overflow.
4123*8975f5c5SAndroid Build Coastguard Worker uint32_t maskMsb = 1u << (bits - 1);
4124*8975f5c5SAndroid Build Coastguard Worker uint32_t mask = ((maskMsb - 1u) | maskMsb) << offset;
4125*8975f5c5SAndroid Build Coastguard Worker if (aggregate->getBasicType() == EbtInt)
4126*8975f5c5SAndroid Build Coastguard Worker {
4127*8975f5c5SAndroid Build Coastguard Worker uint32_t value = static_cast<uint32_t>(unionArrays[0][i].getIConst());
4128*8975f5c5SAndroid Build Coastguard Worker uint32_t resultUnsigned = (value & mask) >> offset;
4129*8975f5c5SAndroid Build Coastguard Worker if ((resultUnsigned & maskMsb) != 0)
4130*8975f5c5SAndroid Build Coastguard Worker {
4131*8975f5c5SAndroid Build Coastguard Worker // The most significant bits (from bits+1 to the most significant bit)
4132*8975f5c5SAndroid Build Coastguard Worker // should be set to 1.
4133*8975f5c5SAndroid Build Coastguard Worker uint32_t higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;
4134*8975f5c5SAndroid Build Coastguard Worker resultUnsigned |= higherBitsMask;
4135*8975f5c5SAndroid Build Coastguard Worker }
4136*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned));
4137*8975f5c5SAndroid Build Coastguard Worker }
4138*8975f5c5SAndroid Build Coastguard Worker else
4139*8975f5c5SAndroid Build Coastguard Worker {
4140*8975f5c5SAndroid Build Coastguard Worker ASSERT(aggregate->getBasicType() == EbtUInt);
4141*8975f5c5SAndroid Build Coastguard Worker uint32_t value = unionArrays[0][i].getUConst();
4142*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst((value & mask) >> offset);
4143*8975f5c5SAndroid Build Coastguard Worker }
4144*8975f5c5SAndroid Build Coastguard Worker }
4145*8975f5c5SAndroid Build Coastguard Worker }
4146*8975f5c5SAndroid Build Coastguard Worker break;
4147*8975f5c5SAndroid Build Coastguard Worker }
4148*8975f5c5SAndroid Build Coastguard Worker case EOpBitfieldInsert:
4149*8975f5c5SAndroid Build Coastguard Worker {
4150*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
4151*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; ++i)
4152*8975f5c5SAndroid Build Coastguard Worker {
4153*8975f5c5SAndroid Build Coastguard Worker int offset = unionArrays[2][0].getIConst();
4154*8975f5c5SAndroid Build Coastguard Worker int bits = unionArrays[3][0].getIConst();
4155*8975f5c5SAndroid Build Coastguard Worker if (bits == 0)
4156*8975f5c5SAndroid Build Coastguard Worker {
4157*8975f5c5SAndroid Build Coastguard Worker if (aggregate->getBasicType() == EbtInt)
4158*8975f5c5SAndroid Build Coastguard Worker {
4159*8975f5c5SAndroid Build Coastguard Worker int32_t base = unionArrays[0][i].getIConst();
4160*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(base);
4161*8975f5c5SAndroid Build Coastguard Worker }
4162*8975f5c5SAndroid Build Coastguard Worker else
4163*8975f5c5SAndroid Build Coastguard Worker {
4164*8975f5c5SAndroid Build Coastguard Worker ASSERT(aggregate->getBasicType() == EbtUInt);
4165*8975f5c5SAndroid Build Coastguard Worker uint32_t base = unionArrays[0][i].getUConst();
4166*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst(base);
4167*8975f5c5SAndroid Build Coastguard Worker }
4168*8975f5c5SAndroid Build Coastguard Worker }
4169*8975f5c5SAndroid Build Coastguard Worker else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32)
4170*8975f5c5SAndroid Build Coastguard Worker {
4171*8975f5c5SAndroid Build Coastguard Worker UndefinedConstantFoldingError(loc, function, aggregate->getBasicType(),
4172*8975f5c5SAndroid Build Coastguard Worker diagnostics, &resultArray[i]);
4173*8975f5c5SAndroid Build Coastguard Worker }
4174*8975f5c5SAndroid Build Coastguard Worker else
4175*8975f5c5SAndroid Build Coastguard Worker {
4176*8975f5c5SAndroid Build Coastguard Worker // bits can be 32 here, so we need to avoid bit shift overflow.
4177*8975f5c5SAndroid Build Coastguard Worker uint32_t maskMsb = 1u << (bits - 1);
4178*8975f5c5SAndroid Build Coastguard Worker uint32_t insertMask = ((maskMsb - 1u) | maskMsb) << offset;
4179*8975f5c5SAndroid Build Coastguard Worker uint32_t baseMask = ~insertMask;
4180*8975f5c5SAndroid Build Coastguard Worker if (aggregate->getBasicType() == EbtInt)
4181*8975f5c5SAndroid Build Coastguard Worker {
4182*8975f5c5SAndroid Build Coastguard Worker uint32_t base = static_cast<uint32_t>(unionArrays[0][i].getIConst());
4183*8975f5c5SAndroid Build Coastguard Worker uint32_t insert = static_cast<uint32_t>(unionArrays[1][i].getIConst());
4184*8975f5c5SAndroid Build Coastguard Worker uint32_t resultUnsigned =
4185*8975f5c5SAndroid Build Coastguard Worker (base & baseMask) | ((insert << offset) & insertMask);
4186*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned));
4187*8975f5c5SAndroid Build Coastguard Worker }
4188*8975f5c5SAndroid Build Coastguard Worker else
4189*8975f5c5SAndroid Build Coastguard Worker {
4190*8975f5c5SAndroid Build Coastguard Worker ASSERT(aggregate->getBasicType() == EbtUInt);
4191*8975f5c5SAndroid Build Coastguard Worker uint32_t base = unionArrays[0][i].getUConst();
4192*8975f5c5SAndroid Build Coastguard Worker uint32_t insert = unionArrays[1][i].getUConst();
4193*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setUConst((base & baseMask) |
4194*8975f5c5SAndroid Build Coastguard Worker ((insert << offset) & insertMask));
4195*8975f5c5SAndroid Build Coastguard Worker }
4196*8975f5c5SAndroid Build Coastguard Worker }
4197*8975f5c5SAndroid Build Coastguard Worker }
4198*8975f5c5SAndroid Build Coastguard Worker break;
4199*8975f5c5SAndroid Build Coastguard Worker }
4200*8975f5c5SAndroid Build Coastguard Worker case EOpDFdx:
4201*8975f5c5SAndroid Build Coastguard Worker case EOpDFdy:
4202*8975f5c5SAndroid Build Coastguard Worker case EOpFwidth:
4203*8975f5c5SAndroid Build Coastguard Worker ASSERT(basicType == EbtFloat);
4204*8975f5c5SAndroid Build Coastguard Worker resultArray = new TConstantUnion[maxObjectSize];
4205*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxObjectSize; i++)
4206*8975f5c5SAndroid Build Coastguard Worker {
4207*8975f5c5SAndroid Build Coastguard Worker // Derivatives of constant arguments should be 0.
4208*8975f5c5SAndroid Build Coastguard Worker resultArray[i].setFConst(0.0f);
4209*8975f5c5SAndroid Build Coastguard Worker }
4210*8975f5c5SAndroid Build Coastguard Worker break;
4211*8975f5c5SAndroid Build Coastguard Worker
4212*8975f5c5SAndroid Build Coastguard Worker default:
4213*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
4214*8975f5c5SAndroid Build Coastguard Worker return nullptr;
4215*8975f5c5SAndroid Build Coastguard Worker }
4216*8975f5c5SAndroid Build Coastguard Worker return resultArray;
4217*8975f5c5SAndroid Build Coastguard Worker }
4218*8975f5c5SAndroid Build Coastguard Worker
4219*8975f5c5SAndroid Build Coastguard Worker // TIntermPreprocessorDirective implementation.
TIntermPreprocessorDirective(PreprocessorDirective directive,ImmutableString command)4220*8975f5c5SAndroid Build Coastguard Worker TIntermPreprocessorDirective::TIntermPreprocessorDirective(PreprocessorDirective directive,
4221*8975f5c5SAndroid Build Coastguard Worker ImmutableString command)
4222*8975f5c5SAndroid Build Coastguard Worker : mDirective(directive), mCommand(std::move(command))
4223*8975f5c5SAndroid Build Coastguard Worker {}
4224*8975f5c5SAndroid Build Coastguard Worker
TIntermPreprocessorDirective(const TIntermPreprocessorDirective & node)4225*8975f5c5SAndroid Build Coastguard Worker TIntermPreprocessorDirective::TIntermPreprocessorDirective(const TIntermPreprocessorDirective &node)
4226*8975f5c5SAndroid Build Coastguard Worker : TIntermPreprocessorDirective(node.mDirective, node.mCommand)
4227*8975f5c5SAndroid Build Coastguard Worker {}
4228*8975f5c5SAndroid Build Coastguard Worker
4229*8975f5c5SAndroid Build Coastguard Worker TIntermPreprocessorDirective::~TIntermPreprocessorDirective() = default;
4230*8975f5c5SAndroid Build Coastguard Worker
getChildCount() const4231*8975f5c5SAndroid Build Coastguard Worker size_t TIntermPreprocessorDirective::getChildCount() const
4232*8975f5c5SAndroid Build Coastguard Worker {
4233*8975f5c5SAndroid Build Coastguard Worker return 0;
4234*8975f5c5SAndroid Build Coastguard Worker }
4235*8975f5c5SAndroid Build Coastguard Worker
getChildNode(size_t index) const4236*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TIntermPreprocessorDirective::getChildNode(size_t index) const
4237*8975f5c5SAndroid Build Coastguard Worker {
4238*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
4239*8975f5c5SAndroid Build Coastguard Worker return nullptr;
4240*8975f5c5SAndroid Build Coastguard Worker }
4241*8975f5c5SAndroid Build Coastguard Worker } // namespace sh
4242