blob: 14cd5b2ab29c383a1622cd34f6bab052bc648c6a [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//
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400335TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, const TSourceLoc &line, const TType *funcReturnType)
John Bauman66b8ab22014-05-06 15:57:45 -0400336{
John Bauman66b8ab22014-05-06 15:57:45 -0400337 if (child == 0) {
338 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
339 return 0;
340 }
341
342 switch (op) {
Alexis Hetud061e422015-05-13 16:37:50 -0400343 case EOpBitwiseNot:
Alexis Hetu9085c8d2015-06-01 13:48:07 -0400344 if (!IsInteger(child->getType().getBasicType()) || child->getType().isMatrix() || child->getType().isArray()) {
Alexis Hetud061e422015-05-13 16:37:50 -0400345 return 0;
346 }
347 break;
348
John Bauman66b8ab22014-05-06 15:57:45 -0400349 case EOpLogicalNot:
350 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
351 return 0;
352 }
353 break;
354
355 case EOpPostIncrement:
356 case EOpPreIncrement:
357 case EOpPostDecrement:
358 case EOpPreDecrement:
359 case EOpNegative:
360 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
361 return 0;
362 default: break;
363 }
364
John Bauman66b8ab22014-05-06 15:57:45 -0400365 TIntermConstantUnion *childTempConstant = 0;
366 if (child->getAsConstantUnion())
367 childTempConstant = child->getAsConstantUnion();
368
369 //
370 // Make a new node for the operator.
371 //
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400372 TIntermUnary *node = new TIntermUnary(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400373 node->setLine(line);
374 node->setOperand(child);
375
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400376 if (! node->promote(infoSink, funcReturnType))
John Bauman66b8ab22014-05-06 15:57:45 -0400377 return 0;
378
379 if (childTempConstant) {
380 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
381
382 if (newChild)
383 return newChild;
384 }
385
386 return node;
387}
388
389//
390// This is the safe way to change the operator on an aggregate, as it
391// does lots of error checking and fixing. Especially for establishing
392// a function call's operation on it's set of parameters. Sequences
393// of instructions are also aggregates, but they just direnctly set
394// their operator to EOpSequence.
395//
396// Returns an aggregate node, which could be the one passed in if
397// it was already an aggregate but no operator was set.
398//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400399TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400400{
401 TIntermAggregate* aggNode;
402
403 //
404 // Make sure we have an aggregate. If not turn it into one.
405 //
406 if (node) {
407 aggNode = node->getAsAggregate();
408 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
409 //
410 // Make an aggregate containing this node.
411 //
412 aggNode = new TIntermAggregate();
413 aggNode->getSequence().push_back(node);
John Bauman66b8ab22014-05-06 15:57:45 -0400414 }
415 } else
416 aggNode = new TIntermAggregate();
417
418 //
419 // Set the operator.
420 //
421 aggNode->setOp(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400422
423 return aggNode;
424}
425
426//
John Bauman66b8ab22014-05-06 15:57:45 -0400427// Safe way to combine two nodes into an aggregate. Works with null pointers,
428// a node that's not a aggregate yet, etc.
429//
430// Returns the resulting aggregate, unless 0 was passed in for
431// both existing nodes.
432//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400433TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400434{
435 if (left == 0 && right == 0)
436 return 0;
437
438 TIntermAggregate* aggNode = 0;
439 if (left)
440 aggNode = left->getAsAggregate();
441 if (!aggNode || aggNode->getOp() != EOpNull) {
442 aggNode = new TIntermAggregate;
443 if (left)
444 aggNode->getSequence().push_back(left);
445 }
446
447 if (right)
448 aggNode->getSequence().push_back(right);
449
Alexis Hetu253fdd12015-07-07 15:12:46 -0400450 aggNode->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400451
452 return aggNode;
453}
454
455//
456// Turn an existing node into an aggregate.
457//
458// Returns an aggregate, unless 0 was passed in for the existing node.
459//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400460TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400461{
462 if (node == 0)
463 return 0;
464
465 TIntermAggregate* aggNode = new TIntermAggregate;
466 aggNode->getSequence().push_back(node);
467
Alexis Hetu253fdd12015-07-07 15:12:46 -0400468 aggNode->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400469
470 return aggNode;
471}
472
473//
474// For "if" test nodes. There are three children; a condition,
475// a true path, and a false path. The two paths are in the
476// nodePair.
477//
478// Returns the selection node created.
479//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400480TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400481{
482 //
483 // For compile time constant selections, prune the code and
484 // test now.
485 //
486
487 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
Nicolas Capens198529d2015-02-10 13:54:19 -0500488 if (cond->getAsConstantUnion()->getBConst(0) == true)
John Bauman66b8ab22014-05-06 15:57:45 -0400489 return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
490 else
491 return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
492 }
493
494 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
495 node->setLine(line);
496
497 return node;
498}
499
500
Alexis Hetu253fdd12015-07-07 15:12:46 -0400501TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400502{
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500503 if (left->getType().getQualifier() == EvqConstExpr && right->getType().getQualifier() == EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400504 return right;
505 } else {
506 TIntermTyped *commaAggregate = growAggregate(left, right, line);
507 commaAggregate->getAsAggregate()->setOp(EOpComma);
508 commaAggregate->setType(right->getType());
509 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
510 return commaAggregate;
511 }
512}
513
514//
515// For "?:" test nodes. There are three children; a condition,
516// a true path, and a false path. The two paths are specified
517// as separate parameters.
518//
519// Returns the selection node created, or 0 if one could not be.
520//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400521TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400522{
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400523 if (trueBlock->getType() != falseBlock->getType())
524 {
525 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400526 }
527
528 //
529 // See if all the operands are constant, then fold it otherwise not.
530 //
531
532 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
Nicolas Capens198529d2015-02-10 13:54:19 -0500533 if (cond->getAsConstantUnion()->getBConst(0))
John Bauman66b8ab22014-05-06 15:57:45 -0400534 return trueBlock;
535 else
536 return falseBlock;
537 }
538
539 //
540 // Make a selection node.
541 //
542 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
543 node->getTypePointer()->setQualifier(EvqTemporary);
544 node->setLine(line);
545
546 return node;
547}
548
Alexis Hetu76a343a2015-06-04 17:21:22 -0400549TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
550{
551 TIntermSwitch *node = new TIntermSwitch(init, statementList);
552 node->setLine(line);
553
554 return node;
555}
556
557TIntermCase *TIntermediate::addCase(TIntermTyped *condition, const TSourceLoc &line)
558{
559 TIntermCase *node = new TIntermCase(condition);
560 node->setLine(line);
561
562 return node;
563}
564
John Bauman66b8ab22014-05-06 15:57:45 -0400565//
566// Constant terminal nodes. Has a union that contains bool, float or int constants
567//
568// Returns the constant union node created.
569//
570
Alexis Hetu253fdd12015-07-07 15:12:46 -0400571TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400572{
573 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
574 node->setLine(line);
575
576 return node;
577}
578
Alexis Hetu253fdd12015-07-07 15:12:46 -0400579TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400580{
581
582 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
583
584 node->setLine(line);
585 TIntermConstantUnion* constIntNode;
586 TIntermSequence &sequenceVector = node->getSequence();
587 ConstantUnion* unionArray;
588
589 for (int i = 0; i < fields.num; i++) {
590 unionArray = new ConstantUnion[1];
591 unionArray->setIConst(fields.offsets[i]);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500592 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), line);
John Bauman66b8ab22014-05-06 15:57:45 -0400593 sequenceVector.push_back(constIntNode);
594 }
595
596 return node;
597}
598
599//
600// Create loop nodes.
601//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400602TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400603{
604 TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
605 node->setLine(line);
606
607 return node;
608}
609
610//
611// Add branches.
612//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400613TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400614{
615 return addBranch(branchOp, 0, line);
616}
617
Alexis Hetu253fdd12015-07-07 15:12:46 -0400618TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400619{
620 TIntermBranch* node = new TIntermBranch(branchOp, expression);
621 node->setLine(line);
622
623 return node;
624}
625
626//
627// This is to be executed once the final root is put on top by the parsing
628// process.
629//
630bool TIntermediate::postProcess(TIntermNode* root)
631{
632 if (root == 0)
633 return true;
634
635 //
636 // First, finish off the top level sequence, if any
637 //
638 TIntermAggregate* aggRoot = root->getAsAggregate();
639 if (aggRoot && aggRoot->getOp() == EOpNull)
640 aggRoot->setOp(EOpSequence);
641
642 return true;
643}
644
John Bauman66b8ab22014-05-06 15:57:45 -0400645////////////////////////////////////////////////////////////////
646//
647// Member functions of the nodes used for building the tree.
648//
649////////////////////////////////////////////////////////////////
650
651//
652// Say whether or not an operation node changes the value of a variable.
653//
654// Returns true if state is modified.
655//
656bool TIntermOperator::modifiesState() const
657{
658 switch (op) {
659 case EOpPostIncrement:
660 case EOpPostDecrement:
661 case EOpPreIncrement:
662 case EOpPreDecrement:
663 case EOpAssign:
664 case EOpAddAssign:
665 case EOpSubAssign:
666 case EOpMulAssign:
667 case EOpVectorTimesMatrixAssign:
668 case EOpVectorTimesScalarAssign:
669 case EOpMatrixTimesScalarAssign:
670 case EOpMatrixTimesMatrixAssign:
671 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400672 case EOpIModAssign:
673 case EOpBitShiftLeftAssign:
674 case EOpBitShiftRightAssign:
675 case EOpBitwiseAndAssign:
676 case EOpBitwiseXorAssign:
677 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400678 return true;
679 default:
680 return false;
681 }
682}
683
684//
685// returns true if the operator is for one of the constructors
686//
687bool TIntermOperator::isConstructor() const
688{
689 switch (op) {
690 case EOpConstructVec2:
691 case EOpConstructVec3:
692 case EOpConstructVec4:
693 case EOpConstructMat2:
Alexis Hetu00106d42015-04-23 11:45:35 -0400694 case EOpConstructMat2x3:
695 case EOpConstructMat2x4:
696 case EOpConstructMat3x2:
John Bauman66b8ab22014-05-06 15:57:45 -0400697 case EOpConstructMat3:
Alexis Hetu00106d42015-04-23 11:45:35 -0400698 case EOpConstructMat3x4:
699 case EOpConstructMat4x2:
700 case EOpConstructMat4x3:
John Bauman66b8ab22014-05-06 15:57:45 -0400701 case EOpConstructMat4:
702 case EOpConstructFloat:
703 case EOpConstructIVec2:
704 case EOpConstructIVec3:
705 case EOpConstructIVec4:
706 case EOpConstructInt:
Nicolas Capense4b1b1d2015-02-17 17:26:01 -0500707 case EOpConstructUVec2:
708 case EOpConstructUVec3:
709 case EOpConstructUVec4:
Nicolas Capens3c20f802015-02-17 17:17:20 -0500710 case EOpConstructUInt:
John Bauman66b8ab22014-05-06 15:57:45 -0400711 case EOpConstructBVec2:
712 case EOpConstructBVec3:
713 case EOpConstructBVec4:
714 case EOpConstructBool:
715 case EOpConstructStruct:
716 return true;
717 default:
718 return false;
719 }
720}
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400721
John Bauman66b8ab22014-05-06 15:57:45 -0400722//
723// Make sure the type of a unary operator is appropriate for its
724// combination of operation and operand type.
725//
726// Returns false in nothing makes sense.
727//
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400728bool TIntermUnary::promote(TInfoSink&, const TType *funcReturnType)
John Bauman66b8ab22014-05-06 15:57:45 -0400729{
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400730 setType(funcReturnType ? *funcReturnType : operand->getType());
731
732 // Unary operations result in temporary variables unless const.
733 if(type.getQualifier() != EvqConstExpr)
734 {
735 type.setQualifier(EvqTemporary);
736 }
737
John Bauman66b8ab22014-05-06 15:57:45 -0400738 switch (op) {
739 case EOpLogicalNot:
740 if (operand->getBasicType() != EbtBool)
741 return false;
742 break;
Alexis Hetud061e422015-05-13 16:37:50 -0400743 case EOpBitwiseNot:
Alexis Hetu9085c8d2015-06-01 13:48:07 -0400744 if (!IsInteger(operand->getBasicType()))
Alexis Hetud061e422015-05-13 16:37:50 -0400745 return false;
746 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400747 case EOpNegative:
748 case EOpPostIncrement:
749 case EOpPostDecrement:
750 case EOpPreIncrement:
751 case EOpPreDecrement:
752 if (operand->getBasicType() == EbtBool)
753 return false;
754 break;
755
756 // operators for built-ins are already type checked against their prototype
757 case EOpAny:
758 case EOpAll:
759 case EOpVectorLogicalNot:
Alexis Hetu0f448072016-03-18 10:56:08 -0400760 case EOpAbs:
761 case EOpSign:
762 case EOpIsNan:
763 case EOpIsInf:
764 case EOpFloatBitsToInt:
765 case EOpFloatBitsToUint:
766 case EOpIntBitsToFloat:
767 case EOpUintBitsToFloat:
768 case EOpPackSnorm2x16:
769 case EOpPackUnorm2x16:
770 case EOpPackHalf2x16:
771 case EOpUnpackSnorm2x16:
772 case EOpUnpackUnorm2x16:
773 case EOpUnpackHalf2x16:
John Bauman66b8ab22014-05-06 15:57:45 -0400774 return true;
775
776 default:
777 if (operand->getBasicType() != EbtFloat)
778 return false;
779 }
780
John Bauman66b8ab22014-05-06 15:57:45 -0400781 return true;
782}
783
784//
785// Establishes the type of the resultant operation, as well as
786// makes the operator the correct one for the operands.
787//
788// Returns false if operator can't work on operands.
789//
790bool TIntermBinary::promote(TInfoSink& infoSink)
791{
Alexis Hetue5246692015-06-18 12:34:52 -0400792 ASSERT(left->isArray() == right->isArray());
John Bauman66b8ab22014-05-06 15:57:45 -0400793
794 // GLSL ES 2.0 does not support implicit type casting.
795 // So the basic type should always match.
Alexis Hetu92ab1982015-08-18 15:28:27 -0400796 // GLSL ES 3.0 supports integer shift operands of different signedness.
797 if(op != EOpBitShiftLeft &&
798 op != EOpBitShiftRight &&
799 op != EOpBitShiftLeftAssign &&
800 op != EOpBitShiftRightAssign &&
801 left->getBasicType() != right->getBasicType())
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400802 {
John Bauman66b8ab22014-05-06 15:57:45 -0400803 return false;
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400804 }
John Bauman66b8ab22014-05-06 15:57:45 -0400805
806 //
807 // Base assumption: just make the type the same as the left
808 // operand. Then only deviations from this need be coded.
809 //
810 setType(left->getType());
811
812 // The result gets promoted to the highest precision.
813 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
814 getTypePointer()->setPrecision(higherPrecision);
815
816 // Binary operations results in temporary variables unless both
817 // operands are const.
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500818 if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400819 getTypePointer()->setQualifier(EvqTemporary);
820 }
821
Alexis Hetud061e422015-05-13 16:37:50 -0400822 int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
John Bauman66b8ab22014-05-06 15:57:45 -0400823
824 //
825 // All scalars. Code after this test assumes this case is removed!
826 //
Alexis Hetud061e422015-05-13 16:37:50 -0400827 if (primarySize == 1) {
John Bauman66b8ab22014-05-06 15:57:45 -0400828 switch (op) {
829 //
830 // Promote to conditional
831 //
832 case EOpEqual:
833 case EOpNotEqual:
834 case EOpLessThan:
835 case EOpGreaterThan:
836 case EOpLessThanEqual:
837 case EOpGreaterThanEqual:
838 setType(TType(EbtBool, EbpUndefined));
839 break;
840
841 //
842 // And and Or operate on conditionals
843 //
844 case EOpLogicalAnd:
845 case EOpLogicalOr:
Alexis Hetud061e422015-05-13 16:37:50 -0400846 case EOpLogicalXor:
John Bauman66b8ab22014-05-06 15:57:45 -0400847 // Both operands must be of type bool.
848 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
849 return false;
850 setType(TType(EbtBool, EbpUndefined));
851 break;
852
853 default:
854 break;
855 }
856 return true;
857 }
858
859 // If we reach here, at least one of the operands is vector or matrix.
860 // The other operand could be a scalar, vector, or matrix.
John Bauman66b8ab22014-05-06 15:57:45 -0400861 // Can these two operands be combined?
862 //
863 TBasicType basicType = left->getBasicType();
864 switch (op) {
865 case EOpMul:
866 if (!left->isMatrix() && right->isMatrix()) {
867 if (left->isVector())
Alexis Hetu00106d42015-04-23 11:45:35 -0400868 {
John Bauman66b8ab22014-05-06 15:57:45 -0400869 op = EOpVectorTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400870 setType(TType(basicType, higherPrecision, EvqTemporary,
871 static_cast<unsigned char>(right->getNominalSize()), 1));
872 }
John Bauman66b8ab22014-05-06 15:57:45 -0400873 else {
874 op = EOpMatrixTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400875 setType(TType(basicType, higherPrecision, EvqTemporary,
876 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400877 }
878 } else if (left->isMatrix() && !right->isMatrix()) {
879 if (right->isVector()) {
880 op = EOpMatrixTimesVector;
Alexis Hetu00106d42015-04-23 11:45:35 -0400881 setType(TType(basicType, higherPrecision, EvqTemporary,
882 static_cast<unsigned char>(left->getSecondarySize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400883 } else {
884 op = EOpMatrixTimesScalar;
885 }
886 } else if (left->isMatrix() && right->isMatrix()) {
887 op = EOpMatrixTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400888 setType(TType(basicType, higherPrecision, EvqTemporary,
889 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400890 } else if (!left->isMatrix() && !right->isMatrix()) {
891 if (left->isVector() && right->isVector()) {
892 // leave as component product
893 } else if (left->isVector() || right->isVector()) {
894 op = EOpVectorTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400895 setType(TType(basicType, higherPrecision, EvqTemporary,
896 static_cast<unsigned char>(primarySize), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400897 }
898 } else {
899 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
900 return false;
901 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400902
903 if(!ValidateMultiplication(op, left->getType(), right->getType()))
904 {
905 return false;
906 }
John Bauman66b8ab22014-05-06 15:57:45 -0400907 break;
908 case EOpMulAssign:
909 if (!left->isMatrix() && right->isMatrix()) {
910 if (left->isVector())
911 op = EOpVectorTimesMatrixAssign;
912 else {
913 return false;
914 }
915 } else if (left->isMatrix() && !right->isMatrix()) {
916 if (right->isVector()) {
917 return false;
918 } else {
919 op = EOpMatrixTimesScalarAssign;
920 }
921 } else if (left->isMatrix() && right->isMatrix()) {
922 op = EOpMatrixTimesMatrixAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400923 setType(TType(basicType, higherPrecision, EvqTemporary,
924 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400925 } else if (!left->isMatrix() && !right->isMatrix()) {
926 if (left->isVector() && right->isVector()) {
927 // leave as component product
928 } else if (left->isVector() || right->isVector()) {
929 if (! left->isVector())
930 return false;
931 op = EOpVectorTimesScalarAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400932 setType(TType(basicType, higherPrecision, EvqTemporary,
933 static_cast<unsigned char>(left->getNominalSize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400934 }
935 } else {
936 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
937 return false;
938 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400939
940 if(!ValidateMultiplication(op, left->getType(), right->getType()))
941 {
942 return false;
943 }
John Bauman66b8ab22014-05-06 15:57:45 -0400944 break;
945
946 case EOpAssign:
947 case EOpInitialize:
Alexis Hetu00106d42015-04-23 11:45:35 -0400948 // No more additional checks are needed.
949 if ((left->getNominalSize() != right->getNominalSize()) ||
950 (left->getSecondarySize() != right->getSecondarySize()))
951 return false;
952 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400953 case EOpAdd:
954 case EOpSub:
955 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -0400956 case EOpIMod:
957 case EOpBitShiftLeft:
958 case EOpBitShiftRight:
959 case EOpBitwiseAnd:
960 case EOpBitwiseXor:
961 case EOpBitwiseOr:
John Bauman66b8ab22014-05-06 15:57:45 -0400962 case EOpAddAssign:
963 case EOpSubAssign:
964 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400965 case EOpIModAssign:
966 case EOpBitShiftLeftAssign:
967 case EOpBitShiftRightAssign:
968 case EOpBitwiseAndAssign:
969 case EOpBitwiseXorAssign:
970 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400971 if ((left->isMatrix() && right->isVector()) ||
972 (left->isVector() && right->isMatrix()))
973 return false;
Alexis Hetud061e422015-05-13 16:37:50 -0400974
975 // Are the sizes compatible?
976 if(left->getNominalSize() != right->getNominalSize() ||
977 left->getSecondarySize() != right->getSecondarySize())
978 {
979 // If the nominal sizes of operands do not match:
980 // One of them must be a scalar.
981 if(!left->isScalar() && !right->isScalar())
982 return false;
983
984 // In the case of compound assignment other than multiply-assign,
985 // the right side needs to be a scalar. Otherwise a vector/matrix
986 // would be assigned to a scalar. A scalar can't be shifted by a
987 // vector either.
988 if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight))
989 return false;
990 }
991
992 {
Alexis Hetu00106d42015-04-23 11:45:35 -0400993 const int secondarySize = std::max(
994 left->getSecondarySize(), right->getSecondarySize());
Alexis Hetud061e422015-05-13 16:37:50 -0400995 setType(TType(basicType, higherPrecision, EvqTemporary,
996 static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
997 if(left->isArray())
998 {
999 ASSERT(left->getArraySize() == right->getArraySize());
1000 type.setArraySize(left->getArraySize());
1001 }
1002 }
John Bauman66b8ab22014-05-06 15:57:45 -04001003 break;
1004
1005 case EOpEqual:
1006 case EOpNotEqual:
1007 case EOpLessThan:
1008 case EOpGreaterThan:
1009 case EOpLessThanEqual:
1010 case EOpGreaterThanEqual:
Alexis Hetu00106d42015-04-23 11:45:35 -04001011 if ((left->getNominalSize() != right->getNominalSize()) ||
1012 (left->getSecondarySize() != right->getSecondarySize()))
John Bauman66b8ab22014-05-06 15:57:45 -04001013 return false;
1014 setType(TType(EbtBool, EbpUndefined));
1015 break;
1016
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001017 case EOpOuterProduct:
1018 if(!left->isVector() || !right->isVector())
1019 return false;
1020 setType(TType(EbtFloat, right->getNominalSize(), left->getNominalSize()));
1021 break;
1022
1023 case EOpTranspose:
1024 if(!right->isMatrix())
1025 return false;
1026 setType(TType(EbtFloat, right->getSecondarySize(), right->getNominalSize()));
1027 break;
1028
1029 case EOpDeterminant:
1030 if(!right->isMatrix())
1031 return false;
1032 setType(TType(EbtFloat));
1033 break;
1034
1035 case EOpInverse:
1036 if(!right->isMatrix() || right->getNominalSize() != right->getSecondarySize())
1037 return false;
1038 setType(right->getType());
1039 break;
1040
John Bauman66b8ab22014-05-06 15:57:45 -04001041 default:
1042 return false;
1043 }
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001044
John Bauman66b8ab22014-05-06 15:57:45 -04001045 return true;
1046}
1047
1048bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1049{
Alexis Hetua8b364b2015-06-10 11:48:40 -04001050 const TFieldList& fields = leftNodeType.getStruct()->fields();
John Bauman66b8ab22014-05-06 15:57:45 -04001051
Alexis Hetua8b364b2015-06-10 11:48:40 -04001052 size_t structSize = fields.size();
John Bauman66b8ab22014-05-06 15:57:45 -04001053 int index = 0;
1054
1055 for (size_t j = 0; j < structSize; j++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001056 int size = fields[j]->type()->getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04001057 for (int i = 0; i < size; i++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001058 if (fields[j]->type()->getBasicType() == EbtStruct) {
1059 if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
John Bauman66b8ab22014-05-06 15:57:45 -04001060 return false;
1061 } else {
1062 if (leftUnionArray[index] != rightUnionArray[index])
1063 return false;
1064 index++;
1065 }
1066
1067 }
1068 }
1069 return true;
1070}
1071
1072bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1073{
1074 if (leftNodeType.isArray()) {
1075 TType typeWithoutArrayness = leftNodeType;
1076 typeWithoutArrayness.clearArrayness();
1077
1078 int arraySize = leftNodeType.getArraySize();
1079
1080 for (int i = 0; i < arraySize; ++i) {
1081 int offset = typeWithoutArrayness.getObjectSize() * i;
1082 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1083 return false;
1084 }
1085 } else
1086 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
1087
1088 return true;
1089}
1090
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001091float determinant2(float m00, float m01, float m10, float m11)
1092{
1093 return m00 * m11 - m01 * m10;
1094}
1095
1096float determinant3(float m00, float m01, float m02,
1097 float m10, float m11, float m12,
1098 float m20, float m21, float m22)
1099{
1100 return m00 * determinant2(m11, m12, m21, m22) -
1101 m10 * determinant2(m01, m02, m21, m22) +
1102 m20 * determinant2(m01, m02, m11, m12);
1103}
1104
1105float determinant4(float m00, float m01, float m02, float m03,
1106 float m10, float m11, float m12, float m13,
1107 float m20, float m21, float m22, float m23,
1108 float m30, float m31, float m32, float m33)
1109{
1110 return m00 * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33) -
1111 m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) +
1112 m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) -
1113 m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
1114}
1115
1116float ComputeDeterminant(int size, ConstantUnion* unionArray)
1117{
1118 switch(size)
1119 {
1120 case 2:
1121 return determinant2(unionArray[0].getFConst(),
1122 unionArray[1].getFConst(),
1123 unionArray[2].getFConst(),
1124 unionArray[3].getFConst());
1125 case 3:
1126 return determinant3(unionArray[0].getFConst(),
1127 unionArray[1].getFConst(),
1128 unionArray[2].getFConst(),
1129 unionArray[3].getFConst(),
1130 unionArray[4].getFConst(),
1131 unionArray[5].getFConst(),
1132 unionArray[6].getFConst(),
1133 unionArray[7].getFConst(),
1134 unionArray[8].getFConst());
1135 case 4:
1136 return determinant4(unionArray[0].getFConst(),
1137 unionArray[1].getFConst(),
1138 unionArray[2].getFConst(),
1139 unionArray[3].getFConst(),
1140 unionArray[4].getFConst(),
1141 unionArray[5].getFConst(),
1142 unionArray[6].getFConst(),
1143 unionArray[7].getFConst(),
1144 unionArray[8].getFConst(),
1145 unionArray[9].getFConst(),
1146 unionArray[10].getFConst(),
1147 unionArray[11].getFConst(),
1148 unionArray[12].getFConst(),
1149 unionArray[13].getFConst(),
1150 unionArray[14].getFConst(),
1151 unionArray[15].getFConst());
1152 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001153 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001154 return 0.0f;
1155 }
1156}
1157
1158ConstantUnion* CreateInverse(TIntermConstantUnion* node, ConstantUnion* unionArray)
1159{
1160 ConstantUnion* tempConstArray = 0;
1161 int size = node->getNominalSize();
1162 float determinant = ComputeDeterminant(size, unionArray);
1163 if(determinant != 0.0f)
1164 {
1165 float invDet = 1.0f / determinant;
1166 tempConstArray = new ConstantUnion[size*size];
1167 switch(size)
1168 {
1169 case 2:
1170 {
1171 float m00 = unionArray[0].getFConst(); // Matrix is:
1172 float m01 = unionArray[1].getFConst(); // (m00, m01)
1173 float m10 = unionArray[2].getFConst(); // (m10, m11)
1174 float m11 = unionArray[3].getFConst();
1175 tempConstArray[0].setFConst( invDet * m11);
1176 tempConstArray[1].setFConst(-invDet * m01);
1177 tempConstArray[2].setFConst(-invDet * m10);
1178 tempConstArray[3].setFConst( invDet * m00);
1179 }
1180 break;
1181 case 3:
1182 {
1183 float m00 = unionArray[0].getFConst(); // Matrix is:
1184 float m01 = unionArray[1].getFConst(); // (m00, m01, m02)
1185 float m02 = unionArray[2].getFConst(); // (m10, m11, m12)
1186 float m10 = unionArray[3].getFConst(); // (m20, m21, m22)
1187 float m11 = unionArray[4].getFConst();
1188 float m12 = unionArray[5].getFConst();
1189 float m20 = unionArray[6].getFConst();
1190 float m21 = unionArray[7].getFConst();
1191 float m22 = unionArray[8].getFConst();
1192 tempConstArray[0].setFConst(invDet * determinant2(m11, m12, m21, m22)); // m00 = invDet * (m11 * m22 - m12 * m21)
1193 tempConstArray[1].setFConst(invDet * determinant2(m12, m10, m22, m20)); // m01 = -invDet * (m10 * m22 - m12 * m20)
1194 tempConstArray[2].setFConst(invDet * determinant2(m10, m11, m20, m21)); // m02 = invDet * (m10 * m21 - m11 * m20)
1195 tempConstArray[3].setFConst(invDet * determinant2(m21, m22, m01, m02)); // m10 = -invDet * (m01 * m22 - m02 * m21)
1196 tempConstArray[4].setFConst(invDet * determinant2(m00, m02, m20, m22)); // m11 = invDet * (m00 * m22 - m02 * m20)
1197 tempConstArray[5].setFConst(invDet * determinant2(m20, m21, m00, m01)); // m12 = -invDet * (m00 * m21 - m01 * m20)
1198 tempConstArray[6].setFConst(invDet * determinant2(m01, m02, m11, m12)); // m20 = invDet * (m01 * m12 - m02 * m11)
1199 tempConstArray[7].setFConst(invDet * determinant2(m10, m12, m00, m02)); // m21 = -invDet * (m00 * m12 - m02 * m10)
1200 tempConstArray[8].setFConst(invDet * determinant2(m00, m01, m10, m11)); // m22 = invDet * (m00 * m11 - m01 * m10)
1201 }
1202 break;
1203 case 4:
1204 {
1205 float m00 = unionArray[0].getFConst(); // Matrix is:
1206 float m01 = unionArray[1].getFConst(); // (m00, m01, m02, m03)
1207 float m02 = unionArray[2].getFConst(); // (m10, m11, m12, m13)
1208 float m03 = unionArray[3].getFConst(); // (m20, m21, m22, m23)
1209 float m10 = unionArray[4].getFConst(); // (m30, m31, m32, m33)
1210 float m11 = unionArray[5].getFConst();
1211 float m12 = unionArray[6].getFConst();
1212 float m13 = unionArray[7].getFConst();
1213 float m20 = unionArray[8].getFConst();
1214 float m21 = unionArray[9].getFConst();
1215 float m22 = unionArray[10].getFConst();
1216 float m23 = unionArray[11].getFConst();
1217 float m30 = unionArray[12].getFConst();
1218 float m31 = unionArray[13].getFConst();
1219 float m32 = unionArray[14].getFConst();
1220 float m33 = unionArray[15].getFConst();
1221 tempConstArray[ 0].setFConst( invDet * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33)); // m00
1222 tempConstArray[ 1].setFConst(-invDet * determinant3(m10, m12, m13, m20, m22, m23, m30, m32, m33)); // m01
1223 tempConstArray[ 2].setFConst( invDet * determinant3(m10, m11, m13, m20, m21, m23, m30, m31, m33)); // m02
1224 tempConstArray[ 3].setFConst(-invDet * determinant3(m10, m11, m12, m20, m21, m22, m30, m31, m32)); // m03
1225 tempConstArray[ 4].setFConst( invDet * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33)); // m10
1226 tempConstArray[ 5].setFConst(-invDet * determinant3(m00, m02, m03, m20, m22, m23, m30, m32, m33)); // m11
1227 tempConstArray[ 6].setFConst( invDet * determinant3(m00, m01, m03, m20, m21, m23, m30, m31, m33)); // m12
1228 tempConstArray[ 7].setFConst(-invDet * determinant3(m00, m01, m02, m20, m21, m22, m30, m31, m32)); // m13
1229 tempConstArray[ 8].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33)); // m20
1230 tempConstArray[ 9].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m30, m32, m33)); // m21
1231 tempConstArray[10].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m30, m31, m33)); // m22
1232 tempConstArray[11].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m30, m31, m32)); // m23
1233 tempConstArray[12].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23)); // m30
1234 tempConstArray[13].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m20, m22, m23)); // m31
1235 tempConstArray[14].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m20, m21, m23)); // m32
1236 tempConstArray[15].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m20, m21, m22)); // m33
1237 }
1238 break;
1239 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001240 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001241 }
1242 }
1243 return tempConstArray;
1244}
1245
John Bauman66b8ab22014-05-06 15:57:45 -04001246//
1247// The fold functions see if an operation on a constant can be done in place,
1248// without generating run-time code.
1249//
1250// Returns the node to keep using, which may or may not be the node passed in.
1251//
1252
1253TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1254{
1255 ConstantUnion *unionArray = getUnionArrayPointer();
1256 int objectSize = getType().getObjectSize();
1257
1258 if (constantNode) { // binary operations
1259 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
1260 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
1261 TType returnType = getType();
1262
1263 // for a case like float f = 1.2 + vec4(2,3,4,5);
1264 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
1265 rightUnionArray = new ConstantUnion[objectSize];
1266 for (int i = 0; i < objectSize; ++i)
1267 rightUnionArray[i] = *node->getUnionArrayPointer();
1268 returnType = getType();
1269 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1270 // for a case like float f = vec4(2,3,4,5) + 1.2;
1271 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
1272 for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
1273 unionArray[i] = *getUnionArrayPointer();
1274 returnType = node->getType();
1275 objectSize = constantNode->getType().getObjectSize();
1276 }
1277
1278 ConstantUnion* tempConstArray = 0;
1279 TIntermConstantUnion *tempNode;
1280
1281 bool boolNodeFlag = false;
1282 switch(op) {
1283 case EOpAdd:
1284 tempConstArray = new ConstantUnion[objectSize];
1285 {// support MSVC++6.0
1286 for (int i = 0; i < objectSize; i++)
1287 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1288 }
1289 break;
1290 case EOpSub:
1291 tempConstArray = new ConstantUnion[objectSize];
1292 {// support MSVC++6.0
1293 for (int i = 0; i < objectSize; i++)
1294 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1295 }
1296 break;
1297
1298 case EOpMul:
1299 case EOpVectorTimesScalar:
1300 case EOpMatrixTimesScalar:
1301 tempConstArray = new ConstantUnion[objectSize];
1302 {// support MSVC++6.0
1303 for (int i = 0; i < objectSize; i++)
1304 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1305 }
1306 break;
1307 case EOpMatrixTimesMatrix:
1308 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1309 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1310 return 0;
1311 }
1312 {// support MSVC++6.0
Alexis Hetu00106d42015-04-23 11:45:35 -04001313 int leftNumCols = getNominalSize();
1314 int leftNumRows = getSecondarySize();
1315 int rightNumCols = node->getNominalSize();
1316 int rightNumRows = node->getSecondarySize();
1317 if(leftNumCols != rightNumRows) {
1318 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1319 return 0;
1320 }
1321 int tempNumCols = rightNumCols;
1322 int tempNumRows = leftNumRows;
1323 int tempNumAdds = leftNumCols;
1324 tempConstArray = new ConstantUnion[tempNumCols*tempNumRows];
1325 for (int row = 0; row < tempNumRows; row++) {
1326 for (int column = 0; column < tempNumCols; column++) {
1327 tempConstArray[tempNumRows * column + row].setFConst(0.0f);
1328 for (int i = 0; i < tempNumAdds; i++) {
1329 tempConstArray[tempNumRows * column + row].setFConst(tempConstArray[tempNumRows * column + row].getFConst() + unionArray[i * leftNumRows + row].getFConst() * (rightUnionArray[column * rightNumRows + i].getFConst()));
John Bauman66b8ab22014-05-06 15:57:45 -04001330 }
1331 }
1332 }
Alexis Hetu00106d42015-04-23 11:45:35 -04001333 // update return type for matrix product
1334 returnType.setNominalSize(static_cast<unsigned char>(tempNumCols));
1335 returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows));
John Bauman66b8ab22014-05-06 15:57:45 -04001336 }
1337 break;
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001338
1339 case EOpOuterProduct:
1340 {
1341 int leftSize = getNominalSize();
1342 int rightSize = node->getNominalSize();
1343 tempConstArray = new ConstantUnion[leftSize*rightSize];
1344 for(int row = 0; row < leftSize; row++) {
1345 for(int column = 0; column < rightSize; column++) {
1346 tempConstArray[leftSize * column + row].setFConst(unionArray[row].getFConst() * rightUnionArray[column].getFConst());
1347 }
1348 }
1349 // update return type for outer product
1350 returnType.setNominalSize(static_cast<unsigned char>(rightSize));
1351 returnType.setSecondarySize(static_cast<unsigned char>(leftSize));
1352 }
1353 break;
1354
1355 case EOpTranspose:
1356 {
1357 int rightCol = node->getNominalSize();
1358 int rightRow = node->getSecondarySize();
1359 tempConstArray = new ConstantUnion[rightCol*rightRow];
1360 for(int row = 0; row < rightRow; row++) {
1361 for(int column = 0; column < rightCol; column++) {
1362 tempConstArray[rightRow * column + row].setFConst(rightUnionArray[rightCol * row + column].getFConst());
1363 }
1364 }
1365 // update return type for transpose
1366 returnType.setNominalSize(static_cast<unsigned char>(rightRow));
1367 returnType.setSecondarySize(static_cast<unsigned char>(rightCol));
1368 }
1369 break;
1370
1371 case EOpDeterminant:
1372 {
1373 ASSERT(node->getNominalSize() == node->getSecondarySize());
1374
1375 tempConstArray = new ConstantUnion[1];
1376 tempConstArray[0].setFConst(ComputeDeterminant(node->getNominalSize(), rightUnionArray));
1377 // update return type for determinant
1378 returnType.setNominalSize(1);
1379 returnType.setSecondarySize(1);
1380 }
1381 break;
1382
1383 case EOpInverse:
1384 {
1385 ASSERT(node->getNominalSize() == node->getSecondarySize());
1386
1387 tempConstArray = CreateInverse(node, rightUnionArray);
1388 if(!tempConstArray)
1389 {
1390 // Singular matrix, just copy
1391 tempConstArray = new ConstantUnion[objectSize];
1392 for(int i = 0; i < objectSize; i++)
1393 tempConstArray[i] = rightUnionArray[i];
1394 }
1395 }
1396 break;
1397
John Bauman66b8ab22014-05-06 15:57:45 -04001398 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -04001399 case EOpIMod:
John Bauman66b8ab22014-05-06 15:57:45 -04001400 tempConstArray = new ConstantUnion[objectSize];
1401 {// support MSVC++6.0
1402 for (int i = 0; i < objectSize; i++) {
1403 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001404 case EbtFloat:
1405 if (rightUnionArray[i] == 0.0f) {
1406 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1407 tempConstArray[i].setFConst(FLT_MAX);
1408 } else {
1409 ASSERT(op == EOpDiv);
1410 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1411 }
1412 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001413
Alexis Hetud061e422015-05-13 16:37:50 -04001414 case EbtInt:
1415 if (rightUnionArray[i] == 0) {
1416 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1417 tempConstArray[i].setIConst(INT_MAX);
1418 } else {
1419 if(op == EOpDiv) {
1420 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1421 } else {
1422 ASSERT(op == EOpIMod);
1423 tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst());
1424 }
1425 }
1426 break;
1427 case EbtUInt:
1428 if (rightUnionArray[i] == 0) {
1429 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1430 tempConstArray[i].setUConst(UINT_MAX);
1431 } else {
1432 if(op == EOpDiv) {
1433 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1434 } else {
1435 ASSERT(op == EOpIMod);
1436 tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst());
1437 }
1438 }
1439 break;
1440 default:
1441 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1442 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -04001443 }
1444 }
1445 }
1446 break;
1447
1448 case EOpMatrixTimesVector:
1449 if (node->getBasicType() != EbtFloat) {
1450 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1451 return 0;
1452 }
1453 tempConstArray = new ConstantUnion[getNominalSize()];
1454
1455 {// support MSVC++6.0
1456 for (int size = getNominalSize(), i = 0; i < size; i++) {
1457 tempConstArray[i].setFConst(0.0f);
1458 for (int j = 0; j < size; j++) {
1459 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1460 }
1461 }
1462 }
1463
1464 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1465 tempNode->setLine(getLine());
1466
1467 return tempNode;
1468
1469 case EOpVectorTimesMatrix:
1470 if (getType().getBasicType() != EbtFloat) {
1471 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1472 return 0;
1473 }
1474
1475 tempConstArray = new ConstantUnion[getNominalSize()];
1476 {// support MSVC++6.0
1477 for (int size = getNominalSize(), i = 0; i < size; i++) {
1478 tempConstArray[i].setFConst(0.0f);
1479 for (int j = 0; j < size; j++) {
1480 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1481 }
1482 }
1483 }
1484 break;
1485
1486 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1487 tempConstArray = new ConstantUnion[objectSize];
1488 {// support MSVC++6.0
1489 for (int i = 0; i < objectSize; i++)
1490 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1491 }
1492 break;
1493
1494 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1495 tempConstArray = new ConstantUnion[objectSize];
1496 {// support MSVC++6.0
1497 for (int i = 0; i < objectSize; i++)
1498 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1499 }
1500 break;
1501
1502 case EOpLogicalXor:
1503 tempConstArray = new ConstantUnion[objectSize];
1504 {// support MSVC++6.0
1505 for (int i = 0; i < objectSize; i++)
1506 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001507 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1508 default: assert(false && "Default missing");
John Bauman66b8ab22014-05-06 15:57:45 -04001509 }
1510 }
1511 break;
1512
Alexis Hetud061e422015-05-13 16:37:50 -04001513 case EOpBitwiseAnd:
1514 tempConstArray = new ConstantUnion[objectSize];
1515 for(int i = 0; i < objectSize; i++)
1516 tempConstArray[i] = unionArray[i] & rightUnionArray[i];
1517 break;
1518 case EOpBitwiseXor:
1519 tempConstArray = new ConstantUnion[objectSize];
1520 for(int i = 0; i < objectSize; i++)
1521 tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
1522 break;
1523 case EOpBitwiseOr:
1524 tempConstArray = new ConstantUnion[objectSize];
1525 for(int i = 0; i < objectSize; i++)
1526 tempConstArray[i] = unionArray[i] | rightUnionArray[i];
1527 break;
1528 case EOpBitShiftLeft:
1529 tempConstArray = new ConstantUnion[objectSize];
1530 for(int i = 0; i < objectSize; i++)
1531 tempConstArray[i] = unionArray[i] << rightUnionArray[i];
1532 break;
1533 case EOpBitShiftRight:
1534 tempConstArray = new ConstantUnion[objectSize];
1535 for(int i = 0; i < objectSize; i++)
1536 tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
1537 break;
1538
John Bauman66b8ab22014-05-06 15:57:45 -04001539 case EOpLessThan:
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001540 tempConstArray = new ConstantUnion[objectSize];
1541 for(int i = 0; i < objectSize; i++)
1542 tempConstArray[i].setBConst(unionArray[i] < rightUnionArray[i]);
1543 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
John Bauman66b8ab22014-05-06 15:57:45 -04001544 break;
1545 case EOpGreaterThan:
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001546 tempConstArray = new ConstantUnion[objectSize];
1547 for(int i = 0; i < objectSize; i++)
1548 tempConstArray[i].setBConst(unionArray[i] > rightUnionArray[i]);
1549 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
John Bauman66b8ab22014-05-06 15:57:45 -04001550 break;
1551 case EOpLessThanEqual:
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001552 tempConstArray = new ConstantUnion[objectSize];
1553 for(int i = 0; i < objectSize; i++)
1554 tempConstArray[i].setBConst(unionArray[i] <= rightUnionArray[i]);
1555 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1556 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001557 case EOpGreaterThanEqual:
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001558 tempConstArray = new ConstantUnion[objectSize];
1559 for(int i = 0; i < objectSize; i++)
1560 tempConstArray[i].setBConst(unionArray[i] >= rightUnionArray[i]);
1561 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1562 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001563 case EOpEqual:
1564 if (getType().getBasicType() == EbtStruct) {
1565 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1566 boolNodeFlag = true;
1567 } else {
1568 for (int i = 0; i < objectSize; i++) {
1569 if (unionArray[i] != rightUnionArray[i]) {
1570 boolNodeFlag = true;
1571 break; // break out of for loop
1572 }
1573 }
1574 }
1575
1576 tempConstArray = new ConstantUnion[1];
1577 if (!boolNodeFlag) {
1578 tempConstArray->setBConst(true);
1579 }
1580 else {
1581 tempConstArray->setBConst(false);
1582 }
1583
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001584 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001585 tempNode->setLine(getLine());
1586
1587 return tempNode;
1588
1589 case EOpNotEqual:
1590 if (getType().getBasicType() == EbtStruct) {
1591 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1592 boolNodeFlag = true;
1593 } else {
1594 for (int i = 0; i < objectSize; i++) {
1595 if (unionArray[i] == rightUnionArray[i]) {
1596 boolNodeFlag = true;
1597 break; // break out of for loop
1598 }
1599 }
1600 }
1601
1602 tempConstArray = new ConstantUnion[1];
1603 if (!boolNodeFlag) {
1604 tempConstArray->setBConst(true);
1605 }
1606 else {
1607 tempConstArray->setBConst(false);
1608 }
1609
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001610 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001611 tempNode->setLine(getLine());
1612
1613 return tempNode;
Nicolas Capens91dfb972016-04-09 23:45:12 -04001614 case EOpMax:
1615 tempConstArray = new ConstantUnion[objectSize];
1616 {// support MSVC++6.0
1617 for (int i = 0; i < objectSize; i++)
1618 tempConstArray[i] = unionArray[i] > rightUnionArray[i] ? unionArray[i] : rightUnionArray[i];
1619 }
1620 break;
1621 case EOpMin:
1622 tempConstArray = new ConstantUnion[objectSize];
1623 {// support MSVC++6.0
1624 for (int i = 0; i < objectSize; i++)
1625 tempConstArray[i] = unionArray[i] < rightUnionArray[i] ? unionArray[i] : rightUnionArray[i];
1626 }
1627 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001628 default:
John Bauman66b8ab22014-05-06 15:57:45 -04001629 return 0;
1630 }
1631 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1632 tempNode->setLine(getLine());
1633
1634 return tempNode;
1635 } else {
1636 //
1637 // Do unary operations
1638 //
1639 TIntermConstantUnion *newNode = 0;
1640 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
1641 for (int i = 0; i < objectSize; i++) {
1642 switch(op) {
1643 case EOpNegative:
1644 switch (getType().getBasicType()) {
1645 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1646 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1647 default:
1648 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1649 return 0;
1650 }
1651 break;
1652 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1653 switch (getType().getBasicType()) {
1654 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1655 default:
1656 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1657 return 0;
1658 }
1659 break;
Alexis Hetud061e422015-05-13 16:37:50 -04001660 case EOpBitwiseNot:
1661 switch(getType().getBasicType()) {
1662 case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
1663 case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
1664 default:
1665 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1666 return 0;
1667 }
1668 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001669 default:
1670 return 0;
1671 }
1672 }
1673 newNode = new TIntermConstantUnion(tempConstArray, getType());
1674 newNode->setLine(getLine());
1675 return newNode;
1676 }
1677}
1678
1679TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1680{
John Bauman66b8ab22014-05-06 15:57:45 -04001681 int size = node->getType().getObjectSize();
1682
1683 ConstantUnion *leftUnionArray = new ConstantUnion[size];
1684
1685 for (int i=0; i < size; i++) {
1686
1687 switch (promoteTo) {
1688 case EbtFloat:
1689 switch (node->getType().getBasicType()) {
1690 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001691 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001692 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001693 case EbtUInt:
1694 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
1695 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001696 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001697 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001698 break;
1699 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001700 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001701 break;
1702 default:
1703 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1704 return 0;
1705 }
1706 break;
1707 case EbtInt:
1708 switch (node->getType().getBasicType()) {
1709 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001710 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001711 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001712 case EbtUInt:
1713 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
1714 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001715 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001716 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001717 break;
1718 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001719 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001720 break;
1721 default:
1722 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1723 return 0;
1724 }
1725 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001726 case EbtUInt:
1727 switch (node->getType().getBasicType()) {
1728 case EbtInt:
1729 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
1730 break;
1731 case EbtUInt:
1732 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
1733 break;
1734 case EbtBool:
1735 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
1736 break;
1737 case EbtFloat:
1738 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
1739 break;
1740 default:
1741 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1742 return 0;
1743 }
1744 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001745 case EbtBool:
1746 switch (node->getType().getBasicType()) {
1747 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001748 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
John Bauman66b8ab22014-05-06 15:57:45 -04001749 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001750 case EbtUInt:
1751 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
1752 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001753 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001754 leftUnionArray[i].setBConst(node->getBConst(i));
John Bauman66b8ab22014-05-06 15:57:45 -04001755 break;
1756 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001757 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
John Bauman66b8ab22014-05-06 15:57:45 -04001758 break;
1759 default:
1760 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1761 return 0;
1762 }
1763
1764 break;
1765 default:
1766 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1767 return 0;
1768 }
1769
1770 }
1771
1772 const TType& t = node->getType();
1773
Alexis Hetub14178b2015-04-13 13:23:20 -04001774 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001775}
1776