blob: eb339729f5e6a0b4174dbec141afb6b81246bf2d [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"
John Bauman66b8ab22014-05-06 15:57:45 -040017
18bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
19
20static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){
21 return left > right ? left : right;
22}
23
Alexis Hetu00106d42015-04-23 11:45:35 -040024static bool ValidateMultiplication(TOperator op, const TType &left, const TType &right)
25{
26 switch(op)
27 {
28 case EOpMul:
29 case EOpMulAssign:
30 return left.getNominalSize() == right.getNominalSize() &&
31 left.getSecondarySize() == right.getSecondarySize();
32 case EOpVectorTimesScalar:
33 case EOpVectorTimesScalarAssign:
34 return true;
35 case EOpVectorTimesMatrix:
36 return left.getNominalSize() == right.getSecondarySize();
37 case EOpVectorTimesMatrixAssign:
38 return left.getNominalSize() == right.getSecondarySize() &&
39 left.getNominalSize() == right.getNominalSize();
40 case EOpMatrixTimesVector:
41 return left.getNominalSize() == right.getNominalSize();
42 case EOpMatrixTimesScalar:
43 case EOpMatrixTimesScalarAssign:
44 return true;
45 case EOpMatrixTimesMatrix:
46 return left.getNominalSize() == right.getSecondarySize();
47 case EOpMatrixTimesMatrixAssign:
48 return left.getNominalSize() == right.getNominalSize() &&
49 left.getSecondarySize() == right.getSecondarySize();
50 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -040051 UNREACHABLE(op);
Alexis Hetu00106d42015-04-23 11:45:35 -040052 return false;
53 }
54}
55
John Bauman66b8ab22014-05-06 15:57:45 -040056const char* getOperatorString(TOperator op) {
57 switch (op) {
58 case EOpInitialize: return "=";
59 case EOpAssign: return "=";
60 case EOpAddAssign: return "+=";
61 case EOpSubAssign: return "-=";
62 case EOpDivAssign: return "/=";
Alexis Hetu17809052015-05-13 11:28:22 -040063 case EOpIModAssign: return "%=";
64 case EOpBitShiftLeftAssign: return "<<=";
65 case EOpBitShiftRightAssign: return ">>=";
66 case EOpBitwiseAndAssign: return "&=";
67 case EOpBitwiseXorAssign: return "^=";
68 case EOpBitwiseOrAssign: return "|=";
John Bauman66b8ab22014-05-06 15:57:45 -040069
70 // Fall-through.
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -040071 case EOpMulAssign:
John Bauman66b8ab22014-05-06 15:57:45 -040072 case EOpVectorTimesMatrixAssign:
73 case EOpVectorTimesScalarAssign:
74 case EOpMatrixTimesScalarAssign:
75 case EOpMatrixTimesMatrixAssign: return "*=";
76
77 // Fall-through.
78 case EOpIndexDirect:
79 case EOpIndexIndirect: return "[]";
80
81 case EOpIndexDirectStruct: return ".";
82 case EOpVectorSwizzle: return ".";
83 case EOpAdd: return "+";
84 case EOpSub: return "-";
85 case EOpMul: return "*";
86 case EOpDiv: return "/";
87 case EOpMod: UNIMPLEMENTED(); break;
88 case EOpEqual: return "==";
89 case EOpNotEqual: return "!=";
90 case EOpLessThan: return "<";
91 case EOpGreaterThan: return ">";
92 case EOpLessThanEqual: return "<=";
93 case EOpGreaterThanEqual: return ">=";
94
95 // Fall-through.
96 case EOpVectorTimesScalar:
97 case EOpVectorTimesMatrix:
98 case EOpMatrixTimesVector:
99 case EOpMatrixTimesScalar:
100 case EOpMatrixTimesMatrix: return "*";
101
102 case EOpLogicalOr: return "||";
103 case EOpLogicalXor: return "^^";
104 case EOpLogicalAnd: return "&&";
Alexis Hetu17809052015-05-13 11:28:22 -0400105 case EOpIMod: return "%";
106 case EOpBitShiftLeft: return "<<";
107 case EOpBitShiftRight: return ">>";
108 case EOpBitwiseAnd: return "&";
109 case EOpBitwiseXor: return "^";
110 case EOpBitwiseOr: return "|";
John Bauman66b8ab22014-05-06 15:57:45 -0400111 case EOpNegative: return "-";
112 case EOpVectorLogicalNot: return "not";
113 case EOpLogicalNot: return "!";
Alexis Hetu17809052015-05-13 11:28:22 -0400114 case EOpBitwiseNot: return "~";
John Bauman66b8ab22014-05-06 15:57:45 -0400115 case EOpPostIncrement: return "++";
116 case EOpPostDecrement: return "--";
117 case EOpPreIncrement: return "++";
118 case EOpPreDecrement: return "--";
119
John Bauman66b8ab22014-05-06 15:57:45 -0400120 case EOpRadians: return "radians";
121 case EOpDegrees: return "degrees";
122 case EOpSin: return "sin";
123 case EOpCos: return "cos";
124 case EOpTan: return "tan";
125 case EOpAsin: return "asin";
126 case EOpAcos: return "acos";
127 case EOpAtan: return "atan";
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400128 case EOpSinh: return "sinh";
129 case EOpCosh: return "cosh";
130 case EOpTanh: return "tanh";
131 case EOpAsinh: return "asinh";
132 case EOpAcosh: return "acosh";
133 case EOpAtanh: return "atanh";
John Bauman66b8ab22014-05-06 15:57:45 -0400134 case EOpExp: return "exp";
135 case EOpLog: return "log";
136 case EOpExp2: return "exp2";
137 case EOpLog2: return "log2";
138 case EOpSqrt: return "sqrt";
139 case EOpInverseSqrt: return "inversesqrt";
140 case EOpAbs: return "abs";
141 case EOpSign: return "sign";
142 case EOpFloor: return "floor";
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400143 case EOpTrunc: return "trunc";
144 case EOpRound: return "round";
145 case EOpRoundEven: return "roundEven";
John Bauman66b8ab22014-05-06 15:57:45 -0400146 case EOpCeil: return "ceil";
147 case EOpFract: return "fract";
148 case EOpLength: return "length";
149 case EOpNormalize: return "normalize";
150 case EOpDFdx: return "dFdx";
151 case EOpDFdy: return "dFdy";
152 case EOpFwidth: return "fwidth";
153 case EOpAny: return "any";
154 case EOpAll: return "all";
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400155 case EOpIsNan: return "isnan";
156 case EOpIsInf: return "isinf";
Alexis Hetu3815b6c2015-05-27 11:21:37 -0400157 case EOpOuterProduct: return "outerProduct";
158 case EOpTranspose: return "transpose";
159 case EOpDeterminant: return "determinant";
160 case EOpInverse: return "inverse";
John Bauman66b8ab22014-05-06 15:57:45 -0400161
162 default: break;
163 }
164 return "";
165}
166
167////////////////////////////////////////////////////////////////////////////
168//
169// First set of functions are to help build the intermediate representation.
170// These functions are not member functions of the nodes.
171// They are called from parser productions.
172//
173/////////////////////////////////////////////////////////////////////////////
174
175//
176// Add a terminal node for an identifier in an expression.
177//
178// Returns the added node.
179//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400180TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400181{
182 TIntermSymbol* node = new TIntermSymbol(id, name, type);
183 node->setLine(line);
184
185 return node;
186}
187
188//
189// Connect two nodes with a new parent that does a binary operation on the nodes.
190//
191// Returns the added node.
192//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400193TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400194{
Alexis Hetu92ab1982015-08-18 15:28:27 -0400195 bool isBitShift = false;
John Bauman66b8ab22014-05-06 15:57:45 -0400196 switch (op) {
197 case EOpEqual:
198 case EOpNotEqual:
199 if (left->isArray())
200 return 0;
201 break;
202 case EOpLessThan:
203 case EOpGreaterThan:
204 case EOpLessThanEqual:
205 case EOpGreaterThanEqual:
206 if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
207 return 0;
208 }
209 break;
210 case EOpLogicalOr:
211 case EOpLogicalXor:
212 case EOpLogicalAnd:
213 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
214 return 0;
215 }
216 break;
Alexis Hetud061e422015-05-13 16:37:50 -0400217 case EOpBitwiseOr:
218 case EOpBitwiseXor:
219 case EOpBitwiseAnd:
Alexis Hetu9085c8d2015-06-01 13:48:07 -0400220 if (!IsInteger(left->getBasicType()) || left->isMatrix() || left->isArray()) {
Alexis Hetud061e422015-05-13 16:37:50 -0400221 return 0;
222 }
223 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400224 case EOpAdd:
225 case EOpSub:
226 case EOpDiv:
227 case EOpMul:
Alexis Hetud061e422015-05-13 16:37:50 -0400228 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) {
John Bauman66b8ab22014-05-06 15:57:45 -0400229 return 0;
Alexis Hetud061e422015-05-13 16:37:50 -0400230 }
231 break;
232 case EOpIMod:
233 // Note that this is only for the % operator, not for mod()
234 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat) {
235 return 0;
236 }
237 break;
Alexis Hetu92ab1982015-08-18 15:28:27 -0400238 case EOpBitShiftLeft:
239 case EOpBitShiftRight:
240 case EOpBitShiftLeftAssign:
241 case EOpBitShiftRightAssign:
242 // Unsigned can be bit-shifted by signed and vice versa, but we need to
243 // check that the basic type is an integer type.
244 isBitShift = true;
245 if(!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
246 {
247 return 0;
248 }
249 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400250 default: break;
251 }
252
Alexis Hetu92ab1982015-08-18 15:28:27 -0400253 if(!isBitShift && left->getBasicType() != right->getBasicType())
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400254 {
255 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400256 }
257
258 //
259 // Need a new node holding things together then. Make
260 // one and promote it to the right type.
261 //
262 TIntermBinary* node = new TIntermBinary(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400263 node->setLine(line);
264
265 node->setLeft(left);
266 node->setRight(right);
267 if (!node->promote(infoSink))
268 return 0;
269
270 //
271 // See if we can fold constants.
272 //
John Bauman66b8ab22014-05-06 15:57:45 -0400273 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
274 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
275 if (leftTempConstant && rightTempConstant) {
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400276 TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
John Bauman66b8ab22014-05-06 15:57:45 -0400277
278 if (typedReturnNode)
279 return typedReturnNode;
280 }
281
282 return node;
283}
284
285//
286// Connect two nodes through an assignment.
287//
288// Returns the added node.
289//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400290TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400291{
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400292 if (left->getType().getStruct() || right->getType().getStruct())
293 {
294 if (left->getType() != right->getType())
295 {
296 return 0;
297 }
298 }
299
John Bauman66b8ab22014-05-06 15:57:45 -0400300 TIntermBinary* node = new TIntermBinary(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400301 node->setLine(line);
302
John Bauman66b8ab22014-05-06 15:57:45 -0400303 node->setLeft(left);
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400304 node->setRight(right);
John Bauman66b8ab22014-05-06 15:57:45 -0400305 if (! node->promote(infoSink))
306 return 0;
307
308 return node;
309}
310
311//
312// Connect two nodes through an index operator, where the left node is the base
313// of an array or struct, and the right node is a direct or indirect offset.
314//
315// Returns the added node.
316// The caller should set the type of the returned node.
317//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400318TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400319{
320 TIntermBinary* node = new TIntermBinary(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400321 node->setLine(line);
322 node->setLeft(base);
323 node->setRight(index);
324
325 // caller should set the type
326
327 return node;
328}
329
330//
331// Add one node as the parent of another that it operates on.
332//
333// Returns the added node.
334//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400335TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400336{
337 TIntermUnary* node;
338 TIntermTyped* child = childNode->getAsTyped();
339
340 if (child == 0) {
341 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
342 return 0;
343 }
344
345 switch (op) {
Alexis Hetud061e422015-05-13 16:37:50 -0400346 case EOpBitwiseNot:
Alexis Hetu9085c8d2015-06-01 13:48:07 -0400347 if (!IsInteger(child->getType().getBasicType()) || child->getType().isMatrix() || child->getType().isArray()) {
Alexis Hetud061e422015-05-13 16:37:50 -0400348 return 0;
349 }
350 break;
351
John Bauman66b8ab22014-05-06 15:57:45 -0400352 case EOpLogicalNot:
353 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
354 return 0;
355 }
356 break;
357
358 case EOpPostIncrement:
359 case EOpPreIncrement:
360 case EOpPostDecrement:
361 case EOpPreDecrement:
362 case EOpNegative:
363 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
364 return 0;
365 default: break;
366 }
367
John Bauman66b8ab22014-05-06 15:57:45 -0400368 TIntermConstantUnion *childTempConstant = 0;
369 if (child->getAsConstantUnion())
370 childTempConstant = child->getAsConstantUnion();
371
372 //
373 // Make a new node for the operator.
374 //
375 node = new TIntermUnary(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400376 node->setLine(line);
377 node->setOperand(child);
378
379 if (! node->promote(infoSink))
380 return 0;
381
382 if (childTempConstant) {
383 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
384
385 if (newChild)
386 return newChild;
387 }
388
389 return node;
390}
391
392//
393// This is the safe way to change the operator on an aggregate, as it
394// does lots of error checking and fixing. Especially for establishing
395// a function call's operation on it's set of parameters. Sequences
396// of instructions are also aggregates, but they just direnctly set
397// their operator to EOpSequence.
398//
399// Returns an aggregate node, which could be the one passed in if
400// it was already an aggregate but no operator was set.
401//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400402TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400403{
404 TIntermAggregate* aggNode;
405
406 //
407 // Make sure we have an aggregate. If not turn it into one.
408 //
409 if (node) {
410 aggNode = node->getAsAggregate();
411 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
412 //
413 // Make an aggregate containing this node.
414 //
415 aggNode = new TIntermAggregate();
416 aggNode->getSequence().push_back(node);
John Bauman66b8ab22014-05-06 15:57:45 -0400417 }
418 } else
419 aggNode = new TIntermAggregate();
420
421 //
422 // Set the operator.
423 //
424 aggNode->setOp(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400425
426 return aggNode;
427}
428
429//
John Bauman66b8ab22014-05-06 15:57:45 -0400430// Safe way to combine two nodes into an aggregate. Works with null pointers,
431// a node that's not a aggregate yet, etc.
432//
433// Returns the resulting aggregate, unless 0 was passed in for
434// both existing nodes.
435//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400436TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400437{
438 if (left == 0 && right == 0)
439 return 0;
440
441 TIntermAggregate* aggNode = 0;
442 if (left)
443 aggNode = left->getAsAggregate();
444 if (!aggNode || aggNode->getOp() != EOpNull) {
445 aggNode = new TIntermAggregate;
446 if (left)
447 aggNode->getSequence().push_back(left);
448 }
449
450 if (right)
451 aggNode->getSequence().push_back(right);
452
Alexis Hetu253fdd12015-07-07 15:12:46 -0400453 aggNode->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400454
455 return aggNode;
456}
457
458//
459// Turn an existing node into an aggregate.
460//
461// Returns an aggregate, unless 0 was passed in for the existing node.
462//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400463TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400464{
465 if (node == 0)
466 return 0;
467
468 TIntermAggregate* aggNode = new TIntermAggregate;
469 aggNode->getSequence().push_back(node);
470
Alexis Hetu253fdd12015-07-07 15:12:46 -0400471 aggNode->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400472
473 return aggNode;
474}
475
476//
477// For "if" test nodes. There are three children; a condition,
478// a true path, and a false path. The two paths are in the
479// nodePair.
480//
481// Returns the selection node created.
482//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400483TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400484{
485 //
486 // For compile time constant selections, prune the code and
487 // test now.
488 //
489
490 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
Nicolas Capens198529d2015-02-10 13:54:19 -0500491 if (cond->getAsConstantUnion()->getBConst(0) == true)
John Bauman66b8ab22014-05-06 15:57:45 -0400492 return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
493 else
494 return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
495 }
496
497 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
498 node->setLine(line);
499
500 return node;
501}
502
503
Alexis Hetu253fdd12015-07-07 15:12:46 -0400504TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400505{
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500506 if (left->getType().getQualifier() == EvqConstExpr && right->getType().getQualifier() == EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400507 return right;
508 } else {
509 TIntermTyped *commaAggregate = growAggregate(left, right, line);
510 commaAggregate->getAsAggregate()->setOp(EOpComma);
511 commaAggregate->setType(right->getType());
512 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
513 return commaAggregate;
514 }
515}
516
517//
518// For "?:" test nodes. There are three children; a condition,
519// a true path, and a false path. The two paths are specified
520// as separate parameters.
521//
522// Returns the selection node created, or 0 if one could not be.
523//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400524TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400525{
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400526 if (trueBlock->getType() != falseBlock->getType())
527 {
528 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400529 }
530
531 //
532 // See if all the operands are constant, then fold it otherwise not.
533 //
534
535 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
Nicolas Capens198529d2015-02-10 13:54:19 -0500536 if (cond->getAsConstantUnion()->getBConst(0))
John Bauman66b8ab22014-05-06 15:57:45 -0400537 return trueBlock;
538 else
539 return falseBlock;
540 }
541
542 //
543 // Make a selection node.
544 //
545 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
546 node->getTypePointer()->setQualifier(EvqTemporary);
547 node->setLine(line);
548
549 return node;
550}
551
Alexis Hetu76a343a2015-06-04 17:21:22 -0400552TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
553{
554 TIntermSwitch *node = new TIntermSwitch(init, statementList);
555 node->setLine(line);
556
557 return node;
558}
559
560TIntermCase *TIntermediate::addCase(TIntermTyped *condition, const TSourceLoc &line)
561{
562 TIntermCase *node = new TIntermCase(condition);
563 node->setLine(line);
564
565 return node;
566}
567
John Bauman66b8ab22014-05-06 15:57:45 -0400568//
569// Constant terminal nodes. Has a union that contains bool, float or int constants
570//
571// Returns the constant union node created.
572//
573
Alexis Hetu253fdd12015-07-07 15:12:46 -0400574TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400575{
576 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
577 node->setLine(line);
578
579 return node;
580}
581
Alexis Hetu253fdd12015-07-07 15:12:46 -0400582TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400583{
584
585 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
586
587 node->setLine(line);
588 TIntermConstantUnion* constIntNode;
589 TIntermSequence &sequenceVector = node->getSequence();
590 ConstantUnion* unionArray;
591
592 for (int i = 0; i < fields.num; i++) {
593 unionArray = new ConstantUnion[1];
594 unionArray->setIConst(fields.offsets[i]);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500595 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), line);
John Bauman66b8ab22014-05-06 15:57:45 -0400596 sequenceVector.push_back(constIntNode);
597 }
598
599 return node;
600}
601
602//
603// Create loop nodes.
604//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400605TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400606{
607 TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
608 node->setLine(line);
609
610 return node;
611}
612
613//
614// Add branches.
615//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400616TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400617{
618 return addBranch(branchOp, 0, line);
619}
620
Alexis Hetu253fdd12015-07-07 15:12:46 -0400621TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400622{
623 TIntermBranch* node = new TIntermBranch(branchOp, expression);
624 node->setLine(line);
625
626 return node;
627}
628
629//
630// This is to be executed once the final root is put on top by the parsing
631// process.
632//
633bool TIntermediate::postProcess(TIntermNode* root)
634{
635 if (root == 0)
636 return true;
637
638 //
639 // First, finish off the top level sequence, if any
640 //
641 TIntermAggregate* aggRoot = root->getAsAggregate();
642 if (aggRoot && aggRoot->getOp() == EOpNull)
643 aggRoot->setOp(EOpSequence);
644
645 return true;
646}
647
John Bauman66b8ab22014-05-06 15:57:45 -0400648////////////////////////////////////////////////////////////////
649//
650// Member functions of the nodes used for building the tree.
651//
652////////////////////////////////////////////////////////////////
653
654//
655// Say whether or not an operation node changes the value of a variable.
656//
657// Returns true if state is modified.
658//
659bool TIntermOperator::modifiesState() const
660{
661 switch (op) {
662 case EOpPostIncrement:
663 case EOpPostDecrement:
664 case EOpPreIncrement:
665 case EOpPreDecrement:
666 case EOpAssign:
667 case EOpAddAssign:
668 case EOpSubAssign:
669 case EOpMulAssign:
670 case EOpVectorTimesMatrixAssign:
671 case EOpVectorTimesScalarAssign:
672 case EOpMatrixTimesScalarAssign:
673 case EOpMatrixTimesMatrixAssign:
674 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400675 case EOpIModAssign:
676 case EOpBitShiftLeftAssign:
677 case EOpBitShiftRightAssign:
678 case EOpBitwiseAndAssign:
679 case EOpBitwiseXorAssign:
680 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400681 return true;
682 default:
683 return false;
684 }
685}
686
687//
688// returns true if the operator is for one of the constructors
689//
690bool TIntermOperator::isConstructor() const
691{
692 switch (op) {
693 case EOpConstructVec2:
694 case EOpConstructVec3:
695 case EOpConstructVec4:
696 case EOpConstructMat2:
Alexis Hetu00106d42015-04-23 11:45:35 -0400697 case EOpConstructMat2x3:
698 case EOpConstructMat2x4:
699 case EOpConstructMat3x2:
John Bauman66b8ab22014-05-06 15:57:45 -0400700 case EOpConstructMat3:
Alexis Hetu00106d42015-04-23 11:45:35 -0400701 case EOpConstructMat3x4:
702 case EOpConstructMat4x2:
703 case EOpConstructMat4x3:
John Bauman66b8ab22014-05-06 15:57:45 -0400704 case EOpConstructMat4:
705 case EOpConstructFloat:
706 case EOpConstructIVec2:
707 case EOpConstructIVec3:
708 case EOpConstructIVec4:
709 case EOpConstructInt:
Nicolas Capense4b1b1d2015-02-17 17:26:01 -0500710 case EOpConstructUVec2:
711 case EOpConstructUVec3:
712 case EOpConstructUVec4:
Nicolas Capens3c20f802015-02-17 17:17:20 -0500713 case EOpConstructUInt:
John Bauman66b8ab22014-05-06 15:57:45 -0400714 case EOpConstructBVec2:
715 case EOpConstructBVec3:
716 case EOpConstructBVec4:
717 case EOpConstructBool:
718 case EOpConstructStruct:
719 return true;
720 default:
721 return false;
722 }
723}
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400724
John Bauman66b8ab22014-05-06 15:57:45 -0400725//
726// Make sure the type of a unary operator is appropriate for its
727// combination of operation and operand type.
728//
729// Returns false in nothing makes sense.
730//
731bool TIntermUnary::promote(TInfoSink&)
732{
733 switch (op) {
734 case EOpLogicalNot:
735 if (operand->getBasicType() != EbtBool)
736 return false;
737 break;
Alexis Hetud061e422015-05-13 16:37:50 -0400738 case EOpBitwiseNot:
Alexis Hetu9085c8d2015-06-01 13:48:07 -0400739 if (!IsInteger(operand->getBasicType()))
Alexis Hetud061e422015-05-13 16:37:50 -0400740 return false;
741 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400742 case EOpNegative:
743 case EOpPostIncrement:
744 case EOpPostDecrement:
745 case EOpPreIncrement:
746 case EOpPreDecrement:
747 if (operand->getBasicType() == EbtBool)
748 return false;
749 break;
750
751 // operators for built-ins are already type checked against their prototype
752 case EOpAny:
753 case EOpAll:
754 case EOpVectorLogicalNot:
Alexis Hetu0f448072016-03-18 10:56:08 -0400755 case EOpAbs:
756 case EOpSign:
757 case EOpIsNan:
758 case EOpIsInf:
759 case EOpFloatBitsToInt:
760 case EOpFloatBitsToUint:
761 case EOpIntBitsToFloat:
762 case EOpUintBitsToFloat:
763 case EOpPackSnorm2x16:
764 case EOpPackUnorm2x16:
765 case EOpPackHalf2x16:
766 case EOpUnpackSnorm2x16:
767 case EOpUnpackUnorm2x16:
768 case EOpUnpackHalf2x16:
John Bauman66b8ab22014-05-06 15:57:45 -0400769 return true;
770
771 default:
772 if (operand->getBasicType() != EbtFloat)
773 return false;
774 }
775
776 setType(operand->getType());
777
778 // Unary operations results in temporary variables unless const.
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500779 if (operand->getQualifier() != EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400780 getTypePointer()->setQualifier(EvqTemporary);
781 }
782
783 return true;
784}
785
786//
787// Establishes the type of the resultant operation, as well as
788// makes the operator the correct one for the operands.
789//
790// Returns false if operator can't work on operands.
791//
792bool TIntermBinary::promote(TInfoSink& infoSink)
793{
Alexis Hetue5246692015-06-18 12:34:52 -0400794 ASSERT(left->isArray() == right->isArray());
John Bauman66b8ab22014-05-06 15:57:45 -0400795
796 // GLSL ES 2.0 does not support implicit type casting.
797 // So the basic type should always match.
Alexis Hetu92ab1982015-08-18 15:28:27 -0400798 // GLSL ES 3.0 supports integer shift operands of different signedness.
799 if(op != EOpBitShiftLeft &&
800 op != EOpBitShiftRight &&
801 op != EOpBitShiftLeftAssign &&
802 op != EOpBitShiftRightAssign &&
803 left->getBasicType() != right->getBasicType())
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400804 {
John Bauman66b8ab22014-05-06 15:57:45 -0400805 return false;
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400806 }
John Bauman66b8ab22014-05-06 15:57:45 -0400807
808 //
809 // Base assumption: just make the type the same as the left
810 // operand. Then only deviations from this need be coded.
811 //
812 setType(left->getType());
813
814 // The result gets promoted to the highest precision.
815 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
816 getTypePointer()->setPrecision(higherPrecision);
817
818 // Binary operations results in temporary variables unless both
819 // operands are const.
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500820 if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400821 getTypePointer()->setQualifier(EvqTemporary);
822 }
823
Alexis Hetud061e422015-05-13 16:37:50 -0400824 int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
John Bauman66b8ab22014-05-06 15:57:45 -0400825
826 //
827 // All scalars. Code after this test assumes this case is removed!
828 //
Alexis Hetud061e422015-05-13 16:37:50 -0400829 if (primarySize == 1) {
John Bauman66b8ab22014-05-06 15:57:45 -0400830 switch (op) {
831 //
832 // Promote to conditional
833 //
834 case EOpEqual:
835 case EOpNotEqual:
836 case EOpLessThan:
837 case EOpGreaterThan:
838 case EOpLessThanEqual:
839 case EOpGreaterThanEqual:
840 setType(TType(EbtBool, EbpUndefined));
841 break;
842
843 //
844 // And and Or operate on conditionals
845 //
846 case EOpLogicalAnd:
847 case EOpLogicalOr:
Alexis Hetud061e422015-05-13 16:37:50 -0400848 case EOpLogicalXor:
John Bauman66b8ab22014-05-06 15:57:45 -0400849 // Both operands must be of type bool.
850 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
851 return false;
852 setType(TType(EbtBool, EbpUndefined));
853 break;
854
855 default:
856 break;
857 }
858 return true;
859 }
860
861 // If we reach here, at least one of the operands is vector or matrix.
862 // The other operand could be a scalar, vector, or matrix.
John Bauman66b8ab22014-05-06 15:57:45 -0400863 // Can these two operands be combined?
864 //
865 TBasicType basicType = left->getBasicType();
866 switch (op) {
867 case EOpMul:
868 if (!left->isMatrix() && right->isMatrix()) {
869 if (left->isVector())
Alexis Hetu00106d42015-04-23 11:45:35 -0400870 {
John Bauman66b8ab22014-05-06 15:57:45 -0400871 op = EOpVectorTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400872 setType(TType(basicType, higherPrecision, EvqTemporary,
873 static_cast<unsigned char>(right->getNominalSize()), 1));
874 }
John Bauman66b8ab22014-05-06 15:57:45 -0400875 else {
876 op = EOpMatrixTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400877 setType(TType(basicType, higherPrecision, EvqTemporary,
878 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400879 }
880 } else if (left->isMatrix() && !right->isMatrix()) {
881 if (right->isVector()) {
882 op = EOpMatrixTimesVector;
Alexis Hetu00106d42015-04-23 11:45:35 -0400883 setType(TType(basicType, higherPrecision, EvqTemporary,
884 static_cast<unsigned char>(left->getSecondarySize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400885 } else {
886 op = EOpMatrixTimesScalar;
887 }
888 } else if (left->isMatrix() && right->isMatrix()) {
889 op = EOpMatrixTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400890 setType(TType(basicType, higherPrecision, EvqTemporary,
891 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400892 } else if (!left->isMatrix() && !right->isMatrix()) {
893 if (left->isVector() && right->isVector()) {
894 // leave as component product
895 } else if (left->isVector() || right->isVector()) {
896 op = EOpVectorTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400897 setType(TType(basicType, higherPrecision, EvqTemporary,
898 static_cast<unsigned char>(primarySize), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400899 }
900 } else {
901 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
902 return false;
903 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400904
905 if(!ValidateMultiplication(op, left->getType(), right->getType()))
906 {
907 return false;
908 }
John Bauman66b8ab22014-05-06 15:57:45 -0400909 break;
910 case EOpMulAssign:
911 if (!left->isMatrix() && right->isMatrix()) {
912 if (left->isVector())
913 op = EOpVectorTimesMatrixAssign;
914 else {
915 return false;
916 }
917 } else if (left->isMatrix() && !right->isMatrix()) {
918 if (right->isVector()) {
919 return false;
920 } else {
921 op = EOpMatrixTimesScalarAssign;
922 }
923 } else if (left->isMatrix() && right->isMatrix()) {
924 op = EOpMatrixTimesMatrixAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400925 setType(TType(basicType, higherPrecision, EvqTemporary,
926 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400927 } else if (!left->isMatrix() && !right->isMatrix()) {
928 if (left->isVector() && right->isVector()) {
929 // leave as component product
930 } else if (left->isVector() || right->isVector()) {
931 if (! left->isVector())
932 return false;
933 op = EOpVectorTimesScalarAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400934 setType(TType(basicType, higherPrecision, EvqTemporary,
935 static_cast<unsigned char>(left->getNominalSize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400936 }
937 } else {
938 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
939 return false;
940 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400941
942 if(!ValidateMultiplication(op, left->getType(), right->getType()))
943 {
944 return false;
945 }
John Bauman66b8ab22014-05-06 15:57:45 -0400946 break;
947
948 case EOpAssign:
949 case EOpInitialize:
Alexis Hetu00106d42015-04-23 11:45:35 -0400950 // No more additional checks are needed.
951 if ((left->getNominalSize() != right->getNominalSize()) ||
952 (left->getSecondarySize() != right->getSecondarySize()))
953 return false;
954 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400955 case EOpAdd:
956 case EOpSub:
957 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -0400958 case EOpIMod:
959 case EOpBitShiftLeft:
960 case EOpBitShiftRight:
961 case EOpBitwiseAnd:
962 case EOpBitwiseXor:
963 case EOpBitwiseOr:
John Bauman66b8ab22014-05-06 15:57:45 -0400964 case EOpAddAssign:
965 case EOpSubAssign:
966 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400967 case EOpIModAssign:
968 case EOpBitShiftLeftAssign:
969 case EOpBitShiftRightAssign:
970 case EOpBitwiseAndAssign:
971 case EOpBitwiseXorAssign:
972 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400973 if ((left->isMatrix() && right->isVector()) ||
974 (left->isVector() && right->isMatrix()))
975 return false;
Alexis Hetud061e422015-05-13 16:37:50 -0400976
977 // Are the sizes compatible?
978 if(left->getNominalSize() != right->getNominalSize() ||
979 left->getSecondarySize() != right->getSecondarySize())
980 {
981 // If the nominal sizes of operands do not match:
982 // One of them must be a scalar.
983 if(!left->isScalar() && !right->isScalar())
984 return false;
985
986 // In the case of compound assignment other than multiply-assign,
987 // the right side needs to be a scalar. Otherwise a vector/matrix
988 // would be assigned to a scalar. A scalar can't be shifted by a
989 // vector either.
990 if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight))
991 return false;
992 }
993
994 {
Alexis Hetu00106d42015-04-23 11:45:35 -0400995 const int secondarySize = std::max(
996 left->getSecondarySize(), right->getSecondarySize());
Alexis Hetud061e422015-05-13 16:37:50 -0400997 setType(TType(basicType, higherPrecision, EvqTemporary,
998 static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
999 if(left->isArray())
1000 {
1001 ASSERT(left->getArraySize() == right->getArraySize());
1002 type.setArraySize(left->getArraySize());
1003 }
1004 }
John Bauman66b8ab22014-05-06 15:57:45 -04001005 break;
1006
1007 case EOpEqual:
1008 case EOpNotEqual:
1009 case EOpLessThan:
1010 case EOpGreaterThan:
1011 case EOpLessThanEqual:
1012 case EOpGreaterThanEqual:
Alexis Hetu00106d42015-04-23 11:45:35 -04001013 if ((left->getNominalSize() != right->getNominalSize()) ||
1014 (left->getSecondarySize() != right->getSecondarySize()))
John Bauman66b8ab22014-05-06 15:57:45 -04001015 return false;
1016 setType(TType(EbtBool, EbpUndefined));
1017 break;
1018
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001019 case EOpOuterProduct:
1020 if(!left->isVector() || !right->isVector())
1021 return false;
1022 setType(TType(EbtFloat, right->getNominalSize(), left->getNominalSize()));
1023 break;
1024
1025 case EOpTranspose:
1026 if(!right->isMatrix())
1027 return false;
1028 setType(TType(EbtFloat, right->getSecondarySize(), right->getNominalSize()));
1029 break;
1030
1031 case EOpDeterminant:
1032 if(!right->isMatrix())
1033 return false;
1034 setType(TType(EbtFloat));
1035 break;
1036
1037 case EOpInverse:
1038 if(!right->isMatrix() || right->getNominalSize() != right->getSecondarySize())
1039 return false;
1040 setType(right->getType());
1041 break;
1042
John Bauman66b8ab22014-05-06 15:57:45 -04001043 default:
1044 return false;
1045 }
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001046
John Bauman66b8ab22014-05-06 15:57:45 -04001047 return true;
1048}
1049
1050bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1051{
Alexis Hetua8b364b2015-06-10 11:48:40 -04001052 const TFieldList& fields = leftNodeType.getStruct()->fields();
John Bauman66b8ab22014-05-06 15:57:45 -04001053
Alexis Hetua8b364b2015-06-10 11:48:40 -04001054 size_t structSize = fields.size();
John Bauman66b8ab22014-05-06 15:57:45 -04001055 int index = 0;
1056
1057 for (size_t j = 0; j < structSize; j++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001058 int size = fields[j]->type()->getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04001059 for (int i = 0; i < size; i++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001060 if (fields[j]->type()->getBasicType() == EbtStruct) {
1061 if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
John Bauman66b8ab22014-05-06 15:57:45 -04001062 return false;
1063 } else {
1064 if (leftUnionArray[index] != rightUnionArray[index])
1065 return false;
1066 index++;
1067 }
1068
1069 }
1070 }
1071 return true;
1072}
1073
1074bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1075{
1076 if (leftNodeType.isArray()) {
1077 TType typeWithoutArrayness = leftNodeType;
1078 typeWithoutArrayness.clearArrayness();
1079
1080 int arraySize = leftNodeType.getArraySize();
1081
1082 for (int i = 0; i < arraySize; ++i) {
1083 int offset = typeWithoutArrayness.getObjectSize() * i;
1084 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1085 return false;
1086 }
1087 } else
1088 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
1089
1090 return true;
1091}
1092
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001093float determinant2(float m00, float m01, float m10, float m11)
1094{
1095 return m00 * m11 - m01 * m10;
1096}
1097
1098float determinant3(float m00, float m01, float m02,
1099 float m10, float m11, float m12,
1100 float m20, float m21, float m22)
1101{
1102 return m00 * determinant2(m11, m12, m21, m22) -
1103 m10 * determinant2(m01, m02, m21, m22) +
1104 m20 * determinant2(m01, m02, m11, m12);
1105}
1106
1107float determinant4(float m00, float m01, float m02, float m03,
1108 float m10, float m11, float m12, float m13,
1109 float m20, float m21, float m22, float m23,
1110 float m30, float m31, float m32, float m33)
1111{
1112 return m00 * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33) -
1113 m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) +
1114 m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) -
1115 m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
1116}
1117
1118float ComputeDeterminant(int size, ConstantUnion* unionArray)
1119{
1120 switch(size)
1121 {
1122 case 2:
1123 return determinant2(unionArray[0].getFConst(),
1124 unionArray[1].getFConst(),
1125 unionArray[2].getFConst(),
1126 unionArray[3].getFConst());
1127 case 3:
1128 return determinant3(unionArray[0].getFConst(),
1129 unionArray[1].getFConst(),
1130 unionArray[2].getFConst(),
1131 unionArray[3].getFConst(),
1132 unionArray[4].getFConst(),
1133 unionArray[5].getFConst(),
1134 unionArray[6].getFConst(),
1135 unionArray[7].getFConst(),
1136 unionArray[8].getFConst());
1137 case 4:
1138 return determinant4(unionArray[0].getFConst(),
1139 unionArray[1].getFConst(),
1140 unionArray[2].getFConst(),
1141 unionArray[3].getFConst(),
1142 unionArray[4].getFConst(),
1143 unionArray[5].getFConst(),
1144 unionArray[6].getFConst(),
1145 unionArray[7].getFConst(),
1146 unionArray[8].getFConst(),
1147 unionArray[9].getFConst(),
1148 unionArray[10].getFConst(),
1149 unionArray[11].getFConst(),
1150 unionArray[12].getFConst(),
1151 unionArray[13].getFConst(),
1152 unionArray[14].getFConst(),
1153 unionArray[15].getFConst());
1154 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001155 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001156 return 0.0f;
1157 }
1158}
1159
1160ConstantUnion* CreateInverse(TIntermConstantUnion* node, ConstantUnion* unionArray)
1161{
1162 ConstantUnion* tempConstArray = 0;
1163 int size = node->getNominalSize();
1164 float determinant = ComputeDeterminant(size, unionArray);
1165 if(determinant != 0.0f)
1166 {
1167 float invDet = 1.0f / determinant;
1168 tempConstArray = new ConstantUnion[size*size];
1169 switch(size)
1170 {
1171 case 2:
1172 {
1173 float m00 = unionArray[0].getFConst(); // Matrix is:
1174 float m01 = unionArray[1].getFConst(); // (m00, m01)
1175 float m10 = unionArray[2].getFConst(); // (m10, m11)
1176 float m11 = unionArray[3].getFConst();
1177 tempConstArray[0].setFConst( invDet * m11);
1178 tempConstArray[1].setFConst(-invDet * m01);
1179 tempConstArray[2].setFConst(-invDet * m10);
1180 tempConstArray[3].setFConst( invDet * m00);
1181 }
1182 break;
1183 case 3:
1184 {
1185 float m00 = unionArray[0].getFConst(); // Matrix is:
1186 float m01 = unionArray[1].getFConst(); // (m00, m01, m02)
1187 float m02 = unionArray[2].getFConst(); // (m10, m11, m12)
1188 float m10 = unionArray[3].getFConst(); // (m20, m21, m22)
1189 float m11 = unionArray[4].getFConst();
1190 float m12 = unionArray[5].getFConst();
1191 float m20 = unionArray[6].getFConst();
1192 float m21 = unionArray[7].getFConst();
1193 float m22 = unionArray[8].getFConst();
1194 tempConstArray[0].setFConst(invDet * determinant2(m11, m12, m21, m22)); // m00 = invDet * (m11 * m22 - m12 * m21)
1195 tempConstArray[1].setFConst(invDet * determinant2(m12, m10, m22, m20)); // m01 = -invDet * (m10 * m22 - m12 * m20)
1196 tempConstArray[2].setFConst(invDet * determinant2(m10, m11, m20, m21)); // m02 = invDet * (m10 * m21 - m11 * m20)
1197 tempConstArray[3].setFConst(invDet * determinant2(m21, m22, m01, m02)); // m10 = -invDet * (m01 * m22 - m02 * m21)
1198 tempConstArray[4].setFConst(invDet * determinant2(m00, m02, m20, m22)); // m11 = invDet * (m00 * m22 - m02 * m20)
1199 tempConstArray[5].setFConst(invDet * determinant2(m20, m21, m00, m01)); // m12 = -invDet * (m00 * m21 - m01 * m20)
1200 tempConstArray[6].setFConst(invDet * determinant2(m01, m02, m11, m12)); // m20 = invDet * (m01 * m12 - m02 * m11)
1201 tempConstArray[7].setFConst(invDet * determinant2(m10, m12, m00, m02)); // m21 = -invDet * (m00 * m12 - m02 * m10)
1202 tempConstArray[8].setFConst(invDet * determinant2(m00, m01, m10, m11)); // m22 = invDet * (m00 * m11 - m01 * m10)
1203 }
1204 break;
1205 case 4:
1206 {
1207 float m00 = unionArray[0].getFConst(); // Matrix is:
1208 float m01 = unionArray[1].getFConst(); // (m00, m01, m02, m03)
1209 float m02 = unionArray[2].getFConst(); // (m10, m11, m12, m13)
1210 float m03 = unionArray[3].getFConst(); // (m20, m21, m22, m23)
1211 float m10 = unionArray[4].getFConst(); // (m30, m31, m32, m33)
1212 float m11 = unionArray[5].getFConst();
1213 float m12 = unionArray[6].getFConst();
1214 float m13 = unionArray[7].getFConst();
1215 float m20 = unionArray[8].getFConst();
1216 float m21 = unionArray[9].getFConst();
1217 float m22 = unionArray[10].getFConst();
1218 float m23 = unionArray[11].getFConst();
1219 float m30 = unionArray[12].getFConst();
1220 float m31 = unionArray[13].getFConst();
1221 float m32 = unionArray[14].getFConst();
1222 float m33 = unionArray[15].getFConst();
1223 tempConstArray[ 0].setFConst( invDet * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33)); // m00
1224 tempConstArray[ 1].setFConst(-invDet * determinant3(m10, m12, m13, m20, m22, m23, m30, m32, m33)); // m01
1225 tempConstArray[ 2].setFConst( invDet * determinant3(m10, m11, m13, m20, m21, m23, m30, m31, m33)); // m02
1226 tempConstArray[ 3].setFConst(-invDet * determinant3(m10, m11, m12, m20, m21, m22, m30, m31, m32)); // m03
1227 tempConstArray[ 4].setFConst( invDet * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33)); // m10
1228 tempConstArray[ 5].setFConst(-invDet * determinant3(m00, m02, m03, m20, m22, m23, m30, m32, m33)); // m11
1229 tempConstArray[ 6].setFConst( invDet * determinant3(m00, m01, m03, m20, m21, m23, m30, m31, m33)); // m12
1230 tempConstArray[ 7].setFConst(-invDet * determinant3(m00, m01, m02, m20, m21, m22, m30, m31, m32)); // m13
1231 tempConstArray[ 8].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33)); // m20
1232 tempConstArray[ 9].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m30, m32, m33)); // m21
1233 tempConstArray[10].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m30, m31, m33)); // m22
1234 tempConstArray[11].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m30, m31, m32)); // m23
1235 tempConstArray[12].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23)); // m30
1236 tempConstArray[13].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m20, m22, m23)); // m31
1237 tempConstArray[14].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m20, m21, m23)); // m32
1238 tempConstArray[15].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m20, m21, m22)); // m33
1239 }
1240 break;
1241 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001242 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001243 }
1244 }
1245 return tempConstArray;
1246}
1247
John Bauman66b8ab22014-05-06 15:57:45 -04001248//
1249// The fold functions see if an operation on a constant can be done in place,
1250// without generating run-time code.
1251//
1252// Returns the node to keep using, which may or may not be the node passed in.
1253//
1254
1255TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1256{
1257 ConstantUnion *unionArray = getUnionArrayPointer();
1258 int objectSize = getType().getObjectSize();
1259
1260 if (constantNode) { // binary operations
1261 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
1262 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
1263 TType returnType = getType();
1264
1265 // for a case like float f = 1.2 + vec4(2,3,4,5);
1266 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
1267 rightUnionArray = new ConstantUnion[objectSize];
1268 for (int i = 0; i < objectSize; ++i)
1269 rightUnionArray[i] = *node->getUnionArrayPointer();
1270 returnType = getType();
1271 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1272 // for a case like float f = vec4(2,3,4,5) + 1.2;
1273 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
1274 for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
1275 unionArray[i] = *getUnionArrayPointer();
1276 returnType = node->getType();
1277 objectSize = constantNode->getType().getObjectSize();
1278 }
1279
1280 ConstantUnion* tempConstArray = 0;
1281 TIntermConstantUnion *tempNode;
1282
1283 bool boolNodeFlag = false;
1284 switch(op) {
1285 case EOpAdd:
1286 tempConstArray = new ConstantUnion[objectSize];
1287 {// support MSVC++6.0
1288 for (int i = 0; i < objectSize; i++)
1289 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1290 }
1291 break;
1292 case EOpSub:
1293 tempConstArray = new ConstantUnion[objectSize];
1294 {// support MSVC++6.0
1295 for (int i = 0; i < objectSize; i++)
1296 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1297 }
1298 break;
1299
1300 case EOpMul:
1301 case EOpVectorTimesScalar:
1302 case EOpMatrixTimesScalar:
1303 tempConstArray = new ConstantUnion[objectSize];
1304 {// support MSVC++6.0
1305 for (int i = 0; i < objectSize; i++)
1306 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1307 }
1308 break;
1309 case EOpMatrixTimesMatrix:
1310 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1311 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1312 return 0;
1313 }
1314 {// support MSVC++6.0
Alexis Hetu00106d42015-04-23 11:45:35 -04001315 int leftNumCols = getNominalSize();
1316 int leftNumRows = getSecondarySize();
1317 int rightNumCols = node->getNominalSize();
1318 int rightNumRows = node->getSecondarySize();
1319 if(leftNumCols != rightNumRows) {
1320 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1321 return 0;
1322 }
1323 int tempNumCols = rightNumCols;
1324 int tempNumRows = leftNumRows;
1325 int tempNumAdds = leftNumCols;
1326 tempConstArray = new ConstantUnion[tempNumCols*tempNumRows];
1327 for (int row = 0; row < tempNumRows; row++) {
1328 for (int column = 0; column < tempNumCols; column++) {
1329 tempConstArray[tempNumRows * column + row].setFConst(0.0f);
1330 for (int i = 0; i < tempNumAdds; i++) {
1331 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 -04001332 }
1333 }
1334 }
Alexis Hetu00106d42015-04-23 11:45:35 -04001335 // update return type for matrix product
1336 returnType.setNominalSize(static_cast<unsigned char>(tempNumCols));
1337 returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows));
John Bauman66b8ab22014-05-06 15:57:45 -04001338 }
1339 break;
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001340
1341 case EOpOuterProduct:
1342 {
1343 int leftSize = getNominalSize();
1344 int rightSize = node->getNominalSize();
1345 tempConstArray = new ConstantUnion[leftSize*rightSize];
1346 for(int row = 0; row < leftSize; row++) {
1347 for(int column = 0; column < rightSize; column++) {
1348 tempConstArray[leftSize * column + row].setFConst(unionArray[row].getFConst() * rightUnionArray[column].getFConst());
1349 }
1350 }
1351 // update return type for outer product
1352 returnType.setNominalSize(static_cast<unsigned char>(rightSize));
1353 returnType.setSecondarySize(static_cast<unsigned char>(leftSize));
1354 }
1355 break;
1356
1357 case EOpTranspose:
1358 {
1359 int rightCol = node->getNominalSize();
1360 int rightRow = node->getSecondarySize();
1361 tempConstArray = new ConstantUnion[rightCol*rightRow];
1362 for(int row = 0; row < rightRow; row++) {
1363 for(int column = 0; column < rightCol; column++) {
1364 tempConstArray[rightRow * column + row].setFConst(rightUnionArray[rightCol * row + column].getFConst());
1365 }
1366 }
1367 // update return type for transpose
1368 returnType.setNominalSize(static_cast<unsigned char>(rightRow));
1369 returnType.setSecondarySize(static_cast<unsigned char>(rightCol));
1370 }
1371 break;
1372
1373 case EOpDeterminant:
1374 {
1375 ASSERT(node->getNominalSize() == node->getSecondarySize());
1376
1377 tempConstArray = new ConstantUnion[1];
1378 tempConstArray[0].setFConst(ComputeDeterminant(node->getNominalSize(), rightUnionArray));
1379 // update return type for determinant
1380 returnType.setNominalSize(1);
1381 returnType.setSecondarySize(1);
1382 }
1383 break;
1384
1385 case EOpInverse:
1386 {
1387 ASSERT(node->getNominalSize() == node->getSecondarySize());
1388
1389 tempConstArray = CreateInverse(node, rightUnionArray);
1390 if(!tempConstArray)
1391 {
1392 // Singular matrix, just copy
1393 tempConstArray = new ConstantUnion[objectSize];
1394 for(int i = 0; i < objectSize; i++)
1395 tempConstArray[i] = rightUnionArray[i];
1396 }
1397 }
1398 break;
1399
John Bauman66b8ab22014-05-06 15:57:45 -04001400 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -04001401 case EOpIMod:
John Bauman66b8ab22014-05-06 15:57:45 -04001402 tempConstArray = new ConstantUnion[objectSize];
1403 {// support MSVC++6.0
1404 for (int i = 0; i < objectSize; i++) {
1405 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001406 case EbtFloat:
1407 if (rightUnionArray[i] == 0.0f) {
1408 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1409 tempConstArray[i].setFConst(FLT_MAX);
1410 } else {
1411 ASSERT(op == EOpDiv);
1412 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1413 }
1414 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001415
Alexis Hetud061e422015-05-13 16:37:50 -04001416 case EbtInt:
1417 if (rightUnionArray[i] == 0) {
1418 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1419 tempConstArray[i].setIConst(INT_MAX);
1420 } else {
1421 if(op == EOpDiv) {
1422 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1423 } else {
1424 ASSERT(op == EOpIMod);
1425 tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst());
1426 }
1427 }
1428 break;
1429 case EbtUInt:
1430 if (rightUnionArray[i] == 0) {
1431 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1432 tempConstArray[i].setUConst(UINT_MAX);
1433 } else {
1434 if(op == EOpDiv) {
1435 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1436 } else {
1437 ASSERT(op == EOpIMod);
1438 tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst());
1439 }
1440 }
1441 break;
1442 default:
1443 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1444 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -04001445 }
1446 }
1447 }
1448 break;
1449
1450 case EOpMatrixTimesVector:
1451 if (node->getBasicType() != EbtFloat) {
1452 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1453 return 0;
1454 }
1455 tempConstArray = new ConstantUnion[getNominalSize()];
1456
1457 {// support MSVC++6.0
1458 for (int size = getNominalSize(), i = 0; i < size; i++) {
1459 tempConstArray[i].setFConst(0.0f);
1460 for (int j = 0; j < size; j++) {
1461 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1462 }
1463 }
1464 }
1465
1466 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1467 tempNode->setLine(getLine());
1468
1469 return tempNode;
1470
1471 case EOpVectorTimesMatrix:
1472 if (getType().getBasicType() != EbtFloat) {
1473 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1474 return 0;
1475 }
1476
1477 tempConstArray = new ConstantUnion[getNominalSize()];
1478 {// support MSVC++6.0
1479 for (int size = getNominalSize(), i = 0; i < size; i++) {
1480 tempConstArray[i].setFConst(0.0f);
1481 for (int j = 0; j < size; j++) {
1482 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1483 }
1484 }
1485 }
1486 break;
1487
1488 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1489 tempConstArray = new ConstantUnion[objectSize];
1490 {// support MSVC++6.0
1491 for (int i = 0; i < objectSize; i++)
1492 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1493 }
1494 break;
1495
1496 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1497 tempConstArray = new ConstantUnion[objectSize];
1498 {// support MSVC++6.0
1499 for (int i = 0; i < objectSize; i++)
1500 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1501 }
1502 break;
1503
1504 case EOpLogicalXor:
1505 tempConstArray = new ConstantUnion[objectSize];
1506 {// support MSVC++6.0
1507 for (int i = 0; i < objectSize; i++)
1508 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001509 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1510 default: assert(false && "Default missing");
John Bauman66b8ab22014-05-06 15:57:45 -04001511 }
1512 }
1513 break;
1514
Alexis Hetud061e422015-05-13 16:37:50 -04001515 case EOpBitwiseAnd:
1516 tempConstArray = new ConstantUnion[objectSize];
1517 for(int i = 0; i < objectSize; i++)
1518 tempConstArray[i] = unionArray[i] & rightUnionArray[i];
1519 break;
1520 case EOpBitwiseXor:
1521 tempConstArray = new ConstantUnion[objectSize];
1522 for(int i = 0; i < objectSize; i++)
1523 tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
1524 break;
1525 case EOpBitwiseOr:
1526 tempConstArray = new ConstantUnion[objectSize];
1527 for(int i = 0; i < objectSize; i++)
1528 tempConstArray[i] = unionArray[i] | rightUnionArray[i];
1529 break;
1530 case EOpBitShiftLeft:
1531 tempConstArray = new ConstantUnion[objectSize];
1532 for(int i = 0; i < objectSize; i++)
1533 tempConstArray[i] = unionArray[i] << rightUnionArray[i];
1534 break;
1535 case EOpBitShiftRight:
1536 tempConstArray = new ConstantUnion[objectSize];
1537 for(int i = 0; i < objectSize; i++)
1538 tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
1539 break;
1540
John Bauman66b8ab22014-05-06 15:57:45 -04001541 case EOpLessThan:
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001542 tempConstArray = new ConstantUnion[objectSize];
1543 for(int i = 0; i < objectSize; i++)
1544 tempConstArray[i].setBConst(unionArray[i] < rightUnionArray[i]);
1545 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
John Bauman66b8ab22014-05-06 15:57:45 -04001546 break;
1547 case EOpGreaterThan:
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001548 tempConstArray = new ConstantUnion[objectSize];
1549 for(int i = 0; i < objectSize; i++)
1550 tempConstArray[i].setBConst(unionArray[i] > rightUnionArray[i]);
1551 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
John Bauman66b8ab22014-05-06 15:57:45 -04001552 break;
1553 case EOpLessThanEqual:
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001554 tempConstArray = new ConstantUnion[objectSize];
1555 for(int i = 0; i < objectSize; i++)
1556 tempConstArray[i].setBConst(unionArray[i] <= rightUnionArray[i]);
1557 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1558 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001559 case EOpGreaterThanEqual:
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001560 tempConstArray = new ConstantUnion[objectSize];
1561 for(int i = 0; i < objectSize; i++)
1562 tempConstArray[i].setBConst(unionArray[i] >= rightUnionArray[i]);
1563 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1564 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001565 case EOpEqual:
1566 if (getType().getBasicType() == EbtStruct) {
1567 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1568 boolNodeFlag = true;
1569 } else {
1570 for (int i = 0; i < objectSize; i++) {
1571 if (unionArray[i] != rightUnionArray[i]) {
1572 boolNodeFlag = true;
1573 break; // break out of for loop
1574 }
1575 }
1576 }
1577
1578 tempConstArray = new ConstantUnion[1];
1579 if (!boolNodeFlag) {
1580 tempConstArray->setBConst(true);
1581 }
1582 else {
1583 tempConstArray->setBConst(false);
1584 }
1585
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001586 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001587 tempNode->setLine(getLine());
1588
1589 return tempNode;
1590
1591 case EOpNotEqual:
1592 if (getType().getBasicType() == EbtStruct) {
1593 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1594 boolNodeFlag = true;
1595 } else {
1596 for (int i = 0; i < objectSize; i++) {
1597 if (unionArray[i] == rightUnionArray[i]) {
1598 boolNodeFlag = true;
1599 break; // break out of for loop
1600 }
1601 }
1602 }
1603
1604 tempConstArray = new ConstantUnion[1];
1605 if (!boolNodeFlag) {
1606 tempConstArray->setBConst(true);
1607 }
1608 else {
1609 tempConstArray->setBConst(false);
1610 }
1611
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001612 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001613 tempNode->setLine(getLine());
1614
1615 return tempNode;
1616
1617 default:
John Bauman66b8ab22014-05-06 15:57:45 -04001618 return 0;
1619 }
1620 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1621 tempNode->setLine(getLine());
1622
1623 return tempNode;
1624 } else {
1625 //
1626 // Do unary operations
1627 //
1628 TIntermConstantUnion *newNode = 0;
1629 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
1630 for (int i = 0; i < objectSize; i++) {
1631 switch(op) {
1632 case EOpNegative:
1633 switch (getType().getBasicType()) {
1634 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1635 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1636 default:
1637 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1638 return 0;
1639 }
1640 break;
1641 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1642 switch (getType().getBasicType()) {
1643 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1644 default:
1645 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1646 return 0;
1647 }
1648 break;
Alexis Hetud061e422015-05-13 16:37:50 -04001649 case EOpBitwiseNot:
1650 switch(getType().getBasicType()) {
1651 case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
1652 case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
1653 default:
1654 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1655 return 0;
1656 }
1657 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001658 default:
1659 return 0;
1660 }
1661 }
1662 newNode = new TIntermConstantUnion(tempConstArray, getType());
1663 newNode->setLine(getLine());
1664 return newNode;
1665 }
1666}
1667
1668TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1669{
John Bauman66b8ab22014-05-06 15:57:45 -04001670 int size = node->getType().getObjectSize();
1671
1672 ConstantUnion *leftUnionArray = new ConstantUnion[size];
1673
1674 for (int i=0; i < size; i++) {
1675
1676 switch (promoteTo) {
1677 case EbtFloat:
1678 switch (node->getType().getBasicType()) {
1679 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001680 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001681 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001682 case EbtUInt:
1683 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
1684 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001685 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001686 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001687 break;
1688 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001689 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001690 break;
1691 default:
1692 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1693 return 0;
1694 }
1695 break;
1696 case EbtInt:
1697 switch (node->getType().getBasicType()) {
1698 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001699 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001700 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001701 case EbtUInt:
1702 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
1703 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001704 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001705 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001706 break;
1707 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001708 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001709 break;
1710 default:
1711 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1712 return 0;
1713 }
1714 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001715 case EbtUInt:
1716 switch (node->getType().getBasicType()) {
1717 case EbtInt:
1718 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
1719 break;
1720 case EbtUInt:
1721 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
1722 break;
1723 case EbtBool:
1724 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
1725 break;
1726 case EbtFloat:
1727 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
1728 break;
1729 default:
1730 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1731 return 0;
1732 }
1733 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001734 case EbtBool:
1735 switch (node->getType().getBasicType()) {
1736 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001737 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
John Bauman66b8ab22014-05-06 15:57:45 -04001738 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001739 case EbtUInt:
1740 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
1741 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001742 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001743 leftUnionArray[i].setBConst(node->getBConst(i));
John Bauman66b8ab22014-05-06 15:57:45 -04001744 break;
1745 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001746 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
John Bauman66b8ab22014-05-06 15:57:45 -04001747 break;
1748 default:
1749 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1750 return 0;
1751 }
1752
1753 break;
1754 default:
1755 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1756 return 0;
1757 }
1758
1759 }
1760
1761 const TType& t = node->getType();
1762
Alexis Hetub14178b2015-04-13 13:23:20 -04001763 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001764}
1765