blob: bbcd6a03f5915cec648e75ef8d0f9b23efcf5046 [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
26namespace
27{
28
Arun Patole9dea48f2015-04-02 11:45:09 +053029const float kPi = 3.14159265358979323846f;
30const float kDegreesToRadiansMultiplier = kPi / 180.0f;
31const float kRadiansToDegreesMultiplier = 180.0f / kPi;
32
Jamie Madillb1a85f42014-08-19 15:23:24 -040033TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
34{
35 return left > right ? left : right;
36}
37
Arun Patole274f0702015-05-05 13:33:30 +053038TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size)
39{
40 TConstantUnion *constUnion = new TConstantUnion[size];
41 for (unsigned int i = 0; i < size; ++i)
42 constUnion[i] = constant;
43
44 return constUnion;
45}
46
Olli Etuahof119a262016-08-19 15:54:22 +030047void UndefinedConstantFoldingError(const TSourceLoc &loc,
48 TOperator op,
49 TBasicType basicType,
50 TDiagnostics *diagnostics,
51 TConstantUnion *result)
Arun Patolebf790422015-05-18 17:53:04 +053052{
Olli Etuahof119a262016-08-19 15:54:22 +030053 diagnostics->warning(loc, "operation result is undefined for the values passed in",
54 GetOperatorString(op), "");
Arun Patolebf790422015-05-18 17:53:04 +053055
56 switch (basicType)
57 {
58 case EbtFloat :
59 result->setFConst(0.0f);
60 break;
61 case EbtInt:
62 result->setIConst(0);
63 break;
64 case EbtUInt:
65 result->setUConst(0u);
66 break;
67 case EbtBool:
68 result->setBConst(false);
69 break;
70 default:
71 break;
72 }
73}
74
Olli Etuaho5c0e0232015-11-11 15:55:59 +020075float VectorLength(const TConstantUnion *paramArray, size_t paramArraySize)
Arun Patole1155ddd2015-06-05 18:04:36 +053076{
77 float result = 0.0f;
78 for (size_t i = 0; i < paramArraySize; i++)
79 {
80 float f = paramArray[i].getFConst();
81 result += f * f;
82 }
83 return sqrtf(result);
84}
85
Olli Etuaho5c0e0232015-11-11 15:55:59 +020086float VectorDotProduct(const TConstantUnion *paramArray1,
87 const TConstantUnion *paramArray2,
88 size_t paramArraySize)
Arun Patole1155ddd2015-06-05 18:04:36 +053089{
90 float result = 0.0f;
91 for (size_t i = 0; i < paramArraySize; i++)
92 result += paramArray1[i].getFConst() * paramArray2[i].getFConst();
93 return result;
94}
95
Olli Etuaho3272a6d2016-08-29 17:54:50 +030096TIntermTyped *CreateFoldedNode(const TConstantUnion *constArray,
Olli Etuaho7c3848e2015-11-04 13:19:17 +020097 const TIntermTyped *originalNode,
98 TQualifier qualifier)
Olli Etuahob43846e2015-06-02 18:18:57 +030099{
100 if (constArray == nullptr)
101 {
102 return nullptr;
103 }
104 TIntermTyped *folded = new TIntermConstantUnion(constArray, originalNode->getType());
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200105 folded->getTypePointer()->setQualifier(qualifier);
Olli Etuahob43846e2015-06-02 18:18:57 +0300106 folded->setLine(originalNode->getLine());
107 return folded;
108}
109
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200110angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray,
111 const unsigned int &rows,
112 const unsigned int &cols)
Arun Patole7fa33552015-06-10 15:15:18 +0530113{
114 std::vector<float> elements;
115 for (size_t i = 0; i < rows * cols; i++)
116 elements.push_back(paramArray[i].getFConst());
117 // Transpose is used since the Matrix constructor expects arguments in row-major order,
Olli Etuahod5da5052016-08-29 13:16:55 +0300118 // whereas the paramArray is in column-major order. Rows/cols parameters are also flipped below
119 // so that the created matrix will have the expected dimensions after the transpose.
120 return angle::Matrix<float>(elements, cols, rows).transpose();
Arun Patole7fa33552015-06-10 15:15:18 +0530121}
122
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200123angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray, const unsigned int &size)
Arun Patole7fa33552015-06-10 15:15:18 +0530124{
125 std::vector<float> elements;
126 for (size_t i = 0; i < size * size; i++)
127 elements.push_back(paramArray[i].getFConst());
128 // Transpose is used since the Matrix constructor expects arguments in row-major order,
129 // whereas the paramArray is in column-major order.
130 return angle::Matrix<float>(elements, size).transpose();
131}
132
133void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resultArray)
134{
135 // Transpose is used since the input Matrix is in row-major order,
136 // whereas the actual result should be in column-major order.
137 angle::Matrix<float> result = m.transpose();
138 std::vector<float> resultElements = result.elements();
139 for (size_t i = 0; i < resultElements.size(); i++)
140 resultArray[i].setFConst(resultElements[i]);
141}
142
Jamie Madillb1a85f42014-08-19 15:23:24 -0400143} // namespace anonymous
144
145
146////////////////////////////////////////////////////////////////
147//
148// Member functions of the nodes used for building the tree.
149//
150////////////////////////////////////////////////////////////////
151
Olli Etuahod2a67b92014-10-21 16:42:57 +0300152void TIntermTyped::setTypePreservePrecision(const TType &t)
153{
154 TPrecision precision = getPrecision();
155 mType = t;
156 ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined);
157 mType.setPrecision(precision);
158}
159
Jamie Madillb1a85f42014-08-19 15:23:24 -0400160#define REPLACE_IF_IS(node, type, original, replacement) \
161 if (node == original) { \
162 node = static_cast<type *>(replacement); \
163 return true; \
164 }
165
166bool TIntermLoop::replaceChildNode(
167 TIntermNode *original, TIntermNode *replacement)
168{
Olli Etuaho3cbb27a2016-07-14 11:55:48 +0300169 ASSERT(original != nullptr); // This risks replacing multiple children.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400170 REPLACE_IF_IS(mInit, TIntermNode, original, replacement);
171 REPLACE_IF_IS(mCond, TIntermTyped, original, replacement);
172 REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100173 REPLACE_IF_IS(mBody, TIntermBlock, original, replacement);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400174 return false;
175}
176
Jamie Madillb1a85f42014-08-19 15:23:24 -0400177bool TIntermBranch::replaceChildNode(
178 TIntermNode *original, TIntermNode *replacement)
179{
180 REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement);
181 return false;
182}
183
Olli Etuahob6fa0432016-09-28 16:28:05 +0100184bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
185{
186 ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
187 REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
188 return false;
189}
190
Jamie Madillb1a85f42014-08-19 15:23:24 -0400191bool TIntermBinary::replaceChildNode(
192 TIntermNode *original, TIntermNode *replacement)
193{
194 REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement);
195 REPLACE_IF_IS(mRight, TIntermTyped, original, replacement);
196 return false;
197}
198
Jamie Madillb1a85f42014-08-19 15:23:24 -0400199bool TIntermUnary::replaceChildNode(
200 TIntermNode *original, TIntermNode *replacement)
201{
Olli Etuahoa2234302016-08-31 12:05:39 +0300202 ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
Jamie Madillb1a85f42014-08-19 15:23:24 -0400203 REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
204 return false;
205}
206
Olli Etuaho336b1472016-10-05 16:37:55 +0100207bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
208{
209 REPLACE_IF_IS(mParameters, TIntermAggregate, original, replacement);
210 REPLACE_IF_IS(mBody, TIntermBlock, original, replacement);
211 return false;
212}
213
Jamie Madillb1a85f42014-08-19 15:23:24 -0400214bool TIntermAggregate::replaceChildNode(
215 TIntermNode *original, TIntermNode *replacement)
216{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100217 return replaceChildNodeInternal(original, replacement);
218}
219
220bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
221{
222 return replaceChildNodeInternal(original, replacement);
223}
224
Olli Etuaho13389b62016-10-16 11:48:18 +0100225bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
226{
227 return replaceChildNodeInternal(original, replacement);
228}
229
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100230bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement)
231{
232 for (size_t ii = 0; ii < getSequence()->size(); ++ii)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400233 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100234 REPLACE_IF_IS((*getSequence())[ii], TIntermNode, original, replacement);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400235 }
236 return false;
237}
238
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100239bool TIntermAggregateBase::replaceChildNodeWithMultiple(TIntermNode *original,
240 const TIntermSequence &replacements)
Olli Etuahofc0e2bc2015-04-16 13:39:56 +0300241{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100242 for (auto it = getSequence()->begin(); it < getSequence()->end(); ++it)
Olli Etuahofc0e2bc2015-04-16 13:39:56 +0300243 {
244 if (*it == original)
245 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100246 it = getSequence()->erase(it);
247 getSequence()->insert(it, replacements.begin(), replacements.end());
Olli Etuahofc0e2bc2015-04-16 13:39:56 +0300248 return true;
249 }
250 }
251 return false;
252}
253
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100254bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position,
255 const TIntermSequence &insertions)
Olli Etuahoa6f22092015-05-08 18:31:10 +0300256{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100257 if (position > getSequence()->size())
Olli Etuahoa6f22092015-05-08 18:31:10 +0300258 {
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300259 return false;
Olli Etuahoa6f22092015-05-08 18:31:10 +0300260 }
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100261 auto it = getSequence()->begin() + position;
262 getSequence()->insert(it, insertions.begin(), insertions.end());
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300263 return true;
Olli Etuahoa6f22092015-05-08 18:31:10 +0300264}
265
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200266bool TIntermAggregate::areChildrenConstQualified()
267{
268 for (TIntermNode *&child : mSequence)
269 {
270 TIntermTyped *typed = child->getAsTyped();
271 if (typed && typed->getQualifier() != EvqConst)
272 {
273 return false;
274 }
275 }
276 return true;
277}
278
Olli Etuahod2a67b92014-10-21 16:42:57 +0300279void TIntermAggregate::setPrecisionFromChildren()
280{
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300281 mGotPrecisionFromChildren = true;
Olli Etuahod2a67b92014-10-21 16:42:57 +0300282 if (getBasicType() == EbtBool)
283 {
284 mType.setPrecision(EbpUndefined);
285 return;
286 }
287
288 TPrecision precision = EbpUndefined;
289 TIntermSequence::iterator childIter = mSequence.begin();
290 while (childIter != mSequence.end())
291 {
292 TIntermTyped *typed = (*childIter)->getAsTyped();
293 if (typed)
294 precision = GetHigherPrecision(typed->getPrecision(), precision);
295 ++childIter;
296 }
297 mType.setPrecision(precision);
298}
299
300void TIntermAggregate::setBuiltInFunctionPrecision()
301{
302 // All built-ins returning bool should be handled as ops, not functions.
303 ASSERT(getBasicType() != EbtBool);
304
305 TPrecision precision = EbpUndefined;
306 TIntermSequence::iterator childIter = mSequence.begin();
307 while (childIter != mSequence.end())
308 {
309 TIntermTyped *typed = (*childIter)->getAsTyped();
310 // ESSL spec section 8: texture functions get their precision from the sampler.
311 if (typed && IsSampler(typed->getBasicType()))
312 {
313 precision = typed->getPrecision();
314 break;
315 }
316 ++childIter;
317 }
318 // ESSL 3.0 spec section 8: textureSize always gets highp precision.
319 // All other functions that take a sampler are assumed to be texture functions.
Olli Etuahobd674552016-10-06 13:28:42 +0100320 if (mFunctionInfo.getName().find("textureSize") == 0)
Olli Etuahod2a67b92014-10-21 16:42:57 +0300321 mType.setPrecision(EbpHigh);
322 else
323 mType.setPrecision(precision);
324}
325
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100326void TIntermBlock::appendStatement(TIntermNode *statement)
327{
Olli Etuaho13389b62016-10-16 11:48:18 +0100328 // Declaration nodes with no children can appear if all the declarators just added constants to
329 // the symbol table instead of generating code. They're no-ops so they aren't added to blocks.
330 if (statement != nullptr && (statement->getAsDeclarationNode() == nullptr ||
331 !statement->getAsDeclarationNode()->getSequence()->empty()))
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100332 {
333 mStatements.push_back(statement);
334 }
335}
336
Olli Etuaho13389b62016-10-16 11:48:18 +0100337void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator)
338{
339 ASSERT(declarator != nullptr);
340 ASSERT(declarator->getAsSymbolNode() != nullptr ||
341 (declarator->getAsBinaryNode() != nullptr &&
342 declarator->getAsBinaryNode()->getOp() == EOpInitialize));
343 ASSERT(mDeclarators.empty() ||
344 declarator->getType().sameElementType(mDeclarators.back()->getAsTyped()->getType()));
345 mDeclarators.push_back(declarator);
346}
347
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300348bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
349{
350 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
351 REPLACE_IF_IS(mTrueExpression, TIntermTyped, original, replacement);
352 REPLACE_IF_IS(mFalseExpression, TIntermTyped, original, replacement);
353 return false;
354}
355
Olli Etuaho57961272016-09-14 13:57:46 +0300356bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400357{
358 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100359 REPLACE_IF_IS(mTrueBlock, TIntermBlock, original, replacement);
360 REPLACE_IF_IS(mFalseBlock, TIntermBlock, original, replacement);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400361 return false;
362}
363
Olli Etuahoa3a36662015-02-17 13:46:51 +0200364bool TIntermSwitch::replaceChildNode(
365 TIntermNode *original, TIntermNode *replacement)
366{
367 REPLACE_IF_IS(mInit, TIntermTyped, original, replacement);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100368 REPLACE_IF_IS(mStatementList, TIntermBlock, original, replacement);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200369 return false;
370}
371
372bool TIntermCase::replaceChildNode(
373 TIntermNode *original, TIntermNode *replacement)
374{
375 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
376 return false;
377}
378
Olli Etuahod7a25242015-08-18 13:49:45 +0300379TIntermTyped::TIntermTyped(const TIntermTyped &node) : TIntermNode(), mType(node.mType)
380{
381 // Copy constructor is disallowed for TIntermNode in order to disallow it for subclasses that
382 // don't explicitly allow it, so normal TIntermNode constructor is used to construct the copy.
383 // We need to manually copy any fields of TIntermNode besides handling fields in TIntermTyped.
384 mLine = node.mLine;
385}
386
Olli Etuahod4f4c112016-04-15 15:11:24 +0300387bool TIntermTyped::isConstructorWithOnlyConstantUnionParameters()
388{
389 TIntermAggregate *constructor = getAsAggregate();
390 if (!constructor || !constructor->isConstructor())
391 {
392 return false;
393 }
394 for (TIntermNode *&node : *constructor->getSequence())
395 {
396 if (!node->getAsConstantUnion())
397 return false;
398 }
399 return true;
400}
401
Corentin Wallez509e4562016-08-25 14:55:44 -0400402// static
403TIntermTyped *TIntermTyped::CreateIndexNode(int index)
404{
405 TConstantUnion *u = new TConstantUnion[1];
406 u[0].setIConst(index);
407
408 TType type(EbtInt, EbpUndefined, EvqConst, 1);
409 TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
410 return node;
411}
412
413// static
414TIntermTyped *TIntermTyped::CreateZero(const TType &type)
415{
416 TType constType(type);
417 constType.setQualifier(EvqConst);
418
419 if (!type.isArray() && type.getBasicType() != EbtStruct)
420 {
421 ASSERT(type.isScalar() || type.isVector() || type.isMatrix());
422
423 size_t size = constType.getObjectSize();
424 TConstantUnion *u = new TConstantUnion[size];
425 for (size_t i = 0; i < size; ++i)
426 {
427 switch (type.getBasicType())
428 {
429 case EbtFloat:
430 u[i].setFConst(0.0f);
431 break;
432 case EbtInt:
433 u[i].setIConst(0);
434 break;
435 case EbtUInt:
436 u[i].setUConst(0u);
437 break;
438 case EbtBool:
439 u[i].setBConst(false);
440 break;
441 default:
442 UNREACHABLE();
443 return nullptr;
444 }
445 }
446
447 TIntermConstantUnion *node = new TIntermConstantUnion(u, constType);
448 return node;
449 }
450
451 TIntermAggregate *constructor = new TIntermAggregate(sh::TypeToConstructorOperator(type));
452 constructor->setType(constType);
453
454 if (type.isArray())
455 {
456 TType elementType(type);
457 elementType.clearArrayness();
458
459 size_t arraySize = type.getArraySize();
460 for (size_t i = 0; i < arraySize; ++i)
461 {
462 constructor->getSequence()->push_back(CreateZero(elementType));
463 }
464 }
465 else
466 {
467 ASSERT(type.getBasicType() == EbtStruct);
468
469 TStructure *structure = type.getStruct();
470 for (const auto &field : structure->fields())
471 {
472 constructor->getSequence()->push_back(CreateZero(*field->type()));
473 }
474 }
475
476 return constructor;
477}
478
Olli Etuahod7a25242015-08-18 13:49:45 +0300479TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) : TIntermTyped(node)
480{
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200481 mUnionArrayPointer = node.mUnionArrayPointer;
Olli Etuahod7a25242015-08-18 13:49:45 +0300482}
483
Olli Etuahobd674552016-10-06 13:28:42 +0100484void TFunctionSymbolInfo::setFromFunction(const TFunction &function)
485{
486 setName(function.getMangledName());
487 setId(function.getUniqueId());
488}
489
Olli Etuahod7a25242015-08-18 13:49:45 +0300490TIntermAggregate::TIntermAggregate(const TIntermAggregate &node)
491 : TIntermOperator(node),
Olli Etuahod7a25242015-08-18 13:49:45 +0300492 mUserDefined(node.mUserDefined),
Olli Etuahod7a25242015-08-18 13:49:45 +0300493 mUseEmulatedFunction(node.mUseEmulatedFunction),
Olli Etuahobd674552016-10-06 13:28:42 +0100494 mGotPrecisionFromChildren(node.mGotPrecisionFromChildren),
495 mFunctionInfo(node.mFunctionInfo)
Olli Etuahod7a25242015-08-18 13:49:45 +0300496{
497 for (TIntermNode *child : node.mSequence)
498 {
499 TIntermTyped *typedChild = child->getAsTyped();
500 ASSERT(typedChild != nullptr);
501 TIntermTyped *childCopy = typedChild->deepCopy();
502 mSequence.push_back(childCopy);
503 }
504}
505
Olli Etuahob6fa0432016-09-28 16:28:05 +0100506TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermTyped(node)
507{
508 TIntermTyped *operandCopy = node.mOperand->deepCopy();
509 ASSERT(operandCopy != nullptr);
510 mOperand = operandCopy;
511}
512
Olli Etuahod7a25242015-08-18 13:49:45 +0300513TIntermBinary::TIntermBinary(const TIntermBinary &node)
514 : TIntermOperator(node), mAddIndexClamp(node.mAddIndexClamp)
515{
516 TIntermTyped *leftCopy = node.mLeft->deepCopy();
517 TIntermTyped *rightCopy = node.mRight->deepCopy();
518 ASSERT(leftCopy != nullptr && rightCopy != nullptr);
519 mLeft = leftCopy;
520 mRight = rightCopy;
521}
522
523TIntermUnary::TIntermUnary(const TIntermUnary &node)
524 : TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction)
525{
526 TIntermTyped *operandCopy = node.mOperand->deepCopy();
527 ASSERT(operandCopy != nullptr);
528 mOperand = operandCopy;
529}
530
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300531TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermTyped(node)
Olli Etuahod7a25242015-08-18 13:49:45 +0300532{
Olli Etuahod7a25242015-08-18 13:49:45 +0300533 TIntermTyped *conditionCopy = node.mCondition->deepCopy();
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300534 TIntermTyped *trueCopy = node.mTrueExpression->deepCopy();
535 TIntermTyped *falseCopy = node.mFalseExpression->deepCopy();
Olli Etuahod7a25242015-08-18 13:49:45 +0300536 ASSERT(conditionCopy != nullptr && trueCopy != nullptr && falseCopy != nullptr);
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300537 mCondition = conditionCopy;
538 mTrueExpression = trueCopy;
539 mFalseExpression = falseCopy;
Olli Etuahod7a25242015-08-18 13:49:45 +0300540}
541
Jamie Madillb1a85f42014-08-19 15:23:24 -0400542bool TIntermOperator::isAssignment() const
543{
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300544 return IsAssignment(mOp);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400545}
546
Olli Etuaho8f76bcc2015-06-02 13:54:20 +0300547bool TIntermOperator::isMultiplication() const
548{
549 switch (mOp)
550 {
551 case EOpMul:
552 case EOpMatrixTimesMatrix:
553 case EOpMatrixTimesVector:
554 case EOpMatrixTimesScalar:
555 case EOpVectorTimesMatrix:
556 case EOpVectorTimesScalar:
557 return true;
558 default:
559 return false;
560 }
561}
562
Jamie Madillb1a85f42014-08-19 15:23:24 -0400563//
564// returns true if the operator is for one of the constructors
565//
566bool TIntermOperator::isConstructor() const
567{
568 switch (mOp)
569 {
570 case EOpConstructVec2:
571 case EOpConstructVec3:
572 case EOpConstructVec4:
573 case EOpConstructMat2:
Alexis Hetu07e57df2015-06-16 16:55:52 -0400574 case EOpConstructMat2x3:
575 case EOpConstructMat2x4:
576 case EOpConstructMat3x2:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400577 case EOpConstructMat3:
Alexis Hetu07e57df2015-06-16 16:55:52 -0400578 case EOpConstructMat3x4:
579 case EOpConstructMat4x2:
580 case EOpConstructMat4x3:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400581 case EOpConstructMat4:
582 case EOpConstructFloat:
583 case EOpConstructIVec2:
584 case EOpConstructIVec3:
585 case EOpConstructIVec4:
586 case EOpConstructInt:
587 case EOpConstructUVec2:
588 case EOpConstructUVec3:
589 case EOpConstructUVec4:
590 case EOpConstructUInt:
591 case EOpConstructBVec2:
592 case EOpConstructBVec3:
593 case EOpConstructBVec4:
594 case EOpConstructBool:
595 case EOpConstructStruct:
596 return true;
597 default:
598 return false;
599 }
600}
601
Olli Etuaho1dded802016-08-18 18:13:13 +0300602TOperator TIntermBinary::GetMulOpBasedOnOperands(const TType &left, const TType &right)
603{
604 if (left.isMatrix())
605 {
606 if (right.isMatrix())
607 {
608 return EOpMatrixTimesMatrix;
609 }
610 else
611 {
612 if (right.isVector())
613 {
614 return EOpMatrixTimesVector;
615 }
616 else
617 {
618 return EOpMatrixTimesScalar;
619 }
620 }
621 }
622 else
623 {
624 if (right.isMatrix())
625 {
626 if (left.isVector())
627 {
628 return EOpVectorTimesMatrix;
629 }
630 else
631 {
632 return EOpMatrixTimesScalar;
633 }
634 }
635 else
636 {
637 // Neither operand is a matrix.
638 if (left.isVector() == right.isVector())
639 {
640 // Leave as component product.
641 return EOpMul;
642 }
643 else
644 {
645 return EOpVectorTimesScalar;
646 }
647 }
648 }
649}
650
651TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const TType &right)
652{
653 if (left.isMatrix())
654 {
655 if (right.isMatrix())
656 {
657 return EOpMatrixTimesMatrixAssign;
658 }
659 else
660 {
661 // right should be scalar, but this may not be validated yet.
662 return EOpMatrixTimesScalarAssign;
663 }
664 }
665 else
666 {
667 if (right.isMatrix())
668 {
669 // Left should be a vector, but this may not be validated yet.
670 return EOpVectorTimesMatrixAssign;
671 }
672 else
673 {
674 // Neither operand is a matrix.
675 if (left.isVector() == right.isVector())
676 {
677 // Leave as component product.
678 return EOpMulAssign;
679 }
680 else
681 {
682 // left should be vector and right should be scalar, but this may not be validated
683 // yet.
684 return EOpVectorTimesScalarAssign;
685 }
686 }
687 }
688}
689
Jamie Madillb1a85f42014-08-19 15:23:24 -0400690//
691// Make sure the type of a unary operator is appropriate for its
692// combination of operation and operand type.
693//
Olli Etuahoa2234302016-08-31 12:05:39 +0300694void TIntermUnary::promote()
Jamie Madillb1a85f42014-08-19 15:23:24 -0400695{
Olli Etuahoa2234302016-08-31 12:05:39 +0300696 TQualifier resultQualifier = EvqTemporary;
697 if (mOperand->getQualifier() == EvqConst)
698 resultQualifier = EvqConst;
699
700 unsigned char operandPrimarySize =
701 static_cast<unsigned char>(mOperand->getType().getNominalSize());
Jamie Madillb1a85f42014-08-19 15:23:24 -0400702 switch (mOp)
703 {
Olli Etuahoa2234302016-08-31 12:05:39 +0300704 case EOpFloatBitsToInt:
705 setType(TType(EbtInt, EbpHigh, resultQualifier, operandPrimarySize));
706 break;
707 case EOpFloatBitsToUint:
708 setType(TType(EbtUInt, EbpHigh, resultQualifier, operandPrimarySize));
709 break;
710 case EOpIntBitsToFloat:
711 case EOpUintBitsToFloat:
712 setType(TType(EbtFloat, EbpHigh, resultQualifier, operandPrimarySize));
713 break;
714 case EOpPackSnorm2x16:
715 case EOpPackUnorm2x16:
716 case EOpPackHalf2x16:
717 setType(TType(EbtUInt, EbpHigh, resultQualifier));
718 break;
719 case EOpUnpackSnorm2x16:
720 case EOpUnpackUnorm2x16:
721 setType(TType(EbtFloat, EbpHigh, resultQualifier, 2));
722 break;
723 case EOpUnpackHalf2x16:
724 setType(TType(EbtFloat, EbpMedium, resultQualifier, 2));
725 break;
726 case EOpAny:
727 case EOpAll:
728 setType(TType(EbtBool, EbpUndefined, resultQualifier));
729 break;
730 case EOpLength:
731 case EOpDeterminant:
732 setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier));
733 break;
734 case EOpTranspose:
735 setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier,
736 static_cast<unsigned char>(mOperand->getType().getRows()),
737 static_cast<unsigned char>(mOperand->getType().getCols())));
738 break;
739 case EOpIsInf:
740 case EOpIsNan:
741 setType(TType(EbtBool, EbpUndefined, resultQualifier, operandPrimarySize));
742 break;
743 default:
744 setType(mOperand->getType());
745 mType.setQualifier(resultQualifier);
746 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400747 }
Olli Etuahoa2234302016-08-31 12:05:39 +0300748}
Jamie Madillb1a85f42014-08-19 15:23:24 -0400749
Olli Etuahob6fa0432016-09-28 16:28:05 +0100750TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets)
751 : TIntermTyped(TType(EbtFloat, EbpUndefined)),
752 mOperand(operand),
753 mSwizzleOffsets(swizzleOffsets)
754{
755 ASSERT(mSwizzleOffsets.size() <= 4);
756 promote();
757}
758
Olli Etuahoa2234302016-08-31 12:05:39 +0300759TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand)
760 : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false)
761{
762 promote();
Jamie Madillb1a85f42014-08-19 15:23:24 -0400763}
764
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300765TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right)
766 : TIntermOperator(op), mLeft(left), mRight(right), mAddIndexClamp(false)
767{
768 promote();
769}
770
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300771TIntermTernary::TIntermTernary(TIntermTyped *cond,
772 TIntermTyped *trueExpression,
773 TIntermTyped *falseExpression)
774 : TIntermTyped(trueExpression->getType()),
775 mCondition(cond),
776 mTrueExpression(trueExpression),
777 mFalseExpression(falseExpression)
778{
779 getTypePointer()->setQualifier(
780 TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression));
781}
782
783// static
784TQualifier TIntermTernary::DetermineQualifier(TIntermTyped *cond,
785 TIntermTyped *trueExpression,
786 TIntermTyped *falseExpression)
787{
788 if (cond->getQualifier() == EvqConst && trueExpression->getQualifier() == EvqConst &&
789 falseExpression->getQualifier() == EvqConst)
790 {
791 return EvqConst;
792 }
793 return EvqTemporary;
794}
795
Olli Etuahob6fa0432016-09-28 16:28:05 +0100796void TIntermSwizzle::promote()
797{
798 TQualifier resultQualifier = EvqTemporary;
799 if (mOperand->getQualifier() == EvqConst)
800 resultQualifier = EvqConst;
801
802 auto numFields = mSwizzleOffsets.size();
803 setType(TType(mOperand->getBasicType(), mOperand->getPrecision(), resultQualifier,
804 static_cast<unsigned char>(numFields)));
805}
806
807bool TIntermSwizzle::hasDuplicateOffsets() const
808{
809 int offsetCount[4] = {0u, 0u, 0u, 0u};
810 for (const auto offset : mSwizzleOffsets)
811 {
812 offsetCount[offset]++;
813 if (offsetCount[offset] > 1)
814 {
815 return true;
816 }
817 }
818 return false;
819}
820
821void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const
822{
823 for (const int offset : mSwizzleOffsets)
824 {
825 switch (offset)
826 {
827 case 0:
828 *out << "x";
829 break;
830 case 1:
831 *out << "y";
832 break;
833 case 2:
834 *out << "z";
835 break;
836 case 3:
837 *out << "w";
838 break;
839 default:
840 UNREACHABLE();
841 }
842 }
843}
844
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100845TQualifier TIntermBinary::GetCommaQualifier(int shaderVersion,
846 const TIntermTyped *left,
847 const TIntermTyped *right)
848{
849 // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
850 if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
851 right->getQualifier() != EvqConst)
852 {
853 return EvqTemporary;
854 }
855 return EvqConst;
856}
Olli Etuahob6fa0432016-09-28 16:28:05 +0100857
858// Establishes the type of the result of the binary operation.
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300859void TIntermBinary::promote()
Jamie Madillb1a85f42014-08-19 15:23:24 -0400860{
Olli Etuaho1dded802016-08-18 18:13:13 +0300861 ASSERT(!isMultiplication() ||
862 mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType()));
863
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100864 // Comma is handled as a special case.
865 if (mOp == EOpComma)
866 {
867 setType(mRight->getType());
868 return;
869 }
870
Jamie Madillb1a85f42014-08-19 15:23:24 -0400871 // Base assumption: just make the type the same as the left
872 // operand. Then only deviations from this need be coded.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400873 setType(mLeft->getType());
874
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200875 TQualifier resultQualifier = EvqConst;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400876 // Binary operations results in temporary variables unless both
877 // operands are const.
878 if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst)
879 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200880 resultQualifier = EvqTemporary;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400881 getTypePointer()->setQualifier(EvqTemporary);
882 }
883
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300884 // Handle indexing ops.
885 switch (mOp)
886 {
887 case EOpIndexDirect:
888 case EOpIndexIndirect:
889 if (mLeft->isArray())
890 {
891 mType.clearArrayness();
892 }
893 else if (mLeft->isMatrix())
894 {
895 setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier,
896 static_cast<unsigned char>(mLeft->getRows())));
897 }
898 else if (mLeft->isVector())
899 {
900 setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier));
901 }
902 else
903 {
904 UNREACHABLE();
905 }
906 return;
907 case EOpIndexDirectStruct:
908 {
909 const TFieldList &fields = mLeft->getType().getStruct()->fields();
910 const int i = mRight->getAsConstantUnion()->getIConst(0);
911 setType(*fields[i]->type());
912 getTypePointer()->setQualifier(resultQualifier);
913 return;
914 }
915 case EOpIndexDirectInterfaceBlock:
916 {
917 const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields();
918 const int i = mRight->getAsConstantUnion()->getIConst(0);
919 setType(*fields[i]->type());
920 getTypePointer()->setQualifier(resultQualifier);
921 return;
922 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300923 default:
924 break;
925 }
926
927 ASSERT(mLeft->isArray() == mRight->isArray());
928
929 // The result gets promoted to the highest precision.
930 TPrecision higherPrecision = GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision());
931 getTypePointer()->setPrecision(higherPrecision);
932
Jamie Madillb1a85f42014-08-19 15:23:24 -0400933 const int nominalSize =
934 std::max(mLeft->getNominalSize(), mRight->getNominalSize());
935
936 //
937 // All scalars or structs. Code after this test assumes this case is removed!
938 //
939 if (nominalSize == 1)
940 {
941 switch (mOp)
942 {
943 //
944 // Promote to conditional
945 //
946 case EOpEqual:
947 case EOpNotEqual:
948 case EOpLessThan:
949 case EOpGreaterThan:
950 case EOpLessThanEqual:
951 case EOpGreaterThanEqual:
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300952 setType(TType(EbtBool, EbpUndefined, resultQualifier));
953 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400954
955 //
956 // And and Or operate on conditionals
957 //
958 case EOpLogicalAnd:
Olli Etuaho47fd36a2015-03-19 14:22:24 +0200959 case EOpLogicalXor:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400960 case EOpLogicalOr:
Olli Etuaho47fd36a2015-03-19 14:22:24 +0200961 ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool);
Olli Etuahoc9550582016-08-29 17:56:22 +0300962 setType(TType(EbtBool, EbpUndefined, resultQualifier));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400963 break;
964
965 default:
966 break;
967 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300968 return;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400969 }
970
971 // If we reach here, at least one of the operands is vector or matrix.
972 // The other operand could be a scalar, vector, or matrix.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400973 TBasicType basicType = mLeft->getBasicType();
Olli Etuaho1dded802016-08-18 18:13:13 +0300974
Jamie Madillb1a85f42014-08-19 15:23:24 -0400975 switch (mOp)
976 {
Olli Etuaho1dded802016-08-18 18:13:13 +0300977 case EOpMul:
978 break;
979 case EOpMatrixTimesScalar:
980 if (mRight->isMatrix())
Jamie Madillb1a85f42014-08-19 15:23:24 -0400981 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200982 setType(TType(basicType, higherPrecision, resultQualifier,
983 static_cast<unsigned char>(mRight->getCols()),
984 static_cast<unsigned char>(mRight->getRows())));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400985 }
Olli Etuaho1dded802016-08-18 18:13:13 +0300986 break;
987 case EOpMatrixTimesVector:
988 setType(TType(basicType, higherPrecision, resultQualifier,
989 static_cast<unsigned char>(mLeft->getRows()), 1));
990 break;
991 case EOpMatrixTimesMatrix:
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200992 setType(TType(basicType, higherPrecision, resultQualifier,
993 static_cast<unsigned char>(mRight->getCols()),
994 static_cast<unsigned char>(mLeft->getRows())));
Olli Etuaho1dded802016-08-18 18:13:13 +0300995 break;
996 case EOpVectorTimesScalar:
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200997 setType(TType(basicType, higherPrecision, resultQualifier,
Olli Etuaho1dded802016-08-18 18:13:13 +0300998 static_cast<unsigned char>(nominalSize), 1));
999 break;
1000 case EOpVectorTimesMatrix:
1001 setType(TType(basicType, higherPrecision, resultQualifier,
1002 static_cast<unsigned char>(mRight->getCols()), 1));
1003 break;
1004 case EOpMulAssign:
1005 case EOpVectorTimesScalarAssign:
1006 case EOpVectorTimesMatrixAssign:
1007 case EOpMatrixTimesScalarAssign:
1008 case EOpMatrixTimesMatrixAssign:
1009 ASSERT(mOp == GetMulAssignOpBasedOnOperands(mLeft->getType(), mRight->getType()));
1010 break;
1011 case EOpAssign:
1012 case EOpInitialize:
Olli Etuaho1dded802016-08-18 18:13:13 +03001013 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
1014 (mLeft->getSecondarySize() == mRight->getSecondarySize()));
1015 break;
1016 case EOpAdd:
1017 case EOpSub:
1018 case EOpDiv:
1019 case EOpIMod:
1020 case EOpBitShiftLeft:
1021 case EOpBitShiftRight:
1022 case EOpBitwiseAnd:
1023 case EOpBitwiseXor:
1024 case EOpBitwiseOr:
1025 case EOpAddAssign:
1026 case EOpSubAssign:
1027 case EOpDivAssign:
1028 case EOpIModAssign:
1029 case EOpBitShiftLeftAssign:
1030 case EOpBitShiftRightAssign:
1031 case EOpBitwiseAndAssign:
1032 case EOpBitwiseXorAssign:
1033 case EOpBitwiseOrAssign:
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001034 {
1035 const int secondarySize =
1036 std::max(mLeft->getSecondarySize(), mRight->getSecondarySize());
1037 setType(TType(basicType, higherPrecision, resultQualifier,
1038 static_cast<unsigned char>(nominalSize),
1039 static_cast<unsigned char>(secondarySize)));
1040 ASSERT(!mLeft->isArray() && !mRight->isArray());
Olli Etuaho1dded802016-08-18 18:13:13 +03001041 break;
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001042 }
Olli Etuaho1dded802016-08-18 18:13:13 +03001043 case EOpEqual:
1044 case EOpNotEqual:
1045 case EOpLessThan:
1046 case EOpGreaterThan:
1047 case EOpLessThanEqual:
1048 case EOpGreaterThanEqual:
1049 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
1050 (mLeft->getSecondarySize() == mRight->getSecondarySize()));
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001051 setType(TType(EbtBool, EbpUndefined, resultQualifier));
Olli Etuaho1dded802016-08-18 18:13:13 +03001052 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001053
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001054 case EOpIndexDirect:
1055 case EOpIndexIndirect:
1056 case EOpIndexDirectInterfaceBlock:
1057 case EOpIndexDirectStruct:
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001058 // These ops should be already fully handled.
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001059 UNREACHABLE();
1060 break;
Olli Etuaho1dded802016-08-18 18:13:13 +03001061 default:
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001062 UNREACHABLE();
1063 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001064 }
Jamie Madillb1a85f42014-08-19 15:23:24 -04001065}
1066
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001067const TConstantUnion *TIntermConstantUnion::foldIndexing(int index)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001068{
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001069 if (isArray())
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001070 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001071 ASSERT(index < static_cast<int>(getType().getArraySize()));
1072 TType arrayElementType = getType();
1073 arrayElementType.clearArrayness();
1074 size_t arrayElementSize = arrayElementType.getObjectSize();
1075 return &mUnionArrayPointer[arrayElementSize * index];
1076 }
1077 else if (isMatrix())
1078 {
1079 ASSERT(index < getType().getCols());
1080 int size = getType().getRows();
1081 return &mUnionArrayPointer[size * index];
1082 }
1083 else if (isVector())
1084 {
1085 ASSERT(index < getType().getNominalSize());
1086 return &mUnionArrayPointer[index];
1087 }
1088 else
1089 {
1090 UNREACHABLE();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001091 return nullptr;
1092 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001093}
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001094
Olli Etuahob6fa0432016-09-28 16:28:05 +01001095TIntermTyped *TIntermSwizzle::fold()
1096{
1097 TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
1098 if (operandConstant == nullptr)
1099 {
1100 return nullptr;
1101 }
1102
1103 TConstantUnion *constArray = new TConstantUnion[mSwizzleOffsets.size()];
1104 for (size_t i = 0; i < mSwizzleOffsets.size(); ++i)
1105 {
1106 constArray[i] = *operandConstant->foldIndexing(mSwizzleOffsets.at(i));
1107 }
1108 return CreateFoldedNode(constArray, this, mType.getQualifier());
1109}
1110
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001111TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
1112{
1113 TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion();
1114 TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion();
1115 switch (mOp)
1116 {
1117 case EOpIndexDirect:
1118 {
1119 if (leftConstant == nullptr || rightConstant == nullptr)
1120 {
1121 return nullptr;
1122 }
1123 int index = rightConstant->getIConst(0);
1124
1125 const TConstantUnion *constArray = leftConstant->foldIndexing(index);
1126 return CreateFoldedNode(constArray, this, mType.getQualifier());
1127 }
1128 case EOpIndexDirectStruct:
1129 {
1130 if (leftConstant == nullptr || rightConstant == nullptr)
1131 {
1132 return nullptr;
1133 }
1134 const TFieldList &fields = mLeft->getType().getStruct()->fields();
1135 size_t index = static_cast<size_t>(rightConstant->getIConst(0));
1136
1137 size_t previousFieldsSize = 0;
1138 for (size_t i = 0; i < index; ++i)
1139 {
1140 previousFieldsSize += fields[i]->type()->getObjectSize();
1141 }
1142
1143 const TConstantUnion *constArray = leftConstant->getUnionArrayPointer();
1144 return CreateFoldedNode(constArray + previousFieldsSize, this, mType.getQualifier());
1145 }
1146 case EOpIndexIndirect:
1147 case EOpIndexDirectInterfaceBlock:
1148 // Can never be constant folded.
1149 return nullptr;
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001150 default:
1151 {
1152 if (leftConstant == nullptr || rightConstant == nullptr)
1153 {
1154 return nullptr;
1155 }
Jamie Madill5db69f52016-09-15 12:47:32 -04001156 TConstantUnion *constArray =
1157 leftConstant->foldBinary(mOp, rightConstant, diagnostics, mLeft->getLine());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001158
1159 // Nodes may be constant folded without being qualified as constant.
1160 return CreateFoldedNode(constArray, this, mType.getQualifier());
1161 }
1162 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001163}
1164
Olli Etuahof119a262016-08-19 15:54:22 +03001165TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
Olli Etuaho95310b02015-06-02 17:43:38 +03001166{
1167 TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
1168 if (operandConstant == nullptr)
1169 {
1170 return nullptr;
1171 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301172
1173 TConstantUnion *constArray = nullptr;
1174 switch (mOp)
1175 {
1176 case EOpAny:
1177 case EOpAll:
1178 case EOpLength:
1179 case EOpTranspose:
1180 case EOpDeterminant:
1181 case EOpInverse:
1182 case EOpPackSnorm2x16:
1183 case EOpUnpackSnorm2x16:
1184 case EOpPackUnorm2x16:
1185 case EOpUnpackUnorm2x16:
1186 case EOpPackHalf2x16:
1187 case EOpUnpackHalf2x16:
Olli Etuahof119a262016-08-19 15:54:22 +03001188 constArray = operandConstant->foldUnaryNonComponentWise(mOp);
1189 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301190 default:
Olli Etuahof119a262016-08-19 15:54:22 +03001191 constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics);
1192 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301193 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001194
1195 // Nodes may be constant folded without being qualified as constant.
Olli Etuahoc9550582016-08-29 17:56:22 +03001196 return CreateFoldedNode(constArray, this, mType.getQualifier());
Olli Etuahob43846e2015-06-02 18:18:57 +03001197}
1198
Olli Etuahof119a262016-08-19 15:54:22 +03001199TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics)
Olli Etuahob43846e2015-06-02 18:18:57 +03001200{
1201 // Make sure that all params are constant before actual constant folding.
1202 for (auto *param : *getSequence())
Olli Etuaho95310b02015-06-02 17:43:38 +03001203 {
Olli Etuahob43846e2015-06-02 18:18:57 +03001204 if (param->getAsConstantUnion() == nullptr)
1205 {
1206 return nullptr;
1207 }
Olli Etuaho95310b02015-06-02 17:43:38 +03001208 }
Olli Etuaho1d122782015-11-06 15:35:17 +02001209 TConstantUnion *constArray = nullptr;
1210 if (isConstructor())
Olli Etuahof119a262016-08-19 15:54:22 +03001211 constArray = TIntermConstantUnion::FoldAggregateConstructor(this);
Olli Etuaho1d122782015-11-06 15:35:17 +02001212 else
Olli Etuahof119a262016-08-19 15:54:22 +03001213 constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001214
1215 // Nodes may be constant folded without being qualified as constant.
1216 TQualifier resultQualifier = areChildrenConstQualified() ? EvqConst : EvqTemporary;
1217 return CreateFoldedNode(constArray, this, resultQualifier);
Olli Etuaho95310b02015-06-02 17:43:38 +03001218}
1219
Jamie Madillb1a85f42014-08-19 15:23:24 -04001220//
1221// The fold functions see if an operation on a constant can be done in place,
1222// without generating run-time code.
1223//
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001224// Returns the constant value to keep using or nullptr.
Jamie Madillb1a85f42014-08-19 15:23:24 -04001225//
Olli Etuaho3fdec912016-08-18 15:08:06 +03001226TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op,
1227 TIntermConstantUnion *rightNode,
Jamie Madill5db69f52016-09-15 12:47:32 -04001228 TDiagnostics *diagnostics,
1229 const TSourceLoc &line)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001230{
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001231 const TConstantUnion *leftArray = getUnionArrayPointer();
1232 const TConstantUnion *rightArray = rightNode->getUnionArrayPointer();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001233
Olli Etuahof119a262016-08-19 15:54:22 +03001234 ASSERT(leftArray && rightArray);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001235
1236 size_t objectSize = getType().getObjectSize();
1237
1238 // for a case like float f = vec4(2, 3, 4, 5) + 1.2;
1239 if (rightNode->getType().getObjectSize() == 1 && objectSize > 1)
1240 {
1241 rightArray = Vectorize(*rightNode->getUnionArrayPointer(), objectSize);
1242 }
1243 else if (rightNode->getType().getObjectSize() > 1 && objectSize == 1)
1244 {
1245 // for a case like float f = 1.2 + vec4(2, 3, 4, 5);
1246 leftArray = Vectorize(*getUnionArrayPointer(), rightNode->getType().getObjectSize());
1247 objectSize = rightNode->getType().getObjectSize();
1248 }
1249
1250 TConstantUnion *resultArray = nullptr;
1251
1252 switch(op)
1253 {
1254 case EOpAdd:
1255 resultArray = new TConstantUnion[objectSize];
1256 for (size_t i = 0; i < objectSize; i++)
Jamie Madill5db69f52016-09-15 12:47:32 -04001257 resultArray[i] = TConstantUnion::add(leftArray[i], rightArray[i], diagnostics, line);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001258 break;
1259 case EOpSub:
1260 resultArray = new TConstantUnion[objectSize];
1261 for (size_t i = 0; i < objectSize; i++)
Jamie Madill5db69f52016-09-15 12:47:32 -04001262 resultArray[i] = TConstantUnion::sub(leftArray[i], rightArray[i], diagnostics, line);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001263 break;
1264
1265 case EOpMul:
1266 case EOpVectorTimesScalar:
1267 case EOpMatrixTimesScalar:
1268 resultArray = new TConstantUnion[objectSize];
1269 for (size_t i = 0; i < objectSize; i++)
Jamie Madill5db69f52016-09-15 12:47:32 -04001270 resultArray[i] = TConstantUnion::mul(leftArray[i], rightArray[i], diagnostics, line);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001271 break;
1272
1273 case EOpMatrixTimesMatrix:
1274 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001275 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001276 ASSERT(getType().getBasicType() == EbtFloat && rightNode->getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001277
1278 const int leftCols = getCols();
1279 const int leftRows = getRows();
1280 const int rightCols = rightNode->getType().getCols();
1281 const int rightRows = rightNode->getType().getRows();
1282 const int resultCols = rightCols;
1283 const int resultRows = leftRows;
1284
1285 resultArray = new TConstantUnion[resultCols * resultRows];
1286 for (int row = 0; row < resultRows; row++)
1287 {
1288 for (int column = 0; column < resultCols; column++)
1289 {
1290 resultArray[resultRows * column + row].setFConst(0.0f);
1291 for (int i = 0; i < leftCols; i++)
1292 {
1293 resultArray[resultRows * column + row].setFConst(
1294 resultArray[resultRows * column + row].getFConst() +
1295 leftArray[i * leftRows + row].getFConst() *
1296 rightArray[column * rightRows + i].getFConst());
1297 }
1298 }
1299 }
1300 }
1301 break;
1302
1303 case EOpDiv:
1304 case EOpIMod:
1305 {
1306 resultArray = new TConstantUnion[objectSize];
1307 for (size_t i = 0; i < objectSize; i++)
1308 {
1309 switch (getType().getBasicType())
1310 {
1311 case EbtFloat:
1312 if (rightArray[i] == 0.0f)
1313 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001314 diagnostics->warning(
1315 getLine(), "Divide by zero error during constant folding", "/", "");
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001316 resultArray[i].setFConst(leftArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
1317 }
1318 else
1319 {
1320 ASSERT(op == EOpDiv);
1321 resultArray[i].setFConst(leftArray[i].getFConst() / rightArray[i].getFConst());
1322 }
1323 break;
1324
1325 case EbtInt:
1326 if (rightArray[i] == 0)
1327 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001328 diagnostics->warning(
1329 getLine(), "Divide by zero error during constant folding", "/", "");
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001330 resultArray[i].setIConst(INT_MAX);
1331 }
1332 else
1333 {
Olli Etuahod4453572016-09-27 13:21:46 +01001334 int lhs = leftArray[i].getIConst();
1335 int divisor = rightArray[i].getIConst();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001336 if (op == EOpDiv)
1337 {
Olli Etuahod4453572016-09-27 13:21:46 +01001338 // Check for the special case where the minimum representable number is
1339 // divided by -1. If left alone this leads to integer overflow in C++.
1340 // ESSL 3.00.6 section 4.1.3 Integers:
1341 // "However, for the case where the minimum representable value is
1342 // divided by -1, it is allowed to return either the minimum
1343 // representable value or the maximum representable value."
1344 if (lhs == -0x7fffffff - 1 && divisor == -1)
1345 {
1346 resultArray[i].setIConst(0x7fffffff);
1347 }
1348 else
1349 {
1350 resultArray[i].setIConst(lhs / divisor);
1351 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001352 }
1353 else
1354 {
1355 ASSERT(op == EOpIMod);
Olli Etuahod4453572016-09-27 13:21:46 +01001356 if (lhs < 0 || divisor < 0)
1357 {
1358 // ESSL 3.00.6 section 5.9: Results of modulus are undefined when
1359 // either one of the operands is negative.
1360 diagnostics->warning(getLine(),
1361 "Negative modulus operator operand "
1362 "encountered during constant folding",
1363 "%", "");
1364 resultArray[i].setIConst(0);
1365 }
1366 else
1367 {
1368 resultArray[i].setIConst(lhs % divisor);
1369 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001370 }
1371 }
1372 break;
1373
1374 case EbtUInt:
1375 if (rightArray[i] == 0)
1376 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001377 diagnostics->warning(
1378 getLine(), "Divide by zero error during constant folding", "/", "");
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001379 resultArray[i].setUConst(UINT_MAX);
1380 }
1381 else
1382 {
1383 if (op == EOpDiv)
1384 {
1385 resultArray[i].setUConst(leftArray[i].getUConst() / rightArray[i].getUConst());
1386 }
1387 else
1388 {
1389 ASSERT(op == EOpIMod);
1390 resultArray[i].setUConst(leftArray[i].getUConst() % rightArray[i].getUConst());
1391 }
1392 }
1393 break;
1394
1395 default:
Olli Etuaho3fdec912016-08-18 15:08:06 +03001396 UNREACHABLE();
1397 return nullptr;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001398 }
1399 }
1400 }
1401 break;
1402
1403 case EOpMatrixTimesVector:
1404 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001405 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001406 ASSERT(rightNode->getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001407
1408 const int matrixCols = getCols();
1409 const int matrixRows = getRows();
1410
1411 resultArray = new TConstantUnion[matrixRows];
1412
1413 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
1414 {
1415 resultArray[matrixRow].setFConst(0.0f);
1416 for (int col = 0; col < matrixCols; col++)
1417 {
1418 resultArray[matrixRow].setFConst(resultArray[matrixRow].getFConst() +
1419 leftArray[col * matrixRows + matrixRow].getFConst() *
1420 rightArray[col].getFConst());
1421 }
1422 }
1423 }
1424 break;
1425
1426 case EOpVectorTimesMatrix:
1427 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001428 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001429 ASSERT(getType().getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001430
1431 const int matrixCols = rightNode->getType().getCols();
1432 const int matrixRows = rightNode->getType().getRows();
1433
1434 resultArray = new TConstantUnion[matrixCols];
1435
1436 for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++)
1437 {
1438 resultArray[matrixCol].setFConst(0.0f);
1439 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
1440 {
1441 resultArray[matrixCol].setFConst(resultArray[matrixCol].getFConst() +
1442 leftArray[matrixRow].getFConst() *
1443 rightArray[matrixCol * matrixRows + matrixRow].getFConst());
1444 }
1445 }
1446 }
1447 break;
1448
1449 case EOpLogicalAnd:
1450 {
1451 resultArray = new TConstantUnion[objectSize];
1452 for (size_t i = 0; i < objectSize; i++)
1453 {
1454 resultArray[i] = leftArray[i] && rightArray[i];
1455 }
1456 }
1457 break;
1458
1459 case EOpLogicalOr:
1460 {
1461 resultArray = new TConstantUnion[objectSize];
1462 for (size_t i = 0; i < objectSize; i++)
1463 {
1464 resultArray[i] = leftArray[i] || rightArray[i];
1465 }
1466 }
1467 break;
1468
1469 case EOpLogicalXor:
1470 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001471 ASSERT(getType().getBasicType() == EbtBool);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001472 resultArray = new TConstantUnion[objectSize];
1473 for (size_t i = 0; i < objectSize; i++)
1474 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001475 resultArray[i].setBConst(leftArray[i] != rightArray[i]);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001476 }
1477 }
1478 break;
1479
1480 case EOpBitwiseAnd:
1481 resultArray = new TConstantUnion[objectSize];
1482 for (size_t i = 0; i < objectSize; i++)
1483 resultArray[i] = leftArray[i] & rightArray[i];
1484 break;
1485 case EOpBitwiseXor:
1486 resultArray = new TConstantUnion[objectSize];
1487 for (size_t i = 0; i < objectSize; i++)
1488 resultArray[i] = leftArray[i] ^ rightArray[i];
1489 break;
1490 case EOpBitwiseOr:
1491 resultArray = new TConstantUnion[objectSize];
1492 for (size_t i = 0; i < objectSize; i++)
1493 resultArray[i] = leftArray[i] | rightArray[i];
1494 break;
1495 case EOpBitShiftLeft:
1496 resultArray = new TConstantUnion[objectSize];
1497 for (size_t i = 0; i < objectSize; i++)
Jamie Madill596018c2016-09-21 12:57:03 -04001498 resultArray[i] = TConstantUnion::lshift(leftArray[i], rightArray[i], diagnostics, line);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001499 break;
1500 case EOpBitShiftRight:
1501 resultArray = new TConstantUnion[objectSize];
1502 for (size_t i = 0; i < objectSize; i++)
Jamie Madill596018c2016-09-21 12:57:03 -04001503 resultArray[i] = TConstantUnion::rshift(leftArray[i], rightArray[i], diagnostics, line);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001504 break;
1505
1506 case EOpLessThan:
1507 ASSERT(objectSize == 1);
1508 resultArray = new TConstantUnion[1];
1509 resultArray->setBConst(*leftArray < *rightArray);
1510 break;
1511
1512 case EOpGreaterThan:
1513 ASSERT(objectSize == 1);
1514 resultArray = new TConstantUnion[1];
1515 resultArray->setBConst(*leftArray > *rightArray);
1516 break;
1517
1518 case EOpLessThanEqual:
1519 ASSERT(objectSize == 1);
1520 resultArray = new TConstantUnion[1];
1521 resultArray->setBConst(!(*leftArray > *rightArray));
1522 break;
1523
1524 case EOpGreaterThanEqual:
1525 ASSERT(objectSize == 1);
1526 resultArray = new TConstantUnion[1];
1527 resultArray->setBConst(!(*leftArray < *rightArray));
1528 break;
1529
1530 case EOpEqual:
1531 case EOpNotEqual:
1532 {
1533 resultArray = new TConstantUnion[1];
1534 bool equal = true;
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001535 for (size_t i = 0; i < objectSize; i++)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001536 {
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001537 if (leftArray[i] != rightArray[i])
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001538 {
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001539 equal = false;
1540 break; // break out of for loop
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001541 }
1542 }
1543 if (op == EOpEqual)
1544 {
1545 resultArray->setBConst(equal);
1546 }
1547 else
1548 {
1549 resultArray->setBConst(!equal);
1550 }
1551 }
1552 break;
1553
1554 default:
Olli Etuaho3fdec912016-08-18 15:08:06 +03001555 UNREACHABLE();
1556 return nullptr;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001557 }
1558 return resultArray;
1559}
1560
Olli Etuahof119a262016-08-19 15:54:22 +03001561// The fold functions do operations on a constant at GLSL compile time, without generating run-time
1562// code. Returns the constant value to keep using. Nullptr should not be returned.
1563TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op)
Jamie Madillb1a85f42014-08-19 15:23:24 -04001564{
Olli Etuahof119a262016-08-19 15:54:22 +03001565 // Do operations where the return type may have a different number of components compared to the
1566 // operand type.
Jamie Madillb1a85f42014-08-19 15:23:24 -04001567
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001568 const TConstantUnion *operandArray = getUnionArrayPointer();
Olli Etuahof119a262016-08-19 15:54:22 +03001569 ASSERT(operandArray);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301570
1571 size_t objectSize = getType().getObjectSize();
1572 TConstantUnion *resultArray = nullptr;
1573 switch (op)
1574 {
Olli Etuahof119a262016-08-19 15:54:22 +03001575 case EOpAny:
1576 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301577 resultArray = new TConstantUnion();
1578 resultArray->setBConst(false);
1579 for (size_t i = 0; i < objectSize; i++)
1580 {
1581 if (operandArray[i].getBConst())
1582 {
1583 resultArray->setBConst(true);
1584 break;
1585 }
1586 }
1587 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301588
Olli Etuahof119a262016-08-19 15:54:22 +03001589 case EOpAll:
1590 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301591 resultArray = new TConstantUnion();
1592 resultArray->setBConst(true);
1593 for (size_t i = 0; i < objectSize; i++)
1594 {
1595 if (!operandArray[i].getBConst())
1596 {
1597 resultArray->setBConst(false);
1598 break;
1599 }
1600 }
1601 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301602
Olli Etuahof119a262016-08-19 15:54:22 +03001603 case EOpLength:
1604 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301605 resultArray = new TConstantUnion();
1606 resultArray->setFConst(VectorLength(operandArray, objectSize));
1607 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301608
Olli Etuahof119a262016-08-19 15:54:22 +03001609 case EOpTranspose:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301610 {
Olli Etuahof119a262016-08-19 15:54:22 +03001611 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301612 resultArray = new TConstantUnion[objectSize];
1613 angle::Matrix<float> result =
Olli Etuahod5da5052016-08-29 13:16:55 +03001614 GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose();
Arun Patoleab2b9a22015-07-06 18:27:56 +05301615 SetUnionArrayFromMatrix(result, resultArray);
1616 break;
1617 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301618
Olli Etuahof119a262016-08-19 15:54:22 +03001619 case EOpDeterminant:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301620 {
Olli Etuahof119a262016-08-19 15:54:22 +03001621 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301622 unsigned int size = getType().getNominalSize();
1623 ASSERT(size >= 2 && size <= 4);
1624 resultArray = new TConstantUnion();
1625 resultArray->setFConst(GetMatrix(operandArray, size).determinant());
1626 break;
1627 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301628
Olli Etuahof119a262016-08-19 15:54:22 +03001629 case EOpInverse:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301630 {
Olli Etuahof119a262016-08-19 15:54:22 +03001631 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301632 unsigned int size = getType().getNominalSize();
1633 ASSERT(size >= 2 && size <= 4);
Olli Etuahof119a262016-08-19 15:54:22 +03001634 resultArray = new TConstantUnion[objectSize];
Arun Patoleab2b9a22015-07-06 18:27:56 +05301635 angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
1636 SetUnionArrayFromMatrix(result, resultArray);
1637 break;
1638 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301639
Olli Etuahof119a262016-08-19 15:54:22 +03001640 case EOpPackSnorm2x16:
1641 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301642 ASSERT(getType().getNominalSize() == 2);
1643 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001644 resultArray->setUConst(
1645 gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301646 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301647
Olli Etuahof119a262016-08-19 15:54:22 +03001648 case EOpUnpackSnorm2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301649 {
Olli Etuahof119a262016-08-19 15:54:22 +03001650 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301651 resultArray = new TConstantUnion[2];
1652 float f1, f2;
1653 gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
1654 resultArray[0].setFConst(f1);
1655 resultArray[1].setFConst(f2);
1656 break;
1657 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301658
Olli Etuahof119a262016-08-19 15:54:22 +03001659 case EOpPackUnorm2x16:
1660 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301661 ASSERT(getType().getNominalSize() == 2);
1662 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001663 resultArray->setUConst(
1664 gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301665 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301666
Olli Etuahof119a262016-08-19 15:54:22 +03001667 case EOpUnpackUnorm2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301668 {
Olli Etuahof119a262016-08-19 15:54:22 +03001669 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301670 resultArray = new TConstantUnion[2];
1671 float f1, f2;
1672 gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
1673 resultArray[0].setFConst(f1);
1674 resultArray[1].setFConst(f2);
1675 break;
1676 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301677
Olli Etuahof119a262016-08-19 15:54:22 +03001678 case EOpPackHalf2x16:
1679 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301680 ASSERT(getType().getNominalSize() == 2);
1681 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001682 resultArray->setUConst(
1683 gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301684 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301685
Olli Etuahof119a262016-08-19 15:54:22 +03001686 case EOpUnpackHalf2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301687 {
Olli Etuahof119a262016-08-19 15:54:22 +03001688 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301689 resultArray = new TConstantUnion[2];
1690 float f1, f2;
1691 gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2);
1692 resultArray[0].setFConst(f1);
1693 resultArray[1].setFConst(f2);
1694 break;
1695 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301696
Olli Etuahof119a262016-08-19 15:54:22 +03001697 default:
1698 UNREACHABLE();
1699 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301700 }
1701
1702 return resultArray;
1703}
1704
Olli Etuahof119a262016-08-19 15:54:22 +03001705TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op,
1706 TDiagnostics *diagnostics)
Arun Patoleab2b9a22015-07-06 18:27:56 +05301707{
Olli Etuahof119a262016-08-19 15:54:22 +03001708 // Do unary operations where each component of the result is computed based on the corresponding
1709 // component of the operand. Also folds normalize, though the divisor in that case takes all
1710 // components into account.
Arun Patoleab2b9a22015-07-06 18:27:56 +05301711
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001712 const TConstantUnion *operandArray = getUnionArrayPointer();
Olli Etuahof119a262016-08-19 15:54:22 +03001713 ASSERT(operandArray);
Jamie Madillb1a85f42014-08-19 15:23:24 -04001714
1715 size_t objectSize = getType().getObjectSize();
1716
Arun Patoleab2b9a22015-07-06 18:27:56 +05301717 TConstantUnion *resultArray = new TConstantUnion[objectSize];
1718 for (size_t i = 0; i < objectSize; i++)
Arun Patole9d0b1f92015-05-20 14:27:17 +05301719 {
Arun Patoleab2b9a22015-07-06 18:27:56 +05301720 switch(op)
Arun Patole9d0b1f92015-05-20 14:27:17 +05301721 {
Olli Etuahof119a262016-08-19 15:54:22 +03001722 case EOpNegative:
1723 switch (getType().getBasicType())
1724 {
1725 case EbtFloat:
1726 resultArray[i].setFConst(-operandArray[i].getFConst());
1727 break;
1728 case EbtInt:
Olli Etuaho42fad762016-09-28 10:06:29 +01001729 if (operandArray[i] == std::numeric_limits<int>::min())
1730 {
1731 // The minimum representable integer doesn't have a positive
1732 // counterpart, rather the negation overflows and in ESSL is supposed to
1733 // wrap back to the minimum representable integer. Make sure that we
1734 // don't actually let the negation overflow, which has undefined
1735 // behavior in C++.
1736 resultArray[i].setIConst(std::numeric_limits<int>::min());
1737 }
1738 else
1739 {
1740 resultArray[i].setIConst(-operandArray[i].getIConst());
1741 }
Olli Etuahof119a262016-08-19 15:54:22 +03001742 break;
1743 case EbtUInt:
Olli Etuaho42fad762016-09-28 10:06:29 +01001744 if (operandArray[i] == 0x80000000u)
1745 {
1746 resultArray[i].setUConst(0x80000000u);
1747 }
1748 else
1749 {
1750 resultArray[i].setUConst(static_cast<unsigned int>(
1751 -static_cast<int>(operandArray[i].getUConst())));
1752 }
Olli Etuahof119a262016-08-19 15:54:22 +03001753 break;
1754 default:
1755 UNREACHABLE();
1756 return nullptr;
1757 }
Arun Patole1155ddd2015-06-05 18:04:36 +05301758 break;
Arun Patolecdfa8f52015-06-30 17:48:25 +05301759
Olli Etuahof119a262016-08-19 15:54:22 +03001760 case EOpPositive:
1761 switch (getType().getBasicType())
1762 {
1763 case EbtFloat:
1764 resultArray[i].setFConst(operandArray[i].getFConst());
1765 break;
1766 case EbtInt:
1767 resultArray[i].setIConst(operandArray[i].getIConst());
1768 break;
1769 case EbtUInt:
1770 resultArray[i].setUConst(static_cast<unsigned int>(
1771 static_cast<int>(operandArray[i].getUConst())));
1772 break;
1773 default:
1774 UNREACHABLE();
1775 return nullptr;
1776 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301777 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301778
Olli Etuahof119a262016-08-19 15:54:22 +03001779 case EOpLogicalNot:
1780 switch (getType().getBasicType())
1781 {
1782 case EbtBool:
1783 resultArray[i].setBConst(!operandArray[i].getBConst());
1784 break;
1785 default:
1786 UNREACHABLE();
1787 return nullptr;
1788 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301789 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301790
Olli Etuahof119a262016-08-19 15:54:22 +03001791 case EOpBitwiseNot:
1792 switch (getType().getBasicType())
1793 {
1794 case EbtInt:
1795 resultArray[i].setIConst(~operandArray[i].getIConst());
1796 break;
1797 case EbtUInt:
1798 resultArray[i].setUConst(~operandArray[i].getUConst());
1799 break;
1800 default:
1801 UNREACHABLE();
1802 return nullptr;
1803 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301804 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301805
Olli Etuahof119a262016-08-19 15:54:22 +03001806 case EOpRadians:
1807 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301808 resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
1809 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301810
Olli Etuahof119a262016-08-19 15:54:22 +03001811 case EOpDegrees:
1812 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301813 resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
1814 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301815
Olli Etuahof119a262016-08-19 15:54:22 +03001816 case EOpSin:
1817 foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301818 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301819
Olli Etuahof119a262016-08-19 15:54:22 +03001820 case EOpCos:
1821 foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]);
1822 break;
1823
1824 case EOpTan:
1825 foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]);
1826 break;
1827
1828 case EOpAsin:
1829 // For asin(x), results are undefined if |x| > 1, we are choosing to set result to
1830 // 0.
1831 if (fabsf(operandArray[i].getFConst()) > 1.0f)
1832 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1833 diagnostics, &resultArray[i]);
1834 else
1835 foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]);
1836 break;
1837
1838 case EOpAcos:
1839 // For acos(x), results are undefined if |x| > 1, we are choosing to set result to
1840 // 0.
1841 if (fabsf(operandArray[i].getFConst()) > 1.0f)
1842 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1843 diagnostics, &resultArray[i]);
1844 else
1845 foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]);
1846 break;
1847
1848 case EOpAtan:
1849 foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]);
1850 break;
1851
1852 case EOpSinh:
1853 foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]);
1854 break;
1855
1856 case EOpCosh:
1857 foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]);
1858 break;
1859
1860 case EOpTanh:
1861 foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]);
1862 break;
1863
1864 case EOpAsinh:
1865 foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]);
1866 break;
1867
1868 case EOpAcosh:
1869 // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
1870 if (operandArray[i].getFConst() < 1.0f)
1871 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1872 diagnostics, &resultArray[i]);
1873 else
1874 foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]);
1875 break;
1876
1877 case EOpAtanh:
1878 // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to
1879 // 0.
1880 if (fabsf(operandArray[i].getFConst()) >= 1.0f)
1881 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1882 diagnostics, &resultArray[i]);
1883 else
1884 foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]);
1885 break;
1886
1887 case EOpAbs:
1888 switch (getType().getBasicType())
Arun Patoleab2b9a22015-07-06 18:27:56 +05301889 {
Olli Etuahof119a262016-08-19 15:54:22 +03001890 case EbtFloat:
1891 resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
1892 break;
1893 case EbtInt:
1894 resultArray[i].setIConst(abs(operandArray[i].getIConst()));
1895 break;
1896 default:
1897 UNREACHABLE();
1898 return nullptr;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301899 }
1900 break;
Olli Etuahof119a262016-08-19 15:54:22 +03001901
1902 case EOpSign:
1903 switch (getType().getBasicType())
Arun Patoleab2b9a22015-07-06 18:27:56 +05301904 {
Olli Etuahof119a262016-08-19 15:54:22 +03001905 case EbtFloat:
1906 {
1907 float fConst = operandArray[i].getFConst();
1908 float fResult = 0.0f;
1909 if (fConst > 0.0f)
1910 fResult = 1.0f;
1911 else if (fConst < 0.0f)
1912 fResult = -1.0f;
1913 resultArray[i].setFConst(fResult);
1914 break;
1915 }
1916 case EbtInt:
1917 {
1918 int iConst = operandArray[i].getIConst();
1919 int iResult = 0;
1920 if (iConst > 0)
1921 iResult = 1;
1922 else if (iConst < 0)
1923 iResult = -1;
1924 resultArray[i].setIConst(iResult);
1925 break;
1926 }
1927 default:
1928 UNREACHABLE();
1929 return nullptr;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301930 }
1931 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301932
Olli Etuahof119a262016-08-19 15:54:22 +03001933 case EOpFloor:
1934 foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]);
1935 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301936
Olli Etuahof119a262016-08-19 15:54:22 +03001937 case EOpTrunc:
1938 foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]);
1939 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301940
Olli Etuahof119a262016-08-19 15:54:22 +03001941 case EOpRound:
1942 foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]);
1943 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301944
Olli Etuahof119a262016-08-19 15:54:22 +03001945 case EOpRoundEven:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301946 {
Olli Etuahof119a262016-08-19 15:54:22 +03001947 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301948 float x = operandArray[i].getFConst();
1949 float result;
1950 float fractPart = modff(x, &result);
1951 if (fabsf(fractPart) == 0.5f)
1952 result = 2.0f * roundf(x / 2.0f);
1953 else
1954 result = roundf(x);
1955 resultArray[i].setFConst(result);
1956 break;
1957 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301958
Olli Etuahof119a262016-08-19 15:54:22 +03001959 case EOpCeil:
1960 foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]);
1961 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301962
Olli Etuahof119a262016-08-19 15:54:22 +03001963 case EOpFract:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301964 {
Olli Etuahof119a262016-08-19 15:54:22 +03001965 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301966 float x = operandArray[i].getFConst();
1967 resultArray[i].setFConst(x - floorf(x));
1968 break;
1969 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301970
Olli Etuahof119a262016-08-19 15:54:22 +03001971 case EOpIsNan:
1972 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05301973 resultArray[i].setBConst(gl::isNaN(operandArray[0].getFConst()));
1974 break;
Arun Patole551279e2015-07-07 18:18:23 +05301975
Olli Etuahof119a262016-08-19 15:54:22 +03001976 case EOpIsInf:
1977 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05301978 resultArray[i].setBConst(gl::isInf(operandArray[0].getFConst()));
1979 break;
Arun Patole551279e2015-07-07 18:18:23 +05301980
Olli Etuahof119a262016-08-19 15:54:22 +03001981 case EOpFloatBitsToInt:
1982 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05301983 resultArray[i].setIConst(gl::bitCast<int32_t>(operandArray[0].getFConst()));
1984 break;
Arun Patole551279e2015-07-07 18:18:23 +05301985
Olli Etuahof119a262016-08-19 15:54:22 +03001986 case EOpFloatBitsToUint:
1987 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05301988 resultArray[i].setUConst(gl::bitCast<uint32_t>(operandArray[0].getFConst()));
1989 break;
Arun Patole551279e2015-07-07 18:18:23 +05301990
Olli Etuahof119a262016-08-19 15:54:22 +03001991 case EOpIntBitsToFloat:
1992 ASSERT(getType().getBasicType() == EbtInt);
Arun Patole551279e2015-07-07 18:18:23 +05301993 resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getIConst()));
1994 break;
Arun Patole551279e2015-07-07 18:18:23 +05301995
Olli Etuahof119a262016-08-19 15:54:22 +03001996 case EOpUintBitsToFloat:
1997 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patole551279e2015-07-07 18:18:23 +05301998 resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getUConst()));
1999 break;
Arun Patole551279e2015-07-07 18:18:23 +05302000
Olli Etuahof119a262016-08-19 15:54:22 +03002001 case EOpExp:
2002 foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]);
2003 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302004
Olli Etuahof119a262016-08-19 15:54:22 +03002005 case EOpLog:
2006 // For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
2007 if (operandArray[i].getFConst() <= 0.0f)
2008 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2009 diagnostics, &resultArray[i]);
2010 else
2011 foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
2012 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302013
Olli Etuahof119a262016-08-19 15:54:22 +03002014 case EOpExp2:
2015 foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]);
2016 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302017
Olli Etuahof119a262016-08-19 15:54:22 +03002018 case EOpLog2:
2019 // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
2020 // And log2f is not available on some plarforms like old android, so just using
2021 // log(x)/log(2) here.
2022 if (operandArray[i].getFConst() <= 0.0f)
2023 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2024 diagnostics, &resultArray[i]);
2025 else
2026 {
2027 foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
2028 resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
2029 }
2030 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302031
Olli Etuahof119a262016-08-19 15:54:22 +03002032 case EOpSqrt:
2033 // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
2034 if (operandArray[i].getFConst() < 0.0f)
2035 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2036 diagnostics, &resultArray[i]);
2037 else
2038 foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
2039 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302040
Olli Etuahof119a262016-08-19 15:54:22 +03002041 case EOpInverseSqrt:
2042 // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
2043 // so getting the square root first using builtin function sqrt() and then taking
2044 // its inverse.
2045 // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set
2046 // result to 0.
2047 if (operandArray[i].getFConst() <= 0.0f)
2048 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2049 diagnostics, &resultArray[i]);
2050 else
2051 {
2052 foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
2053 resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
2054 }
2055 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302056
Olli Etuahof119a262016-08-19 15:54:22 +03002057 case EOpVectorLogicalNot:
2058 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302059 resultArray[i].setBConst(!operandArray[i].getBConst());
2060 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302061
Olli Etuahof119a262016-08-19 15:54:22 +03002062 case EOpNormalize:
Arun Patoleab2b9a22015-07-06 18:27:56 +05302063 {
Olli Etuahof119a262016-08-19 15:54:22 +03002064 ASSERT(getType().getBasicType() == EbtFloat);
2065 float x = operandArray[i].getFConst();
Arun Patoleab2b9a22015-07-06 18:27:56 +05302066 float length = VectorLength(operandArray, objectSize);
2067 if (length)
2068 resultArray[i].setFConst(x / length);
2069 else
Olli Etuahof119a262016-08-19 15:54:22 +03002070 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2071 diagnostics, &resultArray[i]);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302072 break;
2073 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05302074
Olli Etuahof119a262016-08-19 15:54:22 +03002075 case EOpDFdx:
2076 case EOpDFdy:
2077 case EOpFwidth:
2078 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole0c5409f2015-07-08 15:17:53 +05302079 // Derivatives of constant arguments should be 0.
2080 resultArray[i].setFConst(0.0f);
2081 break;
Arun Patole0c5409f2015-07-08 15:17:53 +05302082
Olli Etuahof119a262016-08-19 15:54:22 +03002083 default:
2084 return nullptr;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302085 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302086 }
Jamie Madillb1a85f42014-08-19 15:23:24 -04002087
Arun Patoleab2b9a22015-07-06 18:27:56 +05302088 return resultArray;
Jamie Madillb1a85f42014-08-19 15:23:24 -04002089}
2090
Olli Etuahof119a262016-08-19 15:54:22 +03002091void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter,
2092 FloatTypeUnaryFunc builtinFunc,
2093 TConstantUnion *result) const
Arun Patole9dea48f2015-04-02 11:45:09 +05302094{
2095 ASSERT(builtinFunc);
2096
Olli Etuahof119a262016-08-19 15:54:22 +03002097 ASSERT(getType().getBasicType() == EbtFloat);
2098 result->setFConst(builtinFunc(parameter.getFConst()));
Arun Patole9dea48f2015-04-02 11:45:09 +05302099}
2100
Jamie Madillb1a85f42014-08-19 15:23:24 -04002101// static
Olli Etuahof119a262016-08-19 15:54:22 +03002102TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate)
Olli Etuaho1d122782015-11-06 15:35:17 +02002103{
2104 ASSERT(aggregate->getSequence()->size() > 0u);
2105 size_t resultSize = aggregate->getType().getObjectSize();
2106 TConstantUnion *resultArray = new TConstantUnion[resultSize];
2107 TBasicType basicType = aggregate->getBasicType();
2108
2109 size_t resultIndex = 0u;
2110
2111 if (aggregate->getSequence()->size() == 1u)
2112 {
2113 TIntermNode *argument = aggregate->getSequence()->front();
2114 TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion();
2115 const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
2116 // Check the special case of constructing a matrix diagonal from a single scalar,
2117 // or a vector from a single scalar.
2118 if (argumentConstant->getType().getObjectSize() == 1u)
2119 {
2120 if (aggregate->isMatrix())
2121 {
2122 int resultCols = aggregate->getType().getCols();
2123 int resultRows = aggregate->getType().getRows();
2124 for (int col = 0; col < resultCols; ++col)
2125 {
2126 for (int row = 0; row < resultRows; ++row)
2127 {
2128 if (col == row)
2129 {
2130 resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
2131 }
2132 else
2133 {
2134 resultArray[resultIndex].setFConst(0.0f);
2135 }
2136 ++resultIndex;
2137 }
2138 }
2139 }
2140 else
2141 {
2142 while (resultIndex < resultSize)
2143 {
2144 resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
2145 ++resultIndex;
2146 }
2147 }
2148 ASSERT(resultIndex == resultSize);
2149 return resultArray;
2150 }
2151 else if (aggregate->isMatrix() && argumentConstant->isMatrix())
2152 {
2153 // The special case of constructing a matrix from a matrix.
2154 int argumentCols = argumentConstant->getType().getCols();
2155 int argumentRows = argumentConstant->getType().getRows();
2156 int resultCols = aggregate->getType().getCols();
2157 int resultRows = aggregate->getType().getRows();
2158 for (int col = 0; col < resultCols; ++col)
2159 {
2160 for (int row = 0; row < resultRows; ++row)
2161 {
2162 if (col < argumentCols && row < argumentRows)
2163 {
2164 resultArray[resultIndex].cast(basicType,
2165 argumentUnionArray[col * argumentRows + row]);
2166 }
2167 else if (col == row)
2168 {
2169 resultArray[resultIndex].setFConst(1.0f);
2170 }
2171 else
2172 {
2173 resultArray[resultIndex].setFConst(0.0f);
2174 }
2175 ++resultIndex;
2176 }
2177 }
2178 ASSERT(resultIndex == resultSize);
2179 return resultArray;
2180 }
2181 }
2182
2183 for (TIntermNode *&argument : *aggregate->getSequence())
2184 {
2185 TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion();
2186 size_t argumentSize = argumentConstant->getType().getObjectSize();
2187 const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
2188 for (size_t i = 0u; i < argumentSize; ++i)
2189 {
2190 if (resultIndex >= resultSize)
2191 break;
2192 resultArray[resultIndex].cast(basicType, argumentUnionArray[i]);
2193 ++resultIndex;
2194 }
2195 }
2196 ASSERT(resultIndex == resultSize);
2197 return resultArray;
2198}
2199
2200// static
Olli Etuahof119a262016-08-19 15:54:22 +03002201TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate,
2202 TDiagnostics *diagnostics)
Arun Patole274f0702015-05-05 13:33:30 +05302203{
Olli Etuahob43846e2015-06-02 18:18:57 +03002204 TOperator op = aggregate->getOp();
Arun Patole274f0702015-05-05 13:33:30 +05302205 TIntermSequence *sequence = aggregate->getSequence();
Cooper Partin4d61f7e2015-08-12 10:56:50 -07002206 unsigned int paramsCount = static_cast<unsigned int>(sequence->size());
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002207 std::vector<const TConstantUnion *> unionArrays(paramsCount);
Arun Patole274f0702015-05-05 13:33:30 +05302208 std::vector<size_t> objectSizes(paramsCount);
Olli Etuahob43846e2015-06-02 18:18:57 +03002209 size_t maxObjectSize = 0;
Arun Patole274f0702015-05-05 13:33:30 +05302210 TBasicType basicType = EbtVoid;
2211 TSourceLoc loc;
2212 for (unsigned int i = 0; i < paramsCount; i++)
2213 {
2214 TIntermConstantUnion *paramConstant = (*sequence)[i]->getAsConstantUnion();
Olli Etuahob43846e2015-06-02 18:18:57 +03002215 ASSERT(paramConstant != nullptr); // Should be checked already.
Arun Patole274f0702015-05-05 13:33:30 +05302216
2217 if (i == 0)
2218 {
2219 basicType = paramConstant->getType().getBasicType();
2220 loc = paramConstant->getLine();
2221 }
2222 unionArrays[i] = paramConstant->getUnionArrayPointer();
2223 objectSizes[i] = paramConstant->getType().getObjectSize();
Olli Etuahob43846e2015-06-02 18:18:57 +03002224 if (objectSizes[i] > maxObjectSize)
2225 maxObjectSize = objectSizes[i];
Arun Patole274f0702015-05-05 13:33:30 +05302226 }
2227
Olli Etuahod5da5052016-08-29 13:16:55 +03002228 if (!(*sequence)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct)
Arun Patole7fa33552015-06-10 15:15:18 +05302229 {
2230 for (unsigned int i = 0; i < paramsCount; i++)
2231 if (objectSizes[i] != maxObjectSize)
2232 unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize);
2233 }
Arun Patole274f0702015-05-05 13:33:30 +05302234
Olli Etuahob43846e2015-06-02 18:18:57 +03002235 TConstantUnion *resultArray = nullptr;
Arun Patole274f0702015-05-05 13:33:30 +05302236 if (paramsCount == 2)
2237 {
2238 //
2239 // Binary built-in
2240 //
2241 switch (op)
2242 {
Olli Etuahof119a262016-08-19 15:54:22 +03002243 case EOpAtan:
Arun Patolebf790422015-05-18 17:53:04 +05302244 {
Olli Etuahof119a262016-08-19 15:54:22 +03002245 ASSERT(basicType == EbtFloat);
2246 resultArray = new TConstantUnion[maxObjectSize];
2247 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302248 {
Olli Etuahof119a262016-08-19 15:54:22 +03002249 float y = unionArrays[0][i].getFConst();
2250 float x = unionArrays[1][i].getFConst();
2251 // Results are undefined if x and y are both 0.
2252 if (x == 0.0f && y == 0.0f)
2253 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2254 &resultArray[i]);
2255 else
2256 resultArray[i].setFConst(atan2f(y, x));
Arun Patolebf790422015-05-18 17:53:04 +05302257 }
Olli Etuahof119a262016-08-19 15:54:22 +03002258 break;
Arun Patolebf790422015-05-18 17:53:04 +05302259 }
Arun Patolebf790422015-05-18 17:53:04 +05302260
Olli Etuahof119a262016-08-19 15:54:22 +03002261 case EOpPow:
Arun Patolebf790422015-05-18 17:53:04 +05302262 {
Olli Etuahof119a262016-08-19 15:54:22 +03002263 ASSERT(basicType == EbtFloat);
2264 resultArray = new TConstantUnion[maxObjectSize];
2265 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302266 {
Olli Etuahof119a262016-08-19 15:54:22 +03002267 float x = unionArrays[0][i].getFConst();
2268 float y = unionArrays[1][i].getFConst();
2269 // Results are undefined if x < 0.
2270 // Results are undefined if x = 0 and y <= 0.
2271 if (x < 0.0f)
2272 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2273 &resultArray[i]);
2274 else if (x == 0.0f && y <= 0.0f)
2275 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2276 &resultArray[i]);
2277 else
2278 resultArray[i].setFConst(powf(x, y));
Arun Patolebf790422015-05-18 17:53:04 +05302279 }
Olli Etuahof119a262016-08-19 15:54:22 +03002280 break;
Arun Patolebf790422015-05-18 17:53:04 +05302281 }
Arun Patolebf790422015-05-18 17:53:04 +05302282
Olli Etuahof119a262016-08-19 15:54:22 +03002283 case EOpMod:
Arun Patolebf790422015-05-18 17:53:04 +05302284 {
Olli Etuahof119a262016-08-19 15:54:22 +03002285 ASSERT(basicType == EbtFloat);
2286 resultArray = new TConstantUnion[maxObjectSize];
2287 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302288 {
Olli Etuahof119a262016-08-19 15:54:22 +03002289 float x = unionArrays[0][i].getFConst();
2290 float y = unionArrays[1][i].getFConst();
2291 resultArray[i].setFConst(x - y * floorf(x / y));
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 EOpMin:
Arun Patole274f0702015-05-05 13:33:30 +05302297 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002298 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole274f0702015-05-05 13:33:30 +05302299 for (size_t i = 0; i < maxObjectSize; i++)
2300 {
2301 switch (basicType)
2302 {
Olli Etuahof119a262016-08-19 15:54:22 +03002303 case EbtFloat:
2304 resultArray[i].setFConst(std::min(unionArrays[0][i].getFConst(),
2305 unionArrays[1][i].getFConst()));
2306 break;
2307 case EbtInt:
2308 resultArray[i].setIConst(std::min(unionArrays[0][i].getIConst(),
2309 unionArrays[1][i].getIConst()));
2310 break;
2311 case EbtUInt:
2312 resultArray[i].setUConst(std::min(unionArrays[0][i].getUConst(),
2313 unionArrays[1][i].getUConst()));
2314 break;
2315 default:
2316 UNREACHABLE();
2317 break;
Arun Patole274f0702015-05-05 13:33:30 +05302318 }
2319 }
Olli Etuahof119a262016-08-19 15:54:22 +03002320 break;
Arun Patole274f0702015-05-05 13:33:30 +05302321 }
Arun Patole274f0702015-05-05 13:33:30 +05302322
Olli Etuahof119a262016-08-19 15:54:22 +03002323 case EOpMax:
Arun Patole274f0702015-05-05 13:33:30 +05302324 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002325 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole274f0702015-05-05 13:33:30 +05302326 for (size_t i = 0; i < maxObjectSize; i++)
2327 {
2328 switch (basicType)
2329 {
Olli Etuahof119a262016-08-19 15:54:22 +03002330 case EbtFloat:
2331 resultArray[i].setFConst(std::max(unionArrays[0][i].getFConst(),
2332 unionArrays[1][i].getFConst()));
2333 break;
2334 case EbtInt:
2335 resultArray[i].setIConst(std::max(unionArrays[0][i].getIConst(),
2336 unionArrays[1][i].getIConst()));
2337 break;
2338 case EbtUInt:
2339 resultArray[i].setUConst(std::max(unionArrays[0][i].getUConst(),
2340 unionArrays[1][i].getUConst()));
2341 break;
2342 default:
2343 UNREACHABLE();
2344 break;
Arun Patole274f0702015-05-05 13:33:30 +05302345 }
2346 }
Olli Etuahof119a262016-08-19 15:54:22 +03002347 break;
Arun Patole274f0702015-05-05 13:33:30 +05302348 }
Arun Patole274f0702015-05-05 13:33:30 +05302349
Olli Etuahof119a262016-08-19 15:54:22 +03002350 case EOpStep:
Arun Patolebf790422015-05-18 17:53:04 +05302351 {
Olli Etuahof119a262016-08-19 15:54:22 +03002352 ASSERT(basicType == EbtFloat);
2353 resultArray = new TConstantUnion[maxObjectSize];
2354 for (size_t i = 0; i < maxObjectSize; i++)
2355 resultArray[i].setFConst(
2356 unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f
2357 : 1.0f);
2358 break;
Arun Patolebf790422015-05-18 17:53:04 +05302359 }
Arun Patolebf790422015-05-18 17:53:04 +05302360
Olli Etuahof119a262016-08-19 15:54:22 +03002361 case EOpLessThan:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302362 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002363 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302364 for (size_t i = 0; i < maxObjectSize; i++)
2365 {
2366 switch (basicType)
2367 {
Olli Etuahof119a262016-08-19 15:54:22 +03002368 case EbtFloat:
2369 resultArray[i].setBConst(unionArrays[0][i].getFConst() <
2370 unionArrays[1][i].getFConst());
2371 break;
2372 case EbtInt:
2373 resultArray[i].setBConst(unionArrays[0][i].getIConst() <
2374 unionArrays[1][i].getIConst());
2375 break;
2376 case EbtUInt:
2377 resultArray[i].setBConst(unionArrays[0][i].getUConst() <
2378 unionArrays[1][i].getUConst());
2379 break;
2380 default:
2381 UNREACHABLE();
2382 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302383 }
2384 }
Olli Etuahof119a262016-08-19 15:54:22 +03002385 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302386 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302387
Olli Etuahof119a262016-08-19 15:54:22 +03002388 case EOpLessThanEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302389 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002390 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302391 for (size_t i = 0; i < maxObjectSize; i++)
2392 {
2393 switch (basicType)
2394 {
Olli Etuahof119a262016-08-19 15:54:22 +03002395 case EbtFloat:
2396 resultArray[i].setBConst(unionArrays[0][i].getFConst() <=
2397 unionArrays[1][i].getFConst());
2398 break;
2399 case EbtInt:
2400 resultArray[i].setBConst(unionArrays[0][i].getIConst() <=
2401 unionArrays[1][i].getIConst());
2402 break;
2403 case EbtUInt:
2404 resultArray[i].setBConst(unionArrays[0][i].getUConst() <=
2405 unionArrays[1][i].getUConst());
2406 break;
2407 default:
2408 UNREACHABLE();
2409 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302410 }
2411 }
Olli Etuahof119a262016-08-19 15:54:22 +03002412 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302413 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302414
Olli Etuahof119a262016-08-19 15:54:22 +03002415 case EOpGreaterThan:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302416 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002417 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302418 for (size_t i = 0; i < maxObjectSize; i++)
2419 {
2420 switch (basicType)
2421 {
Olli Etuahof119a262016-08-19 15:54:22 +03002422 case EbtFloat:
2423 resultArray[i].setBConst(unionArrays[0][i].getFConst() >
2424 unionArrays[1][i].getFConst());
2425 break;
2426 case EbtInt:
2427 resultArray[i].setBConst(unionArrays[0][i].getIConst() >
2428 unionArrays[1][i].getIConst());
2429 break;
2430 case EbtUInt:
2431 resultArray[i].setBConst(unionArrays[0][i].getUConst() >
2432 unionArrays[1][i].getUConst());
2433 break;
2434 default:
2435 UNREACHABLE();
2436 break;
Olli Etuahob43846e2015-06-02 18:18:57 +03002437 }
2438 }
Olli Etuahof119a262016-08-19 15:54:22 +03002439 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302440 }
Olli Etuahof119a262016-08-19 15:54:22 +03002441 case EOpGreaterThanEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302442 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002443 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302444 for (size_t i = 0; i < maxObjectSize; i++)
2445 {
2446 switch (basicType)
2447 {
Olli Etuahof119a262016-08-19 15:54:22 +03002448 case EbtFloat:
2449 resultArray[i].setBConst(unionArrays[0][i].getFConst() >=
2450 unionArrays[1][i].getFConst());
2451 break;
2452 case EbtInt:
2453 resultArray[i].setBConst(unionArrays[0][i].getIConst() >=
2454 unionArrays[1][i].getIConst());
2455 break;
2456 case EbtUInt:
2457 resultArray[i].setBConst(unionArrays[0][i].getUConst() >=
2458 unionArrays[1][i].getUConst());
2459 break;
2460 default:
2461 UNREACHABLE();
2462 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302463 }
2464 }
2465 }
2466 break;
2467
Olli Etuahof119a262016-08-19 15:54:22 +03002468 case EOpVectorEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302469 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002470 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302471 for (size_t i = 0; i < maxObjectSize; i++)
2472 {
2473 switch (basicType)
2474 {
Olli Etuahof119a262016-08-19 15:54:22 +03002475 case EbtFloat:
2476 resultArray[i].setBConst(unionArrays[0][i].getFConst() ==
2477 unionArrays[1][i].getFConst());
2478 break;
2479 case EbtInt:
2480 resultArray[i].setBConst(unionArrays[0][i].getIConst() ==
2481 unionArrays[1][i].getIConst());
2482 break;
2483 case EbtUInt:
2484 resultArray[i].setBConst(unionArrays[0][i].getUConst() ==
2485 unionArrays[1][i].getUConst());
2486 break;
2487 case EbtBool:
2488 resultArray[i].setBConst(unionArrays[0][i].getBConst() ==
2489 unionArrays[1][i].getBConst());
2490 break;
2491 default:
2492 UNREACHABLE();
2493 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302494 }
2495 }
Olli Etuahof119a262016-08-19 15:54:22 +03002496 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302497 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302498
Olli Etuahof119a262016-08-19 15:54:22 +03002499 case EOpVectorNotEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302500 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002501 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302502 for (size_t i = 0; i < maxObjectSize; i++)
2503 {
2504 switch (basicType)
2505 {
Olli Etuahof119a262016-08-19 15:54:22 +03002506 case EbtFloat:
2507 resultArray[i].setBConst(unionArrays[0][i].getFConst() !=
2508 unionArrays[1][i].getFConst());
2509 break;
2510 case EbtInt:
2511 resultArray[i].setBConst(unionArrays[0][i].getIConst() !=
2512 unionArrays[1][i].getIConst());
2513 break;
2514 case EbtUInt:
2515 resultArray[i].setBConst(unionArrays[0][i].getUConst() !=
2516 unionArrays[1][i].getUConst());
2517 break;
2518 case EbtBool:
2519 resultArray[i].setBConst(unionArrays[0][i].getBConst() !=
2520 unionArrays[1][i].getBConst());
2521 break;
2522 default:
2523 UNREACHABLE();
2524 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302525 }
2526 }
Olli Etuahof119a262016-08-19 15:54:22 +03002527 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302528 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302529
Olli Etuahof119a262016-08-19 15:54:22 +03002530 case EOpDistance:
Arun Patole1155ddd2015-06-05 18:04:36 +05302531 {
Olli Etuahof119a262016-08-19 15:54:22 +03002532 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302533 TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize];
Olli Etuahof119a262016-08-19 15:54:22 +03002534 resultArray = new TConstantUnion();
Arun Patole1155ddd2015-06-05 18:04:36 +05302535 for (size_t i = 0; i < maxObjectSize; i++)
2536 {
2537 float x = unionArrays[0][i].getFConst();
2538 float y = unionArrays[1][i].getFConst();
2539 distanceArray[i].setFConst(x - y);
2540 }
Olli Etuahob43846e2015-06-02 18:18:57 +03002541 resultArray->setFConst(VectorLength(distanceArray, maxObjectSize));
Olli Etuahof119a262016-08-19 15:54:22 +03002542 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302543 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302544
Olli Etuahof119a262016-08-19 15:54:22 +03002545 case EOpDot:
2546 ASSERT(basicType == EbtFloat);
Olli Etuahob43846e2015-06-02 18:18:57 +03002547 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03002548 resultArray->setFConst(
2549 VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize));
2550 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302551
Olli Etuahof119a262016-08-19 15:54:22 +03002552 case EOpCross:
Arun Patole1155ddd2015-06-05 18:04:36 +05302553 {
Olli Etuahof119a262016-08-19 15:54:22 +03002554 ASSERT(basicType == EbtFloat && maxObjectSize == 3);
Olli Etuahob43846e2015-06-02 18:18:57 +03002555 resultArray = new TConstantUnion[maxObjectSize];
Olli Etuahof119a262016-08-19 15:54:22 +03002556 float x0 = unionArrays[0][0].getFConst();
2557 float x1 = unionArrays[0][1].getFConst();
2558 float x2 = unionArrays[0][2].getFConst();
2559 float y0 = unionArrays[1][0].getFConst();
2560 float y1 = unionArrays[1][1].getFConst();
2561 float y2 = unionArrays[1][2].getFConst();
Olli Etuahob43846e2015-06-02 18:18:57 +03002562 resultArray[0].setFConst(x1 * y2 - y1 * x2);
2563 resultArray[1].setFConst(x2 * y0 - y2 * x0);
2564 resultArray[2].setFConst(x0 * y1 - y0 * x1);
Olli Etuahof119a262016-08-19 15:54:22 +03002565 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302566 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302567
Olli Etuahof119a262016-08-19 15:54:22 +03002568 case EOpReflect:
Arun Patole1155ddd2015-06-05 18:04:36 +05302569 {
Olli Etuahof119a262016-08-19 15:54:22 +03002570 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302571 // genType reflect (genType I, genType N) :
Olli Etuahof119a262016-08-19 15:54:22 +03002572 // For the incident vector I and surface orientation N, returns the reflection
2573 // direction:
Arun Patole1155ddd2015-06-05 18:04:36 +05302574 // I - 2 * dot(N, I) * N.
Olli Etuahof119a262016-08-19 15:54:22 +03002575 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole1155ddd2015-06-05 18:04:36 +05302576 float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
2577 for (size_t i = 0; i < maxObjectSize; i++)
2578 {
2579 float result = unionArrays[0][i].getFConst() -
2580 2.0f * dotProduct * unionArrays[1][i].getFConst();
Olli Etuahob43846e2015-06-02 18:18:57 +03002581 resultArray[i].setFConst(result);
Arun Patole1155ddd2015-06-05 18:04:36 +05302582 }
Olli Etuahof119a262016-08-19 15:54:22 +03002583 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302584 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302585
Olli Etuahof119a262016-08-19 15:54:22 +03002586 case EOpMul:
Arun Patole7fa33552015-06-10 15:15:18 +05302587 {
Olli Etuahof119a262016-08-19 15:54:22 +03002588 ASSERT(basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() &&
2589 (*sequence)[1]->getAsTyped()->isMatrix());
Arun Patole7fa33552015-06-10 15:15:18 +05302590 // Perform component-wise matrix multiplication.
2591 resultArray = new TConstantUnion[maxObjectSize];
Olli Etuahof119a262016-08-19 15:54:22 +03002592 int size = (*sequence)[0]->getAsTyped()->getNominalSize();
Arun Patole7fa33552015-06-10 15:15:18 +05302593 angle::Matrix<float> result =
2594 GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size));
2595 SetUnionArrayFromMatrix(result, resultArray);
Olli Etuahof119a262016-08-19 15:54:22 +03002596 break;
Arun Patole7fa33552015-06-10 15:15:18 +05302597 }
Arun Patole7fa33552015-06-10 15:15:18 +05302598
Olli Etuahof119a262016-08-19 15:54:22 +03002599 case EOpOuterProduct:
Arun Patole7fa33552015-06-10 15:15:18 +05302600 {
Olli Etuahof119a262016-08-19 15:54:22 +03002601 ASSERT(basicType == EbtFloat);
Arun Patole7fa33552015-06-10 15:15:18 +05302602 size_t numRows = (*sequence)[0]->getAsTyped()->getType().getObjectSize();
2603 size_t numCols = (*sequence)[1]->getAsTyped()->getType().getObjectSize();
Olli Etuahof119a262016-08-19 15:54:22 +03002604 resultArray = new TConstantUnion[numRows * numCols];
Arun Patole7fa33552015-06-10 15:15:18 +05302605 angle::Matrix<float> result =
Olli Etuahod5da5052016-08-29 13:16:55 +03002606 GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
2607 .outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols)));
Arun Patole7fa33552015-06-10 15:15:18 +05302608 SetUnionArrayFromMatrix(result, resultArray);
Olli Etuahof119a262016-08-19 15:54:22 +03002609 break;
Arun Patole7fa33552015-06-10 15:15:18 +05302610 }
Arun Patole7fa33552015-06-10 15:15:18 +05302611
Olli Etuahof119a262016-08-19 15:54:22 +03002612 default:
2613 UNREACHABLE();
2614 // TODO: Add constant folding support for other built-in operations that take 2
2615 // parameters and not handled above.
2616 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +05302617 }
2618 }
2619 else if (paramsCount == 3)
2620 {
2621 //
2622 // Ternary built-in
2623 //
2624 switch (op)
2625 {
Olli Etuahof119a262016-08-19 15:54:22 +03002626 case EOpClamp:
Arun Patole274f0702015-05-05 13:33:30 +05302627 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002628 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole274f0702015-05-05 13:33:30 +05302629 for (size_t i = 0; i < maxObjectSize; i++)
2630 {
2631 switch (basicType)
2632 {
Olli Etuahof119a262016-08-19 15:54:22 +03002633 case EbtFloat:
Arun Patole274f0702015-05-05 13:33:30 +05302634 {
Olli Etuahof119a262016-08-19 15:54:22 +03002635 float x = unionArrays[0][i].getFConst();
Arun Patole274f0702015-05-05 13:33:30 +05302636 float min = unionArrays[1][i].getFConst();
2637 float max = unionArrays[2][i].getFConst();
2638 // Results are undefined if min > max.
2639 if (min > max)
Olli Etuahof119a262016-08-19 15:54:22 +03002640 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2641 &resultArray[i]);
Arun Patole274f0702015-05-05 13:33:30 +05302642 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002643 resultArray[i].setFConst(gl::clamp(x, min, max));
Olli Etuahof119a262016-08-19 15:54:22 +03002644 break;
Arun Patole274f0702015-05-05 13:33:30 +05302645 }
Olli Etuahof119a262016-08-19 15:54:22 +03002646
2647 case EbtInt:
Arun Patole274f0702015-05-05 13:33:30 +05302648 {
Olli Etuahof119a262016-08-19 15:54:22 +03002649 int x = unionArrays[0][i].getIConst();
Arun Patole274f0702015-05-05 13:33:30 +05302650 int min = unionArrays[1][i].getIConst();
2651 int max = unionArrays[2][i].getIConst();
2652 // Results are undefined if min > max.
2653 if (min > max)
Olli Etuahof119a262016-08-19 15:54:22 +03002654 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2655 &resultArray[i]);
Arun Patole274f0702015-05-05 13:33:30 +05302656 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002657 resultArray[i].setIConst(gl::clamp(x, min, max));
Olli Etuahof119a262016-08-19 15:54:22 +03002658 break;
Arun Patole274f0702015-05-05 13:33:30 +05302659 }
Olli Etuahof119a262016-08-19 15:54:22 +03002660 case EbtUInt:
Arun Patole274f0702015-05-05 13:33:30 +05302661 {
Olli Etuahof119a262016-08-19 15:54:22 +03002662 unsigned int x = unionArrays[0][i].getUConst();
Arun Patole274f0702015-05-05 13:33:30 +05302663 unsigned int min = unionArrays[1][i].getUConst();
2664 unsigned int max = unionArrays[2][i].getUConst();
2665 // Results are undefined if min > max.
2666 if (min > max)
Olli Etuahof119a262016-08-19 15:54:22 +03002667 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2668 &resultArray[i]);
Arun Patole274f0702015-05-05 13:33:30 +05302669 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002670 resultArray[i].setUConst(gl::clamp(x, min, max));
Olli Etuahof119a262016-08-19 15:54:22 +03002671 break;
Arun Patole274f0702015-05-05 13:33:30 +05302672 }
Olli Etuahof119a262016-08-19 15:54:22 +03002673 default:
2674 UNREACHABLE();
2675 break;
Arun Patole274f0702015-05-05 13:33:30 +05302676 }
2677 }
Olli Etuahof119a262016-08-19 15:54:22 +03002678 break;
Arun Patole274f0702015-05-05 13:33:30 +05302679 }
Arun Patole274f0702015-05-05 13:33:30 +05302680
Olli Etuahof119a262016-08-19 15:54:22 +03002681 case EOpMix:
Arun Patolebf790422015-05-18 17:53:04 +05302682 {
Olli Etuahof119a262016-08-19 15:54:22 +03002683 ASSERT(basicType == EbtFloat);
2684 resultArray = new TConstantUnion[maxObjectSize];
2685 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302686 {
Olli Etuahof119a262016-08-19 15:54:22 +03002687 float x = unionArrays[0][i].getFConst();
2688 float y = unionArrays[1][i].getFConst();
2689 TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType();
2690 if (type == EbtFloat)
Arun Patolebf790422015-05-18 17:53:04 +05302691 {
Olli Etuahof119a262016-08-19 15:54:22 +03002692 // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
2693 float a = unionArrays[2][i].getFConst();
2694 resultArray[i].setFConst(x * (1.0f - a) + y * a);
2695 }
2696 else // 3rd parameter is EbtBool
2697 {
2698 ASSERT(type == EbtBool);
2699 // Selects which vector each returned component comes from.
2700 // For a component of a that is false, the corresponding component of x is
2701 // returned.
2702 // For a component of a that is true, the corresponding component of y is
2703 // returned.
2704 bool a = unionArrays[2][i].getBConst();
2705 resultArray[i].setFConst(a ? y : x);
Arun Patolebf790422015-05-18 17:53:04 +05302706 }
2707 }
Olli Etuahof119a262016-08-19 15:54:22 +03002708 break;
Arun Patolebf790422015-05-18 17:53:04 +05302709 }
Arun Patolebf790422015-05-18 17:53:04 +05302710
Olli Etuahof119a262016-08-19 15:54:22 +03002711 case EOpSmoothStep:
Arun Patolebf790422015-05-18 17:53:04 +05302712 {
Olli Etuahof119a262016-08-19 15:54:22 +03002713 ASSERT(basicType == EbtFloat);
2714 resultArray = new TConstantUnion[maxObjectSize];
2715 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302716 {
Olli Etuahof119a262016-08-19 15:54:22 +03002717 float edge0 = unionArrays[0][i].getFConst();
2718 float edge1 = unionArrays[1][i].getFConst();
2719 float x = unionArrays[2][i].getFConst();
2720 // Results are undefined if edge0 >= edge1.
2721 if (edge0 >= edge1)
Arun Patolebf790422015-05-18 17:53:04 +05302722 {
Olli Etuahof119a262016-08-19 15:54:22 +03002723 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2724 &resultArray[i]);
2725 }
2726 else
2727 {
2728 // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth
2729 // Hermite interpolation between 0 and 1 when edge0 < x < edge1.
2730 float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
2731 resultArray[i].setFConst(t * t * (3.0f - 2.0f * t));
Arun Patolebf790422015-05-18 17:53:04 +05302732 }
2733 }
Olli Etuahof119a262016-08-19 15:54:22 +03002734 break;
Arun Patolebf790422015-05-18 17:53:04 +05302735 }
Arun Patolebf790422015-05-18 17:53:04 +05302736
Olli Etuahof119a262016-08-19 15:54:22 +03002737 case EOpFaceForward:
Arun Patole1155ddd2015-06-05 18:04:36 +05302738 {
Olli Etuahof119a262016-08-19 15:54:22 +03002739 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302740 // genType faceforward(genType N, genType I, genType Nref) :
2741 // If dot(Nref, I) < 0 return N, otherwise return -N.
Olli Etuahof119a262016-08-19 15:54:22 +03002742 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole1155ddd2015-06-05 18:04:36 +05302743 float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize);
2744 for (size_t i = 0; i < maxObjectSize; i++)
2745 {
2746 if (dotProduct < 0)
Olli Etuahob43846e2015-06-02 18:18:57 +03002747 resultArray[i].setFConst(unionArrays[0][i].getFConst());
Arun Patole1155ddd2015-06-05 18:04:36 +05302748 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002749 resultArray[i].setFConst(-unionArrays[0][i].getFConst());
Arun Patole1155ddd2015-06-05 18:04:36 +05302750 }
Olli Etuahof119a262016-08-19 15:54:22 +03002751 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302752 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302753
Olli Etuahof119a262016-08-19 15:54:22 +03002754 case EOpRefract:
Arun Patole1155ddd2015-06-05 18:04:36 +05302755 {
Olli Etuahof119a262016-08-19 15:54:22 +03002756 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302757 // genType refract(genType I, genType N, float eta) :
Olli Etuahof119a262016-08-19 15:54:22 +03002758 // For the incident vector I and surface normal N, and the ratio of indices of
2759 // refraction eta,
Arun Patole1155ddd2015-06-05 18:04:36 +05302760 // return the refraction vector. The result is computed by
2761 // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
2762 // if (k < 0.0)
2763 // return genType(0.0)
2764 // else
2765 // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
Olli Etuahof119a262016-08-19 15:54:22 +03002766 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole1155ddd2015-06-05 18:04:36 +05302767 float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
2768 for (size_t i = 0; i < maxObjectSize; i++)
2769 {
2770 float eta = unionArrays[2][i].getFConst();
Olli Etuahof119a262016-08-19 15:54:22 +03002771 float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct);
Arun Patole1155ddd2015-06-05 18:04:36 +05302772 if (k < 0.0f)
Olli Etuahob43846e2015-06-02 18:18:57 +03002773 resultArray[i].setFConst(0.0f);
Arun Patole1155ddd2015-06-05 18:04:36 +05302774 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002775 resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() -
Olli Etuahof119a262016-08-19 15:54:22 +03002776 (eta * dotProduct + sqrtf(k)) *
2777 unionArrays[1][i].getFConst());
Arun Patole1155ddd2015-06-05 18:04:36 +05302778 }
Olli Etuahof119a262016-08-19 15:54:22 +03002779 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302780 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302781
Olli Etuahof119a262016-08-19 15:54:22 +03002782 default:
2783 UNREACHABLE();
2784 // TODO: Add constant folding support for other built-in operations that take 3
2785 // parameters and not handled above.
2786 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +05302787 }
2788 }
Olli Etuahob43846e2015-06-02 18:18:57 +03002789 return resultArray;
Arun Patole274f0702015-05-05 13:33:30 +05302790}
2791
2792// static
Jamie Madillb1a85f42014-08-19 15:23:24 -04002793TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction)
2794{
2795 if (hashFunction == NULL || name.empty())
2796 return name;
2797 khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
2798 TStringStream stream;
2799 stream << HASHED_NAME_PREFIX << std::hex << number;
2800 TString hashedName = stream.str();
2801 return hashedName;
2802}
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002803
2804void TIntermTraverser::updateTree()
2805{
Olli Etuahoa6f22092015-05-08 18:31:10 +03002806 for (size_t ii = 0; ii < mInsertions.size(); ++ii)
2807 {
2808 const NodeInsertMultipleEntry &insertion = mInsertions[ii];
2809 ASSERT(insertion.parent);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03002810 if (!insertion.insertionsAfter.empty())
2811 {
2812 bool inserted = insertion.parent->insertChildNodes(insertion.position + 1,
2813 insertion.insertionsAfter);
2814 ASSERT(inserted);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03002815 }
2816 if (!insertion.insertionsBefore.empty())
2817 {
2818 bool inserted =
2819 insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore);
2820 ASSERT(inserted);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03002821 }
Olli Etuahoa6f22092015-05-08 18:31:10 +03002822 }
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002823 for (size_t ii = 0; ii < mReplacements.size(); ++ii)
2824 {
Olli Etuahocd94ef92015-04-16 19:18:10 +03002825 const NodeUpdateEntry &replacement = mReplacements[ii];
2826 ASSERT(replacement.parent);
2827 bool replaced = replacement.parent->replaceChildNode(
2828 replacement.original, replacement.replacement);
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002829 ASSERT(replaced);
2830
Olli Etuahocd94ef92015-04-16 19:18:10 +03002831 if (!replacement.originalBecomesChildOfReplacement)
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002832 {
2833 // In AST traversing, a parent is visited before its children.
Olli Etuahocd94ef92015-04-16 19:18:10 +03002834 // After we replace a node, if its immediate child is to
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002835 // be replaced, we need to make sure we don't update the replaced
2836 // node; instead, we update the replacement node.
2837 for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj)
2838 {
Olli Etuahocd94ef92015-04-16 19:18:10 +03002839 NodeUpdateEntry &replacement2 = mReplacements[jj];
2840 if (replacement2.parent == replacement.original)
2841 replacement2.parent = replacement.replacement;
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002842 }
2843 }
2844 }
Olli Etuahofc0e2bc2015-04-16 13:39:56 +03002845 for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii)
2846 {
2847 const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii];
2848 ASSERT(replacement.parent);
2849 bool replaced = replacement.parent->replaceChildNodeWithMultiple(
2850 replacement.original, replacement.replacements);
2851 ASSERT(replaced);
2852 }
Olli Etuahod4f303e2015-05-20 17:09:06 +03002853
Jamie Madill03d863c2016-07-27 18:15:53 -04002854 clearReplacementQueue();
2855}
2856
2857void TIntermTraverser::clearReplacementQueue()
2858{
Olli Etuahod4f303e2015-05-20 17:09:06 +03002859 mReplacements.clear();
2860 mMultiReplacements.clear();
Jamie Madill03d863c2016-07-27 18:15:53 -04002861 mInsertions.clear();
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002862}
Jamie Madill1048e432016-07-23 18:51:28 -04002863
Jamie Madill03d863c2016-07-27 18:15:53 -04002864void TIntermTraverser::queueReplacement(TIntermNode *original,
2865 TIntermNode *replacement,
2866 OriginalNode originalStatus)
Jamie Madill1048e432016-07-23 18:51:28 -04002867{
Jamie Madill03d863c2016-07-27 18:15:53 -04002868 queueReplacementWithParent(getParentNode(), original, replacement, originalStatus);
Jamie Madill1048e432016-07-23 18:51:28 -04002869}
2870
Jamie Madill03d863c2016-07-27 18:15:53 -04002871void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent,
2872 TIntermNode *original,
2873 TIntermNode *replacement,
2874 OriginalNode originalStatus)
Jamie Madill1048e432016-07-23 18:51:28 -04002875{
Jamie Madill03d863c2016-07-27 18:15:53 -04002876 bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD);
2877 mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild));
Jamie Madill1048e432016-07-23 18:51:28 -04002878}