blob: 7cdf90f8b97282995c58b759c541434bc2860c3a [file] [log] [blame]
Jamie Madillb1a85f42014-08-19 15:23:24 -04001//
2// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7//
8// Build the intermediate representation.
9//
10
11#include <float.h>
12#include <limits.h>
Arun Patole9dea48f2015-04-02 11:45:09 +053013#include <math.h>
Arun Patole97dc22e2015-04-06 17:35:38 +053014#include <stdlib.h>
Jamie Madillb1a85f42014-08-19 15:23:24 -040015#include <algorithm>
Arun Patole274f0702015-05-05 13:33:30 +053016#include <vector>
Jamie Madillb1a85f42014-08-19 15:23:24 -040017
Arun Patole274f0702015-05-05 13:33:30 +053018#include "common/mathutil.h"
Arun Patole7fa33552015-06-10 15:15:18 +053019#include "common/matrix_utils.h"
Olli Etuaho3fdec912016-08-18 15:08:06 +030020#include "compiler/translator/Diagnostics.h"
Jamie Madillb1a85f42014-08-19 15:23:24 -040021#include "compiler/translator/HashNames.h"
22#include "compiler/translator/IntermNode.h"
23#include "compiler/translator/SymbolTable.h"
Corentin Wallez509e4562016-08-25 14:55:44 -040024#include "compiler/translator/util.h"
Jamie Madillb1a85f42014-08-19 15:23:24 -040025
Jamie Madill45bcc782016-11-07 13:58:48 -050026namespace sh
27{
28
Jamie Madillb1a85f42014-08-19 15:23:24 -040029namespace
30{
31
Jamie Madilld7b1ab52016-12-12 14:42:19 -050032const float kPi = 3.14159265358979323846f;
Arun Patole9dea48f2015-04-02 11:45:09 +053033const float kDegreesToRadiansMultiplier = kPi / 180.0f;
34const float kRadiansToDegreesMultiplier = 180.0f / kPi;
35
Jamie Madillb1a85f42014-08-19 15:23:24 -040036TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
37{
38 return left > right ? left : right;
39}
40
Arun Patole274f0702015-05-05 13:33:30 +053041TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size)
42{
43 TConstantUnion *constUnion = new TConstantUnion[size];
44 for (unsigned int i = 0; i < size; ++i)
Jamie Madilld7b1ab52016-12-12 14:42:19 -050045 constUnion[i] = constant;
Arun Patole274f0702015-05-05 13:33:30 +053046
47 return constUnion;
48}
49
Olli Etuahof119a262016-08-19 15:54:22 +030050void UndefinedConstantFoldingError(const TSourceLoc &loc,
51 TOperator op,
52 TBasicType basicType,
53 TDiagnostics *diagnostics,
54 TConstantUnion *result)
Arun Patolebf790422015-05-18 17:53:04 +053055{
Olli Etuahof119a262016-08-19 15:54:22 +030056 diagnostics->warning(loc, "operation result is undefined for the values passed in",
Olli Etuaho4de340a2016-12-16 09:32:03 +000057 GetOperatorString(op));
Arun Patolebf790422015-05-18 17:53:04 +053058
59 switch (basicType)
60 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -050061 case EbtFloat:
62 result->setFConst(0.0f);
63 break;
64 case EbtInt:
65 result->setIConst(0);
66 break;
67 case EbtUInt:
68 result->setUConst(0u);
69 break;
70 case EbtBool:
71 result->setBConst(false);
72 break;
73 default:
74 break;
Arun Patolebf790422015-05-18 17:53:04 +053075 }
76}
77
Olli Etuaho5c0e0232015-11-11 15:55:59 +020078float VectorLength(const TConstantUnion *paramArray, size_t paramArraySize)
Arun Patole1155ddd2015-06-05 18:04:36 +053079{
80 float result = 0.0f;
81 for (size_t i = 0; i < paramArraySize; i++)
82 {
83 float f = paramArray[i].getFConst();
84 result += f * f;
85 }
86 return sqrtf(result);
87}
88
Olli Etuaho5c0e0232015-11-11 15:55:59 +020089float VectorDotProduct(const TConstantUnion *paramArray1,
90 const TConstantUnion *paramArray2,
91 size_t paramArraySize)
Arun Patole1155ddd2015-06-05 18:04:36 +053092{
93 float result = 0.0f;
94 for (size_t i = 0; i < paramArraySize; i++)
95 result += paramArray1[i].getFConst() * paramArray2[i].getFConst();
96 return result;
97}
98
Olli Etuaho3272a6d2016-08-29 17:54:50 +030099TIntermTyped *CreateFoldedNode(const TConstantUnion *constArray,
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200100 const TIntermTyped *originalNode,
101 TQualifier qualifier)
Olli Etuahob43846e2015-06-02 18:18:57 +0300102{
103 if (constArray == nullptr)
104 {
105 return nullptr;
106 }
107 TIntermTyped *folded = new TIntermConstantUnion(constArray, originalNode->getType());
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200108 folded->getTypePointer()->setQualifier(qualifier);
Olli Etuahob43846e2015-06-02 18:18:57 +0300109 folded->setLine(originalNode->getLine());
110 return folded;
111}
112
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200113angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray,
114 const unsigned int &rows,
115 const unsigned int &cols)
Arun Patole7fa33552015-06-10 15:15:18 +0530116{
117 std::vector<float> elements;
118 for (size_t i = 0; i < rows * cols; i++)
119 elements.push_back(paramArray[i].getFConst());
120 // Transpose is used since the Matrix constructor expects arguments in row-major order,
Olli Etuahod5da5052016-08-29 13:16:55 +0300121 // whereas the paramArray is in column-major order. Rows/cols parameters are also flipped below
122 // so that the created matrix will have the expected dimensions after the transpose.
123 return angle::Matrix<float>(elements, cols, rows).transpose();
Arun Patole7fa33552015-06-10 15:15:18 +0530124}
125
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200126angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray, const unsigned int &size)
Arun Patole7fa33552015-06-10 15:15:18 +0530127{
128 std::vector<float> elements;
129 for (size_t i = 0; i < size * size; i++)
130 elements.push_back(paramArray[i].getFConst());
131 // Transpose is used since the Matrix constructor expects arguments in row-major order,
132 // whereas the paramArray is in column-major order.
133 return angle::Matrix<float>(elements, size).transpose();
134}
135
136void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resultArray)
137{
138 // Transpose is used since the input Matrix is in row-major order,
139 // whereas the actual result should be in column-major order.
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500140 angle::Matrix<float> result = m.transpose();
Arun Patole7fa33552015-06-10 15:15:18 +0530141 std::vector<float> resultElements = result.elements();
142 for (size_t i = 0; i < resultElements.size(); i++)
143 resultArray[i].setFConst(resultElements[i]);
144}
145
Jamie Madillb1a85f42014-08-19 15:23:24 -0400146} // namespace anonymous
147
Jamie Madillb1a85f42014-08-19 15:23:24 -0400148////////////////////////////////////////////////////////////////
149//
150// Member functions of the nodes used for building the tree.
151//
152////////////////////////////////////////////////////////////////
153
Olli Etuahod2a67b92014-10-21 16:42:57 +0300154void TIntermTyped::setTypePreservePrecision(const TType &t)
155{
156 TPrecision precision = getPrecision();
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500157 mType = t;
Olli Etuahod2a67b92014-10-21 16:42:57 +0300158 ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined);
159 mType.setPrecision(precision);
160}
161
Jamie Madillb1a85f42014-08-19 15:23:24 -0400162#define REPLACE_IF_IS(node, type, original, replacement) \
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500163 if (node == original) \
164 { \
165 node = static_cast<type *>(replacement); \
166 return true; \
Jamie Madillb1a85f42014-08-19 15:23:24 -0400167 }
168
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500169bool TIntermLoop::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400170{
Olli Etuaho3cbb27a2016-07-14 11:55:48 +0300171 ASSERT(original != nullptr); // This risks replacing multiple children.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400172 REPLACE_IF_IS(mInit, TIntermNode, original, replacement);
173 REPLACE_IF_IS(mCond, TIntermTyped, original, replacement);
174 REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100175 REPLACE_IF_IS(mBody, TIntermBlock, original, replacement);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400176 return false;
177}
178
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500179bool TIntermBranch::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400180{
181 REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement);
182 return false;
183}
184
Olli Etuahob6fa0432016-09-28 16:28:05 +0100185bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
186{
187 ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
188 REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
189 return false;
190}
191
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500192bool TIntermBinary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400193{
194 REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement);
195 REPLACE_IF_IS(mRight, TIntermTyped, original, replacement);
196 return false;
197}
198
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500199bool TIntermUnary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400200{
Olli Etuahoa2234302016-08-31 12:05:39 +0300201 ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
Jamie Madillb1a85f42014-08-19 15:23:24 -0400202 REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
203 return false;
204}
205
Olli Etuahobf4e1b72016-12-09 11:30:15 +0000206bool TIntermInvariantDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
207{
208 REPLACE_IF_IS(mSymbol, TIntermSymbol, original, replacement);
209 return false;
210}
211
Olli Etuaho336b1472016-10-05 16:37:55 +0100212bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
213{
Olli Etuaho8ad9e752017-01-16 19:55:20 +0000214 REPLACE_IF_IS(mPrototype, TIntermFunctionPrototype, original, replacement);
Olli Etuaho336b1472016-10-05 16:37:55 +0100215 REPLACE_IF_IS(mBody, TIntermBlock, original, replacement);
216 return false;
217}
218
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500219bool TIntermAggregate::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400220{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100221 return replaceChildNodeInternal(original, replacement);
222}
223
224bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
225{
226 return replaceChildNodeInternal(original, replacement);
227}
228
Olli Etuaho16c745a2017-01-16 17:02:27 +0000229bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
230{
231 return replaceChildNodeInternal(original, replacement);
232}
233
Olli Etuaho13389b62016-10-16 11:48:18 +0100234bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
235{
236 return replaceChildNodeInternal(original, replacement);
237}
238
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100239bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement)
240{
241 for (size_t ii = 0; ii < getSequence()->size(); ++ii)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400242 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100243 REPLACE_IF_IS((*getSequence())[ii], TIntermNode, original, replacement);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400244 }
245 return false;
246}
247
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100248bool TIntermAggregateBase::replaceChildNodeWithMultiple(TIntermNode *original,
249 const TIntermSequence &replacements)
Olli Etuahofc0e2bc2015-04-16 13:39:56 +0300250{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100251 for (auto it = getSequence()->begin(); it < getSequence()->end(); ++it)
Olli Etuahofc0e2bc2015-04-16 13:39:56 +0300252 {
253 if (*it == original)
254 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100255 it = getSequence()->erase(it);
256 getSequence()->insert(it, replacements.begin(), replacements.end());
Olli Etuahofc0e2bc2015-04-16 13:39:56 +0300257 return true;
258 }
259 }
260 return false;
261}
262
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100263bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position,
264 const TIntermSequence &insertions)
Olli Etuahoa6f22092015-05-08 18:31:10 +0300265{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100266 if (position > getSequence()->size())
Olli Etuahoa6f22092015-05-08 18:31:10 +0300267 {
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300268 return false;
Olli Etuahoa6f22092015-05-08 18:31:10 +0300269 }
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100270 auto it = getSequence()->begin() + position;
271 getSequence()->insert(it, insertions.begin(), insertions.end());
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300272 return true;
Olli Etuahoa6f22092015-05-08 18:31:10 +0300273}
274
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200275bool TIntermAggregate::areChildrenConstQualified()
276{
277 for (TIntermNode *&child : mSequence)
278 {
279 TIntermTyped *typed = child->getAsTyped();
280 if (typed && typed->getQualifier() != EvqConst)
281 {
282 return false;
283 }
284 }
285 return true;
286}
287
Olli Etuahod2a67b92014-10-21 16:42:57 +0300288void TIntermAggregate::setPrecisionFromChildren()
289{
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300290 mGotPrecisionFromChildren = true;
Olli Etuahod2a67b92014-10-21 16:42:57 +0300291 if (getBasicType() == EbtBool)
292 {
293 mType.setPrecision(EbpUndefined);
294 return;
295 }
296
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500297 TPrecision precision = EbpUndefined;
Olli Etuahod2a67b92014-10-21 16:42:57 +0300298 TIntermSequence::iterator childIter = mSequence.begin();
299 while (childIter != mSequence.end())
300 {
301 TIntermTyped *typed = (*childIter)->getAsTyped();
302 if (typed)
303 precision = GetHigherPrecision(typed->getPrecision(), precision);
304 ++childIter;
305 }
306 mType.setPrecision(precision);
307}
308
Olli Etuaho9250cb22017-01-21 10:51:27 +0000309void TIntermAggregate::setPrecisionForBuiltInOp()
310{
311 ASSERT(!isConstructor());
312 ASSERT(mOp != EOpFunctionCall);
313 if (!setPrecisionForSpecialBuiltInOp())
314 {
315 setPrecisionFromChildren();
316 }
317}
318
319bool TIntermAggregate::setPrecisionForSpecialBuiltInOp()
320{
321 switch (mOp)
322 {
323 case EOpBitfieldExtract:
324 mType.setPrecision(mSequence[0]->getAsTyped()->getPrecision());
325 return true;
326 case EOpBitfieldInsert:
327 mType.setPrecision(GetHigherPrecision(mSequence[0]->getAsTyped()->getPrecision(),
328 mSequence[1]->getAsTyped()->getPrecision()));
329 return true;
330 case EOpUaddCarry:
331 case EOpUsubBorrow:
332 mType.setPrecision(EbpHigh);
333 return true;
334 default:
335 return false;
336 }
337}
338
Olli Etuahod2a67b92014-10-21 16:42:57 +0300339void TIntermAggregate::setBuiltInFunctionPrecision()
340{
341 // All built-ins returning bool should be handled as ops, not functions.
342 ASSERT(getBasicType() != EbtBool);
Olli Etuaho9250cb22017-01-21 10:51:27 +0000343 ASSERT(getOp() == EOpFunctionCall);
Olli Etuahod2a67b92014-10-21 16:42:57 +0300344
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500345 TPrecision precision = EbpUndefined;
Olli Etuahod2a67b92014-10-21 16:42:57 +0300346 TIntermSequence::iterator childIter = mSequence.begin();
347 while (childIter != mSequence.end())
348 {
349 TIntermTyped *typed = (*childIter)->getAsTyped();
350 // ESSL spec section 8: texture functions get their precision from the sampler.
351 if (typed && IsSampler(typed->getBasicType()))
352 {
353 precision = typed->getPrecision();
354 break;
355 }
356 ++childIter;
357 }
358 // ESSL 3.0 spec section 8: textureSize always gets highp precision.
359 // All other functions that take a sampler are assumed to be texture functions.
Olli Etuahobd674552016-10-06 13:28:42 +0100360 if (mFunctionInfo.getName().find("textureSize") == 0)
Olli Etuahod2a67b92014-10-21 16:42:57 +0300361 mType.setPrecision(EbpHigh);
362 else
363 mType.setPrecision(precision);
364}
365
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100366void TIntermBlock::appendStatement(TIntermNode *statement)
367{
Olli Etuaho13389b62016-10-16 11:48:18 +0100368 // Declaration nodes with no children can appear if all the declarators just added constants to
369 // the symbol table instead of generating code. They're no-ops so they aren't added to blocks.
370 if (statement != nullptr && (statement->getAsDeclarationNode() == nullptr ||
371 !statement->getAsDeclarationNode()->getSequence()->empty()))
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100372 {
373 mStatements.push_back(statement);
374 }
375}
376
Olli Etuaho16c745a2017-01-16 17:02:27 +0000377void TIntermFunctionPrototype::appendParameter(TIntermSymbol *parameter)
378{
379 ASSERT(parameter != nullptr);
380 mParameters.push_back(parameter);
381}
382
Olli Etuaho13389b62016-10-16 11:48:18 +0100383void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator)
384{
385 ASSERT(declarator != nullptr);
386 ASSERT(declarator->getAsSymbolNode() != nullptr ||
387 (declarator->getAsBinaryNode() != nullptr &&
388 declarator->getAsBinaryNode()->getOp() == EOpInitialize));
389 ASSERT(mDeclarators.empty() ||
390 declarator->getType().sameElementType(mDeclarators.back()->getAsTyped()->getType()));
391 mDeclarators.push_back(declarator);
392}
393
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300394bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
395{
396 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
397 REPLACE_IF_IS(mTrueExpression, TIntermTyped, original, replacement);
398 REPLACE_IF_IS(mFalseExpression, TIntermTyped, original, replacement);
399 return false;
400}
401
Olli Etuaho57961272016-09-14 13:57:46 +0300402bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400403{
404 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100405 REPLACE_IF_IS(mTrueBlock, TIntermBlock, original, replacement);
406 REPLACE_IF_IS(mFalseBlock, TIntermBlock, original, replacement);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400407 return false;
408}
409
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500410bool TIntermSwitch::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200411{
412 REPLACE_IF_IS(mInit, TIntermTyped, original, replacement);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100413 REPLACE_IF_IS(mStatementList, TIntermBlock, original, replacement);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200414 return false;
415}
416
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500417bool TIntermCase::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200418{
419 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
420 return false;
421}
422
Olli Etuahod7a25242015-08-18 13:49:45 +0300423TIntermTyped::TIntermTyped(const TIntermTyped &node) : TIntermNode(), mType(node.mType)
424{
425 // Copy constructor is disallowed for TIntermNode in order to disallow it for subclasses that
426 // don't explicitly allow it, so normal TIntermNode constructor is used to construct the copy.
427 // We need to manually copy any fields of TIntermNode besides handling fields in TIntermTyped.
428 mLine = node.mLine;
429}
430
Olli Etuahod4f4c112016-04-15 15:11:24 +0300431bool TIntermTyped::isConstructorWithOnlyConstantUnionParameters()
432{
433 TIntermAggregate *constructor = getAsAggregate();
434 if (!constructor || !constructor->isConstructor())
435 {
436 return false;
437 }
438 for (TIntermNode *&node : *constructor->getSequence())
439 {
440 if (!node->getAsConstantUnion())
441 return false;
442 }
443 return true;
444}
445
Corentin Wallez509e4562016-08-25 14:55:44 -0400446// static
447TIntermTyped *TIntermTyped::CreateIndexNode(int index)
448{
449 TConstantUnion *u = new TConstantUnion[1];
450 u[0].setIConst(index);
451
452 TType type(EbtInt, EbpUndefined, EvqConst, 1);
453 TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
454 return node;
455}
456
457// static
458TIntermTyped *TIntermTyped::CreateZero(const TType &type)
459{
460 TType constType(type);
461 constType.setQualifier(EvqConst);
462
463 if (!type.isArray() && type.getBasicType() != EbtStruct)
464 {
465 ASSERT(type.isScalar() || type.isVector() || type.isMatrix());
466
467 size_t size = constType.getObjectSize();
468 TConstantUnion *u = new TConstantUnion[size];
469 for (size_t i = 0; i < size; ++i)
470 {
471 switch (type.getBasicType())
472 {
473 case EbtFloat:
474 u[i].setFConst(0.0f);
475 break;
476 case EbtInt:
477 u[i].setIConst(0);
478 break;
479 case EbtUInt:
480 u[i].setUConst(0u);
481 break;
482 case EbtBool:
483 u[i].setBConst(false);
484 break;
485 default:
486 UNREACHABLE();
487 return nullptr;
488 }
489 }
490
491 TIntermConstantUnion *node = new TIntermConstantUnion(u, constType);
492 return node;
493 }
494
495 TIntermAggregate *constructor = new TIntermAggregate(sh::TypeToConstructorOperator(type));
496 constructor->setType(constType);
497
498 if (type.isArray())
499 {
500 TType elementType(type);
501 elementType.clearArrayness();
502
503 size_t arraySize = type.getArraySize();
504 for (size_t i = 0; i < arraySize; ++i)
505 {
506 constructor->getSequence()->push_back(CreateZero(elementType));
507 }
508 }
509 else
510 {
511 ASSERT(type.getBasicType() == EbtStruct);
512
513 TStructure *structure = type.getStruct();
514 for (const auto &field : structure->fields())
515 {
516 constructor->getSequence()->push_back(CreateZero(*field->type()));
517 }
518 }
519
520 return constructor;
521}
522
Corentin Wallez36fd1002016-12-08 11:30:44 -0500523// static
524TIntermTyped *TIntermTyped::CreateBool(bool value)
525{
526 TConstantUnion *u = new TConstantUnion[1];
527 u[0].setBConst(value);
528
529 TType type(EbtBool, EbpUndefined, EvqConst, 1);
530 TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
531 return node;
532}
533
Olli Etuahod7a25242015-08-18 13:49:45 +0300534TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) : TIntermTyped(node)
535{
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200536 mUnionArrayPointer = node.mUnionArrayPointer;
Olli Etuahod7a25242015-08-18 13:49:45 +0300537}
538
Olli Etuahobd674552016-10-06 13:28:42 +0100539void TFunctionSymbolInfo::setFromFunction(const TFunction &function)
540{
541 setName(function.getMangledName());
542 setId(function.getUniqueId());
543}
544
Olli Etuahod7a25242015-08-18 13:49:45 +0300545TIntermAggregate::TIntermAggregate(const TIntermAggregate &node)
546 : TIntermOperator(node),
Olli Etuahod7a25242015-08-18 13:49:45 +0300547 mUserDefined(node.mUserDefined),
Olli Etuahod7a25242015-08-18 13:49:45 +0300548 mUseEmulatedFunction(node.mUseEmulatedFunction),
Olli Etuahobd674552016-10-06 13:28:42 +0100549 mGotPrecisionFromChildren(node.mGotPrecisionFromChildren),
550 mFunctionInfo(node.mFunctionInfo)
Olli Etuahod7a25242015-08-18 13:49:45 +0300551{
552 for (TIntermNode *child : node.mSequence)
553 {
554 TIntermTyped *typedChild = child->getAsTyped();
555 ASSERT(typedChild != nullptr);
556 TIntermTyped *childCopy = typedChild->deepCopy();
557 mSequence.push_back(childCopy);
558 }
559}
560
Olli Etuahob6fa0432016-09-28 16:28:05 +0100561TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermTyped(node)
562{
563 TIntermTyped *operandCopy = node.mOperand->deepCopy();
564 ASSERT(operandCopy != nullptr);
565 mOperand = operandCopy;
566}
567
Olli Etuahod7a25242015-08-18 13:49:45 +0300568TIntermBinary::TIntermBinary(const TIntermBinary &node)
569 : TIntermOperator(node), mAddIndexClamp(node.mAddIndexClamp)
570{
571 TIntermTyped *leftCopy = node.mLeft->deepCopy();
572 TIntermTyped *rightCopy = node.mRight->deepCopy();
573 ASSERT(leftCopy != nullptr && rightCopy != nullptr);
574 mLeft = leftCopy;
575 mRight = rightCopy;
576}
577
578TIntermUnary::TIntermUnary(const TIntermUnary &node)
579 : TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction)
580{
581 TIntermTyped *operandCopy = node.mOperand->deepCopy();
582 ASSERT(operandCopy != nullptr);
583 mOperand = operandCopy;
584}
585
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300586TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermTyped(node)
Olli Etuahod7a25242015-08-18 13:49:45 +0300587{
Olli Etuahod7a25242015-08-18 13:49:45 +0300588 TIntermTyped *conditionCopy = node.mCondition->deepCopy();
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300589 TIntermTyped *trueCopy = node.mTrueExpression->deepCopy();
590 TIntermTyped *falseCopy = node.mFalseExpression->deepCopy();
Olli Etuahod7a25242015-08-18 13:49:45 +0300591 ASSERT(conditionCopy != nullptr && trueCopy != nullptr && falseCopy != nullptr);
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300592 mCondition = conditionCopy;
593 mTrueExpression = trueCopy;
594 mFalseExpression = falseCopy;
Olli Etuahod7a25242015-08-18 13:49:45 +0300595}
596
Jamie Madillb1a85f42014-08-19 15:23:24 -0400597bool TIntermOperator::isAssignment() const
598{
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300599 return IsAssignment(mOp);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400600}
601
Olli Etuaho8f76bcc2015-06-02 13:54:20 +0300602bool TIntermOperator::isMultiplication() const
603{
604 switch (mOp)
605 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500606 case EOpMul:
607 case EOpMatrixTimesMatrix:
608 case EOpMatrixTimesVector:
609 case EOpMatrixTimesScalar:
610 case EOpVectorTimesMatrix:
611 case EOpVectorTimesScalar:
612 return true;
613 default:
614 return false;
Olli Etuaho8f76bcc2015-06-02 13:54:20 +0300615 }
616}
617
Jamie Madillb1a85f42014-08-19 15:23:24 -0400618//
619// returns true if the operator is for one of the constructors
620//
621bool TIntermOperator::isConstructor() const
622{
623 switch (mOp)
624 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500625 case EOpConstructVec2:
626 case EOpConstructVec3:
627 case EOpConstructVec4:
628 case EOpConstructMat2:
629 case EOpConstructMat2x3:
630 case EOpConstructMat2x4:
631 case EOpConstructMat3x2:
632 case EOpConstructMat3:
633 case EOpConstructMat3x4:
634 case EOpConstructMat4x2:
635 case EOpConstructMat4x3:
636 case EOpConstructMat4:
637 case EOpConstructFloat:
638 case EOpConstructIVec2:
639 case EOpConstructIVec3:
640 case EOpConstructIVec4:
641 case EOpConstructInt:
642 case EOpConstructUVec2:
643 case EOpConstructUVec3:
644 case EOpConstructUVec4:
645 case EOpConstructUInt:
646 case EOpConstructBVec2:
647 case EOpConstructBVec3:
648 case EOpConstructBVec4:
649 case EOpConstructBool:
650 case EOpConstructStruct:
651 return true;
652 default:
653 return false;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400654 }
655}
656
Olli Etuaho1dded802016-08-18 18:13:13 +0300657TOperator TIntermBinary::GetMulOpBasedOnOperands(const TType &left, const TType &right)
658{
659 if (left.isMatrix())
660 {
661 if (right.isMatrix())
662 {
663 return EOpMatrixTimesMatrix;
664 }
665 else
666 {
667 if (right.isVector())
668 {
669 return EOpMatrixTimesVector;
670 }
671 else
672 {
673 return EOpMatrixTimesScalar;
674 }
675 }
676 }
677 else
678 {
679 if (right.isMatrix())
680 {
681 if (left.isVector())
682 {
683 return EOpVectorTimesMatrix;
684 }
685 else
686 {
687 return EOpMatrixTimesScalar;
688 }
689 }
690 else
691 {
692 // Neither operand is a matrix.
693 if (left.isVector() == right.isVector())
694 {
695 // Leave as component product.
696 return EOpMul;
697 }
698 else
699 {
700 return EOpVectorTimesScalar;
701 }
702 }
703 }
704}
705
706TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const TType &right)
707{
708 if (left.isMatrix())
709 {
710 if (right.isMatrix())
711 {
712 return EOpMatrixTimesMatrixAssign;
713 }
714 else
715 {
716 // right should be scalar, but this may not be validated yet.
717 return EOpMatrixTimesScalarAssign;
718 }
719 }
720 else
721 {
722 if (right.isMatrix())
723 {
724 // Left should be a vector, but this may not be validated yet.
725 return EOpVectorTimesMatrixAssign;
726 }
727 else
728 {
729 // Neither operand is a matrix.
730 if (left.isVector() == right.isVector())
731 {
732 // Leave as component product.
733 return EOpMulAssign;
734 }
735 else
736 {
737 // left should be vector and right should be scalar, but this may not be validated
738 // yet.
739 return EOpVectorTimesScalarAssign;
740 }
741 }
742 }
743}
744
Jamie Madillb1a85f42014-08-19 15:23:24 -0400745//
746// Make sure the type of a unary operator is appropriate for its
747// combination of operation and operand type.
748//
Olli Etuahoa2234302016-08-31 12:05:39 +0300749void TIntermUnary::promote()
Jamie Madillb1a85f42014-08-19 15:23:24 -0400750{
Olli Etuahoa2234302016-08-31 12:05:39 +0300751 TQualifier resultQualifier = EvqTemporary;
752 if (mOperand->getQualifier() == EvqConst)
753 resultQualifier = EvqConst;
754
755 unsigned char operandPrimarySize =
756 static_cast<unsigned char>(mOperand->getType().getNominalSize());
Jamie Madillb1a85f42014-08-19 15:23:24 -0400757 switch (mOp)
758 {
Olli Etuahoa2234302016-08-31 12:05:39 +0300759 case EOpFloatBitsToInt:
760 setType(TType(EbtInt, EbpHigh, resultQualifier, operandPrimarySize));
761 break;
762 case EOpFloatBitsToUint:
763 setType(TType(EbtUInt, EbpHigh, resultQualifier, operandPrimarySize));
764 break;
765 case EOpIntBitsToFloat:
766 case EOpUintBitsToFloat:
767 setType(TType(EbtFloat, EbpHigh, resultQualifier, operandPrimarySize));
768 break;
769 case EOpPackSnorm2x16:
770 case EOpPackUnorm2x16:
771 case EOpPackHalf2x16:
772 setType(TType(EbtUInt, EbpHigh, resultQualifier));
773 break;
774 case EOpUnpackSnorm2x16:
775 case EOpUnpackUnorm2x16:
776 setType(TType(EbtFloat, EbpHigh, resultQualifier, 2));
777 break;
778 case EOpUnpackHalf2x16:
779 setType(TType(EbtFloat, EbpMedium, resultQualifier, 2));
780 break;
781 case EOpAny:
782 case EOpAll:
783 setType(TType(EbtBool, EbpUndefined, resultQualifier));
784 break;
785 case EOpLength:
786 case EOpDeterminant:
787 setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier));
788 break;
789 case EOpTranspose:
790 setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier,
791 static_cast<unsigned char>(mOperand->getType().getRows()),
792 static_cast<unsigned char>(mOperand->getType().getCols())));
793 break;
794 case EOpIsInf:
795 case EOpIsNan:
796 setType(TType(EbtBool, EbpUndefined, resultQualifier, operandPrimarySize));
797 break;
Olli Etuaho9250cb22017-01-21 10:51:27 +0000798 case EOpBitfieldReverse:
799 setType(TType(mOperand->getBasicType(), EbpHigh, resultQualifier, operandPrimarySize));
800 break;
801 case EOpBitCount:
802 setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
803 break;
804 case EOpFindLSB:
805 setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
806 break;
807 case EOpFindMSB:
808 setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
809 break;
Olli Etuahoa2234302016-08-31 12:05:39 +0300810 default:
811 setType(mOperand->getType());
812 mType.setQualifier(resultQualifier);
813 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400814 }
Olli Etuahoa2234302016-08-31 12:05:39 +0300815}
Jamie Madillb1a85f42014-08-19 15:23:24 -0400816
Olli Etuahob6fa0432016-09-28 16:28:05 +0100817TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets)
818 : TIntermTyped(TType(EbtFloat, EbpUndefined)),
819 mOperand(operand),
820 mSwizzleOffsets(swizzleOffsets)
821{
822 ASSERT(mSwizzleOffsets.size() <= 4);
823 promote();
824}
825
Olli Etuahoa2234302016-08-31 12:05:39 +0300826TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand)
827 : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false)
828{
829 promote();
Jamie Madillb1a85f42014-08-19 15:23:24 -0400830}
831
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300832TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right)
833 : TIntermOperator(op), mLeft(left), mRight(right), mAddIndexClamp(false)
834{
835 promote();
836}
837
Olli Etuahobf4e1b72016-12-09 11:30:15 +0000838TIntermInvariantDeclaration::TIntermInvariantDeclaration(TIntermSymbol *symbol, const TSourceLoc &line)
839 : TIntermNode(), mSymbol(symbol)
840{
841 ASSERT(symbol);
842 setLine(line);
843}
844
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300845TIntermTernary::TIntermTernary(TIntermTyped *cond,
846 TIntermTyped *trueExpression,
847 TIntermTyped *falseExpression)
848 : TIntermTyped(trueExpression->getType()),
849 mCondition(cond),
850 mTrueExpression(trueExpression),
851 mFalseExpression(falseExpression)
852{
853 getTypePointer()->setQualifier(
854 TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression));
855}
856
857// static
858TQualifier TIntermTernary::DetermineQualifier(TIntermTyped *cond,
859 TIntermTyped *trueExpression,
860 TIntermTyped *falseExpression)
861{
862 if (cond->getQualifier() == EvqConst && trueExpression->getQualifier() == EvqConst &&
863 falseExpression->getQualifier() == EvqConst)
864 {
865 return EvqConst;
866 }
867 return EvqTemporary;
868}
869
Olli Etuahob6fa0432016-09-28 16:28:05 +0100870void TIntermSwizzle::promote()
871{
872 TQualifier resultQualifier = EvqTemporary;
873 if (mOperand->getQualifier() == EvqConst)
874 resultQualifier = EvqConst;
875
876 auto numFields = mSwizzleOffsets.size();
877 setType(TType(mOperand->getBasicType(), mOperand->getPrecision(), resultQualifier,
878 static_cast<unsigned char>(numFields)));
879}
880
881bool TIntermSwizzle::hasDuplicateOffsets() const
882{
883 int offsetCount[4] = {0u, 0u, 0u, 0u};
884 for (const auto offset : mSwizzleOffsets)
885 {
886 offsetCount[offset]++;
887 if (offsetCount[offset] > 1)
888 {
889 return true;
890 }
891 }
892 return false;
893}
894
Olli Etuaho09b04a22016-12-15 13:30:26 +0000895bool TIntermSwizzle::offsetsMatch(int offset) const
896{
897 return mSwizzleOffsets.size() == 1 && mSwizzleOffsets[0] == offset;
898}
899
Olli Etuahob6fa0432016-09-28 16:28:05 +0100900void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const
901{
902 for (const int offset : mSwizzleOffsets)
903 {
904 switch (offset)
905 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500906 case 0:
907 *out << "x";
908 break;
909 case 1:
910 *out << "y";
911 break;
912 case 2:
913 *out << "z";
914 break;
915 case 3:
916 *out << "w";
917 break;
918 default:
919 UNREACHABLE();
Olli Etuahob6fa0432016-09-28 16:28:05 +0100920 }
921 }
922}
923
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100924TQualifier TIntermBinary::GetCommaQualifier(int shaderVersion,
925 const TIntermTyped *left,
926 const TIntermTyped *right)
927{
928 // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
929 if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
930 right->getQualifier() != EvqConst)
931 {
932 return EvqTemporary;
933 }
934 return EvqConst;
935}
Olli Etuahob6fa0432016-09-28 16:28:05 +0100936
937// Establishes the type of the result of the binary operation.
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300938void TIntermBinary::promote()
Jamie Madillb1a85f42014-08-19 15:23:24 -0400939{
Olli Etuaho1dded802016-08-18 18:13:13 +0300940 ASSERT(!isMultiplication() ||
941 mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType()));
942
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100943 // Comma is handled as a special case.
944 if (mOp == EOpComma)
945 {
946 setType(mRight->getType());
947 return;
948 }
949
Jamie Madillb1a85f42014-08-19 15:23:24 -0400950 // Base assumption: just make the type the same as the left
951 // operand. Then only deviations from this need be coded.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400952 setType(mLeft->getType());
953
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200954 TQualifier resultQualifier = EvqConst;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400955 // Binary operations results in temporary variables unless both
956 // operands are const.
957 if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst)
958 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200959 resultQualifier = EvqTemporary;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400960 getTypePointer()->setQualifier(EvqTemporary);
961 }
962
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300963 // Handle indexing ops.
964 switch (mOp)
965 {
966 case EOpIndexDirect:
967 case EOpIndexIndirect:
968 if (mLeft->isArray())
969 {
970 mType.clearArrayness();
971 }
972 else if (mLeft->isMatrix())
973 {
974 setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier,
975 static_cast<unsigned char>(mLeft->getRows())));
976 }
977 else if (mLeft->isVector())
978 {
979 setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier));
980 }
981 else
982 {
983 UNREACHABLE();
984 }
985 return;
986 case EOpIndexDirectStruct:
987 {
988 const TFieldList &fields = mLeft->getType().getStruct()->fields();
989 const int i = mRight->getAsConstantUnion()->getIConst(0);
990 setType(*fields[i]->type());
991 getTypePointer()->setQualifier(resultQualifier);
992 return;
993 }
994 case EOpIndexDirectInterfaceBlock:
995 {
996 const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields();
997 const int i = mRight->getAsConstantUnion()->getIConst(0);
998 setType(*fields[i]->type());
999 getTypePointer()->setQualifier(resultQualifier);
1000 return;
1001 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001002 default:
1003 break;
1004 }
1005
1006 ASSERT(mLeft->isArray() == mRight->isArray());
1007
1008 // The result gets promoted to the highest precision.
1009 TPrecision higherPrecision = GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision());
1010 getTypePointer()->setPrecision(higherPrecision);
1011
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001012 const int nominalSize = std::max(mLeft->getNominalSize(), mRight->getNominalSize());
Jamie Madillb1a85f42014-08-19 15:23:24 -04001013
1014 //
1015 // All scalars or structs. Code after this test assumes this case is removed!
1016 //
1017 if (nominalSize == 1)
1018 {
1019 switch (mOp)
1020 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001021 //
1022 // Promote to conditional
1023 //
1024 case EOpEqual:
1025 case EOpNotEqual:
1026 case EOpLessThan:
1027 case EOpGreaterThan:
1028 case EOpLessThanEqual:
1029 case EOpGreaterThanEqual:
1030 setType(TType(EbtBool, EbpUndefined, resultQualifier));
1031 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001032
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001033 //
1034 // And and Or operate on conditionals
1035 //
1036 case EOpLogicalAnd:
1037 case EOpLogicalXor:
1038 case EOpLogicalOr:
1039 ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool);
1040 setType(TType(EbtBool, EbpUndefined, resultQualifier));
1041 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001042
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001043 default:
1044 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001045 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001046 return;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001047 }
1048
1049 // If we reach here, at least one of the operands is vector or matrix.
1050 // The other operand could be a scalar, vector, or matrix.
Jamie Madillb1a85f42014-08-19 15:23:24 -04001051 TBasicType basicType = mLeft->getBasicType();
Olli Etuaho1dded802016-08-18 18:13:13 +03001052
Jamie Madillb1a85f42014-08-19 15:23:24 -04001053 switch (mOp)
1054 {
Olli Etuaho1dded802016-08-18 18:13:13 +03001055 case EOpMul:
1056 break;
1057 case EOpMatrixTimesScalar:
1058 if (mRight->isMatrix())
Jamie Madillb1a85f42014-08-19 15:23:24 -04001059 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001060 setType(TType(basicType, higherPrecision, resultQualifier,
1061 static_cast<unsigned char>(mRight->getCols()),
1062 static_cast<unsigned char>(mRight->getRows())));
Jamie Madillb1a85f42014-08-19 15:23:24 -04001063 }
Olli Etuaho1dded802016-08-18 18:13:13 +03001064 break;
1065 case EOpMatrixTimesVector:
1066 setType(TType(basicType, higherPrecision, resultQualifier,
1067 static_cast<unsigned char>(mLeft->getRows()), 1));
1068 break;
1069 case EOpMatrixTimesMatrix:
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001070 setType(TType(basicType, higherPrecision, resultQualifier,
1071 static_cast<unsigned char>(mRight->getCols()),
1072 static_cast<unsigned char>(mLeft->getRows())));
Olli Etuaho1dded802016-08-18 18:13:13 +03001073 break;
1074 case EOpVectorTimesScalar:
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001075 setType(TType(basicType, higherPrecision, resultQualifier,
Olli Etuaho1dded802016-08-18 18:13:13 +03001076 static_cast<unsigned char>(nominalSize), 1));
1077 break;
1078 case EOpVectorTimesMatrix:
1079 setType(TType(basicType, higherPrecision, resultQualifier,
1080 static_cast<unsigned char>(mRight->getCols()), 1));
1081 break;
1082 case EOpMulAssign:
1083 case EOpVectorTimesScalarAssign:
1084 case EOpVectorTimesMatrixAssign:
1085 case EOpMatrixTimesScalarAssign:
1086 case EOpMatrixTimesMatrixAssign:
1087 ASSERT(mOp == GetMulAssignOpBasedOnOperands(mLeft->getType(), mRight->getType()));
1088 break;
1089 case EOpAssign:
1090 case EOpInitialize:
Olli Etuaho1dded802016-08-18 18:13:13 +03001091 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
1092 (mLeft->getSecondarySize() == mRight->getSecondarySize()));
1093 break;
1094 case EOpAdd:
1095 case EOpSub:
1096 case EOpDiv:
1097 case EOpIMod:
1098 case EOpBitShiftLeft:
1099 case EOpBitShiftRight:
1100 case EOpBitwiseAnd:
1101 case EOpBitwiseXor:
1102 case EOpBitwiseOr:
1103 case EOpAddAssign:
1104 case EOpSubAssign:
1105 case EOpDivAssign:
1106 case EOpIModAssign:
1107 case EOpBitShiftLeftAssign:
1108 case EOpBitShiftRightAssign:
1109 case EOpBitwiseAndAssign:
1110 case EOpBitwiseXorAssign:
1111 case EOpBitwiseOrAssign:
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001112 {
1113 const int secondarySize =
1114 std::max(mLeft->getSecondarySize(), mRight->getSecondarySize());
1115 setType(TType(basicType, higherPrecision, resultQualifier,
1116 static_cast<unsigned char>(nominalSize),
1117 static_cast<unsigned char>(secondarySize)));
1118 ASSERT(!mLeft->isArray() && !mRight->isArray());
Olli Etuaho1dded802016-08-18 18:13:13 +03001119 break;
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001120 }
Olli Etuaho1dded802016-08-18 18:13:13 +03001121 case EOpEqual:
1122 case EOpNotEqual:
1123 case EOpLessThan:
1124 case EOpGreaterThan:
1125 case EOpLessThanEqual:
1126 case EOpGreaterThanEqual:
1127 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
1128 (mLeft->getSecondarySize() == mRight->getSecondarySize()));
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001129 setType(TType(EbtBool, EbpUndefined, resultQualifier));
Olli Etuaho1dded802016-08-18 18:13:13 +03001130 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001131
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001132 case EOpIndexDirect:
1133 case EOpIndexIndirect:
1134 case EOpIndexDirectInterfaceBlock:
1135 case EOpIndexDirectStruct:
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001136 // These ops should be already fully handled.
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001137 UNREACHABLE();
1138 break;
Olli Etuaho1dded802016-08-18 18:13:13 +03001139 default:
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001140 UNREACHABLE();
1141 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001142 }
Jamie Madillb1a85f42014-08-19 15:23:24 -04001143}
1144
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001145const TConstantUnion *TIntermConstantUnion::foldIndexing(int index)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001146{
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001147 if (isArray())
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001148 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001149 ASSERT(index < static_cast<int>(getType().getArraySize()));
1150 TType arrayElementType = getType();
1151 arrayElementType.clearArrayness();
1152 size_t arrayElementSize = arrayElementType.getObjectSize();
1153 return &mUnionArrayPointer[arrayElementSize * index];
1154 }
1155 else if (isMatrix())
1156 {
1157 ASSERT(index < getType().getCols());
1158 int size = getType().getRows();
1159 return &mUnionArrayPointer[size * index];
1160 }
1161 else if (isVector())
1162 {
1163 ASSERT(index < getType().getNominalSize());
1164 return &mUnionArrayPointer[index];
1165 }
1166 else
1167 {
1168 UNREACHABLE();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001169 return nullptr;
1170 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001171}
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001172
Olli Etuahob6fa0432016-09-28 16:28:05 +01001173TIntermTyped *TIntermSwizzle::fold()
1174{
1175 TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
1176 if (operandConstant == nullptr)
1177 {
1178 return nullptr;
1179 }
1180
1181 TConstantUnion *constArray = new TConstantUnion[mSwizzleOffsets.size()];
1182 for (size_t i = 0; i < mSwizzleOffsets.size(); ++i)
1183 {
1184 constArray[i] = *operandConstant->foldIndexing(mSwizzleOffsets.at(i));
1185 }
1186 return CreateFoldedNode(constArray, this, mType.getQualifier());
1187}
1188
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001189TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
1190{
1191 TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion();
1192 TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion();
1193 switch (mOp)
1194 {
1195 case EOpIndexDirect:
1196 {
1197 if (leftConstant == nullptr || rightConstant == nullptr)
1198 {
1199 return nullptr;
1200 }
1201 int index = rightConstant->getIConst(0);
1202
1203 const TConstantUnion *constArray = leftConstant->foldIndexing(index);
1204 return CreateFoldedNode(constArray, this, mType.getQualifier());
1205 }
1206 case EOpIndexDirectStruct:
1207 {
1208 if (leftConstant == nullptr || rightConstant == nullptr)
1209 {
1210 return nullptr;
1211 }
1212 const TFieldList &fields = mLeft->getType().getStruct()->fields();
1213 size_t index = static_cast<size_t>(rightConstant->getIConst(0));
1214
1215 size_t previousFieldsSize = 0;
1216 for (size_t i = 0; i < index; ++i)
1217 {
1218 previousFieldsSize += fields[i]->type()->getObjectSize();
1219 }
1220
1221 const TConstantUnion *constArray = leftConstant->getUnionArrayPointer();
1222 return CreateFoldedNode(constArray + previousFieldsSize, this, mType.getQualifier());
1223 }
1224 case EOpIndexIndirect:
1225 case EOpIndexDirectInterfaceBlock:
1226 // Can never be constant folded.
1227 return nullptr;
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001228 default:
1229 {
1230 if (leftConstant == nullptr || rightConstant == nullptr)
1231 {
1232 return nullptr;
1233 }
Jamie Madill5db69f52016-09-15 12:47:32 -04001234 TConstantUnion *constArray =
1235 leftConstant->foldBinary(mOp, rightConstant, diagnostics, mLeft->getLine());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001236
1237 // Nodes may be constant folded without being qualified as constant.
1238 return CreateFoldedNode(constArray, this, mType.getQualifier());
1239 }
1240 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001241}
1242
Olli Etuahof119a262016-08-19 15:54:22 +03001243TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
Olli Etuaho95310b02015-06-02 17:43:38 +03001244{
1245 TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
1246 if (operandConstant == nullptr)
1247 {
1248 return nullptr;
1249 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301250
1251 TConstantUnion *constArray = nullptr;
1252 switch (mOp)
1253 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001254 case EOpAny:
1255 case EOpAll:
1256 case EOpLength:
1257 case EOpTranspose:
1258 case EOpDeterminant:
1259 case EOpInverse:
1260 case EOpPackSnorm2x16:
1261 case EOpUnpackSnorm2x16:
1262 case EOpPackUnorm2x16:
1263 case EOpUnpackUnorm2x16:
1264 case EOpPackHalf2x16:
1265 case EOpUnpackHalf2x16:
1266 constArray = operandConstant->foldUnaryNonComponentWise(mOp);
1267 break;
1268 default:
1269 constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics);
1270 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301271 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001272
1273 // Nodes may be constant folded without being qualified as constant.
Olli Etuahoc9550582016-08-29 17:56:22 +03001274 return CreateFoldedNode(constArray, this, mType.getQualifier());
Olli Etuahob43846e2015-06-02 18:18:57 +03001275}
1276
Olli Etuahof119a262016-08-19 15:54:22 +03001277TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics)
Olli Etuahob43846e2015-06-02 18:18:57 +03001278{
1279 // Make sure that all params are constant before actual constant folding.
1280 for (auto *param : *getSequence())
Olli Etuaho95310b02015-06-02 17:43:38 +03001281 {
Olli Etuahob43846e2015-06-02 18:18:57 +03001282 if (param->getAsConstantUnion() == nullptr)
1283 {
1284 return nullptr;
1285 }
Olli Etuaho95310b02015-06-02 17:43:38 +03001286 }
Olli Etuaho1d122782015-11-06 15:35:17 +02001287 TConstantUnion *constArray = nullptr;
1288 if (isConstructor())
Olli Etuahof119a262016-08-19 15:54:22 +03001289 constArray = TIntermConstantUnion::FoldAggregateConstructor(this);
Olli Etuaho1d122782015-11-06 15:35:17 +02001290 else
Olli Etuahof119a262016-08-19 15:54:22 +03001291 constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001292
1293 // Nodes may be constant folded without being qualified as constant.
1294 TQualifier resultQualifier = areChildrenConstQualified() ? EvqConst : EvqTemporary;
1295 return CreateFoldedNode(constArray, this, resultQualifier);
Olli Etuaho95310b02015-06-02 17:43:38 +03001296}
1297
Jamie Madillb1a85f42014-08-19 15:23:24 -04001298//
1299// The fold functions see if an operation on a constant can be done in place,
1300// without generating run-time code.
1301//
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001302// Returns the constant value to keep using or nullptr.
Jamie Madillb1a85f42014-08-19 15:23:24 -04001303//
Olli Etuaho3fdec912016-08-18 15:08:06 +03001304TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op,
1305 TIntermConstantUnion *rightNode,
Jamie Madill5db69f52016-09-15 12:47:32 -04001306 TDiagnostics *diagnostics,
1307 const TSourceLoc &line)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001308{
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001309 const TConstantUnion *leftArray = getUnionArrayPointer();
1310 const TConstantUnion *rightArray = rightNode->getUnionArrayPointer();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001311
Olli Etuahof119a262016-08-19 15:54:22 +03001312 ASSERT(leftArray && rightArray);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001313
1314 size_t objectSize = getType().getObjectSize();
1315
1316 // for a case like float f = vec4(2, 3, 4, 5) + 1.2;
1317 if (rightNode->getType().getObjectSize() == 1 && objectSize > 1)
1318 {
1319 rightArray = Vectorize(*rightNode->getUnionArrayPointer(), objectSize);
1320 }
1321 else if (rightNode->getType().getObjectSize() > 1 && objectSize == 1)
1322 {
1323 // for a case like float f = 1.2 + vec4(2, 3, 4, 5);
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001324 leftArray = Vectorize(*getUnionArrayPointer(), rightNode->getType().getObjectSize());
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001325 objectSize = rightNode->getType().getObjectSize();
1326 }
1327
1328 TConstantUnion *resultArray = nullptr;
1329
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001330 switch (op)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001331 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001332 case EOpAdd:
1333 resultArray = new TConstantUnion[objectSize];
1334 for (size_t i = 0; i < objectSize; i++)
1335 resultArray[i] =
1336 TConstantUnion::add(leftArray[i], rightArray[i], diagnostics, line);
1337 break;
1338 case EOpSub:
1339 resultArray = new TConstantUnion[objectSize];
1340 for (size_t i = 0; i < objectSize; i++)
1341 resultArray[i] =
1342 TConstantUnion::sub(leftArray[i], rightArray[i], diagnostics, line);
1343 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001344
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001345 case EOpMul:
1346 case EOpVectorTimesScalar:
1347 case EOpMatrixTimesScalar:
1348 resultArray = new TConstantUnion[objectSize];
1349 for (size_t i = 0; i < objectSize; i++)
1350 resultArray[i] =
1351 TConstantUnion::mul(leftArray[i], rightArray[i], diagnostics, line);
1352 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001353
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001354 case EOpMatrixTimesMatrix:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001355 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001356 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001357 ASSERT(getType().getBasicType() == EbtFloat && rightNode->getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001358
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001359 const int leftCols = getCols();
1360 const int leftRows = getRows();
1361 const int rightCols = rightNode->getType().getCols();
1362 const int rightRows = rightNode->getType().getRows();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001363 const int resultCols = rightCols;
1364 const int resultRows = leftRows;
1365
1366 resultArray = new TConstantUnion[resultCols * resultRows];
1367 for (int row = 0; row < resultRows; row++)
1368 {
1369 for (int column = 0; column < resultCols; column++)
1370 {
1371 resultArray[resultRows * column + row].setFConst(0.0f);
1372 for (int i = 0; i < leftCols; i++)
1373 {
1374 resultArray[resultRows * column + row].setFConst(
1375 resultArray[resultRows * column + row].getFConst() +
1376 leftArray[i * leftRows + row].getFConst() *
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001377 rightArray[column * rightRows + i].getFConst());
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001378 }
1379 }
1380 }
1381 }
1382 break;
1383
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001384 case EOpDiv:
1385 case EOpIMod:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001386 {
1387 resultArray = new TConstantUnion[objectSize];
1388 for (size_t i = 0; i < objectSize; i++)
1389 {
1390 switch (getType().getBasicType())
1391 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001392 case EbtFloat:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001393 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001394 ASSERT(op == EOpDiv);
1395 float dividend = leftArray[i].getFConst();
1396 float divisor = rightArray[i].getFConst();
1397 if (divisor == 0.0f)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001398 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001399 if (dividend == 0.0f)
Olli Etuahod4453572016-09-27 13:21:46 +01001400 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001401 diagnostics->warning(
1402 getLine(),
1403 "Zero divided by zero during constant folding generated NaN",
Olli Etuaho4de340a2016-12-16 09:32:03 +00001404 "/");
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001405 resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
Olli Etuahod4453572016-09-27 13:21:46 +01001406 }
1407 else
1408 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001409 diagnostics->warning(getLine(),
1410 "Divide by zero during constant folding", "/");
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001411 bool negativeResult =
1412 std::signbit(dividend) != std::signbit(divisor);
1413 resultArray[i].setFConst(
1414 negativeResult ? -std::numeric_limits<float>::infinity()
1415 : std::numeric_limits<float>::infinity());
Olli Etuahod4453572016-09-27 13:21:46 +01001416 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001417 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001418 else if (gl::isInf(dividend) && gl::isInf(divisor))
1419 {
1420 diagnostics->warning(getLine(),
1421 "Infinity divided by infinity during constant "
1422 "folding generated NaN",
Olli Etuaho4de340a2016-12-16 09:32:03 +00001423 "/");
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001424 resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
1425 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001426 else
1427 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001428 float result = dividend / divisor;
1429 if (!gl::isInf(dividend) && gl::isInf(result))
Olli Etuahod4453572016-09-27 13:21:46 +01001430 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001431 diagnostics->warning(
1432 getLine(), "Constant folded division overflowed to infinity",
Olli Etuaho4de340a2016-12-16 09:32:03 +00001433 "/");
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001434 }
1435 resultArray[i].setFConst(result);
1436 }
1437 break;
1438 }
1439 case EbtInt:
1440 if (rightArray[i] == 0)
1441 {
1442 diagnostics->warning(
Olli Etuaho4de340a2016-12-16 09:32:03 +00001443 getLine(), "Divide by zero error during constant folding", "/");
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001444 resultArray[i].setIConst(INT_MAX);
1445 }
1446 else
1447 {
1448 int lhs = leftArray[i].getIConst();
1449 int divisor = rightArray[i].getIConst();
1450 if (op == EOpDiv)
1451 {
1452 // Check for the special case where the minimum representable number
1453 // is
1454 // divided by -1. If left alone this leads to integer overflow in
1455 // C++.
1456 // ESSL 3.00.6 section 4.1.3 Integers:
1457 // "However, for the case where the minimum representable value is
1458 // divided by -1, it is allowed to return either the minimum
1459 // representable value or the maximum representable value."
1460 if (lhs == -0x7fffffff - 1 && divisor == -1)
1461 {
1462 resultArray[i].setIConst(0x7fffffff);
1463 }
1464 else
1465 {
1466 resultArray[i].setIConst(lhs / divisor);
1467 }
Olli Etuahod4453572016-09-27 13:21:46 +01001468 }
1469 else
1470 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001471 ASSERT(op == EOpIMod);
1472 if (lhs < 0 || divisor < 0)
1473 {
1474 // ESSL 3.00.6 section 5.9: Results of modulus are undefined
1475 // when
1476 // either one of the operands is negative.
1477 diagnostics->warning(getLine(),
1478 "Negative modulus operator operand "
1479 "encountered during constant folding",
Olli Etuaho4de340a2016-12-16 09:32:03 +00001480 "%");
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001481 resultArray[i].setIConst(0);
1482 }
1483 else
1484 {
1485 resultArray[i].setIConst(lhs % divisor);
1486 }
Olli Etuahod4453572016-09-27 13:21:46 +01001487 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001488 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001489 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001490
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001491 case EbtUInt:
1492 if (rightArray[i] == 0)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001493 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001494 diagnostics->warning(
Olli Etuaho4de340a2016-12-16 09:32:03 +00001495 getLine(), "Divide by zero error during constant folding", "/");
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001496 resultArray[i].setUConst(UINT_MAX);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001497 }
1498 else
1499 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001500 if (op == EOpDiv)
1501 {
1502 resultArray[i].setUConst(leftArray[i].getUConst() /
1503 rightArray[i].getUConst());
1504 }
1505 else
1506 {
1507 ASSERT(op == EOpIMod);
1508 resultArray[i].setUConst(leftArray[i].getUConst() %
1509 rightArray[i].getUConst());
1510 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001511 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001512 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001513
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001514 default:
1515 UNREACHABLE();
1516 return nullptr;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001517 }
1518 }
1519 }
1520 break;
1521
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001522 case EOpMatrixTimesVector:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001523 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001524 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001525 ASSERT(rightNode->getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001526
1527 const int matrixCols = getCols();
1528 const int matrixRows = getRows();
1529
1530 resultArray = new TConstantUnion[matrixRows];
1531
1532 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
1533 {
1534 resultArray[matrixRow].setFConst(0.0f);
1535 for (int col = 0; col < matrixCols; col++)
1536 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001537 resultArray[matrixRow].setFConst(
1538 resultArray[matrixRow].getFConst() +
1539 leftArray[col * matrixRows + matrixRow].getFConst() *
1540 rightArray[col].getFConst());
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001541 }
1542 }
1543 }
1544 break;
1545
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001546 case EOpVectorTimesMatrix:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001547 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001548 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001549 ASSERT(getType().getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001550
1551 const int matrixCols = rightNode->getType().getCols();
1552 const int matrixRows = rightNode->getType().getRows();
1553
1554 resultArray = new TConstantUnion[matrixCols];
1555
1556 for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++)
1557 {
1558 resultArray[matrixCol].setFConst(0.0f);
1559 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
1560 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001561 resultArray[matrixCol].setFConst(
1562 resultArray[matrixCol].getFConst() +
1563 leftArray[matrixRow].getFConst() *
1564 rightArray[matrixCol * matrixRows + matrixRow].getFConst());
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001565 }
1566 }
1567 }
1568 break;
1569
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001570 case EOpLogicalAnd:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001571 {
1572 resultArray = new TConstantUnion[objectSize];
1573 for (size_t i = 0; i < objectSize; i++)
1574 {
1575 resultArray[i] = leftArray[i] && rightArray[i];
1576 }
1577 }
1578 break;
1579
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001580 case EOpLogicalOr:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001581 {
1582 resultArray = new TConstantUnion[objectSize];
1583 for (size_t i = 0; i < objectSize; i++)
1584 {
1585 resultArray[i] = leftArray[i] || rightArray[i];
1586 }
1587 }
1588 break;
1589
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001590 case EOpLogicalXor:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001591 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001592 ASSERT(getType().getBasicType() == EbtBool);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001593 resultArray = new TConstantUnion[objectSize];
1594 for (size_t i = 0; i < objectSize; i++)
1595 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001596 resultArray[i].setBConst(leftArray[i] != rightArray[i]);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001597 }
1598 }
1599 break;
1600
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001601 case EOpBitwiseAnd:
1602 resultArray = new TConstantUnion[objectSize];
1603 for (size_t i = 0; i < objectSize; i++)
1604 resultArray[i] = leftArray[i] & rightArray[i];
1605 break;
1606 case EOpBitwiseXor:
1607 resultArray = new TConstantUnion[objectSize];
1608 for (size_t i = 0; i < objectSize; i++)
1609 resultArray[i] = leftArray[i] ^ rightArray[i];
1610 break;
1611 case EOpBitwiseOr:
1612 resultArray = new TConstantUnion[objectSize];
1613 for (size_t i = 0; i < objectSize; i++)
1614 resultArray[i] = leftArray[i] | rightArray[i];
1615 break;
1616 case EOpBitShiftLeft:
1617 resultArray = new TConstantUnion[objectSize];
1618 for (size_t i = 0; i < objectSize; i++)
1619 resultArray[i] =
1620 TConstantUnion::lshift(leftArray[i], rightArray[i], diagnostics, line);
1621 break;
1622 case EOpBitShiftRight:
1623 resultArray = new TConstantUnion[objectSize];
1624 for (size_t i = 0; i < objectSize; i++)
1625 resultArray[i] =
1626 TConstantUnion::rshift(leftArray[i], rightArray[i], diagnostics, line);
1627 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001628
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001629 case EOpLessThan:
1630 ASSERT(objectSize == 1);
1631 resultArray = new TConstantUnion[1];
1632 resultArray->setBConst(*leftArray < *rightArray);
1633 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001634
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001635 case EOpGreaterThan:
1636 ASSERT(objectSize == 1);
1637 resultArray = new TConstantUnion[1];
1638 resultArray->setBConst(*leftArray > *rightArray);
1639 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001640
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001641 case EOpLessThanEqual:
1642 ASSERT(objectSize == 1);
1643 resultArray = new TConstantUnion[1];
1644 resultArray->setBConst(!(*leftArray > *rightArray));
1645 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001646
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001647 case EOpGreaterThanEqual:
1648 ASSERT(objectSize == 1);
1649 resultArray = new TConstantUnion[1];
1650 resultArray->setBConst(!(*leftArray < *rightArray));
1651 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001652
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001653 case EOpEqual:
1654 case EOpNotEqual:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001655 {
1656 resultArray = new TConstantUnion[1];
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001657 bool equal = true;
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001658 for (size_t i = 0; i < objectSize; i++)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001659 {
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001660 if (leftArray[i] != rightArray[i])
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001661 {
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001662 equal = false;
1663 break; // break out of for loop
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001664 }
1665 }
1666 if (op == EOpEqual)
1667 {
1668 resultArray->setBConst(equal);
1669 }
1670 else
1671 {
1672 resultArray->setBConst(!equal);
1673 }
1674 }
1675 break;
1676
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001677 default:
1678 UNREACHABLE();
1679 return nullptr;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001680 }
1681 return resultArray;
1682}
1683
Olli Etuahof119a262016-08-19 15:54:22 +03001684// The fold functions do operations on a constant at GLSL compile time, without generating run-time
1685// code. Returns the constant value to keep using. Nullptr should not be returned.
1686TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op)
Jamie Madillb1a85f42014-08-19 15:23:24 -04001687{
Olli Etuahof119a262016-08-19 15:54:22 +03001688 // Do operations where the return type may have a different number of components compared to the
1689 // operand type.
Jamie Madillb1a85f42014-08-19 15:23:24 -04001690
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001691 const TConstantUnion *operandArray = getUnionArrayPointer();
Olli Etuahof119a262016-08-19 15:54:22 +03001692 ASSERT(operandArray);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301693
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001694 size_t objectSize = getType().getObjectSize();
Arun Patoleab2b9a22015-07-06 18:27:56 +05301695 TConstantUnion *resultArray = nullptr;
1696 switch (op)
1697 {
Olli Etuahof119a262016-08-19 15:54:22 +03001698 case EOpAny:
1699 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301700 resultArray = new TConstantUnion();
1701 resultArray->setBConst(false);
1702 for (size_t i = 0; i < objectSize; i++)
1703 {
1704 if (operandArray[i].getBConst())
1705 {
1706 resultArray->setBConst(true);
1707 break;
1708 }
1709 }
1710 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301711
Olli Etuahof119a262016-08-19 15:54:22 +03001712 case EOpAll:
1713 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301714 resultArray = new TConstantUnion();
1715 resultArray->setBConst(true);
1716 for (size_t i = 0; i < objectSize; i++)
1717 {
1718 if (!operandArray[i].getBConst())
1719 {
1720 resultArray->setBConst(false);
1721 break;
1722 }
1723 }
1724 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301725
Olli Etuahof119a262016-08-19 15:54:22 +03001726 case EOpLength:
1727 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301728 resultArray = new TConstantUnion();
1729 resultArray->setFConst(VectorLength(operandArray, objectSize));
1730 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301731
Olli Etuahof119a262016-08-19 15:54:22 +03001732 case EOpTranspose:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301733 {
Olli Etuahof119a262016-08-19 15:54:22 +03001734 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301735 resultArray = new TConstantUnion[objectSize];
1736 angle::Matrix<float> result =
Olli Etuahod5da5052016-08-29 13:16:55 +03001737 GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose();
Arun Patoleab2b9a22015-07-06 18:27:56 +05301738 SetUnionArrayFromMatrix(result, resultArray);
1739 break;
1740 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301741
Olli Etuahof119a262016-08-19 15:54:22 +03001742 case EOpDeterminant:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301743 {
Olli Etuahof119a262016-08-19 15:54:22 +03001744 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301745 unsigned int size = getType().getNominalSize();
1746 ASSERT(size >= 2 && size <= 4);
1747 resultArray = new TConstantUnion();
1748 resultArray->setFConst(GetMatrix(operandArray, size).determinant());
1749 break;
1750 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301751
Olli Etuahof119a262016-08-19 15:54:22 +03001752 case EOpInverse:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301753 {
Olli Etuahof119a262016-08-19 15:54:22 +03001754 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301755 unsigned int size = getType().getNominalSize();
1756 ASSERT(size >= 2 && size <= 4);
Olli Etuahof119a262016-08-19 15:54:22 +03001757 resultArray = new TConstantUnion[objectSize];
Arun Patoleab2b9a22015-07-06 18:27:56 +05301758 angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
1759 SetUnionArrayFromMatrix(result, resultArray);
1760 break;
1761 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301762
Olli Etuahof119a262016-08-19 15:54:22 +03001763 case EOpPackSnorm2x16:
1764 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301765 ASSERT(getType().getNominalSize() == 2);
1766 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001767 resultArray->setUConst(
1768 gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301769 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301770
Olli Etuahof119a262016-08-19 15:54:22 +03001771 case EOpUnpackSnorm2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301772 {
Olli Etuahof119a262016-08-19 15:54:22 +03001773 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301774 resultArray = new TConstantUnion[2];
1775 float f1, f2;
1776 gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
1777 resultArray[0].setFConst(f1);
1778 resultArray[1].setFConst(f2);
1779 break;
1780 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301781
Olli Etuahof119a262016-08-19 15:54:22 +03001782 case EOpPackUnorm2x16:
1783 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301784 ASSERT(getType().getNominalSize() == 2);
1785 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001786 resultArray->setUConst(
1787 gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301788 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301789
Olli Etuahof119a262016-08-19 15:54:22 +03001790 case EOpUnpackUnorm2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301791 {
Olli Etuahof119a262016-08-19 15:54:22 +03001792 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301793 resultArray = new TConstantUnion[2];
1794 float f1, f2;
1795 gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
1796 resultArray[0].setFConst(f1);
1797 resultArray[1].setFConst(f2);
1798 break;
1799 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301800
Olli Etuahof119a262016-08-19 15:54:22 +03001801 case EOpPackHalf2x16:
1802 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301803 ASSERT(getType().getNominalSize() == 2);
1804 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001805 resultArray->setUConst(
1806 gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301807 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301808
Olli Etuahof119a262016-08-19 15:54:22 +03001809 case EOpUnpackHalf2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301810 {
Olli Etuahof119a262016-08-19 15:54:22 +03001811 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301812 resultArray = new TConstantUnion[2];
1813 float f1, f2;
1814 gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2);
1815 resultArray[0].setFConst(f1);
1816 resultArray[1].setFConst(f2);
1817 break;
1818 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301819
Olli Etuahof119a262016-08-19 15:54:22 +03001820 default:
1821 UNREACHABLE();
1822 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301823 }
1824
1825 return resultArray;
1826}
1827
Olli Etuahof119a262016-08-19 15:54:22 +03001828TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op,
1829 TDiagnostics *diagnostics)
Arun Patoleab2b9a22015-07-06 18:27:56 +05301830{
Olli Etuahof119a262016-08-19 15:54:22 +03001831 // Do unary operations where each component of the result is computed based on the corresponding
1832 // component of the operand. Also folds normalize, though the divisor in that case takes all
1833 // components into account.
Arun Patoleab2b9a22015-07-06 18:27:56 +05301834
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001835 const TConstantUnion *operandArray = getUnionArrayPointer();
Olli Etuahof119a262016-08-19 15:54:22 +03001836 ASSERT(operandArray);
Jamie Madillb1a85f42014-08-19 15:23:24 -04001837
1838 size_t objectSize = getType().getObjectSize();
1839
Arun Patoleab2b9a22015-07-06 18:27:56 +05301840 TConstantUnion *resultArray = new TConstantUnion[objectSize];
1841 for (size_t i = 0; i < objectSize; i++)
Arun Patole9d0b1f92015-05-20 14:27:17 +05301842 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001843 switch (op)
Arun Patole9d0b1f92015-05-20 14:27:17 +05301844 {
Olli Etuahof119a262016-08-19 15:54:22 +03001845 case EOpNegative:
1846 switch (getType().getBasicType())
1847 {
1848 case EbtFloat:
1849 resultArray[i].setFConst(-operandArray[i].getFConst());
1850 break;
1851 case EbtInt:
Olli Etuaho42fad762016-09-28 10:06:29 +01001852 if (operandArray[i] == std::numeric_limits<int>::min())
1853 {
1854 // The minimum representable integer doesn't have a positive
1855 // counterpart, rather the negation overflows and in ESSL is supposed to
1856 // wrap back to the minimum representable integer. Make sure that we
1857 // don't actually let the negation overflow, which has undefined
1858 // behavior in C++.
1859 resultArray[i].setIConst(std::numeric_limits<int>::min());
1860 }
1861 else
1862 {
1863 resultArray[i].setIConst(-operandArray[i].getIConst());
1864 }
Olli Etuahof119a262016-08-19 15:54:22 +03001865 break;
1866 case EbtUInt:
Olli Etuaho42fad762016-09-28 10:06:29 +01001867 if (operandArray[i] == 0x80000000u)
1868 {
1869 resultArray[i].setUConst(0x80000000u);
1870 }
1871 else
1872 {
1873 resultArray[i].setUConst(static_cast<unsigned int>(
1874 -static_cast<int>(operandArray[i].getUConst())));
1875 }
Olli Etuahof119a262016-08-19 15:54:22 +03001876 break;
1877 default:
1878 UNREACHABLE();
1879 return nullptr;
1880 }
Arun Patole1155ddd2015-06-05 18:04:36 +05301881 break;
Arun Patolecdfa8f52015-06-30 17:48:25 +05301882
Olli Etuahof119a262016-08-19 15:54:22 +03001883 case EOpPositive:
1884 switch (getType().getBasicType())
1885 {
1886 case EbtFloat:
1887 resultArray[i].setFConst(operandArray[i].getFConst());
1888 break;
1889 case EbtInt:
1890 resultArray[i].setIConst(operandArray[i].getIConst());
1891 break;
1892 case EbtUInt:
1893 resultArray[i].setUConst(static_cast<unsigned int>(
1894 static_cast<int>(operandArray[i].getUConst())));
1895 break;
1896 default:
1897 UNREACHABLE();
1898 return nullptr;
1899 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301900 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301901
Olli Etuahof119a262016-08-19 15:54:22 +03001902 case EOpLogicalNot:
1903 switch (getType().getBasicType())
1904 {
1905 case EbtBool:
1906 resultArray[i].setBConst(!operandArray[i].getBConst());
1907 break;
1908 default:
1909 UNREACHABLE();
1910 return nullptr;
1911 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301912 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301913
Olli Etuahof119a262016-08-19 15:54:22 +03001914 case EOpBitwiseNot:
1915 switch (getType().getBasicType())
1916 {
1917 case EbtInt:
1918 resultArray[i].setIConst(~operandArray[i].getIConst());
1919 break;
1920 case EbtUInt:
1921 resultArray[i].setUConst(~operandArray[i].getUConst());
1922 break;
1923 default:
1924 UNREACHABLE();
1925 return nullptr;
1926 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301927 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301928
Olli Etuahof119a262016-08-19 15:54:22 +03001929 case EOpRadians:
1930 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301931 resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
1932 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301933
Olli Etuahof119a262016-08-19 15:54:22 +03001934 case EOpDegrees:
1935 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301936 resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
1937 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301938
Olli Etuahof119a262016-08-19 15:54:22 +03001939 case EOpSin:
1940 foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301941 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301942
Olli Etuahof119a262016-08-19 15:54:22 +03001943 case EOpCos:
1944 foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]);
1945 break;
1946
1947 case EOpTan:
1948 foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]);
1949 break;
1950
1951 case EOpAsin:
1952 // For asin(x), results are undefined if |x| > 1, we are choosing to set result to
1953 // 0.
1954 if (fabsf(operandArray[i].getFConst()) > 1.0f)
1955 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1956 diagnostics, &resultArray[i]);
1957 else
1958 foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]);
1959 break;
1960
1961 case EOpAcos:
1962 // For acos(x), results are undefined if |x| > 1, we are choosing to set result to
1963 // 0.
1964 if (fabsf(operandArray[i].getFConst()) > 1.0f)
1965 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1966 diagnostics, &resultArray[i]);
1967 else
1968 foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]);
1969 break;
1970
1971 case EOpAtan:
1972 foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]);
1973 break;
1974
1975 case EOpSinh:
1976 foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]);
1977 break;
1978
1979 case EOpCosh:
1980 foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]);
1981 break;
1982
1983 case EOpTanh:
1984 foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]);
1985 break;
1986
1987 case EOpAsinh:
1988 foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]);
1989 break;
1990
1991 case EOpAcosh:
1992 // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
1993 if (operandArray[i].getFConst() < 1.0f)
1994 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1995 diagnostics, &resultArray[i]);
1996 else
1997 foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]);
1998 break;
1999
2000 case EOpAtanh:
2001 // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to
2002 // 0.
2003 if (fabsf(operandArray[i].getFConst()) >= 1.0f)
2004 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2005 diagnostics, &resultArray[i]);
2006 else
2007 foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]);
2008 break;
2009
2010 case EOpAbs:
2011 switch (getType().getBasicType())
Arun Patoleab2b9a22015-07-06 18:27:56 +05302012 {
Olli Etuahof119a262016-08-19 15:54:22 +03002013 case EbtFloat:
2014 resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
2015 break;
2016 case EbtInt:
2017 resultArray[i].setIConst(abs(operandArray[i].getIConst()));
2018 break;
2019 default:
2020 UNREACHABLE();
2021 return nullptr;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302022 }
2023 break;
Olli Etuahof119a262016-08-19 15:54:22 +03002024
2025 case EOpSign:
2026 switch (getType().getBasicType())
Arun Patoleab2b9a22015-07-06 18:27:56 +05302027 {
Olli Etuahof119a262016-08-19 15:54:22 +03002028 case EbtFloat:
2029 {
2030 float fConst = operandArray[i].getFConst();
2031 float fResult = 0.0f;
2032 if (fConst > 0.0f)
2033 fResult = 1.0f;
2034 else if (fConst < 0.0f)
2035 fResult = -1.0f;
2036 resultArray[i].setFConst(fResult);
2037 break;
2038 }
2039 case EbtInt:
2040 {
2041 int iConst = operandArray[i].getIConst();
2042 int iResult = 0;
2043 if (iConst > 0)
2044 iResult = 1;
2045 else if (iConst < 0)
2046 iResult = -1;
2047 resultArray[i].setIConst(iResult);
2048 break;
2049 }
2050 default:
2051 UNREACHABLE();
2052 return nullptr;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302053 }
2054 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302055
Olli Etuahof119a262016-08-19 15:54:22 +03002056 case EOpFloor:
2057 foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]);
2058 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302059
Olli Etuahof119a262016-08-19 15:54:22 +03002060 case EOpTrunc:
2061 foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]);
2062 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302063
Olli Etuahof119a262016-08-19 15:54:22 +03002064 case EOpRound:
2065 foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]);
2066 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302067
Olli Etuahof119a262016-08-19 15:54:22 +03002068 case EOpRoundEven:
Arun Patoleab2b9a22015-07-06 18:27:56 +05302069 {
Olli Etuahof119a262016-08-19 15:54:22 +03002070 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302071 float x = operandArray[i].getFConst();
2072 float result;
2073 float fractPart = modff(x, &result);
2074 if (fabsf(fractPart) == 0.5f)
2075 result = 2.0f * roundf(x / 2.0f);
2076 else
2077 result = roundf(x);
2078 resultArray[i].setFConst(result);
2079 break;
2080 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05302081
Olli Etuahof119a262016-08-19 15:54:22 +03002082 case EOpCeil:
2083 foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]);
2084 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302085
Olli Etuahof119a262016-08-19 15:54:22 +03002086 case EOpFract:
Arun Patoleab2b9a22015-07-06 18:27:56 +05302087 {
Olli Etuahof119a262016-08-19 15:54:22 +03002088 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302089 float x = operandArray[i].getFConst();
2090 resultArray[i].setFConst(x - floorf(x));
2091 break;
2092 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05302093
Olli Etuahof119a262016-08-19 15:54:22 +03002094 case EOpIsNan:
2095 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302096 resultArray[i].setBConst(gl::isNaN(operandArray[0].getFConst()));
2097 break;
Arun Patole551279e2015-07-07 18:18:23 +05302098
Olli Etuahof119a262016-08-19 15:54:22 +03002099 case EOpIsInf:
2100 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302101 resultArray[i].setBConst(gl::isInf(operandArray[0].getFConst()));
2102 break;
Arun Patole551279e2015-07-07 18:18:23 +05302103
Olli Etuahof119a262016-08-19 15:54:22 +03002104 case EOpFloatBitsToInt:
2105 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302106 resultArray[i].setIConst(gl::bitCast<int32_t>(operandArray[0].getFConst()));
2107 break;
Arun Patole551279e2015-07-07 18:18:23 +05302108
Olli Etuahof119a262016-08-19 15:54:22 +03002109 case EOpFloatBitsToUint:
2110 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302111 resultArray[i].setUConst(gl::bitCast<uint32_t>(operandArray[0].getFConst()));
2112 break;
Arun Patole551279e2015-07-07 18:18:23 +05302113
Olli Etuahof119a262016-08-19 15:54:22 +03002114 case EOpIntBitsToFloat:
2115 ASSERT(getType().getBasicType() == EbtInt);
Arun Patole551279e2015-07-07 18:18:23 +05302116 resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getIConst()));
2117 break;
Arun Patole551279e2015-07-07 18:18:23 +05302118
Olli Etuahof119a262016-08-19 15:54:22 +03002119 case EOpUintBitsToFloat:
2120 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patole551279e2015-07-07 18:18:23 +05302121 resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getUConst()));
2122 break;
Arun Patole551279e2015-07-07 18:18:23 +05302123
Olli Etuahof119a262016-08-19 15:54:22 +03002124 case EOpExp:
2125 foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]);
2126 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302127
Olli Etuahof119a262016-08-19 15:54:22 +03002128 case EOpLog:
2129 // For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
2130 if (operandArray[i].getFConst() <= 0.0f)
2131 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2132 diagnostics, &resultArray[i]);
2133 else
2134 foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
2135 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302136
Olli Etuahof119a262016-08-19 15:54:22 +03002137 case EOpExp2:
2138 foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]);
2139 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302140
Olli Etuahof119a262016-08-19 15:54:22 +03002141 case EOpLog2:
2142 // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
2143 // And log2f is not available on some plarforms like old android, so just using
2144 // log(x)/log(2) here.
2145 if (operandArray[i].getFConst() <= 0.0f)
2146 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2147 diagnostics, &resultArray[i]);
2148 else
2149 {
2150 foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
2151 resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
2152 }
2153 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302154
Olli Etuahof119a262016-08-19 15:54:22 +03002155 case EOpSqrt:
2156 // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
2157 if (operandArray[i].getFConst() < 0.0f)
2158 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2159 diagnostics, &resultArray[i]);
2160 else
2161 foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
2162 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302163
Olli Etuahof119a262016-08-19 15:54:22 +03002164 case EOpInverseSqrt:
2165 // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
2166 // so getting the square root first using builtin function sqrt() and then taking
2167 // its inverse.
2168 // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set
2169 // result to 0.
2170 if (operandArray[i].getFConst() <= 0.0f)
2171 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2172 diagnostics, &resultArray[i]);
2173 else
2174 {
2175 foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
2176 resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
2177 }
2178 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302179
Olli Etuahod68924e2017-01-02 17:34:40 +00002180 case EOpLogicalNotComponentWise:
Olli Etuahof119a262016-08-19 15:54:22 +03002181 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302182 resultArray[i].setBConst(!operandArray[i].getBConst());
2183 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302184
Olli Etuahof119a262016-08-19 15:54:22 +03002185 case EOpNormalize:
Arun Patoleab2b9a22015-07-06 18:27:56 +05302186 {
Olli Etuahof119a262016-08-19 15:54:22 +03002187 ASSERT(getType().getBasicType() == EbtFloat);
2188 float x = operandArray[i].getFConst();
Arun Patoleab2b9a22015-07-06 18:27:56 +05302189 float length = VectorLength(operandArray, objectSize);
2190 if (length)
2191 resultArray[i].setFConst(x / length);
2192 else
Olli Etuahof119a262016-08-19 15:54:22 +03002193 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2194 diagnostics, &resultArray[i]);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302195 break;
2196 }
Olli Etuaho9250cb22017-01-21 10:51:27 +00002197 case EOpBitfieldReverse:
2198 {
2199 uint32_t value;
2200 if (getType().getBasicType() == EbtInt)
2201 {
2202 value = static_cast<uint32_t>(operandArray[i].getIConst());
2203 }
2204 else
2205 {
2206 ASSERT(getType().getBasicType() == EbtUInt);
2207 value = operandArray[i].getUConst();
2208 }
2209 uint32_t result = gl::BitfieldReverse(value);
2210 if (getType().getBasicType() == EbtInt)
2211 {
2212 resultArray[i].setIConst(static_cast<int32_t>(result));
2213 }
2214 else
2215 {
2216 resultArray[i].setUConst(result);
2217 }
2218 break;
2219 }
2220 case EOpBitCount:
2221 {
2222 uint32_t value;
2223 if (getType().getBasicType() == EbtInt)
2224 {
2225 value = static_cast<uint32_t>(operandArray[i].getIConst());
2226 }
2227 else
2228 {
2229 ASSERT(getType().getBasicType() == EbtUInt);
2230 value = operandArray[i].getUConst();
2231 }
2232 int result = gl::BitCount(value);
2233 resultArray[i].setIConst(result);
2234 break;
2235 }
2236 case EOpFindLSB:
2237 {
2238 uint32_t value;
2239 if (getType().getBasicType() == EbtInt)
2240 {
2241 value = static_cast<uint32_t>(operandArray[i].getIConst());
2242 }
2243 else
2244 {
2245 ASSERT(getType().getBasicType() == EbtUInt);
2246 value = operandArray[i].getUConst();
2247 }
2248 resultArray[i].setIConst(gl::FindLSB(value));
2249 break;
2250 }
2251 case EOpFindMSB:
2252 {
2253 uint32_t value;
2254 if (getType().getBasicType() == EbtInt)
2255 {
2256 int intValue = operandArray[i].getIConst();
2257 value = static_cast<uint32_t>(intValue);
2258 if (intValue < 0)
2259 {
2260 // Look for zero instead of one in value. This also handles the intValue ==
2261 // -1 special case, where the return value needs to be -1.
2262 value = ~value;
2263 }
2264 }
2265 else
2266 {
2267 ASSERT(getType().getBasicType() == EbtUInt);
2268 value = operandArray[i].getUConst();
2269 }
2270 resultArray[i].setIConst(gl::FindMSB(value));
2271 break;
2272 }
Olli Etuahof119a262016-08-19 15:54:22 +03002273 case EOpDFdx:
2274 case EOpDFdy:
2275 case EOpFwidth:
2276 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole0c5409f2015-07-08 15:17:53 +05302277 // Derivatives of constant arguments should be 0.
2278 resultArray[i].setFConst(0.0f);
2279 break;
Arun Patole0c5409f2015-07-08 15:17:53 +05302280
Olli Etuahof119a262016-08-19 15:54:22 +03002281 default:
2282 return nullptr;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302283 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302284 }
Jamie Madillb1a85f42014-08-19 15:23:24 -04002285
Arun Patoleab2b9a22015-07-06 18:27:56 +05302286 return resultArray;
Jamie Madillb1a85f42014-08-19 15:23:24 -04002287}
2288
Olli Etuahof119a262016-08-19 15:54:22 +03002289void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter,
2290 FloatTypeUnaryFunc builtinFunc,
2291 TConstantUnion *result) const
Arun Patole9dea48f2015-04-02 11:45:09 +05302292{
2293 ASSERT(builtinFunc);
2294
Olli Etuahof119a262016-08-19 15:54:22 +03002295 ASSERT(getType().getBasicType() == EbtFloat);
2296 result->setFConst(builtinFunc(parameter.getFConst()));
Arun Patole9dea48f2015-04-02 11:45:09 +05302297}
2298
Jamie Madillb1a85f42014-08-19 15:23:24 -04002299// static
Olli Etuahof119a262016-08-19 15:54:22 +03002300TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate)
Olli Etuaho1d122782015-11-06 15:35:17 +02002301{
2302 ASSERT(aggregate->getSequence()->size() > 0u);
2303 size_t resultSize = aggregate->getType().getObjectSize();
2304 TConstantUnion *resultArray = new TConstantUnion[resultSize];
2305 TBasicType basicType = aggregate->getBasicType();
2306
2307 size_t resultIndex = 0u;
2308
2309 if (aggregate->getSequence()->size() == 1u)
2310 {
2311 TIntermNode *argument = aggregate->getSequence()->front();
2312 TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion();
2313 const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
2314 // Check the special case of constructing a matrix diagonal from a single scalar,
2315 // or a vector from a single scalar.
2316 if (argumentConstant->getType().getObjectSize() == 1u)
2317 {
2318 if (aggregate->isMatrix())
2319 {
2320 int resultCols = aggregate->getType().getCols();
2321 int resultRows = aggregate->getType().getRows();
2322 for (int col = 0; col < resultCols; ++col)
2323 {
2324 for (int row = 0; row < resultRows; ++row)
2325 {
2326 if (col == row)
2327 {
2328 resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
2329 }
2330 else
2331 {
2332 resultArray[resultIndex].setFConst(0.0f);
2333 }
2334 ++resultIndex;
2335 }
2336 }
2337 }
2338 else
2339 {
2340 while (resultIndex < resultSize)
2341 {
2342 resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
2343 ++resultIndex;
2344 }
2345 }
2346 ASSERT(resultIndex == resultSize);
2347 return resultArray;
2348 }
2349 else if (aggregate->isMatrix() && argumentConstant->isMatrix())
2350 {
2351 // The special case of constructing a matrix from a matrix.
2352 int argumentCols = argumentConstant->getType().getCols();
2353 int argumentRows = argumentConstant->getType().getRows();
2354 int resultCols = aggregate->getType().getCols();
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002355 int resultRows = aggregate->getType().getRows();
Olli Etuaho1d122782015-11-06 15:35:17 +02002356 for (int col = 0; col < resultCols; ++col)
2357 {
2358 for (int row = 0; row < resultRows; ++row)
2359 {
2360 if (col < argumentCols && row < argumentRows)
2361 {
2362 resultArray[resultIndex].cast(basicType,
2363 argumentUnionArray[col * argumentRows + row]);
2364 }
2365 else if (col == row)
2366 {
2367 resultArray[resultIndex].setFConst(1.0f);
2368 }
2369 else
2370 {
2371 resultArray[resultIndex].setFConst(0.0f);
2372 }
2373 ++resultIndex;
2374 }
2375 }
2376 ASSERT(resultIndex == resultSize);
2377 return resultArray;
2378 }
2379 }
2380
2381 for (TIntermNode *&argument : *aggregate->getSequence())
2382 {
2383 TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion();
2384 size_t argumentSize = argumentConstant->getType().getObjectSize();
2385 const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
2386 for (size_t i = 0u; i < argumentSize; ++i)
2387 {
2388 if (resultIndex >= resultSize)
2389 break;
2390 resultArray[resultIndex].cast(basicType, argumentUnionArray[i]);
2391 ++resultIndex;
2392 }
2393 }
2394 ASSERT(resultIndex == resultSize);
2395 return resultArray;
2396}
2397
2398// static
Olli Etuahof119a262016-08-19 15:54:22 +03002399TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate,
2400 TDiagnostics *diagnostics)
Arun Patole274f0702015-05-05 13:33:30 +05302401{
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002402 TOperator op = aggregate->getOp();
Arun Patole274f0702015-05-05 13:33:30 +05302403 TIntermSequence *sequence = aggregate->getSequence();
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002404 unsigned int paramsCount = static_cast<unsigned int>(sequence->size());
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002405 std::vector<const TConstantUnion *> unionArrays(paramsCount);
Arun Patole274f0702015-05-05 13:33:30 +05302406 std::vector<size_t> objectSizes(paramsCount);
Olli Etuahob43846e2015-06-02 18:18:57 +03002407 size_t maxObjectSize = 0;
Arun Patole274f0702015-05-05 13:33:30 +05302408 TBasicType basicType = EbtVoid;
2409 TSourceLoc loc;
2410 for (unsigned int i = 0; i < paramsCount; i++)
2411 {
2412 TIntermConstantUnion *paramConstant = (*sequence)[i]->getAsConstantUnion();
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002413 ASSERT(paramConstant != nullptr); // Should be checked already.
Arun Patole274f0702015-05-05 13:33:30 +05302414
2415 if (i == 0)
2416 {
2417 basicType = paramConstant->getType().getBasicType();
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002418 loc = paramConstant->getLine();
Arun Patole274f0702015-05-05 13:33:30 +05302419 }
2420 unionArrays[i] = paramConstant->getUnionArrayPointer();
2421 objectSizes[i] = paramConstant->getType().getObjectSize();
Olli Etuahob43846e2015-06-02 18:18:57 +03002422 if (objectSizes[i] > maxObjectSize)
2423 maxObjectSize = objectSizes[i];
Arun Patole274f0702015-05-05 13:33:30 +05302424 }
2425
Olli Etuahod5da5052016-08-29 13:16:55 +03002426 if (!(*sequence)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct)
Arun Patole7fa33552015-06-10 15:15:18 +05302427 {
2428 for (unsigned int i = 0; i < paramsCount; i++)
2429 if (objectSizes[i] != maxObjectSize)
2430 unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize);
2431 }
Arun Patole274f0702015-05-05 13:33:30 +05302432
Olli Etuahob43846e2015-06-02 18:18:57 +03002433 TConstantUnion *resultArray = nullptr;
Olli Etuaho51182ab2017-01-22 00:12:29 +00002434
2435 switch (op)
Arun Patole274f0702015-05-05 13:33:30 +05302436 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002437 case EOpAtan:
Arun Patole274f0702015-05-05 13:33:30 +05302438 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002439 ASSERT(basicType == EbtFloat);
2440 resultArray = new TConstantUnion[maxObjectSize];
2441 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302442 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002443 float y = unionArrays[0][i].getFConst();
2444 float x = unionArrays[1][i].getFConst();
2445 // Results are undefined if x and y are both 0.
2446 if (x == 0.0f && y == 0.0f)
2447 UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
2448 else
2449 resultArray[i].setFConst(atan2f(y, x));
Arun Patolebf790422015-05-18 17:53:04 +05302450 }
Olli Etuaho51182ab2017-01-22 00:12:29 +00002451 break;
2452 }
Arun Patolebf790422015-05-18 17:53:04 +05302453
Olli Etuaho51182ab2017-01-22 00:12:29 +00002454 case EOpPow:
2455 {
2456 ASSERT(basicType == EbtFloat);
2457 resultArray = new TConstantUnion[maxObjectSize];
2458 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302459 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002460 float x = unionArrays[0][i].getFConst();
2461 float y = unionArrays[1][i].getFConst();
2462 // Results are undefined if x < 0.
2463 // Results are undefined if x = 0 and y <= 0.
2464 if (x < 0.0f)
2465 UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
2466 else if (x == 0.0f && y <= 0.0f)
2467 UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
2468 else
2469 resultArray[i].setFConst(powf(x, y));
Arun Patolebf790422015-05-18 17:53:04 +05302470 }
Olli Etuaho51182ab2017-01-22 00:12:29 +00002471 break;
2472 }
Arun Patolebf790422015-05-18 17:53:04 +05302473
Olli Etuaho51182ab2017-01-22 00:12:29 +00002474 case EOpMod:
2475 {
2476 ASSERT(basicType == EbtFloat);
2477 resultArray = new TConstantUnion[maxObjectSize];
2478 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302479 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002480 float x = unionArrays[0][i].getFConst();
2481 float y = unionArrays[1][i].getFConst();
2482 resultArray[i].setFConst(x - y * floorf(x / y));
Arun Patolebf790422015-05-18 17:53:04 +05302483 }
Olli Etuaho51182ab2017-01-22 00:12:29 +00002484 break;
2485 }
Arun Patolebf790422015-05-18 17:53:04 +05302486
Olli Etuaho51182ab2017-01-22 00:12:29 +00002487 case EOpMin:
2488 {
2489 resultArray = new TConstantUnion[maxObjectSize];
2490 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patole274f0702015-05-05 13:33:30 +05302491 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002492 switch (basicType)
Arun Patole274f0702015-05-05 13:33:30 +05302493 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002494 case EbtFloat:
2495 resultArray[i].setFConst(
2496 std::min(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
2497 break;
2498 case EbtInt:
2499 resultArray[i].setIConst(
2500 std::min(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
2501 break;
2502 case EbtUInt:
2503 resultArray[i].setUConst(
2504 std::min(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
2505 break;
2506 default:
2507 UNREACHABLE();
2508 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302509 }
2510 }
2511 break;
Arun Patole274f0702015-05-05 13:33:30 +05302512 }
Olli Etuaho51182ab2017-01-22 00:12:29 +00002513
2514 case EOpMax:
Arun Patole274f0702015-05-05 13:33:30 +05302515 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002516 resultArray = new TConstantUnion[maxObjectSize];
2517 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patole274f0702015-05-05 13:33:30 +05302518 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002519 switch (basicType)
Arun Patole274f0702015-05-05 13:33:30 +05302520 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002521 case EbtFloat:
2522 resultArray[i].setFConst(
2523 std::max(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
2524 break;
2525 case EbtInt:
2526 resultArray[i].setIConst(
2527 std::max(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
2528 break;
2529 case EbtUInt:
2530 resultArray[i].setUConst(
2531 std::max(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
2532 break;
2533 default:
2534 UNREACHABLE();
2535 break;
Arun Patole274f0702015-05-05 13:33:30 +05302536 }
2537 }
Olli Etuaho51182ab2017-01-22 00:12:29 +00002538 break;
Arun Patole274f0702015-05-05 13:33:30 +05302539 }
Olli Etuaho51182ab2017-01-22 00:12:29 +00002540
2541 case EOpStep:
2542 {
2543 ASSERT(basicType == EbtFloat);
2544 resultArray = new TConstantUnion[maxObjectSize];
2545 for (size_t i = 0; i < maxObjectSize; i++)
2546 resultArray[i].setFConst(
2547 unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f : 1.0f);
2548 break;
2549 }
2550
2551 case EOpLessThanComponentWise:
2552 {
2553 resultArray = new TConstantUnion[maxObjectSize];
2554 for (size_t i = 0; i < maxObjectSize; i++)
2555 {
2556 switch (basicType)
2557 {
2558 case EbtFloat:
2559 resultArray[i].setBConst(unionArrays[0][i].getFConst() <
2560 unionArrays[1][i].getFConst());
2561 break;
2562 case EbtInt:
2563 resultArray[i].setBConst(unionArrays[0][i].getIConst() <
2564 unionArrays[1][i].getIConst());
2565 break;
2566 case EbtUInt:
2567 resultArray[i].setBConst(unionArrays[0][i].getUConst() <
2568 unionArrays[1][i].getUConst());
2569 break;
2570 default:
2571 UNREACHABLE();
2572 break;
2573 }
2574 }
2575 break;
2576 }
2577
2578 case EOpLessThanEqualComponentWise:
2579 {
2580 resultArray = new TConstantUnion[maxObjectSize];
2581 for (size_t i = 0; i < maxObjectSize; i++)
2582 {
2583 switch (basicType)
2584 {
2585 case EbtFloat:
2586 resultArray[i].setBConst(unionArrays[0][i].getFConst() <=
2587 unionArrays[1][i].getFConst());
2588 break;
2589 case EbtInt:
2590 resultArray[i].setBConst(unionArrays[0][i].getIConst() <=
2591 unionArrays[1][i].getIConst());
2592 break;
2593 case EbtUInt:
2594 resultArray[i].setBConst(unionArrays[0][i].getUConst() <=
2595 unionArrays[1][i].getUConst());
2596 break;
2597 default:
2598 UNREACHABLE();
2599 break;
2600 }
2601 }
2602 break;
2603 }
2604
2605 case EOpGreaterThanComponentWise:
2606 {
2607 resultArray = new TConstantUnion[maxObjectSize];
2608 for (size_t i = 0; i < maxObjectSize; i++)
2609 {
2610 switch (basicType)
2611 {
2612 case EbtFloat:
2613 resultArray[i].setBConst(unionArrays[0][i].getFConst() >
2614 unionArrays[1][i].getFConst());
2615 break;
2616 case EbtInt:
2617 resultArray[i].setBConst(unionArrays[0][i].getIConst() >
2618 unionArrays[1][i].getIConst());
2619 break;
2620 case EbtUInt:
2621 resultArray[i].setBConst(unionArrays[0][i].getUConst() >
2622 unionArrays[1][i].getUConst());
2623 break;
2624 default:
2625 UNREACHABLE();
2626 break;
2627 }
2628 }
2629 break;
2630 }
2631 case EOpGreaterThanEqualComponentWise:
2632 {
2633 resultArray = new TConstantUnion[maxObjectSize];
2634 for (size_t i = 0; i < maxObjectSize; i++)
2635 {
2636 switch (basicType)
2637 {
2638 case EbtFloat:
2639 resultArray[i].setBConst(unionArrays[0][i].getFConst() >=
2640 unionArrays[1][i].getFConst());
2641 break;
2642 case EbtInt:
2643 resultArray[i].setBConst(unionArrays[0][i].getIConst() >=
2644 unionArrays[1][i].getIConst());
2645 break;
2646 case EbtUInt:
2647 resultArray[i].setBConst(unionArrays[0][i].getUConst() >=
2648 unionArrays[1][i].getUConst());
2649 break;
2650 default:
2651 UNREACHABLE();
2652 break;
2653 }
2654 }
2655 }
2656 break;
2657
2658 case EOpEqualComponentWise:
2659 {
2660 resultArray = new TConstantUnion[maxObjectSize];
2661 for (size_t i = 0; i < maxObjectSize; i++)
2662 {
2663 switch (basicType)
2664 {
2665 case EbtFloat:
2666 resultArray[i].setBConst(unionArrays[0][i].getFConst() ==
2667 unionArrays[1][i].getFConst());
2668 break;
2669 case EbtInt:
2670 resultArray[i].setBConst(unionArrays[0][i].getIConst() ==
2671 unionArrays[1][i].getIConst());
2672 break;
2673 case EbtUInt:
2674 resultArray[i].setBConst(unionArrays[0][i].getUConst() ==
2675 unionArrays[1][i].getUConst());
2676 break;
2677 case EbtBool:
2678 resultArray[i].setBConst(unionArrays[0][i].getBConst() ==
2679 unionArrays[1][i].getBConst());
2680 break;
2681 default:
2682 UNREACHABLE();
2683 break;
2684 }
2685 }
2686 break;
2687 }
2688
2689 case EOpNotEqualComponentWise:
2690 {
2691 resultArray = new TConstantUnion[maxObjectSize];
2692 for (size_t i = 0; i < maxObjectSize; i++)
2693 {
2694 switch (basicType)
2695 {
2696 case EbtFloat:
2697 resultArray[i].setBConst(unionArrays[0][i].getFConst() !=
2698 unionArrays[1][i].getFConst());
2699 break;
2700 case EbtInt:
2701 resultArray[i].setBConst(unionArrays[0][i].getIConst() !=
2702 unionArrays[1][i].getIConst());
2703 break;
2704 case EbtUInt:
2705 resultArray[i].setBConst(unionArrays[0][i].getUConst() !=
2706 unionArrays[1][i].getUConst());
2707 break;
2708 case EbtBool:
2709 resultArray[i].setBConst(unionArrays[0][i].getBConst() !=
2710 unionArrays[1][i].getBConst());
2711 break;
2712 default:
2713 UNREACHABLE();
2714 break;
2715 }
2716 }
2717 break;
2718 }
2719
2720 case EOpDistance:
2721 {
2722 ASSERT(basicType == EbtFloat);
2723 TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize];
2724 resultArray = new TConstantUnion();
2725 for (size_t i = 0; i < maxObjectSize; i++)
2726 {
2727 float x = unionArrays[0][i].getFConst();
2728 float y = unionArrays[1][i].getFConst();
2729 distanceArray[i].setFConst(x - y);
2730 }
2731 resultArray->setFConst(VectorLength(distanceArray, maxObjectSize));
2732 break;
2733 }
2734
2735 case EOpDot:
2736 ASSERT(basicType == EbtFloat);
2737 resultArray = new TConstantUnion();
2738 resultArray->setFConst(VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize));
2739 break;
2740
2741 case EOpCross:
2742 {
2743 ASSERT(basicType == EbtFloat && maxObjectSize == 3);
2744 resultArray = new TConstantUnion[maxObjectSize];
2745 float x0 = unionArrays[0][0].getFConst();
2746 float x1 = unionArrays[0][1].getFConst();
2747 float x2 = unionArrays[0][2].getFConst();
2748 float y0 = unionArrays[1][0].getFConst();
2749 float y1 = unionArrays[1][1].getFConst();
2750 float y2 = unionArrays[1][2].getFConst();
2751 resultArray[0].setFConst(x1 * y2 - y1 * x2);
2752 resultArray[1].setFConst(x2 * y0 - y2 * x0);
2753 resultArray[2].setFConst(x0 * y1 - y0 * x1);
2754 break;
2755 }
2756
2757 case EOpReflect:
2758 {
2759 ASSERT(basicType == EbtFloat);
2760 // genType reflect (genType I, genType N) :
2761 // For the incident vector I and surface orientation N, returns the reflection
2762 // direction:
2763 // I - 2 * dot(N, I) * N.
2764 resultArray = new TConstantUnion[maxObjectSize];
2765 float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
2766 for (size_t i = 0; i < maxObjectSize; i++)
2767 {
2768 float result = unionArrays[0][i].getFConst() -
2769 2.0f * dotProduct * unionArrays[1][i].getFConst();
2770 resultArray[i].setFConst(result);
2771 }
2772 break;
2773 }
2774
2775 case EOpMulMatrixComponentWise:
2776 {
2777 ASSERT(basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() &&
2778 (*sequence)[1]->getAsTyped()->isMatrix());
2779 // Perform component-wise matrix multiplication.
2780 resultArray = new TConstantUnion[maxObjectSize];
2781 int size = (*sequence)[0]->getAsTyped()->getNominalSize();
2782 angle::Matrix<float> result =
2783 GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size));
2784 SetUnionArrayFromMatrix(result, resultArray);
2785 break;
2786 }
2787
2788 case EOpOuterProduct:
2789 {
2790 ASSERT(basicType == EbtFloat);
2791 size_t numRows = (*sequence)[0]->getAsTyped()->getType().getObjectSize();
2792 size_t numCols = (*sequence)[1]->getAsTyped()->getType().getObjectSize();
2793 resultArray = new TConstantUnion[numRows * numCols];
2794 angle::Matrix<float> result =
2795 GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
2796 .outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols)));
2797 SetUnionArrayFromMatrix(result, resultArray);
2798 break;
2799 }
2800
2801 case EOpClamp:
2802 {
2803 resultArray = new TConstantUnion[maxObjectSize];
2804 for (size_t i = 0; i < maxObjectSize; i++)
2805 {
2806 switch (basicType)
2807 {
2808 case EbtFloat:
2809 {
2810 float x = unionArrays[0][i].getFConst();
2811 float min = unionArrays[1][i].getFConst();
2812 float max = unionArrays[2][i].getFConst();
2813 // Results are undefined if min > max.
2814 if (min > max)
2815 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2816 &resultArray[i]);
2817 else
2818 resultArray[i].setFConst(gl::clamp(x, min, max));
2819 break;
2820 }
2821
2822 case EbtInt:
2823 {
2824 int x = unionArrays[0][i].getIConst();
2825 int min = unionArrays[1][i].getIConst();
2826 int max = unionArrays[2][i].getIConst();
2827 // Results are undefined if min > max.
2828 if (min > max)
2829 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2830 &resultArray[i]);
2831 else
2832 resultArray[i].setIConst(gl::clamp(x, min, max));
2833 break;
2834 }
2835 case EbtUInt:
2836 {
2837 unsigned int x = unionArrays[0][i].getUConst();
2838 unsigned int min = unionArrays[1][i].getUConst();
2839 unsigned int max = unionArrays[2][i].getUConst();
2840 // Results are undefined if min > max.
2841 if (min > max)
2842 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2843 &resultArray[i]);
2844 else
2845 resultArray[i].setUConst(gl::clamp(x, min, max));
2846 break;
2847 }
2848 default:
2849 UNREACHABLE();
2850 break;
2851 }
2852 }
2853 break;
2854 }
2855
2856 case EOpMix:
2857 {
2858 ASSERT(basicType == EbtFloat);
2859 resultArray = new TConstantUnion[maxObjectSize];
2860 for (size_t i = 0; i < maxObjectSize; i++)
2861 {
2862 float x = unionArrays[0][i].getFConst();
2863 float y = unionArrays[1][i].getFConst();
2864 TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType();
2865 if (type == EbtFloat)
2866 {
2867 // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
2868 float a = unionArrays[2][i].getFConst();
2869 resultArray[i].setFConst(x * (1.0f - a) + y * a);
2870 }
2871 else // 3rd parameter is EbtBool
2872 {
2873 ASSERT(type == EbtBool);
2874 // Selects which vector each returned component comes from.
2875 // For a component of a that is false, the corresponding component of x is
2876 // returned.
2877 // For a component of a that is true, the corresponding component of y is
2878 // returned.
2879 bool a = unionArrays[2][i].getBConst();
2880 resultArray[i].setFConst(a ? y : x);
2881 }
2882 }
2883 break;
2884 }
2885
2886 case EOpSmoothStep:
2887 {
2888 ASSERT(basicType == EbtFloat);
2889 resultArray = new TConstantUnion[maxObjectSize];
2890 for (size_t i = 0; i < maxObjectSize; i++)
2891 {
2892 float edge0 = unionArrays[0][i].getFConst();
2893 float edge1 = unionArrays[1][i].getFConst();
2894 float x = unionArrays[2][i].getFConst();
2895 // Results are undefined if edge0 >= edge1.
2896 if (edge0 >= edge1)
2897 {
2898 UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
2899 }
2900 else
2901 {
2902 // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth
2903 // Hermite interpolation between 0 and 1 when edge0 < x < edge1.
2904 float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
2905 resultArray[i].setFConst(t * t * (3.0f - 2.0f * t));
2906 }
2907 }
2908 break;
2909 }
2910
2911 case EOpFaceForward:
2912 {
2913 ASSERT(basicType == EbtFloat);
2914 // genType faceforward(genType N, genType I, genType Nref) :
2915 // If dot(Nref, I) < 0 return N, otherwise return -N.
2916 resultArray = new TConstantUnion[maxObjectSize];
2917 float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize);
2918 for (size_t i = 0; i < maxObjectSize; i++)
2919 {
2920 if (dotProduct < 0)
2921 resultArray[i].setFConst(unionArrays[0][i].getFConst());
2922 else
2923 resultArray[i].setFConst(-unionArrays[0][i].getFConst());
2924 }
2925 break;
2926 }
2927
2928 case EOpRefract:
2929 {
2930 ASSERT(basicType == EbtFloat);
2931 // genType refract(genType I, genType N, float eta) :
2932 // For the incident vector I and surface normal N, and the ratio of indices of
2933 // refraction eta,
2934 // return the refraction vector. The result is computed by
2935 // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
2936 // if (k < 0.0)
2937 // return genType(0.0)
2938 // else
2939 // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
2940 resultArray = new TConstantUnion[maxObjectSize];
2941 float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
2942 for (size_t i = 0; i < maxObjectSize; i++)
2943 {
2944 float eta = unionArrays[2][i].getFConst();
2945 float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct);
2946 if (k < 0.0f)
2947 resultArray[i].setFConst(0.0f);
2948 else
2949 resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() -
2950 (eta * dotProduct + sqrtf(k)) *
2951 unionArrays[1][i].getFConst());
2952 }
2953 break;
2954 }
Olli Etuaho9250cb22017-01-21 10:51:27 +00002955 case EOpBitfieldExtract:
2956 {
2957 resultArray = new TConstantUnion[maxObjectSize];
2958 for (size_t i = 0; i < maxObjectSize; ++i)
2959 {
2960 int offset = unionArrays[1][0].getIConst();
2961 int bits = unionArrays[2][0].getIConst();
2962 if (bits == 0)
2963 {
2964 if (aggregate->getBasicType() == EbtInt)
2965 {
2966 resultArray[i].setIConst(0);
2967 }
2968 else
2969 {
2970 ASSERT(aggregate->getBasicType() == EbtUInt);
2971 resultArray[i].setUConst(0);
2972 }
2973 }
2974 else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32)
2975 {
2976 UndefinedConstantFoldingError(loc, op, aggregate->getBasicType(), diagnostics,
2977 &resultArray[i]);
2978 }
2979 else
2980 {
2981 // bits can be 32 here, so we need to avoid bit shift overflow.
2982 uint32_t maskMsb = 1u << (bits - 1);
2983 uint32_t mask = ((maskMsb - 1u) | maskMsb) << offset;
2984 if (aggregate->getBasicType() == EbtInt)
2985 {
2986 uint32_t value = static_cast<uint32_t>(unionArrays[0][i].getIConst());
2987 uint32_t resultUnsigned = (value & mask) >> offset;
2988 if ((resultUnsigned & maskMsb) != 0)
2989 {
2990 // The most significant bits (from bits+1 to the most significant bit)
2991 // should be set to 1.
2992 uint32_t higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;
2993 resultUnsigned |= higherBitsMask;
2994 }
2995 resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned));
2996 }
2997 else
2998 {
2999 ASSERT(aggregate->getBasicType() == EbtUInt);
3000 uint32_t value = unionArrays[0][i].getUConst();
3001 resultArray[i].setUConst((value & mask) >> offset);
3002 }
3003 }
3004 }
3005 break;
3006 }
3007 case EOpBitfieldInsert:
3008 {
3009 resultArray = new TConstantUnion[maxObjectSize];
3010 for (size_t i = 0; i < maxObjectSize; ++i)
3011 {
3012 int offset = unionArrays[2][0].getIConst();
3013 int bits = unionArrays[3][0].getIConst();
3014 if (bits == 0)
3015 {
3016 if (aggregate->getBasicType() == EbtInt)
3017 {
3018 int32_t base = unionArrays[0][i].getIConst();
3019 resultArray[i].setIConst(base);
3020 }
3021 else
3022 {
3023 ASSERT(aggregate->getBasicType() == EbtUInt);
3024 uint32_t base = unionArrays[0][i].getUConst();
3025 resultArray[i].setUConst(base);
3026 }
3027 }
3028 else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32)
3029 {
3030 UndefinedConstantFoldingError(loc, op, aggregate->getBasicType(), diagnostics,
3031 &resultArray[i]);
3032 }
3033 else
3034 {
3035 // bits can be 32 here, so we need to avoid bit shift overflow.
3036 uint32_t maskMsb = 1u << (bits - 1);
3037 uint32_t insertMask = ((maskMsb - 1u) | maskMsb) << offset;
3038 uint32_t baseMask = ~insertMask;
3039 if (aggregate->getBasicType() == EbtInt)
3040 {
3041 uint32_t base = static_cast<uint32_t>(unionArrays[0][i].getIConst());
3042 uint32_t insert = static_cast<uint32_t>(unionArrays[1][i].getIConst());
3043 uint32_t resultUnsigned =
3044 (base & baseMask) | ((insert << offset) & insertMask);
3045 resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned));
3046 }
3047 else
3048 {
3049 ASSERT(aggregate->getBasicType() == EbtUInt);
3050 uint32_t base = unionArrays[0][i].getUConst();
3051 uint32_t insert = unionArrays[1][i].getUConst();
3052 resultArray[i].setUConst((base & baseMask) |
3053 ((insert << offset) & insertMask));
3054 }
3055 }
3056 }
3057 break;
3058 }
Olli Etuaho51182ab2017-01-22 00:12:29 +00003059
3060 default:
3061 UNREACHABLE();
3062 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +05303063 }
Olli Etuahob43846e2015-06-02 18:18:57 +03003064 return resultArray;
Arun Patole274f0702015-05-05 13:33:30 +05303065}
3066
3067// static
Jamie Madillb1a85f42014-08-19 15:23:24 -04003068TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction)
3069{
3070 if (hashFunction == NULL || name.empty())
3071 return name;
3072 khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
3073 TStringStream stream;
3074 stream << HASHED_NAME_PREFIX << std::hex << number;
3075 TString hashedName = stream.str();
3076 return hashedName;
3077}
Olli Etuaho853dc1a2014-11-06 17:25:48 +02003078
3079void TIntermTraverser::updateTree()
3080{
Olli Etuahoa6f22092015-05-08 18:31:10 +03003081 for (size_t ii = 0; ii < mInsertions.size(); ++ii)
3082 {
3083 const NodeInsertMultipleEntry &insertion = mInsertions[ii];
3084 ASSERT(insertion.parent);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03003085 if (!insertion.insertionsAfter.empty())
3086 {
3087 bool inserted = insertion.parent->insertChildNodes(insertion.position + 1,
3088 insertion.insertionsAfter);
3089 ASSERT(inserted);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03003090 }
3091 if (!insertion.insertionsBefore.empty())
3092 {
3093 bool inserted =
3094 insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore);
3095 ASSERT(inserted);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03003096 }
Olli Etuahoa6f22092015-05-08 18:31:10 +03003097 }
Olli Etuaho853dc1a2014-11-06 17:25:48 +02003098 for (size_t ii = 0; ii < mReplacements.size(); ++ii)
3099 {
Olli Etuahocd94ef92015-04-16 19:18:10 +03003100 const NodeUpdateEntry &replacement = mReplacements[ii];
3101 ASSERT(replacement.parent);
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003102 bool replaced =
3103 replacement.parent->replaceChildNode(replacement.original, replacement.replacement);
Olli Etuaho853dc1a2014-11-06 17:25:48 +02003104 ASSERT(replaced);
3105
Olli Etuahocd94ef92015-04-16 19:18:10 +03003106 if (!replacement.originalBecomesChildOfReplacement)
Olli Etuaho853dc1a2014-11-06 17:25:48 +02003107 {
3108 // In AST traversing, a parent is visited before its children.
Olli Etuahocd94ef92015-04-16 19:18:10 +03003109 // After we replace a node, if its immediate child is to
Olli Etuaho853dc1a2014-11-06 17:25:48 +02003110 // be replaced, we need to make sure we don't update the replaced
3111 // node; instead, we update the replacement node.
3112 for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj)
3113 {
Olli Etuahocd94ef92015-04-16 19:18:10 +03003114 NodeUpdateEntry &replacement2 = mReplacements[jj];
3115 if (replacement2.parent == replacement.original)
3116 replacement2.parent = replacement.replacement;
Olli Etuaho853dc1a2014-11-06 17:25:48 +02003117 }
3118 }
3119 }
Olli Etuahofc0e2bc2015-04-16 13:39:56 +03003120 for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii)
3121 {
3122 const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii];
3123 ASSERT(replacement.parent);
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003124 bool replaced = replacement.parent->replaceChildNodeWithMultiple(replacement.original,
3125 replacement.replacements);
Olli Etuahofc0e2bc2015-04-16 13:39:56 +03003126 ASSERT(replaced);
3127 }
Olli Etuahod4f303e2015-05-20 17:09:06 +03003128
Jamie Madill03d863c2016-07-27 18:15:53 -04003129 clearReplacementQueue();
3130}
3131
3132void TIntermTraverser::clearReplacementQueue()
3133{
Olli Etuahod4f303e2015-05-20 17:09:06 +03003134 mReplacements.clear();
3135 mMultiReplacements.clear();
Jamie Madill03d863c2016-07-27 18:15:53 -04003136 mInsertions.clear();
Olli Etuaho853dc1a2014-11-06 17:25:48 +02003137}
Jamie Madill1048e432016-07-23 18:51:28 -04003138
Jamie Madill03d863c2016-07-27 18:15:53 -04003139void TIntermTraverser::queueReplacement(TIntermNode *original,
3140 TIntermNode *replacement,
3141 OriginalNode originalStatus)
Jamie Madill1048e432016-07-23 18:51:28 -04003142{
Jamie Madill03d863c2016-07-27 18:15:53 -04003143 queueReplacementWithParent(getParentNode(), original, replacement, originalStatus);
Jamie Madill1048e432016-07-23 18:51:28 -04003144}
3145
Jamie Madill03d863c2016-07-27 18:15:53 -04003146void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent,
3147 TIntermNode *original,
3148 TIntermNode *replacement,
3149 OriginalNode originalStatus)
Jamie Madill1048e432016-07-23 18:51:28 -04003150{
Jamie Madill03d863c2016-07-27 18:15:53 -04003151 bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD);
3152 mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild));
Jamie Madill1048e432016-07-23 18:51:28 -04003153}
Jamie Madill45bcc782016-11-07 13:58:48 -05003154
3155} // namespace sh