blob: 2c85e4f3ec78a697f4658edb6fbf7072aaff058e [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:
Corentin Wallez17a5c062017-01-22 15:20:53 -0500486 // CreateZero is called by ParseContext that keeps parsing even when an error
487 // occurs, so it is possible for CreateZero to be called with non-basic types.
488 // This happens only on error condition but CreateZero needs to return a value
489 // with the correct type to continue the typecheck. That's why we handle
490 // non-basic type by setting whatever value, we just need the type to be right.
491 u[i].setIConst(42);
492 break;
Corentin Wallez509e4562016-08-25 14:55:44 -0400493 }
494 }
495
496 TIntermConstantUnion *node = new TIntermConstantUnion(u, constType);
497 return node;
498 }
499
500 TIntermAggregate *constructor = new TIntermAggregate(sh::TypeToConstructorOperator(type));
501 constructor->setType(constType);
502
503 if (type.isArray())
504 {
505 TType elementType(type);
506 elementType.clearArrayness();
507
508 size_t arraySize = type.getArraySize();
509 for (size_t i = 0; i < arraySize; ++i)
510 {
511 constructor->getSequence()->push_back(CreateZero(elementType));
512 }
513 }
514 else
515 {
516 ASSERT(type.getBasicType() == EbtStruct);
517
518 TStructure *structure = type.getStruct();
519 for (const auto &field : structure->fields())
520 {
521 constructor->getSequence()->push_back(CreateZero(*field->type()));
522 }
523 }
524
525 return constructor;
526}
527
Corentin Wallez36fd1002016-12-08 11:30:44 -0500528// static
529TIntermTyped *TIntermTyped::CreateBool(bool value)
530{
531 TConstantUnion *u = new TConstantUnion[1];
532 u[0].setBConst(value);
533
534 TType type(EbtBool, EbpUndefined, EvqConst, 1);
535 TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
536 return node;
537}
538
Olli Etuahod7a25242015-08-18 13:49:45 +0300539TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) : TIntermTyped(node)
540{
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200541 mUnionArrayPointer = node.mUnionArrayPointer;
Olli Etuahod7a25242015-08-18 13:49:45 +0300542}
543
Olli Etuahobd674552016-10-06 13:28:42 +0100544void TFunctionSymbolInfo::setFromFunction(const TFunction &function)
545{
546 setName(function.getMangledName());
547 setId(function.getUniqueId());
548}
549
Olli Etuahod7a25242015-08-18 13:49:45 +0300550TIntermAggregate::TIntermAggregate(const TIntermAggregate &node)
551 : TIntermOperator(node),
Olli Etuahod7a25242015-08-18 13:49:45 +0300552 mUserDefined(node.mUserDefined),
Olli Etuahod7a25242015-08-18 13:49:45 +0300553 mUseEmulatedFunction(node.mUseEmulatedFunction),
Olli Etuahobd674552016-10-06 13:28:42 +0100554 mGotPrecisionFromChildren(node.mGotPrecisionFromChildren),
555 mFunctionInfo(node.mFunctionInfo)
Olli Etuahod7a25242015-08-18 13:49:45 +0300556{
557 for (TIntermNode *child : node.mSequence)
558 {
559 TIntermTyped *typedChild = child->getAsTyped();
560 ASSERT(typedChild != nullptr);
561 TIntermTyped *childCopy = typedChild->deepCopy();
562 mSequence.push_back(childCopy);
563 }
564}
565
Olli Etuahob6fa0432016-09-28 16:28:05 +0100566TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermTyped(node)
567{
568 TIntermTyped *operandCopy = node.mOperand->deepCopy();
569 ASSERT(operandCopy != nullptr);
570 mOperand = operandCopy;
571}
572
Olli Etuahod7a25242015-08-18 13:49:45 +0300573TIntermBinary::TIntermBinary(const TIntermBinary &node)
574 : TIntermOperator(node), mAddIndexClamp(node.mAddIndexClamp)
575{
576 TIntermTyped *leftCopy = node.mLeft->deepCopy();
577 TIntermTyped *rightCopy = node.mRight->deepCopy();
578 ASSERT(leftCopy != nullptr && rightCopy != nullptr);
579 mLeft = leftCopy;
580 mRight = rightCopy;
581}
582
583TIntermUnary::TIntermUnary(const TIntermUnary &node)
584 : TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction)
585{
586 TIntermTyped *operandCopy = node.mOperand->deepCopy();
587 ASSERT(operandCopy != nullptr);
588 mOperand = operandCopy;
589}
590
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300591TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermTyped(node)
Olli Etuahod7a25242015-08-18 13:49:45 +0300592{
Olli Etuahod7a25242015-08-18 13:49:45 +0300593 TIntermTyped *conditionCopy = node.mCondition->deepCopy();
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300594 TIntermTyped *trueCopy = node.mTrueExpression->deepCopy();
595 TIntermTyped *falseCopy = node.mFalseExpression->deepCopy();
Olli Etuahod7a25242015-08-18 13:49:45 +0300596 ASSERT(conditionCopy != nullptr && trueCopy != nullptr && falseCopy != nullptr);
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300597 mCondition = conditionCopy;
598 mTrueExpression = trueCopy;
599 mFalseExpression = falseCopy;
Olli Etuahod7a25242015-08-18 13:49:45 +0300600}
601
Jamie Madillb1a85f42014-08-19 15:23:24 -0400602bool TIntermOperator::isAssignment() const
603{
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300604 return IsAssignment(mOp);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400605}
606
Olli Etuaho8f76bcc2015-06-02 13:54:20 +0300607bool TIntermOperator::isMultiplication() const
608{
609 switch (mOp)
610 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500611 case EOpMul:
612 case EOpMatrixTimesMatrix:
613 case EOpMatrixTimesVector:
614 case EOpMatrixTimesScalar:
615 case EOpVectorTimesMatrix:
616 case EOpVectorTimesScalar:
617 return true;
618 default:
619 return false;
Olli Etuaho8f76bcc2015-06-02 13:54:20 +0300620 }
621}
622
Jamie Madillb1a85f42014-08-19 15:23:24 -0400623//
624// returns true if the operator is for one of the constructors
625//
626bool TIntermOperator::isConstructor() const
627{
628 switch (mOp)
629 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500630 case EOpConstructVec2:
631 case EOpConstructVec3:
632 case EOpConstructVec4:
633 case EOpConstructMat2:
634 case EOpConstructMat2x3:
635 case EOpConstructMat2x4:
636 case EOpConstructMat3x2:
637 case EOpConstructMat3:
638 case EOpConstructMat3x4:
639 case EOpConstructMat4x2:
640 case EOpConstructMat4x3:
641 case EOpConstructMat4:
642 case EOpConstructFloat:
643 case EOpConstructIVec2:
644 case EOpConstructIVec3:
645 case EOpConstructIVec4:
646 case EOpConstructInt:
647 case EOpConstructUVec2:
648 case EOpConstructUVec3:
649 case EOpConstructUVec4:
650 case EOpConstructUInt:
651 case EOpConstructBVec2:
652 case EOpConstructBVec3:
653 case EOpConstructBVec4:
654 case EOpConstructBool:
655 case EOpConstructStruct:
656 return true;
657 default:
658 return false;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400659 }
660}
661
Olli Etuaho1dded802016-08-18 18:13:13 +0300662TOperator TIntermBinary::GetMulOpBasedOnOperands(const TType &left, const TType &right)
663{
664 if (left.isMatrix())
665 {
666 if (right.isMatrix())
667 {
668 return EOpMatrixTimesMatrix;
669 }
670 else
671 {
672 if (right.isVector())
673 {
674 return EOpMatrixTimesVector;
675 }
676 else
677 {
678 return EOpMatrixTimesScalar;
679 }
680 }
681 }
682 else
683 {
684 if (right.isMatrix())
685 {
686 if (left.isVector())
687 {
688 return EOpVectorTimesMatrix;
689 }
690 else
691 {
692 return EOpMatrixTimesScalar;
693 }
694 }
695 else
696 {
697 // Neither operand is a matrix.
698 if (left.isVector() == right.isVector())
699 {
700 // Leave as component product.
701 return EOpMul;
702 }
703 else
704 {
705 return EOpVectorTimesScalar;
706 }
707 }
708 }
709}
710
711TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const TType &right)
712{
713 if (left.isMatrix())
714 {
715 if (right.isMatrix())
716 {
717 return EOpMatrixTimesMatrixAssign;
718 }
719 else
720 {
721 // right should be scalar, but this may not be validated yet.
722 return EOpMatrixTimesScalarAssign;
723 }
724 }
725 else
726 {
727 if (right.isMatrix())
728 {
729 // Left should be a vector, but this may not be validated yet.
730 return EOpVectorTimesMatrixAssign;
731 }
732 else
733 {
734 // Neither operand is a matrix.
735 if (left.isVector() == right.isVector())
736 {
737 // Leave as component product.
738 return EOpMulAssign;
739 }
740 else
741 {
742 // left should be vector and right should be scalar, but this may not be validated
743 // yet.
744 return EOpVectorTimesScalarAssign;
745 }
746 }
747 }
748}
749
Jamie Madillb1a85f42014-08-19 15:23:24 -0400750//
751// Make sure the type of a unary operator is appropriate for its
752// combination of operation and operand type.
753//
Olli Etuahoa2234302016-08-31 12:05:39 +0300754void TIntermUnary::promote()
Jamie Madillb1a85f42014-08-19 15:23:24 -0400755{
Olli Etuahoa2234302016-08-31 12:05:39 +0300756 TQualifier resultQualifier = EvqTemporary;
757 if (mOperand->getQualifier() == EvqConst)
758 resultQualifier = EvqConst;
759
760 unsigned char operandPrimarySize =
761 static_cast<unsigned char>(mOperand->getType().getNominalSize());
Jamie Madillb1a85f42014-08-19 15:23:24 -0400762 switch (mOp)
763 {
Olli Etuahoa2234302016-08-31 12:05:39 +0300764 case EOpFloatBitsToInt:
765 setType(TType(EbtInt, EbpHigh, resultQualifier, operandPrimarySize));
766 break;
767 case EOpFloatBitsToUint:
768 setType(TType(EbtUInt, EbpHigh, resultQualifier, operandPrimarySize));
769 break;
770 case EOpIntBitsToFloat:
771 case EOpUintBitsToFloat:
772 setType(TType(EbtFloat, EbpHigh, resultQualifier, operandPrimarySize));
773 break;
774 case EOpPackSnorm2x16:
775 case EOpPackUnorm2x16:
776 case EOpPackHalf2x16:
777 setType(TType(EbtUInt, EbpHigh, resultQualifier));
778 break;
779 case EOpUnpackSnorm2x16:
780 case EOpUnpackUnorm2x16:
781 setType(TType(EbtFloat, EbpHigh, resultQualifier, 2));
782 break;
783 case EOpUnpackHalf2x16:
784 setType(TType(EbtFloat, EbpMedium, resultQualifier, 2));
785 break;
786 case EOpAny:
787 case EOpAll:
788 setType(TType(EbtBool, EbpUndefined, resultQualifier));
789 break;
790 case EOpLength:
791 case EOpDeterminant:
792 setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier));
793 break;
794 case EOpTranspose:
795 setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier,
796 static_cast<unsigned char>(mOperand->getType().getRows()),
797 static_cast<unsigned char>(mOperand->getType().getCols())));
798 break;
799 case EOpIsInf:
800 case EOpIsNan:
801 setType(TType(EbtBool, EbpUndefined, resultQualifier, operandPrimarySize));
802 break;
Olli Etuaho9250cb22017-01-21 10:51:27 +0000803 case EOpBitfieldReverse:
804 setType(TType(mOperand->getBasicType(), EbpHigh, resultQualifier, operandPrimarySize));
805 break;
806 case EOpBitCount:
807 setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
808 break;
809 case EOpFindLSB:
810 setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
811 break;
812 case EOpFindMSB:
813 setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
814 break;
Olli Etuahoa2234302016-08-31 12:05:39 +0300815 default:
816 setType(mOperand->getType());
817 mType.setQualifier(resultQualifier);
818 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400819 }
Olli Etuahoa2234302016-08-31 12:05:39 +0300820}
Jamie Madillb1a85f42014-08-19 15:23:24 -0400821
Olli Etuahob6fa0432016-09-28 16:28:05 +0100822TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets)
823 : TIntermTyped(TType(EbtFloat, EbpUndefined)),
824 mOperand(operand),
825 mSwizzleOffsets(swizzleOffsets)
826{
827 ASSERT(mSwizzleOffsets.size() <= 4);
828 promote();
829}
830
Olli Etuahoa2234302016-08-31 12:05:39 +0300831TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand)
832 : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false)
833{
834 promote();
Jamie Madillb1a85f42014-08-19 15:23:24 -0400835}
836
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300837TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right)
838 : TIntermOperator(op), mLeft(left), mRight(right), mAddIndexClamp(false)
839{
840 promote();
841}
842
Olli Etuahobf4e1b72016-12-09 11:30:15 +0000843TIntermInvariantDeclaration::TIntermInvariantDeclaration(TIntermSymbol *symbol, const TSourceLoc &line)
844 : TIntermNode(), mSymbol(symbol)
845{
846 ASSERT(symbol);
847 setLine(line);
848}
849
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300850TIntermTernary::TIntermTernary(TIntermTyped *cond,
851 TIntermTyped *trueExpression,
852 TIntermTyped *falseExpression)
853 : TIntermTyped(trueExpression->getType()),
854 mCondition(cond),
855 mTrueExpression(trueExpression),
856 mFalseExpression(falseExpression)
857{
858 getTypePointer()->setQualifier(
859 TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression));
860}
861
862// static
863TQualifier TIntermTernary::DetermineQualifier(TIntermTyped *cond,
864 TIntermTyped *trueExpression,
865 TIntermTyped *falseExpression)
866{
867 if (cond->getQualifier() == EvqConst && trueExpression->getQualifier() == EvqConst &&
868 falseExpression->getQualifier() == EvqConst)
869 {
870 return EvqConst;
871 }
872 return EvqTemporary;
873}
874
Olli Etuahob6fa0432016-09-28 16:28:05 +0100875void TIntermSwizzle::promote()
876{
877 TQualifier resultQualifier = EvqTemporary;
878 if (mOperand->getQualifier() == EvqConst)
879 resultQualifier = EvqConst;
880
881 auto numFields = mSwizzleOffsets.size();
882 setType(TType(mOperand->getBasicType(), mOperand->getPrecision(), resultQualifier,
883 static_cast<unsigned char>(numFields)));
884}
885
886bool TIntermSwizzle::hasDuplicateOffsets() const
887{
888 int offsetCount[4] = {0u, 0u, 0u, 0u};
889 for (const auto offset : mSwizzleOffsets)
890 {
891 offsetCount[offset]++;
892 if (offsetCount[offset] > 1)
893 {
894 return true;
895 }
896 }
897 return false;
898}
899
Olli Etuaho09b04a22016-12-15 13:30:26 +0000900bool TIntermSwizzle::offsetsMatch(int offset) const
901{
902 return mSwizzleOffsets.size() == 1 && mSwizzleOffsets[0] == offset;
903}
904
Olli Etuahob6fa0432016-09-28 16:28:05 +0100905void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const
906{
907 for (const int offset : mSwizzleOffsets)
908 {
909 switch (offset)
910 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500911 case 0:
912 *out << "x";
913 break;
914 case 1:
915 *out << "y";
916 break;
917 case 2:
918 *out << "z";
919 break;
920 case 3:
921 *out << "w";
922 break;
923 default:
924 UNREACHABLE();
Olli Etuahob6fa0432016-09-28 16:28:05 +0100925 }
926 }
927}
928
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100929TQualifier TIntermBinary::GetCommaQualifier(int shaderVersion,
930 const TIntermTyped *left,
931 const TIntermTyped *right)
932{
933 // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
934 if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
935 right->getQualifier() != EvqConst)
936 {
937 return EvqTemporary;
938 }
939 return EvqConst;
940}
Olli Etuahob6fa0432016-09-28 16:28:05 +0100941
942// Establishes the type of the result of the binary operation.
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300943void TIntermBinary::promote()
Jamie Madillb1a85f42014-08-19 15:23:24 -0400944{
Olli Etuaho1dded802016-08-18 18:13:13 +0300945 ASSERT(!isMultiplication() ||
946 mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType()));
947
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100948 // Comma is handled as a special case.
949 if (mOp == EOpComma)
950 {
951 setType(mRight->getType());
952 return;
953 }
954
Jamie Madillb1a85f42014-08-19 15:23:24 -0400955 // Base assumption: just make the type the same as the left
956 // operand. Then only deviations from this need be coded.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400957 setType(mLeft->getType());
958
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200959 TQualifier resultQualifier = EvqConst;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400960 // Binary operations results in temporary variables unless both
961 // operands are const.
962 if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst)
963 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200964 resultQualifier = EvqTemporary;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400965 getTypePointer()->setQualifier(EvqTemporary);
966 }
967
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300968 // Handle indexing ops.
969 switch (mOp)
970 {
971 case EOpIndexDirect:
972 case EOpIndexIndirect:
973 if (mLeft->isArray())
974 {
975 mType.clearArrayness();
976 }
977 else if (mLeft->isMatrix())
978 {
979 setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier,
980 static_cast<unsigned char>(mLeft->getRows())));
981 }
982 else if (mLeft->isVector())
983 {
984 setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier));
985 }
986 else
987 {
988 UNREACHABLE();
989 }
990 return;
991 case EOpIndexDirectStruct:
992 {
993 const TFieldList &fields = mLeft->getType().getStruct()->fields();
994 const int i = mRight->getAsConstantUnion()->getIConst(0);
995 setType(*fields[i]->type());
996 getTypePointer()->setQualifier(resultQualifier);
997 return;
998 }
999 case EOpIndexDirectInterfaceBlock:
1000 {
1001 const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields();
1002 const int i = mRight->getAsConstantUnion()->getIConst(0);
1003 setType(*fields[i]->type());
1004 getTypePointer()->setQualifier(resultQualifier);
1005 return;
1006 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001007 default:
1008 break;
1009 }
1010
1011 ASSERT(mLeft->isArray() == mRight->isArray());
1012
1013 // The result gets promoted to the highest precision.
1014 TPrecision higherPrecision = GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision());
1015 getTypePointer()->setPrecision(higherPrecision);
1016
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001017 const int nominalSize = std::max(mLeft->getNominalSize(), mRight->getNominalSize());
Jamie Madillb1a85f42014-08-19 15:23:24 -04001018
1019 //
1020 // All scalars or structs. Code after this test assumes this case is removed!
1021 //
1022 if (nominalSize == 1)
1023 {
1024 switch (mOp)
1025 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001026 //
1027 // Promote to conditional
1028 //
1029 case EOpEqual:
1030 case EOpNotEqual:
1031 case EOpLessThan:
1032 case EOpGreaterThan:
1033 case EOpLessThanEqual:
1034 case EOpGreaterThanEqual:
1035 setType(TType(EbtBool, EbpUndefined, resultQualifier));
1036 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001037
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001038 //
1039 // And and Or operate on conditionals
1040 //
1041 case EOpLogicalAnd:
1042 case EOpLogicalXor:
1043 case EOpLogicalOr:
1044 ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool);
1045 setType(TType(EbtBool, EbpUndefined, resultQualifier));
1046 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001047
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001048 default:
1049 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001050 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001051 return;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001052 }
1053
1054 // If we reach here, at least one of the operands is vector or matrix.
1055 // The other operand could be a scalar, vector, or matrix.
Jamie Madillb1a85f42014-08-19 15:23:24 -04001056 TBasicType basicType = mLeft->getBasicType();
Olli Etuaho1dded802016-08-18 18:13:13 +03001057
Jamie Madillb1a85f42014-08-19 15:23:24 -04001058 switch (mOp)
1059 {
Olli Etuaho1dded802016-08-18 18:13:13 +03001060 case EOpMul:
1061 break;
1062 case EOpMatrixTimesScalar:
1063 if (mRight->isMatrix())
Jamie Madillb1a85f42014-08-19 15:23:24 -04001064 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001065 setType(TType(basicType, higherPrecision, resultQualifier,
1066 static_cast<unsigned char>(mRight->getCols()),
1067 static_cast<unsigned char>(mRight->getRows())));
Jamie Madillb1a85f42014-08-19 15:23:24 -04001068 }
Olli Etuaho1dded802016-08-18 18:13:13 +03001069 break;
1070 case EOpMatrixTimesVector:
1071 setType(TType(basicType, higherPrecision, resultQualifier,
1072 static_cast<unsigned char>(mLeft->getRows()), 1));
1073 break;
1074 case EOpMatrixTimesMatrix:
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001075 setType(TType(basicType, higherPrecision, resultQualifier,
1076 static_cast<unsigned char>(mRight->getCols()),
1077 static_cast<unsigned char>(mLeft->getRows())));
Olli Etuaho1dded802016-08-18 18:13:13 +03001078 break;
1079 case EOpVectorTimesScalar:
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001080 setType(TType(basicType, higherPrecision, resultQualifier,
Olli Etuaho1dded802016-08-18 18:13:13 +03001081 static_cast<unsigned char>(nominalSize), 1));
1082 break;
1083 case EOpVectorTimesMatrix:
1084 setType(TType(basicType, higherPrecision, resultQualifier,
1085 static_cast<unsigned char>(mRight->getCols()), 1));
1086 break;
1087 case EOpMulAssign:
1088 case EOpVectorTimesScalarAssign:
1089 case EOpVectorTimesMatrixAssign:
1090 case EOpMatrixTimesScalarAssign:
1091 case EOpMatrixTimesMatrixAssign:
1092 ASSERT(mOp == GetMulAssignOpBasedOnOperands(mLeft->getType(), mRight->getType()));
1093 break;
1094 case EOpAssign:
1095 case EOpInitialize:
Olli Etuaho1dded802016-08-18 18:13:13 +03001096 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
1097 (mLeft->getSecondarySize() == mRight->getSecondarySize()));
1098 break;
1099 case EOpAdd:
1100 case EOpSub:
1101 case EOpDiv:
1102 case EOpIMod:
1103 case EOpBitShiftLeft:
1104 case EOpBitShiftRight:
1105 case EOpBitwiseAnd:
1106 case EOpBitwiseXor:
1107 case EOpBitwiseOr:
1108 case EOpAddAssign:
1109 case EOpSubAssign:
1110 case EOpDivAssign:
1111 case EOpIModAssign:
1112 case EOpBitShiftLeftAssign:
1113 case EOpBitShiftRightAssign:
1114 case EOpBitwiseAndAssign:
1115 case EOpBitwiseXorAssign:
1116 case EOpBitwiseOrAssign:
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001117 {
1118 const int secondarySize =
1119 std::max(mLeft->getSecondarySize(), mRight->getSecondarySize());
1120 setType(TType(basicType, higherPrecision, resultQualifier,
1121 static_cast<unsigned char>(nominalSize),
1122 static_cast<unsigned char>(secondarySize)));
1123 ASSERT(!mLeft->isArray() && !mRight->isArray());
Olli Etuaho1dded802016-08-18 18:13:13 +03001124 break;
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001125 }
Olli Etuaho1dded802016-08-18 18:13:13 +03001126 case EOpEqual:
1127 case EOpNotEqual:
1128 case EOpLessThan:
1129 case EOpGreaterThan:
1130 case EOpLessThanEqual:
1131 case EOpGreaterThanEqual:
1132 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
1133 (mLeft->getSecondarySize() == mRight->getSecondarySize()));
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001134 setType(TType(EbtBool, EbpUndefined, resultQualifier));
Olli Etuaho1dded802016-08-18 18:13:13 +03001135 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001136
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001137 case EOpIndexDirect:
1138 case EOpIndexIndirect:
1139 case EOpIndexDirectInterfaceBlock:
1140 case EOpIndexDirectStruct:
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001141 // These ops should be already fully handled.
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001142 UNREACHABLE();
1143 break;
Olli Etuaho1dded802016-08-18 18:13:13 +03001144 default:
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001145 UNREACHABLE();
1146 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001147 }
Jamie Madillb1a85f42014-08-19 15:23:24 -04001148}
1149
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001150const TConstantUnion *TIntermConstantUnion::foldIndexing(int index)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001151{
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001152 if (isArray())
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001153 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001154 ASSERT(index < static_cast<int>(getType().getArraySize()));
1155 TType arrayElementType = getType();
1156 arrayElementType.clearArrayness();
1157 size_t arrayElementSize = arrayElementType.getObjectSize();
1158 return &mUnionArrayPointer[arrayElementSize * index];
1159 }
1160 else if (isMatrix())
1161 {
1162 ASSERT(index < getType().getCols());
1163 int size = getType().getRows();
1164 return &mUnionArrayPointer[size * index];
1165 }
1166 else if (isVector())
1167 {
1168 ASSERT(index < getType().getNominalSize());
1169 return &mUnionArrayPointer[index];
1170 }
1171 else
1172 {
1173 UNREACHABLE();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001174 return nullptr;
1175 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001176}
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001177
Olli Etuahob6fa0432016-09-28 16:28:05 +01001178TIntermTyped *TIntermSwizzle::fold()
1179{
1180 TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
1181 if (operandConstant == nullptr)
1182 {
1183 return nullptr;
1184 }
1185
1186 TConstantUnion *constArray = new TConstantUnion[mSwizzleOffsets.size()];
1187 for (size_t i = 0; i < mSwizzleOffsets.size(); ++i)
1188 {
1189 constArray[i] = *operandConstant->foldIndexing(mSwizzleOffsets.at(i));
1190 }
1191 return CreateFoldedNode(constArray, this, mType.getQualifier());
1192}
1193
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001194TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
1195{
1196 TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion();
1197 TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion();
1198 switch (mOp)
1199 {
1200 case EOpIndexDirect:
1201 {
1202 if (leftConstant == nullptr || rightConstant == nullptr)
1203 {
1204 return nullptr;
1205 }
1206 int index = rightConstant->getIConst(0);
1207
1208 const TConstantUnion *constArray = leftConstant->foldIndexing(index);
1209 return CreateFoldedNode(constArray, this, mType.getQualifier());
1210 }
1211 case EOpIndexDirectStruct:
1212 {
1213 if (leftConstant == nullptr || rightConstant == nullptr)
1214 {
1215 return nullptr;
1216 }
1217 const TFieldList &fields = mLeft->getType().getStruct()->fields();
1218 size_t index = static_cast<size_t>(rightConstant->getIConst(0));
1219
1220 size_t previousFieldsSize = 0;
1221 for (size_t i = 0; i < index; ++i)
1222 {
1223 previousFieldsSize += fields[i]->type()->getObjectSize();
1224 }
1225
1226 const TConstantUnion *constArray = leftConstant->getUnionArrayPointer();
1227 return CreateFoldedNode(constArray + previousFieldsSize, this, mType.getQualifier());
1228 }
1229 case EOpIndexIndirect:
1230 case EOpIndexDirectInterfaceBlock:
1231 // Can never be constant folded.
1232 return nullptr;
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001233 default:
1234 {
1235 if (leftConstant == nullptr || rightConstant == nullptr)
1236 {
1237 return nullptr;
1238 }
Jamie Madill5db69f52016-09-15 12:47:32 -04001239 TConstantUnion *constArray =
1240 leftConstant->foldBinary(mOp, rightConstant, diagnostics, mLeft->getLine());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001241
1242 // Nodes may be constant folded without being qualified as constant.
1243 return CreateFoldedNode(constArray, this, mType.getQualifier());
1244 }
1245 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001246}
1247
Olli Etuahof119a262016-08-19 15:54:22 +03001248TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
Olli Etuaho95310b02015-06-02 17:43:38 +03001249{
1250 TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
1251 if (operandConstant == nullptr)
1252 {
1253 return nullptr;
1254 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301255
1256 TConstantUnion *constArray = nullptr;
1257 switch (mOp)
1258 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001259 case EOpAny:
1260 case EOpAll:
1261 case EOpLength:
1262 case EOpTranspose:
1263 case EOpDeterminant:
1264 case EOpInverse:
1265 case EOpPackSnorm2x16:
1266 case EOpUnpackSnorm2x16:
1267 case EOpPackUnorm2x16:
1268 case EOpUnpackUnorm2x16:
1269 case EOpPackHalf2x16:
1270 case EOpUnpackHalf2x16:
1271 constArray = operandConstant->foldUnaryNonComponentWise(mOp);
1272 break;
1273 default:
1274 constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics);
1275 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301276 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001277
1278 // Nodes may be constant folded without being qualified as constant.
Olli Etuahoc9550582016-08-29 17:56:22 +03001279 return CreateFoldedNode(constArray, this, mType.getQualifier());
Olli Etuahob43846e2015-06-02 18:18:57 +03001280}
1281
Olli Etuahof119a262016-08-19 15:54:22 +03001282TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics)
Olli Etuahob43846e2015-06-02 18:18:57 +03001283{
1284 // Make sure that all params are constant before actual constant folding.
1285 for (auto *param : *getSequence())
Olli Etuaho95310b02015-06-02 17:43:38 +03001286 {
Olli Etuahob43846e2015-06-02 18:18:57 +03001287 if (param->getAsConstantUnion() == nullptr)
1288 {
1289 return nullptr;
1290 }
Olli Etuaho95310b02015-06-02 17:43:38 +03001291 }
Olli Etuaho1d122782015-11-06 15:35:17 +02001292 TConstantUnion *constArray = nullptr;
1293 if (isConstructor())
Olli Etuahof119a262016-08-19 15:54:22 +03001294 constArray = TIntermConstantUnion::FoldAggregateConstructor(this);
Olli Etuaho1d122782015-11-06 15:35:17 +02001295 else
Olli Etuahof119a262016-08-19 15:54:22 +03001296 constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001297
1298 // Nodes may be constant folded without being qualified as constant.
1299 TQualifier resultQualifier = areChildrenConstQualified() ? EvqConst : EvqTemporary;
1300 return CreateFoldedNode(constArray, this, resultQualifier);
Olli Etuaho95310b02015-06-02 17:43:38 +03001301}
1302
Jamie Madillb1a85f42014-08-19 15:23:24 -04001303//
1304// The fold functions see if an operation on a constant can be done in place,
1305// without generating run-time code.
1306//
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001307// Returns the constant value to keep using or nullptr.
Jamie Madillb1a85f42014-08-19 15:23:24 -04001308//
Olli Etuaho3fdec912016-08-18 15:08:06 +03001309TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op,
1310 TIntermConstantUnion *rightNode,
Jamie Madill5db69f52016-09-15 12:47:32 -04001311 TDiagnostics *diagnostics,
1312 const TSourceLoc &line)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001313{
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001314 const TConstantUnion *leftArray = getUnionArrayPointer();
1315 const TConstantUnion *rightArray = rightNode->getUnionArrayPointer();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001316
Olli Etuahof119a262016-08-19 15:54:22 +03001317 ASSERT(leftArray && rightArray);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001318
1319 size_t objectSize = getType().getObjectSize();
1320
1321 // for a case like float f = vec4(2, 3, 4, 5) + 1.2;
1322 if (rightNode->getType().getObjectSize() == 1 && objectSize > 1)
1323 {
1324 rightArray = Vectorize(*rightNode->getUnionArrayPointer(), objectSize);
1325 }
1326 else if (rightNode->getType().getObjectSize() > 1 && objectSize == 1)
1327 {
1328 // for a case like float f = 1.2 + vec4(2, 3, 4, 5);
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001329 leftArray = Vectorize(*getUnionArrayPointer(), rightNode->getType().getObjectSize());
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001330 objectSize = rightNode->getType().getObjectSize();
1331 }
1332
1333 TConstantUnion *resultArray = nullptr;
1334
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001335 switch (op)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001336 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001337 case EOpAdd:
1338 resultArray = new TConstantUnion[objectSize];
1339 for (size_t i = 0; i < objectSize; i++)
1340 resultArray[i] =
1341 TConstantUnion::add(leftArray[i], rightArray[i], diagnostics, line);
1342 break;
1343 case EOpSub:
1344 resultArray = new TConstantUnion[objectSize];
1345 for (size_t i = 0; i < objectSize; i++)
1346 resultArray[i] =
1347 TConstantUnion::sub(leftArray[i], rightArray[i], diagnostics, line);
1348 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001349
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001350 case EOpMul:
1351 case EOpVectorTimesScalar:
1352 case EOpMatrixTimesScalar:
1353 resultArray = new TConstantUnion[objectSize];
1354 for (size_t i = 0; i < objectSize; i++)
1355 resultArray[i] =
1356 TConstantUnion::mul(leftArray[i], rightArray[i], diagnostics, line);
1357 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001358
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001359 case EOpMatrixTimesMatrix:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001360 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001361 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001362 ASSERT(getType().getBasicType() == EbtFloat && rightNode->getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001363
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001364 const int leftCols = getCols();
1365 const int leftRows = getRows();
1366 const int rightCols = rightNode->getType().getCols();
1367 const int rightRows = rightNode->getType().getRows();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001368 const int resultCols = rightCols;
1369 const int resultRows = leftRows;
1370
1371 resultArray = new TConstantUnion[resultCols * resultRows];
1372 for (int row = 0; row < resultRows; row++)
1373 {
1374 for (int column = 0; column < resultCols; column++)
1375 {
1376 resultArray[resultRows * column + row].setFConst(0.0f);
1377 for (int i = 0; i < leftCols; i++)
1378 {
1379 resultArray[resultRows * column + row].setFConst(
1380 resultArray[resultRows * column + row].getFConst() +
1381 leftArray[i * leftRows + row].getFConst() *
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001382 rightArray[column * rightRows + i].getFConst());
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001383 }
1384 }
1385 }
1386 }
1387 break;
1388
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001389 case EOpDiv:
1390 case EOpIMod:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001391 {
1392 resultArray = new TConstantUnion[objectSize];
1393 for (size_t i = 0; i < objectSize; i++)
1394 {
1395 switch (getType().getBasicType())
1396 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001397 case EbtFloat:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001398 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001399 ASSERT(op == EOpDiv);
1400 float dividend = leftArray[i].getFConst();
1401 float divisor = rightArray[i].getFConst();
1402 if (divisor == 0.0f)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001403 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001404 if (dividend == 0.0f)
Olli Etuahod4453572016-09-27 13:21:46 +01001405 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001406 diagnostics->warning(
1407 getLine(),
1408 "Zero divided by zero during constant folding generated NaN",
Olli Etuaho4de340a2016-12-16 09:32:03 +00001409 "/");
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001410 resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
Olli Etuahod4453572016-09-27 13:21:46 +01001411 }
1412 else
1413 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001414 diagnostics->warning(getLine(),
1415 "Divide by zero during constant folding", "/");
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001416 bool negativeResult =
1417 std::signbit(dividend) != std::signbit(divisor);
1418 resultArray[i].setFConst(
1419 negativeResult ? -std::numeric_limits<float>::infinity()
1420 : std::numeric_limits<float>::infinity());
Olli Etuahod4453572016-09-27 13:21:46 +01001421 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001422 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001423 else if (gl::isInf(dividend) && gl::isInf(divisor))
1424 {
1425 diagnostics->warning(getLine(),
1426 "Infinity divided by infinity during constant "
1427 "folding generated NaN",
Olli Etuaho4de340a2016-12-16 09:32:03 +00001428 "/");
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001429 resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
1430 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001431 else
1432 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001433 float result = dividend / divisor;
1434 if (!gl::isInf(dividend) && gl::isInf(result))
Olli Etuahod4453572016-09-27 13:21:46 +01001435 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001436 diagnostics->warning(
1437 getLine(), "Constant folded division overflowed to infinity",
Olli Etuaho4de340a2016-12-16 09:32:03 +00001438 "/");
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001439 }
1440 resultArray[i].setFConst(result);
1441 }
1442 break;
1443 }
1444 case EbtInt:
1445 if (rightArray[i] == 0)
1446 {
1447 diagnostics->warning(
Olli Etuaho4de340a2016-12-16 09:32:03 +00001448 getLine(), "Divide by zero error during constant folding", "/");
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001449 resultArray[i].setIConst(INT_MAX);
1450 }
1451 else
1452 {
1453 int lhs = leftArray[i].getIConst();
1454 int divisor = rightArray[i].getIConst();
1455 if (op == EOpDiv)
1456 {
1457 // Check for the special case where the minimum representable number
1458 // is
1459 // divided by -1. If left alone this leads to integer overflow in
1460 // C++.
1461 // ESSL 3.00.6 section 4.1.3 Integers:
1462 // "However, for the case where the minimum representable value is
1463 // divided by -1, it is allowed to return either the minimum
1464 // representable value or the maximum representable value."
1465 if (lhs == -0x7fffffff - 1 && divisor == -1)
1466 {
1467 resultArray[i].setIConst(0x7fffffff);
1468 }
1469 else
1470 {
1471 resultArray[i].setIConst(lhs / divisor);
1472 }
Olli Etuahod4453572016-09-27 13:21:46 +01001473 }
1474 else
1475 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001476 ASSERT(op == EOpIMod);
1477 if (lhs < 0 || divisor < 0)
1478 {
1479 // ESSL 3.00.6 section 5.9: Results of modulus are undefined
1480 // when
1481 // either one of the operands is negative.
1482 diagnostics->warning(getLine(),
1483 "Negative modulus operator operand "
1484 "encountered during constant folding",
Olli Etuaho4de340a2016-12-16 09:32:03 +00001485 "%");
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001486 resultArray[i].setIConst(0);
1487 }
1488 else
1489 {
1490 resultArray[i].setIConst(lhs % divisor);
1491 }
Olli Etuahod4453572016-09-27 13:21:46 +01001492 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001493 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001494 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001495
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001496 case EbtUInt:
1497 if (rightArray[i] == 0)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001498 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001499 diagnostics->warning(
Olli Etuaho4de340a2016-12-16 09:32:03 +00001500 getLine(), "Divide by zero error during constant folding", "/");
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001501 resultArray[i].setUConst(UINT_MAX);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001502 }
1503 else
1504 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001505 if (op == EOpDiv)
1506 {
1507 resultArray[i].setUConst(leftArray[i].getUConst() /
1508 rightArray[i].getUConst());
1509 }
1510 else
1511 {
1512 ASSERT(op == EOpIMod);
1513 resultArray[i].setUConst(leftArray[i].getUConst() %
1514 rightArray[i].getUConst());
1515 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001516 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001517 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001518
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001519 default:
1520 UNREACHABLE();
1521 return nullptr;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001522 }
1523 }
1524 }
1525 break;
1526
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001527 case EOpMatrixTimesVector:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001528 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001529 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001530 ASSERT(rightNode->getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001531
1532 const int matrixCols = getCols();
1533 const int matrixRows = getRows();
1534
1535 resultArray = new TConstantUnion[matrixRows];
1536
1537 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
1538 {
1539 resultArray[matrixRow].setFConst(0.0f);
1540 for (int col = 0; col < matrixCols; col++)
1541 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001542 resultArray[matrixRow].setFConst(
1543 resultArray[matrixRow].getFConst() +
1544 leftArray[col * matrixRows + matrixRow].getFConst() *
1545 rightArray[col].getFConst());
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001546 }
1547 }
1548 }
1549 break;
1550
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001551 case EOpVectorTimesMatrix:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001552 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001553 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001554 ASSERT(getType().getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001555
1556 const int matrixCols = rightNode->getType().getCols();
1557 const int matrixRows = rightNode->getType().getRows();
1558
1559 resultArray = new TConstantUnion[matrixCols];
1560
1561 for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++)
1562 {
1563 resultArray[matrixCol].setFConst(0.0f);
1564 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
1565 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001566 resultArray[matrixCol].setFConst(
1567 resultArray[matrixCol].getFConst() +
1568 leftArray[matrixRow].getFConst() *
1569 rightArray[matrixCol * matrixRows + matrixRow].getFConst());
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001570 }
1571 }
1572 }
1573 break;
1574
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001575 case EOpLogicalAnd:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001576 {
1577 resultArray = new TConstantUnion[objectSize];
1578 for (size_t i = 0; i < objectSize; i++)
1579 {
1580 resultArray[i] = leftArray[i] && rightArray[i];
1581 }
1582 }
1583 break;
1584
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001585 case EOpLogicalOr:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001586 {
1587 resultArray = new TConstantUnion[objectSize];
1588 for (size_t i = 0; i < objectSize; i++)
1589 {
1590 resultArray[i] = leftArray[i] || rightArray[i];
1591 }
1592 }
1593 break;
1594
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001595 case EOpLogicalXor:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001596 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001597 ASSERT(getType().getBasicType() == EbtBool);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001598 resultArray = new TConstantUnion[objectSize];
1599 for (size_t i = 0; i < objectSize; i++)
1600 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001601 resultArray[i].setBConst(leftArray[i] != rightArray[i]);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001602 }
1603 }
1604 break;
1605
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001606 case EOpBitwiseAnd:
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 EOpBitwiseXor:
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 EOpBitwiseOr:
1617 resultArray = new TConstantUnion[objectSize];
1618 for (size_t i = 0; i < objectSize; i++)
1619 resultArray[i] = leftArray[i] | rightArray[i];
1620 break;
1621 case EOpBitShiftLeft:
1622 resultArray = new TConstantUnion[objectSize];
1623 for (size_t i = 0; i < objectSize; i++)
1624 resultArray[i] =
1625 TConstantUnion::lshift(leftArray[i], rightArray[i], diagnostics, line);
1626 break;
1627 case EOpBitShiftRight:
1628 resultArray = new TConstantUnion[objectSize];
1629 for (size_t i = 0; i < objectSize; i++)
1630 resultArray[i] =
1631 TConstantUnion::rshift(leftArray[i], rightArray[i], diagnostics, line);
1632 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001633
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001634 case EOpLessThan:
1635 ASSERT(objectSize == 1);
1636 resultArray = new TConstantUnion[1];
1637 resultArray->setBConst(*leftArray < *rightArray);
1638 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001639
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001640 case EOpGreaterThan:
1641 ASSERT(objectSize == 1);
1642 resultArray = new TConstantUnion[1];
1643 resultArray->setBConst(*leftArray > *rightArray);
1644 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001645
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001646 case EOpLessThanEqual:
1647 ASSERT(objectSize == 1);
1648 resultArray = new TConstantUnion[1];
1649 resultArray->setBConst(!(*leftArray > *rightArray));
1650 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001651
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001652 case EOpGreaterThanEqual:
1653 ASSERT(objectSize == 1);
1654 resultArray = new TConstantUnion[1];
1655 resultArray->setBConst(!(*leftArray < *rightArray));
1656 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001657
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001658 case EOpEqual:
1659 case EOpNotEqual:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001660 {
1661 resultArray = new TConstantUnion[1];
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001662 bool equal = true;
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001663 for (size_t i = 0; i < objectSize; i++)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001664 {
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001665 if (leftArray[i] != rightArray[i])
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001666 {
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001667 equal = false;
1668 break; // break out of for loop
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001669 }
1670 }
1671 if (op == EOpEqual)
1672 {
1673 resultArray->setBConst(equal);
1674 }
1675 else
1676 {
1677 resultArray->setBConst(!equal);
1678 }
1679 }
1680 break;
1681
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001682 default:
1683 UNREACHABLE();
1684 return nullptr;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001685 }
1686 return resultArray;
1687}
1688
Olli Etuahof119a262016-08-19 15:54:22 +03001689// The fold functions do operations on a constant at GLSL compile time, without generating run-time
1690// code. Returns the constant value to keep using. Nullptr should not be returned.
1691TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op)
Jamie Madillb1a85f42014-08-19 15:23:24 -04001692{
Olli Etuahof119a262016-08-19 15:54:22 +03001693 // Do operations where the return type may have a different number of components compared to the
1694 // operand type.
Jamie Madillb1a85f42014-08-19 15:23:24 -04001695
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001696 const TConstantUnion *operandArray = getUnionArrayPointer();
Olli Etuahof119a262016-08-19 15:54:22 +03001697 ASSERT(operandArray);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301698
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001699 size_t objectSize = getType().getObjectSize();
Arun Patoleab2b9a22015-07-06 18:27:56 +05301700 TConstantUnion *resultArray = nullptr;
1701 switch (op)
1702 {
Olli Etuahof119a262016-08-19 15:54:22 +03001703 case EOpAny:
1704 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301705 resultArray = new TConstantUnion();
1706 resultArray->setBConst(false);
1707 for (size_t i = 0; i < objectSize; i++)
1708 {
1709 if (operandArray[i].getBConst())
1710 {
1711 resultArray->setBConst(true);
1712 break;
1713 }
1714 }
1715 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301716
Olli Etuahof119a262016-08-19 15:54:22 +03001717 case EOpAll:
1718 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301719 resultArray = new TConstantUnion();
1720 resultArray->setBConst(true);
1721 for (size_t i = 0; i < objectSize; i++)
1722 {
1723 if (!operandArray[i].getBConst())
1724 {
1725 resultArray->setBConst(false);
1726 break;
1727 }
1728 }
1729 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301730
Olli Etuahof119a262016-08-19 15:54:22 +03001731 case EOpLength:
1732 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301733 resultArray = new TConstantUnion();
1734 resultArray->setFConst(VectorLength(operandArray, objectSize));
1735 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301736
Olli Etuahof119a262016-08-19 15:54:22 +03001737 case EOpTranspose:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301738 {
Olli Etuahof119a262016-08-19 15:54:22 +03001739 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301740 resultArray = new TConstantUnion[objectSize];
1741 angle::Matrix<float> result =
Olli Etuahod5da5052016-08-29 13:16:55 +03001742 GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose();
Arun Patoleab2b9a22015-07-06 18:27:56 +05301743 SetUnionArrayFromMatrix(result, resultArray);
1744 break;
1745 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301746
Olli Etuahof119a262016-08-19 15:54:22 +03001747 case EOpDeterminant:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301748 {
Olli Etuahof119a262016-08-19 15:54:22 +03001749 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301750 unsigned int size = getType().getNominalSize();
1751 ASSERT(size >= 2 && size <= 4);
1752 resultArray = new TConstantUnion();
1753 resultArray->setFConst(GetMatrix(operandArray, size).determinant());
1754 break;
1755 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301756
Olli Etuahof119a262016-08-19 15:54:22 +03001757 case EOpInverse:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301758 {
Olli Etuahof119a262016-08-19 15:54:22 +03001759 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301760 unsigned int size = getType().getNominalSize();
1761 ASSERT(size >= 2 && size <= 4);
Olli Etuahof119a262016-08-19 15:54:22 +03001762 resultArray = new TConstantUnion[objectSize];
Arun Patoleab2b9a22015-07-06 18:27:56 +05301763 angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
1764 SetUnionArrayFromMatrix(result, resultArray);
1765 break;
1766 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301767
Olli Etuahof119a262016-08-19 15:54:22 +03001768 case EOpPackSnorm2x16:
1769 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301770 ASSERT(getType().getNominalSize() == 2);
1771 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001772 resultArray->setUConst(
1773 gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301774 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301775
Olli Etuahof119a262016-08-19 15:54:22 +03001776 case EOpUnpackSnorm2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301777 {
Olli Etuahof119a262016-08-19 15:54:22 +03001778 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301779 resultArray = new TConstantUnion[2];
1780 float f1, f2;
1781 gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
1782 resultArray[0].setFConst(f1);
1783 resultArray[1].setFConst(f2);
1784 break;
1785 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301786
Olli Etuahof119a262016-08-19 15:54:22 +03001787 case EOpPackUnorm2x16:
1788 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301789 ASSERT(getType().getNominalSize() == 2);
1790 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001791 resultArray->setUConst(
1792 gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301793 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301794
Olli Etuahof119a262016-08-19 15:54:22 +03001795 case EOpUnpackUnorm2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301796 {
Olli Etuahof119a262016-08-19 15:54:22 +03001797 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301798 resultArray = new TConstantUnion[2];
1799 float f1, f2;
1800 gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
1801 resultArray[0].setFConst(f1);
1802 resultArray[1].setFConst(f2);
1803 break;
1804 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301805
Olli Etuahof119a262016-08-19 15:54:22 +03001806 case EOpPackHalf2x16:
1807 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301808 ASSERT(getType().getNominalSize() == 2);
1809 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001810 resultArray->setUConst(
1811 gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301812 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301813
Olli Etuahof119a262016-08-19 15:54:22 +03001814 case EOpUnpackHalf2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301815 {
Olli Etuahof119a262016-08-19 15:54:22 +03001816 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301817 resultArray = new TConstantUnion[2];
1818 float f1, f2;
1819 gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2);
1820 resultArray[0].setFConst(f1);
1821 resultArray[1].setFConst(f2);
1822 break;
1823 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301824
Olli Etuahof119a262016-08-19 15:54:22 +03001825 default:
1826 UNREACHABLE();
1827 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301828 }
1829
1830 return resultArray;
1831}
1832
Olli Etuahof119a262016-08-19 15:54:22 +03001833TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op,
1834 TDiagnostics *diagnostics)
Arun Patoleab2b9a22015-07-06 18:27:56 +05301835{
Olli Etuahof119a262016-08-19 15:54:22 +03001836 // Do unary operations where each component of the result is computed based on the corresponding
1837 // component of the operand. Also folds normalize, though the divisor in that case takes all
1838 // components into account.
Arun Patoleab2b9a22015-07-06 18:27:56 +05301839
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001840 const TConstantUnion *operandArray = getUnionArrayPointer();
Olli Etuahof119a262016-08-19 15:54:22 +03001841 ASSERT(operandArray);
Jamie Madillb1a85f42014-08-19 15:23:24 -04001842
1843 size_t objectSize = getType().getObjectSize();
1844
Arun Patoleab2b9a22015-07-06 18:27:56 +05301845 TConstantUnion *resultArray = new TConstantUnion[objectSize];
1846 for (size_t i = 0; i < objectSize; i++)
Arun Patole9d0b1f92015-05-20 14:27:17 +05301847 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001848 switch (op)
Arun Patole9d0b1f92015-05-20 14:27:17 +05301849 {
Olli Etuahof119a262016-08-19 15:54:22 +03001850 case EOpNegative:
1851 switch (getType().getBasicType())
1852 {
1853 case EbtFloat:
1854 resultArray[i].setFConst(-operandArray[i].getFConst());
1855 break;
1856 case EbtInt:
Olli Etuaho42fad762016-09-28 10:06:29 +01001857 if (operandArray[i] == std::numeric_limits<int>::min())
1858 {
1859 // The minimum representable integer doesn't have a positive
1860 // counterpart, rather the negation overflows and in ESSL is supposed to
1861 // wrap back to the minimum representable integer. Make sure that we
1862 // don't actually let the negation overflow, which has undefined
1863 // behavior in C++.
1864 resultArray[i].setIConst(std::numeric_limits<int>::min());
1865 }
1866 else
1867 {
1868 resultArray[i].setIConst(-operandArray[i].getIConst());
1869 }
Olli Etuahof119a262016-08-19 15:54:22 +03001870 break;
1871 case EbtUInt:
Olli Etuaho42fad762016-09-28 10:06:29 +01001872 if (operandArray[i] == 0x80000000u)
1873 {
1874 resultArray[i].setUConst(0x80000000u);
1875 }
1876 else
1877 {
1878 resultArray[i].setUConst(static_cast<unsigned int>(
1879 -static_cast<int>(operandArray[i].getUConst())));
1880 }
Olli Etuahof119a262016-08-19 15:54:22 +03001881 break;
1882 default:
1883 UNREACHABLE();
1884 return nullptr;
1885 }
Arun Patole1155ddd2015-06-05 18:04:36 +05301886 break;
Arun Patolecdfa8f52015-06-30 17:48:25 +05301887
Olli Etuahof119a262016-08-19 15:54:22 +03001888 case EOpPositive:
1889 switch (getType().getBasicType())
1890 {
1891 case EbtFloat:
1892 resultArray[i].setFConst(operandArray[i].getFConst());
1893 break;
1894 case EbtInt:
1895 resultArray[i].setIConst(operandArray[i].getIConst());
1896 break;
1897 case EbtUInt:
1898 resultArray[i].setUConst(static_cast<unsigned int>(
1899 static_cast<int>(operandArray[i].getUConst())));
1900 break;
1901 default:
1902 UNREACHABLE();
1903 return nullptr;
1904 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301905 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301906
Olli Etuahof119a262016-08-19 15:54:22 +03001907 case EOpLogicalNot:
1908 switch (getType().getBasicType())
1909 {
1910 case EbtBool:
1911 resultArray[i].setBConst(!operandArray[i].getBConst());
1912 break;
1913 default:
1914 UNREACHABLE();
1915 return nullptr;
1916 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301917 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301918
Olli Etuahof119a262016-08-19 15:54:22 +03001919 case EOpBitwiseNot:
1920 switch (getType().getBasicType())
1921 {
1922 case EbtInt:
1923 resultArray[i].setIConst(~operandArray[i].getIConst());
1924 break;
1925 case EbtUInt:
1926 resultArray[i].setUConst(~operandArray[i].getUConst());
1927 break;
1928 default:
1929 UNREACHABLE();
1930 return nullptr;
1931 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301932 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301933
Olli Etuahof119a262016-08-19 15:54:22 +03001934 case EOpRadians:
1935 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301936 resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
1937 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301938
Olli Etuahof119a262016-08-19 15:54:22 +03001939 case EOpDegrees:
1940 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301941 resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
1942 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301943
Olli Etuahof119a262016-08-19 15:54:22 +03001944 case EOpSin:
1945 foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301946 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301947
Olli Etuahof119a262016-08-19 15:54:22 +03001948 case EOpCos:
1949 foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]);
1950 break;
1951
1952 case EOpTan:
1953 foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]);
1954 break;
1955
1956 case EOpAsin:
1957 // For asin(x), results are undefined if |x| > 1, we are choosing to set result to
1958 // 0.
1959 if (fabsf(operandArray[i].getFConst()) > 1.0f)
1960 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1961 diagnostics, &resultArray[i]);
1962 else
1963 foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]);
1964 break;
1965
1966 case EOpAcos:
1967 // For acos(x), results are undefined if |x| > 1, we are choosing to set result to
1968 // 0.
1969 if (fabsf(operandArray[i].getFConst()) > 1.0f)
1970 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1971 diagnostics, &resultArray[i]);
1972 else
1973 foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]);
1974 break;
1975
1976 case EOpAtan:
1977 foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]);
1978 break;
1979
1980 case EOpSinh:
1981 foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]);
1982 break;
1983
1984 case EOpCosh:
1985 foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]);
1986 break;
1987
1988 case EOpTanh:
1989 foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]);
1990 break;
1991
1992 case EOpAsinh:
1993 foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]);
1994 break;
1995
1996 case EOpAcosh:
1997 // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
1998 if (operandArray[i].getFConst() < 1.0f)
1999 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2000 diagnostics, &resultArray[i]);
2001 else
2002 foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]);
2003 break;
2004
2005 case EOpAtanh:
2006 // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to
2007 // 0.
2008 if (fabsf(operandArray[i].getFConst()) >= 1.0f)
2009 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2010 diagnostics, &resultArray[i]);
2011 else
2012 foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]);
2013 break;
2014
2015 case EOpAbs:
2016 switch (getType().getBasicType())
Arun Patoleab2b9a22015-07-06 18:27:56 +05302017 {
Olli Etuahof119a262016-08-19 15:54:22 +03002018 case EbtFloat:
2019 resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
2020 break;
2021 case EbtInt:
2022 resultArray[i].setIConst(abs(operandArray[i].getIConst()));
2023 break;
2024 default:
2025 UNREACHABLE();
2026 return nullptr;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302027 }
2028 break;
Olli Etuahof119a262016-08-19 15:54:22 +03002029
2030 case EOpSign:
2031 switch (getType().getBasicType())
Arun Patoleab2b9a22015-07-06 18:27:56 +05302032 {
Olli Etuahof119a262016-08-19 15:54:22 +03002033 case EbtFloat:
2034 {
2035 float fConst = operandArray[i].getFConst();
2036 float fResult = 0.0f;
2037 if (fConst > 0.0f)
2038 fResult = 1.0f;
2039 else if (fConst < 0.0f)
2040 fResult = -1.0f;
2041 resultArray[i].setFConst(fResult);
2042 break;
2043 }
2044 case EbtInt:
2045 {
2046 int iConst = operandArray[i].getIConst();
2047 int iResult = 0;
2048 if (iConst > 0)
2049 iResult = 1;
2050 else if (iConst < 0)
2051 iResult = -1;
2052 resultArray[i].setIConst(iResult);
2053 break;
2054 }
2055 default:
2056 UNREACHABLE();
2057 return nullptr;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302058 }
2059 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302060
Olli Etuahof119a262016-08-19 15:54:22 +03002061 case EOpFloor:
2062 foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]);
2063 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302064
Olli Etuahof119a262016-08-19 15:54:22 +03002065 case EOpTrunc:
2066 foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]);
2067 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302068
Olli Etuahof119a262016-08-19 15:54:22 +03002069 case EOpRound:
2070 foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]);
2071 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302072
Olli Etuahof119a262016-08-19 15:54:22 +03002073 case EOpRoundEven:
Arun Patoleab2b9a22015-07-06 18:27:56 +05302074 {
Olli Etuahof119a262016-08-19 15:54:22 +03002075 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302076 float x = operandArray[i].getFConst();
2077 float result;
2078 float fractPart = modff(x, &result);
2079 if (fabsf(fractPart) == 0.5f)
2080 result = 2.0f * roundf(x / 2.0f);
2081 else
2082 result = roundf(x);
2083 resultArray[i].setFConst(result);
2084 break;
2085 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05302086
Olli Etuahof119a262016-08-19 15:54:22 +03002087 case EOpCeil:
2088 foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]);
2089 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302090
Olli Etuahof119a262016-08-19 15:54:22 +03002091 case EOpFract:
Arun Patoleab2b9a22015-07-06 18:27:56 +05302092 {
Olli Etuahof119a262016-08-19 15:54:22 +03002093 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302094 float x = operandArray[i].getFConst();
2095 resultArray[i].setFConst(x - floorf(x));
2096 break;
2097 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05302098
Olli Etuahof119a262016-08-19 15:54:22 +03002099 case EOpIsNan:
2100 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302101 resultArray[i].setBConst(gl::isNaN(operandArray[0].getFConst()));
2102 break;
Arun Patole551279e2015-07-07 18:18:23 +05302103
Olli Etuahof119a262016-08-19 15:54:22 +03002104 case EOpIsInf:
2105 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302106 resultArray[i].setBConst(gl::isInf(operandArray[0].getFConst()));
2107 break;
Arun Patole551279e2015-07-07 18:18:23 +05302108
Olli Etuahof119a262016-08-19 15:54:22 +03002109 case EOpFloatBitsToInt:
2110 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302111 resultArray[i].setIConst(gl::bitCast<int32_t>(operandArray[0].getFConst()));
2112 break;
Arun Patole551279e2015-07-07 18:18:23 +05302113
Olli Etuahof119a262016-08-19 15:54:22 +03002114 case EOpFloatBitsToUint:
2115 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302116 resultArray[i].setUConst(gl::bitCast<uint32_t>(operandArray[0].getFConst()));
2117 break;
Arun Patole551279e2015-07-07 18:18:23 +05302118
Olli Etuahof119a262016-08-19 15:54:22 +03002119 case EOpIntBitsToFloat:
2120 ASSERT(getType().getBasicType() == EbtInt);
Arun Patole551279e2015-07-07 18:18:23 +05302121 resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getIConst()));
2122 break;
Arun Patole551279e2015-07-07 18:18:23 +05302123
Olli Etuahof119a262016-08-19 15:54:22 +03002124 case EOpUintBitsToFloat:
2125 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patole551279e2015-07-07 18:18:23 +05302126 resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getUConst()));
2127 break;
Arun Patole551279e2015-07-07 18:18:23 +05302128
Olli Etuahof119a262016-08-19 15:54:22 +03002129 case EOpExp:
2130 foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]);
2131 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302132
Olli Etuahof119a262016-08-19 15:54:22 +03002133 case EOpLog:
2134 // For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
2135 if (operandArray[i].getFConst() <= 0.0f)
2136 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2137 diagnostics, &resultArray[i]);
2138 else
2139 foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
2140 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302141
Olli Etuahof119a262016-08-19 15:54:22 +03002142 case EOpExp2:
2143 foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]);
2144 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302145
Olli Etuahof119a262016-08-19 15:54:22 +03002146 case EOpLog2:
2147 // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
2148 // And log2f is not available on some plarforms like old android, so just using
2149 // log(x)/log(2) here.
2150 if (operandArray[i].getFConst() <= 0.0f)
2151 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2152 diagnostics, &resultArray[i]);
2153 else
2154 {
2155 foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
2156 resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
2157 }
2158 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302159
Olli Etuahof119a262016-08-19 15:54:22 +03002160 case EOpSqrt:
2161 // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
2162 if (operandArray[i].getFConst() < 0.0f)
2163 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2164 diagnostics, &resultArray[i]);
2165 else
2166 foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
2167 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302168
Olli Etuahof119a262016-08-19 15:54:22 +03002169 case EOpInverseSqrt:
2170 // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
2171 // so getting the square root first using builtin function sqrt() and then taking
2172 // its inverse.
2173 // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set
2174 // result to 0.
2175 if (operandArray[i].getFConst() <= 0.0f)
2176 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2177 diagnostics, &resultArray[i]);
2178 else
2179 {
2180 foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
2181 resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
2182 }
2183 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302184
Olli Etuahod68924e2017-01-02 17:34:40 +00002185 case EOpLogicalNotComponentWise:
Olli Etuahof119a262016-08-19 15:54:22 +03002186 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302187 resultArray[i].setBConst(!operandArray[i].getBConst());
2188 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302189
Olli Etuahof119a262016-08-19 15:54:22 +03002190 case EOpNormalize:
Arun Patoleab2b9a22015-07-06 18:27:56 +05302191 {
Olli Etuahof119a262016-08-19 15:54:22 +03002192 ASSERT(getType().getBasicType() == EbtFloat);
2193 float x = operandArray[i].getFConst();
Arun Patoleab2b9a22015-07-06 18:27:56 +05302194 float length = VectorLength(operandArray, objectSize);
2195 if (length)
2196 resultArray[i].setFConst(x / length);
2197 else
Olli Etuahof119a262016-08-19 15:54:22 +03002198 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2199 diagnostics, &resultArray[i]);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302200 break;
2201 }
Olli Etuaho9250cb22017-01-21 10:51:27 +00002202 case EOpBitfieldReverse:
2203 {
2204 uint32_t value;
2205 if (getType().getBasicType() == EbtInt)
2206 {
2207 value = static_cast<uint32_t>(operandArray[i].getIConst());
2208 }
2209 else
2210 {
2211 ASSERT(getType().getBasicType() == EbtUInt);
2212 value = operandArray[i].getUConst();
2213 }
2214 uint32_t result = gl::BitfieldReverse(value);
2215 if (getType().getBasicType() == EbtInt)
2216 {
2217 resultArray[i].setIConst(static_cast<int32_t>(result));
2218 }
2219 else
2220 {
2221 resultArray[i].setUConst(result);
2222 }
2223 break;
2224 }
2225 case EOpBitCount:
2226 {
2227 uint32_t value;
2228 if (getType().getBasicType() == EbtInt)
2229 {
2230 value = static_cast<uint32_t>(operandArray[i].getIConst());
2231 }
2232 else
2233 {
2234 ASSERT(getType().getBasicType() == EbtUInt);
2235 value = operandArray[i].getUConst();
2236 }
2237 int result = gl::BitCount(value);
2238 resultArray[i].setIConst(result);
2239 break;
2240 }
2241 case EOpFindLSB:
2242 {
2243 uint32_t value;
2244 if (getType().getBasicType() == EbtInt)
2245 {
2246 value = static_cast<uint32_t>(operandArray[i].getIConst());
2247 }
2248 else
2249 {
2250 ASSERT(getType().getBasicType() == EbtUInt);
2251 value = operandArray[i].getUConst();
2252 }
2253 resultArray[i].setIConst(gl::FindLSB(value));
2254 break;
2255 }
2256 case EOpFindMSB:
2257 {
2258 uint32_t value;
2259 if (getType().getBasicType() == EbtInt)
2260 {
2261 int intValue = operandArray[i].getIConst();
2262 value = static_cast<uint32_t>(intValue);
2263 if (intValue < 0)
2264 {
2265 // Look for zero instead of one in value. This also handles the intValue ==
2266 // -1 special case, where the return value needs to be -1.
2267 value = ~value;
2268 }
2269 }
2270 else
2271 {
2272 ASSERT(getType().getBasicType() == EbtUInt);
2273 value = operandArray[i].getUConst();
2274 }
2275 resultArray[i].setIConst(gl::FindMSB(value));
2276 break;
2277 }
Olli Etuahof119a262016-08-19 15:54:22 +03002278 case EOpDFdx:
2279 case EOpDFdy:
2280 case EOpFwidth:
2281 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole0c5409f2015-07-08 15:17:53 +05302282 // Derivatives of constant arguments should be 0.
2283 resultArray[i].setFConst(0.0f);
2284 break;
Arun Patole0c5409f2015-07-08 15:17:53 +05302285
Olli Etuahof119a262016-08-19 15:54:22 +03002286 default:
2287 return nullptr;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302288 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302289 }
Jamie Madillb1a85f42014-08-19 15:23:24 -04002290
Arun Patoleab2b9a22015-07-06 18:27:56 +05302291 return resultArray;
Jamie Madillb1a85f42014-08-19 15:23:24 -04002292}
2293
Olli Etuahof119a262016-08-19 15:54:22 +03002294void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter,
2295 FloatTypeUnaryFunc builtinFunc,
2296 TConstantUnion *result) const
Arun Patole9dea48f2015-04-02 11:45:09 +05302297{
2298 ASSERT(builtinFunc);
2299
Olli Etuahof119a262016-08-19 15:54:22 +03002300 ASSERT(getType().getBasicType() == EbtFloat);
2301 result->setFConst(builtinFunc(parameter.getFConst()));
Arun Patole9dea48f2015-04-02 11:45:09 +05302302}
2303
Jamie Madillb1a85f42014-08-19 15:23:24 -04002304// static
Olli Etuahof119a262016-08-19 15:54:22 +03002305TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate)
Olli Etuaho1d122782015-11-06 15:35:17 +02002306{
2307 ASSERT(aggregate->getSequence()->size() > 0u);
2308 size_t resultSize = aggregate->getType().getObjectSize();
2309 TConstantUnion *resultArray = new TConstantUnion[resultSize];
2310 TBasicType basicType = aggregate->getBasicType();
2311
2312 size_t resultIndex = 0u;
2313
2314 if (aggregate->getSequence()->size() == 1u)
2315 {
2316 TIntermNode *argument = aggregate->getSequence()->front();
2317 TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion();
2318 const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
2319 // Check the special case of constructing a matrix diagonal from a single scalar,
2320 // or a vector from a single scalar.
2321 if (argumentConstant->getType().getObjectSize() == 1u)
2322 {
2323 if (aggregate->isMatrix())
2324 {
2325 int resultCols = aggregate->getType().getCols();
2326 int resultRows = aggregate->getType().getRows();
2327 for (int col = 0; col < resultCols; ++col)
2328 {
2329 for (int row = 0; row < resultRows; ++row)
2330 {
2331 if (col == row)
2332 {
2333 resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
2334 }
2335 else
2336 {
2337 resultArray[resultIndex].setFConst(0.0f);
2338 }
2339 ++resultIndex;
2340 }
2341 }
2342 }
2343 else
2344 {
2345 while (resultIndex < resultSize)
2346 {
2347 resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
2348 ++resultIndex;
2349 }
2350 }
2351 ASSERT(resultIndex == resultSize);
2352 return resultArray;
2353 }
2354 else if (aggregate->isMatrix() && argumentConstant->isMatrix())
2355 {
2356 // The special case of constructing a matrix from a matrix.
2357 int argumentCols = argumentConstant->getType().getCols();
2358 int argumentRows = argumentConstant->getType().getRows();
2359 int resultCols = aggregate->getType().getCols();
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002360 int resultRows = aggregate->getType().getRows();
Olli Etuaho1d122782015-11-06 15:35:17 +02002361 for (int col = 0; col < resultCols; ++col)
2362 {
2363 for (int row = 0; row < resultRows; ++row)
2364 {
2365 if (col < argumentCols && row < argumentRows)
2366 {
2367 resultArray[resultIndex].cast(basicType,
2368 argumentUnionArray[col * argumentRows + row]);
2369 }
2370 else if (col == row)
2371 {
2372 resultArray[resultIndex].setFConst(1.0f);
2373 }
2374 else
2375 {
2376 resultArray[resultIndex].setFConst(0.0f);
2377 }
2378 ++resultIndex;
2379 }
2380 }
2381 ASSERT(resultIndex == resultSize);
2382 return resultArray;
2383 }
2384 }
2385
2386 for (TIntermNode *&argument : *aggregate->getSequence())
2387 {
2388 TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion();
2389 size_t argumentSize = argumentConstant->getType().getObjectSize();
2390 const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
2391 for (size_t i = 0u; i < argumentSize; ++i)
2392 {
2393 if (resultIndex >= resultSize)
2394 break;
2395 resultArray[resultIndex].cast(basicType, argumentUnionArray[i]);
2396 ++resultIndex;
2397 }
2398 }
2399 ASSERT(resultIndex == resultSize);
2400 return resultArray;
2401}
2402
2403// static
Olli Etuahof119a262016-08-19 15:54:22 +03002404TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate,
2405 TDiagnostics *diagnostics)
Arun Patole274f0702015-05-05 13:33:30 +05302406{
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002407 TOperator op = aggregate->getOp();
Arun Patole274f0702015-05-05 13:33:30 +05302408 TIntermSequence *sequence = aggregate->getSequence();
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002409 unsigned int paramsCount = static_cast<unsigned int>(sequence->size());
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002410 std::vector<const TConstantUnion *> unionArrays(paramsCount);
Arun Patole274f0702015-05-05 13:33:30 +05302411 std::vector<size_t> objectSizes(paramsCount);
Olli Etuahob43846e2015-06-02 18:18:57 +03002412 size_t maxObjectSize = 0;
Arun Patole274f0702015-05-05 13:33:30 +05302413 TBasicType basicType = EbtVoid;
2414 TSourceLoc loc;
2415 for (unsigned int i = 0; i < paramsCount; i++)
2416 {
2417 TIntermConstantUnion *paramConstant = (*sequence)[i]->getAsConstantUnion();
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002418 ASSERT(paramConstant != nullptr); // Should be checked already.
Arun Patole274f0702015-05-05 13:33:30 +05302419
2420 if (i == 0)
2421 {
2422 basicType = paramConstant->getType().getBasicType();
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002423 loc = paramConstant->getLine();
Arun Patole274f0702015-05-05 13:33:30 +05302424 }
2425 unionArrays[i] = paramConstant->getUnionArrayPointer();
2426 objectSizes[i] = paramConstant->getType().getObjectSize();
Olli Etuahob43846e2015-06-02 18:18:57 +03002427 if (objectSizes[i] > maxObjectSize)
2428 maxObjectSize = objectSizes[i];
Arun Patole274f0702015-05-05 13:33:30 +05302429 }
2430
Olli Etuahod5da5052016-08-29 13:16:55 +03002431 if (!(*sequence)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct)
Arun Patole7fa33552015-06-10 15:15:18 +05302432 {
2433 for (unsigned int i = 0; i < paramsCount; i++)
2434 if (objectSizes[i] != maxObjectSize)
2435 unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize);
2436 }
Arun Patole274f0702015-05-05 13:33:30 +05302437
Olli Etuahob43846e2015-06-02 18:18:57 +03002438 TConstantUnion *resultArray = nullptr;
Olli Etuaho51182ab2017-01-22 00:12:29 +00002439
2440 switch (op)
Arun Patole274f0702015-05-05 13:33:30 +05302441 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002442 case EOpAtan:
Arun Patole274f0702015-05-05 13:33:30 +05302443 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002444 ASSERT(basicType == EbtFloat);
2445 resultArray = new TConstantUnion[maxObjectSize];
2446 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302447 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002448 float y = unionArrays[0][i].getFConst();
2449 float x = unionArrays[1][i].getFConst();
2450 // Results are undefined if x and y are both 0.
2451 if (x == 0.0f && y == 0.0f)
2452 UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
2453 else
2454 resultArray[i].setFConst(atan2f(y, x));
Arun Patolebf790422015-05-18 17:53:04 +05302455 }
Olli Etuaho51182ab2017-01-22 00:12:29 +00002456 break;
2457 }
Arun Patolebf790422015-05-18 17:53:04 +05302458
Olli Etuaho51182ab2017-01-22 00:12:29 +00002459 case EOpPow:
2460 {
2461 ASSERT(basicType == EbtFloat);
2462 resultArray = new TConstantUnion[maxObjectSize];
2463 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302464 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002465 float x = unionArrays[0][i].getFConst();
2466 float y = unionArrays[1][i].getFConst();
2467 // Results are undefined if x < 0.
2468 // Results are undefined if x = 0 and y <= 0.
2469 if (x < 0.0f)
2470 UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
2471 else if (x == 0.0f && y <= 0.0f)
2472 UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
2473 else
2474 resultArray[i].setFConst(powf(x, y));
Arun Patolebf790422015-05-18 17:53:04 +05302475 }
Olli Etuaho51182ab2017-01-22 00:12:29 +00002476 break;
2477 }
Arun Patolebf790422015-05-18 17:53:04 +05302478
Olli Etuaho51182ab2017-01-22 00:12:29 +00002479 case EOpMod:
2480 {
2481 ASSERT(basicType == EbtFloat);
2482 resultArray = new TConstantUnion[maxObjectSize];
2483 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302484 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002485 float x = unionArrays[0][i].getFConst();
2486 float y = unionArrays[1][i].getFConst();
2487 resultArray[i].setFConst(x - y * floorf(x / y));
Arun Patolebf790422015-05-18 17:53:04 +05302488 }
Olli Etuaho51182ab2017-01-22 00:12:29 +00002489 break;
2490 }
Arun Patolebf790422015-05-18 17:53:04 +05302491
Olli Etuaho51182ab2017-01-22 00:12:29 +00002492 case EOpMin:
2493 {
2494 resultArray = new TConstantUnion[maxObjectSize];
2495 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patole274f0702015-05-05 13:33:30 +05302496 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002497 switch (basicType)
Arun Patole274f0702015-05-05 13:33:30 +05302498 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002499 case EbtFloat:
2500 resultArray[i].setFConst(
2501 std::min(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
2502 break;
2503 case EbtInt:
2504 resultArray[i].setIConst(
2505 std::min(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
2506 break;
2507 case EbtUInt:
2508 resultArray[i].setUConst(
2509 std::min(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
2510 break;
2511 default:
2512 UNREACHABLE();
2513 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302514 }
2515 }
2516 break;
Arun Patole274f0702015-05-05 13:33:30 +05302517 }
Olli Etuaho51182ab2017-01-22 00:12:29 +00002518
2519 case EOpMax:
Arun Patole274f0702015-05-05 13:33:30 +05302520 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002521 resultArray = new TConstantUnion[maxObjectSize];
2522 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patole274f0702015-05-05 13:33:30 +05302523 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002524 switch (basicType)
Arun Patole274f0702015-05-05 13:33:30 +05302525 {
Olli Etuaho51182ab2017-01-22 00:12:29 +00002526 case EbtFloat:
2527 resultArray[i].setFConst(
2528 std::max(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
2529 break;
2530 case EbtInt:
2531 resultArray[i].setIConst(
2532 std::max(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
2533 break;
2534 case EbtUInt:
2535 resultArray[i].setUConst(
2536 std::max(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
2537 break;
2538 default:
2539 UNREACHABLE();
2540 break;
Arun Patole274f0702015-05-05 13:33:30 +05302541 }
2542 }
Olli Etuaho51182ab2017-01-22 00:12:29 +00002543 break;
Arun Patole274f0702015-05-05 13:33:30 +05302544 }
Olli Etuaho51182ab2017-01-22 00:12:29 +00002545
2546 case EOpStep:
2547 {
2548 ASSERT(basicType == EbtFloat);
2549 resultArray = new TConstantUnion[maxObjectSize];
2550 for (size_t i = 0; i < maxObjectSize; i++)
2551 resultArray[i].setFConst(
2552 unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f : 1.0f);
2553 break;
2554 }
2555
2556 case EOpLessThanComponentWise:
2557 {
2558 resultArray = new TConstantUnion[maxObjectSize];
2559 for (size_t i = 0; i < maxObjectSize; i++)
2560 {
2561 switch (basicType)
2562 {
2563 case EbtFloat:
2564 resultArray[i].setBConst(unionArrays[0][i].getFConst() <
2565 unionArrays[1][i].getFConst());
2566 break;
2567 case EbtInt:
2568 resultArray[i].setBConst(unionArrays[0][i].getIConst() <
2569 unionArrays[1][i].getIConst());
2570 break;
2571 case EbtUInt:
2572 resultArray[i].setBConst(unionArrays[0][i].getUConst() <
2573 unionArrays[1][i].getUConst());
2574 break;
2575 default:
2576 UNREACHABLE();
2577 break;
2578 }
2579 }
2580 break;
2581 }
2582
2583 case EOpLessThanEqualComponentWise:
2584 {
2585 resultArray = new TConstantUnion[maxObjectSize];
2586 for (size_t i = 0; i < maxObjectSize; i++)
2587 {
2588 switch (basicType)
2589 {
2590 case EbtFloat:
2591 resultArray[i].setBConst(unionArrays[0][i].getFConst() <=
2592 unionArrays[1][i].getFConst());
2593 break;
2594 case EbtInt:
2595 resultArray[i].setBConst(unionArrays[0][i].getIConst() <=
2596 unionArrays[1][i].getIConst());
2597 break;
2598 case EbtUInt:
2599 resultArray[i].setBConst(unionArrays[0][i].getUConst() <=
2600 unionArrays[1][i].getUConst());
2601 break;
2602 default:
2603 UNREACHABLE();
2604 break;
2605 }
2606 }
2607 break;
2608 }
2609
2610 case EOpGreaterThanComponentWise:
2611 {
2612 resultArray = new TConstantUnion[maxObjectSize];
2613 for (size_t i = 0; i < maxObjectSize; i++)
2614 {
2615 switch (basicType)
2616 {
2617 case EbtFloat:
2618 resultArray[i].setBConst(unionArrays[0][i].getFConst() >
2619 unionArrays[1][i].getFConst());
2620 break;
2621 case EbtInt:
2622 resultArray[i].setBConst(unionArrays[0][i].getIConst() >
2623 unionArrays[1][i].getIConst());
2624 break;
2625 case EbtUInt:
2626 resultArray[i].setBConst(unionArrays[0][i].getUConst() >
2627 unionArrays[1][i].getUConst());
2628 break;
2629 default:
2630 UNREACHABLE();
2631 break;
2632 }
2633 }
2634 break;
2635 }
2636 case EOpGreaterThanEqualComponentWise:
2637 {
2638 resultArray = new TConstantUnion[maxObjectSize];
2639 for (size_t i = 0; i < maxObjectSize; i++)
2640 {
2641 switch (basicType)
2642 {
2643 case EbtFloat:
2644 resultArray[i].setBConst(unionArrays[0][i].getFConst() >=
2645 unionArrays[1][i].getFConst());
2646 break;
2647 case EbtInt:
2648 resultArray[i].setBConst(unionArrays[0][i].getIConst() >=
2649 unionArrays[1][i].getIConst());
2650 break;
2651 case EbtUInt:
2652 resultArray[i].setBConst(unionArrays[0][i].getUConst() >=
2653 unionArrays[1][i].getUConst());
2654 break;
2655 default:
2656 UNREACHABLE();
2657 break;
2658 }
2659 }
2660 }
2661 break;
2662
2663 case EOpEqualComponentWise:
2664 {
2665 resultArray = new TConstantUnion[maxObjectSize];
2666 for (size_t i = 0; i < maxObjectSize; i++)
2667 {
2668 switch (basicType)
2669 {
2670 case EbtFloat:
2671 resultArray[i].setBConst(unionArrays[0][i].getFConst() ==
2672 unionArrays[1][i].getFConst());
2673 break;
2674 case EbtInt:
2675 resultArray[i].setBConst(unionArrays[0][i].getIConst() ==
2676 unionArrays[1][i].getIConst());
2677 break;
2678 case EbtUInt:
2679 resultArray[i].setBConst(unionArrays[0][i].getUConst() ==
2680 unionArrays[1][i].getUConst());
2681 break;
2682 case EbtBool:
2683 resultArray[i].setBConst(unionArrays[0][i].getBConst() ==
2684 unionArrays[1][i].getBConst());
2685 break;
2686 default:
2687 UNREACHABLE();
2688 break;
2689 }
2690 }
2691 break;
2692 }
2693
2694 case EOpNotEqualComponentWise:
2695 {
2696 resultArray = new TConstantUnion[maxObjectSize];
2697 for (size_t i = 0; i < maxObjectSize; i++)
2698 {
2699 switch (basicType)
2700 {
2701 case EbtFloat:
2702 resultArray[i].setBConst(unionArrays[0][i].getFConst() !=
2703 unionArrays[1][i].getFConst());
2704 break;
2705 case EbtInt:
2706 resultArray[i].setBConst(unionArrays[0][i].getIConst() !=
2707 unionArrays[1][i].getIConst());
2708 break;
2709 case EbtUInt:
2710 resultArray[i].setBConst(unionArrays[0][i].getUConst() !=
2711 unionArrays[1][i].getUConst());
2712 break;
2713 case EbtBool:
2714 resultArray[i].setBConst(unionArrays[0][i].getBConst() !=
2715 unionArrays[1][i].getBConst());
2716 break;
2717 default:
2718 UNREACHABLE();
2719 break;
2720 }
2721 }
2722 break;
2723 }
2724
2725 case EOpDistance:
2726 {
2727 ASSERT(basicType == EbtFloat);
2728 TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize];
2729 resultArray = new TConstantUnion();
2730 for (size_t i = 0; i < maxObjectSize; i++)
2731 {
2732 float x = unionArrays[0][i].getFConst();
2733 float y = unionArrays[1][i].getFConst();
2734 distanceArray[i].setFConst(x - y);
2735 }
2736 resultArray->setFConst(VectorLength(distanceArray, maxObjectSize));
2737 break;
2738 }
2739
2740 case EOpDot:
2741 ASSERT(basicType == EbtFloat);
2742 resultArray = new TConstantUnion();
2743 resultArray->setFConst(VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize));
2744 break;
2745
2746 case EOpCross:
2747 {
2748 ASSERT(basicType == EbtFloat && maxObjectSize == 3);
2749 resultArray = new TConstantUnion[maxObjectSize];
2750 float x0 = unionArrays[0][0].getFConst();
2751 float x1 = unionArrays[0][1].getFConst();
2752 float x2 = unionArrays[0][2].getFConst();
2753 float y0 = unionArrays[1][0].getFConst();
2754 float y1 = unionArrays[1][1].getFConst();
2755 float y2 = unionArrays[1][2].getFConst();
2756 resultArray[0].setFConst(x1 * y2 - y1 * x2);
2757 resultArray[1].setFConst(x2 * y0 - y2 * x0);
2758 resultArray[2].setFConst(x0 * y1 - y0 * x1);
2759 break;
2760 }
2761
2762 case EOpReflect:
2763 {
2764 ASSERT(basicType == EbtFloat);
2765 // genType reflect (genType I, genType N) :
2766 // For the incident vector I and surface orientation N, returns the reflection
2767 // direction:
2768 // I - 2 * dot(N, I) * N.
2769 resultArray = new TConstantUnion[maxObjectSize];
2770 float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
2771 for (size_t i = 0; i < maxObjectSize; i++)
2772 {
2773 float result = unionArrays[0][i].getFConst() -
2774 2.0f * dotProduct * unionArrays[1][i].getFConst();
2775 resultArray[i].setFConst(result);
2776 }
2777 break;
2778 }
2779
2780 case EOpMulMatrixComponentWise:
2781 {
2782 ASSERT(basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() &&
2783 (*sequence)[1]->getAsTyped()->isMatrix());
2784 // Perform component-wise matrix multiplication.
2785 resultArray = new TConstantUnion[maxObjectSize];
2786 int size = (*sequence)[0]->getAsTyped()->getNominalSize();
2787 angle::Matrix<float> result =
2788 GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size));
2789 SetUnionArrayFromMatrix(result, resultArray);
2790 break;
2791 }
2792
2793 case EOpOuterProduct:
2794 {
2795 ASSERT(basicType == EbtFloat);
2796 size_t numRows = (*sequence)[0]->getAsTyped()->getType().getObjectSize();
2797 size_t numCols = (*sequence)[1]->getAsTyped()->getType().getObjectSize();
2798 resultArray = new TConstantUnion[numRows * numCols];
2799 angle::Matrix<float> result =
2800 GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
2801 .outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols)));
2802 SetUnionArrayFromMatrix(result, resultArray);
2803 break;
2804 }
2805
2806 case EOpClamp:
2807 {
2808 resultArray = new TConstantUnion[maxObjectSize];
2809 for (size_t i = 0; i < maxObjectSize; i++)
2810 {
2811 switch (basicType)
2812 {
2813 case EbtFloat:
2814 {
2815 float x = unionArrays[0][i].getFConst();
2816 float min = unionArrays[1][i].getFConst();
2817 float max = unionArrays[2][i].getFConst();
2818 // Results are undefined if min > max.
2819 if (min > max)
2820 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2821 &resultArray[i]);
2822 else
2823 resultArray[i].setFConst(gl::clamp(x, min, max));
2824 break;
2825 }
2826
2827 case EbtInt:
2828 {
2829 int x = unionArrays[0][i].getIConst();
2830 int min = unionArrays[1][i].getIConst();
2831 int max = unionArrays[2][i].getIConst();
2832 // Results are undefined if min > max.
2833 if (min > max)
2834 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2835 &resultArray[i]);
2836 else
2837 resultArray[i].setIConst(gl::clamp(x, min, max));
2838 break;
2839 }
2840 case EbtUInt:
2841 {
2842 unsigned int x = unionArrays[0][i].getUConst();
2843 unsigned int min = unionArrays[1][i].getUConst();
2844 unsigned int max = unionArrays[2][i].getUConst();
2845 // Results are undefined if min > max.
2846 if (min > max)
2847 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2848 &resultArray[i]);
2849 else
2850 resultArray[i].setUConst(gl::clamp(x, min, max));
2851 break;
2852 }
2853 default:
2854 UNREACHABLE();
2855 break;
2856 }
2857 }
2858 break;
2859 }
2860
2861 case EOpMix:
2862 {
2863 ASSERT(basicType == EbtFloat);
2864 resultArray = new TConstantUnion[maxObjectSize];
2865 for (size_t i = 0; i < maxObjectSize; i++)
2866 {
2867 float x = unionArrays[0][i].getFConst();
2868 float y = unionArrays[1][i].getFConst();
2869 TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType();
2870 if (type == EbtFloat)
2871 {
2872 // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
2873 float a = unionArrays[2][i].getFConst();
2874 resultArray[i].setFConst(x * (1.0f - a) + y * a);
2875 }
2876 else // 3rd parameter is EbtBool
2877 {
2878 ASSERT(type == EbtBool);
2879 // Selects which vector each returned component comes from.
2880 // For a component of a that is false, the corresponding component of x is
2881 // returned.
2882 // For a component of a that is true, the corresponding component of y is
2883 // returned.
2884 bool a = unionArrays[2][i].getBConst();
2885 resultArray[i].setFConst(a ? y : x);
2886 }
2887 }
2888 break;
2889 }
2890
2891 case EOpSmoothStep:
2892 {
2893 ASSERT(basicType == EbtFloat);
2894 resultArray = new TConstantUnion[maxObjectSize];
2895 for (size_t i = 0; i < maxObjectSize; i++)
2896 {
2897 float edge0 = unionArrays[0][i].getFConst();
2898 float edge1 = unionArrays[1][i].getFConst();
2899 float x = unionArrays[2][i].getFConst();
2900 // Results are undefined if edge0 >= edge1.
2901 if (edge0 >= edge1)
2902 {
2903 UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
2904 }
2905 else
2906 {
2907 // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth
2908 // Hermite interpolation between 0 and 1 when edge0 < x < edge1.
2909 float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
2910 resultArray[i].setFConst(t * t * (3.0f - 2.0f * t));
2911 }
2912 }
2913 break;
2914 }
2915
2916 case EOpFaceForward:
2917 {
2918 ASSERT(basicType == EbtFloat);
2919 // genType faceforward(genType N, genType I, genType Nref) :
2920 // If dot(Nref, I) < 0 return N, otherwise return -N.
2921 resultArray = new TConstantUnion[maxObjectSize];
2922 float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize);
2923 for (size_t i = 0; i < maxObjectSize; i++)
2924 {
2925 if (dotProduct < 0)
2926 resultArray[i].setFConst(unionArrays[0][i].getFConst());
2927 else
2928 resultArray[i].setFConst(-unionArrays[0][i].getFConst());
2929 }
2930 break;
2931 }
2932
2933 case EOpRefract:
2934 {
2935 ASSERT(basicType == EbtFloat);
2936 // genType refract(genType I, genType N, float eta) :
2937 // For the incident vector I and surface normal N, and the ratio of indices of
2938 // refraction eta,
2939 // return the refraction vector. The result is computed by
2940 // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
2941 // if (k < 0.0)
2942 // return genType(0.0)
2943 // else
2944 // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
2945 resultArray = new TConstantUnion[maxObjectSize];
2946 float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
2947 for (size_t i = 0; i < maxObjectSize; i++)
2948 {
2949 float eta = unionArrays[2][i].getFConst();
2950 float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct);
2951 if (k < 0.0f)
2952 resultArray[i].setFConst(0.0f);
2953 else
2954 resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() -
2955 (eta * dotProduct + sqrtf(k)) *
2956 unionArrays[1][i].getFConst());
2957 }
2958 break;
2959 }
Olli Etuaho9250cb22017-01-21 10:51:27 +00002960 case EOpBitfieldExtract:
2961 {
2962 resultArray = new TConstantUnion[maxObjectSize];
2963 for (size_t i = 0; i < maxObjectSize; ++i)
2964 {
2965 int offset = unionArrays[1][0].getIConst();
2966 int bits = unionArrays[2][0].getIConst();
2967 if (bits == 0)
2968 {
2969 if (aggregate->getBasicType() == EbtInt)
2970 {
2971 resultArray[i].setIConst(0);
2972 }
2973 else
2974 {
2975 ASSERT(aggregate->getBasicType() == EbtUInt);
2976 resultArray[i].setUConst(0);
2977 }
2978 }
2979 else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32)
2980 {
2981 UndefinedConstantFoldingError(loc, op, aggregate->getBasicType(), diagnostics,
2982 &resultArray[i]);
2983 }
2984 else
2985 {
2986 // bits can be 32 here, so we need to avoid bit shift overflow.
2987 uint32_t maskMsb = 1u << (bits - 1);
2988 uint32_t mask = ((maskMsb - 1u) | maskMsb) << offset;
2989 if (aggregate->getBasicType() == EbtInt)
2990 {
2991 uint32_t value = static_cast<uint32_t>(unionArrays[0][i].getIConst());
2992 uint32_t resultUnsigned = (value & mask) >> offset;
2993 if ((resultUnsigned & maskMsb) != 0)
2994 {
2995 // The most significant bits (from bits+1 to the most significant bit)
2996 // should be set to 1.
2997 uint32_t higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;
2998 resultUnsigned |= higherBitsMask;
2999 }
3000 resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned));
3001 }
3002 else
3003 {
3004 ASSERT(aggregate->getBasicType() == EbtUInt);
3005 uint32_t value = unionArrays[0][i].getUConst();
3006 resultArray[i].setUConst((value & mask) >> offset);
3007 }
3008 }
3009 }
3010 break;
3011 }
3012 case EOpBitfieldInsert:
3013 {
3014 resultArray = new TConstantUnion[maxObjectSize];
3015 for (size_t i = 0; i < maxObjectSize; ++i)
3016 {
3017 int offset = unionArrays[2][0].getIConst();
3018 int bits = unionArrays[3][0].getIConst();
3019 if (bits == 0)
3020 {
3021 if (aggregate->getBasicType() == EbtInt)
3022 {
3023 int32_t base = unionArrays[0][i].getIConst();
3024 resultArray[i].setIConst(base);
3025 }
3026 else
3027 {
3028 ASSERT(aggregate->getBasicType() == EbtUInt);
3029 uint32_t base = unionArrays[0][i].getUConst();
3030 resultArray[i].setUConst(base);
3031 }
3032 }
3033 else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32)
3034 {
3035 UndefinedConstantFoldingError(loc, op, aggregate->getBasicType(), diagnostics,
3036 &resultArray[i]);
3037 }
3038 else
3039 {
3040 // bits can be 32 here, so we need to avoid bit shift overflow.
3041 uint32_t maskMsb = 1u << (bits - 1);
3042 uint32_t insertMask = ((maskMsb - 1u) | maskMsb) << offset;
3043 uint32_t baseMask = ~insertMask;
3044 if (aggregate->getBasicType() == EbtInt)
3045 {
3046 uint32_t base = static_cast<uint32_t>(unionArrays[0][i].getIConst());
3047 uint32_t insert = static_cast<uint32_t>(unionArrays[1][i].getIConst());
3048 uint32_t resultUnsigned =
3049 (base & baseMask) | ((insert << offset) & insertMask);
3050 resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned));
3051 }
3052 else
3053 {
3054 ASSERT(aggregate->getBasicType() == EbtUInt);
3055 uint32_t base = unionArrays[0][i].getUConst();
3056 uint32_t insert = unionArrays[1][i].getUConst();
3057 resultArray[i].setUConst((base & baseMask) |
3058 ((insert << offset) & insertMask));
3059 }
3060 }
3061 }
3062 break;
3063 }
Olli Etuaho51182ab2017-01-22 00:12:29 +00003064
3065 default:
3066 UNREACHABLE();
3067 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +05303068 }
Olli Etuahob43846e2015-06-02 18:18:57 +03003069 return resultArray;
Arun Patole274f0702015-05-05 13:33:30 +05303070}
3071
3072// static
Jamie Madillb1a85f42014-08-19 15:23:24 -04003073TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction)
3074{
3075 if (hashFunction == NULL || name.empty())
3076 return name;
3077 khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
3078 TStringStream stream;
3079 stream << HASHED_NAME_PREFIX << std::hex << number;
3080 TString hashedName = stream.str();
3081 return hashedName;
3082}
Olli Etuaho853dc1a2014-11-06 17:25:48 +02003083
3084void TIntermTraverser::updateTree()
3085{
Olli Etuahoa6f22092015-05-08 18:31:10 +03003086 for (size_t ii = 0; ii < mInsertions.size(); ++ii)
3087 {
3088 const NodeInsertMultipleEntry &insertion = mInsertions[ii];
3089 ASSERT(insertion.parent);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03003090 if (!insertion.insertionsAfter.empty())
3091 {
3092 bool inserted = insertion.parent->insertChildNodes(insertion.position + 1,
3093 insertion.insertionsAfter);
3094 ASSERT(inserted);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03003095 }
3096 if (!insertion.insertionsBefore.empty())
3097 {
3098 bool inserted =
3099 insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore);
3100 ASSERT(inserted);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03003101 }
Olli Etuahoa6f22092015-05-08 18:31:10 +03003102 }
Olli Etuaho853dc1a2014-11-06 17:25:48 +02003103 for (size_t ii = 0; ii < mReplacements.size(); ++ii)
3104 {
Olli Etuahocd94ef92015-04-16 19:18:10 +03003105 const NodeUpdateEntry &replacement = mReplacements[ii];
3106 ASSERT(replacement.parent);
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003107 bool replaced =
3108 replacement.parent->replaceChildNode(replacement.original, replacement.replacement);
Olli Etuaho853dc1a2014-11-06 17:25:48 +02003109 ASSERT(replaced);
3110
Olli Etuahocd94ef92015-04-16 19:18:10 +03003111 if (!replacement.originalBecomesChildOfReplacement)
Olli Etuaho853dc1a2014-11-06 17:25:48 +02003112 {
3113 // In AST traversing, a parent is visited before its children.
Olli Etuahocd94ef92015-04-16 19:18:10 +03003114 // After we replace a node, if its immediate child is to
Olli Etuaho853dc1a2014-11-06 17:25:48 +02003115 // be replaced, we need to make sure we don't update the replaced
3116 // node; instead, we update the replacement node.
3117 for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj)
3118 {
Olli Etuahocd94ef92015-04-16 19:18:10 +03003119 NodeUpdateEntry &replacement2 = mReplacements[jj];
3120 if (replacement2.parent == replacement.original)
3121 replacement2.parent = replacement.replacement;
Olli Etuaho853dc1a2014-11-06 17:25:48 +02003122 }
3123 }
3124 }
Olli Etuahofc0e2bc2015-04-16 13:39:56 +03003125 for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii)
3126 {
3127 const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii];
3128 ASSERT(replacement.parent);
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003129 bool replaced = replacement.parent->replaceChildNodeWithMultiple(replacement.original,
3130 replacement.replacements);
Olli Etuahofc0e2bc2015-04-16 13:39:56 +03003131 ASSERT(replaced);
3132 }
Olli Etuahod4f303e2015-05-20 17:09:06 +03003133
Jamie Madill03d863c2016-07-27 18:15:53 -04003134 clearReplacementQueue();
3135}
3136
3137void TIntermTraverser::clearReplacementQueue()
3138{
Olli Etuahod4f303e2015-05-20 17:09:06 +03003139 mReplacements.clear();
3140 mMultiReplacements.clear();
Jamie Madill03d863c2016-07-27 18:15:53 -04003141 mInsertions.clear();
Olli Etuaho853dc1a2014-11-06 17:25:48 +02003142}
Jamie Madill1048e432016-07-23 18:51:28 -04003143
Jamie Madill03d863c2016-07-27 18:15:53 -04003144void TIntermTraverser::queueReplacement(TIntermNode *original,
3145 TIntermNode *replacement,
3146 OriginalNode originalStatus)
Jamie Madill1048e432016-07-23 18:51:28 -04003147{
Jamie Madill03d863c2016-07-27 18:15:53 -04003148 queueReplacementWithParent(getParentNode(), original, replacement, originalStatus);
Jamie Madill1048e432016-07-23 18:51:28 -04003149}
3150
Jamie Madill03d863c2016-07-27 18:15:53 -04003151void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent,
3152 TIntermNode *original,
3153 TIntermNode *replacement,
3154 OriginalNode originalStatus)
Jamie Madill1048e432016-07-23 18:51:28 -04003155{
Jamie Madill03d863c2016-07-27 18:15:53 -04003156 bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD);
3157 mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild));
Jamie Madill1048e432016-07-23 18:51:28 -04003158}
Jamie Madill45bcc782016-11-07 13:58:48 -05003159
3160} // namespace sh