blob: 49f688d1009bc257f28aea92da796e436a81ca70 [file] [log] [blame]
Jamie Madillb1a85f42014-08-19 15:23:24 -04001//
2// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7//
8// Build the intermediate representation.
9//
10
11#include <float.h>
12#include <limits.h>
Arun Patole9dea48f2015-04-02 11:45:09 +053013#include <math.h>
Jamie Madillb1a85f42014-08-19 15:23:24 -040014#include <algorithm>
15
16#include "compiler/translator/HashNames.h"
17#include "compiler/translator/IntermNode.h"
18#include "compiler/translator/SymbolTable.h"
19
20namespace
21{
22
Arun Patole9dea48f2015-04-02 11:45:09 +053023const float kPi = 3.14159265358979323846f;
24const float kDegreesToRadiansMultiplier = kPi / 180.0f;
25const float kRadiansToDegreesMultiplier = 180.0f / kPi;
26
Jamie Madillb1a85f42014-08-19 15:23:24 -040027TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
28{
29 return left > right ? left : right;
30}
31
32bool ValidateMultiplication(TOperator op, const TType &left, const TType &right)
33{
34 switch (op)
35 {
36 case EOpMul:
37 case EOpMulAssign:
38 return left.getNominalSize() == right.getNominalSize() &&
39 left.getSecondarySize() == right.getSecondarySize();
40 case EOpVectorTimesScalar:
41 case EOpVectorTimesScalarAssign:
42 return true;
43 case EOpVectorTimesMatrix:
44 return left.getNominalSize() == right.getRows();
45 case EOpVectorTimesMatrixAssign:
46 return left.getNominalSize() == right.getRows() &&
47 left.getNominalSize() == right.getCols();
48 case EOpMatrixTimesVector:
49 return left.getCols() == right.getNominalSize();
50 case EOpMatrixTimesScalar:
51 case EOpMatrixTimesScalarAssign:
52 return true;
53 case EOpMatrixTimesMatrix:
54 return left.getCols() == right.getRows();
55 case EOpMatrixTimesMatrixAssign:
56 return left.getCols() == right.getCols() &&
57 left.getRows() == right.getRows();
58
59 default:
60 UNREACHABLE();
61 return false;
62 }
63}
64
65bool CompareStructure(const TType& leftNodeType,
66 ConstantUnion *rightUnionArray,
67 ConstantUnion *leftUnionArray);
68
69bool CompareStruct(const TType &leftNodeType,
70 ConstantUnion *rightUnionArray,
71 ConstantUnion *leftUnionArray)
72{
73 const TFieldList &fields = leftNodeType.getStruct()->fields();
74
75 size_t structSize = fields.size();
76 size_t index = 0;
77
78 for (size_t j = 0; j < structSize; j++)
79 {
80 size_t size = fields[j]->type()->getObjectSize();
81 for (size_t i = 0; i < size; i++)
82 {
83 if (fields[j]->type()->getBasicType() == EbtStruct)
84 {
85 if (!CompareStructure(*fields[j]->type(),
86 &rightUnionArray[index],
87 &leftUnionArray[index]))
88 {
89 return false;
90 }
91 }
92 else
93 {
94 if (leftUnionArray[index] != rightUnionArray[index])
95 return false;
96 index++;
97 }
98 }
99 }
100 return true;
101}
102
103bool CompareStructure(const TType &leftNodeType,
104 ConstantUnion *rightUnionArray,
105 ConstantUnion *leftUnionArray)
106{
107 if (leftNodeType.isArray())
108 {
109 TType typeWithoutArrayness = leftNodeType;
110 typeWithoutArrayness.clearArrayness();
111
112 size_t arraySize = leftNodeType.getArraySize();
113
114 for (size_t i = 0; i < arraySize; ++i)
115 {
116 size_t offset = typeWithoutArrayness.getObjectSize() * i;
117 if (!CompareStruct(typeWithoutArrayness,
118 &rightUnionArray[offset],
119 &leftUnionArray[offset]))
120 {
121 return false;
122 }
123 }
124 }
125 else
126 {
127 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
128 }
129 return true;
130}
131
132} // namespace anonymous
133
134
135////////////////////////////////////////////////////////////////
136//
137// Member functions of the nodes used for building the tree.
138//
139////////////////////////////////////////////////////////////////
140
Olli Etuahod2a67b92014-10-21 16:42:57 +0300141void TIntermTyped::setTypePreservePrecision(const TType &t)
142{
143 TPrecision precision = getPrecision();
144 mType = t;
145 ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined);
146 mType.setPrecision(precision);
147}
148
Jamie Madillb1a85f42014-08-19 15:23:24 -0400149#define REPLACE_IF_IS(node, type, original, replacement) \
150 if (node == original) { \
151 node = static_cast<type *>(replacement); \
152 return true; \
153 }
154
155bool TIntermLoop::replaceChildNode(
156 TIntermNode *original, TIntermNode *replacement)
157{
158 REPLACE_IF_IS(mInit, TIntermNode, original, replacement);
159 REPLACE_IF_IS(mCond, TIntermTyped, original, replacement);
160 REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement);
161 REPLACE_IF_IS(mBody, TIntermNode, original, replacement);
162 return false;
163}
164
Jamie Madillb1a85f42014-08-19 15:23:24 -0400165bool TIntermBranch::replaceChildNode(
166 TIntermNode *original, TIntermNode *replacement)
167{
168 REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement);
169 return false;
170}
171
Jamie Madillb1a85f42014-08-19 15:23:24 -0400172bool TIntermBinary::replaceChildNode(
173 TIntermNode *original, TIntermNode *replacement)
174{
175 REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement);
176 REPLACE_IF_IS(mRight, TIntermTyped, original, replacement);
177 return false;
178}
179
Jamie Madillb1a85f42014-08-19 15:23:24 -0400180bool TIntermUnary::replaceChildNode(
181 TIntermNode *original, TIntermNode *replacement)
182{
183 REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
184 return false;
185}
186
Jamie Madillb1a85f42014-08-19 15:23:24 -0400187bool TIntermAggregate::replaceChildNode(
188 TIntermNode *original, TIntermNode *replacement)
189{
190 for (size_t ii = 0; ii < mSequence.size(); ++ii)
191 {
192 REPLACE_IF_IS(mSequence[ii], TIntermNode, original, replacement);
193 }
194 return false;
195}
196
Olli Etuahod2a67b92014-10-21 16:42:57 +0300197void TIntermAggregate::setPrecisionFromChildren()
198{
199 if (getBasicType() == EbtBool)
200 {
201 mType.setPrecision(EbpUndefined);
202 return;
203 }
204
205 TPrecision precision = EbpUndefined;
206 TIntermSequence::iterator childIter = mSequence.begin();
207 while (childIter != mSequence.end())
208 {
209 TIntermTyped *typed = (*childIter)->getAsTyped();
210 if (typed)
211 precision = GetHigherPrecision(typed->getPrecision(), precision);
212 ++childIter;
213 }
214 mType.setPrecision(precision);
215}
216
217void TIntermAggregate::setBuiltInFunctionPrecision()
218{
219 // All built-ins returning bool should be handled as ops, not functions.
220 ASSERT(getBasicType() != EbtBool);
221
222 TPrecision precision = EbpUndefined;
223 TIntermSequence::iterator childIter = mSequence.begin();
224 while (childIter != mSequence.end())
225 {
226 TIntermTyped *typed = (*childIter)->getAsTyped();
227 // ESSL spec section 8: texture functions get their precision from the sampler.
228 if (typed && IsSampler(typed->getBasicType()))
229 {
230 precision = typed->getPrecision();
231 break;
232 }
233 ++childIter;
234 }
235 // ESSL 3.0 spec section 8: textureSize always gets highp precision.
236 // All other functions that take a sampler are assumed to be texture functions.
237 if (mName.find("textureSize") == 0)
238 mType.setPrecision(EbpHigh);
239 else
240 mType.setPrecision(precision);
241}
242
Jamie Madillb1a85f42014-08-19 15:23:24 -0400243bool TIntermSelection::replaceChildNode(
244 TIntermNode *original, TIntermNode *replacement)
245{
246 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
247 REPLACE_IF_IS(mTrueBlock, TIntermNode, original, replacement);
248 REPLACE_IF_IS(mFalseBlock, TIntermNode, original, replacement);
249 return false;
250}
251
Olli Etuahoa3a36662015-02-17 13:46:51 +0200252bool TIntermSwitch::replaceChildNode(
253 TIntermNode *original, TIntermNode *replacement)
254{
255 REPLACE_IF_IS(mInit, TIntermTyped, original, replacement);
256 REPLACE_IF_IS(mStatementList, TIntermAggregate, original, replacement);
257 return false;
258}
259
260bool TIntermCase::replaceChildNode(
261 TIntermNode *original, TIntermNode *replacement)
262{
263 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
264 return false;
265}
266
Jamie Madillb1a85f42014-08-19 15:23:24 -0400267//
268// Say whether or not an operation node changes the value of a variable.
269//
270bool TIntermOperator::isAssignment() const
271{
272 switch (mOp)
273 {
274 case EOpPostIncrement:
275 case EOpPostDecrement:
276 case EOpPreIncrement:
277 case EOpPreDecrement:
278 case EOpAssign:
279 case EOpAddAssign:
280 case EOpSubAssign:
281 case EOpMulAssign:
282 case EOpVectorTimesMatrixAssign:
283 case EOpVectorTimesScalarAssign:
284 case EOpMatrixTimesScalarAssign:
285 case EOpMatrixTimesMatrixAssign:
286 case EOpDivAssign:
Olli Etuahoff805cc2015-02-13 10:59:34 +0200287 case EOpIModAssign:
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200288 case EOpBitShiftLeftAssign:
289 case EOpBitShiftRightAssign:
290 case EOpBitwiseAndAssign:
291 case EOpBitwiseXorAssign:
292 case EOpBitwiseOrAssign:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400293 return true;
294 default:
295 return false;
296 }
297}
298
299//
300// returns true if the operator is for one of the constructors
301//
302bool TIntermOperator::isConstructor() const
303{
304 switch (mOp)
305 {
306 case EOpConstructVec2:
307 case EOpConstructVec3:
308 case EOpConstructVec4:
309 case EOpConstructMat2:
310 case EOpConstructMat3:
311 case EOpConstructMat4:
312 case EOpConstructFloat:
313 case EOpConstructIVec2:
314 case EOpConstructIVec3:
315 case EOpConstructIVec4:
316 case EOpConstructInt:
317 case EOpConstructUVec2:
318 case EOpConstructUVec3:
319 case EOpConstructUVec4:
320 case EOpConstructUInt:
321 case EOpConstructBVec2:
322 case EOpConstructBVec3:
323 case EOpConstructBVec4:
324 case EOpConstructBool:
325 case EOpConstructStruct:
326 return true;
327 default:
328 return false;
329 }
330}
331
332//
333// Make sure the type of a unary operator is appropriate for its
334// combination of operation and operand type.
335//
Olli Etuahof6c694b2015-03-26 14:50:53 +0200336void TIntermUnary::promote(const TType *funcReturnType)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400337{
338 switch (mOp)
339 {
Olli Etuahodca3e792015-03-26 13:24:04 +0200340 case EOpFloatBitsToInt:
341 case EOpFloatBitsToUint:
Olli Etuahoe8d2c072015-01-08 16:33:54 +0200342 case EOpIntBitsToFloat:
343 case EOpUintBitsToFloat:
Olli Etuahodca3e792015-03-26 13:24:04 +0200344 case EOpPackSnorm2x16:
345 case EOpPackUnorm2x16:
346 case EOpPackHalf2x16:
Olli Etuaho7700ff62015-01-15 12:16:29 +0200347 case EOpUnpackSnorm2x16:
348 case EOpUnpackUnorm2x16:
Olli Etuahodca3e792015-03-26 13:24:04 +0200349 mType.setPrecision(EbpHigh);
Arun Patole6b19d762015-02-19 09:40:39 +0530350 break;
Olli Etuahodca3e792015-03-26 13:24:04 +0200351 case EOpUnpackHalf2x16:
352 mType.setPrecision(EbpMedium);
353 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400354 default:
Olli Etuahodca3e792015-03-26 13:24:04 +0200355 setType(mOperand->getType());
Jamie Madillb1a85f42014-08-19 15:23:24 -0400356 }
357
Olli Etuahof6c694b2015-03-26 14:50:53 +0200358 if (funcReturnType != nullptr)
359 {
360 if (funcReturnType->getBasicType() == EbtBool)
361 {
362 // Bool types should not have precision.
363 setType(*funcReturnType);
364 }
365 else
366 {
367 // Precision of the node has been set based on the operand.
368 setTypePreservePrecision(*funcReturnType);
369 }
370 }
371
Jamie Madillb1a85f42014-08-19 15:23:24 -0400372 mType.setQualifier(EvqTemporary);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400373}
374
375//
376// Establishes the type of the resultant operation, as well as
377// makes the operator the correct one for the operands.
378//
Olli Etuaho47fd36a2015-03-19 14:22:24 +0200379// For lots of operations it should already be established that the operand
380// combination is valid, but returns false if operator can't work on operands.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400381//
382bool TIntermBinary::promote(TInfoSink &infoSink)
383{
Olli Etuahoe79904c2015-03-18 16:56:42 +0200384 ASSERT(mLeft->isArray() == mRight->isArray());
Jamie Madillb1a85f42014-08-19 15:23:24 -0400385
Jamie Madillb1a85f42014-08-19 15:23:24 -0400386 //
387 // Base assumption: just make the type the same as the left
388 // operand. Then only deviations from this need be coded.
389 //
390 setType(mLeft->getType());
391
392 // The result gets promoted to the highest precision.
393 TPrecision higherPrecision = GetHigherPrecision(
394 mLeft->getPrecision(), mRight->getPrecision());
395 getTypePointer()->setPrecision(higherPrecision);
396
397 // Binary operations results in temporary variables unless both
398 // operands are const.
399 if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst)
400 {
401 getTypePointer()->setQualifier(EvqTemporary);
402 }
403
404 const int nominalSize =
405 std::max(mLeft->getNominalSize(), mRight->getNominalSize());
406
407 //
408 // All scalars or structs. Code after this test assumes this case is removed!
409 //
410 if (nominalSize == 1)
411 {
412 switch (mOp)
413 {
414 //
415 // Promote to conditional
416 //
417 case EOpEqual:
418 case EOpNotEqual:
419 case EOpLessThan:
420 case EOpGreaterThan:
421 case EOpLessThanEqual:
422 case EOpGreaterThanEqual:
423 setType(TType(EbtBool, EbpUndefined));
424 break;
425
426 //
427 // And and Or operate on conditionals
428 //
429 case EOpLogicalAnd:
Olli Etuaho47fd36a2015-03-19 14:22:24 +0200430 case EOpLogicalXor:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400431 case EOpLogicalOr:
Olli Etuaho47fd36a2015-03-19 14:22:24 +0200432 ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400433 setType(TType(EbtBool, EbpUndefined));
434 break;
435
436 default:
437 break;
438 }
439 return true;
440 }
441
442 // If we reach here, at least one of the operands is vector or matrix.
443 // The other operand could be a scalar, vector, or matrix.
444 // Can these two operands be combined?
445 //
446 TBasicType basicType = mLeft->getBasicType();
447 switch (mOp)
448 {
449 case EOpMul:
450 if (!mLeft->isMatrix() && mRight->isMatrix())
451 {
452 if (mLeft->isVector())
453 {
454 mOp = EOpVectorTimesMatrix;
455 setType(TType(basicType, higherPrecision, EvqTemporary,
Minmin Gong794e0002015-04-07 18:31:54 -0700456 static_cast<unsigned char>(mRight->getCols()), 1));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400457 }
458 else
459 {
460 mOp = EOpMatrixTimesScalar;
461 setType(TType(basicType, higherPrecision, EvqTemporary,
Minmin Gong794e0002015-04-07 18:31:54 -0700462 static_cast<unsigned char>(mRight->getCols()), static_cast<unsigned char>(mRight->getRows())));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400463 }
464 }
465 else if (mLeft->isMatrix() && !mRight->isMatrix())
466 {
467 if (mRight->isVector())
468 {
469 mOp = EOpMatrixTimesVector;
470 setType(TType(basicType, higherPrecision, EvqTemporary,
Minmin Gong794e0002015-04-07 18:31:54 -0700471 static_cast<unsigned char>(mLeft->getRows()), 1));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400472 }
473 else
474 {
475 mOp = EOpMatrixTimesScalar;
476 }
477 }
478 else if (mLeft->isMatrix() && mRight->isMatrix())
479 {
480 mOp = EOpMatrixTimesMatrix;
481 setType(TType(basicType, higherPrecision, EvqTemporary,
Minmin Gong794e0002015-04-07 18:31:54 -0700482 static_cast<unsigned char>(mRight->getCols()), static_cast<unsigned char>(mLeft->getRows())));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400483 }
484 else if (!mLeft->isMatrix() && !mRight->isMatrix())
485 {
486 if (mLeft->isVector() && mRight->isVector())
487 {
488 // leave as component product
489 }
490 else if (mLeft->isVector() || mRight->isVector())
491 {
492 mOp = EOpVectorTimesScalar;
493 setType(TType(basicType, higherPrecision, EvqTemporary,
Minmin Gong794e0002015-04-07 18:31:54 -0700494 static_cast<unsigned char>(nominalSize), 1));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400495 }
496 }
497 else
498 {
499 infoSink.info.message(EPrefixInternalError, getLine(),
500 "Missing elses");
501 return false;
502 }
503
504 if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType()))
505 {
506 return false;
507 }
508 break;
509
510 case EOpMulAssign:
511 if (!mLeft->isMatrix() && mRight->isMatrix())
512 {
513 if (mLeft->isVector())
514 {
515 mOp = EOpVectorTimesMatrixAssign;
516 }
517 else
518 {
519 return false;
520 }
521 }
522 else if (mLeft->isMatrix() && !mRight->isMatrix())
523 {
524 if (mRight->isVector())
525 {
526 return false;
527 }
528 else
529 {
530 mOp = EOpMatrixTimesScalarAssign;
531 }
532 }
533 else if (mLeft->isMatrix() && mRight->isMatrix())
534 {
535 mOp = EOpMatrixTimesMatrixAssign;
536 setType(TType(basicType, higherPrecision, EvqTemporary,
Minmin Gong794e0002015-04-07 18:31:54 -0700537 static_cast<unsigned char>(mRight->getCols()), static_cast<unsigned char>(mLeft->getRows())));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400538 }
539 else if (!mLeft->isMatrix() && !mRight->isMatrix())
540 {
541 if (mLeft->isVector() && mRight->isVector())
542 {
543 // leave as component product
544 }
545 else if (mLeft->isVector() || mRight->isVector())
546 {
547 if (!mLeft->isVector())
548 return false;
549 mOp = EOpVectorTimesScalarAssign;
550 setType(TType(basicType, higherPrecision, EvqTemporary,
Minmin Gong794e0002015-04-07 18:31:54 -0700551 static_cast<unsigned char>(mLeft->getNominalSize()), 1));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400552 }
553 }
554 else
555 {
556 infoSink.info.message(EPrefixInternalError, getLine(),
557 "Missing elses");
558 return false;
559 }
560
561 if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType()))
562 {
563 return false;
564 }
565 break;
566
567 case EOpAssign:
568 case EOpInitialize:
Olli Etuaho47fd36a2015-03-19 14:22:24 +0200569 // No more additional checks are needed.
570 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
571 (mLeft->getSecondarySize() == mRight->getSecondarySize()));
572 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400573 case EOpAdd:
574 case EOpSub:
575 case EOpDiv:
Olli Etuahoff805cc2015-02-13 10:59:34 +0200576 case EOpIMod:
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200577 case EOpBitShiftLeft:
578 case EOpBitShiftRight:
579 case EOpBitwiseAnd:
580 case EOpBitwiseXor:
581 case EOpBitwiseOr:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400582 case EOpAddAssign:
583 case EOpSubAssign:
584 case EOpDivAssign:
Olli Etuahoff805cc2015-02-13 10:59:34 +0200585 case EOpIModAssign:
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200586 case EOpBitShiftLeftAssign:
587 case EOpBitShiftRightAssign:
588 case EOpBitwiseAndAssign:
589 case EOpBitwiseXorAssign:
590 case EOpBitwiseOrAssign:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400591 if ((mLeft->isMatrix() && mRight->isVector()) ||
592 (mLeft->isVector() && mRight->isMatrix()))
593 {
594 return false;
595 }
596
597 // Are the sizes compatible?
598 if (mLeft->getNominalSize() != mRight->getNominalSize() ||
599 mLeft->getSecondarySize() != mRight->getSecondarySize())
600 {
Olli Etuaho6c850472014-12-02 16:23:17 +0200601 // If the nominal sizes of operands do not match:
602 // One of them must be a scalar.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400603 if (!mLeft->isScalar() && !mRight->isScalar())
604 return false;
605
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200606 // In the case of compound assignment other than multiply-assign,
607 // the right side needs to be a scalar. Otherwise a vector/matrix
608 // would be assigned to a scalar. A scalar can't be shifted by a
609 // vector either.
Olli Etuaho6c850472014-12-02 16:23:17 +0200610 if (!mRight->isScalar() &&
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200611 (isAssignment() ||
612 mOp == EOpBitShiftLeft ||
613 mOp == EOpBitShiftRight))
Olli Etuaho6c850472014-12-02 16:23:17 +0200614 return false;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400615 }
616
617 {
618 const int secondarySize = std::max(
619 mLeft->getSecondarySize(), mRight->getSecondarySize());
620 setType(TType(basicType, higherPrecision, EvqTemporary,
Minmin Gong794e0002015-04-07 18:31:54 -0700621 static_cast<unsigned char>(nominalSize), static_cast<unsigned char>(secondarySize)));
Olli Etuahoe79904c2015-03-18 16:56:42 +0200622 if (mLeft->isArray())
623 {
624 ASSERT(mLeft->getArraySize() == mRight->getArraySize());
625 mType.setArraySize(mLeft->getArraySize());
626 }
Jamie Madillb1a85f42014-08-19 15:23:24 -0400627 }
628 break;
629
630 case EOpEqual:
631 case EOpNotEqual:
632 case EOpLessThan:
633 case EOpGreaterThan:
634 case EOpLessThanEqual:
635 case EOpGreaterThanEqual:
Olli Etuaho47fd36a2015-03-19 14:22:24 +0200636 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
637 (mLeft->getSecondarySize() == mRight->getSecondarySize()));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400638 setType(TType(EbtBool, EbpUndefined));
639 break;
640
641 default:
642 return false;
643 }
644 return true;
645}
646
647//
648// The fold functions see if an operation on a constant can be done in place,
649// without generating run-time code.
650//
651// Returns the node to keep using, which may or may not be the node passed in.
652//
653TIntermTyped *TIntermConstantUnion::fold(
654 TOperator op, TIntermTyped *constantNode, TInfoSink &infoSink)
655{
656 ConstantUnion *unionArray = getUnionArrayPointer();
657
658 if (!unionArray)
Jamie Madillb7757782015-04-14 15:29:29 +0000659 return NULL;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400660
661 size_t objectSize = getType().getObjectSize();
662
663 if (constantNode)
664 {
665 // binary operations
666 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
667 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
668 TType returnType = getType();
669
670 if (!rightUnionArray)
Jamie Madillb7757782015-04-14 15:29:29 +0000671 return NULL;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400672
673 // for a case like float f = 1.2 + vec4(2,3,4,5);
674 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1)
675 {
676 rightUnionArray = new ConstantUnion[objectSize];
677 for (size_t i = 0; i < objectSize; ++i)
678 {
679 rightUnionArray[i] = *node->getUnionArrayPointer();
680 }
681 returnType = getType();
682 }
683 else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1)
684 {
685 // for a case like float f = vec4(2,3,4,5) + 1.2;
686 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
687 for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
688 {
689 unionArray[i] = *getUnionArrayPointer();
690 }
691 returnType = node->getType();
692 objectSize = constantNode->getType().getObjectSize();
693 }
694
695 ConstantUnion *tempConstArray = NULL;
696 TIntermConstantUnion *tempNode;
697
698 bool boolNodeFlag = false;
699 switch(op)
700 {
701 case EOpAdd:
702 tempConstArray = new ConstantUnion[objectSize];
703 for (size_t i = 0; i < objectSize; i++)
704 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
705 break;
706 case EOpSub:
707 tempConstArray = new ConstantUnion[objectSize];
708 for (size_t i = 0; i < objectSize; i++)
709 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
710 break;
711
712 case EOpMul:
713 case EOpVectorTimesScalar:
714 case EOpMatrixTimesScalar:
715 tempConstArray = new ConstantUnion[objectSize];
716 for (size_t i = 0; i < objectSize; i++)
717 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
718 break;
719
720 case EOpMatrixTimesMatrix:
721 {
722 if (getType().getBasicType() != EbtFloat ||
723 node->getBasicType() != EbtFloat)
724 {
725 infoSink.info.message(
726 EPrefixInternalError, getLine(),
727 "Constant Folding cannot be done for matrix multiply");
Jamie Madillb7757782015-04-14 15:29:29 +0000728 return NULL;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400729 }
730
731 const int leftCols = getCols();
732 const int leftRows = getRows();
733 const int rightCols = constantNode->getType().getCols();
734 const int rightRows = constantNode->getType().getRows();
735 const int resultCols = rightCols;
736 const int resultRows = leftRows;
737
738 tempConstArray = new ConstantUnion[resultCols*resultRows];
739 for (int row = 0; row < resultRows; row++)
740 {
741 for (int column = 0; column < resultCols; column++)
742 {
743 tempConstArray[resultRows * column + row].setFConst(0.0f);
744 for (int i = 0; i < leftCols; i++)
745 {
746 tempConstArray[resultRows * column + row].setFConst(
747 tempConstArray[resultRows * column + row].getFConst() +
748 unionArray[i * leftRows + row].getFConst() *
749 rightUnionArray[column * rightRows + i].getFConst());
750 }
751 }
752 }
753
754 // update return type for matrix product
Minmin Gong794e0002015-04-07 18:31:54 -0700755 returnType.setPrimarySize(static_cast<unsigned char>(resultCols));
756 returnType.setSecondarySize(static_cast<unsigned char>(resultRows));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400757 }
758 break;
759
760 case EOpDiv:
Olli Etuahoff805cc2015-02-13 10:59:34 +0200761 case EOpIMod:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400762 {
763 tempConstArray = new ConstantUnion[objectSize];
764 for (size_t i = 0; i < objectSize; i++)
765 {
766 switch (getType().getBasicType())
767 {
768 case EbtFloat:
769 if (rightUnionArray[i] == 0.0f)
770 {
771 infoSink.info.message(
772 EPrefixWarning, getLine(),
773 "Divide by zero error during constant folding");
774 tempConstArray[i].setFConst(
775 unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
776 }
777 else
778 {
Olli Etuaho3eab00a2015-02-12 16:02:39 +0200779 ASSERT(op == EOpDiv);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400780 tempConstArray[i].setFConst(
781 unionArray[i].getFConst() /
782 rightUnionArray[i].getFConst());
783 }
784 break;
785
786 case EbtInt:
787 if (rightUnionArray[i] == 0)
788 {
789 infoSink.info.message(
790 EPrefixWarning, getLine(),
791 "Divide by zero error during constant folding");
792 tempConstArray[i].setIConst(INT_MAX);
793 }
794 else
795 {
Olli Etuaho3eab00a2015-02-12 16:02:39 +0200796 if (op == EOpDiv)
797 {
798 tempConstArray[i].setIConst(
799 unionArray[i].getIConst() /
800 rightUnionArray[i].getIConst());
801 }
802 else
803 {
804 ASSERT(op == EOpIMod);
805 tempConstArray[i].setIConst(
806 unionArray[i].getIConst() %
807 rightUnionArray[i].getIConst());
808 }
Jamie Madillb1a85f42014-08-19 15:23:24 -0400809 }
810 break;
811
812 case EbtUInt:
813 if (rightUnionArray[i] == 0)
814 {
815 infoSink.info.message(
816 EPrefixWarning, getLine(),
817 "Divide by zero error during constant folding");
818 tempConstArray[i].setUConst(UINT_MAX);
819 }
820 else
821 {
Olli Etuaho3eab00a2015-02-12 16:02:39 +0200822 if (op == EOpDiv)
823 {
824 tempConstArray[i].setUConst(
825 unionArray[i].getUConst() /
826 rightUnionArray[i].getUConst());
827 }
828 else
829 {
830 ASSERT(op == EOpIMod);
831 tempConstArray[i].setUConst(
832 unionArray[i].getUConst() %
833 rightUnionArray[i].getUConst());
834 }
Jamie Madillb1a85f42014-08-19 15:23:24 -0400835 }
836 break;
837
838 default:
839 infoSink.info.message(
840 EPrefixInternalError, getLine(),
841 "Constant folding cannot be done for \"/\"");
Jamie Madillb7757782015-04-14 15:29:29 +0000842 return NULL;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400843 }
844 }
845 }
846 break;
847
848 case EOpMatrixTimesVector:
849 {
850 if (node->getBasicType() != EbtFloat)
851 {
852 infoSink.info.message(
853 EPrefixInternalError, getLine(),
854 "Constant Folding cannot be done for matrix times vector");
Jamie Madillb7757782015-04-14 15:29:29 +0000855 return NULL;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400856 }
857
858 const int matrixCols = getCols();
859 const int matrixRows = getRows();
860
861 tempConstArray = new ConstantUnion[matrixRows];
862
863 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
864 {
865 tempConstArray[matrixRow].setFConst(0.0f);
866 for (int col = 0; col < matrixCols; col++)
867 {
868 tempConstArray[matrixRow].setFConst(
869 tempConstArray[matrixRow].getFConst() +
870 unionArray[col * matrixRows + matrixRow].getFConst() *
871 rightUnionArray[col].getFConst());
872 }
873 }
874
875 returnType = node->getType();
Minmin Gong794e0002015-04-07 18:31:54 -0700876 returnType.setPrimarySize(static_cast<unsigned char>(matrixRows));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400877
878 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
879 tempNode->setLine(getLine());
880
881 return tempNode;
882 }
883
884 case EOpVectorTimesMatrix:
885 {
886 if (getType().getBasicType() != EbtFloat)
887 {
888 infoSink.info.message(
889 EPrefixInternalError, getLine(),
890 "Constant Folding cannot be done for vector times matrix");
Jamie Madillb7757782015-04-14 15:29:29 +0000891 return NULL;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400892 }
893
894 const int matrixCols = constantNode->getType().getCols();
895 const int matrixRows = constantNode->getType().getRows();
896
897 tempConstArray = new ConstantUnion[matrixCols];
898
899 for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++)
900 {
901 tempConstArray[matrixCol].setFConst(0.0f);
902 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
903 {
904 tempConstArray[matrixCol].setFConst(
905 tempConstArray[matrixCol].getFConst() +
906 unionArray[matrixRow].getFConst() *
907 rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst());
908 }
909 }
910
Minmin Gong794e0002015-04-07 18:31:54 -0700911 returnType.setPrimarySize(static_cast<unsigned char>(matrixCols));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400912 }
913 break;
914
915 case EOpLogicalAnd:
916 // this code is written for possible future use,
917 // will not get executed currently
918 {
919 tempConstArray = new ConstantUnion[objectSize];
920 for (size_t i = 0; i < objectSize; i++)
921 {
922 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
923 }
924 }
925 break;
926
927 case EOpLogicalOr:
928 // this code is written for possible future use,
929 // will not get executed currently
930 {
931 tempConstArray = new ConstantUnion[objectSize];
932 for (size_t i = 0; i < objectSize; i++)
933 {
934 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
935 }
936 }
937 break;
938
939 case EOpLogicalXor:
940 {
941 tempConstArray = new ConstantUnion[objectSize];
942 for (size_t i = 0; i < objectSize; i++)
943 {
944 switch (getType().getBasicType())
945 {
946 case EbtBool:
947 tempConstArray[i].setBConst(
948 unionArray[i] == rightUnionArray[i] ? false : true);
949 break;
950 default:
951 UNREACHABLE();
952 break;
953 }
954 }
955 }
956 break;
957
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200958 case EOpBitwiseAnd:
959 tempConstArray = new ConstantUnion[objectSize];
960 for (size_t i = 0; i < objectSize; i++)
961 tempConstArray[i] = unionArray[i] & rightUnionArray[i];
962 break;
963 case EOpBitwiseXor:
964 tempConstArray = new ConstantUnion[objectSize];
965 for (size_t i = 0; i < objectSize; i++)
966 tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
967 break;
968 case EOpBitwiseOr:
969 tempConstArray = new ConstantUnion[objectSize];
970 for (size_t i = 0; i < objectSize; i++)
971 tempConstArray[i] = unionArray[i] | rightUnionArray[i];
972 break;
973 case EOpBitShiftLeft:
974 tempConstArray = new ConstantUnion[objectSize];
975 for (size_t i = 0; i < objectSize; i++)
976 tempConstArray[i] = unionArray[i] << rightUnionArray[i];
977 break;
978 case EOpBitShiftRight:
979 tempConstArray = new ConstantUnion[objectSize];
980 for (size_t i = 0; i < objectSize; i++)
981 tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
982 break;
983
Jamie Madillb1a85f42014-08-19 15:23:24 -0400984 case EOpLessThan:
985 ASSERT(objectSize == 1);
986 tempConstArray = new ConstantUnion[1];
987 tempConstArray->setBConst(*unionArray < *rightUnionArray);
988 returnType = TType(EbtBool, EbpUndefined, EvqConst);
989 break;
990
991 case EOpGreaterThan:
992 ASSERT(objectSize == 1);
993 tempConstArray = new ConstantUnion[1];
994 tempConstArray->setBConst(*unionArray > *rightUnionArray);
995 returnType = TType(EbtBool, EbpUndefined, EvqConst);
996 break;
997
998 case EOpLessThanEqual:
999 {
1000 ASSERT(objectSize == 1);
1001 ConstantUnion constant;
1002 constant.setBConst(*unionArray > *rightUnionArray);
1003 tempConstArray = new ConstantUnion[1];
1004 tempConstArray->setBConst(!constant.getBConst());
1005 returnType = TType(EbtBool, EbpUndefined, EvqConst);
1006 break;
1007 }
1008
1009 case EOpGreaterThanEqual:
1010 {
1011 ASSERT(objectSize == 1);
1012 ConstantUnion constant;
1013 constant.setBConst(*unionArray < *rightUnionArray);
1014 tempConstArray = new ConstantUnion[1];
1015 tempConstArray->setBConst(!constant.getBConst());
1016 returnType = TType(EbtBool, EbpUndefined, EvqConst);
1017 break;
1018 }
1019
1020 case EOpEqual:
1021 if (getType().getBasicType() == EbtStruct)
1022 {
1023 if (!CompareStructure(node->getType(),
1024 node->getUnionArrayPointer(),
1025 unionArray))
1026 {
1027 boolNodeFlag = true;
1028 }
1029 }
1030 else
1031 {
1032 for (size_t i = 0; i < objectSize; i++)
1033 {
1034 if (unionArray[i] != rightUnionArray[i])
1035 {
1036 boolNodeFlag = true;
1037 break; // break out of for loop
1038 }
1039 }
1040 }
1041
1042 tempConstArray = new ConstantUnion[1];
1043 if (!boolNodeFlag)
1044 {
1045 tempConstArray->setBConst(true);
1046 }
1047 else
1048 {
1049 tempConstArray->setBConst(false);
1050 }
1051
1052 tempNode = new TIntermConstantUnion(
1053 tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
1054 tempNode->setLine(getLine());
1055
1056 return tempNode;
1057
1058 case EOpNotEqual:
1059 if (getType().getBasicType() == EbtStruct)
1060 {
1061 if (CompareStructure(node->getType(),
1062 node->getUnionArrayPointer(),
1063 unionArray))
1064 {
1065 boolNodeFlag = true;
1066 }
1067 }
1068 else
1069 {
1070 for (size_t i = 0; i < objectSize; i++)
1071 {
1072 if (unionArray[i] == rightUnionArray[i])
1073 {
1074 boolNodeFlag = true;
1075 break; // break out of for loop
1076 }
1077 }
1078 }
1079
1080 tempConstArray = new ConstantUnion[1];
1081 if (!boolNodeFlag)
1082 {
1083 tempConstArray->setBConst(true);
1084 }
1085 else
1086 {
1087 tempConstArray->setBConst(false);
1088 }
1089
1090 tempNode = new TIntermConstantUnion(
1091 tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
1092 tempNode->setLine(getLine());
1093
1094 return tempNode;
1095
1096 default:
1097 infoSink.info.message(
1098 EPrefixInternalError, getLine(),
1099 "Invalid operator for constant folding");
Jamie Madillb7757782015-04-14 15:29:29 +00001100 return NULL;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001101 }
1102 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1103 tempNode->setLine(getLine());
1104
1105 return tempNode;
1106 }
1107 else
1108 {
1109 //
1110 // Do unary operations
1111 //
1112 TIntermConstantUnion *newNode = 0;
1113 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
1114 for (size_t i = 0; i < objectSize; i++)
1115 {
1116 switch(op)
1117 {
1118 case EOpNegative:
1119 switch (getType().getBasicType())
1120 {
1121 case EbtFloat:
1122 tempConstArray[i].setFConst(-unionArray[i].getFConst());
1123 break;
1124 case EbtInt:
1125 tempConstArray[i].setIConst(-unionArray[i].getIConst());
1126 break;
1127 case EbtUInt:
1128 tempConstArray[i].setUConst(static_cast<unsigned int>(
1129 -static_cast<int>(unionArray[i].getUConst())));
1130 break;
1131 default:
1132 infoSink.info.message(
1133 EPrefixInternalError, getLine(),
1134 "Unary operation not folded into constant");
Jamie Madillb7757782015-04-14 15:29:29 +00001135 return NULL;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001136 }
1137 break;
1138
Zhenyao Mode1e00e2014-10-09 16:55:32 -07001139 case EOpPositive:
1140 switch (getType().getBasicType())
1141 {
1142 case EbtFloat:
1143 tempConstArray[i].setFConst(unionArray[i].getFConst());
1144 break;
1145 case EbtInt:
1146 tempConstArray[i].setIConst(unionArray[i].getIConst());
1147 break;
1148 case EbtUInt:
1149 tempConstArray[i].setUConst(static_cast<unsigned int>(
1150 static_cast<int>(unionArray[i].getUConst())));
1151 break;
1152 default:
1153 infoSink.info.message(
1154 EPrefixInternalError, getLine(),
1155 "Unary operation not folded into constant");
Jamie Madillb7757782015-04-14 15:29:29 +00001156 return NULL;
Zhenyao Mode1e00e2014-10-09 16:55:32 -07001157 }
1158 break;
1159
Jamie Madillb1a85f42014-08-19 15:23:24 -04001160 case EOpLogicalNot:
1161 // this code is written for possible future use,
1162 // will not get executed currently
1163 switch (getType().getBasicType())
1164 {
1165 case EbtBool:
1166 tempConstArray[i].setBConst(!unionArray[i].getBConst());
1167 break;
1168 default:
1169 infoSink.info.message(
1170 EPrefixInternalError, getLine(),
1171 "Unary operation not folded into constant");
Jamie Madillb7757782015-04-14 15:29:29 +00001172 return NULL;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001173 }
1174 break;
1175
Olli Etuaho31b5fc62015-01-16 12:13:36 +02001176 case EOpBitwiseNot:
1177 switch (getType().getBasicType())
1178 {
1179 case EbtInt:
1180 tempConstArray[i].setIConst(~unionArray[i].getIConst());
1181 break;
1182 case EbtUInt:
1183 tempConstArray[i].setUConst(~unionArray[i].getUConst());
1184 break;
1185 default:
1186 infoSink.info.message(
1187 EPrefixInternalError, getLine(),
1188 "Unary operation not folded into constant");
Jamie Madillb7757782015-04-14 15:29:29 +00001189 return NULL;
Olli Etuaho31b5fc62015-01-16 12:13:36 +02001190 }
1191 break;
1192
Arun Patole9dea48f2015-04-02 11:45:09 +05301193 case EOpRadians:
1194 if (getType().getBasicType() == EbtFloat)
1195 {
1196 tempConstArray[i].setFConst(kDegreesToRadiansMultiplier * unionArray[i].getFConst());
1197 break;
1198 }
1199 infoSink.info.message(
1200 EPrefixInternalError, getLine(),
1201 "Unary operation not folded into constant");
1202 return nullptr;
1203
1204 case EOpDegrees:
1205 if (getType().getBasicType() == EbtFloat)
1206 {
1207 tempConstArray[i].setFConst(kRadiansToDegreesMultiplier * unionArray[i].getFConst());
1208 break;
1209 }
1210 infoSink.info.message(
1211 EPrefixInternalError, getLine(),
1212 "Unary operation not folded into constant");
1213 return nullptr;
1214
1215 case EOpSin:
1216 if (!foldFloatTypeUnary(unionArray[i], &sinf, infoSink, &tempConstArray[i]))
1217 return nullptr;
1218 break;
1219
1220 case EOpCos:
1221 if (!foldFloatTypeUnary(unionArray[i], &cosf, infoSink, &tempConstArray[i]))
1222 return nullptr;
1223 break;
1224
1225 case EOpTan:
1226 if (!foldFloatTypeUnary(unionArray[i], &tanf, infoSink, &tempConstArray[i]))
1227 return nullptr;
1228 break;
1229
1230 case EOpAsin:
1231 // For asin(x), results are undefined if |x| > 1, we are choosing to set result to 0.
1232 if (getType().getBasicType() == EbtFloat && fabsf(unionArray[i].getFConst()) > 1.0f)
1233 tempConstArray[i].setFConst(0.0f);
1234 else if (!foldFloatTypeUnary(unionArray[i], &asinf, infoSink, &tempConstArray[i]))
1235 return nullptr;
1236 break;
1237
1238 case EOpAcos:
1239 // For acos(x), results are undefined if |x| > 1, we are choosing to set result to 0.
1240 if (getType().getBasicType() == EbtFloat && fabsf(unionArray[i].getFConst()) > 1.0f)
1241 tempConstArray[i].setFConst(0.0f);
1242 else if (!foldFloatTypeUnary(unionArray[i], &acosf, infoSink, &tempConstArray[i]))
1243 return nullptr;
1244 break;
1245
1246 case EOpAtan:
1247 if (!foldFloatTypeUnary(unionArray[i], &atanf, infoSink, &tempConstArray[i]))
1248 return nullptr;
1249 break;
1250
1251 case EOpSinh:
1252 if (!foldFloatTypeUnary(unionArray[i], &sinhf, infoSink, &tempConstArray[i]))
1253 return nullptr;
1254 break;
1255
1256 case EOpCosh:
1257 if (!foldFloatTypeUnary(unionArray[i], &coshf, infoSink, &tempConstArray[i]))
1258 return nullptr;
1259 break;
1260
1261 case EOpTanh:
1262 if (!foldFloatTypeUnary(unionArray[i], &tanhf, infoSink, &tempConstArray[i]))
1263 return nullptr;
1264 break;
1265
1266 case EOpAsinh:
1267 if (!foldFloatTypeUnary(unionArray[i], &asinhf, infoSink, &tempConstArray[i]))
1268 return nullptr;
1269 break;
1270
1271 case EOpAcosh:
1272 // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
1273 if (getType().getBasicType() == EbtFloat && unionArray[i].getFConst() < 1.0f)
1274 tempConstArray[i].setFConst(0.0f);
1275 else if (!foldFloatTypeUnary(unionArray[i], &acoshf, infoSink, &tempConstArray[i]))
1276 return nullptr;
1277 break;
1278
1279 case EOpAtanh:
1280 // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to 0.
1281 if (getType().getBasicType() == EbtFloat && fabsf(unionArray[i].getFConst()) >= 1.0f)
1282 tempConstArray[i].setFConst(0.0f);
1283 else if (!foldFloatTypeUnary(unionArray[i], &atanhf, infoSink, &tempConstArray[i]))
1284 return nullptr;
1285 break;
1286
Jamie Madillb1a85f42014-08-19 15:23:24 -04001287 default:
Jamie Madillb7757782015-04-14 15:29:29 +00001288 return NULL;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001289 }
1290 }
1291 newNode = new TIntermConstantUnion(tempConstArray, getType());
1292 newNode->setLine(getLine());
1293 return newNode;
1294 }
1295}
1296
Arun Patole9dea48f2015-04-02 11:45:09 +05301297bool TIntermConstantUnion::foldFloatTypeUnary(const ConstantUnion &parameter, FloatTypeUnaryFunc builtinFunc,
1298 TInfoSink &infoSink, ConstantUnion *result) const
1299{
1300 ASSERT(builtinFunc);
1301
1302 if (getType().getBasicType() == EbtFloat)
1303 {
1304 result->setFConst(builtinFunc(parameter.getFConst()));
1305 return true;
1306 }
1307
1308 infoSink.info.message(
1309 EPrefixInternalError, getLine(),
1310 "Unary operation not folded into constant");
1311 return false;
1312}
1313
Jamie Madillb1a85f42014-08-19 15:23:24 -04001314// static
1315TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction)
1316{
1317 if (hashFunction == NULL || name.empty())
1318 return name;
1319 khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
1320 TStringStream stream;
1321 stream << HASHED_NAME_PREFIX << std::hex << number;
1322 TString hashedName = stream.str();
1323 return hashedName;
1324}
Olli Etuaho853dc1a2014-11-06 17:25:48 +02001325
1326void TIntermTraverser::updateTree()
1327{
1328 for (size_t ii = 0; ii < mReplacements.size(); ++ii)
1329 {
Olli Etuahocd94ef92015-04-16 19:18:10 +03001330 const NodeUpdateEntry &replacement = mReplacements[ii];
1331 ASSERT(replacement.parent);
1332 bool replaced = replacement.parent->replaceChildNode(
1333 replacement.original, replacement.replacement);
Olli Etuaho853dc1a2014-11-06 17:25:48 +02001334 ASSERT(replaced);
1335
Olli Etuahocd94ef92015-04-16 19:18:10 +03001336 if (!replacement.originalBecomesChildOfReplacement)
Olli Etuaho853dc1a2014-11-06 17:25:48 +02001337 {
1338 // In AST traversing, a parent is visited before its children.
Olli Etuahocd94ef92015-04-16 19:18:10 +03001339 // After we replace a node, if its immediate child is to
Olli Etuaho853dc1a2014-11-06 17:25:48 +02001340 // be replaced, we need to make sure we don't update the replaced
1341 // node; instead, we update the replacement node.
1342 for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj)
1343 {
Olli Etuahocd94ef92015-04-16 19:18:10 +03001344 NodeUpdateEntry &replacement2 = mReplacements[jj];
1345 if (replacement2.parent == replacement.original)
1346 replacement2.parent = replacement.replacement;
Olli Etuaho853dc1a2014-11-06 17:25:48 +02001347 }
1348 }
1349 }
1350}