blob: ca0e59e1919e154833b8858673a393dc66fac73f [file] [log] [blame]
John Bauman66b8ab22014-05-06 15:57:45 -04001//
John Baumand4ae8632014-05-06 16:18:33 -04002// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
John Bauman66b8ab22014-05-06 15:57:45 -04003// 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>
13#include <algorithm>
14
Nicolas Capenscc863da2015-01-21 15:50:55 -050015#include "localintermediate.h"
16#include "SymbolTable.h"
Alexis Hetu2ce222c2016-05-02 11:20:52 -040017#include "Common/Math.hpp"
John Bauman66b8ab22014-05-06 15:57:45 -040018
19bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
20
21static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){
22 return left > right ? left : right;
23}
24
Alexis Hetu00106d42015-04-23 11:45:35 -040025static bool ValidateMultiplication(TOperator op, const TType &left, const TType &right)
26{
27 switch(op)
28 {
29 case EOpMul:
30 case EOpMulAssign:
31 return left.getNominalSize() == right.getNominalSize() &&
32 left.getSecondarySize() == right.getSecondarySize();
33 case EOpVectorTimesScalar:
34 case EOpVectorTimesScalarAssign:
35 return true;
36 case EOpVectorTimesMatrix:
37 return left.getNominalSize() == right.getSecondarySize();
38 case EOpVectorTimesMatrixAssign:
39 return left.getNominalSize() == right.getSecondarySize() &&
40 left.getNominalSize() == right.getNominalSize();
41 case EOpMatrixTimesVector:
42 return left.getNominalSize() == right.getNominalSize();
43 case EOpMatrixTimesScalar:
44 case EOpMatrixTimesScalarAssign:
45 return true;
46 case EOpMatrixTimesMatrix:
47 return left.getNominalSize() == right.getSecondarySize();
48 case EOpMatrixTimesMatrixAssign:
49 return left.getNominalSize() == right.getNominalSize() &&
50 left.getSecondarySize() == right.getSecondarySize();
51 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -040052 UNREACHABLE(op);
Alexis Hetu00106d42015-04-23 11:45:35 -040053 return false;
54 }
55}
56
John Bauman66b8ab22014-05-06 15:57:45 -040057const char* getOperatorString(TOperator op) {
58 switch (op) {
59 case EOpInitialize: return "=";
60 case EOpAssign: return "=";
61 case EOpAddAssign: return "+=";
62 case EOpSubAssign: return "-=";
63 case EOpDivAssign: return "/=";
Alexis Hetu17809052015-05-13 11:28:22 -040064 case EOpIModAssign: return "%=";
65 case EOpBitShiftLeftAssign: return "<<=";
66 case EOpBitShiftRightAssign: return ">>=";
67 case EOpBitwiseAndAssign: return "&=";
68 case EOpBitwiseXorAssign: return "^=";
69 case EOpBitwiseOrAssign: return "|=";
John Bauman66b8ab22014-05-06 15:57:45 -040070
71 // Fall-through.
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -040072 case EOpMulAssign:
John Bauman66b8ab22014-05-06 15:57:45 -040073 case EOpVectorTimesMatrixAssign:
74 case EOpVectorTimesScalarAssign:
75 case EOpMatrixTimesScalarAssign:
76 case EOpMatrixTimesMatrixAssign: return "*=";
77
78 // Fall-through.
79 case EOpIndexDirect:
80 case EOpIndexIndirect: return "[]";
81
82 case EOpIndexDirectStruct: return ".";
83 case EOpVectorSwizzle: return ".";
84 case EOpAdd: return "+";
85 case EOpSub: return "-";
86 case EOpMul: return "*";
87 case EOpDiv: return "/";
88 case EOpMod: UNIMPLEMENTED(); break;
89 case EOpEqual: return "==";
90 case EOpNotEqual: return "!=";
91 case EOpLessThan: return "<";
92 case EOpGreaterThan: return ">";
93 case EOpLessThanEqual: return "<=";
94 case EOpGreaterThanEqual: return ">=";
95
96 // Fall-through.
97 case EOpVectorTimesScalar:
98 case EOpVectorTimesMatrix:
99 case EOpMatrixTimesVector:
100 case EOpMatrixTimesScalar:
101 case EOpMatrixTimesMatrix: return "*";
102
103 case EOpLogicalOr: return "||";
104 case EOpLogicalXor: return "^^";
105 case EOpLogicalAnd: return "&&";
Alexis Hetu17809052015-05-13 11:28:22 -0400106 case EOpIMod: return "%";
107 case EOpBitShiftLeft: return "<<";
108 case EOpBitShiftRight: return ">>";
109 case EOpBitwiseAnd: return "&";
110 case EOpBitwiseXor: return "^";
111 case EOpBitwiseOr: return "|";
John Bauman66b8ab22014-05-06 15:57:45 -0400112 case EOpNegative: return "-";
113 case EOpVectorLogicalNot: return "not";
114 case EOpLogicalNot: return "!";
Alexis Hetu17809052015-05-13 11:28:22 -0400115 case EOpBitwiseNot: return "~";
John Bauman66b8ab22014-05-06 15:57:45 -0400116 case EOpPostIncrement: return "++";
117 case EOpPostDecrement: return "--";
118 case EOpPreIncrement: return "++";
119 case EOpPreDecrement: return "--";
120
John Bauman66b8ab22014-05-06 15:57:45 -0400121 case EOpRadians: return "radians";
122 case EOpDegrees: return "degrees";
123 case EOpSin: return "sin";
124 case EOpCos: return "cos";
125 case EOpTan: return "tan";
126 case EOpAsin: return "asin";
127 case EOpAcos: return "acos";
128 case EOpAtan: return "atan";
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400129 case EOpSinh: return "sinh";
130 case EOpCosh: return "cosh";
131 case EOpTanh: return "tanh";
132 case EOpAsinh: return "asinh";
133 case EOpAcosh: return "acosh";
134 case EOpAtanh: return "atanh";
John Bauman66b8ab22014-05-06 15:57:45 -0400135 case EOpExp: return "exp";
136 case EOpLog: return "log";
137 case EOpExp2: return "exp2";
138 case EOpLog2: return "log2";
139 case EOpSqrt: return "sqrt";
140 case EOpInverseSqrt: return "inversesqrt";
141 case EOpAbs: return "abs";
142 case EOpSign: return "sign";
143 case EOpFloor: return "floor";
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400144 case EOpTrunc: return "trunc";
145 case EOpRound: return "round";
146 case EOpRoundEven: return "roundEven";
John Bauman66b8ab22014-05-06 15:57:45 -0400147 case EOpCeil: return "ceil";
148 case EOpFract: return "fract";
149 case EOpLength: return "length";
150 case EOpNormalize: return "normalize";
151 case EOpDFdx: return "dFdx";
152 case EOpDFdy: return "dFdy";
153 case EOpFwidth: return "fwidth";
154 case EOpAny: return "any";
155 case EOpAll: return "all";
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400156 case EOpIsNan: return "isnan";
157 case EOpIsInf: return "isinf";
Alexis Hetu3815b6c2015-05-27 11:21:37 -0400158 case EOpOuterProduct: return "outerProduct";
159 case EOpTranspose: return "transpose";
160 case EOpDeterminant: return "determinant";
161 case EOpInverse: return "inverse";
John Bauman66b8ab22014-05-06 15:57:45 -0400162
163 default: break;
164 }
165 return "";
166}
167
168////////////////////////////////////////////////////////////////////////////
169//
170// First set of functions are to help build the intermediate representation.
171// These functions are not member functions of the nodes.
172// They are called from parser productions.
173//
174/////////////////////////////////////////////////////////////////////////////
175
176//
177// Add a terminal node for an identifier in an expression.
178//
179// Returns the added node.
180//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400181TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400182{
183 TIntermSymbol* node = new TIntermSymbol(id, name, type);
184 node->setLine(line);
185
186 return node;
187}
188
189//
190// Connect two nodes with a new parent that does a binary operation on the nodes.
191//
192// Returns the added node.
193//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400194TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400195{
Alexis Hetu92ab1982015-08-18 15:28:27 -0400196 bool isBitShift = false;
John Bauman66b8ab22014-05-06 15:57:45 -0400197 switch (op) {
198 case EOpEqual:
199 case EOpNotEqual:
200 if (left->isArray())
201 return 0;
202 break;
203 case EOpLessThan:
204 case EOpGreaterThan:
205 case EOpLessThanEqual:
206 case EOpGreaterThanEqual:
207 if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
208 return 0;
209 }
210 break;
211 case EOpLogicalOr:
212 case EOpLogicalXor:
213 case EOpLogicalAnd:
214 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
215 return 0;
216 }
217 break;
Alexis Hetud061e422015-05-13 16:37:50 -0400218 case EOpBitwiseOr:
219 case EOpBitwiseXor:
220 case EOpBitwiseAnd:
Alexis Hetu9085c8d2015-06-01 13:48:07 -0400221 if (!IsInteger(left->getBasicType()) || left->isMatrix() || left->isArray()) {
Alexis Hetud061e422015-05-13 16:37:50 -0400222 return 0;
223 }
224 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400225 case EOpAdd:
226 case EOpSub:
227 case EOpDiv:
228 case EOpMul:
Alexis Hetud061e422015-05-13 16:37:50 -0400229 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) {
John Bauman66b8ab22014-05-06 15:57:45 -0400230 return 0;
Alexis Hetud061e422015-05-13 16:37:50 -0400231 }
232 break;
233 case EOpIMod:
234 // Note that this is only for the % operator, not for mod()
235 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat) {
236 return 0;
237 }
238 break;
Alexis Hetu92ab1982015-08-18 15:28:27 -0400239 case EOpBitShiftLeft:
240 case EOpBitShiftRight:
241 case EOpBitShiftLeftAssign:
242 case EOpBitShiftRightAssign:
243 // Unsigned can be bit-shifted by signed and vice versa, but we need to
244 // check that the basic type is an integer type.
245 isBitShift = true;
246 if(!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
247 {
248 return 0;
249 }
250 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400251 default: break;
252 }
253
Alexis Hetu92ab1982015-08-18 15:28:27 -0400254 if(!isBitShift && left->getBasicType() != right->getBasicType())
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400255 {
256 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400257 }
258
259 //
260 // Need a new node holding things together then. Make
261 // one and promote it to the right type.
262 //
263 TIntermBinary* node = new TIntermBinary(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400264 node->setLine(line);
265
266 node->setLeft(left);
267 node->setRight(right);
268 if (!node->promote(infoSink))
269 return 0;
270
271 //
272 // See if we can fold constants.
273 //
John Bauman66b8ab22014-05-06 15:57:45 -0400274 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
275 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
276 if (leftTempConstant && rightTempConstant) {
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400277 TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
John Bauman66b8ab22014-05-06 15:57:45 -0400278
279 if (typedReturnNode)
280 return typedReturnNode;
281 }
282
283 return node;
284}
285
286//
287// Connect two nodes through an assignment.
288//
289// Returns the added node.
290//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400291TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400292{
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400293 if (left->getType().getStruct() || right->getType().getStruct())
294 {
295 if (left->getType() != right->getType())
296 {
297 return 0;
298 }
299 }
300
John Bauman66b8ab22014-05-06 15:57:45 -0400301 TIntermBinary* node = new TIntermBinary(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400302 node->setLine(line);
303
John Bauman66b8ab22014-05-06 15:57:45 -0400304 node->setLeft(left);
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400305 node->setRight(right);
John Bauman66b8ab22014-05-06 15:57:45 -0400306 if (! node->promote(infoSink))
307 return 0;
308
309 return node;
310}
311
312//
313// Connect two nodes through an index operator, where the left node is the base
314// of an array or struct, and the right node is a direct or indirect offset.
315//
316// Returns the added node.
317// The caller should set the type of the returned node.
318//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400319TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400320{
321 TIntermBinary* node = new TIntermBinary(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400322 node->setLine(line);
323 node->setLeft(base);
324 node->setRight(index);
325
326 // caller should set the type
327
328 return node;
329}
330
331//
332// Add one node as the parent of another that it operates on.
333//
334// Returns the added node.
335//
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400336TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, const TSourceLoc &line, const TType *funcReturnType)
John Bauman66b8ab22014-05-06 15:57:45 -0400337{
John Bauman66b8ab22014-05-06 15:57:45 -0400338 if (child == 0) {
339 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
340 return 0;
341 }
342
343 switch (op) {
Alexis Hetud061e422015-05-13 16:37:50 -0400344 case EOpBitwiseNot:
Alexis Hetu9085c8d2015-06-01 13:48:07 -0400345 if (!IsInteger(child->getType().getBasicType()) || child->getType().isMatrix() || child->getType().isArray()) {
Alexis Hetud061e422015-05-13 16:37:50 -0400346 return 0;
347 }
348 break;
349
John Bauman66b8ab22014-05-06 15:57:45 -0400350 case EOpLogicalNot:
351 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
352 return 0;
353 }
354 break;
355
356 case EOpPostIncrement:
357 case EOpPreIncrement:
358 case EOpPostDecrement:
359 case EOpPreDecrement:
360 case EOpNegative:
361 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
362 return 0;
363 default: break;
364 }
365
John Bauman66b8ab22014-05-06 15:57:45 -0400366 TIntermConstantUnion *childTempConstant = 0;
367 if (child->getAsConstantUnion())
368 childTempConstant = child->getAsConstantUnion();
369
370 //
371 // Make a new node for the operator.
372 //
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400373 TIntermUnary *node = new TIntermUnary(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400374 node->setLine(line);
375 node->setOperand(child);
376
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400377 if (! node->promote(infoSink, funcReturnType))
John Bauman66b8ab22014-05-06 15:57:45 -0400378 return 0;
379
380 if (childTempConstant) {
381 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
382
383 if (newChild)
384 return newChild;
385 }
386
387 return node;
388}
389
390//
391// This is the safe way to change the operator on an aggregate, as it
392// does lots of error checking and fixing. Especially for establishing
393// a function call's operation on it's set of parameters. Sequences
394// of instructions are also aggregates, but they just direnctly set
395// their operator to EOpSequence.
396//
397// Returns an aggregate node, which could be the one passed in if
398// it was already an aggregate but no operator was set.
399//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400400TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400401{
402 TIntermAggregate* aggNode;
403
404 //
405 // Make sure we have an aggregate. If not turn it into one.
406 //
407 if (node) {
408 aggNode = node->getAsAggregate();
409 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
410 //
411 // Make an aggregate containing this node.
412 //
413 aggNode = new TIntermAggregate();
414 aggNode->getSequence().push_back(node);
John Bauman66b8ab22014-05-06 15:57:45 -0400415 }
416 } else
417 aggNode = new TIntermAggregate();
418
419 //
420 // Set the operator.
421 //
422 aggNode->setOp(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400423
424 return aggNode;
425}
426
427//
John Bauman66b8ab22014-05-06 15:57:45 -0400428// Safe way to combine two nodes into an aggregate. Works with null pointers,
429// a node that's not a aggregate yet, etc.
430//
431// Returns the resulting aggregate, unless 0 was passed in for
432// both existing nodes.
433//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400434TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400435{
436 if (left == 0 && right == 0)
437 return 0;
438
439 TIntermAggregate* aggNode = 0;
440 if (left)
441 aggNode = left->getAsAggregate();
442 if (!aggNode || aggNode->getOp() != EOpNull) {
443 aggNode = new TIntermAggregate;
444 if (left)
445 aggNode->getSequence().push_back(left);
446 }
447
448 if (right)
449 aggNode->getSequence().push_back(right);
450
Alexis Hetu253fdd12015-07-07 15:12:46 -0400451 aggNode->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400452
453 return aggNode;
454}
455
456//
457// Turn an existing node into an aggregate.
458//
459// Returns an aggregate, unless 0 was passed in for the existing node.
460//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400461TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400462{
463 if (node == 0)
464 return 0;
465
466 TIntermAggregate* aggNode = new TIntermAggregate;
467 aggNode->getSequence().push_back(node);
468
Alexis Hetu253fdd12015-07-07 15:12:46 -0400469 aggNode->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400470
471 return aggNode;
472}
473
474//
475// For "if" test nodes. There are three children; a condition,
476// a true path, and a false path. The two paths are in the
477// nodePair.
478//
479// Returns the selection node created.
480//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400481TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400482{
483 //
484 // For compile time constant selections, prune the code and
485 // test now.
486 //
487
488 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
Nicolas Capens198529d2015-02-10 13:54:19 -0500489 if (cond->getAsConstantUnion()->getBConst(0) == true)
John Bauman66b8ab22014-05-06 15:57:45 -0400490 return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
491 else
492 return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
493 }
494
495 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
496 node->setLine(line);
497
498 return node;
499}
500
501
Alexis Hetu253fdd12015-07-07 15:12:46 -0400502TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400503{
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500504 if (left->getType().getQualifier() == EvqConstExpr && right->getType().getQualifier() == EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400505 return right;
506 } else {
507 TIntermTyped *commaAggregate = growAggregate(left, right, line);
508 commaAggregate->getAsAggregate()->setOp(EOpComma);
509 commaAggregate->setType(right->getType());
510 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
511 return commaAggregate;
512 }
513}
514
515//
516// For "?:" test nodes. There are three children; a condition,
517// a true path, and a false path. The two paths are specified
518// as separate parameters.
519//
520// Returns the selection node created, or 0 if one could not be.
521//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400522TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400523{
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400524 if (trueBlock->getType() != falseBlock->getType())
525 {
526 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400527 }
528
529 //
530 // See if all the operands are constant, then fold it otherwise not.
531 //
532
533 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
Nicolas Capens198529d2015-02-10 13:54:19 -0500534 if (cond->getAsConstantUnion()->getBConst(0))
John Bauman66b8ab22014-05-06 15:57:45 -0400535 return trueBlock;
536 else
537 return falseBlock;
538 }
539
540 //
541 // Make a selection node.
542 //
543 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
544 node->getTypePointer()->setQualifier(EvqTemporary);
545 node->setLine(line);
546
547 return node;
548}
549
Alexis Hetu76a343a2015-06-04 17:21:22 -0400550TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
551{
552 TIntermSwitch *node = new TIntermSwitch(init, statementList);
553 node->setLine(line);
554
555 return node;
556}
557
558TIntermCase *TIntermediate::addCase(TIntermTyped *condition, const TSourceLoc &line)
559{
560 TIntermCase *node = new TIntermCase(condition);
561 node->setLine(line);
562
563 return node;
564}
565
John Bauman66b8ab22014-05-06 15:57:45 -0400566//
567// Constant terminal nodes. Has a union that contains bool, float or int constants
568//
569// Returns the constant union node created.
570//
571
Alexis Hetu253fdd12015-07-07 15:12:46 -0400572TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400573{
574 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
575 node->setLine(line);
576
577 return node;
578}
579
Alexis Hetu253fdd12015-07-07 15:12:46 -0400580TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400581{
582
583 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
584
585 node->setLine(line);
586 TIntermConstantUnion* constIntNode;
587 TIntermSequence &sequenceVector = node->getSequence();
588 ConstantUnion* unionArray;
589
590 for (int i = 0; i < fields.num; i++) {
591 unionArray = new ConstantUnion[1];
592 unionArray->setIConst(fields.offsets[i]);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500593 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), line);
John Bauman66b8ab22014-05-06 15:57:45 -0400594 sequenceVector.push_back(constIntNode);
595 }
596
597 return node;
598}
599
600//
601// Create loop nodes.
602//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400603TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400604{
605 TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
606 node->setLine(line);
607
608 return node;
609}
610
611//
612// Add branches.
613//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400614TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400615{
616 return addBranch(branchOp, 0, line);
617}
618
Alexis Hetu253fdd12015-07-07 15:12:46 -0400619TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400620{
621 TIntermBranch* node = new TIntermBranch(branchOp, expression);
622 node->setLine(line);
623
624 return node;
625}
626
627//
628// This is to be executed once the final root is put on top by the parsing
629// process.
630//
631bool TIntermediate::postProcess(TIntermNode* root)
632{
633 if (root == 0)
634 return true;
635
636 //
637 // First, finish off the top level sequence, if any
638 //
639 TIntermAggregate* aggRoot = root->getAsAggregate();
640 if (aggRoot && aggRoot->getOp() == EOpNull)
641 aggRoot->setOp(EOpSequence);
642
643 return true;
644}
645
John Bauman66b8ab22014-05-06 15:57:45 -0400646////////////////////////////////////////////////////////////////
647//
648// Member functions of the nodes used for building the tree.
649//
650////////////////////////////////////////////////////////////////
651
652//
653// Say whether or not an operation node changes the value of a variable.
654//
655// Returns true if state is modified.
656//
657bool TIntermOperator::modifiesState() const
658{
659 switch (op) {
660 case EOpPostIncrement:
661 case EOpPostDecrement:
662 case EOpPreIncrement:
663 case EOpPreDecrement:
664 case EOpAssign:
665 case EOpAddAssign:
666 case EOpSubAssign:
667 case EOpMulAssign:
668 case EOpVectorTimesMatrixAssign:
669 case EOpVectorTimesScalarAssign:
670 case EOpMatrixTimesScalarAssign:
671 case EOpMatrixTimesMatrixAssign:
672 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400673 case EOpIModAssign:
674 case EOpBitShiftLeftAssign:
675 case EOpBitShiftRightAssign:
676 case EOpBitwiseAndAssign:
677 case EOpBitwiseXorAssign:
678 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400679 return true;
680 default:
681 return false;
682 }
683}
684
685//
686// returns true if the operator is for one of the constructors
687//
688bool TIntermOperator::isConstructor() const
689{
690 switch (op) {
691 case EOpConstructVec2:
692 case EOpConstructVec3:
693 case EOpConstructVec4:
694 case EOpConstructMat2:
Alexis Hetu00106d42015-04-23 11:45:35 -0400695 case EOpConstructMat2x3:
696 case EOpConstructMat2x4:
697 case EOpConstructMat3x2:
John Bauman66b8ab22014-05-06 15:57:45 -0400698 case EOpConstructMat3:
Alexis Hetu00106d42015-04-23 11:45:35 -0400699 case EOpConstructMat3x4:
700 case EOpConstructMat4x2:
701 case EOpConstructMat4x3:
John Bauman66b8ab22014-05-06 15:57:45 -0400702 case EOpConstructMat4:
703 case EOpConstructFloat:
704 case EOpConstructIVec2:
705 case EOpConstructIVec3:
706 case EOpConstructIVec4:
707 case EOpConstructInt:
Nicolas Capense4b1b1d2015-02-17 17:26:01 -0500708 case EOpConstructUVec2:
709 case EOpConstructUVec3:
710 case EOpConstructUVec4:
Nicolas Capens3c20f802015-02-17 17:17:20 -0500711 case EOpConstructUInt:
John Bauman66b8ab22014-05-06 15:57:45 -0400712 case EOpConstructBVec2:
713 case EOpConstructBVec3:
714 case EOpConstructBVec4:
715 case EOpConstructBool:
716 case EOpConstructStruct:
717 return true;
718 default:
719 return false;
720 }
721}
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400722
John Bauman66b8ab22014-05-06 15:57:45 -0400723//
724// Make sure the type of a unary operator is appropriate for its
725// combination of operation and operand type.
726//
727// Returns false in nothing makes sense.
728//
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400729bool TIntermUnary::promote(TInfoSink&, const TType *funcReturnType)
John Bauman66b8ab22014-05-06 15:57:45 -0400730{
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400731 setType(funcReturnType ? *funcReturnType : operand->getType());
732
733 // Unary operations result in temporary variables unless const.
734 if(type.getQualifier() != EvqConstExpr)
735 {
736 type.setQualifier(EvqTemporary);
737 }
738
John Bauman66b8ab22014-05-06 15:57:45 -0400739 switch (op) {
740 case EOpLogicalNot:
741 if (operand->getBasicType() != EbtBool)
742 return false;
743 break;
Alexis Hetud061e422015-05-13 16:37:50 -0400744 case EOpBitwiseNot:
Alexis Hetu9085c8d2015-06-01 13:48:07 -0400745 if (!IsInteger(operand->getBasicType()))
Alexis Hetud061e422015-05-13 16:37:50 -0400746 return false;
747 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400748 case EOpNegative:
749 case EOpPostIncrement:
750 case EOpPostDecrement:
751 case EOpPreIncrement:
752 case EOpPreDecrement:
753 if (operand->getBasicType() == EbtBool)
754 return false;
755 break;
756
757 // operators for built-ins are already type checked against their prototype
758 case EOpAny:
759 case EOpAll:
760 case EOpVectorLogicalNot:
Alexis Hetu0f448072016-03-18 10:56:08 -0400761 case EOpAbs:
762 case EOpSign:
763 case EOpIsNan:
764 case EOpIsInf:
765 case EOpFloatBitsToInt:
766 case EOpFloatBitsToUint:
767 case EOpIntBitsToFloat:
768 case EOpUintBitsToFloat:
769 case EOpPackSnorm2x16:
770 case EOpPackUnorm2x16:
771 case EOpPackHalf2x16:
772 case EOpUnpackSnorm2x16:
773 case EOpUnpackUnorm2x16:
774 case EOpUnpackHalf2x16:
John Bauman66b8ab22014-05-06 15:57:45 -0400775 return true;
776
777 default:
778 if (operand->getBasicType() != EbtFloat)
779 return false;
780 }
781
John Bauman66b8ab22014-05-06 15:57:45 -0400782 return true;
783}
784
785//
786// Establishes the type of the resultant operation, as well as
787// makes the operator the correct one for the operands.
788//
789// Returns false if operator can't work on operands.
790//
791bool TIntermBinary::promote(TInfoSink& infoSink)
792{
Alexis Hetue5246692015-06-18 12:34:52 -0400793 ASSERT(left->isArray() == right->isArray());
John Bauman66b8ab22014-05-06 15:57:45 -0400794
795 // GLSL ES 2.0 does not support implicit type casting.
796 // So the basic type should always match.
Alexis Hetu92ab1982015-08-18 15:28:27 -0400797 // GLSL ES 3.0 supports integer shift operands of different signedness.
798 if(op != EOpBitShiftLeft &&
799 op != EOpBitShiftRight &&
800 op != EOpBitShiftLeftAssign &&
801 op != EOpBitShiftRightAssign &&
802 left->getBasicType() != right->getBasicType())
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400803 {
John Bauman66b8ab22014-05-06 15:57:45 -0400804 return false;
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400805 }
John Bauman66b8ab22014-05-06 15:57:45 -0400806
807 //
808 // Base assumption: just make the type the same as the left
809 // operand. Then only deviations from this need be coded.
810 //
811 setType(left->getType());
812
813 // The result gets promoted to the highest precision.
814 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
815 getTypePointer()->setPrecision(higherPrecision);
816
817 // Binary operations results in temporary variables unless both
818 // operands are const.
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500819 if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400820 getTypePointer()->setQualifier(EvqTemporary);
821 }
822
Alexis Hetud061e422015-05-13 16:37:50 -0400823 int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
John Bauman66b8ab22014-05-06 15:57:45 -0400824
825 //
826 // All scalars. Code after this test assumes this case is removed!
827 //
Alexis Hetud061e422015-05-13 16:37:50 -0400828 if (primarySize == 1) {
John Bauman66b8ab22014-05-06 15:57:45 -0400829 switch (op) {
830 //
831 // Promote to conditional
832 //
833 case EOpEqual:
834 case EOpNotEqual:
835 case EOpLessThan:
836 case EOpGreaterThan:
837 case EOpLessThanEqual:
838 case EOpGreaterThanEqual:
839 setType(TType(EbtBool, EbpUndefined));
840 break;
841
842 //
843 // And and Or operate on conditionals
844 //
845 case EOpLogicalAnd:
846 case EOpLogicalOr:
Alexis Hetud061e422015-05-13 16:37:50 -0400847 case EOpLogicalXor:
John Bauman66b8ab22014-05-06 15:57:45 -0400848 // Both operands must be of type bool.
849 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
850 return false;
851 setType(TType(EbtBool, EbpUndefined));
852 break;
853
854 default:
855 break;
856 }
857 return true;
858 }
859
860 // If we reach here, at least one of the operands is vector or matrix.
861 // The other operand could be a scalar, vector, or matrix.
John Bauman66b8ab22014-05-06 15:57:45 -0400862 // Can these two operands be combined?
863 //
864 TBasicType basicType = left->getBasicType();
865 switch (op) {
866 case EOpMul:
867 if (!left->isMatrix() && right->isMatrix()) {
868 if (left->isVector())
Alexis Hetu00106d42015-04-23 11:45:35 -0400869 {
John Bauman66b8ab22014-05-06 15:57:45 -0400870 op = EOpVectorTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400871 setType(TType(basicType, higherPrecision, EvqTemporary,
872 static_cast<unsigned char>(right->getNominalSize()), 1));
873 }
John Bauman66b8ab22014-05-06 15:57:45 -0400874 else {
875 op = EOpMatrixTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400876 setType(TType(basicType, higherPrecision, EvqTemporary,
877 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400878 }
879 } else if (left->isMatrix() && !right->isMatrix()) {
880 if (right->isVector()) {
881 op = EOpMatrixTimesVector;
Alexis Hetu00106d42015-04-23 11:45:35 -0400882 setType(TType(basicType, higherPrecision, EvqTemporary,
883 static_cast<unsigned char>(left->getSecondarySize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400884 } else {
885 op = EOpMatrixTimesScalar;
886 }
887 } else if (left->isMatrix() && right->isMatrix()) {
888 op = EOpMatrixTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400889 setType(TType(basicType, higherPrecision, EvqTemporary,
890 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400891 } else if (!left->isMatrix() && !right->isMatrix()) {
892 if (left->isVector() && right->isVector()) {
893 // leave as component product
894 } else if (left->isVector() || right->isVector()) {
895 op = EOpVectorTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400896 setType(TType(basicType, higherPrecision, EvqTemporary,
897 static_cast<unsigned char>(primarySize), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400898 }
899 } else {
900 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
901 return false;
902 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400903
904 if(!ValidateMultiplication(op, left->getType(), right->getType()))
905 {
906 return false;
907 }
John Bauman66b8ab22014-05-06 15:57:45 -0400908 break;
909 case EOpMulAssign:
910 if (!left->isMatrix() && right->isMatrix()) {
911 if (left->isVector())
912 op = EOpVectorTimesMatrixAssign;
913 else {
914 return false;
915 }
916 } else if (left->isMatrix() && !right->isMatrix()) {
917 if (right->isVector()) {
918 return false;
919 } else {
920 op = EOpMatrixTimesScalarAssign;
921 }
922 } else if (left->isMatrix() && right->isMatrix()) {
923 op = EOpMatrixTimesMatrixAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400924 setType(TType(basicType, higherPrecision, EvqTemporary,
925 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400926 } else if (!left->isMatrix() && !right->isMatrix()) {
927 if (left->isVector() && right->isVector()) {
928 // leave as component product
929 } else if (left->isVector() || right->isVector()) {
930 if (! left->isVector())
931 return false;
932 op = EOpVectorTimesScalarAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400933 setType(TType(basicType, higherPrecision, EvqTemporary,
934 static_cast<unsigned char>(left->getNominalSize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400935 }
936 } else {
937 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
938 return false;
939 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400940
941 if(!ValidateMultiplication(op, left->getType(), right->getType()))
942 {
943 return false;
944 }
John Bauman66b8ab22014-05-06 15:57:45 -0400945 break;
946
947 case EOpAssign:
948 case EOpInitialize:
Alexis Hetu00106d42015-04-23 11:45:35 -0400949 // No more additional checks are needed.
950 if ((left->getNominalSize() != right->getNominalSize()) ||
951 (left->getSecondarySize() != right->getSecondarySize()))
952 return false;
953 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400954 case EOpAdd:
955 case EOpSub:
956 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -0400957 case EOpIMod:
958 case EOpBitShiftLeft:
959 case EOpBitShiftRight:
960 case EOpBitwiseAnd:
961 case EOpBitwiseXor:
962 case EOpBitwiseOr:
John Bauman66b8ab22014-05-06 15:57:45 -0400963 case EOpAddAssign:
964 case EOpSubAssign:
965 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400966 case EOpIModAssign:
967 case EOpBitShiftLeftAssign:
968 case EOpBitShiftRightAssign:
969 case EOpBitwiseAndAssign:
970 case EOpBitwiseXorAssign:
971 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400972 if ((left->isMatrix() && right->isVector()) ||
973 (left->isVector() && right->isMatrix()))
974 return false;
Alexis Hetud061e422015-05-13 16:37:50 -0400975
976 // Are the sizes compatible?
977 if(left->getNominalSize() != right->getNominalSize() ||
978 left->getSecondarySize() != right->getSecondarySize())
979 {
980 // If the nominal sizes of operands do not match:
981 // One of them must be a scalar.
982 if(!left->isScalar() && !right->isScalar())
983 return false;
984
985 // In the case of compound assignment other than multiply-assign,
986 // the right side needs to be a scalar. Otherwise a vector/matrix
987 // would be assigned to a scalar. A scalar can't be shifted by a
988 // vector either.
989 if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight))
990 return false;
991 }
992
993 {
Alexis Hetu00106d42015-04-23 11:45:35 -0400994 const int secondarySize = std::max(
995 left->getSecondarySize(), right->getSecondarySize());
Alexis Hetud061e422015-05-13 16:37:50 -0400996 setType(TType(basicType, higherPrecision, EvqTemporary,
997 static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
998 if(left->isArray())
999 {
1000 ASSERT(left->getArraySize() == right->getArraySize());
1001 type.setArraySize(left->getArraySize());
1002 }
1003 }
John Bauman66b8ab22014-05-06 15:57:45 -04001004 break;
1005
1006 case EOpEqual:
1007 case EOpNotEqual:
1008 case EOpLessThan:
1009 case EOpGreaterThan:
1010 case EOpLessThanEqual:
1011 case EOpGreaterThanEqual:
Alexis Hetu00106d42015-04-23 11:45:35 -04001012 if ((left->getNominalSize() != right->getNominalSize()) ||
1013 (left->getSecondarySize() != right->getSecondarySize()))
John Bauman66b8ab22014-05-06 15:57:45 -04001014 return false;
1015 setType(TType(EbtBool, EbpUndefined));
1016 break;
1017
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001018 case EOpOuterProduct:
1019 if(!left->isVector() || !right->isVector())
1020 return false;
1021 setType(TType(EbtFloat, right->getNominalSize(), left->getNominalSize()));
1022 break;
1023
1024 case EOpTranspose:
1025 if(!right->isMatrix())
1026 return false;
1027 setType(TType(EbtFloat, right->getSecondarySize(), right->getNominalSize()));
1028 break;
1029
1030 case EOpDeterminant:
1031 if(!right->isMatrix())
1032 return false;
1033 setType(TType(EbtFloat));
1034 break;
1035
1036 case EOpInverse:
1037 if(!right->isMatrix() || right->getNominalSize() != right->getSecondarySize())
1038 return false;
1039 setType(right->getType());
1040 break;
1041
John Bauman66b8ab22014-05-06 15:57:45 -04001042 default:
1043 return false;
1044 }
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001045
John Bauman66b8ab22014-05-06 15:57:45 -04001046 return true;
1047}
1048
1049bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1050{
Alexis Hetua8b364b2015-06-10 11:48:40 -04001051 const TFieldList& fields = leftNodeType.getStruct()->fields();
John Bauman66b8ab22014-05-06 15:57:45 -04001052
Alexis Hetua8b364b2015-06-10 11:48:40 -04001053 size_t structSize = fields.size();
John Bauman66b8ab22014-05-06 15:57:45 -04001054 int index = 0;
1055
1056 for (size_t j = 0; j < structSize; j++) {
Alexis Hetuab752792016-04-21 16:11:31 -04001057 size_t size = fields[j]->type()->getObjectSize();
1058 for(size_t i = 0; i < size; i++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001059 if (fields[j]->type()->getBasicType() == EbtStruct) {
1060 if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
John Bauman66b8ab22014-05-06 15:57:45 -04001061 return false;
1062 } else {
1063 if (leftUnionArray[index] != rightUnionArray[index])
1064 return false;
1065 index++;
1066 }
1067
1068 }
1069 }
1070 return true;
1071}
1072
1073bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1074{
1075 if (leftNodeType.isArray()) {
1076 TType typeWithoutArrayness = leftNodeType;
1077 typeWithoutArrayness.clearArrayness();
1078
1079 int arraySize = leftNodeType.getArraySize();
1080
1081 for (int i = 0; i < arraySize; ++i) {
Alexis Hetuab752792016-04-21 16:11:31 -04001082 size_t offset = typeWithoutArrayness.getObjectSize() * i;
John Bauman66b8ab22014-05-06 15:57:45 -04001083 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1084 return false;
1085 }
1086 } else
1087 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
1088
1089 return true;
1090}
1091
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001092float determinant2(float m00, float m01, float m10, float m11)
1093{
1094 return m00 * m11 - m01 * m10;
1095}
1096
1097float determinant3(float m00, float m01, float m02,
1098 float m10, float m11, float m12,
1099 float m20, float m21, float m22)
1100{
1101 return m00 * determinant2(m11, m12, m21, m22) -
1102 m10 * determinant2(m01, m02, m21, m22) +
1103 m20 * determinant2(m01, m02, m11, m12);
1104}
1105
1106float determinant4(float m00, float m01, float m02, float m03,
1107 float m10, float m11, float m12, float m13,
1108 float m20, float m21, float m22, float m23,
1109 float m30, float m31, float m32, float m33)
1110{
1111 return m00 * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33) -
1112 m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) +
1113 m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) -
1114 m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
1115}
1116
1117float ComputeDeterminant(int size, ConstantUnion* unionArray)
1118{
1119 switch(size)
1120 {
1121 case 2:
1122 return determinant2(unionArray[0].getFConst(),
1123 unionArray[1].getFConst(),
1124 unionArray[2].getFConst(),
1125 unionArray[3].getFConst());
1126 case 3:
1127 return determinant3(unionArray[0].getFConst(),
1128 unionArray[1].getFConst(),
1129 unionArray[2].getFConst(),
1130 unionArray[3].getFConst(),
1131 unionArray[4].getFConst(),
1132 unionArray[5].getFConst(),
1133 unionArray[6].getFConst(),
1134 unionArray[7].getFConst(),
1135 unionArray[8].getFConst());
1136 case 4:
1137 return determinant4(unionArray[0].getFConst(),
1138 unionArray[1].getFConst(),
1139 unionArray[2].getFConst(),
1140 unionArray[3].getFConst(),
1141 unionArray[4].getFConst(),
1142 unionArray[5].getFConst(),
1143 unionArray[6].getFConst(),
1144 unionArray[7].getFConst(),
1145 unionArray[8].getFConst(),
1146 unionArray[9].getFConst(),
1147 unionArray[10].getFConst(),
1148 unionArray[11].getFConst(),
1149 unionArray[12].getFConst(),
1150 unionArray[13].getFConst(),
1151 unionArray[14].getFConst(),
1152 unionArray[15].getFConst());
1153 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001154 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001155 return 0.0f;
1156 }
1157}
1158
1159ConstantUnion* CreateInverse(TIntermConstantUnion* node, ConstantUnion* unionArray)
1160{
1161 ConstantUnion* tempConstArray = 0;
1162 int size = node->getNominalSize();
1163 float determinant = ComputeDeterminant(size, unionArray);
1164 if(determinant != 0.0f)
1165 {
1166 float invDet = 1.0f / determinant;
1167 tempConstArray = new ConstantUnion[size*size];
1168 switch(size)
1169 {
1170 case 2:
1171 {
1172 float m00 = unionArray[0].getFConst(); // Matrix is:
1173 float m01 = unionArray[1].getFConst(); // (m00, m01)
1174 float m10 = unionArray[2].getFConst(); // (m10, m11)
1175 float m11 = unionArray[3].getFConst();
1176 tempConstArray[0].setFConst( invDet * m11);
1177 tempConstArray[1].setFConst(-invDet * m01);
1178 tempConstArray[2].setFConst(-invDet * m10);
1179 tempConstArray[3].setFConst( invDet * m00);
1180 }
1181 break;
1182 case 3:
1183 {
1184 float m00 = unionArray[0].getFConst(); // Matrix is:
1185 float m01 = unionArray[1].getFConst(); // (m00, m01, m02)
1186 float m02 = unionArray[2].getFConst(); // (m10, m11, m12)
1187 float m10 = unionArray[3].getFConst(); // (m20, m21, m22)
1188 float m11 = unionArray[4].getFConst();
1189 float m12 = unionArray[5].getFConst();
1190 float m20 = unionArray[6].getFConst();
1191 float m21 = unionArray[7].getFConst();
1192 float m22 = unionArray[8].getFConst();
1193 tempConstArray[0].setFConst(invDet * determinant2(m11, m12, m21, m22)); // m00 = invDet * (m11 * m22 - m12 * m21)
1194 tempConstArray[1].setFConst(invDet * determinant2(m12, m10, m22, m20)); // m01 = -invDet * (m10 * m22 - m12 * m20)
1195 tempConstArray[2].setFConst(invDet * determinant2(m10, m11, m20, m21)); // m02 = invDet * (m10 * m21 - m11 * m20)
1196 tempConstArray[3].setFConst(invDet * determinant2(m21, m22, m01, m02)); // m10 = -invDet * (m01 * m22 - m02 * m21)
1197 tempConstArray[4].setFConst(invDet * determinant2(m00, m02, m20, m22)); // m11 = invDet * (m00 * m22 - m02 * m20)
1198 tempConstArray[5].setFConst(invDet * determinant2(m20, m21, m00, m01)); // m12 = -invDet * (m00 * m21 - m01 * m20)
1199 tempConstArray[6].setFConst(invDet * determinant2(m01, m02, m11, m12)); // m20 = invDet * (m01 * m12 - m02 * m11)
1200 tempConstArray[7].setFConst(invDet * determinant2(m10, m12, m00, m02)); // m21 = -invDet * (m00 * m12 - m02 * m10)
1201 tempConstArray[8].setFConst(invDet * determinant2(m00, m01, m10, m11)); // m22 = invDet * (m00 * m11 - m01 * m10)
1202 }
1203 break;
1204 case 4:
1205 {
1206 float m00 = unionArray[0].getFConst(); // Matrix is:
1207 float m01 = unionArray[1].getFConst(); // (m00, m01, m02, m03)
1208 float m02 = unionArray[2].getFConst(); // (m10, m11, m12, m13)
1209 float m03 = unionArray[3].getFConst(); // (m20, m21, m22, m23)
1210 float m10 = unionArray[4].getFConst(); // (m30, m31, m32, m33)
1211 float m11 = unionArray[5].getFConst();
1212 float m12 = unionArray[6].getFConst();
1213 float m13 = unionArray[7].getFConst();
1214 float m20 = unionArray[8].getFConst();
1215 float m21 = unionArray[9].getFConst();
1216 float m22 = unionArray[10].getFConst();
1217 float m23 = unionArray[11].getFConst();
1218 float m30 = unionArray[12].getFConst();
1219 float m31 = unionArray[13].getFConst();
1220 float m32 = unionArray[14].getFConst();
1221 float m33 = unionArray[15].getFConst();
1222 tempConstArray[ 0].setFConst( invDet * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33)); // m00
1223 tempConstArray[ 1].setFConst(-invDet * determinant3(m10, m12, m13, m20, m22, m23, m30, m32, m33)); // m01
1224 tempConstArray[ 2].setFConst( invDet * determinant3(m10, m11, m13, m20, m21, m23, m30, m31, m33)); // m02
1225 tempConstArray[ 3].setFConst(-invDet * determinant3(m10, m11, m12, m20, m21, m22, m30, m31, m32)); // m03
1226 tempConstArray[ 4].setFConst( invDet * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33)); // m10
1227 tempConstArray[ 5].setFConst(-invDet * determinant3(m00, m02, m03, m20, m22, m23, m30, m32, m33)); // m11
1228 tempConstArray[ 6].setFConst( invDet * determinant3(m00, m01, m03, m20, m21, m23, m30, m31, m33)); // m12
1229 tempConstArray[ 7].setFConst(-invDet * determinant3(m00, m01, m02, m20, m21, m22, m30, m31, m32)); // m13
1230 tempConstArray[ 8].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33)); // m20
1231 tempConstArray[ 9].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m30, m32, m33)); // m21
1232 tempConstArray[10].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m30, m31, m33)); // m22
1233 tempConstArray[11].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m30, m31, m32)); // m23
1234 tempConstArray[12].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23)); // m30
1235 tempConstArray[13].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m20, m22, m23)); // m31
1236 tempConstArray[14].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m20, m21, m23)); // m32
1237 tempConstArray[15].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m20, m21, m22)); // m33
1238 }
1239 break;
1240 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001241 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001242 }
1243 }
1244 return tempConstArray;
1245}
1246
John Bauman66b8ab22014-05-06 15:57:45 -04001247//
1248// The fold functions see if an operation on a constant can be done in place,
1249// without generating run-time code.
1250//
1251// Returns the node to keep using, which may or may not be the node passed in.
1252//
1253
1254TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1255{
1256 ConstantUnion *unionArray = getUnionArrayPointer();
Alexis Hetuab752792016-04-21 16:11:31 -04001257 size_t objectSize = getType().getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04001258
1259 if (constantNode) { // binary operations
1260 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
1261 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
1262 TType returnType = getType();
1263
1264 // for a case like float f = 1.2 + vec4(2,3,4,5);
1265 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
1266 rightUnionArray = new ConstantUnion[objectSize];
Alexis Hetuab752792016-04-21 16:11:31 -04001267 for (size_t i = 0; i < objectSize; ++i)
John Bauman66b8ab22014-05-06 15:57:45 -04001268 rightUnionArray[i] = *node->getUnionArrayPointer();
1269 returnType = getType();
1270 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1271 // for a case like float f = vec4(2,3,4,5) + 1.2;
1272 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
Alexis Hetuab752792016-04-21 16:11:31 -04001273 for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
John Bauman66b8ab22014-05-06 15:57:45 -04001274 unionArray[i] = *getUnionArrayPointer();
1275 returnType = node->getType();
1276 objectSize = constantNode->getType().getObjectSize();
1277 }
1278
1279 ConstantUnion* tempConstArray = 0;
1280 TIntermConstantUnion *tempNode;
1281
John Bauman66b8ab22014-05-06 15:57:45 -04001282 switch(op) {
1283 case EOpAdd:
1284 tempConstArray = new ConstantUnion[objectSize];
1285 {// support MSVC++6.0
Alexis Hetuab752792016-04-21 16:11:31 -04001286 for (size_t i = 0; i < objectSize; i++)
John Bauman66b8ab22014-05-06 15:57:45 -04001287 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1288 }
1289 break;
1290 case EOpSub:
1291 tempConstArray = new ConstantUnion[objectSize];
1292 {// support MSVC++6.0
Alexis Hetuab752792016-04-21 16:11:31 -04001293 for (size_t i = 0; i < objectSize; i++)
John Bauman66b8ab22014-05-06 15:57:45 -04001294 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1295 }
1296 break;
1297
1298 case EOpMul:
1299 case EOpVectorTimesScalar:
1300 case EOpMatrixTimesScalar:
1301 tempConstArray = new ConstantUnion[objectSize];
1302 {// support MSVC++6.0
Alexis Hetuab752792016-04-21 16:11:31 -04001303 for (size_t i = 0; i < objectSize; i++)
John Bauman66b8ab22014-05-06 15:57:45 -04001304 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1305 }
1306 break;
1307 case EOpMatrixTimesMatrix:
1308 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1309 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1310 return 0;
1311 }
1312 {// support MSVC++6.0
Alexis Hetu00106d42015-04-23 11:45:35 -04001313 int leftNumCols = getNominalSize();
1314 int leftNumRows = getSecondarySize();
1315 int rightNumCols = node->getNominalSize();
1316 int rightNumRows = node->getSecondarySize();
1317 if(leftNumCols != rightNumRows) {
1318 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1319 return 0;
1320 }
1321 int tempNumCols = rightNumCols;
1322 int tempNumRows = leftNumRows;
1323 int tempNumAdds = leftNumCols;
1324 tempConstArray = new ConstantUnion[tempNumCols*tempNumRows];
1325 for (int row = 0; row < tempNumRows; row++) {
1326 for (int column = 0; column < tempNumCols; column++) {
1327 tempConstArray[tempNumRows * column + row].setFConst(0.0f);
1328 for (int i = 0; i < tempNumAdds; i++) {
1329 tempConstArray[tempNumRows * column + row].setFConst(tempConstArray[tempNumRows * column + row].getFConst() + unionArray[i * leftNumRows + row].getFConst() * (rightUnionArray[column * rightNumRows + i].getFConst()));
John Bauman66b8ab22014-05-06 15:57:45 -04001330 }
1331 }
1332 }
Alexis Hetu00106d42015-04-23 11:45:35 -04001333 // update return type for matrix product
1334 returnType.setNominalSize(static_cast<unsigned char>(tempNumCols));
1335 returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows));
John Bauman66b8ab22014-05-06 15:57:45 -04001336 }
1337 break;
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001338
1339 case EOpOuterProduct:
1340 {
1341 int leftSize = getNominalSize();
1342 int rightSize = node->getNominalSize();
1343 tempConstArray = new ConstantUnion[leftSize*rightSize];
1344 for(int row = 0; row < leftSize; row++) {
1345 for(int column = 0; column < rightSize; column++) {
1346 tempConstArray[leftSize * column + row].setFConst(unionArray[row].getFConst() * rightUnionArray[column].getFConst());
1347 }
1348 }
1349 // update return type for outer product
1350 returnType.setNominalSize(static_cast<unsigned char>(rightSize));
1351 returnType.setSecondarySize(static_cast<unsigned char>(leftSize));
1352 }
1353 break;
1354
1355 case EOpTranspose:
1356 {
1357 int rightCol = node->getNominalSize();
1358 int rightRow = node->getSecondarySize();
1359 tempConstArray = new ConstantUnion[rightCol*rightRow];
1360 for(int row = 0; row < rightRow; row++) {
1361 for(int column = 0; column < rightCol; column++) {
1362 tempConstArray[rightRow * column + row].setFConst(rightUnionArray[rightCol * row + column].getFConst());
1363 }
1364 }
1365 // update return type for transpose
1366 returnType.setNominalSize(static_cast<unsigned char>(rightRow));
1367 returnType.setSecondarySize(static_cast<unsigned char>(rightCol));
1368 }
1369 break;
1370
1371 case EOpDeterminant:
1372 {
1373 ASSERT(node->getNominalSize() == node->getSecondarySize());
1374
1375 tempConstArray = new ConstantUnion[1];
1376 tempConstArray[0].setFConst(ComputeDeterminant(node->getNominalSize(), rightUnionArray));
1377 // update return type for determinant
1378 returnType.setNominalSize(1);
1379 returnType.setSecondarySize(1);
1380 }
1381 break;
1382
1383 case EOpInverse:
1384 {
1385 ASSERT(node->getNominalSize() == node->getSecondarySize());
1386
1387 tempConstArray = CreateInverse(node, rightUnionArray);
1388 if(!tempConstArray)
1389 {
1390 // Singular matrix, just copy
1391 tempConstArray = new ConstantUnion[objectSize];
Alexis Hetuab752792016-04-21 16:11:31 -04001392 for(size_t i = 0; i < objectSize; i++)
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001393 tempConstArray[i] = rightUnionArray[i];
1394 }
1395 }
1396 break;
1397
John Bauman66b8ab22014-05-06 15:57:45 -04001398 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -04001399 case EOpIMod:
John Bauman66b8ab22014-05-06 15:57:45 -04001400 tempConstArray = new ConstantUnion[objectSize];
1401 {// support MSVC++6.0
Alexis Hetuab752792016-04-21 16:11:31 -04001402 for (size_t i = 0; i < objectSize; i++) {
John Bauman66b8ab22014-05-06 15:57:45 -04001403 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001404 case EbtFloat:
1405 if (rightUnionArray[i] == 0.0f) {
1406 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1407 tempConstArray[i].setFConst(FLT_MAX);
1408 } else {
1409 ASSERT(op == EOpDiv);
1410 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1411 }
1412 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001413
Alexis Hetud061e422015-05-13 16:37:50 -04001414 case EbtInt:
1415 if (rightUnionArray[i] == 0) {
1416 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1417 tempConstArray[i].setIConst(INT_MAX);
1418 } else {
1419 if(op == EOpDiv) {
1420 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1421 } else {
1422 ASSERT(op == EOpIMod);
1423 tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst());
1424 }
1425 }
1426 break;
1427 case EbtUInt:
1428 if (rightUnionArray[i] == 0) {
1429 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1430 tempConstArray[i].setUConst(UINT_MAX);
1431 } else {
1432 if(op == EOpDiv) {
1433 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1434 } else {
1435 ASSERT(op == EOpIMod);
1436 tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst());
1437 }
1438 }
1439 break;
1440 default:
1441 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1442 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -04001443 }
1444 }
1445 }
1446 break;
1447
1448 case EOpMatrixTimesVector:
1449 if (node->getBasicType() != EbtFloat) {
1450 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1451 return 0;
1452 }
1453 tempConstArray = new ConstantUnion[getNominalSize()];
1454
1455 {// support MSVC++6.0
1456 for (int size = getNominalSize(), i = 0; i < size; i++) {
1457 tempConstArray[i].setFConst(0.0f);
1458 for (int j = 0; j < size; j++) {
1459 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1460 }
1461 }
1462 }
1463
1464 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1465 tempNode->setLine(getLine());
1466
1467 return tempNode;
1468
1469 case EOpVectorTimesMatrix:
1470 if (getType().getBasicType() != EbtFloat) {
1471 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1472 return 0;
1473 }
1474
1475 tempConstArray = new ConstantUnion[getNominalSize()];
1476 {// support MSVC++6.0
1477 for (int size = getNominalSize(), i = 0; i < size; i++) {
1478 tempConstArray[i].setFConst(0.0f);
1479 for (int j = 0; j < size; j++) {
1480 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1481 }
1482 }
1483 }
1484 break;
1485
1486 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1487 tempConstArray = new ConstantUnion[objectSize];
1488 {// support MSVC++6.0
Alexis Hetuab752792016-04-21 16:11:31 -04001489 for (size_t i = 0; i < objectSize; i++)
John Bauman66b8ab22014-05-06 15:57:45 -04001490 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1491 }
1492 break;
1493
1494 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1495 tempConstArray = new ConstantUnion[objectSize];
1496 {// support MSVC++6.0
Alexis Hetuab752792016-04-21 16:11:31 -04001497 for (size_t i = 0; i < objectSize; i++)
John Bauman66b8ab22014-05-06 15:57:45 -04001498 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1499 }
1500 break;
1501
1502 case EOpLogicalXor:
1503 tempConstArray = new ConstantUnion[objectSize];
1504 {// support MSVC++6.0
Alexis Hetuab752792016-04-21 16:11:31 -04001505 for (size_t i = 0; i < objectSize; i++)
John Bauman66b8ab22014-05-06 15:57:45 -04001506 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001507 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1508 default: assert(false && "Default missing");
John Bauman66b8ab22014-05-06 15:57:45 -04001509 }
1510 }
1511 break;
1512
Alexis Hetud061e422015-05-13 16:37:50 -04001513 case EOpBitwiseAnd:
1514 tempConstArray = new ConstantUnion[objectSize];
Alexis Hetuab752792016-04-21 16:11:31 -04001515 for(size_t i = 0; i < objectSize; i++)
Alexis Hetud061e422015-05-13 16:37:50 -04001516 tempConstArray[i] = unionArray[i] & rightUnionArray[i];
1517 break;
1518 case EOpBitwiseXor:
1519 tempConstArray = new ConstantUnion[objectSize];
Alexis Hetuab752792016-04-21 16:11:31 -04001520 for(size_t i = 0; i < objectSize; i++)
Alexis Hetud061e422015-05-13 16:37:50 -04001521 tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
1522 break;
1523 case EOpBitwiseOr:
1524 tempConstArray = new ConstantUnion[objectSize];
Alexis Hetuab752792016-04-21 16:11:31 -04001525 for(size_t i = 0; i < objectSize; i++)
Alexis Hetud061e422015-05-13 16:37:50 -04001526 tempConstArray[i] = unionArray[i] | rightUnionArray[i];
1527 break;
1528 case EOpBitShiftLeft:
1529 tempConstArray = new ConstantUnion[objectSize];
Alexis Hetuab752792016-04-21 16:11:31 -04001530 for(size_t i = 0; i < objectSize; i++)
Alexis Hetud061e422015-05-13 16:37:50 -04001531 tempConstArray[i] = unionArray[i] << rightUnionArray[i];
1532 break;
1533 case EOpBitShiftRight:
1534 tempConstArray = new ConstantUnion[objectSize];
Alexis Hetuab752792016-04-21 16:11:31 -04001535 for(size_t i = 0; i < objectSize; i++)
Alexis Hetud061e422015-05-13 16:37:50 -04001536 tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
1537 break;
1538
John Bauman66b8ab22014-05-06 15:57:45 -04001539 case EOpLessThan:
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001540 tempConstArray = new ConstantUnion[objectSize];
Alexis Hetuab752792016-04-21 16:11:31 -04001541 for(size_t i = 0; i < objectSize; i++)
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001542 tempConstArray[i].setBConst(unionArray[i] < rightUnionArray[i]);
1543 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
John Bauman66b8ab22014-05-06 15:57:45 -04001544 break;
1545 case EOpGreaterThan:
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001546 tempConstArray = new ConstantUnion[objectSize];
Alexis Hetuab752792016-04-21 16:11:31 -04001547 for(size_t i = 0; i < objectSize; i++)
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001548 tempConstArray[i].setBConst(unionArray[i] > rightUnionArray[i]);
1549 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
John Bauman66b8ab22014-05-06 15:57:45 -04001550 break;
1551 case EOpLessThanEqual:
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001552 tempConstArray = new ConstantUnion[objectSize];
Alexis Hetuab752792016-04-21 16:11:31 -04001553 for(size_t i = 0; i < objectSize; i++)
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001554 tempConstArray[i].setBConst(unionArray[i] <= rightUnionArray[i]);
1555 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1556 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001557 case EOpGreaterThanEqual:
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001558 tempConstArray = new ConstantUnion[objectSize];
Alexis Hetuab752792016-04-21 16:11:31 -04001559 for(size_t i = 0; i < objectSize; i++)
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001560 tempConstArray[i].setBConst(unionArray[i] >= rightUnionArray[i]);
1561 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1562 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001563 case EOpEqual:
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001564 tempConstArray = new ConstantUnion[1];
1565
1566 if(getType().getBasicType() == EbtStruct) {
1567 tempConstArray->setBConst(CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray));
John Bauman66b8ab22014-05-06 15:57:45 -04001568 } else {
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001569 bool boolNodeFlag = true;
Alexis Hetuab752792016-04-21 16:11:31 -04001570 for (size_t i = 0; i < objectSize; i++) {
John Bauman66b8ab22014-05-06 15:57:45 -04001571 if (unionArray[i] != rightUnionArray[i]) {
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001572 boolNodeFlag = false;
John Bauman66b8ab22014-05-06 15:57:45 -04001573 break; // break out of for loop
1574 }
1575 }
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001576 tempConstArray->setBConst(boolNodeFlag);
John Bauman66b8ab22014-05-06 15:57:45 -04001577 }
1578
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001579 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001580 tempNode->setLine(getLine());
1581
1582 return tempNode;
1583
1584 case EOpNotEqual:
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001585 tempConstArray = new ConstantUnion[1];
1586
1587 if(getType().getBasicType() == EbtStruct) {
1588 tempConstArray->setBConst(!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray));
John Bauman66b8ab22014-05-06 15:57:45 -04001589 } else {
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001590 bool boolNodeFlag = false;
Alexis Hetuab752792016-04-21 16:11:31 -04001591 for (size_t i = 0; i < objectSize; i++) {
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001592 if (unionArray[i] != rightUnionArray[i]) {
John Bauman66b8ab22014-05-06 15:57:45 -04001593 boolNodeFlag = true;
1594 break; // break out of for loop
1595 }
1596 }
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001597 tempConstArray->setBConst(boolNodeFlag);
John Bauman66b8ab22014-05-06 15:57:45 -04001598 }
1599
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001600 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001601 tempNode->setLine(getLine());
1602
1603 return tempNode;
Nicolas Capens91dfb972016-04-09 23:45:12 -04001604 case EOpMax:
1605 tempConstArray = new ConstantUnion[objectSize];
1606 {// support MSVC++6.0
Alexis Hetuab752792016-04-21 16:11:31 -04001607 for (size_t i = 0; i < objectSize; i++)
Nicolas Capens91dfb972016-04-09 23:45:12 -04001608 tempConstArray[i] = unionArray[i] > rightUnionArray[i] ? unionArray[i] : rightUnionArray[i];
1609 }
1610 break;
1611 case EOpMin:
1612 tempConstArray = new ConstantUnion[objectSize];
1613 {// support MSVC++6.0
Alexis Hetuab752792016-04-21 16:11:31 -04001614 for (size_t i = 0; i < objectSize; i++)
Nicolas Capens91dfb972016-04-09 23:45:12 -04001615 tempConstArray[i] = unionArray[i] < rightUnionArray[i] ? unionArray[i] : rightUnionArray[i];
1616 }
1617 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001618 default:
John Bauman66b8ab22014-05-06 15:57:45 -04001619 return 0;
1620 }
1621 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1622 tempNode->setLine(getLine());
1623
1624 return tempNode;
1625 } else {
1626 //
1627 // Do unary operations
1628 //
1629 TIntermConstantUnion *newNode = 0;
1630 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
Alexis Hetuab752792016-04-21 16:11:31 -04001631 for (size_t i = 0; i < objectSize; i++) {
John Bauman66b8ab22014-05-06 15:57:45 -04001632 switch(op) {
1633 case EOpNegative:
1634 switch (getType().getBasicType()) {
1635 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1636 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1637 default:
1638 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1639 return 0;
1640 }
1641 break;
1642 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1643 switch (getType().getBasicType()) {
1644 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1645 default:
1646 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1647 return 0;
1648 }
1649 break;
Alexis Hetud061e422015-05-13 16:37:50 -04001650 case EOpBitwiseNot:
1651 switch(getType().getBasicType()) {
1652 case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
1653 case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
1654 default:
1655 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1656 return 0;
1657 }
1658 break;
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001659 case EOpRadians:
1660 switch(getType().getBasicType()) {
1661 case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 1.74532925e-2f); break;
1662 default:
1663 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1664 return 0;
1665 }
1666 break;
1667 case EOpDegrees:
1668 switch(getType().getBasicType()) {
1669 case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 5.72957795e+1f); break;
1670 default:
1671 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1672 return 0;
1673 }
1674 break;
1675 case EOpSin:
1676 switch(getType().getBasicType()) {
1677 case EbtFloat: tempConstArray[i].setFConst(sinf(unionArray[i].getFConst())); break;
1678 default:
1679 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1680 return 0;
1681 }
1682 break;
1683 case EOpCos:
1684 switch(getType().getBasicType()) {
1685 case EbtFloat: tempConstArray[i].setFConst(cosf(unionArray[i].getFConst())); break;
1686 default:
1687 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1688 return 0;
1689 }
1690 break;
1691 case EOpTan:
1692 switch(getType().getBasicType()) {
1693 case EbtFloat: tempConstArray[i].setFConst(tanf(unionArray[i].getFConst())); break;
1694 default:
1695 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1696 return 0;
1697 }
1698 break;
1699 case EOpAsin:
1700 switch(getType().getBasicType()) {
1701 case EbtFloat: tempConstArray[i].setFConst(asinf(unionArray[i].getFConst())); break;
1702 default:
1703 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1704 return 0;
1705 }
1706 break;
1707 case EOpAcos:
1708 switch(getType().getBasicType()) {
1709 case EbtFloat: tempConstArray[i].setFConst(acosf(unionArray[i].getFConst())); break;
1710 default:
1711 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1712 return 0;
1713 }
1714 break;
1715 case EOpAtan:
1716 switch(getType().getBasicType()) {
1717 case EbtFloat: tempConstArray[i].setFConst(atanf(unionArray[i].getFConst())); break;
1718 default:
1719 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1720 return 0;
1721 }
1722 break;
1723 case EOpSinh:
1724 switch(getType().getBasicType()) {
1725 case EbtFloat: tempConstArray[i].setFConst(sinhf(unionArray[i].getFConst())); break;
1726 default:
1727 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1728 return 0;
1729 }
1730 break;
1731 case EOpCosh:
1732 switch(getType().getBasicType()) {
1733 case EbtFloat: tempConstArray[i].setFConst(coshf(unionArray[i].getFConst())); break;
1734 default:
1735 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1736 return 0;
1737 }
1738 break;
1739 case EOpTanh:
1740 switch(getType().getBasicType()) {
1741 case EbtFloat: tempConstArray[i].setFConst(tanhf(unionArray[i].getFConst())); break;
1742 default:
1743 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1744 return 0;
1745 }
1746 break;
1747 case EOpAsinh:
1748 switch(getType().getBasicType()) {
1749 case EbtFloat: tempConstArray[i].setFConst(asinhf(unionArray[i].getFConst())); break;
1750 default:
1751 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1752 return 0;
1753 }
1754 break;
1755 case EOpAcosh:
1756 switch(getType().getBasicType()) {
1757 case EbtFloat: tempConstArray[i].setFConst(acoshf(unionArray[i].getFConst())); break;
1758 default:
1759 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1760 return 0;
1761 }
1762 break;
1763 case EOpAtanh:
1764 switch(getType().getBasicType()) {
1765 case EbtFloat: tempConstArray[i].setFConst(atanhf(unionArray[i].getFConst())); break;
1766 default:
1767 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1768 return 0;
1769 }
1770 break;
1771 case EOpLog:
1772 switch(getType().getBasicType()) {
1773 case EbtFloat: tempConstArray[i].setFConst(logf(unionArray[i].getFConst())); break;
1774 default:
1775 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1776 return 0;
1777 }
1778 break;
1779 case EOpLog2:
1780 switch(getType().getBasicType()) {
Alexis Hetu2ce222c2016-05-02 11:20:52 -04001781 case EbtFloat: tempConstArray[i].setFConst(sw::log2(unionArray[i].getFConst())); break;
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001782 default:
1783 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1784 return 0;
1785 }
1786 break;
1787 case EOpExp:
1788 switch(getType().getBasicType()) {
1789 case EbtFloat: tempConstArray[i].setFConst(expf(unionArray[i].getFConst())); break;
1790 default:
1791 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1792 return 0;
1793 }
1794 break;
1795 case EOpExp2:
1796 switch(getType().getBasicType()) {
1797 case EbtFloat: tempConstArray[i].setFConst(exp2f(unionArray[i].getFConst())); break;
1798 default:
1799 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1800 return 0;
1801 }
1802 break;
1803 case EOpSqrt:
1804 switch(getType().getBasicType()) {
1805 case EbtFloat: tempConstArray[i].setFConst(sqrtf(unionArray[i].getFConst())); break;
1806 default:
1807 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1808 return 0;
1809 }
1810 break;
1811 case EOpInverseSqrt:
1812 switch(getType().getBasicType()) {
1813 case EbtFloat: tempConstArray[i].setFConst(1.0f / sqrtf(unionArray[i].getFConst())); break;
1814 default:
1815 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1816 return 0;
1817 }
1818 break;
1819 default:
John Bauman66b8ab22014-05-06 15:57:45 -04001820 return 0;
1821 }
1822 }
1823 newNode = new TIntermConstantUnion(tempConstArray, getType());
1824 newNode->setLine(getLine());
1825 return newNode;
1826 }
1827}
1828
1829TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1830{
Alexis Hetuab752792016-04-21 16:11:31 -04001831 size_t size = node->getType().getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04001832
1833 ConstantUnion *leftUnionArray = new ConstantUnion[size];
1834
Alexis Hetuab752792016-04-21 16:11:31 -04001835 for(size_t i = 0; i < size; i++) {
John Bauman66b8ab22014-05-06 15:57:45 -04001836 switch (promoteTo) {
1837 case EbtFloat:
1838 switch (node->getType().getBasicType()) {
1839 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001840 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001841 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001842 case EbtUInt:
1843 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
1844 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001845 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001846 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001847 break;
1848 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001849 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001850 break;
1851 default:
1852 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1853 return 0;
1854 }
1855 break;
1856 case EbtInt:
1857 switch (node->getType().getBasicType()) {
1858 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001859 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001860 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001861 case EbtUInt:
1862 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
1863 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001864 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001865 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001866 break;
1867 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001868 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001869 break;
1870 default:
1871 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1872 return 0;
1873 }
1874 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001875 case EbtUInt:
1876 switch (node->getType().getBasicType()) {
1877 case EbtInt:
1878 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
1879 break;
1880 case EbtUInt:
1881 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
1882 break;
1883 case EbtBool:
1884 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
1885 break;
1886 case EbtFloat:
1887 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
1888 break;
1889 default:
1890 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1891 return 0;
1892 }
1893 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001894 case EbtBool:
1895 switch (node->getType().getBasicType()) {
1896 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001897 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
John Bauman66b8ab22014-05-06 15:57:45 -04001898 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001899 case EbtUInt:
1900 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
1901 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001902 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001903 leftUnionArray[i].setBConst(node->getBConst(i));
John Bauman66b8ab22014-05-06 15:57:45 -04001904 break;
1905 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001906 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
John Bauman66b8ab22014-05-06 15:57:45 -04001907 break;
1908 default:
1909 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1910 return 0;
1911 }
1912
1913 break;
1914 default:
1915 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1916 return 0;
1917 }
1918
1919 }
1920
1921 const TType& t = node->getType();
1922
Alexis Hetub14178b2015-04-13 13:23:20 -04001923 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001924}
1925