1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//
16// Build the intermediate representation.
17//
18
19#include <float.h>
20#include <limits.h>
21#include <algorithm>
22
23#include "localintermediate.h"
24#include "SymbolTable.h"
25#include "Common/Math.hpp"
26
27bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
28
29static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){
30 return left > right ? left : right;
31}
32
33static bool ValidateMultiplication(TOperator op, const TType &left, const TType &right)
34{
35 switch(op)
36 {
37 case EOpMul:
38 case EOpMulAssign:
39 return left.getNominalSize() == right.getNominalSize() &&
40 left.getSecondarySize() == right.getSecondarySize();
41 case EOpVectorTimesScalar:
42 case EOpVectorTimesScalarAssign:
43 return true;
44 case EOpVectorTimesMatrix:
45 return left.getNominalSize() == right.getSecondarySize();
46 case EOpVectorTimesMatrixAssign:
47 return left.getNominalSize() == right.getSecondarySize() &&
48 left.getNominalSize() == right.getNominalSize();
49 case EOpMatrixTimesVector:
50 return left.getNominalSize() == right.getNominalSize();
51 case EOpMatrixTimesScalar:
52 case EOpMatrixTimesScalarAssign:
53 return true;
54 case EOpMatrixTimesMatrix:
55 return left.getNominalSize() == right.getSecondarySize();
56 case EOpMatrixTimesMatrixAssign:
57 return left.getNominalSize() == right.getNominalSize() &&
58 left.getSecondarySize() == right.getSecondarySize();
59 default:
60 UNREACHABLE(op);
61 return false;
62 }
63}
64
65TOperator TypeToConstructorOperator(const TType &type)
66{
67 switch(type.getBasicType())
68 {
69 case EbtFloat:
70 if(type.isMatrix())
71 {
72 switch(type.getNominalSize())
73 {
74 case 2:
75 switch(type.getSecondarySize())
76 {
77 case 2:
78 return EOpConstructMat2;
79 case 3:
80 return EOpConstructMat2x3;
81 case 4:
82 return EOpConstructMat2x4;
83 default:
84 break;
85 }
86 break;
87
88 case 3:
89 switch(type.getSecondarySize())
90 {
91 case 2:
92 return EOpConstructMat3x2;
93 case 3:
94 return EOpConstructMat3;
95 case 4:
96 return EOpConstructMat3x4;
97 default:
98 break;
99 }
100 break;
101
102 case 4:
103 switch(type.getSecondarySize())
104 {
105 case 2:
106 return EOpConstructMat4x2;
107 case 3:
108 return EOpConstructMat4x3;
109 case 4:
110 return EOpConstructMat4;
111 default:
112 break;
113 }
114 break;
115 }
116 }
117 else
118 {
119 switch(type.getNominalSize())
120 {
121 case 1:
122 return EOpConstructFloat;
123 case 2:
124 return EOpConstructVec2;
125 case 3:
126 return EOpConstructVec3;
127 case 4:
128 return EOpConstructVec4;
129 default:
130 break;
131 }
132 }
133 break;
134
135 case EbtInt:
136 switch(type.getNominalSize())
137 {
138 case 1:
139 return EOpConstructInt;
140 case 2:
141 return EOpConstructIVec2;
142 case 3:
143 return EOpConstructIVec3;
144 case 4:
145 return EOpConstructIVec4;
146 default:
147 break;
148 }
149 break;
150
151 case EbtUInt:
152 switch(type.getNominalSize())
153 {
154 case 1:
155 return EOpConstructUInt;
156 case 2:
157 return EOpConstructUVec2;
158 case 3:
159 return EOpConstructUVec3;
160 case 4:
161 return EOpConstructUVec4;
162 default:
163 break;
164 }
165 break;
166
167 case EbtBool:
168 switch(type.getNominalSize())
169 {
170 case 1:
171 return EOpConstructBool;
172 case 2:
173 return EOpConstructBVec2;
174 case 3:
175 return EOpConstructBVec3;
176 case 4:
177 return EOpConstructBVec4;
178 default:
179 break;
180 }
181 break;
182
183 case EbtStruct:
184 return EOpConstructStruct;
185
186 default:
187 break;
188 }
189
190 return EOpNull;
191}
192
193const char* getOperatorString(TOperator op) {
194 switch (op) {
195 case EOpInitialize: return "=";
196 case EOpAssign: return "=";
197 case EOpAddAssign: return "+=";
198 case EOpSubAssign: return "-=";
199 case EOpDivAssign: return "/=";
200 case EOpIModAssign: return "%=";
201 case EOpBitShiftLeftAssign: return "<<=";
202 case EOpBitShiftRightAssign: return ">>=";
203 case EOpBitwiseAndAssign: return "&=";
204 case EOpBitwiseXorAssign: return "^=";
205 case EOpBitwiseOrAssign: return "|=";
206
207 // Fall-through.
208 case EOpMulAssign:
209 case EOpVectorTimesMatrixAssign:
210 case EOpVectorTimesScalarAssign:
211 case EOpMatrixTimesScalarAssign:
212 case EOpMatrixTimesMatrixAssign: return "*=";
213
214 // Fall-through.
215 case EOpIndexDirect:
216 case EOpIndexIndirect: return "[]";
217
218 case EOpIndexDirectStruct: return ".";
219 case EOpVectorSwizzle: return ".";
220 case EOpAdd: return "+";
221 case EOpSub: return "-";
222 case EOpMul: return "*";
223 case EOpDiv: return "/";
224 case EOpMod: UNIMPLEMENTED(); break;
225 case EOpEqual: return "==";
226 case EOpNotEqual: return "!=";
227 case EOpLessThan: return "<";
228 case EOpGreaterThan: return ">";
229 case EOpLessThanEqual: return "<=";
230 case EOpGreaterThanEqual: return ">=";
231
232 // Fall-through.
233 case EOpVectorTimesScalar:
234 case EOpVectorTimesMatrix:
235 case EOpMatrixTimesVector:
236 case EOpMatrixTimesScalar:
237 case EOpMatrixTimesMatrix: return "*";
238
239 case EOpLogicalOr: return "||";
240 case EOpLogicalXor: return "^^";
241 case EOpLogicalAnd: return "&&";
242 case EOpIMod: return "%";
243 case EOpBitShiftLeft: return "<<";
244 case EOpBitShiftRight: return ">>";
245 case EOpBitwiseAnd: return "&";
246 case EOpBitwiseXor: return "^";
247 case EOpBitwiseOr: return "|";
248 case EOpNegative: return "-";
249 case EOpVectorLogicalNot: return "not";
250 case EOpLogicalNot: return "!";
251 case EOpBitwiseNot: return "~";
252 case EOpPostIncrement: return "++";
253 case EOpPostDecrement: return "--";
254 case EOpPreIncrement: return "++";
255 case EOpPreDecrement: return "--";
256
257 case EOpRadians: return "radians";
258 case EOpDegrees: return "degrees";
259 case EOpSin: return "sin";
260 case EOpCos: return "cos";
261 case EOpTan: return "tan";
262 case EOpAsin: return "asin";
263 case EOpAcos: return "acos";
264 case EOpAtan: return "atan";
265 case EOpSinh: return "sinh";
266 case EOpCosh: return "cosh";
267 case EOpTanh: return "tanh";
268 case EOpAsinh: return "asinh";
269 case EOpAcosh: return "acosh";
270 case EOpAtanh: return "atanh";
271 case EOpExp: return "exp";
272 case EOpLog: return "log";
273 case EOpExp2: return "exp2";
274 case EOpLog2: return "log2";
275 case EOpSqrt: return "sqrt";
276 case EOpInverseSqrt: return "inversesqrt";
277 case EOpAbs: return "abs";
278 case EOpSign: return "sign";
279 case EOpFloor: return "floor";
280 case EOpTrunc: return "trunc";
281 case EOpRound: return "round";
282 case EOpRoundEven: return "roundEven";
283 case EOpCeil: return "ceil";
284 case EOpFract: return "fract";
285 case EOpLength: return "length";
286 case EOpNormalize: return "normalize";
287 case EOpDFdx: return "dFdx";
288 case EOpDFdy: return "dFdy";
289 case EOpFwidth: return "fwidth";
290 case EOpAny: return "any";
291 case EOpAll: return "all";
292 case EOpIsNan: return "isnan";
293 case EOpIsInf: return "isinf";
294 case EOpOuterProduct: return "outerProduct";
295 case EOpTranspose: return "transpose";
296 case EOpDeterminant: return "determinant";
297 case EOpInverse: return "inverse";
298
299 default: break;
300 }
301 return "";
302}
303
304////////////////////////////////////////////////////////////////////////////
305//
306// First set of functions are to help build the intermediate representation.
307// These functions are not member functions of the nodes.
308// They are called from parser productions.
309//
310/////////////////////////////////////////////////////////////////////////////
311
312//
313// Add a terminal node for an identifier in an expression.
314//
315// Returns the added node.
316//
317TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc &line)
318{
319 TIntermSymbol* node = new TIntermSymbol(id, name, type);
320 node->setLine(line);
321
322 return node;
323}
324
325//
326// Connect two nodes with a new parent that does a binary operation on the nodes.
327//
328// Returns the added node.
329//
330TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
331{
332 bool isBitShift = false;
333 switch (op) {
334 case EOpEqual:
335 case EOpNotEqual:
336 break;
337 case EOpLessThan:
338 case EOpGreaterThan:
339 case EOpLessThanEqual:
340 case EOpGreaterThanEqual:
341 if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
342 return 0;
343 }
344 break;
345 case EOpLogicalOr:
346 case EOpLogicalXor:
347 case EOpLogicalAnd:
348 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
349 return 0;
350 }
351 break;
352 case EOpBitwiseOr:
353 case EOpBitwiseXor:
354 case EOpBitwiseAnd:
355 if (!IsInteger(left->getBasicType()) || left->isMatrix() || left->isArray()) {
356 return 0;
357 }
358 break;
359 case EOpAdd:
360 case EOpSub:
361 case EOpDiv:
362 case EOpMul:
363 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) {
364 return 0;
365 }
366 break;
367 case EOpIMod:
368 // Note that this is only for the % operator, not for mod()
369 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat) {
370 return 0;
371 }
372 break;
373 case EOpBitShiftLeft:
374 case EOpBitShiftRight:
375 case EOpBitShiftLeftAssign:
376 case EOpBitShiftRightAssign:
377 // Unsigned can be bit-shifted by signed and vice versa, but we need to
378 // check that the basic type is an integer type.
379 isBitShift = true;
380 if(!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
381 {
382 return 0;
383 }
384 break;
385 default: break;
386 }
387
388 if(!isBitShift && left->getBasicType() != right->getBasicType())
389 {
390 return 0;
391 }
392
393 //
394 // Need a new node holding things together then. Make
395 // one and promote it to the right type.
396 //
397 TIntermBinary* node = new TIntermBinary(op);
398 node->setLine(line);
399
400 node->setLeft(left);
401 node->setRight(right);
402 if (!node->promote(infoSink))
403 {
404 delete node;
405 return 0;
406 }
407
408 //
409 // See if we can fold constants.
410 //
411 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
412 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
413 if (leftTempConstant && rightTempConstant) {
414 TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
415
416 if (typedReturnNode)
417 return typedReturnNode;
418 }
419
420 return node;
421}
422
423//
424// Connect two nodes through an assignment.
425//
426// Returns the added node.
427//
428TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
429{
430 if (left->getType().getStruct() || right->getType().getStruct())
431 {
432 if (left->getType() != right->getType())
433 {
434 return 0;
435 }
436 }
437
438 TIntermBinary* node = new TIntermBinary(op);
439 node->setLine(line);
440
441 node->setLeft(left);
442 node->setRight(right);
443 if (! node->promote(infoSink))
444 return 0;
445
446 return node;
447}
448
449//
450// Connect two nodes through an index operator, where the left node is the base
451// of an array or struct, and the right node is a direct or indirect offset.
452//
453// Returns the added node.
454// The caller should set the type of the returned node.
455//
456TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc &line)
457{
458 TIntermBinary* node = new TIntermBinary(op);
459 node->setLine(line);
460 node->setLeft(base);
461 node->setRight(index);
462
463 // caller should set the type
464
465 return node;
466}
467
468//
469// Add one node as the parent of another that it operates on.
470//
471// Returns the added node.
472//
473TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, const TSourceLoc &line, const TType *funcReturnType)
474{
475 if (child == 0) {
476 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
477 return 0;
478 }
479
480 switch (op) {
481 case EOpBitwiseNot:
482 if (!IsInteger(child->getType().getBasicType()) || child->getType().isMatrix() || child->getType().isArray()) {
483 return 0;
484 }
485 break;
486
487 case EOpLogicalNot:
488 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
489 return 0;
490 }
491 break;
492
493 case EOpPostIncrement:
494 case EOpPreIncrement:
495 case EOpPostDecrement:
496 case EOpPreDecrement:
497 case EOpNegative:
498 if (!child->getType().isScalar() && !child->getType().isVector() && !child->getType().isMatrix())
499 return 0;
500 default: break;
501 }
502
503 TIntermConstantUnion *childTempConstant = 0;
504 if (child->getAsConstantUnion())
505 childTempConstant = child->getAsConstantUnion();
506
507 //
508 // Make a new node for the operator.
509 //
510 TIntermUnary *node = new TIntermUnary(op);
511 node->setLine(line);
512 node->setOperand(child);
513
514 if (! node->promote(infoSink, funcReturnType))
515 return 0;
516
517 if (childTempConstant) {
518 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
519
520 if (newChild)
521 return newChild;
522 }
523
524 return node;
525}
526
527//
528// This is the safe way to change the operator on an aggregate, as it
529// does lots of error checking and fixing. Especially for establishing
530// a function call's operation on its set of parameters. Sequences
531// of instructions are also aggregates, but they just directly set
532// their operator to EOpSequence.
533//
534// Returns an aggregate node, which could be the one passed in if
535// it was already an aggregate but no operator was set.
536//
537TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc &line)
538{
539 TIntermAggregate* aggNode;
540
541 //
542 // Make sure we have an aggregate. If not turn it into one.
543 //
544 if (node) {
545 aggNode = node->getAsAggregate();
546 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
547 //
548 // Make an aggregate containing this node.
549 //
550 aggNode = new TIntermAggregate();
551 aggNode->getSequence().push_back(node);
552 }
553 } else
554 aggNode = new TIntermAggregate();
555
556 //
557 // Set the operator.
558 //
559 aggNode->setOp(op);
560
561 return aggNode;
562}
563
564//
565// Safe way to combine two nodes into an aggregate. Works with null pointers,
566// a node that's not a aggregate yet, etc.
567//
568// Returns the resulting aggregate, unless 0 was passed in for
569// both existing nodes.
570//
571TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc &line)
572{
573 if (left == 0 && right == 0)
574 return 0;
575
576 TIntermAggregate* aggNode = 0;
577 if (left)
578 aggNode = left->getAsAggregate();
579 if (!aggNode || aggNode->getOp() != EOpNull) {
580 aggNode = new TIntermAggregate;
581 if (left)
582 aggNode->getSequence().push_back(left);
583 }
584
585 if (right)
586 aggNode->getSequence().push_back(right);
587
588 aggNode->setLine(line);
589
590 return aggNode;
591}
592
593//
594// Turn an existing node into an aggregate.
595//
596// Returns an aggregate, unless 0 was passed in for the existing node.
597//
598TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc &line)
599{
600 if (node == 0)
601 return 0;
602
603 TIntermAggregate* aggNode = new TIntermAggregate;
604 aggNode->getSequence().push_back(node);
605
606 aggNode->setLine(line);
607
608 return aggNode;
609}
610
611//
612// For "if" test nodes. There are three children; a condition,
613// a true path, and a false path. The two paths are in the
614// nodePair.
615//
616// Returns the selection node created.
617//
618TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc &line)
619{
620 //
621 // For compile time constant selections, prune the code and
622 // test now.
623 //
624
625 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
626 if (cond->getAsConstantUnion()->getBConst(0) == true)
627 return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : nullptr;
628 else
629 return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : nullptr;
630 }
631
632 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
633 node->setLine(line);
634
635 return node;
636}
637
638
639TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
640{
641 if (left->getType().getQualifier() == EvqConstExpr && right->getType().getQualifier() == EvqConstExpr) {
642 return right;
643 } else {
644 TIntermTyped *commaAggregate = growAggregate(left, right, line);
645 commaAggregate->getAsAggregate()->setOp(EOpComma);
646 commaAggregate->setType(right->getType());
647 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
648 return commaAggregate;
649 }
650}
651
652//
653// For "?:" test nodes. There are three children; a condition,
654// a true path, and a false path. The two paths are specified
655// as separate parameters.
656//
657// Returns the selection node created, or 0 if one could not be.
658//
659TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc &line)
660{
661 if (trueBlock->getType() != falseBlock->getType())
662 {
663 return 0;
664 }
665
666 //
667 // See if all the operands are constant, then fold it otherwise not.
668 //
669
670 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
671 if (cond->getAsConstantUnion()->getBConst(0))
672 return trueBlock;
673 else
674 return falseBlock;
675 }
676
677 //
678 // Make a selection node.
679 //
680 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
681 node->getTypePointer()->setQualifier(EvqTemporary);
682 node->setLine(line);
683
684 return node;
685}
686
687TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
688{
689 TIntermSwitch *node = new TIntermSwitch(init, statementList);
690 node->setLine(line);
691
692 return node;
693}
694
695TIntermCase *TIntermediate::addCase(TIntermTyped *condition, const TSourceLoc &line)
696{
697 TIntermCase *node = new TIntermCase(condition);
698 node->setLine(line);
699
700 return node;
701}
702
703//
704// Constant terminal nodes. Has a union that contains bool, float or int constants
705//
706// Returns the constant union node created.
707//
708
709TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc &line)
710{
711 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
712 node->setLine(line);
713
714 return node;
715}
716
717TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc &line)
718{
719
720 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
721
722 node->setLine(line);
723 TIntermConstantUnion* constIntNode;
724 TIntermSequence &sequenceVector = node->getSequence();
725 ConstantUnion* unionArray;
726
727 for (int i = 0; i < fields.num; i++) {
728 unionArray = new ConstantUnion[1];
729 unionArray->setIConst(fields.offsets[i]);
730 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), line);
731 sequenceVector.push_back(constIntNode);
732 }
733
734 return node;
735}
736
737//
738// Create loop nodes.
739//
740TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc &line)
741{
742 TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
743 node->setLine(line);
744
745 return node;
746}
747
748//
749// Add branches.
750//
751TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc &line)
752{
753 return addBranch(branchOp, 0, line);
754}
755
756TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc &line)
757{
758 TIntermBranch* node = new TIntermBranch(branchOp, expression);
759 node->setLine(line);
760
761 return node;
762}
763
764//
765// This is to be executed once the final root is put on top by the parsing
766// process.
767//
768bool TIntermediate::postProcess(TIntermNode* root)
769{
770 if (root == 0)
771 return true;
772
773 //
774 // First, finish off the top level sequence, if any
775 //
776 TIntermAggregate* aggRoot = root->getAsAggregate();
777 if (aggRoot && aggRoot->getOp() == EOpNull)
778 aggRoot->setOp(EOpSequence);
779
780 return true;
781}
782
783////////////////////////////////////////////////////////////////
784//
785// Member functions of the nodes used for building the tree.
786//
787////////////////////////////////////////////////////////////////
788
789// static
790TIntermTyped *TIntermTyped::CreateIndexNode(int index)
791{
792 ConstantUnion *u = new ConstantUnion[1];
793 u[0].setIConst(index);
794
795 TType type(EbtInt, EbpUndefined, EvqConstExpr, 1);
796 TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
797 return node;
798}
799
800//
801// Say whether or not an operation node changes the value of a variable.
802//
803// Returns true if state is modified.
804//
805bool TIntermOperator::modifiesState() const
806{
807 switch (op) {
808 case EOpPostIncrement:
809 case EOpPostDecrement:
810 case EOpPreIncrement:
811 case EOpPreDecrement:
812 case EOpAssign:
813 case EOpAddAssign:
814 case EOpSubAssign:
815 case EOpMulAssign:
816 case EOpVectorTimesMatrixAssign:
817 case EOpVectorTimesScalarAssign:
818 case EOpMatrixTimesScalarAssign:
819 case EOpMatrixTimesMatrixAssign:
820 case EOpDivAssign:
821 case EOpIModAssign:
822 case EOpBitShiftLeftAssign:
823 case EOpBitShiftRightAssign:
824 case EOpBitwiseAndAssign:
825 case EOpBitwiseXorAssign:
826 case EOpBitwiseOrAssign:
827 return true;
828 default:
829 return false;
830 }
831}
832
833//
834// returns true if the operator is for one of the constructors
835//
836bool TIntermOperator::isConstructor() const
837{
838 switch (op) {
839 case EOpConstructVec2:
840 case EOpConstructVec3:
841 case EOpConstructVec4:
842 case EOpConstructMat2:
843 case EOpConstructMat2x3:
844 case EOpConstructMat2x4:
845 case EOpConstructMat3x2:
846 case EOpConstructMat3:
847 case EOpConstructMat3x4:
848 case EOpConstructMat4x2:
849 case EOpConstructMat4x3:
850 case EOpConstructMat4:
851 case EOpConstructFloat:
852 case EOpConstructIVec2:
853 case EOpConstructIVec3:
854 case EOpConstructIVec4:
855 case EOpConstructInt:
856 case EOpConstructUVec2:
857 case EOpConstructUVec3:
858 case EOpConstructUVec4:
859 case EOpConstructUInt:
860 case EOpConstructBVec2:
861 case EOpConstructBVec3:
862 case EOpConstructBVec4:
863 case EOpConstructBool:
864 case EOpConstructStruct:
865 return true;
866 default:
867 return false;
868 }
869}
870
871//
872// Make sure the type of a unary operator is appropriate for its
873// combination of operation and operand type.
874//
875// Returns false in nothing makes sense.
876//
877bool TIntermUnary::promote(TInfoSink&, const TType *funcReturnType)
878{
879 setType(funcReturnType ? *funcReturnType : operand->getType());
880
881 // Unary operations result in temporary variables unless const.
882 if(type.getQualifier() != EvqConstExpr)
883 {
884 type.setQualifier(EvqTemporary);
885 }
886
887 switch (op) {
888 case EOpLogicalNot:
889 if (operand->getBasicType() != EbtBool)
890 return false;
891 break;
892 case EOpBitwiseNot:
893 if (!IsInteger(operand->getBasicType()))
894 return false;
895 break;
896 case EOpNegative:
897 case EOpPostIncrement:
898 case EOpPostDecrement:
899 case EOpPreIncrement:
900 case EOpPreDecrement:
901 if (operand->getBasicType() == EbtBool)
902 return false;
903 break;
904
905 // operators for built-ins are already type checked against their prototype
906 case EOpAny:
907 case EOpAll:
908 case EOpVectorLogicalNot:
909 case EOpAbs:
910 case EOpSign:
911 case EOpIsNan:
912 case EOpIsInf:
913 case EOpFloatBitsToInt:
914 case EOpFloatBitsToUint:
915 case EOpIntBitsToFloat:
916 case EOpUintBitsToFloat:
917 case EOpPackSnorm2x16:
918 case EOpPackUnorm2x16:
919 case EOpPackHalf2x16:
920 case EOpUnpackSnorm2x16:
921 case EOpUnpackUnorm2x16:
922 case EOpUnpackHalf2x16:
923 return true;
924
925 default:
926 if (operand->getBasicType() != EbtFloat)
927 return false;
928 }
929
930 return true;
931}
932
933//
934// Establishes the type of the resultant operation, as well as
935// makes the operator the correct one for the operands.
936//
937// Returns false if operator can't work on operands.
938//
939bool TIntermBinary::promote(TInfoSink& infoSink)
940{
941 ASSERT(left->isArray() == right->isArray());
942
943 // GLSL ES 2.0 does not support implicit type casting.
944 // So the basic type should always match.
945 // GLSL ES 3.0 supports integer shift operands of different signedness.
946 if(op != EOpBitShiftLeft &&
947 op != EOpBitShiftRight &&
948 op != EOpBitShiftLeftAssign &&
949 op != EOpBitShiftRightAssign &&
950 left->getBasicType() != right->getBasicType())
951 {
952 return false;
953 }
954
955 //
956 // Base assumption: just make the type the same as the left
957 // operand. Then only deviations from this need be coded.
958 //
959 setType(left->getType());
960
961 // The result gets promoted to the highest precision.
962 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
963 getTypePointer()->setPrecision(higherPrecision);
964
965 // Binary operations results in temporary variables unless both
966 // operands are const.
967 if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) {
968 getTypePointer()->setQualifier(EvqTemporary);
969 }
970
971 int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
972
973 //
974 // All scalars. Code after this test assumes this case is removed!
975 //
976 if (primarySize == 1) {
977 switch (op) {
978 //
979 // Promote to conditional
980 //
981 case EOpEqual:
982 case EOpNotEqual:
983 case EOpLessThan:
984 case EOpGreaterThan:
985 case EOpLessThanEqual:
986 case EOpGreaterThanEqual:
987 setType(TType(EbtBool, EbpUndefined));
988 break;
989
990 //
991 // And and Or operate on conditionals
992 //
993 case EOpLogicalAnd:
994 case EOpLogicalOr:
995 case EOpLogicalXor:
996 // Both operands must be of type bool.
997 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
998 return false;
999 setType(TType(EbtBool, EbpUndefined));
1000 break;
1001
1002 default:
1003 break;
1004 }
1005 return true;
1006 }
1007
1008 // If we reach here, at least one of the operands is vector or matrix.
1009 // The other operand could be a scalar, vector, or matrix.
1010 // Can these two operands be combined?
1011 //
1012 TBasicType basicType = left->getBasicType();
1013 switch (op) {
1014 case EOpMul:
1015 if (!left->isMatrix() && right->isMatrix()) {
1016 if (left->isVector())
1017 {
1018 op = EOpVectorTimesMatrix;
1019 setType(TType(basicType, higherPrecision, EvqTemporary,
1020 static_cast<unsigned char>(right->getNominalSize()), 1));
1021 }
1022 else {
1023 op = EOpMatrixTimesScalar;
1024 setType(TType(basicType, higherPrecision, EvqTemporary,
1025 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize())));
1026 }
1027 } else if (left->isMatrix() && !right->isMatrix()) {
1028 if (right->isVector()) {
1029 op = EOpMatrixTimesVector;
1030 setType(TType(basicType, higherPrecision, EvqTemporary,
1031 static_cast<unsigned char>(left->getSecondarySize()), 1));
1032 } else {
1033 op = EOpMatrixTimesScalar;
1034 }
1035 } else if (left->isMatrix() && right->isMatrix()) {
1036 op = EOpMatrixTimesMatrix;
1037 setType(TType(basicType, higherPrecision, EvqTemporary,
1038 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
1039 } else if (!left->isMatrix() && !right->isMatrix()) {
1040 if (left->isVector() && right->isVector()) {
1041 // leave as component product
1042 } else if (left->isVector() || right->isVector()) {
1043 op = EOpVectorTimesScalar;
1044 setType(TType(basicType, higherPrecision, EvqTemporary,
1045 static_cast<unsigned char>(primarySize), 1));
1046 }
1047 } else {
1048 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
1049 return false;
1050 }
1051
1052 if(!ValidateMultiplication(op, left->getType(), right->getType()))
1053 {
1054 return false;
1055 }
1056 break;
1057 case EOpMulAssign:
1058 if (!left->isMatrix() && right->isMatrix()) {
1059 if (left->isVector())
1060 op = EOpVectorTimesMatrixAssign;
1061 else {
1062 return false;
1063 }
1064 } else if (left->isMatrix() && !right->isMatrix()) {
1065 if (right->isVector()) {
1066 return false;
1067 } else {
1068 op = EOpMatrixTimesScalarAssign;
1069 }
1070 } else if (left->isMatrix() && right->isMatrix()) {
1071 op = EOpMatrixTimesMatrixAssign;
1072 setType(TType(basicType, higherPrecision, EvqTemporary,
1073 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
1074 } else if (!left->isMatrix() && !right->isMatrix()) {
1075 if (left->isVector() && right->isVector()) {
1076 // leave as component product
1077 } else if (left->isVector() || right->isVector()) {
1078 if (! left->isVector())
1079 return false;
1080 op = EOpVectorTimesScalarAssign;
1081 setType(TType(basicType, higherPrecision, EvqTemporary,
1082 static_cast<unsigned char>(left->getNominalSize()), 1));
1083 }
1084 } else {
1085 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
1086 return false;
1087 }
1088
1089 if(!ValidateMultiplication(op, left->getType(), right->getType()))
1090 {
1091 return false;
1092 }
1093 break;
1094
1095 case EOpAssign:
1096 case EOpInitialize:
1097 // No more additional checks are needed.
1098 if ((left->getNominalSize() != right->getNominalSize()) ||
1099 (left->getSecondarySize() != right->getSecondarySize()))
1100 return false;
1101 break;
1102 case EOpAdd:
1103 case EOpSub:
1104 case EOpDiv:
1105 case EOpIMod:
1106 case EOpBitShiftLeft:
1107 case EOpBitShiftRight:
1108 case EOpBitwiseAnd:
1109 case EOpBitwiseXor:
1110 case EOpBitwiseOr:
1111 case EOpAddAssign:
1112 case EOpSubAssign:
1113 case EOpDivAssign:
1114 case EOpIModAssign:
1115 case EOpBitShiftLeftAssign:
1116 case EOpBitShiftRightAssign:
1117 case EOpBitwiseAndAssign:
1118 case EOpBitwiseXorAssign:
1119 case EOpBitwiseOrAssign:
1120 if ((left->isMatrix() && right->isVector()) ||
1121 (left->isVector() && right->isMatrix()))
1122 return false;
1123
1124 // Are the sizes compatible?
1125 if(left->getNominalSize() != right->getNominalSize() ||
1126 left->getSecondarySize() != right->getSecondarySize())
1127 {
1128 // If the nominal sizes of operands do not match:
1129 // One of them must be a scalar.
1130 if(!left->isScalar() && !right->isScalar())
1131 return false;
1132
1133 // In the case of compound assignment other than multiply-assign,
1134 // the right side needs to be a scalar. Otherwise a vector/matrix
1135 // would be assigned to a scalar. A scalar can't be shifted by a
1136 // vector either.
1137 if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight))
1138 return false;
1139 }
1140
1141 {
1142 const int secondarySize = std::max(
1143 left->getSecondarySize(), right->getSecondarySize());
1144 setType(TType(basicType, higherPrecision, EvqTemporary,
1145 static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
1146 if(left->isArray())
1147 {
1148 ASSERT(left->getArraySize() == right->getArraySize());
1149 type.setArraySize(left->getArraySize());
1150 }
1151 }
1152 break;
1153
1154 case EOpEqual:
1155 case EOpNotEqual:
1156 case EOpLessThan:
1157 case EOpGreaterThan:
1158 case EOpLessThanEqual:
1159 case EOpGreaterThanEqual:
1160 if ((left->getNominalSize() != right->getNominalSize()) ||
1161 (left->getSecondarySize() != right->getSecondarySize()))
1162 return false;
1163 setType(TType(EbtBool, EbpUndefined));
1164 break;
1165
1166 case EOpOuterProduct:
1167 if(!left->isVector() || !right->isVector())
1168 return false;
1169 setType(TType(EbtFloat, right->getNominalSize(), left->getNominalSize()));
1170 break;
1171
1172 case EOpTranspose:
1173 if(!right->isMatrix())
1174 return false;
1175 setType(TType(EbtFloat, right->getSecondarySize(), right->getNominalSize()));
1176 break;
1177
1178 case EOpDeterminant:
1179 if(!right->isMatrix())
1180 return false;
1181 setType(TType(EbtFloat));
1182 break;
1183
1184 case EOpInverse:
1185 if(!right->isMatrix() || right->getNominalSize() != right->getSecondarySize())
1186 return false;
1187 setType(right->getType());
1188 break;
1189
1190 default:
1191 return false;
1192 }
1193
1194 return true;
1195}
1196
1197bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1198{
1199 const TFieldList& fields = leftNodeType.getStruct()->fields();
1200
1201 size_t structSize = fields.size();
1202 int index = 0;
1203
1204 for (size_t j = 0; j < structSize; j++) {
1205 size_t size = fields[j]->type()->getObjectSize();
1206 for(size_t i = 0; i < size; i++) {
1207 if (fields[j]->type()->getBasicType() == EbtStruct) {
1208 if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
1209 return false;
1210 } else {
1211 if (leftUnionArray[index] != rightUnionArray[index])
1212 return false;
1213 index++;
1214 }
1215
1216 }
1217 }
1218 return true;
1219}
1220
1221bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1222{
1223 if (leftNodeType.isArray()) {
1224 TType typeWithoutArrayness = leftNodeType;
1225 typeWithoutArrayness.clearArrayness();
1226
1227 int arraySize = leftNodeType.getArraySize();
1228
1229 for (int i = 0; i < arraySize; ++i) {
1230 size_t offset = typeWithoutArrayness.getObjectSize() * i;
1231 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1232 return false;
1233 }
1234 } else
1235 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
1236
1237 return true;
1238}
1239
1240float determinant2(float m00, float m01, float m10, float m11)
1241{
1242 return m00 * m11 - m01 * m10;
1243}
1244
1245float determinant3(float m00, float m01, float m02,
1246 float m10, float m11, float m12,
1247 float m20, float m21, float m22)
1248{
1249 return m00 * determinant2(m11, m12, m21, m22) -
1250 m10 * determinant2(m01, m02, m21, m22) +
1251 m20 * determinant2(m01, m02, m11, m12);
1252}
1253
1254float determinant4(float m00, float m01, float m02, float m03,
1255 float m10, float m11, float m12, float m13,
1256 float m20, float m21, float m22, float m23,
1257 float m30, float m31, float m32, float m33)
1258{
1259 return m00 * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33) -
1260 m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) +
1261 m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) -
1262 m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
1263}
1264
1265float ComputeDeterminant(int size, ConstantUnion* unionArray)
1266{
1267 switch(size)
1268 {
1269 case 2:
1270 return determinant2(unionArray[0].getFConst(),
1271 unionArray[1].getFConst(),
1272 unionArray[2].getFConst(),
1273 unionArray[3].getFConst());
1274 case 3:
1275 return determinant3(unionArray[0].getFConst(),
1276 unionArray[1].getFConst(),
1277 unionArray[2].getFConst(),
1278 unionArray[3].getFConst(),
1279 unionArray[4].getFConst(),
1280 unionArray[5].getFConst(),
1281 unionArray[6].getFConst(),
1282 unionArray[7].getFConst(),
1283 unionArray[8].getFConst());
1284 case 4:
1285 return determinant4(unionArray[0].getFConst(),
1286 unionArray[1].getFConst(),
1287 unionArray[2].getFConst(),
1288 unionArray[3].getFConst(),
1289 unionArray[4].getFConst(),
1290 unionArray[5].getFConst(),
1291 unionArray[6].getFConst(),
1292 unionArray[7].getFConst(),
1293 unionArray[8].getFConst(),
1294 unionArray[9].getFConst(),
1295 unionArray[10].getFConst(),
1296 unionArray[11].getFConst(),
1297 unionArray[12].getFConst(),
1298 unionArray[13].getFConst(),
1299 unionArray[14].getFConst(),
1300 unionArray[15].getFConst());
1301 default:
1302 UNREACHABLE(size);
1303 return 0.0f;
1304 }
1305}
1306
1307ConstantUnion* CreateInverse(TIntermConstantUnion* node, ConstantUnion* unionArray)
1308{
1309 ConstantUnion* tempConstArray = 0;
1310 int size = node->getNominalSize();
1311 float determinant = ComputeDeterminant(size, unionArray);
1312 if(determinant != 0.0f)
1313 {
1314 float invDet = 1.0f / determinant;
1315 tempConstArray = new ConstantUnion[size*size];
1316 switch(size)
1317 {
1318 case 2:
1319 {
1320 float m00 = unionArray[0].getFConst(); // Matrix is:
1321 float m01 = unionArray[1].getFConst(); // (m00, m01)
1322 float m10 = unionArray[2].getFConst(); // (m10, m11)
1323 float m11 = unionArray[3].getFConst();
1324 tempConstArray[0].setFConst( invDet * m11);
1325 tempConstArray[1].setFConst(-invDet * m01);
1326 tempConstArray[2].setFConst(-invDet * m10);
1327 tempConstArray[3].setFConst( invDet * m00);
1328 }
1329 break;
1330 case 3:
1331 {
1332 float m00 = unionArray[0].getFConst(); // Matrix is:
1333 float m01 = unionArray[1].getFConst(); // (m00, m01, m02)
1334 float m02 = unionArray[2].getFConst(); // (m10, m11, m12)
1335 float m10 = unionArray[3].getFConst(); // (m20, m21, m22)
1336 float m11 = unionArray[4].getFConst();
1337 float m12 = unionArray[5].getFConst();
1338 float m20 = unionArray[6].getFConst();
1339 float m21 = unionArray[7].getFConst();
1340 float m22 = unionArray[8].getFConst();
1341 tempConstArray[0].setFConst(invDet * determinant2(m11, m12, m21, m22)); // m00 = invDet * (m11 * m22 - m12 * m21)
1342 tempConstArray[1].setFConst(invDet * determinant2(m12, m10, m22, m20)); // m01 = -invDet * (m10 * m22 - m12 * m20)
1343 tempConstArray[2].setFConst(invDet * determinant2(m10, m11, m20, m21)); // m02 = invDet * (m10 * m21 - m11 * m20)
1344 tempConstArray[3].setFConst(invDet * determinant2(m21, m22, m01, m02)); // m10 = -invDet * (m01 * m22 - m02 * m21)
1345 tempConstArray[4].setFConst(invDet * determinant2(m00, m02, m20, m22)); // m11 = invDet * (m00 * m22 - m02 * m20)
1346 tempConstArray[5].setFConst(invDet * determinant2(m20, m21, m00, m01)); // m12 = -invDet * (m00 * m21 - m01 * m20)
1347 tempConstArray[6].setFConst(invDet * determinant2(m01, m02, m11, m12)); // m20 = invDet * (m01 * m12 - m02 * m11)
1348 tempConstArray[7].setFConst(invDet * determinant2(m10, m12, m00, m02)); // m21 = -invDet * (m00 * m12 - m02 * m10)
1349 tempConstArray[8].setFConst(invDet * determinant2(m00, m01, m10, m11)); // m22 = invDet * (m00 * m11 - m01 * m10)
1350 }
1351 break;
1352 case 4:
1353 {
1354 float m00 = unionArray[0].getFConst(); // Matrix is:
1355 float m01 = unionArray[1].getFConst(); // (m00, m01, m02, m03)
1356 float m02 = unionArray[2].getFConst(); // (m10, m11, m12, m13)
1357 float m03 = unionArray[3].getFConst(); // (m20, m21, m22, m23)
1358 float m10 = unionArray[4].getFConst(); // (m30, m31, m32, m33)
1359 float m11 = unionArray[5].getFConst();
1360 float m12 = unionArray[6].getFConst();
1361 float m13 = unionArray[7].getFConst();
1362 float m20 = unionArray[8].getFConst();
1363 float m21 = unionArray[9].getFConst();
1364 float m22 = unionArray[10].getFConst();
1365 float m23 = unionArray[11].getFConst();
1366 float m30 = unionArray[12].getFConst();
1367 float m31 = unionArray[13].getFConst();
1368 float m32 = unionArray[14].getFConst();
1369 float m33 = unionArray[15].getFConst();
1370 tempConstArray[ 0].setFConst( invDet * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33)); // m00
1371 tempConstArray[ 1].setFConst(-invDet * determinant3(m10, m12, m13, m20, m22, m23, m30, m32, m33)); // m01
1372 tempConstArray[ 2].setFConst( invDet * determinant3(m10, m11, m13, m20, m21, m23, m30, m31, m33)); // m02
1373 tempConstArray[ 3].setFConst(-invDet * determinant3(m10, m11, m12, m20, m21, m22, m30, m31, m32)); // m03
1374 tempConstArray[ 4].setFConst( invDet * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33)); // m10
1375 tempConstArray[ 5].setFConst(-invDet * determinant3(m00, m02, m03, m20, m22, m23, m30, m32, m33)); // m11
1376 tempConstArray[ 6].setFConst( invDet * determinant3(m00, m01, m03, m20, m21, m23, m30, m31, m33)); // m12
1377 tempConstArray[ 7].setFConst(-invDet * determinant3(m00, m01, m02, m20, m21, m22, m30, m31, m32)); // m13
1378 tempConstArray[ 8].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33)); // m20
1379 tempConstArray[ 9].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m30, m32, m33)); // m21
1380 tempConstArray[10].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m30, m31, m33)); // m22
1381 tempConstArray[11].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m30, m31, m32)); // m23
1382 tempConstArray[12].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23)); // m30
1383 tempConstArray[13].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m20, m22, m23)); // m31
1384 tempConstArray[14].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m20, m21, m23)); // m32
1385 tempConstArray[15].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m20, m21, m22)); // m33
1386 }
1387 break;
1388 default:
1389 UNREACHABLE(size);
1390 }
1391 }
1392 return tempConstArray;
1393}
1394
1395//
1396// The fold functions see if an operation on a constant can be done in place,
1397// without generating run-time code.
1398//
1399// Returns the node to keep using, which may or may not be the node passed in.
1400//
1401
1402TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1403{
1404 ConstantUnion *unionArray = getUnionArrayPointer();
1405 size_t objectSize = getType().getObjectSize();
1406
1407 if (constantNode) { // binary operations
1408 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
1409 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
1410 TType returnType = getType();
1411
1412 // for a case like float f = 1.2 + vec4(2,3,4,5);
1413 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
1414 rightUnionArray = new ConstantUnion[objectSize];
1415 for (size_t i = 0; i < objectSize; ++i)
1416 rightUnionArray[i] = *node->getUnionArrayPointer();
1417 returnType = getType();
1418 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1419 // for a case like float f = vec4(2,3,4,5) + 1.2;
1420 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
1421 for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
1422 unionArray[i] = *getUnionArrayPointer();
1423 returnType = node->getType();
1424 objectSize = constantNode->getType().getObjectSize();
1425 }
1426
1427 ConstantUnion* tempConstArray = 0;
1428 TIntermConstantUnion *tempNode;
1429
1430 switch(op) {
1431 case EOpAdd:
1432 tempConstArray = new ConstantUnion[objectSize];
1433 {// support MSVC++6.0
1434 for (size_t i = 0; i < objectSize; i++)
1435 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1436 }
1437 break;
1438 case EOpSub:
1439 tempConstArray = new ConstantUnion[objectSize];
1440 {// support MSVC++6.0
1441 for (size_t i = 0; i < objectSize; i++)
1442 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1443 }
1444 break;
1445
1446 case EOpMul:
1447 case EOpVectorTimesScalar:
1448 case EOpMatrixTimesScalar:
1449 tempConstArray = new ConstantUnion[objectSize];
1450 {// support MSVC++6.0
1451 for (size_t i = 0; i < objectSize; i++)
1452 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1453 }
1454 break;
1455 case EOpMatrixTimesMatrix:
1456 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1457 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1458 return 0;
1459 }
1460 {// support MSVC++6.0
1461 int leftNumCols = getNominalSize();
1462 int leftNumRows = getSecondarySize();
1463 int rightNumCols = node->getNominalSize();
1464 int rightNumRows = node->getSecondarySize();
1465 if(leftNumCols != rightNumRows) {
1466 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1467 return 0;
1468 }
1469 int tempNumCols = rightNumCols;
1470 int tempNumRows = leftNumRows;
1471 int tempNumAdds = leftNumCols;
1472 tempConstArray = new ConstantUnion[tempNumCols*tempNumRows];
1473 for (int row = 0; row < tempNumRows; row++) {
1474 for (int column = 0; column < tempNumCols; column++) {
1475 tempConstArray[tempNumRows * column + row].setFConst(0.0f);
1476 for (int i = 0; i < tempNumAdds; i++) {
1477 tempConstArray[tempNumRows * column + row].setFConst(tempConstArray[tempNumRows * column + row].getFConst() + unionArray[i * leftNumRows + row].getFConst() * (rightUnionArray[column * rightNumRows + i].getFConst()));
1478 }
1479 }
1480 }
1481 // update return type for matrix product
1482 returnType.setNominalSize(static_cast<unsigned char>(tempNumCols));
1483 returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows));
1484 }
1485 break;
1486
1487 case EOpOuterProduct:
1488 {
1489 int leftSize = getNominalSize();
1490 int rightSize = node->getNominalSize();
1491 tempConstArray = new ConstantUnion[leftSize*rightSize];
1492 for(int row = 0; row < leftSize; row++) {
1493 for(int column = 0; column < rightSize; column++) {
1494 tempConstArray[leftSize * column + row].setFConst(unionArray[row].getFConst() * rightUnionArray[column].getFConst());
1495 }
1496 }
1497 // update return type for outer product
1498 returnType.setNominalSize(static_cast<unsigned char>(rightSize));
1499 returnType.setSecondarySize(static_cast<unsigned char>(leftSize));
1500 }
1501 break;
1502
1503 case EOpTranspose:
1504 {
1505 int rightCol = node->getNominalSize();
1506 int rightRow = node->getSecondarySize();
1507 tempConstArray = new ConstantUnion[rightCol*rightRow];
1508 for(int row = 0; row < rightRow; row++) {
1509 for(int column = 0; column < rightCol; column++) {
1510 tempConstArray[rightRow * column + row].setFConst(rightUnionArray[rightCol * row + column].getFConst());
1511 }
1512 }
1513 // update return type for transpose
1514 returnType.setNominalSize(static_cast<unsigned char>(rightRow));
1515 returnType.setSecondarySize(static_cast<unsigned char>(rightCol));
1516 }
1517 break;
1518
1519 case EOpDeterminant:
1520 {
1521 ASSERT(node->getNominalSize() == node->getSecondarySize());
1522
1523 tempConstArray = new ConstantUnion[1];
1524 tempConstArray[0].setFConst(ComputeDeterminant(node->getNominalSize(), rightUnionArray));
1525 // update return type for determinant
1526 returnType.setNominalSize(1);
1527 returnType.setSecondarySize(1);
1528 }
1529 break;
1530
1531 case EOpInverse:
1532 {
1533 ASSERT(node->getNominalSize() == node->getSecondarySize());
1534
1535 tempConstArray = CreateInverse(node, rightUnionArray);
1536 if(!tempConstArray)
1537 {
1538 // Singular matrix, just copy
1539 tempConstArray = new ConstantUnion[objectSize];
1540 for(size_t i = 0; i < objectSize; i++)
1541 tempConstArray[i] = rightUnionArray[i];
1542 }
1543 }
1544 break;
1545
1546 case EOpDiv:
1547 case EOpIMod:
1548 tempConstArray = new ConstantUnion[objectSize];
1549 {// support MSVC++6.0
1550 for (size_t i = 0; i < objectSize; i++) {
1551 switch (getType().getBasicType()) {
1552 case EbtFloat:
1553 if (rightUnionArray[i] == 0.0f) {
1554 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1555 tempConstArray[i].setFConst(FLT_MAX);
1556 } else {
1557 ASSERT(op == EOpDiv);
1558 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1559 }
1560 break;
1561
1562 case EbtInt:
1563 if (rightUnionArray[i] == 0) {
1564 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1565 tempConstArray[i].setIConst(INT_MAX);
1566 } else {
1567 if(op == EOpDiv) {
1568 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1569 } else {
1570 ASSERT(op == EOpIMod);
1571 tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst());
1572 }
1573 }
1574 break;
1575 case EbtUInt:
1576 if (rightUnionArray[i] == 0) {
1577 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1578 tempConstArray[i].setUConst(UINT_MAX);
1579 } else {
1580 if(op == EOpDiv) {
1581 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1582 } else {
1583 ASSERT(op == EOpIMod);
1584 tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst());
1585 }
1586 }
1587 break;
1588 default:
1589 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1590 return 0;
1591 }
1592 }
1593 }
1594 break;
1595
1596 case EOpMatrixTimesVector:
1597 if (node->getBasicType() != EbtFloat) {
1598 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1599 return 0;
1600 }
1601 tempConstArray = new ConstantUnion[getSecondarySize()];
1602
1603 {// support MSVC++6.0
1604 for (int rows = getSecondarySize(), i = 0; i < rows; i++) {
1605 tempConstArray[i].setFConst(0.0f);
1606 for (int cols = getNominalSize(), j = 0; j < cols; j++) {
1607 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*rows + i].getFConst()) * rightUnionArray[j].getFConst()));
1608 }
1609 }
1610 }
1611
1612 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtFloat, EbpUndefined, EvqConstExpr, getSecondarySize()));
1613 tempNode->setLine(getLine());
1614
1615 return tempNode;
1616
1617 case EOpVectorTimesMatrix:
1618 if (getType().getBasicType() != EbtFloat) {
1619 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1620 return 0;
1621 }
1622
1623 tempConstArray = new ConstantUnion[node->getNominalSize()];
1624 {// support MSVC++6.0
1625 for (int cols = node->getNominalSize(), i = 0; i < cols; i++) {
1626 tempConstArray[i].setFConst(0.0f);
1627 for (int rows = node->getSecondarySize(), j = 0; j < rows; j++) {
1628 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*rows + j].getFConst()));
1629 }
1630 }
1631 }
1632
1633 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtFloat, EbpUndefined, EvqConstExpr, node->getNominalSize()));
1634 tempNode->setLine(getLine());
1635 return tempNode;
1636
1637 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1638 tempConstArray = new ConstantUnion[objectSize];
1639 {// support MSVC++6.0
1640 for (size_t i = 0; i < objectSize; i++)
1641 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1642 }
1643 break;
1644
1645 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1646 tempConstArray = new ConstantUnion[objectSize];
1647 {// support MSVC++6.0
1648 for (size_t i = 0; i < objectSize; i++)
1649 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1650 }
1651 break;
1652
1653 case EOpLogicalXor:
1654 tempConstArray = new ConstantUnion[objectSize];
1655 {// support MSVC++6.0
1656 for (size_t i = 0; i < objectSize; i++)
1657 switch (getType().getBasicType()) {
1658 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1659 default: assert(false && "Default missing");
1660 }
1661 }
1662 break;
1663
1664 case EOpBitwiseAnd:
1665 tempConstArray = new ConstantUnion[objectSize];
1666 for(size_t i = 0; i < objectSize; i++)
1667 tempConstArray[i] = unionArray[i] & rightUnionArray[i];
1668 break;
1669 case EOpBitwiseXor:
1670 tempConstArray = new ConstantUnion[objectSize];
1671 for(size_t i = 0; i < objectSize; i++)
1672 tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
1673 break;
1674 case EOpBitwiseOr:
1675 tempConstArray = new ConstantUnion[objectSize];
1676 for(size_t i = 0; i < objectSize; i++)
1677 tempConstArray[i] = unionArray[i] | rightUnionArray[i];
1678 break;
1679 case EOpBitShiftLeft:
1680 tempConstArray = new ConstantUnion[objectSize];
1681 for(size_t i = 0; i < objectSize; i++)
1682 tempConstArray[i] = unionArray[i] << rightUnionArray[i];
1683 break;
1684 case EOpBitShiftRight:
1685 tempConstArray = new ConstantUnion[objectSize];
1686 for(size_t i = 0; i < objectSize; i++)
1687 tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
1688 break;
1689
1690 case EOpLessThan:
1691 tempConstArray = new ConstantUnion[objectSize];
1692 for(size_t i = 0; i < objectSize; i++)
1693 tempConstArray[i].setBConst(unionArray[i] < rightUnionArray[i]);
1694 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1695 break;
1696 case EOpGreaterThan:
1697 tempConstArray = new ConstantUnion[objectSize];
1698 for(size_t i = 0; i < objectSize; i++)
1699 tempConstArray[i].setBConst(unionArray[i] > rightUnionArray[i]);
1700 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1701 break;
1702 case EOpLessThanEqual:
1703 tempConstArray = new ConstantUnion[objectSize];
1704 for(size_t i = 0; i < objectSize; i++)
1705 tempConstArray[i].setBConst(unionArray[i] <= rightUnionArray[i]);
1706 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1707 break;
1708 case EOpGreaterThanEqual:
1709 tempConstArray = new ConstantUnion[objectSize];
1710 for(size_t i = 0; i < objectSize; i++)
1711 tempConstArray[i].setBConst(unionArray[i] >= rightUnionArray[i]);
1712 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1713 break;
1714 case EOpEqual:
1715 tempConstArray = new ConstantUnion[1];
1716
1717 if(getType().getBasicType() == EbtStruct) {
1718 tempConstArray->setBConst(CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray));
1719 } else {
1720 bool boolNodeFlag = true;
1721 for (size_t i = 0; i < objectSize; i++) {
1722 if (unionArray[i] != rightUnionArray[i]) {
1723 boolNodeFlag = false;
1724 break; // break out of for loop
1725 }
1726 }
1727 tempConstArray->setBConst(boolNodeFlag);
1728 }
1729
1730 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
1731 tempNode->setLine(getLine());
1732
1733 return tempNode;
1734
1735 case EOpNotEqual:
1736 tempConstArray = new ConstantUnion[1];
1737
1738 if(getType().getBasicType() == EbtStruct) {
1739 tempConstArray->setBConst(!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray));
1740 } else {
1741 bool boolNodeFlag = false;
1742 for (size_t i = 0; i < objectSize; i++) {
1743 if (unionArray[i] != rightUnionArray[i]) {
1744 boolNodeFlag = true;
1745 break; // break out of for loop
1746 }
1747 }
1748 tempConstArray->setBConst(boolNodeFlag);
1749 }
1750
1751 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
1752 tempNode->setLine(getLine());
1753
1754 return tempNode;
1755 case EOpMax:
1756 tempConstArray = new ConstantUnion[objectSize];
1757 {// support MSVC++6.0
1758 for (size_t i = 0; i < objectSize; i++)
1759 tempConstArray[i] = unionArray[i] > rightUnionArray[i] ? unionArray[i] : rightUnionArray[i];
1760 }
1761 break;
1762 case EOpMin:
1763 tempConstArray = new ConstantUnion[objectSize];
1764 {// support MSVC++6.0
1765 for (size_t i = 0; i < objectSize; i++)
1766 tempConstArray[i] = unionArray[i] < rightUnionArray[i] ? unionArray[i] : rightUnionArray[i];
1767 }
1768 break;
1769 default:
1770 return 0;
1771 }
1772 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1773 tempNode->setLine(getLine());
1774
1775 return tempNode;
1776 } else {
1777 //
1778 // Do unary operations
1779 //
1780 TIntermConstantUnion *newNode = 0;
1781 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
1782 TType type = getType();
1783 TBasicType basicType = type.getBasicType();
1784 for (size_t i = 0; i < objectSize; i++) {
1785 switch(op) {
1786 case EOpNegative:
1787 switch (basicType) {
1788 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1789 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1790 default:
1791 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1792 return 0;
1793 }
1794 break;
1795 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1796 switch (basicType) {
1797 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1798 default:
1799 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1800 return 0;
1801 }
1802 break;
1803 case EOpBitwiseNot:
1804 switch(basicType) {
1805 case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
1806 case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
1807 default:
1808 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1809 return 0;
1810 }
1811 break;
1812 case EOpRadians:
1813 switch(basicType) {
1814 case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 1.74532925e-2f); break;
1815 default:
1816 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1817 return 0;
1818 }
1819 break;
1820 case EOpDegrees:
1821 switch(basicType) {
1822 case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 5.72957795e+1f); break;
1823 default:
1824 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1825 return 0;
1826 }
1827 break;
1828 case EOpSin:
1829 switch(basicType) {
1830 case EbtFloat: tempConstArray[i].setFConst(sinf(unionArray[i].getFConst())); break;
1831 default:
1832 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1833 return 0;
1834 }
1835 break;
1836 case EOpCos:
1837 switch(basicType) {
1838 case EbtFloat: tempConstArray[i].setFConst(cosf(unionArray[i].getFConst())); break;
1839 default:
1840 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1841 return 0;
1842 }
1843 break;
1844 case EOpTan:
1845 switch(basicType) {
1846 case EbtFloat: tempConstArray[i].setFConst(tanf(unionArray[i].getFConst())); break;
1847 default:
1848 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1849 return 0;
1850 }
1851 break;
1852 case EOpAsin:
1853 switch(basicType) {
1854 case EbtFloat: tempConstArray[i].setFConst(asinf(unionArray[i].getFConst())); break;
1855 default:
1856 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1857 return 0;
1858 }
1859 break;
1860 case EOpAcos:
1861 switch(basicType) {
1862 case EbtFloat: tempConstArray[i].setFConst(acosf(unionArray[i].getFConst())); break;
1863 default:
1864 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1865 return 0;
1866 }
1867 break;
1868 case EOpAtan:
1869 switch(basicType) {
1870 case EbtFloat: tempConstArray[i].setFConst(atanf(unionArray[i].getFConst())); break;
1871 default:
1872 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1873 return 0;
1874 }
1875 break;
1876 case EOpSinh:
1877 switch(basicType) {
1878 case EbtFloat: tempConstArray[i].setFConst(sinhf(unionArray[i].getFConst())); break;
1879 default:
1880 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1881 return 0;
1882 }
1883 break;
1884 case EOpCosh:
1885 switch(basicType) {
1886 case EbtFloat: tempConstArray[i].setFConst(coshf(unionArray[i].getFConst())); break;
1887 default:
1888 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1889 return 0;
1890 }
1891 break;
1892 case EOpTanh:
1893 switch(basicType) {
1894 case EbtFloat: tempConstArray[i].setFConst(tanhf(unionArray[i].getFConst())); break;
1895 default:
1896 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1897 return 0;
1898 }
1899 break;
1900 case EOpAsinh:
1901 switch(basicType) {
1902 case EbtFloat: tempConstArray[i].setFConst(asinhf(unionArray[i].getFConst())); break;
1903 default:
1904 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1905 return 0;
1906 }
1907 break;
1908 case EOpAcosh:
1909 switch(basicType) {
1910 case EbtFloat: tempConstArray[i].setFConst(acoshf(unionArray[i].getFConst())); break;
1911 default:
1912 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1913 return 0;
1914 }
1915 break;
1916 case EOpAtanh:
1917 switch(basicType) {
1918 case EbtFloat: tempConstArray[i].setFConst(atanhf(unionArray[i].getFConst())); break;
1919 default:
1920 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1921 return 0;
1922 }
1923 break;
1924 case EOpLog:
1925 switch(basicType) {
1926 case EbtFloat: tempConstArray[i].setFConst(logf(unionArray[i].getFConst())); break;
1927 default:
1928 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1929 return 0;
1930 }
1931 break;
1932 case EOpLog2:
1933 switch(basicType) {
1934 case EbtFloat: tempConstArray[i].setFConst(sw::log2(unionArray[i].getFConst())); break;
1935 default:
1936 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1937 return 0;
1938 }
1939 break;
1940 case EOpExp:
1941 switch(basicType) {
1942 case EbtFloat: tempConstArray[i].setFConst(expf(unionArray[i].getFConst())); break;
1943 default:
1944 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1945 return 0;
1946 }
1947 break;
1948 case EOpExp2:
1949 switch(basicType) {
1950 case EbtFloat: tempConstArray[i].setFConst(exp2f(unionArray[i].getFConst())); break;
1951 default:
1952 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1953 return 0;
1954 }
1955 break;
1956 case EOpSqrt:
1957 switch(basicType) {
1958 case EbtFloat: tempConstArray[i].setFConst(sqrtf(unionArray[i].getFConst())); break;
1959 default:
1960 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1961 return 0;
1962 }
1963 break;
1964 case EOpInverseSqrt:
1965 switch(basicType) {
1966 case EbtFloat: tempConstArray[i].setFConst(1.0f / sqrtf(unionArray[i].getFConst())); break;
1967 default:
1968 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1969 return 0;
1970 }
1971 break;
1972 case EOpFloatBitsToInt:
1973 switch(basicType) {
1974 case EbtFloat:
1975 tempConstArray[i].setIConst(sw::bit_cast<int>(unionArray[i].getFConst()));
1976 type.setBasicType(EbtInt);
1977 break;
1978 default:
1979 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1980 return 0;
1981 }
1982 break;
1983 break;
1984 case EOpFloatBitsToUint:
1985 switch(basicType) {
1986 case EbtFloat:
1987 tempConstArray[i].setUConst(sw::bit_cast<unsigned int>(unionArray[i].getFConst()));
1988 type.setBasicType(EbtUInt);
1989 break;
1990 default:
1991 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1992 return 0;
1993 }
1994 break;
1995 case EOpIntBitsToFloat:
1996 switch(basicType) {
1997 case EbtInt:
1998 tempConstArray[i].setFConst(sw::bit_cast<float>(unionArray[i].getIConst()));
1999 type.setBasicType(EbtFloat);
2000 break;
2001 default:
2002 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
2003 return 0;
2004 }
2005 break;
2006 case EOpUintBitsToFloat:
2007 switch(basicType) {
2008 case EbtUInt:
2009 tempConstArray[i].setFConst(sw::bit_cast<float>(unionArray[i].getUConst()));
2010 type.setBasicType(EbtFloat);
2011 break;
2012 default:
2013 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
2014 return 0;
2015 }
2016 break;
2017 default:
2018 return 0;
2019 }
2020 }
2021 newNode = new TIntermConstantUnion(tempConstArray, type);
2022 newNode->setLine(getLine());
2023 return newNode;
2024 }
2025}
2026
2027TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
2028{
2029 size_t size = node->getType().getObjectSize();
2030
2031 ConstantUnion *leftUnionArray = new ConstantUnion[size];
2032
2033 for(size_t i = 0; i < size; i++) {
2034 switch (promoteTo) {
2035 case EbtFloat:
2036 switch (node->getType().getBasicType()) {
2037 case EbtInt:
2038 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
2039 break;
2040 case EbtUInt:
2041 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
2042 break;
2043 case EbtBool:
2044 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
2045 break;
2046 case EbtFloat:
2047 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
2048 break;
2049 default:
2050 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2051 return 0;
2052 }
2053 break;
2054 case EbtInt:
2055 switch (node->getType().getBasicType()) {
2056 case EbtInt:
2057 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
2058 break;
2059 case EbtUInt:
2060 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
2061 break;
2062 case EbtBool:
2063 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
2064 break;
2065 case EbtFloat:
2066 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
2067 break;
2068 default:
2069 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2070 return 0;
2071 }
2072 break;
2073 case EbtUInt:
2074 switch (node->getType().getBasicType()) {
2075 case EbtInt:
2076 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
2077 break;
2078 case EbtUInt:
2079 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
2080 break;
2081 case EbtBool:
2082 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
2083 break;
2084 case EbtFloat:
2085 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
2086 break;
2087 default:
2088 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2089 return 0;
2090 }
2091 break;
2092 case EbtBool:
2093 switch (node->getType().getBasicType()) {
2094 case EbtInt:
2095 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
2096 break;
2097 case EbtUInt:
2098 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
2099 break;
2100 case EbtBool:
2101 leftUnionArray[i].setBConst(node->getBConst(i));
2102 break;
2103 case EbtFloat:
2104 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
2105 break;
2106 default:
2107 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2108 return 0;
2109 }
2110
2111 break;
2112 default:
2113 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
2114 return 0;
2115 }
2116
2117 }
2118
2119 const TType& t = node->getType();
2120
2121 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
2122}
2123
2124