blob: a0247b9440284bd94f1d652e81b1d4fdb02eec3c [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:
755 return true;
756
757 default:
758 if (operand->getBasicType() != EbtFloat)
759 return false;
760 }
761
762 setType(operand->getType());
763
764 // Unary operations results in temporary variables unless const.
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500765 if (operand->getQualifier() != EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400766 getTypePointer()->setQualifier(EvqTemporary);
767 }
768
769 return true;
770}
771
772//
773// Establishes the type of the resultant operation, as well as
774// makes the operator the correct one for the operands.
775//
776// Returns false if operator can't work on operands.
777//
778bool TIntermBinary::promote(TInfoSink& infoSink)
779{
Alexis Hetue5246692015-06-18 12:34:52 -0400780 ASSERT(left->isArray() == right->isArray());
John Bauman66b8ab22014-05-06 15:57:45 -0400781
782 // GLSL ES 2.0 does not support implicit type casting.
783 // So the basic type should always match.
Alexis Hetu92ab1982015-08-18 15:28:27 -0400784 // GLSL ES 3.0 supports integer shift operands of different signedness.
785 if(op != EOpBitShiftLeft &&
786 op != EOpBitShiftRight &&
787 op != EOpBitShiftLeftAssign &&
788 op != EOpBitShiftRightAssign &&
789 left->getBasicType() != right->getBasicType())
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400790 {
John Bauman66b8ab22014-05-06 15:57:45 -0400791 return false;
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400792 }
John Bauman66b8ab22014-05-06 15:57:45 -0400793
794 //
795 // Base assumption: just make the type the same as the left
796 // operand. Then only deviations from this need be coded.
797 //
798 setType(left->getType());
799
800 // The result gets promoted to the highest precision.
801 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
802 getTypePointer()->setPrecision(higherPrecision);
803
804 // Binary operations results in temporary variables unless both
805 // operands are const.
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500806 if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400807 getTypePointer()->setQualifier(EvqTemporary);
808 }
809
Alexis Hetud061e422015-05-13 16:37:50 -0400810 int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
John Bauman66b8ab22014-05-06 15:57:45 -0400811
812 //
813 // All scalars. Code after this test assumes this case is removed!
814 //
Alexis Hetud061e422015-05-13 16:37:50 -0400815 if (primarySize == 1) {
John Bauman66b8ab22014-05-06 15:57:45 -0400816 switch (op) {
817 //
818 // Promote to conditional
819 //
820 case EOpEqual:
821 case EOpNotEqual:
822 case EOpLessThan:
823 case EOpGreaterThan:
824 case EOpLessThanEqual:
825 case EOpGreaterThanEqual:
826 setType(TType(EbtBool, EbpUndefined));
827 break;
828
829 //
830 // And and Or operate on conditionals
831 //
832 case EOpLogicalAnd:
833 case EOpLogicalOr:
Alexis Hetud061e422015-05-13 16:37:50 -0400834 case EOpLogicalXor:
John Bauman66b8ab22014-05-06 15:57:45 -0400835 // Both operands must be of type bool.
836 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
837 return false;
838 setType(TType(EbtBool, EbpUndefined));
839 break;
840
841 default:
842 break;
843 }
844 return true;
845 }
846
847 // If we reach here, at least one of the operands is vector or matrix.
848 // The other operand could be a scalar, vector, or matrix.
John Bauman66b8ab22014-05-06 15:57:45 -0400849 // Can these two operands be combined?
850 //
851 TBasicType basicType = left->getBasicType();
852 switch (op) {
853 case EOpMul:
854 if (!left->isMatrix() && right->isMatrix()) {
855 if (left->isVector())
Alexis Hetu00106d42015-04-23 11:45:35 -0400856 {
John Bauman66b8ab22014-05-06 15:57:45 -0400857 op = EOpVectorTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400858 setType(TType(basicType, higherPrecision, EvqTemporary,
859 static_cast<unsigned char>(right->getNominalSize()), 1));
860 }
John Bauman66b8ab22014-05-06 15:57:45 -0400861 else {
862 op = EOpMatrixTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400863 setType(TType(basicType, higherPrecision, EvqTemporary,
864 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400865 }
866 } else if (left->isMatrix() && !right->isMatrix()) {
867 if (right->isVector()) {
868 op = EOpMatrixTimesVector;
Alexis Hetu00106d42015-04-23 11:45:35 -0400869 setType(TType(basicType, higherPrecision, EvqTemporary,
870 static_cast<unsigned char>(left->getSecondarySize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400871 } else {
872 op = EOpMatrixTimesScalar;
873 }
874 } else if (left->isMatrix() && right->isMatrix()) {
875 op = EOpMatrixTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400876 setType(TType(basicType, higherPrecision, EvqTemporary,
877 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400878 } else if (!left->isMatrix() && !right->isMatrix()) {
879 if (left->isVector() && right->isVector()) {
880 // leave as component product
881 } else if (left->isVector() || right->isVector()) {
882 op = EOpVectorTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400883 setType(TType(basicType, higherPrecision, EvqTemporary,
884 static_cast<unsigned char>(primarySize), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400885 }
886 } else {
887 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
888 return false;
889 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400890
891 if(!ValidateMultiplication(op, left->getType(), right->getType()))
892 {
893 return false;
894 }
John Bauman66b8ab22014-05-06 15:57:45 -0400895 break;
896 case EOpMulAssign:
897 if (!left->isMatrix() && right->isMatrix()) {
898 if (left->isVector())
899 op = EOpVectorTimesMatrixAssign;
900 else {
901 return false;
902 }
903 } else if (left->isMatrix() && !right->isMatrix()) {
904 if (right->isVector()) {
905 return false;
906 } else {
907 op = EOpMatrixTimesScalarAssign;
908 }
909 } else if (left->isMatrix() && right->isMatrix()) {
910 op = EOpMatrixTimesMatrixAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400911 setType(TType(basicType, higherPrecision, EvqTemporary,
912 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400913 } else if (!left->isMatrix() && !right->isMatrix()) {
914 if (left->isVector() && right->isVector()) {
915 // leave as component product
916 } else if (left->isVector() || right->isVector()) {
917 if (! left->isVector())
918 return false;
919 op = EOpVectorTimesScalarAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400920 setType(TType(basicType, higherPrecision, EvqTemporary,
921 static_cast<unsigned char>(left->getNominalSize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400922 }
923 } else {
924 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
925 return false;
926 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400927
928 if(!ValidateMultiplication(op, left->getType(), right->getType()))
929 {
930 return false;
931 }
John Bauman66b8ab22014-05-06 15:57:45 -0400932 break;
933
934 case EOpAssign:
935 case EOpInitialize:
Alexis Hetu00106d42015-04-23 11:45:35 -0400936 // No more additional checks are needed.
937 if ((left->getNominalSize() != right->getNominalSize()) ||
938 (left->getSecondarySize() != right->getSecondarySize()))
939 return false;
940 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400941 case EOpAdd:
942 case EOpSub:
943 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -0400944 case EOpIMod:
945 case EOpBitShiftLeft:
946 case EOpBitShiftRight:
947 case EOpBitwiseAnd:
948 case EOpBitwiseXor:
949 case EOpBitwiseOr:
John Bauman66b8ab22014-05-06 15:57:45 -0400950 case EOpAddAssign:
951 case EOpSubAssign:
952 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400953 case EOpIModAssign:
954 case EOpBitShiftLeftAssign:
955 case EOpBitShiftRightAssign:
956 case EOpBitwiseAndAssign:
957 case EOpBitwiseXorAssign:
958 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400959 if ((left->isMatrix() && right->isVector()) ||
960 (left->isVector() && right->isMatrix()))
961 return false;
Alexis Hetud061e422015-05-13 16:37:50 -0400962
963 // Are the sizes compatible?
964 if(left->getNominalSize() != right->getNominalSize() ||
965 left->getSecondarySize() != right->getSecondarySize())
966 {
967 // If the nominal sizes of operands do not match:
968 // One of them must be a scalar.
969 if(!left->isScalar() && !right->isScalar())
970 return false;
971
972 // In the case of compound assignment other than multiply-assign,
973 // the right side needs to be a scalar. Otherwise a vector/matrix
974 // would be assigned to a scalar. A scalar can't be shifted by a
975 // vector either.
976 if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight))
977 return false;
978 }
979
980 {
Alexis Hetu00106d42015-04-23 11:45:35 -0400981 const int secondarySize = std::max(
982 left->getSecondarySize(), right->getSecondarySize());
Alexis Hetud061e422015-05-13 16:37:50 -0400983 setType(TType(basicType, higherPrecision, EvqTemporary,
984 static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
985 if(left->isArray())
986 {
987 ASSERT(left->getArraySize() == right->getArraySize());
988 type.setArraySize(left->getArraySize());
989 }
990 }
John Bauman66b8ab22014-05-06 15:57:45 -0400991 break;
992
993 case EOpEqual:
994 case EOpNotEqual:
995 case EOpLessThan:
996 case EOpGreaterThan:
997 case EOpLessThanEqual:
998 case EOpGreaterThanEqual:
Alexis Hetu00106d42015-04-23 11:45:35 -0400999 if ((left->getNominalSize() != right->getNominalSize()) ||
1000 (left->getSecondarySize() != right->getSecondarySize()))
John Bauman66b8ab22014-05-06 15:57:45 -04001001 return false;
1002 setType(TType(EbtBool, EbpUndefined));
1003 break;
1004
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001005 case EOpOuterProduct:
1006 if(!left->isVector() || !right->isVector())
1007 return false;
1008 setType(TType(EbtFloat, right->getNominalSize(), left->getNominalSize()));
1009 break;
1010
1011 case EOpTranspose:
1012 if(!right->isMatrix())
1013 return false;
1014 setType(TType(EbtFloat, right->getSecondarySize(), right->getNominalSize()));
1015 break;
1016
1017 case EOpDeterminant:
1018 if(!right->isMatrix())
1019 return false;
1020 setType(TType(EbtFloat));
1021 break;
1022
1023 case EOpInverse:
1024 if(!right->isMatrix() || right->getNominalSize() != right->getSecondarySize())
1025 return false;
1026 setType(right->getType());
1027 break;
1028
John Bauman66b8ab22014-05-06 15:57:45 -04001029 default:
1030 return false;
1031 }
1032
1033 return true;
1034}
1035
1036bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1037{
Alexis Hetua8b364b2015-06-10 11:48:40 -04001038 const TFieldList& fields = leftNodeType.getStruct()->fields();
John Bauman66b8ab22014-05-06 15:57:45 -04001039
Alexis Hetua8b364b2015-06-10 11:48:40 -04001040 size_t structSize = fields.size();
John Bauman66b8ab22014-05-06 15:57:45 -04001041 int index = 0;
1042
1043 for (size_t j = 0; j < structSize; j++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001044 int size = fields[j]->type()->getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04001045 for (int i = 0; i < size; i++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001046 if (fields[j]->type()->getBasicType() == EbtStruct) {
1047 if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
John Bauman66b8ab22014-05-06 15:57:45 -04001048 return false;
1049 } else {
1050 if (leftUnionArray[index] != rightUnionArray[index])
1051 return false;
1052 index++;
1053 }
1054
1055 }
1056 }
1057 return true;
1058}
1059
1060bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1061{
1062 if (leftNodeType.isArray()) {
1063 TType typeWithoutArrayness = leftNodeType;
1064 typeWithoutArrayness.clearArrayness();
1065
1066 int arraySize = leftNodeType.getArraySize();
1067
1068 for (int i = 0; i < arraySize; ++i) {
1069 int offset = typeWithoutArrayness.getObjectSize() * i;
1070 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1071 return false;
1072 }
1073 } else
1074 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
1075
1076 return true;
1077}
1078
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001079float determinant2(float m00, float m01, float m10, float m11)
1080{
1081 return m00 * m11 - m01 * m10;
1082}
1083
1084float determinant3(float m00, float m01, float m02,
1085 float m10, float m11, float m12,
1086 float m20, float m21, float m22)
1087{
1088 return m00 * determinant2(m11, m12, m21, m22) -
1089 m10 * determinant2(m01, m02, m21, m22) +
1090 m20 * determinant2(m01, m02, m11, m12);
1091}
1092
1093float determinant4(float m00, float m01, float m02, float m03,
1094 float m10, float m11, float m12, float m13,
1095 float m20, float m21, float m22, float m23,
1096 float m30, float m31, float m32, float m33)
1097{
1098 return m00 * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33) -
1099 m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) +
1100 m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) -
1101 m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
1102}
1103
1104float ComputeDeterminant(int size, ConstantUnion* unionArray)
1105{
1106 switch(size)
1107 {
1108 case 2:
1109 return determinant2(unionArray[0].getFConst(),
1110 unionArray[1].getFConst(),
1111 unionArray[2].getFConst(),
1112 unionArray[3].getFConst());
1113 case 3:
1114 return determinant3(unionArray[0].getFConst(),
1115 unionArray[1].getFConst(),
1116 unionArray[2].getFConst(),
1117 unionArray[3].getFConst(),
1118 unionArray[4].getFConst(),
1119 unionArray[5].getFConst(),
1120 unionArray[6].getFConst(),
1121 unionArray[7].getFConst(),
1122 unionArray[8].getFConst());
1123 case 4:
1124 return determinant4(unionArray[0].getFConst(),
1125 unionArray[1].getFConst(),
1126 unionArray[2].getFConst(),
1127 unionArray[3].getFConst(),
1128 unionArray[4].getFConst(),
1129 unionArray[5].getFConst(),
1130 unionArray[6].getFConst(),
1131 unionArray[7].getFConst(),
1132 unionArray[8].getFConst(),
1133 unionArray[9].getFConst(),
1134 unionArray[10].getFConst(),
1135 unionArray[11].getFConst(),
1136 unionArray[12].getFConst(),
1137 unionArray[13].getFConst(),
1138 unionArray[14].getFConst(),
1139 unionArray[15].getFConst());
1140 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001141 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001142 return 0.0f;
1143 }
1144}
1145
1146ConstantUnion* CreateInverse(TIntermConstantUnion* node, ConstantUnion* unionArray)
1147{
1148 ConstantUnion* tempConstArray = 0;
1149 int size = node->getNominalSize();
1150 float determinant = ComputeDeterminant(size, unionArray);
1151 if(determinant != 0.0f)
1152 {
1153 float invDet = 1.0f / determinant;
1154 tempConstArray = new ConstantUnion[size*size];
1155 switch(size)
1156 {
1157 case 2:
1158 {
1159 float m00 = unionArray[0].getFConst(); // Matrix is:
1160 float m01 = unionArray[1].getFConst(); // (m00, m01)
1161 float m10 = unionArray[2].getFConst(); // (m10, m11)
1162 float m11 = unionArray[3].getFConst();
1163 tempConstArray[0].setFConst( invDet * m11);
1164 tempConstArray[1].setFConst(-invDet * m01);
1165 tempConstArray[2].setFConst(-invDet * m10);
1166 tempConstArray[3].setFConst( invDet * m00);
1167 }
1168 break;
1169 case 3:
1170 {
1171 float m00 = unionArray[0].getFConst(); // Matrix is:
1172 float m01 = unionArray[1].getFConst(); // (m00, m01, m02)
1173 float m02 = unionArray[2].getFConst(); // (m10, m11, m12)
1174 float m10 = unionArray[3].getFConst(); // (m20, m21, m22)
1175 float m11 = unionArray[4].getFConst();
1176 float m12 = unionArray[5].getFConst();
1177 float m20 = unionArray[6].getFConst();
1178 float m21 = unionArray[7].getFConst();
1179 float m22 = unionArray[8].getFConst();
1180 tempConstArray[0].setFConst(invDet * determinant2(m11, m12, m21, m22)); // m00 = invDet * (m11 * m22 - m12 * m21)
1181 tempConstArray[1].setFConst(invDet * determinant2(m12, m10, m22, m20)); // m01 = -invDet * (m10 * m22 - m12 * m20)
1182 tempConstArray[2].setFConst(invDet * determinant2(m10, m11, m20, m21)); // m02 = invDet * (m10 * m21 - m11 * m20)
1183 tempConstArray[3].setFConst(invDet * determinant2(m21, m22, m01, m02)); // m10 = -invDet * (m01 * m22 - m02 * m21)
1184 tempConstArray[4].setFConst(invDet * determinant2(m00, m02, m20, m22)); // m11 = invDet * (m00 * m22 - m02 * m20)
1185 tempConstArray[5].setFConst(invDet * determinant2(m20, m21, m00, m01)); // m12 = -invDet * (m00 * m21 - m01 * m20)
1186 tempConstArray[6].setFConst(invDet * determinant2(m01, m02, m11, m12)); // m20 = invDet * (m01 * m12 - m02 * m11)
1187 tempConstArray[7].setFConst(invDet * determinant2(m10, m12, m00, m02)); // m21 = -invDet * (m00 * m12 - m02 * m10)
1188 tempConstArray[8].setFConst(invDet * determinant2(m00, m01, m10, m11)); // m22 = invDet * (m00 * m11 - m01 * m10)
1189 }
1190 break;
1191 case 4:
1192 {
1193 float m00 = unionArray[0].getFConst(); // Matrix is:
1194 float m01 = unionArray[1].getFConst(); // (m00, m01, m02, m03)
1195 float m02 = unionArray[2].getFConst(); // (m10, m11, m12, m13)
1196 float m03 = unionArray[3].getFConst(); // (m20, m21, m22, m23)
1197 float m10 = unionArray[4].getFConst(); // (m30, m31, m32, m33)
1198 float m11 = unionArray[5].getFConst();
1199 float m12 = unionArray[6].getFConst();
1200 float m13 = unionArray[7].getFConst();
1201 float m20 = unionArray[8].getFConst();
1202 float m21 = unionArray[9].getFConst();
1203 float m22 = unionArray[10].getFConst();
1204 float m23 = unionArray[11].getFConst();
1205 float m30 = unionArray[12].getFConst();
1206 float m31 = unionArray[13].getFConst();
1207 float m32 = unionArray[14].getFConst();
1208 float m33 = unionArray[15].getFConst();
1209 tempConstArray[ 0].setFConst( invDet * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33)); // m00
1210 tempConstArray[ 1].setFConst(-invDet * determinant3(m10, m12, m13, m20, m22, m23, m30, m32, m33)); // m01
1211 tempConstArray[ 2].setFConst( invDet * determinant3(m10, m11, m13, m20, m21, m23, m30, m31, m33)); // m02
1212 tempConstArray[ 3].setFConst(-invDet * determinant3(m10, m11, m12, m20, m21, m22, m30, m31, m32)); // m03
1213 tempConstArray[ 4].setFConst( invDet * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33)); // m10
1214 tempConstArray[ 5].setFConst(-invDet * determinant3(m00, m02, m03, m20, m22, m23, m30, m32, m33)); // m11
1215 tempConstArray[ 6].setFConst( invDet * determinant3(m00, m01, m03, m20, m21, m23, m30, m31, m33)); // m12
1216 tempConstArray[ 7].setFConst(-invDet * determinant3(m00, m01, m02, m20, m21, m22, m30, m31, m32)); // m13
1217 tempConstArray[ 8].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33)); // m20
1218 tempConstArray[ 9].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m30, m32, m33)); // m21
1219 tempConstArray[10].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m30, m31, m33)); // m22
1220 tempConstArray[11].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m30, m31, m32)); // m23
1221 tempConstArray[12].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23)); // m30
1222 tempConstArray[13].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m20, m22, m23)); // m31
1223 tempConstArray[14].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m20, m21, m23)); // m32
1224 tempConstArray[15].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m20, m21, m22)); // m33
1225 }
1226 break;
1227 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001228 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001229 }
1230 }
1231 return tempConstArray;
1232}
1233
John Bauman66b8ab22014-05-06 15:57:45 -04001234//
1235// The fold functions see if an operation on a constant can be done in place,
1236// without generating run-time code.
1237//
1238// Returns the node to keep using, which may or may not be the node passed in.
1239//
1240
1241TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1242{
1243 ConstantUnion *unionArray = getUnionArrayPointer();
1244 int objectSize = getType().getObjectSize();
1245
1246 if (constantNode) { // binary operations
1247 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
1248 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
1249 TType returnType = getType();
1250
1251 // for a case like float f = 1.2 + vec4(2,3,4,5);
1252 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
1253 rightUnionArray = new ConstantUnion[objectSize];
1254 for (int i = 0; i < objectSize; ++i)
1255 rightUnionArray[i] = *node->getUnionArrayPointer();
1256 returnType = getType();
1257 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1258 // for a case like float f = vec4(2,3,4,5) + 1.2;
1259 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
1260 for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
1261 unionArray[i] = *getUnionArrayPointer();
1262 returnType = node->getType();
1263 objectSize = constantNode->getType().getObjectSize();
1264 }
1265
1266 ConstantUnion* tempConstArray = 0;
1267 TIntermConstantUnion *tempNode;
1268
1269 bool boolNodeFlag = false;
1270 switch(op) {
1271 case EOpAdd:
1272 tempConstArray = new ConstantUnion[objectSize];
1273 {// support MSVC++6.0
1274 for (int i = 0; i < objectSize; i++)
1275 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1276 }
1277 break;
1278 case EOpSub:
1279 tempConstArray = new ConstantUnion[objectSize];
1280 {// support MSVC++6.0
1281 for (int i = 0; i < objectSize; i++)
1282 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1283 }
1284 break;
1285
1286 case EOpMul:
1287 case EOpVectorTimesScalar:
1288 case EOpMatrixTimesScalar:
1289 tempConstArray = new ConstantUnion[objectSize];
1290 {// support MSVC++6.0
1291 for (int i = 0; i < objectSize; i++)
1292 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1293 }
1294 break;
1295 case EOpMatrixTimesMatrix:
1296 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1297 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1298 return 0;
1299 }
1300 {// support MSVC++6.0
Alexis Hetu00106d42015-04-23 11:45:35 -04001301 int leftNumCols = getNominalSize();
1302 int leftNumRows = getSecondarySize();
1303 int rightNumCols = node->getNominalSize();
1304 int rightNumRows = node->getSecondarySize();
1305 if(leftNumCols != rightNumRows) {
1306 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1307 return 0;
1308 }
1309 int tempNumCols = rightNumCols;
1310 int tempNumRows = leftNumRows;
1311 int tempNumAdds = leftNumCols;
1312 tempConstArray = new ConstantUnion[tempNumCols*tempNumRows];
1313 for (int row = 0; row < tempNumRows; row++) {
1314 for (int column = 0; column < tempNumCols; column++) {
1315 tempConstArray[tempNumRows * column + row].setFConst(0.0f);
1316 for (int i = 0; i < tempNumAdds; i++) {
1317 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 -04001318 }
1319 }
1320 }
Alexis Hetu00106d42015-04-23 11:45:35 -04001321 // update return type for matrix product
1322 returnType.setNominalSize(static_cast<unsigned char>(tempNumCols));
1323 returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows));
John Bauman66b8ab22014-05-06 15:57:45 -04001324 }
1325 break;
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001326
1327 case EOpOuterProduct:
1328 {
1329 int leftSize = getNominalSize();
1330 int rightSize = node->getNominalSize();
1331 tempConstArray = new ConstantUnion[leftSize*rightSize];
1332 for(int row = 0; row < leftSize; row++) {
1333 for(int column = 0; column < rightSize; column++) {
1334 tempConstArray[leftSize * column + row].setFConst(unionArray[row].getFConst() * rightUnionArray[column].getFConst());
1335 }
1336 }
1337 // update return type for outer product
1338 returnType.setNominalSize(static_cast<unsigned char>(rightSize));
1339 returnType.setSecondarySize(static_cast<unsigned char>(leftSize));
1340 }
1341 break;
1342
1343 case EOpTranspose:
1344 {
1345 int rightCol = node->getNominalSize();
1346 int rightRow = node->getSecondarySize();
1347 tempConstArray = new ConstantUnion[rightCol*rightRow];
1348 for(int row = 0; row < rightRow; row++) {
1349 for(int column = 0; column < rightCol; column++) {
1350 tempConstArray[rightRow * column + row].setFConst(rightUnionArray[rightCol * row + column].getFConst());
1351 }
1352 }
1353 // update return type for transpose
1354 returnType.setNominalSize(static_cast<unsigned char>(rightRow));
1355 returnType.setSecondarySize(static_cast<unsigned char>(rightCol));
1356 }
1357 break;
1358
1359 case EOpDeterminant:
1360 {
1361 ASSERT(node->getNominalSize() == node->getSecondarySize());
1362
1363 tempConstArray = new ConstantUnion[1];
1364 tempConstArray[0].setFConst(ComputeDeterminant(node->getNominalSize(), rightUnionArray));
1365 // update return type for determinant
1366 returnType.setNominalSize(1);
1367 returnType.setSecondarySize(1);
1368 }
1369 break;
1370
1371 case EOpInverse:
1372 {
1373 ASSERT(node->getNominalSize() == node->getSecondarySize());
1374
1375 tempConstArray = CreateInverse(node, rightUnionArray);
1376 if(!tempConstArray)
1377 {
1378 // Singular matrix, just copy
1379 tempConstArray = new ConstantUnion[objectSize];
1380 for(int i = 0; i < objectSize; i++)
1381 tempConstArray[i] = rightUnionArray[i];
1382 }
1383 }
1384 break;
1385
John Bauman66b8ab22014-05-06 15:57:45 -04001386 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -04001387 case EOpIMod:
John Bauman66b8ab22014-05-06 15:57:45 -04001388 tempConstArray = new ConstantUnion[objectSize];
1389 {// support MSVC++6.0
1390 for (int i = 0; i < objectSize; i++) {
1391 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001392 case EbtFloat:
1393 if (rightUnionArray[i] == 0.0f) {
1394 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1395 tempConstArray[i].setFConst(FLT_MAX);
1396 } else {
1397 ASSERT(op == EOpDiv);
1398 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1399 }
1400 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001401
Alexis Hetud061e422015-05-13 16:37:50 -04001402 case EbtInt:
1403 if (rightUnionArray[i] == 0) {
1404 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1405 tempConstArray[i].setIConst(INT_MAX);
1406 } else {
1407 if(op == EOpDiv) {
1408 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1409 } else {
1410 ASSERT(op == EOpIMod);
1411 tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst());
1412 }
1413 }
1414 break;
1415 case EbtUInt:
1416 if (rightUnionArray[i] == 0) {
1417 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1418 tempConstArray[i].setUConst(UINT_MAX);
1419 } else {
1420 if(op == EOpDiv) {
1421 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1422 } else {
1423 ASSERT(op == EOpIMod);
1424 tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst());
1425 }
1426 }
1427 break;
1428 default:
1429 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1430 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -04001431 }
1432 }
1433 }
1434 break;
1435
1436 case EOpMatrixTimesVector:
1437 if (node->getBasicType() != EbtFloat) {
1438 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1439 return 0;
1440 }
1441 tempConstArray = new ConstantUnion[getNominalSize()];
1442
1443 {// support MSVC++6.0
1444 for (int size = getNominalSize(), i = 0; i < size; i++) {
1445 tempConstArray[i].setFConst(0.0f);
1446 for (int j = 0; j < size; j++) {
1447 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1448 }
1449 }
1450 }
1451
1452 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1453 tempNode->setLine(getLine());
1454
1455 return tempNode;
1456
1457 case EOpVectorTimesMatrix:
1458 if (getType().getBasicType() != EbtFloat) {
1459 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1460 return 0;
1461 }
1462
1463 tempConstArray = new ConstantUnion[getNominalSize()];
1464 {// support MSVC++6.0
1465 for (int size = getNominalSize(), i = 0; i < size; i++) {
1466 tempConstArray[i].setFConst(0.0f);
1467 for (int j = 0; j < size; j++) {
1468 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1469 }
1470 }
1471 }
1472 break;
1473
1474 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1475 tempConstArray = new ConstantUnion[objectSize];
1476 {// support MSVC++6.0
1477 for (int i = 0; i < objectSize; i++)
1478 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1479 }
1480 break;
1481
1482 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1483 tempConstArray = new ConstantUnion[objectSize];
1484 {// support MSVC++6.0
1485 for (int i = 0; i < objectSize; i++)
1486 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1487 }
1488 break;
1489
1490 case EOpLogicalXor:
1491 tempConstArray = new ConstantUnion[objectSize];
1492 {// support MSVC++6.0
1493 for (int i = 0; i < objectSize; i++)
1494 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001495 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1496 default: assert(false && "Default missing");
John Bauman66b8ab22014-05-06 15:57:45 -04001497 }
1498 }
1499 break;
1500
Alexis Hetud061e422015-05-13 16:37:50 -04001501 case EOpBitwiseAnd:
1502 tempConstArray = new ConstantUnion[objectSize];
1503 for(int i = 0; i < objectSize; i++)
1504 tempConstArray[i] = unionArray[i] & rightUnionArray[i];
1505 break;
1506 case EOpBitwiseXor:
1507 tempConstArray = new ConstantUnion[objectSize];
1508 for(int i = 0; i < objectSize; i++)
1509 tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
1510 break;
1511 case EOpBitwiseOr:
1512 tempConstArray = new ConstantUnion[objectSize];
1513 for(int i = 0; i < objectSize; i++)
1514 tempConstArray[i] = unionArray[i] | rightUnionArray[i];
1515 break;
1516 case EOpBitShiftLeft:
1517 tempConstArray = new ConstantUnion[objectSize];
1518 for(int i = 0; i < objectSize; i++)
1519 tempConstArray[i] = unionArray[i] << rightUnionArray[i];
1520 break;
1521 case EOpBitShiftRight:
1522 tempConstArray = new ConstantUnion[objectSize];
1523 for(int i = 0; i < objectSize; i++)
1524 tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
1525 break;
1526
John Bauman66b8ab22014-05-06 15:57:45 -04001527 case EOpLessThan:
1528 assert(objectSize == 1);
1529 tempConstArray = new ConstantUnion[1];
1530 tempConstArray->setBConst(*unionArray < *rightUnionArray);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001531 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001532 break;
1533 case EOpGreaterThan:
1534 assert(objectSize == 1);
1535 tempConstArray = new ConstantUnion[1];
1536 tempConstArray->setBConst(*unionArray > *rightUnionArray);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001537 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001538 break;
1539 case EOpLessThanEqual:
1540 {
1541 assert(objectSize == 1);
1542 ConstantUnion constant;
1543 constant.setBConst(*unionArray > *rightUnionArray);
1544 tempConstArray = new ConstantUnion[1];
1545 tempConstArray->setBConst(!constant.getBConst());
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001546 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001547 break;
1548 }
1549 case EOpGreaterThanEqual:
1550 {
1551 assert(objectSize == 1);
1552 ConstantUnion constant;
1553 constant.setBConst(*unionArray < *rightUnionArray);
1554 tempConstArray = new ConstantUnion[1];
1555 tempConstArray->setBConst(!constant.getBConst());
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001556 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001557 break;
1558 }
1559
1560 case EOpEqual:
1561 if (getType().getBasicType() == EbtStruct) {
1562 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1563 boolNodeFlag = true;
1564 } else {
1565 for (int i = 0; i < objectSize; i++) {
1566 if (unionArray[i] != rightUnionArray[i]) {
1567 boolNodeFlag = true;
1568 break; // break out of for loop
1569 }
1570 }
1571 }
1572
1573 tempConstArray = new ConstantUnion[1];
1574 if (!boolNodeFlag) {
1575 tempConstArray->setBConst(true);
1576 }
1577 else {
1578 tempConstArray->setBConst(false);
1579 }
1580
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001581 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001582 tempNode->setLine(getLine());
1583
1584 return tempNode;
1585
1586 case EOpNotEqual:
1587 if (getType().getBasicType() == EbtStruct) {
1588 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1589 boolNodeFlag = true;
1590 } else {
1591 for (int i = 0; i < objectSize; i++) {
1592 if (unionArray[i] == rightUnionArray[i]) {
1593 boolNodeFlag = true;
1594 break; // break out of for loop
1595 }
1596 }
1597 }
1598
1599 tempConstArray = new ConstantUnion[1];
1600 if (!boolNodeFlag) {
1601 tempConstArray->setBConst(true);
1602 }
1603 else {
1604 tempConstArray->setBConst(false);
1605 }
1606
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001607 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001608 tempNode->setLine(getLine());
1609
1610 return tempNode;
1611
1612 default:
1613 infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
1614 return 0;
1615 }
1616 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1617 tempNode->setLine(getLine());
1618
1619 return tempNode;
1620 } else {
1621 //
1622 // Do unary operations
1623 //
1624 TIntermConstantUnion *newNode = 0;
1625 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
1626 for (int i = 0; i < objectSize; i++) {
1627 switch(op) {
1628 case EOpNegative:
1629 switch (getType().getBasicType()) {
1630 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1631 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1632 default:
1633 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1634 return 0;
1635 }
1636 break;
1637 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1638 switch (getType().getBasicType()) {
1639 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1640 default:
1641 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1642 return 0;
1643 }
1644 break;
Alexis Hetud061e422015-05-13 16:37:50 -04001645 case EOpBitwiseNot:
1646 switch(getType().getBasicType()) {
1647 case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
1648 case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
1649 default:
1650 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1651 return 0;
1652 }
1653 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001654 default:
1655 return 0;
1656 }
1657 }
1658 newNode = new TIntermConstantUnion(tempConstArray, getType());
1659 newNode->setLine(getLine());
1660 return newNode;
1661 }
1662}
1663
1664TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1665{
John Bauman66b8ab22014-05-06 15:57:45 -04001666 int size = node->getType().getObjectSize();
1667
1668 ConstantUnion *leftUnionArray = new ConstantUnion[size];
1669
1670 for (int i=0; i < size; i++) {
1671
1672 switch (promoteTo) {
1673 case EbtFloat:
1674 switch (node->getType().getBasicType()) {
1675 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001676 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001677 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001678 case EbtUInt:
1679 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
1680 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001681 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001682 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001683 break;
1684 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001685 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001686 break;
1687 default:
1688 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1689 return 0;
1690 }
1691 break;
1692 case EbtInt:
1693 switch (node->getType().getBasicType()) {
1694 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001695 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001696 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001697 case EbtUInt:
1698 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
1699 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001700 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001701 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001702 break;
1703 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001704 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001705 break;
1706 default:
1707 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1708 return 0;
1709 }
1710 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001711 case EbtUInt:
1712 switch (node->getType().getBasicType()) {
1713 case EbtInt:
1714 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
1715 break;
1716 case EbtUInt:
1717 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
1718 break;
1719 case EbtBool:
1720 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
1721 break;
1722 case EbtFloat:
1723 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
1724 break;
1725 default:
1726 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1727 return 0;
1728 }
1729 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001730 case EbtBool:
1731 switch (node->getType().getBasicType()) {
1732 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001733 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
John Bauman66b8ab22014-05-06 15:57:45 -04001734 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001735 case EbtUInt:
1736 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
1737 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001738 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001739 leftUnionArray[i].setBConst(node->getBConst(i));
John Bauman66b8ab22014-05-06 15:57:45 -04001740 break;
1741 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001742 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
John Bauman66b8ab22014-05-06 15:57:45 -04001743 break;
1744 default:
1745 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1746 return 0;
1747 }
1748
1749 break;
1750 default:
1751 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1752 return 0;
1753 }
1754
1755 }
1756
1757 const TType& t = node->getType();
1758
Alexis Hetub14178b2015-04-13 13:23:20 -04001759 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001760}
1761