blob: 7a2184f5dc536d661fa9f5fa07d7d293c4da7fd9 [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>
Arun Patole97dc22e2015-04-06 17:35:38 +053014#include <stdlib.h>
Jamie Madillb1a85f42014-08-19 15:23:24 -040015#include <algorithm>
Arun Patole274f0702015-05-05 13:33:30 +053016#include <vector>
Jamie Madillb1a85f42014-08-19 15:23:24 -040017
Arun Patole274f0702015-05-05 13:33:30 +053018#include "common/mathutil.h"
Arun Patole7fa33552015-06-10 15:15:18 +053019#include "common/matrix_utils.h"
Olli Etuaho3fdec912016-08-18 15:08:06 +030020#include "compiler/translator/Diagnostics.h"
Jamie Madillb1a85f42014-08-19 15:23:24 -040021#include "compiler/translator/HashNames.h"
22#include "compiler/translator/IntermNode.h"
23#include "compiler/translator/SymbolTable.h"
Corentin Wallez509e4562016-08-25 14:55:44 -040024#include "compiler/translator/util.h"
Jamie Madillb1a85f42014-08-19 15:23:24 -040025
Jamie Madill45bcc782016-11-07 13:58:48 -050026namespace sh
27{
28
Jamie Madillb1a85f42014-08-19 15:23:24 -040029namespace
30{
31
Arun Patole9dea48f2015-04-02 11:45:09 +053032const float kPi = 3.14159265358979323846f;
33const float kDegreesToRadiansMultiplier = kPi / 180.0f;
34const float kRadiansToDegreesMultiplier = 180.0f / kPi;
35
Jamie Madillb1a85f42014-08-19 15:23:24 -040036TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
37{
38 return left > right ? left : right;
39}
40
Arun Patole274f0702015-05-05 13:33:30 +053041TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size)
42{
43 TConstantUnion *constUnion = new TConstantUnion[size];
44 for (unsigned int i = 0; i < size; ++i)
45 constUnion[i] = constant;
46
47 return constUnion;
48}
49
Olli Etuahof119a262016-08-19 15:54:22 +030050void UndefinedConstantFoldingError(const TSourceLoc &loc,
51 TOperator op,
52 TBasicType basicType,
53 TDiagnostics *diagnostics,
54 TConstantUnion *result)
Arun Patolebf790422015-05-18 17:53:04 +053055{
Olli Etuahof119a262016-08-19 15:54:22 +030056 diagnostics->warning(loc, "operation result is undefined for the values passed in",
57 GetOperatorString(op), "");
Arun Patolebf790422015-05-18 17:53:04 +053058
59 switch (basicType)
60 {
61 case EbtFloat :
62 result->setFConst(0.0f);
63 break;
64 case EbtInt:
65 result->setIConst(0);
66 break;
67 case EbtUInt:
68 result->setUConst(0u);
69 break;
70 case EbtBool:
71 result->setBConst(false);
72 break;
73 default:
74 break;
75 }
76}
77
Olli Etuaho5c0e0232015-11-11 15:55:59 +020078float VectorLength(const TConstantUnion *paramArray, size_t paramArraySize)
Arun Patole1155ddd2015-06-05 18:04:36 +053079{
80 float result = 0.0f;
81 for (size_t i = 0; i < paramArraySize; i++)
82 {
83 float f = paramArray[i].getFConst();
84 result += f * f;
85 }
86 return sqrtf(result);
87}
88
Olli Etuaho5c0e0232015-11-11 15:55:59 +020089float VectorDotProduct(const TConstantUnion *paramArray1,
90 const TConstantUnion *paramArray2,
91 size_t paramArraySize)
Arun Patole1155ddd2015-06-05 18:04:36 +053092{
93 float result = 0.0f;
94 for (size_t i = 0; i < paramArraySize; i++)
95 result += paramArray1[i].getFConst() * paramArray2[i].getFConst();
96 return result;
97}
98
Olli Etuaho3272a6d2016-08-29 17:54:50 +030099TIntermTyped *CreateFoldedNode(const TConstantUnion *constArray,
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200100 const TIntermTyped *originalNode,
101 TQualifier qualifier)
Olli Etuahob43846e2015-06-02 18:18:57 +0300102{
103 if (constArray == nullptr)
104 {
105 return nullptr;
106 }
107 TIntermTyped *folded = new TIntermConstantUnion(constArray, originalNode->getType());
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200108 folded->getTypePointer()->setQualifier(qualifier);
Olli Etuahob43846e2015-06-02 18:18:57 +0300109 folded->setLine(originalNode->getLine());
110 return folded;
111}
112
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200113angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray,
114 const unsigned int &rows,
115 const unsigned int &cols)
Arun Patole7fa33552015-06-10 15:15:18 +0530116{
117 std::vector<float> elements;
118 for (size_t i = 0; i < rows * cols; i++)
119 elements.push_back(paramArray[i].getFConst());
120 // Transpose is used since the Matrix constructor expects arguments in row-major order,
Olli Etuahod5da5052016-08-29 13:16:55 +0300121 // whereas the paramArray is in column-major order. Rows/cols parameters are also flipped below
122 // so that the created matrix will have the expected dimensions after the transpose.
123 return angle::Matrix<float>(elements, cols, rows).transpose();
Arun Patole7fa33552015-06-10 15:15:18 +0530124}
125
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200126angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray, const unsigned int &size)
Arun Patole7fa33552015-06-10 15:15:18 +0530127{
128 std::vector<float> elements;
129 for (size_t i = 0; i < size * size; i++)
130 elements.push_back(paramArray[i].getFConst());
131 // Transpose is used since the Matrix constructor expects arguments in row-major order,
132 // whereas the paramArray is in column-major order.
133 return angle::Matrix<float>(elements, size).transpose();
134}
135
136void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resultArray)
137{
138 // Transpose is used since the input Matrix is in row-major order,
139 // whereas the actual result should be in column-major order.
140 angle::Matrix<float> result = m.transpose();
141 std::vector<float> resultElements = result.elements();
142 for (size_t i = 0; i < resultElements.size(); i++)
143 resultArray[i].setFConst(resultElements[i]);
144}
145
Jamie Madillb1a85f42014-08-19 15:23:24 -0400146} // namespace anonymous
147
148
149////////////////////////////////////////////////////////////////
150//
151// Member functions of the nodes used for building the tree.
152//
153////////////////////////////////////////////////////////////////
154
Olli Etuahod2a67b92014-10-21 16:42:57 +0300155void TIntermTyped::setTypePreservePrecision(const TType &t)
156{
157 TPrecision precision = getPrecision();
158 mType = t;
159 ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined);
160 mType.setPrecision(precision);
161}
162
Jamie Madillb1a85f42014-08-19 15:23:24 -0400163#define REPLACE_IF_IS(node, type, original, replacement) \
164 if (node == original) { \
165 node = static_cast<type *>(replacement); \
166 return true; \
167 }
168
169bool TIntermLoop::replaceChildNode(
170 TIntermNode *original, TIntermNode *replacement)
171{
Olli Etuaho3cbb27a2016-07-14 11:55:48 +0300172 ASSERT(original != nullptr); // This risks replacing multiple children.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400173 REPLACE_IF_IS(mInit, TIntermNode, original, replacement);
174 REPLACE_IF_IS(mCond, TIntermTyped, original, replacement);
175 REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100176 REPLACE_IF_IS(mBody, TIntermBlock, original, replacement);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400177 return false;
178}
179
Jamie Madillb1a85f42014-08-19 15:23:24 -0400180bool TIntermBranch::replaceChildNode(
181 TIntermNode *original, TIntermNode *replacement)
182{
183 REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement);
184 return false;
185}
186
Olli Etuahob6fa0432016-09-28 16:28:05 +0100187bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
188{
189 ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
190 REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
191 return false;
192}
193
Jamie Madillb1a85f42014-08-19 15:23:24 -0400194bool TIntermBinary::replaceChildNode(
195 TIntermNode *original, TIntermNode *replacement)
196{
197 REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement);
198 REPLACE_IF_IS(mRight, TIntermTyped, original, replacement);
199 return false;
200}
201
Jamie Madillb1a85f42014-08-19 15:23:24 -0400202bool TIntermUnary::replaceChildNode(
203 TIntermNode *original, TIntermNode *replacement)
204{
Olli Etuahoa2234302016-08-31 12:05:39 +0300205 ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
Jamie Madillb1a85f42014-08-19 15:23:24 -0400206 REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
207 return false;
208}
209
Olli Etuaho336b1472016-10-05 16:37:55 +0100210bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
211{
212 REPLACE_IF_IS(mParameters, TIntermAggregate, original, replacement);
213 REPLACE_IF_IS(mBody, TIntermBlock, original, replacement);
214 return false;
215}
216
Jamie Madillb1a85f42014-08-19 15:23:24 -0400217bool TIntermAggregate::replaceChildNode(
218 TIntermNode *original, TIntermNode *replacement)
219{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100220 return replaceChildNodeInternal(original, replacement);
221}
222
223bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
224{
225 return replaceChildNodeInternal(original, replacement);
226}
227
Olli Etuaho13389b62016-10-16 11:48:18 +0100228bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
229{
230 return replaceChildNodeInternal(original, replacement);
231}
232
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100233bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement)
234{
235 for (size_t ii = 0; ii < getSequence()->size(); ++ii)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400236 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100237 REPLACE_IF_IS((*getSequence())[ii], TIntermNode, original, replacement);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400238 }
239 return false;
240}
241
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100242bool TIntermAggregateBase::replaceChildNodeWithMultiple(TIntermNode *original,
243 const TIntermSequence &replacements)
Olli Etuahofc0e2bc2015-04-16 13:39:56 +0300244{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100245 for (auto it = getSequence()->begin(); it < getSequence()->end(); ++it)
Olli Etuahofc0e2bc2015-04-16 13:39:56 +0300246 {
247 if (*it == original)
248 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100249 it = getSequence()->erase(it);
250 getSequence()->insert(it, replacements.begin(), replacements.end());
Olli Etuahofc0e2bc2015-04-16 13:39:56 +0300251 return true;
252 }
253 }
254 return false;
255}
256
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100257bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position,
258 const TIntermSequence &insertions)
Olli Etuahoa6f22092015-05-08 18:31:10 +0300259{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100260 if (position > getSequence()->size())
Olli Etuahoa6f22092015-05-08 18:31:10 +0300261 {
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300262 return false;
Olli Etuahoa6f22092015-05-08 18:31:10 +0300263 }
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100264 auto it = getSequence()->begin() + position;
265 getSequence()->insert(it, insertions.begin(), insertions.end());
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300266 return true;
Olli Etuahoa6f22092015-05-08 18:31:10 +0300267}
268
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200269bool TIntermAggregate::areChildrenConstQualified()
270{
271 for (TIntermNode *&child : mSequence)
272 {
273 TIntermTyped *typed = child->getAsTyped();
274 if (typed && typed->getQualifier() != EvqConst)
275 {
276 return false;
277 }
278 }
279 return true;
280}
281
Olli Etuahod2a67b92014-10-21 16:42:57 +0300282void TIntermAggregate::setPrecisionFromChildren()
283{
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300284 mGotPrecisionFromChildren = true;
Olli Etuahod2a67b92014-10-21 16:42:57 +0300285 if (getBasicType() == EbtBool)
286 {
287 mType.setPrecision(EbpUndefined);
288 return;
289 }
290
291 TPrecision precision = EbpUndefined;
292 TIntermSequence::iterator childIter = mSequence.begin();
293 while (childIter != mSequence.end())
294 {
295 TIntermTyped *typed = (*childIter)->getAsTyped();
296 if (typed)
297 precision = GetHigherPrecision(typed->getPrecision(), precision);
298 ++childIter;
299 }
300 mType.setPrecision(precision);
301}
302
303void TIntermAggregate::setBuiltInFunctionPrecision()
304{
305 // All built-ins returning bool should be handled as ops, not functions.
306 ASSERT(getBasicType() != EbtBool);
307
308 TPrecision precision = EbpUndefined;
309 TIntermSequence::iterator childIter = mSequence.begin();
310 while (childIter != mSequence.end())
311 {
312 TIntermTyped *typed = (*childIter)->getAsTyped();
313 // ESSL spec section 8: texture functions get their precision from the sampler.
314 if (typed && IsSampler(typed->getBasicType()))
315 {
316 precision = typed->getPrecision();
317 break;
318 }
319 ++childIter;
320 }
321 // ESSL 3.0 spec section 8: textureSize always gets highp precision.
322 // All other functions that take a sampler are assumed to be texture functions.
Olli Etuahobd674552016-10-06 13:28:42 +0100323 if (mFunctionInfo.getName().find("textureSize") == 0)
Olli Etuahod2a67b92014-10-21 16:42:57 +0300324 mType.setPrecision(EbpHigh);
325 else
326 mType.setPrecision(precision);
327}
328
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100329void TIntermBlock::appendStatement(TIntermNode *statement)
330{
Olli Etuaho13389b62016-10-16 11:48:18 +0100331 // Declaration nodes with no children can appear if all the declarators just added constants to
332 // the symbol table instead of generating code. They're no-ops so they aren't added to blocks.
333 if (statement != nullptr && (statement->getAsDeclarationNode() == nullptr ||
334 !statement->getAsDeclarationNode()->getSequence()->empty()))
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100335 {
336 mStatements.push_back(statement);
337 }
338}
339
Olli Etuaho13389b62016-10-16 11:48:18 +0100340void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator)
341{
342 ASSERT(declarator != nullptr);
343 ASSERT(declarator->getAsSymbolNode() != nullptr ||
344 (declarator->getAsBinaryNode() != nullptr &&
345 declarator->getAsBinaryNode()->getOp() == EOpInitialize));
346 ASSERT(mDeclarators.empty() ||
347 declarator->getType().sameElementType(mDeclarators.back()->getAsTyped()->getType()));
348 mDeclarators.push_back(declarator);
349}
350
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300351bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
352{
353 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
354 REPLACE_IF_IS(mTrueExpression, TIntermTyped, original, replacement);
355 REPLACE_IF_IS(mFalseExpression, TIntermTyped, original, replacement);
356 return false;
357}
358
Olli Etuaho57961272016-09-14 13:57:46 +0300359bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400360{
361 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100362 REPLACE_IF_IS(mTrueBlock, TIntermBlock, original, replacement);
363 REPLACE_IF_IS(mFalseBlock, TIntermBlock, original, replacement);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400364 return false;
365}
366
Olli Etuahoa3a36662015-02-17 13:46:51 +0200367bool TIntermSwitch::replaceChildNode(
368 TIntermNode *original, TIntermNode *replacement)
369{
370 REPLACE_IF_IS(mInit, TIntermTyped, original, replacement);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100371 REPLACE_IF_IS(mStatementList, TIntermBlock, original, replacement);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200372 return false;
373}
374
375bool TIntermCase::replaceChildNode(
376 TIntermNode *original, TIntermNode *replacement)
377{
378 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
379 return false;
380}
381
Olli Etuahod7a25242015-08-18 13:49:45 +0300382TIntermTyped::TIntermTyped(const TIntermTyped &node) : TIntermNode(), mType(node.mType)
383{
384 // Copy constructor is disallowed for TIntermNode in order to disallow it for subclasses that
385 // don't explicitly allow it, so normal TIntermNode constructor is used to construct the copy.
386 // We need to manually copy any fields of TIntermNode besides handling fields in TIntermTyped.
387 mLine = node.mLine;
388}
389
Olli Etuahod4f4c112016-04-15 15:11:24 +0300390bool TIntermTyped::isConstructorWithOnlyConstantUnionParameters()
391{
392 TIntermAggregate *constructor = getAsAggregate();
393 if (!constructor || !constructor->isConstructor())
394 {
395 return false;
396 }
397 for (TIntermNode *&node : *constructor->getSequence())
398 {
399 if (!node->getAsConstantUnion())
400 return false;
401 }
402 return true;
403}
404
Corentin Wallez509e4562016-08-25 14:55:44 -0400405// static
406TIntermTyped *TIntermTyped::CreateIndexNode(int index)
407{
408 TConstantUnion *u = new TConstantUnion[1];
409 u[0].setIConst(index);
410
411 TType type(EbtInt, EbpUndefined, EvqConst, 1);
412 TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
413 return node;
414}
415
416// static
417TIntermTyped *TIntermTyped::CreateZero(const TType &type)
418{
419 TType constType(type);
420 constType.setQualifier(EvqConst);
421
422 if (!type.isArray() && type.getBasicType() != EbtStruct)
423 {
424 ASSERT(type.isScalar() || type.isVector() || type.isMatrix());
425
426 size_t size = constType.getObjectSize();
427 TConstantUnion *u = new TConstantUnion[size];
428 for (size_t i = 0; i < size; ++i)
429 {
430 switch (type.getBasicType())
431 {
432 case EbtFloat:
433 u[i].setFConst(0.0f);
434 break;
435 case EbtInt:
436 u[i].setIConst(0);
437 break;
438 case EbtUInt:
439 u[i].setUConst(0u);
440 break;
441 case EbtBool:
442 u[i].setBConst(false);
443 break;
444 default:
445 UNREACHABLE();
446 return nullptr;
447 }
448 }
449
450 TIntermConstantUnion *node = new TIntermConstantUnion(u, constType);
451 return node;
452 }
453
454 TIntermAggregate *constructor = new TIntermAggregate(sh::TypeToConstructorOperator(type));
455 constructor->setType(constType);
456
457 if (type.isArray())
458 {
459 TType elementType(type);
460 elementType.clearArrayness();
461
462 size_t arraySize = type.getArraySize();
463 for (size_t i = 0; i < arraySize; ++i)
464 {
465 constructor->getSequence()->push_back(CreateZero(elementType));
466 }
467 }
468 else
469 {
470 ASSERT(type.getBasicType() == EbtStruct);
471
472 TStructure *structure = type.getStruct();
473 for (const auto &field : structure->fields())
474 {
475 constructor->getSequence()->push_back(CreateZero(*field->type()));
476 }
477 }
478
479 return constructor;
480}
481
Olli Etuahod7a25242015-08-18 13:49:45 +0300482TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) : TIntermTyped(node)
483{
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200484 mUnionArrayPointer = node.mUnionArrayPointer;
Olli Etuahod7a25242015-08-18 13:49:45 +0300485}
486
Olli Etuahobd674552016-10-06 13:28:42 +0100487void TFunctionSymbolInfo::setFromFunction(const TFunction &function)
488{
489 setName(function.getMangledName());
490 setId(function.getUniqueId());
491}
492
Olli Etuahod7a25242015-08-18 13:49:45 +0300493TIntermAggregate::TIntermAggregate(const TIntermAggregate &node)
494 : TIntermOperator(node),
Olli Etuahod7a25242015-08-18 13:49:45 +0300495 mUserDefined(node.mUserDefined),
Olli Etuahod7a25242015-08-18 13:49:45 +0300496 mUseEmulatedFunction(node.mUseEmulatedFunction),
Olli Etuahobd674552016-10-06 13:28:42 +0100497 mGotPrecisionFromChildren(node.mGotPrecisionFromChildren),
498 mFunctionInfo(node.mFunctionInfo)
Olli Etuahod7a25242015-08-18 13:49:45 +0300499{
500 for (TIntermNode *child : node.mSequence)
501 {
502 TIntermTyped *typedChild = child->getAsTyped();
503 ASSERT(typedChild != nullptr);
504 TIntermTyped *childCopy = typedChild->deepCopy();
505 mSequence.push_back(childCopy);
506 }
507}
508
Olli Etuahob6fa0432016-09-28 16:28:05 +0100509TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermTyped(node)
510{
511 TIntermTyped *operandCopy = node.mOperand->deepCopy();
512 ASSERT(operandCopy != nullptr);
513 mOperand = operandCopy;
514}
515
Olli Etuahod7a25242015-08-18 13:49:45 +0300516TIntermBinary::TIntermBinary(const TIntermBinary &node)
517 : TIntermOperator(node), mAddIndexClamp(node.mAddIndexClamp)
518{
519 TIntermTyped *leftCopy = node.mLeft->deepCopy();
520 TIntermTyped *rightCopy = node.mRight->deepCopy();
521 ASSERT(leftCopy != nullptr && rightCopy != nullptr);
522 mLeft = leftCopy;
523 mRight = rightCopy;
524}
525
526TIntermUnary::TIntermUnary(const TIntermUnary &node)
527 : TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction)
528{
529 TIntermTyped *operandCopy = node.mOperand->deepCopy();
530 ASSERT(operandCopy != nullptr);
531 mOperand = operandCopy;
532}
533
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300534TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermTyped(node)
Olli Etuahod7a25242015-08-18 13:49:45 +0300535{
Olli Etuahod7a25242015-08-18 13:49:45 +0300536 TIntermTyped *conditionCopy = node.mCondition->deepCopy();
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300537 TIntermTyped *trueCopy = node.mTrueExpression->deepCopy();
538 TIntermTyped *falseCopy = node.mFalseExpression->deepCopy();
Olli Etuahod7a25242015-08-18 13:49:45 +0300539 ASSERT(conditionCopy != nullptr && trueCopy != nullptr && falseCopy != nullptr);
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300540 mCondition = conditionCopy;
541 mTrueExpression = trueCopy;
542 mFalseExpression = falseCopy;
Olli Etuahod7a25242015-08-18 13:49:45 +0300543}
544
Jamie Madillb1a85f42014-08-19 15:23:24 -0400545bool TIntermOperator::isAssignment() const
546{
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300547 return IsAssignment(mOp);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400548}
549
Olli Etuaho8f76bcc2015-06-02 13:54:20 +0300550bool TIntermOperator::isMultiplication() const
551{
552 switch (mOp)
553 {
554 case EOpMul:
555 case EOpMatrixTimesMatrix:
556 case EOpMatrixTimesVector:
557 case EOpMatrixTimesScalar:
558 case EOpVectorTimesMatrix:
559 case EOpVectorTimesScalar:
560 return true;
561 default:
562 return false;
563 }
564}
565
Jamie Madillb1a85f42014-08-19 15:23:24 -0400566//
567// returns true if the operator is for one of the constructors
568//
569bool TIntermOperator::isConstructor() const
570{
571 switch (mOp)
572 {
573 case EOpConstructVec2:
574 case EOpConstructVec3:
575 case EOpConstructVec4:
576 case EOpConstructMat2:
Alexis Hetu07e57df2015-06-16 16:55:52 -0400577 case EOpConstructMat2x3:
578 case EOpConstructMat2x4:
579 case EOpConstructMat3x2:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400580 case EOpConstructMat3:
Alexis Hetu07e57df2015-06-16 16:55:52 -0400581 case EOpConstructMat3x4:
582 case EOpConstructMat4x2:
583 case EOpConstructMat4x3:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400584 case EOpConstructMat4:
585 case EOpConstructFloat:
586 case EOpConstructIVec2:
587 case EOpConstructIVec3:
588 case EOpConstructIVec4:
589 case EOpConstructInt:
590 case EOpConstructUVec2:
591 case EOpConstructUVec3:
592 case EOpConstructUVec4:
593 case EOpConstructUInt:
594 case EOpConstructBVec2:
595 case EOpConstructBVec3:
596 case EOpConstructBVec4:
597 case EOpConstructBool:
598 case EOpConstructStruct:
599 return true;
600 default:
601 return false;
602 }
603}
604
Olli Etuaho1dded802016-08-18 18:13:13 +0300605TOperator TIntermBinary::GetMulOpBasedOnOperands(const TType &left, const TType &right)
606{
607 if (left.isMatrix())
608 {
609 if (right.isMatrix())
610 {
611 return EOpMatrixTimesMatrix;
612 }
613 else
614 {
615 if (right.isVector())
616 {
617 return EOpMatrixTimesVector;
618 }
619 else
620 {
621 return EOpMatrixTimesScalar;
622 }
623 }
624 }
625 else
626 {
627 if (right.isMatrix())
628 {
629 if (left.isVector())
630 {
631 return EOpVectorTimesMatrix;
632 }
633 else
634 {
635 return EOpMatrixTimesScalar;
636 }
637 }
638 else
639 {
640 // Neither operand is a matrix.
641 if (left.isVector() == right.isVector())
642 {
643 // Leave as component product.
644 return EOpMul;
645 }
646 else
647 {
648 return EOpVectorTimesScalar;
649 }
650 }
651 }
652}
653
654TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const TType &right)
655{
656 if (left.isMatrix())
657 {
658 if (right.isMatrix())
659 {
660 return EOpMatrixTimesMatrixAssign;
661 }
662 else
663 {
664 // right should be scalar, but this may not be validated yet.
665 return EOpMatrixTimesScalarAssign;
666 }
667 }
668 else
669 {
670 if (right.isMatrix())
671 {
672 // Left should be a vector, but this may not be validated yet.
673 return EOpVectorTimesMatrixAssign;
674 }
675 else
676 {
677 // Neither operand is a matrix.
678 if (left.isVector() == right.isVector())
679 {
680 // Leave as component product.
681 return EOpMulAssign;
682 }
683 else
684 {
685 // left should be vector and right should be scalar, but this may not be validated
686 // yet.
687 return EOpVectorTimesScalarAssign;
688 }
689 }
690 }
691}
692
Jamie Madillb1a85f42014-08-19 15:23:24 -0400693//
694// Make sure the type of a unary operator is appropriate for its
695// combination of operation and operand type.
696//
Olli Etuahoa2234302016-08-31 12:05:39 +0300697void TIntermUnary::promote()
Jamie Madillb1a85f42014-08-19 15:23:24 -0400698{
Olli Etuahoa2234302016-08-31 12:05:39 +0300699 TQualifier resultQualifier = EvqTemporary;
700 if (mOperand->getQualifier() == EvqConst)
701 resultQualifier = EvqConst;
702
703 unsigned char operandPrimarySize =
704 static_cast<unsigned char>(mOperand->getType().getNominalSize());
Jamie Madillb1a85f42014-08-19 15:23:24 -0400705 switch (mOp)
706 {
Olli Etuahoa2234302016-08-31 12:05:39 +0300707 case EOpFloatBitsToInt:
708 setType(TType(EbtInt, EbpHigh, resultQualifier, operandPrimarySize));
709 break;
710 case EOpFloatBitsToUint:
711 setType(TType(EbtUInt, EbpHigh, resultQualifier, operandPrimarySize));
712 break;
713 case EOpIntBitsToFloat:
714 case EOpUintBitsToFloat:
715 setType(TType(EbtFloat, EbpHigh, resultQualifier, operandPrimarySize));
716 break;
717 case EOpPackSnorm2x16:
718 case EOpPackUnorm2x16:
719 case EOpPackHalf2x16:
720 setType(TType(EbtUInt, EbpHigh, resultQualifier));
721 break;
722 case EOpUnpackSnorm2x16:
723 case EOpUnpackUnorm2x16:
724 setType(TType(EbtFloat, EbpHigh, resultQualifier, 2));
725 break;
726 case EOpUnpackHalf2x16:
727 setType(TType(EbtFloat, EbpMedium, resultQualifier, 2));
728 break;
729 case EOpAny:
730 case EOpAll:
731 setType(TType(EbtBool, EbpUndefined, resultQualifier));
732 break;
733 case EOpLength:
734 case EOpDeterminant:
735 setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier));
736 break;
737 case EOpTranspose:
738 setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier,
739 static_cast<unsigned char>(mOperand->getType().getRows()),
740 static_cast<unsigned char>(mOperand->getType().getCols())));
741 break;
742 case EOpIsInf:
743 case EOpIsNan:
744 setType(TType(EbtBool, EbpUndefined, resultQualifier, operandPrimarySize));
745 break;
746 default:
747 setType(mOperand->getType());
748 mType.setQualifier(resultQualifier);
749 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400750 }
Olli Etuahoa2234302016-08-31 12:05:39 +0300751}
Jamie Madillb1a85f42014-08-19 15:23:24 -0400752
Olli Etuahob6fa0432016-09-28 16:28:05 +0100753TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets)
754 : TIntermTyped(TType(EbtFloat, EbpUndefined)),
755 mOperand(operand),
756 mSwizzleOffsets(swizzleOffsets)
757{
758 ASSERT(mSwizzleOffsets.size() <= 4);
759 promote();
760}
761
Olli Etuahoa2234302016-08-31 12:05:39 +0300762TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand)
763 : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false)
764{
765 promote();
Jamie Madillb1a85f42014-08-19 15:23:24 -0400766}
767
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300768TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right)
769 : TIntermOperator(op), mLeft(left), mRight(right), mAddIndexClamp(false)
770{
771 promote();
772}
773
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300774TIntermTernary::TIntermTernary(TIntermTyped *cond,
775 TIntermTyped *trueExpression,
776 TIntermTyped *falseExpression)
777 : TIntermTyped(trueExpression->getType()),
778 mCondition(cond),
779 mTrueExpression(trueExpression),
780 mFalseExpression(falseExpression)
781{
782 getTypePointer()->setQualifier(
783 TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression));
784}
785
786// static
787TQualifier TIntermTernary::DetermineQualifier(TIntermTyped *cond,
788 TIntermTyped *trueExpression,
789 TIntermTyped *falseExpression)
790{
791 if (cond->getQualifier() == EvqConst && trueExpression->getQualifier() == EvqConst &&
792 falseExpression->getQualifier() == EvqConst)
793 {
794 return EvqConst;
795 }
796 return EvqTemporary;
797}
798
Olli Etuahob6fa0432016-09-28 16:28:05 +0100799void TIntermSwizzle::promote()
800{
801 TQualifier resultQualifier = EvqTemporary;
802 if (mOperand->getQualifier() == EvqConst)
803 resultQualifier = EvqConst;
804
805 auto numFields = mSwizzleOffsets.size();
806 setType(TType(mOperand->getBasicType(), mOperand->getPrecision(), resultQualifier,
807 static_cast<unsigned char>(numFields)));
808}
809
810bool TIntermSwizzle::hasDuplicateOffsets() const
811{
812 int offsetCount[4] = {0u, 0u, 0u, 0u};
813 for (const auto offset : mSwizzleOffsets)
814 {
815 offsetCount[offset]++;
816 if (offsetCount[offset] > 1)
817 {
818 return true;
819 }
820 }
821 return false;
822}
823
824void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const
825{
826 for (const int offset : mSwizzleOffsets)
827 {
828 switch (offset)
829 {
830 case 0:
831 *out << "x";
832 break;
833 case 1:
834 *out << "y";
835 break;
836 case 2:
837 *out << "z";
838 break;
839 case 3:
840 *out << "w";
841 break;
842 default:
843 UNREACHABLE();
844 }
845 }
846}
847
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100848TQualifier TIntermBinary::GetCommaQualifier(int shaderVersion,
849 const TIntermTyped *left,
850 const TIntermTyped *right)
851{
852 // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
853 if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
854 right->getQualifier() != EvqConst)
855 {
856 return EvqTemporary;
857 }
858 return EvqConst;
859}
Olli Etuahob6fa0432016-09-28 16:28:05 +0100860
861// Establishes the type of the result of the binary operation.
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300862void TIntermBinary::promote()
Jamie Madillb1a85f42014-08-19 15:23:24 -0400863{
Olli Etuaho1dded802016-08-18 18:13:13 +0300864 ASSERT(!isMultiplication() ||
865 mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType()));
866
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100867 // Comma is handled as a special case.
868 if (mOp == EOpComma)
869 {
870 setType(mRight->getType());
871 return;
872 }
873
Jamie Madillb1a85f42014-08-19 15:23:24 -0400874 // Base assumption: just make the type the same as the left
875 // operand. Then only deviations from this need be coded.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400876 setType(mLeft->getType());
877
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200878 TQualifier resultQualifier = EvqConst;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400879 // Binary operations results in temporary variables unless both
880 // operands are const.
881 if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst)
882 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200883 resultQualifier = EvqTemporary;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400884 getTypePointer()->setQualifier(EvqTemporary);
885 }
886
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300887 // Handle indexing ops.
888 switch (mOp)
889 {
890 case EOpIndexDirect:
891 case EOpIndexIndirect:
892 if (mLeft->isArray())
893 {
894 mType.clearArrayness();
895 }
896 else if (mLeft->isMatrix())
897 {
898 setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier,
899 static_cast<unsigned char>(mLeft->getRows())));
900 }
901 else if (mLeft->isVector())
902 {
903 setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier));
904 }
905 else
906 {
907 UNREACHABLE();
908 }
909 return;
910 case EOpIndexDirectStruct:
911 {
912 const TFieldList &fields = mLeft->getType().getStruct()->fields();
913 const int i = mRight->getAsConstantUnion()->getIConst(0);
914 setType(*fields[i]->type());
915 getTypePointer()->setQualifier(resultQualifier);
916 return;
917 }
918 case EOpIndexDirectInterfaceBlock:
919 {
920 const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields();
921 const int i = mRight->getAsConstantUnion()->getIConst(0);
922 setType(*fields[i]->type());
923 getTypePointer()->setQualifier(resultQualifier);
924 return;
925 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300926 default:
927 break;
928 }
929
930 ASSERT(mLeft->isArray() == mRight->isArray());
931
932 // The result gets promoted to the highest precision.
933 TPrecision higherPrecision = GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision());
934 getTypePointer()->setPrecision(higherPrecision);
935
Jamie Madillb1a85f42014-08-19 15:23:24 -0400936 const int nominalSize =
937 std::max(mLeft->getNominalSize(), mRight->getNominalSize());
938
939 //
940 // All scalars or structs. Code after this test assumes this case is removed!
941 //
942 if (nominalSize == 1)
943 {
944 switch (mOp)
945 {
946 //
947 // Promote to conditional
948 //
949 case EOpEqual:
950 case EOpNotEqual:
951 case EOpLessThan:
952 case EOpGreaterThan:
953 case EOpLessThanEqual:
954 case EOpGreaterThanEqual:
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300955 setType(TType(EbtBool, EbpUndefined, resultQualifier));
956 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400957
958 //
959 // And and Or operate on conditionals
960 //
961 case EOpLogicalAnd:
Olli Etuaho47fd36a2015-03-19 14:22:24 +0200962 case EOpLogicalXor:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400963 case EOpLogicalOr:
Olli Etuaho47fd36a2015-03-19 14:22:24 +0200964 ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool);
Olli Etuahoc9550582016-08-29 17:56:22 +0300965 setType(TType(EbtBool, EbpUndefined, resultQualifier));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400966 break;
967
968 default:
969 break;
970 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300971 return;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400972 }
973
974 // If we reach here, at least one of the operands is vector or matrix.
975 // The other operand could be a scalar, vector, or matrix.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400976 TBasicType basicType = mLeft->getBasicType();
Olli Etuaho1dded802016-08-18 18:13:13 +0300977
Jamie Madillb1a85f42014-08-19 15:23:24 -0400978 switch (mOp)
979 {
Olli Etuaho1dded802016-08-18 18:13:13 +0300980 case EOpMul:
981 break;
982 case EOpMatrixTimesScalar:
983 if (mRight->isMatrix())
Jamie Madillb1a85f42014-08-19 15:23:24 -0400984 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200985 setType(TType(basicType, higherPrecision, resultQualifier,
986 static_cast<unsigned char>(mRight->getCols()),
987 static_cast<unsigned char>(mRight->getRows())));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400988 }
Olli Etuaho1dded802016-08-18 18:13:13 +0300989 break;
990 case EOpMatrixTimesVector:
991 setType(TType(basicType, higherPrecision, resultQualifier,
992 static_cast<unsigned char>(mLeft->getRows()), 1));
993 break;
994 case EOpMatrixTimesMatrix:
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200995 setType(TType(basicType, higherPrecision, resultQualifier,
996 static_cast<unsigned char>(mRight->getCols()),
997 static_cast<unsigned char>(mLeft->getRows())));
Olli Etuaho1dded802016-08-18 18:13:13 +0300998 break;
999 case EOpVectorTimesScalar:
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001000 setType(TType(basicType, higherPrecision, resultQualifier,
Olli Etuaho1dded802016-08-18 18:13:13 +03001001 static_cast<unsigned char>(nominalSize), 1));
1002 break;
1003 case EOpVectorTimesMatrix:
1004 setType(TType(basicType, higherPrecision, resultQualifier,
1005 static_cast<unsigned char>(mRight->getCols()), 1));
1006 break;
1007 case EOpMulAssign:
1008 case EOpVectorTimesScalarAssign:
1009 case EOpVectorTimesMatrixAssign:
1010 case EOpMatrixTimesScalarAssign:
1011 case EOpMatrixTimesMatrixAssign:
1012 ASSERT(mOp == GetMulAssignOpBasedOnOperands(mLeft->getType(), mRight->getType()));
1013 break;
1014 case EOpAssign:
1015 case EOpInitialize:
Olli Etuaho1dded802016-08-18 18:13:13 +03001016 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
1017 (mLeft->getSecondarySize() == mRight->getSecondarySize()));
1018 break;
1019 case EOpAdd:
1020 case EOpSub:
1021 case EOpDiv:
1022 case EOpIMod:
1023 case EOpBitShiftLeft:
1024 case EOpBitShiftRight:
1025 case EOpBitwiseAnd:
1026 case EOpBitwiseXor:
1027 case EOpBitwiseOr:
1028 case EOpAddAssign:
1029 case EOpSubAssign:
1030 case EOpDivAssign:
1031 case EOpIModAssign:
1032 case EOpBitShiftLeftAssign:
1033 case EOpBitShiftRightAssign:
1034 case EOpBitwiseAndAssign:
1035 case EOpBitwiseXorAssign:
1036 case EOpBitwiseOrAssign:
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001037 {
1038 const int secondarySize =
1039 std::max(mLeft->getSecondarySize(), mRight->getSecondarySize());
1040 setType(TType(basicType, higherPrecision, resultQualifier,
1041 static_cast<unsigned char>(nominalSize),
1042 static_cast<unsigned char>(secondarySize)));
1043 ASSERT(!mLeft->isArray() && !mRight->isArray());
Olli Etuaho1dded802016-08-18 18:13:13 +03001044 break;
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001045 }
Olli Etuaho1dded802016-08-18 18:13:13 +03001046 case EOpEqual:
1047 case EOpNotEqual:
1048 case EOpLessThan:
1049 case EOpGreaterThan:
1050 case EOpLessThanEqual:
1051 case EOpGreaterThanEqual:
1052 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
1053 (mLeft->getSecondarySize() == mRight->getSecondarySize()));
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001054 setType(TType(EbtBool, EbpUndefined, resultQualifier));
Olli Etuaho1dded802016-08-18 18:13:13 +03001055 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001056
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001057 case EOpIndexDirect:
1058 case EOpIndexIndirect:
1059 case EOpIndexDirectInterfaceBlock:
1060 case EOpIndexDirectStruct:
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001061 // These ops should be already fully handled.
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001062 UNREACHABLE();
1063 break;
Olli Etuaho1dded802016-08-18 18:13:13 +03001064 default:
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001065 UNREACHABLE();
1066 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001067 }
Jamie Madillb1a85f42014-08-19 15:23:24 -04001068}
1069
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001070const TConstantUnion *TIntermConstantUnion::foldIndexing(int index)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001071{
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001072 if (isArray())
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001073 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001074 ASSERT(index < static_cast<int>(getType().getArraySize()));
1075 TType arrayElementType = getType();
1076 arrayElementType.clearArrayness();
1077 size_t arrayElementSize = arrayElementType.getObjectSize();
1078 return &mUnionArrayPointer[arrayElementSize * index];
1079 }
1080 else if (isMatrix())
1081 {
1082 ASSERT(index < getType().getCols());
1083 int size = getType().getRows();
1084 return &mUnionArrayPointer[size * index];
1085 }
1086 else if (isVector())
1087 {
1088 ASSERT(index < getType().getNominalSize());
1089 return &mUnionArrayPointer[index];
1090 }
1091 else
1092 {
1093 UNREACHABLE();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001094 return nullptr;
1095 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001096}
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001097
Olli Etuahob6fa0432016-09-28 16:28:05 +01001098TIntermTyped *TIntermSwizzle::fold()
1099{
1100 TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
1101 if (operandConstant == nullptr)
1102 {
1103 return nullptr;
1104 }
1105
1106 TConstantUnion *constArray = new TConstantUnion[mSwizzleOffsets.size()];
1107 for (size_t i = 0; i < mSwizzleOffsets.size(); ++i)
1108 {
1109 constArray[i] = *operandConstant->foldIndexing(mSwizzleOffsets.at(i));
1110 }
1111 return CreateFoldedNode(constArray, this, mType.getQualifier());
1112}
1113
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001114TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
1115{
1116 TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion();
1117 TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion();
1118 switch (mOp)
1119 {
1120 case EOpIndexDirect:
1121 {
1122 if (leftConstant == nullptr || rightConstant == nullptr)
1123 {
1124 return nullptr;
1125 }
1126 int index = rightConstant->getIConst(0);
1127
1128 const TConstantUnion *constArray = leftConstant->foldIndexing(index);
1129 return CreateFoldedNode(constArray, this, mType.getQualifier());
1130 }
1131 case EOpIndexDirectStruct:
1132 {
1133 if (leftConstant == nullptr || rightConstant == nullptr)
1134 {
1135 return nullptr;
1136 }
1137 const TFieldList &fields = mLeft->getType().getStruct()->fields();
1138 size_t index = static_cast<size_t>(rightConstant->getIConst(0));
1139
1140 size_t previousFieldsSize = 0;
1141 for (size_t i = 0; i < index; ++i)
1142 {
1143 previousFieldsSize += fields[i]->type()->getObjectSize();
1144 }
1145
1146 const TConstantUnion *constArray = leftConstant->getUnionArrayPointer();
1147 return CreateFoldedNode(constArray + previousFieldsSize, this, mType.getQualifier());
1148 }
1149 case EOpIndexIndirect:
1150 case EOpIndexDirectInterfaceBlock:
1151 // Can never be constant folded.
1152 return nullptr;
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001153 default:
1154 {
1155 if (leftConstant == nullptr || rightConstant == nullptr)
1156 {
1157 return nullptr;
1158 }
Jamie Madill5db69f52016-09-15 12:47:32 -04001159 TConstantUnion *constArray =
1160 leftConstant->foldBinary(mOp, rightConstant, diagnostics, mLeft->getLine());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001161
1162 // Nodes may be constant folded without being qualified as constant.
1163 return CreateFoldedNode(constArray, this, mType.getQualifier());
1164 }
1165 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001166}
1167
Olli Etuahof119a262016-08-19 15:54:22 +03001168TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
Olli Etuaho95310b02015-06-02 17:43:38 +03001169{
1170 TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
1171 if (operandConstant == nullptr)
1172 {
1173 return nullptr;
1174 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301175
1176 TConstantUnion *constArray = nullptr;
1177 switch (mOp)
1178 {
1179 case EOpAny:
1180 case EOpAll:
1181 case EOpLength:
1182 case EOpTranspose:
1183 case EOpDeterminant:
1184 case EOpInverse:
1185 case EOpPackSnorm2x16:
1186 case EOpUnpackSnorm2x16:
1187 case EOpPackUnorm2x16:
1188 case EOpUnpackUnorm2x16:
1189 case EOpPackHalf2x16:
1190 case EOpUnpackHalf2x16:
Olli Etuahof119a262016-08-19 15:54:22 +03001191 constArray = operandConstant->foldUnaryNonComponentWise(mOp);
1192 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301193 default:
Olli Etuahof119a262016-08-19 15:54:22 +03001194 constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics);
1195 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301196 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001197
1198 // Nodes may be constant folded without being qualified as constant.
Olli Etuahoc9550582016-08-29 17:56:22 +03001199 return CreateFoldedNode(constArray, this, mType.getQualifier());
Olli Etuahob43846e2015-06-02 18:18:57 +03001200}
1201
Olli Etuahof119a262016-08-19 15:54:22 +03001202TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics)
Olli Etuahob43846e2015-06-02 18:18:57 +03001203{
1204 // Make sure that all params are constant before actual constant folding.
1205 for (auto *param : *getSequence())
Olli Etuaho95310b02015-06-02 17:43:38 +03001206 {
Olli Etuahob43846e2015-06-02 18:18:57 +03001207 if (param->getAsConstantUnion() == nullptr)
1208 {
1209 return nullptr;
1210 }
Olli Etuaho95310b02015-06-02 17:43:38 +03001211 }
Olli Etuaho1d122782015-11-06 15:35:17 +02001212 TConstantUnion *constArray = nullptr;
1213 if (isConstructor())
Olli Etuahof119a262016-08-19 15:54:22 +03001214 constArray = TIntermConstantUnion::FoldAggregateConstructor(this);
Olli Etuaho1d122782015-11-06 15:35:17 +02001215 else
Olli Etuahof119a262016-08-19 15:54:22 +03001216 constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001217
1218 // Nodes may be constant folded without being qualified as constant.
1219 TQualifier resultQualifier = areChildrenConstQualified() ? EvqConst : EvqTemporary;
1220 return CreateFoldedNode(constArray, this, resultQualifier);
Olli Etuaho95310b02015-06-02 17:43:38 +03001221}
1222
Jamie Madillb1a85f42014-08-19 15:23:24 -04001223//
1224// The fold functions see if an operation on a constant can be done in place,
1225// without generating run-time code.
1226//
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001227// Returns the constant value to keep using or nullptr.
Jamie Madillb1a85f42014-08-19 15:23:24 -04001228//
Olli Etuaho3fdec912016-08-18 15:08:06 +03001229TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op,
1230 TIntermConstantUnion *rightNode,
Jamie Madill5db69f52016-09-15 12:47:32 -04001231 TDiagnostics *diagnostics,
1232 const TSourceLoc &line)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001233{
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001234 const TConstantUnion *leftArray = getUnionArrayPointer();
1235 const TConstantUnion *rightArray = rightNode->getUnionArrayPointer();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001236
Olli Etuahof119a262016-08-19 15:54:22 +03001237 ASSERT(leftArray && rightArray);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001238
1239 size_t objectSize = getType().getObjectSize();
1240
1241 // for a case like float f = vec4(2, 3, 4, 5) + 1.2;
1242 if (rightNode->getType().getObjectSize() == 1 && objectSize > 1)
1243 {
1244 rightArray = Vectorize(*rightNode->getUnionArrayPointer(), objectSize);
1245 }
1246 else if (rightNode->getType().getObjectSize() > 1 && objectSize == 1)
1247 {
1248 // for a case like float f = 1.2 + vec4(2, 3, 4, 5);
1249 leftArray = Vectorize(*getUnionArrayPointer(), rightNode->getType().getObjectSize());
1250 objectSize = rightNode->getType().getObjectSize();
1251 }
1252
1253 TConstantUnion *resultArray = nullptr;
1254
1255 switch(op)
1256 {
1257 case EOpAdd:
1258 resultArray = new TConstantUnion[objectSize];
1259 for (size_t i = 0; i < objectSize; i++)
Jamie Madill5db69f52016-09-15 12:47:32 -04001260 resultArray[i] = TConstantUnion::add(leftArray[i], rightArray[i], diagnostics, line);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001261 break;
1262 case EOpSub:
1263 resultArray = new TConstantUnion[objectSize];
1264 for (size_t i = 0; i < objectSize; i++)
Jamie Madill5db69f52016-09-15 12:47:32 -04001265 resultArray[i] = TConstantUnion::sub(leftArray[i], rightArray[i], diagnostics, line);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001266 break;
1267
1268 case EOpMul:
1269 case EOpVectorTimesScalar:
1270 case EOpMatrixTimesScalar:
1271 resultArray = new TConstantUnion[objectSize];
1272 for (size_t i = 0; i < objectSize; i++)
Jamie Madill5db69f52016-09-15 12:47:32 -04001273 resultArray[i] = TConstantUnion::mul(leftArray[i], rightArray[i], diagnostics, line);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001274 break;
1275
1276 case EOpMatrixTimesMatrix:
1277 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001278 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001279 ASSERT(getType().getBasicType() == EbtFloat && rightNode->getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001280
1281 const int leftCols = getCols();
1282 const int leftRows = getRows();
1283 const int rightCols = rightNode->getType().getCols();
1284 const int rightRows = rightNode->getType().getRows();
1285 const int resultCols = rightCols;
1286 const int resultRows = leftRows;
1287
1288 resultArray = new TConstantUnion[resultCols * resultRows];
1289 for (int row = 0; row < resultRows; row++)
1290 {
1291 for (int column = 0; column < resultCols; column++)
1292 {
1293 resultArray[resultRows * column + row].setFConst(0.0f);
1294 for (int i = 0; i < leftCols; i++)
1295 {
1296 resultArray[resultRows * column + row].setFConst(
1297 resultArray[resultRows * column + row].getFConst() +
1298 leftArray[i * leftRows + row].getFConst() *
1299 rightArray[column * rightRows + i].getFConst());
1300 }
1301 }
1302 }
1303 }
1304 break;
1305
1306 case EOpDiv:
1307 case EOpIMod:
1308 {
1309 resultArray = new TConstantUnion[objectSize];
1310 for (size_t i = 0; i < objectSize; i++)
1311 {
1312 switch (getType().getBasicType())
1313 {
1314 case EbtFloat:
Olli Etuaho2d736652016-11-30 10:37:49 +00001315 {
1316 ASSERT(op == EOpDiv);
1317 float dividend = leftArray[i].getFConst();
1318 float divisor = rightArray[i].getFConst();
1319 if (divisor == 0.0f)
1320 {
1321 if (dividend == 0.0f)
1322 {
1323 diagnostics->warning(
1324 getLine(),
1325 "Zero divided by zero during constant folding generated NaN", "/",
1326 "");
1327 resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
1328 }
1329 else
1330 {
1331 diagnostics->warning(
1332 getLine(), "Divide by zero during constant folding", "/", "");
1333 bool negativeResult = std::signbit(dividend) != std::signbit(divisor);
1334 resultArray[i].setFConst(
1335 negativeResult ? -std::numeric_limits<float>::infinity()
1336 : std::numeric_limits<float>::infinity());
1337 }
1338 }
1339 else if (gl::isInf(dividend) && gl::isInf(divisor))
1340 {
1341 diagnostics->warning(
1342 getLine(),
1343 "Infinity divided by infinity during constant folding generated NaN",
1344 "/", "");
1345 resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
1346 }
1347 else
1348 {
1349 float result = dividend / divisor;
1350 if (!gl::isInf(dividend) && gl::isInf(result))
1351 {
1352 diagnostics->warning(
1353 getLine(), "Constant folded division overflowed to infinity", "/",
1354 "");
1355 }
1356 resultArray[i].setFConst(result);
1357 }
1358 break;
1359 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001360 case EbtInt:
1361 if (rightArray[i] == 0)
1362 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001363 diagnostics->warning(
1364 getLine(), "Divide by zero error during constant folding", "/", "");
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001365 resultArray[i].setIConst(INT_MAX);
1366 }
1367 else
1368 {
Olli Etuahod4453572016-09-27 13:21:46 +01001369 int lhs = leftArray[i].getIConst();
1370 int divisor = rightArray[i].getIConst();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001371 if (op == EOpDiv)
1372 {
Olli Etuahod4453572016-09-27 13:21:46 +01001373 // Check for the special case where the minimum representable number is
1374 // divided by -1. If left alone this leads to integer overflow in C++.
1375 // ESSL 3.00.6 section 4.1.3 Integers:
1376 // "However, for the case where the minimum representable value is
1377 // divided by -1, it is allowed to return either the minimum
1378 // representable value or the maximum representable value."
1379 if (lhs == -0x7fffffff - 1 && divisor == -1)
1380 {
1381 resultArray[i].setIConst(0x7fffffff);
1382 }
1383 else
1384 {
1385 resultArray[i].setIConst(lhs / divisor);
1386 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001387 }
1388 else
1389 {
1390 ASSERT(op == EOpIMod);
Olli Etuahod4453572016-09-27 13:21:46 +01001391 if (lhs < 0 || divisor < 0)
1392 {
1393 // ESSL 3.00.6 section 5.9: Results of modulus are undefined when
1394 // either one of the operands is negative.
1395 diagnostics->warning(getLine(),
1396 "Negative modulus operator operand "
1397 "encountered during constant folding",
1398 "%", "");
1399 resultArray[i].setIConst(0);
1400 }
1401 else
1402 {
1403 resultArray[i].setIConst(lhs % divisor);
1404 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001405 }
1406 }
1407 break;
1408
1409 case EbtUInt:
1410 if (rightArray[i] == 0)
1411 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001412 diagnostics->warning(
1413 getLine(), "Divide by zero error during constant folding", "/", "");
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001414 resultArray[i].setUConst(UINT_MAX);
1415 }
1416 else
1417 {
1418 if (op == EOpDiv)
1419 {
1420 resultArray[i].setUConst(leftArray[i].getUConst() / rightArray[i].getUConst());
1421 }
1422 else
1423 {
1424 ASSERT(op == EOpIMod);
1425 resultArray[i].setUConst(leftArray[i].getUConst() % rightArray[i].getUConst());
1426 }
1427 }
1428 break;
1429
1430 default:
Olli Etuaho3fdec912016-08-18 15:08:06 +03001431 UNREACHABLE();
1432 return nullptr;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001433 }
1434 }
1435 }
1436 break;
1437
1438 case EOpMatrixTimesVector:
1439 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001440 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001441 ASSERT(rightNode->getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001442
1443 const int matrixCols = getCols();
1444 const int matrixRows = getRows();
1445
1446 resultArray = new TConstantUnion[matrixRows];
1447
1448 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
1449 {
1450 resultArray[matrixRow].setFConst(0.0f);
1451 for (int col = 0; col < matrixCols; col++)
1452 {
1453 resultArray[matrixRow].setFConst(resultArray[matrixRow].getFConst() +
1454 leftArray[col * matrixRows + matrixRow].getFConst() *
1455 rightArray[col].getFConst());
1456 }
1457 }
1458 }
1459 break;
1460
1461 case EOpVectorTimesMatrix:
1462 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001463 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001464 ASSERT(getType().getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001465
1466 const int matrixCols = rightNode->getType().getCols();
1467 const int matrixRows = rightNode->getType().getRows();
1468
1469 resultArray = new TConstantUnion[matrixCols];
1470
1471 for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++)
1472 {
1473 resultArray[matrixCol].setFConst(0.0f);
1474 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
1475 {
1476 resultArray[matrixCol].setFConst(resultArray[matrixCol].getFConst() +
1477 leftArray[matrixRow].getFConst() *
1478 rightArray[matrixCol * matrixRows + matrixRow].getFConst());
1479 }
1480 }
1481 }
1482 break;
1483
1484 case EOpLogicalAnd:
1485 {
1486 resultArray = new TConstantUnion[objectSize];
1487 for (size_t i = 0; i < objectSize; i++)
1488 {
1489 resultArray[i] = leftArray[i] && rightArray[i];
1490 }
1491 }
1492 break;
1493
1494 case EOpLogicalOr:
1495 {
1496 resultArray = new TConstantUnion[objectSize];
1497 for (size_t i = 0; i < objectSize; i++)
1498 {
1499 resultArray[i] = leftArray[i] || rightArray[i];
1500 }
1501 }
1502 break;
1503
1504 case EOpLogicalXor:
1505 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001506 ASSERT(getType().getBasicType() == EbtBool);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001507 resultArray = new TConstantUnion[objectSize];
1508 for (size_t i = 0; i < objectSize; i++)
1509 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001510 resultArray[i].setBConst(leftArray[i] != rightArray[i]);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001511 }
1512 }
1513 break;
1514
1515 case EOpBitwiseAnd:
1516 resultArray = new TConstantUnion[objectSize];
1517 for (size_t i = 0; i < objectSize; i++)
1518 resultArray[i] = leftArray[i] & rightArray[i];
1519 break;
1520 case EOpBitwiseXor:
1521 resultArray = new TConstantUnion[objectSize];
1522 for (size_t i = 0; i < objectSize; i++)
1523 resultArray[i] = leftArray[i] ^ rightArray[i];
1524 break;
1525 case EOpBitwiseOr:
1526 resultArray = new TConstantUnion[objectSize];
1527 for (size_t i = 0; i < objectSize; i++)
1528 resultArray[i] = leftArray[i] | rightArray[i];
1529 break;
1530 case EOpBitShiftLeft:
1531 resultArray = new TConstantUnion[objectSize];
1532 for (size_t i = 0; i < objectSize; i++)
Jamie Madill596018c2016-09-21 12:57:03 -04001533 resultArray[i] = TConstantUnion::lshift(leftArray[i], rightArray[i], diagnostics, line);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001534 break;
1535 case EOpBitShiftRight:
1536 resultArray = new TConstantUnion[objectSize];
1537 for (size_t i = 0; i < objectSize; i++)
Jamie Madill596018c2016-09-21 12:57:03 -04001538 resultArray[i] = TConstantUnion::rshift(leftArray[i], rightArray[i], diagnostics, line);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001539 break;
1540
1541 case EOpLessThan:
1542 ASSERT(objectSize == 1);
1543 resultArray = new TConstantUnion[1];
1544 resultArray->setBConst(*leftArray < *rightArray);
1545 break;
1546
1547 case EOpGreaterThan:
1548 ASSERT(objectSize == 1);
1549 resultArray = new TConstantUnion[1];
1550 resultArray->setBConst(*leftArray > *rightArray);
1551 break;
1552
1553 case EOpLessThanEqual:
1554 ASSERT(objectSize == 1);
1555 resultArray = new TConstantUnion[1];
1556 resultArray->setBConst(!(*leftArray > *rightArray));
1557 break;
1558
1559 case EOpGreaterThanEqual:
1560 ASSERT(objectSize == 1);
1561 resultArray = new TConstantUnion[1];
1562 resultArray->setBConst(!(*leftArray < *rightArray));
1563 break;
1564
1565 case EOpEqual:
1566 case EOpNotEqual:
1567 {
1568 resultArray = new TConstantUnion[1];
1569 bool equal = true;
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001570 for (size_t i = 0; i < objectSize; i++)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001571 {
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001572 if (leftArray[i] != rightArray[i])
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001573 {
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001574 equal = false;
1575 break; // break out of for loop
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001576 }
1577 }
1578 if (op == EOpEqual)
1579 {
1580 resultArray->setBConst(equal);
1581 }
1582 else
1583 {
1584 resultArray->setBConst(!equal);
1585 }
1586 }
1587 break;
1588
1589 default:
Olli Etuaho3fdec912016-08-18 15:08:06 +03001590 UNREACHABLE();
1591 return nullptr;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001592 }
1593 return resultArray;
1594}
1595
Olli Etuahof119a262016-08-19 15:54:22 +03001596// The fold functions do operations on a constant at GLSL compile time, without generating run-time
1597// code. Returns the constant value to keep using. Nullptr should not be returned.
1598TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op)
Jamie Madillb1a85f42014-08-19 15:23:24 -04001599{
Olli Etuahof119a262016-08-19 15:54:22 +03001600 // Do operations where the return type may have a different number of components compared to the
1601 // operand type.
Jamie Madillb1a85f42014-08-19 15:23:24 -04001602
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001603 const TConstantUnion *operandArray = getUnionArrayPointer();
Olli Etuahof119a262016-08-19 15:54:22 +03001604 ASSERT(operandArray);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301605
1606 size_t objectSize = getType().getObjectSize();
1607 TConstantUnion *resultArray = nullptr;
1608 switch (op)
1609 {
Olli Etuahof119a262016-08-19 15:54:22 +03001610 case EOpAny:
1611 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301612 resultArray = new TConstantUnion();
1613 resultArray->setBConst(false);
1614 for (size_t i = 0; i < objectSize; i++)
1615 {
1616 if (operandArray[i].getBConst())
1617 {
1618 resultArray->setBConst(true);
1619 break;
1620 }
1621 }
1622 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301623
Olli Etuahof119a262016-08-19 15:54:22 +03001624 case EOpAll:
1625 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301626 resultArray = new TConstantUnion();
1627 resultArray->setBConst(true);
1628 for (size_t i = 0; i < objectSize; i++)
1629 {
1630 if (!operandArray[i].getBConst())
1631 {
1632 resultArray->setBConst(false);
1633 break;
1634 }
1635 }
1636 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301637
Olli Etuahof119a262016-08-19 15:54:22 +03001638 case EOpLength:
1639 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301640 resultArray = new TConstantUnion();
1641 resultArray->setFConst(VectorLength(operandArray, objectSize));
1642 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301643
Olli Etuahof119a262016-08-19 15:54:22 +03001644 case EOpTranspose:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301645 {
Olli Etuahof119a262016-08-19 15:54:22 +03001646 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301647 resultArray = new TConstantUnion[objectSize];
1648 angle::Matrix<float> result =
Olli Etuahod5da5052016-08-29 13:16:55 +03001649 GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose();
Arun Patoleab2b9a22015-07-06 18:27:56 +05301650 SetUnionArrayFromMatrix(result, resultArray);
1651 break;
1652 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301653
Olli Etuahof119a262016-08-19 15:54:22 +03001654 case EOpDeterminant:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301655 {
Olli Etuahof119a262016-08-19 15:54:22 +03001656 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301657 unsigned int size = getType().getNominalSize();
1658 ASSERT(size >= 2 && size <= 4);
1659 resultArray = new TConstantUnion();
1660 resultArray->setFConst(GetMatrix(operandArray, size).determinant());
1661 break;
1662 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301663
Olli Etuahof119a262016-08-19 15:54:22 +03001664 case EOpInverse:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301665 {
Olli Etuahof119a262016-08-19 15:54:22 +03001666 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301667 unsigned int size = getType().getNominalSize();
1668 ASSERT(size >= 2 && size <= 4);
Olli Etuahof119a262016-08-19 15:54:22 +03001669 resultArray = new TConstantUnion[objectSize];
Arun Patoleab2b9a22015-07-06 18:27:56 +05301670 angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
1671 SetUnionArrayFromMatrix(result, resultArray);
1672 break;
1673 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301674
Olli Etuahof119a262016-08-19 15:54:22 +03001675 case EOpPackSnorm2x16:
1676 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301677 ASSERT(getType().getNominalSize() == 2);
1678 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001679 resultArray->setUConst(
1680 gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301681 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301682
Olli Etuahof119a262016-08-19 15:54:22 +03001683 case EOpUnpackSnorm2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301684 {
Olli Etuahof119a262016-08-19 15:54:22 +03001685 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301686 resultArray = new TConstantUnion[2];
1687 float f1, f2;
1688 gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
1689 resultArray[0].setFConst(f1);
1690 resultArray[1].setFConst(f2);
1691 break;
1692 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301693
Olli Etuahof119a262016-08-19 15:54:22 +03001694 case EOpPackUnorm2x16:
1695 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301696 ASSERT(getType().getNominalSize() == 2);
1697 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001698 resultArray->setUConst(
1699 gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301700 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301701
Olli Etuahof119a262016-08-19 15:54:22 +03001702 case EOpUnpackUnorm2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301703 {
Olli Etuahof119a262016-08-19 15:54:22 +03001704 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301705 resultArray = new TConstantUnion[2];
1706 float f1, f2;
1707 gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
1708 resultArray[0].setFConst(f1);
1709 resultArray[1].setFConst(f2);
1710 break;
1711 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301712
Olli Etuahof119a262016-08-19 15:54:22 +03001713 case EOpPackHalf2x16:
1714 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301715 ASSERT(getType().getNominalSize() == 2);
1716 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001717 resultArray->setUConst(
1718 gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301719 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301720
Olli Etuahof119a262016-08-19 15:54:22 +03001721 case EOpUnpackHalf2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301722 {
Olli Etuahof119a262016-08-19 15:54:22 +03001723 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301724 resultArray = new TConstantUnion[2];
1725 float f1, f2;
1726 gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2);
1727 resultArray[0].setFConst(f1);
1728 resultArray[1].setFConst(f2);
1729 break;
1730 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301731
Olli Etuahof119a262016-08-19 15:54:22 +03001732 default:
1733 UNREACHABLE();
1734 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301735 }
1736
1737 return resultArray;
1738}
1739
Olli Etuahof119a262016-08-19 15:54:22 +03001740TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op,
1741 TDiagnostics *diagnostics)
Arun Patoleab2b9a22015-07-06 18:27:56 +05301742{
Olli Etuahof119a262016-08-19 15:54:22 +03001743 // Do unary operations where each component of the result is computed based on the corresponding
1744 // component of the operand. Also folds normalize, though the divisor in that case takes all
1745 // components into account.
Arun Patoleab2b9a22015-07-06 18:27:56 +05301746
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001747 const TConstantUnion *operandArray = getUnionArrayPointer();
Olli Etuahof119a262016-08-19 15:54:22 +03001748 ASSERT(operandArray);
Jamie Madillb1a85f42014-08-19 15:23:24 -04001749
1750 size_t objectSize = getType().getObjectSize();
1751
Arun Patoleab2b9a22015-07-06 18:27:56 +05301752 TConstantUnion *resultArray = new TConstantUnion[objectSize];
1753 for (size_t i = 0; i < objectSize; i++)
Arun Patole9d0b1f92015-05-20 14:27:17 +05301754 {
Arun Patoleab2b9a22015-07-06 18:27:56 +05301755 switch(op)
Arun Patole9d0b1f92015-05-20 14:27:17 +05301756 {
Olli Etuahof119a262016-08-19 15:54:22 +03001757 case EOpNegative:
1758 switch (getType().getBasicType())
1759 {
1760 case EbtFloat:
1761 resultArray[i].setFConst(-operandArray[i].getFConst());
1762 break;
1763 case EbtInt:
Olli Etuaho42fad762016-09-28 10:06:29 +01001764 if (operandArray[i] == std::numeric_limits<int>::min())
1765 {
1766 // The minimum representable integer doesn't have a positive
1767 // counterpart, rather the negation overflows and in ESSL is supposed to
1768 // wrap back to the minimum representable integer. Make sure that we
1769 // don't actually let the negation overflow, which has undefined
1770 // behavior in C++.
1771 resultArray[i].setIConst(std::numeric_limits<int>::min());
1772 }
1773 else
1774 {
1775 resultArray[i].setIConst(-operandArray[i].getIConst());
1776 }
Olli Etuahof119a262016-08-19 15:54:22 +03001777 break;
1778 case EbtUInt:
Olli Etuaho42fad762016-09-28 10:06:29 +01001779 if (operandArray[i] == 0x80000000u)
1780 {
1781 resultArray[i].setUConst(0x80000000u);
1782 }
1783 else
1784 {
1785 resultArray[i].setUConst(static_cast<unsigned int>(
1786 -static_cast<int>(operandArray[i].getUConst())));
1787 }
Olli Etuahof119a262016-08-19 15:54:22 +03001788 break;
1789 default:
1790 UNREACHABLE();
1791 return nullptr;
1792 }
Arun Patole1155ddd2015-06-05 18:04:36 +05301793 break;
Arun Patolecdfa8f52015-06-30 17:48:25 +05301794
Olli Etuahof119a262016-08-19 15:54:22 +03001795 case EOpPositive:
1796 switch (getType().getBasicType())
1797 {
1798 case EbtFloat:
1799 resultArray[i].setFConst(operandArray[i].getFConst());
1800 break;
1801 case EbtInt:
1802 resultArray[i].setIConst(operandArray[i].getIConst());
1803 break;
1804 case EbtUInt:
1805 resultArray[i].setUConst(static_cast<unsigned int>(
1806 static_cast<int>(operandArray[i].getUConst())));
1807 break;
1808 default:
1809 UNREACHABLE();
1810 return nullptr;
1811 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301812 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301813
Olli Etuahof119a262016-08-19 15:54:22 +03001814 case EOpLogicalNot:
1815 switch (getType().getBasicType())
1816 {
1817 case EbtBool:
1818 resultArray[i].setBConst(!operandArray[i].getBConst());
1819 break;
1820 default:
1821 UNREACHABLE();
1822 return nullptr;
1823 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301824 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301825
Olli Etuahof119a262016-08-19 15:54:22 +03001826 case EOpBitwiseNot:
1827 switch (getType().getBasicType())
1828 {
1829 case EbtInt:
1830 resultArray[i].setIConst(~operandArray[i].getIConst());
1831 break;
1832 case EbtUInt:
1833 resultArray[i].setUConst(~operandArray[i].getUConst());
1834 break;
1835 default:
1836 UNREACHABLE();
1837 return nullptr;
1838 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301839 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301840
Olli Etuahof119a262016-08-19 15:54:22 +03001841 case EOpRadians:
1842 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301843 resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
1844 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301845
Olli Etuahof119a262016-08-19 15:54:22 +03001846 case EOpDegrees:
1847 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301848 resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
1849 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301850
Olli Etuahof119a262016-08-19 15:54:22 +03001851 case EOpSin:
1852 foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301853 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301854
Olli Etuahof119a262016-08-19 15:54:22 +03001855 case EOpCos:
1856 foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]);
1857 break;
1858
1859 case EOpTan:
1860 foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]);
1861 break;
1862
1863 case EOpAsin:
1864 // For asin(x), results are undefined if |x| > 1, we are choosing to set result to
1865 // 0.
1866 if (fabsf(operandArray[i].getFConst()) > 1.0f)
1867 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1868 diagnostics, &resultArray[i]);
1869 else
1870 foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]);
1871 break;
1872
1873 case EOpAcos:
1874 // For acos(x), results are undefined if |x| > 1, we are choosing to set result to
1875 // 0.
1876 if (fabsf(operandArray[i].getFConst()) > 1.0f)
1877 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1878 diagnostics, &resultArray[i]);
1879 else
1880 foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]);
1881 break;
1882
1883 case EOpAtan:
1884 foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]);
1885 break;
1886
1887 case EOpSinh:
1888 foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]);
1889 break;
1890
1891 case EOpCosh:
1892 foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]);
1893 break;
1894
1895 case EOpTanh:
1896 foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]);
1897 break;
1898
1899 case EOpAsinh:
1900 foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]);
1901 break;
1902
1903 case EOpAcosh:
1904 // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
1905 if (operandArray[i].getFConst() < 1.0f)
1906 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1907 diagnostics, &resultArray[i]);
1908 else
1909 foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]);
1910 break;
1911
1912 case EOpAtanh:
1913 // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to
1914 // 0.
1915 if (fabsf(operandArray[i].getFConst()) >= 1.0f)
1916 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1917 diagnostics, &resultArray[i]);
1918 else
1919 foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]);
1920 break;
1921
1922 case EOpAbs:
1923 switch (getType().getBasicType())
Arun Patoleab2b9a22015-07-06 18:27:56 +05301924 {
Olli Etuahof119a262016-08-19 15:54:22 +03001925 case EbtFloat:
1926 resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
1927 break;
1928 case EbtInt:
1929 resultArray[i].setIConst(abs(operandArray[i].getIConst()));
1930 break;
1931 default:
1932 UNREACHABLE();
1933 return nullptr;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301934 }
1935 break;
Olli Etuahof119a262016-08-19 15:54:22 +03001936
1937 case EOpSign:
1938 switch (getType().getBasicType())
Arun Patoleab2b9a22015-07-06 18:27:56 +05301939 {
Olli Etuahof119a262016-08-19 15:54:22 +03001940 case EbtFloat:
1941 {
1942 float fConst = operandArray[i].getFConst();
1943 float fResult = 0.0f;
1944 if (fConst > 0.0f)
1945 fResult = 1.0f;
1946 else if (fConst < 0.0f)
1947 fResult = -1.0f;
1948 resultArray[i].setFConst(fResult);
1949 break;
1950 }
1951 case EbtInt:
1952 {
1953 int iConst = operandArray[i].getIConst();
1954 int iResult = 0;
1955 if (iConst > 0)
1956 iResult = 1;
1957 else if (iConst < 0)
1958 iResult = -1;
1959 resultArray[i].setIConst(iResult);
1960 break;
1961 }
1962 default:
1963 UNREACHABLE();
1964 return nullptr;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301965 }
1966 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301967
Olli Etuahof119a262016-08-19 15:54:22 +03001968 case EOpFloor:
1969 foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]);
1970 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301971
Olli Etuahof119a262016-08-19 15:54:22 +03001972 case EOpTrunc:
1973 foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]);
1974 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301975
Olli Etuahof119a262016-08-19 15:54:22 +03001976 case EOpRound:
1977 foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]);
1978 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301979
Olli Etuahof119a262016-08-19 15:54:22 +03001980 case EOpRoundEven:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301981 {
Olli Etuahof119a262016-08-19 15:54:22 +03001982 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301983 float x = operandArray[i].getFConst();
1984 float result;
1985 float fractPart = modff(x, &result);
1986 if (fabsf(fractPart) == 0.5f)
1987 result = 2.0f * roundf(x / 2.0f);
1988 else
1989 result = roundf(x);
1990 resultArray[i].setFConst(result);
1991 break;
1992 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301993
Olli Etuahof119a262016-08-19 15:54:22 +03001994 case EOpCeil:
1995 foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]);
1996 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301997
Olli Etuahof119a262016-08-19 15:54:22 +03001998 case EOpFract:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301999 {
Olli Etuahof119a262016-08-19 15:54:22 +03002000 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302001 float x = operandArray[i].getFConst();
2002 resultArray[i].setFConst(x - floorf(x));
2003 break;
2004 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05302005
Olli Etuahof119a262016-08-19 15:54:22 +03002006 case EOpIsNan:
2007 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302008 resultArray[i].setBConst(gl::isNaN(operandArray[0].getFConst()));
2009 break;
Arun Patole551279e2015-07-07 18:18:23 +05302010
Olli Etuahof119a262016-08-19 15:54:22 +03002011 case EOpIsInf:
2012 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302013 resultArray[i].setBConst(gl::isInf(operandArray[0].getFConst()));
2014 break;
Arun Patole551279e2015-07-07 18:18:23 +05302015
Olli Etuahof119a262016-08-19 15:54:22 +03002016 case EOpFloatBitsToInt:
2017 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302018 resultArray[i].setIConst(gl::bitCast<int32_t>(operandArray[0].getFConst()));
2019 break;
Arun Patole551279e2015-07-07 18:18:23 +05302020
Olli Etuahof119a262016-08-19 15:54:22 +03002021 case EOpFloatBitsToUint:
2022 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302023 resultArray[i].setUConst(gl::bitCast<uint32_t>(operandArray[0].getFConst()));
2024 break;
Arun Patole551279e2015-07-07 18:18:23 +05302025
Olli Etuahof119a262016-08-19 15:54:22 +03002026 case EOpIntBitsToFloat:
2027 ASSERT(getType().getBasicType() == EbtInt);
Arun Patole551279e2015-07-07 18:18:23 +05302028 resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getIConst()));
2029 break;
Arun Patole551279e2015-07-07 18:18:23 +05302030
Olli Etuahof119a262016-08-19 15:54:22 +03002031 case EOpUintBitsToFloat:
2032 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patole551279e2015-07-07 18:18:23 +05302033 resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getUConst()));
2034 break;
Arun Patole551279e2015-07-07 18:18:23 +05302035
Olli Etuahof119a262016-08-19 15:54:22 +03002036 case EOpExp:
2037 foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]);
2038 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302039
Olli Etuahof119a262016-08-19 15:54:22 +03002040 case EOpLog:
2041 // For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
2042 if (operandArray[i].getFConst() <= 0.0f)
2043 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2044 diagnostics, &resultArray[i]);
2045 else
2046 foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
2047 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302048
Olli Etuahof119a262016-08-19 15:54:22 +03002049 case EOpExp2:
2050 foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]);
2051 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302052
Olli Etuahof119a262016-08-19 15:54:22 +03002053 case EOpLog2:
2054 // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
2055 // And log2f is not available on some plarforms like old android, so just using
2056 // log(x)/log(2) here.
2057 if (operandArray[i].getFConst() <= 0.0f)
2058 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2059 diagnostics, &resultArray[i]);
2060 else
2061 {
2062 foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
2063 resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
2064 }
2065 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302066
Olli Etuahof119a262016-08-19 15:54:22 +03002067 case EOpSqrt:
2068 // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
2069 if (operandArray[i].getFConst() < 0.0f)
2070 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2071 diagnostics, &resultArray[i]);
2072 else
2073 foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
2074 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302075
Olli Etuahof119a262016-08-19 15:54:22 +03002076 case EOpInverseSqrt:
2077 // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
2078 // so getting the square root first using builtin function sqrt() and then taking
2079 // its inverse.
2080 // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set
2081 // result to 0.
2082 if (operandArray[i].getFConst() <= 0.0f)
2083 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2084 diagnostics, &resultArray[i]);
2085 else
2086 {
2087 foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
2088 resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
2089 }
2090 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302091
Olli Etuahof119a262016-08-19 15:54:22 +03002092 case EOpVectorLogicalNot:
2093 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302094 resultArray[i].setBConst(!operandArray[i].getBConst());
2095 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302096
Olli Etuahof119a262016-08-19 15:54:22 +03002097 case EOpNormalize:
Arun Patoleab2b9a22015-07-06 18:27:56 +05302098 {
Olli Etuahof119a262016-08-19 15:54:22 +03002099 ASSERT(getType().getBasicType() == EbtFloat);
2100 float x = operandArray[i].getFConst();
Arun Patoleab2b9a22015-07-06 18:27:56 +05302101 float length = VectorLength(operandArray, objectSize);
2102 if (length)
2103 resultArray[i].setFConst(x / length);
2104 else
Olli Etuahof119a262016-08-19 15:54:22 +03002105 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2106 diagnostics, &resultArray[i]);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302107 break;
2108 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05302109
Olli Etuahof119a262016-08-19 15:54:22 +03002110 case EOpDFdx:
2111 case EOpDFdy:
2112 case EOpFwidth:
2113 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole0c5409f2015-07-08 15:17:53 +05302114 // Derivatives of constant arguments should be 0.
2115 resultArray[i].setFConst(0.0f);
2116 break;
Arun Patole0c5409f2015-07-08 15:17:53 +05302117
Olli Etuahof119a262016-08-19 15:54:22 +03002118 default:
2119 return nullptr;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302120 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302121 }
Jamie Madillb1a85f42014-08-19 15:23:24 -04002122
Arun Patoleab2b9a22015-07-06 18:27:56 +05302123 return resultArray;
Jamie Madillb1a85f42014-08-19 15:23:24 -04002124}
2125
Olli Etuahof119a262016-08-19 15:54:22 +03002126void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter,
2127 FloatTypeUnaryFunc builtinFunc,
2128 TConstantUnion *result) const
Arun Patole9dea48f2015-04-02 11:45:09 +05302129{
2130 ASSERT(builtinFunc);
2131
Olli Etuahof119a262016-08-19 15:54:22 +03002132 ASSERT(getType().getBasicType() == EbtFloat);
2133 result->setFConst(builtinFunc(parameter.getFConst()));
Arun Patole9dea48f2015-04-02 11:45:09 +05302134}
2135
Jamie Madillb1a85f42014-08-19 15:23:24 -04002136// static
Olli Etuahof119a262016-08-19 15:54:22 +03002137TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate)
Olli Etuaho1d122782015-11-06 15:35:17 +02002138{
2139 ASSERT(aggregate->getSequence()->size() > 0u);
2140 size_t resultSize = aggregate->getType().getObjectSize();
2141 TConstantUnion *resultArray = new TConstantUnion[resultSize];
2142 TBasicType basicType = aggregate->getBasicType();
2143
2144 size_t resultIndex = 0u;
2145
2146 if (aggregate->getSequence()->size() == 1u)
2147 {
2148 TIntermNode *argument = aggregate->getSequence()->front();
2149 TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion();
2150 const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
2151 // Check the special case of constructing a matrix diagonal from a single scalar,
2152 // or a vector from a single scalar.
2153 if (argumentConstant->getType().getObjectSize() == 1u)
2154 {
2155 if (aggregate->isMatrix())
2156 {
2157 int resultCols = aggregate->getType().getCols();
2158 int resultRows = aggregate->getType().getRows();
2159 for (int col = 0; col < resultCols; ++col)
2160 {
2161 for (int row = 0; row < resultRows; ++row)
2162 {
2163 if (col == row)
2164 {
2165 resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
2166 }
2167 else
2168 {
2169 resultArray[resultIndex].setFConst(0.0f);
2170 }
2171 ++resultIndex;
2172 }
2173 }
2174 }
2175 else
2176 {
2177 while (resultIndex < resultSize)
2178 {
2179 resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
2180 ++resultIndex;
2181 }
2182 }
2183 ASSERT(resultIndex == resultSize);
2184 return resultArray;
2185 }
2186 else if (aggregate->isMatrix() && argumentConstant->isMatrix())
2187 {
2188 // The special case of constructing a matrix from a matrix.
2189 int argumentCols = argumentConstant->getType().getCols();
2190 int argumentRows = argumentConstant->getType().getRows();
2191 int resultCols = aggregate->getType().getCols();
2192 int resultRows = aggregate->getType().getRows();
2193 for (int col = 0; col < resultCols; ++col)
2194 {
2195 for (int row = 0; row < resultRows; ++row)
2196 {
2197 if (col < argumentCols && row < argumentRows)
2198 {
2199 resultArray[resultIndex].cast(basicType,
2200 argumentUnionArray[col * argumentRows + row]);
2201 }
2202 else if (col == row)
2203 {
2204 resultArray[resultIndex].setFConst(1.0f);
2205 }
2206 else
2207 {
2208 resultArray[resultIndex].setFConst(0.0f);
2209 }
2210 ++resultIndex;
2211 }
2212 }
2213 ASSERT(resultIndex == resultSize);
2214 return resultArray;
2215 }
2216 }
2217
2218 for (TIntermNode *&argument : *aggregate->getSequence())
2219 {
2220 TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion();
2221 size_t argumentSize = argumentConstant->getType().getObjectSize();
2222 const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
2223 for (size_t i = 0u; i < argumentSize; ++i)
2224 {
2225 if (resultIndex >= resultSize)
2226 break;
2227 resultArray[resultIndex].cast(basicType, argumentUnionArray[i]);
2228 ++resultIndex;
2229 }
2230 }
2231 ASSERT(resultIndex == resultSize);
2232 return resultArray;
2233}
2234
2235// static
Olli Etuahof119a262016-08-19 15:54:22 +03002236TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate,
2237 TDiagnostics *diagnostics)
Arun Patole274f0702015-05-05 13:33:30 +05302238{
Olli Etuahob43846e2015-06-02 18:18:57 +03002239 TOperator op = aggregate->getOp();
Arun Patole274f0702015-05-05 13:33:30 +05302240 TIntermSequence *sequence = aggregate->getSequence();
Cooper Partin4d61f7e2015-08-12 10:56:50 -07002241 unsigned int paramsCount = static_cast<unsigned int>(sequence->size());
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002242 std::vector<const TConstantUnion *> unionArrays(paramsCount);
Arun Patole274f0702015-05-05 13:33:30 +05302243 std::vector<size_t> objectSizes(paramsCount);
Olli Etuahob43846e2015-06-02 18:18:57 +03002244 size_t maxObjectSize = 0;
Arun Patole274f0702015-05-05 13:33:30 +05302245 TBasicType basicType = EbtVoid;
2246 TSourceLoc loc;
2247 for (unsigned int i = 0; i < paramsCount; i++)
2248 {
2249 TIntermConstantUnion *paramConstant = (*sequence)[i]->getAsConstantUnion();
Olli Etuahob43846e2015-06-02 18:18:57 +03002250 ASSERT(paramConstant != nullptr); // Should be checked already.
Arun Patole274f0702015-05-05 13:33:30 +05302251
2252 if (i == 0)
2253 {
2254 basicType = paramConstant->getType().getBasicType();
2255 loc = paramConstant->getLine();
2256 }
2257 unionArrays[i] = paramConstant->getUnionArrayPointer();
2258 objectSizes[i] = paramConstant->getType().getObjectSize();
Olli Etuahob43846e2015-06-02 18:18:57 +03002259 if (objectSizes[i] > maxObjectSize)
2260 maxObjectSize = objectSizes[i];
Arun Patole274f0702015-05-05 13:33:30 +05302261 }
2262
Olli Etuahod5da5052016-08-29 13:16:55 +03002263 if (!(*sequence)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct)
Arun Patole7fa33552015-06-10 15:15:18 +05302264 {
2265 for (unsigned int i = 0; i < paramsCount; i++)
2266 if (objectSizes[i] != maxObjectSize)
2267 unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize);
2268 }
Arun Patole274f0702015-05-05 13:33:30 +05302269
Olli Etuahob43846e2015-06-02 18:18:57 +03002270 TConstantUnion *resultArray = nullptr;
Arun Patole274f0702015-05-05 13:33:30 +05302271 if (paramsCount == 2)
2272 {
2273 //
2274 // Binary built-in
2275 //
2276 switch (op)
2277 {
Olli Etuahof119a262016-08-19 15:54:22 +03002278 case EOpAtan:
Arun Patolebf790422015-05-18 17:53:04 +05302279 {
Olli Etuahof119a262016-08-19 15:54:22 +03002280 ASSERT(basicType == EbtFloat);
2281 resultArray = new TConstantUnion[maxObjectSize];
2282 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302283 {
Olli Etuahof119a262016-08-19 15:54:22 +03002284 float y = unionArrays[0][i].getFConst();
2285 float x = unionArrays[1][i].getFConst();
2286 // Results are undefined if x and y are both 0.
2287 if (x == 0.0f && y == 0.0f)
2288 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2289 &resultArray[i]);
2290 else
2291 resultArray[i].setFConst(atan2f(y, x));
Arun Patolebf790422015-05-18 17:53:04 +05302292 }
Olli Etuahof119a262016-08-19 15:54:22 +03002293 break;
Arun Patolebf790422015-05-18 17:53:04 +05302294 }
Arun Patolebf790422015-05-18 17:53:04 +05302295
Olli Etuahof119a262016-08-19 15:54:22 +03002296 case EOpPow:
Arun Patolebf790422015-05-18 17:53:04 +05302297 {
Olli Etuahof119a262016-08-19 15:54:22 +03002298 ASSERT(basicType == EbtFloat);
2299 resultArray = new TConstantUnion[maxObjectSize];
2300 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302301 {
Olli Etuahof119a262016-08-19 15:54:22 +03002302 float x = unionArrays[0][i].getFConst();
2303 float y = unionArrays[1][i].getFConst();
2304 // Results are undefined if x < 0.
2305 // Results are undefined if x = 0 and y <= 0.
2306 if (x < 0.0f)
2307 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2308 &resultArray[i]);
2309 else if (x == 0.0f && y <= 0.0f)
2310 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2311 &resultArray[i]);
2312 else
2313 resultArray[i].setFConst(powf(x, y));
Arun Patolebf790422015-05-18 17:53:04 +05302314 }
Olli Etuahof119a262016-08-19 15:54:22 +03002315 break;
Arun Patolebf790422015-05-18 17:53:04 +05302316 }
Arun Patolebf790422015-05-18 17:53:04 +05302317
Olli Etuahof119a262016-08-19 15:54:22 +03002318 case EOpMod:
Arun Patolebf790422015-05-18 17:53:04 +05302319 {
Olli Etuahof119a262016-08-19 15:54:22 +03002320 ASSERT(basicType == EbtFloat);
2321 resultArray = new TConstantUnion[maxObjectSize];
2322 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302323 {
Olli Etuahof119a262016-08-19 15:54:22 +03002324 float x = unionArrays[0][i].getFConst();
2325 float y = unionArrays[1][i].getFConst();
2326 resultArray[i].setFConst(x - y * floorf(x / y));
Arun Patolebf790422015-05-18 17:53:04 +05302327 }
Olli Etuahof119a262016-08-19 15:54:22 +03002328 break;
Arun Patolebf790422015-05-18 17:53:04 +05302329 }
Arun Patolebf790422015-05-18 17:53:04 +05302330
Olli Etuahof119a262016-08-19 15:54:22 +03002331 case EOpMin:
Arun Patole274f0702015-05-05 13:33:30 +05302332 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002333 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole274f0702015-05-05 13:33:30 +05302334 for (size_t i = 0; i < maxObjectSize; i++)
2335 {
2336 switch (basicType)
2337 {
Olli Etuahof119a262016-08-19 15:54:22 +03002338 case EbtFloat:
2339 resultArray[i].setFConst(std::min(unionArrays[0][i].getFConst(),
2340 unionArrays[1][i].getFConst()));
2341 break;
2342 case EbtInt:
2343 resultArray[i].setIConst(std::min(unionArrays[0][i].getIConst(),
2344 unionArrays[1][i].getIConst()));
2345 break;
2346 case EbtUInt:
2347 resultArray[i].setUConst(std::min(unionArrays[0][i].getUConst(),
2348 unionArrays[1][i].getUConst()));
2349 break;
2350 default:
2351 UNREACHABLE();
2352 break;
Arun Patole274f0702015-05-05 13:33:30 +05302353 }
2354 }
Olli Etuahof119a262016-08-19 15:54:22 +03002355 break;
Arun Patole274f0702015-05-05 13:33:30 +05302356 }
Arun Patole274f0702015-05-05 13:33:30 +05302357
Olli Etuahof119a262016-08-19 15:54:22 +03002358 case EOpMax:
Arun Patole274f0702015-05-05 13:33:30 +05302359 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002360 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole274f0702015-05-05 13:33:30 +05302361 for (size_t i = 0; i < maxObjectSize; i++)
2362 {
2363 switch (basicType)
2364 {
Olli Etuahof119a262016-08-19 15:54:22 +03002365 case EbtFloat:
2366 resultArray[i].setFConst(std::max(unionArrays[0][i].getFConst(),
2367 unionArrays[1][i].getFConst()));
2368 break;
2369 case EbtInt:
2370 resultArray[i].setIConst(std::max(unionArrays[0][i].getIConst(),
2371 unionArrays[1][i].getIConst()));
2372 break;
2373 case EbtUInt:
2374 resultArray[i].setUConst(std::max(unionArrays[0][i].getUConst(),
2375 unionArrays[1][i].getUConst()));
2376 break;
2377 default:
2378 UNREACHABLE();
2379 break;
Arun Patole274f0702015-05-05 13:33:30 +05302380 }
2381 }
Olli Etuahof119a262016-08-19 15:54:22 +03002382 break;
Arun Patole274f0702015-05-05 13:33:30 +05302383 }
Arun Patole274f0702015-05-05 13:33:30 +05302384
Olli Etuahof119a262016-08-19 15:54:22 +03002385 case EOpStep:
Arun Patolebf790422015-05-18 17:53:04 +05302386 {
Olli Etuahof119a262016-08-19 15:54:22 +03002387 ASSERT(basicType == EbtFloat);
2388 resultArray = new TConstantUnion[maxObjectSize];
2389 for (size_t i = 0; i < maxObjectSize; i++)
2390 resultArray[i].setFConst(
2391 unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f
2392 : 1.0f);
2393 break;
Arun Patolebf790422015-05-18 17:53:04 +05302394 }
Arun Patolebf790422015-05-18 17:53:04 +05302395
Olli Etuahof119a262016-08-19 15:54:22 +03002396 case EOpLessThan:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302397 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002398 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302399 for (size_t i = 0; i < maxObjectSize; i++)
2400 {
2401 switch (basicType)
2402 {
Olli Etuahof119a262016-08-19 15:54:22 +03002403 case EbtFloat:
2404 resultArray[i].setBConst(unionArrays[0][i].getFConst() <
2405 unionArrays[1][i].getFConst());
2406 break;
2407 case EbtInt:
2408 resultArray[i].setBConst(unionArrays[0][i].getIConst() <
2409 unionArrays[1][i].getIConst());
2410 break;
2411 case EbtUInt:
2412 resultArray[i].setBConst(unionArrays[0][i].getUConst() <
2413 unionArrays[1][i].getUConst());
2414 break;
2415 default:
2416 UNREACHABLE();
2417 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302418 }
2419 }
Olli Etuahof119a262016-08-19 15:54:22 +03002420 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302421 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302422
Olli Etuahof119a262016-08-19 15:54:22 +03002423 case EOpLessThanEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302424 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002425 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302426 for (size_t i = 0; i < maxObjectSize; i++)
2427 {
2428 switch (basicType)
2429 {
Olli Etuahof119a262016-08-19 15:54:22 +03002430 case EbtFloat:
2431 resultArray[i].setBConst(unionArrays[0][i].getFConst() <=
2432 unionArrays[1][i].getFConst());
2433 break;
2434 case EbtInt:
2435 resultArray[i].setBConst(unionArrays[0][i].getIConst() <=
2436 unionArrays[1][i].getIConst());
2437 break;
2438 case EbtUInt:
2439 resultArray[i].setBConst(unionArrays[0][i].getUConst() <=
2440 unionArrays[1][i].getUConst());
2441 break;
2442 default:
2443 UNREACHABLE();
2444 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302445 }
2446 }
Olli Etuahof119a262016-08-19 15:54:22 +03002447 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302448 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302449
Olli Etuahof119a262016-08-19 15:54:22 +03002450 case EOpGreaterThan:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302451 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002452 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302453 for (size_t i = 0; i < maxObjectSize; i++)
2454 {
2455 switch (basicType)
2456 {
Olli Etuahof119a262016-08-19 15:54:22 +03002457 case EbtFloat:
2458 resultArray[i].setBConst(unionArrays[0][i].getFConst() >
2459 unionArrays[1][i].getFConst());
2460 break;
2461 case EbtInt:
2462 resultArray[i].setBConst(unionArrays[0][i].getIConst() >
2463 unionArrays[1][i].getIConst());
2464 break;
2465 case EbtUInt:
2466 resultArray[i].setBConst(unionArrays[0][i].getUConst() >
2467 unionArrays[1][i].getUConst());
2468 break;
2469 default:
2470 UNREACHABLE();
2471 break;
Olli Etuahob43846e2015-06-02 18:18:57 +03002472 }
2473 }
Olli Etuahof119a262016-08-19 15:54:22 +03002474 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302475 }
Olli Etuahof119a262016-08-19 15:54:22 +03002476 case EOpGreaterThanEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302477 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002478 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302479 for (size_t i = 0; i < maxObjectSize; i++)
2480 {
2481 switch (basicType)
2482 {
Olli Etuahof119a262016-08-19 15:54:22 +03002483 case EbtFloat:
2484 resultArray[i].setBConst(unionArrays[0][i].getFConst() >=
2485 unionArrays[1][i].getFConst());
2486 break;
2487 case EbtInt:
2488 resultArray[i].setBConst(unionArrays[0][i].getIConst() >=
2489 unionArrays[1][i].getIConst());
2490 break;
2491 case EbtUInt:
2492 resultArray[i].setBConst(unionArrays[0][i].getUConst() >=
2493 unionArrays[1][i].getUConst());
2494 break;
2495 default:
2496 UNREACHABLE();
2497 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302498 }
2499 }
2500 }
2501 break;
2502
Olli Etuahof119a262016-08-19 15:54:22 +03002503 case EOpVectorEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302504 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002505 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302506 for (size_t i = 0; i < maxObjectSize; i++)
2507 {
2508 switch (basicType)
2509 {
Olli Etuahof119a262016-08-19 15:54:22 +03002510 case EbtFloat:
2511 resultArray[i].setBConst(unionArrays[0][i].getFConst() ==
2512 unionArrays[1][i].getFConst());
2513 break;
2514 case EbtInt:
2515 resultArray[i].setBConst(unionArrays[0][i].getIConst() ==
2516 unionArrays[1][i].getIConst());
2517 break;
2518 case EbtUInt:
2519 resultArray[i].setBConst(unionArrays[0][i].getUConst() ==
2520 unionArrays[1][i].getUConst());
2521 break;
2522 case EbtBool:
2523 resultArray[i].setBConst(unionArrays[0][i].getBConst() ==
2524 unionArrays[1][i].getBConst());
2525 break;
2526 default:
2527 UNREACHABLE();
2528 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302529 }
2530 }
Olli Etuahof119a262016-08-19 15:54:22 +03002531 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302532 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302533
Olli Etuahof119a262016-08-19 15:54:22 +03002534 case EOpVectorNotEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302535 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002536 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302537 for (size_t i = 0; i < maxObjectSize; i++)
2538 {
2539 switch (basicType)
2540 {
Olli Etuahof119a262016-08-19 15:54:22 +03002541 case EbtFloat:
2542 resultArray[i].setBConst(unionArrays[0][i].getFConst() !=
2543 unionArrays[1][i].getFConst());
2544 break;
2545 case EbtInt:
2546 resultArray[i].setBConst(unionArrays[0][i].getIConst() !=
2547 unionArrays[1][i].getIConst());
2548 break;
2549 case EbtUInt:
2550 resultArray[i].setBConst(unionArrays[0][i].getUConst() !=
2551 unionArrays[1][i].getUConst());
2552 break;
2553 case EbtBool:
2554 resultArray[i].setBConst(unionArrays[0][i].getBConst() !=
2555 unionArrays[1][i].getBConst());
2556 break;
2557 default:
2558 UNREACHABLE();
2559 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302560 }
2561 }
Olli Etuahof119a262016-08-19 15:54:22 +03002562 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302563 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302564
Olli Etuahof119a262016-08-19 15:54:22 +03002565 case EOpDistance:
Arun Patole1155ddd2015-06-05 18:04:36 +05302566 {
Olli Etuahof119a262016-08-19 15:54:22 +03002567 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302568 TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize];
Olli Etuahof119a262016-08-19 15:54:22 +03002569 resultArray = new TConstantUnion();
Arun Patole1155ddd2015-06-05 18:04:36 +05302570 for (size_t i = 0; i < maxObjectSize; i++)
2571 {
2572 float x = unionArrays[0][i].getFConst();
2573 float y = unionArrays[1][i].getFConst();
2574 distanceArray[i].setFConst(x - y);
2575 }
Olli Etuahob43846e2015-06-02 18:18:57 +03002576 resultArray->setFConst(VectorLength(distanceArray, maxObjectSize));
Olli Etuahof119a262016-08-19 15:54:22 +03002577 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302578 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302579
Olli Etuahof119a262016-08-19 15:54:22 +03002580 case EOpDot:
2581 ASSERT(basicType == EbtFloat);
Olli Etuahob43846e2015-06-02 18:18:57 +03002582 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03002583 resultArray->setFConst(
2584 VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize));
2585 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302586
Olli Etuahof119a262016-08-19 15:54:22 +03002587 case EOpCross:
Arun Patole1155ddd2015-06-05 18:04:36 +05302588 {
Olli Etuahof119a262016-08-19 15:54:22 +03002589 ASSERT(basicType == EbtFloat && maxObjectSize == 3);
Olli Etuahob43846e2015-06-02 18:18:57 +03002590 resultArray = new TConstantUnion[maxObjectSize];
Olli Etuahof119a262016-08-19 15:54:22 +03002591 float x0 = unionArrays[0][0].getFConst();
2592 float x1 = unionArrays[0][1].getFConst();
2593 float x2 = unionArrays[0][2].getFConst();
2594 float y0 = unionArrays[1][0].getFConst();
2595 float y1 = unionArrays[1][1].getFConst();
2596 float y2 = unionArrays[1][2].getFConst();
Olli Etuahob43846e2015-06-02 18:18:57 +03002597 resultArray[0].setFConst(x1 * y2 - y1 * x2);
2598 resultArray[1].setFConst(x2 * y0 - y2 * x0);
2599 resultArray[2].setFConst(x0 * y1 - y0 * x1);
Olli Etuahof119a262016-08-19 15:54:22 +03002600 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302601 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302602
Olli Etuahof119a262016-08-19 15:54:22 +03002603 case EOpReflect:
Arun Patole1155ddd2015-06-05 18:04:36 +05302604 {
Olli Etuahof119a262016-08-19 15:54:22 +03002605 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302606 // genType reflect (genType I, genType N) :
Olli Etuahof119a262016-08-19 15:54:22 +03002607 // For the incident vector I and surface orientation N, returns the reflection
2608 // direction:
Arun Patole1155ddd2015-06-05 18:04:36 +05302609 // I - 2 * dot(N, I) * N.
Olli Etuahof119a262016-08-19 15:54:22 +03002610 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole1155ddd2015-06-05 18:04:36 +05302611 float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
2612 for (size_t i = 0; i < maxObjectSize; i++)
2613 {
2614 float result = unionArrays[0][i].getFConst() -
2615 2.0f * dotProduct * unionArrays[1][i].getFConst();
Olli Etuahob43846e2015-06-02 18:18:57 +03002616 resultArray[i].setFConst(result);
Arun Patole1155ddd2015-06-05 18:04:36 +05302617 }
Olli Etuahof119a262016-08-19 15:54:22 +03002618 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302619 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302620
Olli Etuahof119a262016-08-19 15:54:22 +03002621 case EOpMul:
Arun Patole7fa33552015-06-10 15:15:18 +05302622 {
Olli Etuahof119a262016-08-19 15:54:22 +03002623 ASSERT(basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() &&
2624 (*sequence)[1]->getAsTyped()->isMatrix());
Arun Patole7fa33552015-06-10 15:15:18 +05302625 // Perform component-wise matrix multiplication.
2626 resultArray = new TConstantUnion[maxObjectSize];
Olli Etuahof119a262016-08-19 15:54:22 +03002627 int size = (*sequence)[0]->getAsTyped()->getNominalSize();
Arun Patole7fa33552015-06-10 15:15:18 +05302628 angle::Matrix<float> result =
2629 GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size));
2630 SetUnionArrayFromMatrix(result, resultArray);
Olli Etuahof119a262016-08-19 15:54:22 +03002631 break;
Arun Patole7fa33552015-06-10 15:15:18 +05302632 }
Arun Patole7fa33552015-06-10 15:15:18 +05302633
Olli Etuahof119a262016-08-19 15:54:22 +03002634 case EOpOuterProduct:
Arun Patole7fa33552015-06-10 15:15:18 +05302635 {
Olli Etuahof119a262016-08-19 15:54:22 +03002636 ASSERT(basicType == EbtFloat);
Arun Patole7fa33552015-06-10 15:15:18 +05302637 size_t numRows = (*sequence)[0]->getAsTyped()->getType().getObjectSize();
2638 size_t numCols = (*sequence)[1]->getAsTyped()->getType().getObjectSize();
Olli Etuahof119a262016-08-19 15:54:22 +03002639 resultArray = new TConstantUnion[numRows * numCols];
Arun Patole7fa33552015-06-10 15:15:18 +05302640 angle::Matrix<float> result =
Olli Etuahod5da5052016-08-29 13:16:55 +03002641 GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
2642 .outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols)));
Arun Patole7fa33552015-06-10 15:15:18 +05302643 SetUnionArrayFromMatrix(result, resultArray);
Olli Etuahof119a262016-08-19 15:54:22 +03002644 break;
Arun Patole7fa33552015-06-10 15:15:18 +05302645 }
Arun Patole7fa33552015-06-10 15:15:18 +05302646
Olli Etuahof119a262016-08-19 15:54:22 +03002647 default:
2648 UNREACHABLE();
2649 // TODO: Add constant folding support for other built-in operations that take 2
2650 // parameters and not handled above.
2651 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +05302652 }
2653 }
2654 else if (paramsCount == 3)
2655 {
2656 //
2657 // Ternary built-in
2658 //
2659 switch (op)
2660 {
Olli Etuahof119a262016-08-19 15:54:22 +03002661 case EOpClamp:
Arun Patole274f0702015-05-05 13:33:30 +05302662 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002663 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole274f0702015-05-05 13:33:30 +05302664 for (size_t i = 0; i < maxObjectSize; i++)
2665 {
2666 switch (basicType)
2667 {
Olli Etuahof119a262016-08-19 15:54:22 +03002668 case EbtFloat:
Arun Patole274f0702015-05-05 13:33:30 +05302669 {
Olli Etuahof119a262016-08-19 15:54:22 +03002670 float x = unionArrays[0][i].getFConst();
Arun Patole274f0702015-05-05 13:33:30 +05302671 float min = unionArrays[1][i].getFConst();
2672 float max = unionArrays[2][i].getFConst();
2673 // Results are undefined if min > max.
2674 if (min > max)
Olli Etuahof119a262016-08-19 15:54:22 +03002675 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2676 &resultArray[i]);
Arun Patole274f0702015-05-05 13:33:30 +05302677 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002678 resultArray[i].setFConst(gl::clamp(x, min, max));
Olli Etuahof119a262016-08-19 15:54:22 +03002679 break;
Arun Patole274f0702015-05-05 13:33:30 +05302680 }
Olli Etuahof119a262016-08-19 15:54:22 +03002681
2682 case EbtInt:
Arun Patole274f0702015-05-05 13:33:30 +05302683 {
Olli Etuahof119a262016-08-19 15:54:22 +03002684 int x = unionArrays[0][i].getIConst();
Arun Patole274f0702015-05-05 13:33:30 +05302685 int min = unionArrays[1][i].getIConst();
2686 int max = unionArrays[2][i].getIConst();
2687 // Results are undefined if min > max.
2688 if (min > max)
Olli Etuahof119a262016-08-19 15:54:22 +03002689 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2690 &resultArray[i]);
Arun Patole274f0702015-05-05 13:33:30 +05302691 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002692 resultArray[i].setIConst(gl::clamp(x, min, max));
Olli Etuahof119a262016-08-19 15:54:22 +03002693 break;
Arun Patole274f0702015-05-05 13:33:30 +05302694 }
Olli Etuahof119a262016-08-19 15:54:22 +03002695 case EbtUInt:
Arun Patole274f0702015-05-05 13:33:30 +05302696 {
Olli Etuahof119a262016-08-19 15:54:22 +03002697 unsigned int x = unionArrays[0][i].getUConst();
Arun Patole274f0702015-05-05 13:33:30 +05302698 unsigned int min = unionArrays[1][i].getUConst();
2699 unsigned int max = unionArrays[2][i].getUConst();
2700 // Results are undefined if min > max.
2701 if (min > max)
Olli Etuahof119a262016-08-19 15:54:22 +03002702 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2703 &resultArray[i]);
Arun Patole274f0702015-05-05 13:33:30 +05302704 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002705 resultArray[i].setUConst(gl::clamp(x, min, max));
Olli Etuahof119a262016-08-19 15:54:22 +03002706 break;
Arun Patole274f0702015-05-05 13:33:30 +05302707 }
Olli Etuahof119a262016-08-19 15:54:22 +03002708 default:
2709 UNREACHABLE();
2710 break;
Arun Patole274f0702015-05-05 13:33:30 +05302711 }
2712 }
Olli Etuahof119a262016-08-19 15:54:22 +03002713 break;
Arun Patole274f0702015-05-05 13:33:30 +05302714 }
Arun Patole274f0702015-05-05 13:33:30 +05302715
Olli Etuahof119a262016-08-19 15:54:22 +03002716 case EOpMix:
Arun Patolebf790422015-05-18 17:53:04 +05302717 {
Olli Etuahof119a262016-08-19 15:54:22 +03002718 ASSERT(basicType == EbtFloat);
2719 resultArray = new TConstantUnion[maxObjectSize];
2720 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302721 {
Olli Etuahof119a262016-08-19 15:54:22 +03002722 float x = unionArrays[0][i].getFConst();
2723 float y = unionArrays[1][i].getFConst();
2724 TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType();
2725 if (type == EbtFloat)
Arun Patolebf790422015-05-18 17:53:04 +05302726 {
Olli Etuahof119a262016-08-19 15:54:22 +03002727 // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
2728 float a = unionArrays[2][i].getFConst();
2729 resultArray[i].setFConst(x * (1.0f - a) + y * a);
2730 }
2731 else // 3rd parameter is EbtBool
2732 {
2733 ASSERT(type == EbtBool);
2734 // Selects which vector each returned component comes from.
2735 // For a component of a that is false, the corresponding component of x is
2736 // returned.
2737 // For a component of a that is true, the corresponding component of y is
2738 // returned.
2739 bool a = unionArrays[2][i].getBConst();
2740 resultArray[i].setFConst(a ? y : x);
Arun Patolebf790422015-05-18 17:53:04 +05302741 }
2742 }
Olli Etuahof119a262016-08-19 15:54:22 +03002743 break;
Arun Patolebf790422015-05-18 17:53:04 +05302744 }
Arun Patolebf790422015-05-18 17:53:04 +05302745
Olli Etuahof119a262016-08-19 15:54:22 +03002746 case EOpSmoothStep:
Arun Patolebf790422015-05-18 17:53:04 +05302747 {
Olli Etuahof119a262016-08-19 15:54:22 +03002748 ASSERT(basicType == EbtFloat);
2749 resultArray = new TConstantUnion[maxObjectSize];
2750 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302751 {
Olli Etuahof119a262016-08-19 15:54:22 +03002752 float edge0 = unionArrays[0][i].getFConst();
2753 float edge1 = unionArrays[1][i].getFConst();
2754 float x = unionArrays[2][i].getFConst();
2755 // Results are undefined if edge0 >= edge1.
2756 if (edge0 >= edge1)
Arun Patolebf790422015-05-18 17:53:04 +05302757 {
Olli Etuahof119a262016-08-19 15:54:22 +03002758 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2759 &resultArray[i]);
2760 }
2761 else
2762 {
2763 // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth
2764 // Hermite interpolation between 0 and 1 when edge0 < x < edge1.
2765 float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
2766 resultArray[i].setFConst(t * t * (3.0f - 2.0f * t));
Arun Patolebf790422015-05-18 17:53:04 +05302767 }
2768 }
Olli Etuahof119a262016-08-19 15:54:22 +03002769 break;
Arun Patolebf790422015-05-18 17:53:04 +05302770 }
Arun Patolebf790422015-05-18 17:53:04 +05302771
Olli Etuahof119a262016-08-19 15:54:22 +03002772 case EOpFaceForward:
Arun Patole1155ddd2015-06-05 18:04:36 +05302773 {
Olli Etuahof119a262016-08-19 15:54:22 +03002774 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302775 // genType faceforward(genType N, genType I, genType Nref) :
2776 // If dot(Nref, I) < 0 return N, otherwise return -N.
Olli Etuahof119a262016-08-19 15:54:22 +03002777 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole1155ddd2015-06-05 18:04:36 +05302778 float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize);
2779 for (size_t i = 0; i < maxObjectSize; i++)
2780 {
2781 if (dotProduct < 0)
Olli Etuahob43846e2015-06-02 18:18:57 +03002782 resultArray[i].setFConst(unionArrays[0][i].getFConst());
Arun Patole1155ddd2015-06-05 18:04:36 +05302783 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002784 resultArray[i].setFConst(-unionArrays[0][i].getFConst());
Arun Patole1155ddd2015-06-05 18:04:36 +05302785 }
Olli Etuahof119a262016-08-19 15:54:22 +03002786 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302787 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302788
Olli Etuahof119a262016-08-19 15:54:22 +03002789 case EOpRefract:
Arun Patole1155ddd2015-06-05 18:04:36 +05302790 {
Olli Etuahof119a262016-08-19 15:54:22 +03002791 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302792 // genType refract(genType I, genType N, float eta) :
Olli Etuahof119a262016-08-19 15:54:22 +03002793 // For the incident vector I and surface normal N, and the ratio of indices of
2794 // refraction eta,
Arun Patole1155ddd2015-06-05 18:04:36 +05302795 // return the refraction vector. The result is computed by
2796 // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
2797 // if (k < 0.0)
2798 // return genType(0.0)
2799 // else
2800 // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
Olli Etuahof119a262016-08-19 15:54:22 +03002801 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole1155ddd2015-06-05 18:04:36 +05302802 float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
2803 for (size_t i = 0; i < maxObjectSize; i++)
2804 {
2805 float eta = unionArrays[2][i].getFConst();
Olli Etuahof119a262016-08-19 15:54:22 +03002806 float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct);
Arun Patole1155ddd2015-06-05 18:04:36 +05302807 if (k < 0.0f)
Olli Etuahob43846e2015-06-02 18:18:57 +03002808 resultArray[i].setFConst(0.0f);
Arun Patole1155ddd2015-06-05 18:04:36 +05302809 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002810 resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() -
Olli Etuahof119a262016-08-19 15:54:22 +03002811 (eta * dotProduct + sqrtf(k)) *
2812 unionArrays[1][i].getFConst());
Arun Patole1155ddd2015-06-05 18:04:36 +05302813 }
Olli Etuahof119a262016-08-19 15:54:22 +03002814 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302815 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302816
Olli Etuahof119a262016-08-19 15:54:22 +03002817 default:
2818 UNREACHABLE();
2819 // TODO: Add constant folding support for other built-in operations that take 3
2820 // parameters and not handled above.
2821 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +05302822 }
2823 }
Olli Etuahob43846e2015-06-02 18:18:57 +03002824 return resultArray;
Arun Patole274f0702015-05-05 13:33:30 +05302825}
2826
2827// static
Jamie Madillb1a85f42014-08-19 15:23:24 -04002828TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction)
2829{
2830 if (hashFunction == NULL || name.empty())
2831 return name;
2832 khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
2833 TStringStream stream;
2834 stream << HASHED_NAME_PREFIX << std::hex << number;
2835 TString hashedName = stream.str();
2836 return hashedName;
2837}
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002838
2839void TIntermTraverser::updateTree()
2840{
Olli Etuahoa6f22092015-05-08 18:31:10 +03002841 for (size_t ii = 0; ii < mInsertions.size(); ++ii)
2842 {
2843 const NodeInsertMultipleEntry &insertion = mInsertions[ii];
2844 ASSERT(insertion.parent);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03002845 if (!insertion.insertionsAfter.empty())
2846 {
2847 bool inserted = insertion.parent->insertChildNodes(insertion.position + 1,
2848 insertion.insertionsAfter);
2849 ASSERT(inserted);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03002850 }
2851 if (!insertion.insertionsBefore.empty())
2852 {
2853 bool inserted =
2854 insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore);
2855 ASSERT(inserted);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03002856 }
Olli Etuahoa6f22092015-05-08 18:31:10 +03002857 }
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002858 for (size_t ii = 0; ii < mReplacements.size(); ++ii)
2859 {
Olli Etuahocd94ef92015-04-16 19:18:10 +03002860 const NodeUpdateEntry &replacement = mReplacements[ii];
2861 ASSERT(replacement.parent);
2862 bool replaced = replacement.parent->replaceChildNode(
2863 replacement.original, replacement.replacement);
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002864 ASSERT(replaced);
2865
Olli Etuahocd94ef92015-04-16 19:18:10 +03002866 if (!replacement.originalBecomesChildOfReplacement)
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002867 {
2868 // In AST traversing, a parent is visited before its children.
Olli Etuahocd94ef92015-04-16 19:18:10 +03002869 // After we replace a node, if its immediate child is to
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002870 // be replaced, we need to make sure we don't update the replaced
2871 // node; instead, we update the replacement node.
2872 for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj)
2873 {
Olli Etuahocd94ef92015-04-16 19:18:10 +03002874 NodeUpdateEntry &replacement2 = mReplacements[jj];
2875 if (replacement2.parent == replacement.original)
2876 replacement2.parent = replacement.replacement;
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002877 }
2878 }
2879 }
Olli Etuahofc0e2bc2015-04-16 13:39:56 +03002880 for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii)
2881 {
2882 const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii];
2883 ASSERT(replacement.parent);
2884 bool replaced = replacement.parent->replaceChildNodeWithMultiple(
2885 replacement.original, replacement.replacements);
2886 ASSERT(replaced);
2887 }
Olli Etuahod4f303e2015-05-20 17:09:06 +03002888
Jamie Madill03d863c2016-07-27 18:15:53 -04002889 clearReplacementQueue();
2890}
2891
2892void TIntermTraverser::clearReplacementQueue()
2893{
Olli Etuahod4f303e2015-05-20 17:09:06 +03002894 mReplacements.clear();
2895 mMultiReplacements.clear();
Jamie Madill03d863c2016-07-27 18:15:53 -04002896 mInsertions.clear();
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002897}
Jamie Madill1048e432016-07-23 18:51:28 -04002898
Jamie Madill03d863c2016-07-27 18:15:53 -04002899void TIntermTraverser::queueReplacement(TIntermNode *original,
2900 TIntermNode *replacement,
2901 OriginalNode originalStatus)
Jamie Madill1048e432016-07-23 18:51:28 -04002902{
Jamie Madill03d863c2016-07-27 18:15:53 -04002903 queueReplacementWithParent(getParentNode(), original, replacement, originalStatus);
Jamie Madill1048e432016-07-23 18:51:28 -04002904}
2905
Jamie Madill03d863c2016-07-27 18:15:53 -04002906void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent,
2907 TIntermNode *original,
2908 TIntermNode *replacement,
2909 OriginalNode originalStatus)
Jamie Madill1048e432016-07-23 18:51:28 -04002910{
Jamie Madill03d863c2016-07-27 18:15:53 -04002911 bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD);
2912 mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild));
Jamie Madill1048e432016-07-23 18:51:28 -04002913}
Jamie Madill45bcc782016-11-07 13:58:48 -05002914
2915} // namespace sh