Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / compiler / translator / Intermediate.cpp
1 //
2 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
3 // 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
15 #include "compiler/translator/HashNames.h"
16 #include "compiler/translator/localintermediate.h"
17 #include "compiler/translator/QualifierAlive.h"
18 #include "compiler/translator/RemoveTree.h"
19
20 bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
21
22 static TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
23 {
24     return left > right ? left : right;
25 }
26
27 const char* getOperatorString(TOperator op)
28 {
29     switch (op) {
30       case EOpInitialize: return "=";
31       case EOpAssign: return "=";
32       case EOpAddAssign: return "+=";
33       case EOpSubAssign: return "-=";
34       case EOpDivAssign: return "/=";
35
36       // Fall-through.
37       case EOpMulAssign: 
38       case EOpVectorTimesMatrixAssign:
39       case EOpVectorTimesScalarAssign:
40       case EOpMatrixTimesScalarAssign:
41       case EOpMatrixTimesMatrixAssign: return "*=";
42
43       // Fall-through.
44       case EOpIndexDirect:
45       case EOpIndexIndirect: return "[]";
46
47       case EOpIndexDirectStruct: return ".";
48       case EOpVectorSwizzle: return ".";
49       case EOpAdd: return "+";
50       case EOpSub: return "-";
51       case EOpMul: return "*";
52       case EOpDiv: return "/";
53       case EOpMod: UNIMPLEMENTED(); break;
54       case EOpEqual: return "==";
55       case EOpNotEqual: return "!=";
56       case EOpLessThan: return "<";
57       case EOpGreaterThan: return ">";
58       case EOpLessThanEqual: return "<=";
59       case EOpGreaterThanEqual: return ">=";
60
61       // Fall-through.
62       case EOpVectorTimesScalar:
63       case EOpVectorTimesMatrix:
64       case EOpMatrixTimesVector:
65       case EOpMatrixTimesScalar:
66       case EOpMatrixTimesMatrix: return "*";
67
68       case EOpLogicalOr: return "||";
69       case EOpLogicalXor: return "^^";
70       case EOpLogicalAnd: return "&&";
71       case EOpNegative: return "-";
72       case EOpVectorLogicalNot: return "not";
73       case EOpLogicalNot: return "!";
74       case EOpPostIncrement: return "++";
75       case EOpPostDecrement: return "--";
76       case EOpPreIncrement: return "++";
77       case EOpPreDecrement: return "--";
78
79       // Fall-through.
80       case EOpConvIntToBool:
81       case EOpConvFloatToBool: return "bool";
82  
83       // Fall-through.
84       case EOpConvBoolToFloat:
85       case EOpConvIntToFloat: return "float";
86  
87       // Fall-through.
88       case EOpConvFloatToInt:
89       case EOpConvBoolToInt: return "int";
90
91       case EOpRadians: return "radians";
92       case EOpDegrees: return "degrees";
93       case EOpSin: return "sin";
94       case EOpCos: return "cos";
95       case EOpTan: return "tan";
96       case EOpAsin: return "asin";
97       case EOpAcos: return "acos";
98       case EOpAtan: return "atan";
99       case EOpExp: return "exp";
100       case EOpLog: return "log";
101       case EOpExp2: return "exp2";
102       case EOpLog2: return "log2";
103       case EOpSqrt: return "sqrt";
104       case EOpInverseSqrt: return "inversesqrt";
105       case EOpAbs: return "abs";
106       case EOpSign: return "sign";
107       case EOpFloor: return "floor";
108       case EOpCeil: return "ceil";
109       case EOpFract: return "fract";
110       case EOpLength: return "length";
111       case EOpNormalize: return "normalize";
112       case EOpDFdx: return "dFdx";
113       case EOpDFdy: return "dFdy";
114       case EOpFwidth: return "fwidth";
115       case EOpAny: return "any";
116       case EOpAll: return "all";
117
118       default: break;
119     }
120     return "";
121 }
122
123 ////////////////////////////////////////////////////////////////////////////
124 //
125 // First set of functions are to help build the intermediate representation.
126 // These functions are not member functions of the nodes.
127 // They are called from parser productions.
128 //
129 /////////////////////////////////////////////////////////////////////////////
130
131 //
132 // Add a terminal node for an identifier in an expression.
133 //
134 // Returns the added node.
135 //
136 TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line)
137 {
138     TIntermSymbol* node = new TIntermSymbol(id, name, type);
139     node->setLine(line);
140
141     return node;
142 }
143
144 //
145 // Connect two nodes with a new parent that does a binary operation on the nodes.
146 //
147 // Returns the added node.
148 //
149 TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line, TSymbolTable& symbolTable)
150 {
151     switch (op) {
152         case EOpEqual:
153         case EOpNotEqual:
154             if (left->isArray())
155                 return 0;
156             break;
157         case EOpLessThan:
158         case EOpGreaterThan:
159         case EOpLessThanEqual:
160         case EOpGreaterThanEqual:
161             if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
162                 return 0;
163             }
164             break;
165         case EOpLogicalOr:
166         case EOpLogicalXor:
167         case EOpLogicalAnd:
168             if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
169                 return 0;
170             }
171             break;
172         case EOpAdd:
173         case EOpSub:
174         case EOpDiv:
175         case EOpMul:
176             if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
177                 return 0;
178         default: break;
179     }
180
181     //
182     // First try converting the children to compatible types.
183     //
184     if (left->getType().getStruct() && right->getType().getStruct()) {
185         if (left->getType() != right->getType())
186             return 0;
187     } else {
188         TIntermTyped* child = addConversion(op, left->getType(), right);
189         if (child)
190             right = child;
191         else {
192             child = addConversion(op, right->getType(), left);
193             if (child)
194                 left = child;
195             else
196                 return 0;
197         }
198     }
199
200     //
201     // Need a new node holding things together then.  Make
202     // one and promote it to the right type.
203     //
204     TIntermBinary* node = new TIntermBinary(op);
205     node->setLine(line);
206
207     node->setLeft(left);
208     node->setRight(right);
209     if (!node->promote(infoSink))
210         return 0;
211
212     //
213     // See if we can fold constants.
214     //
215     TIntermTyped* typedReturnNode = 0;
216     TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
217     TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
218     if (leftTempConstant && rightTempConstant) {
219         typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
220
221         if (typedReturnNode)
222             return typedReturnNode;
223     }
224
225     return node;
226 }
227
228 //
229 // Connect two nodes through an assignment.
230 //
231 // Returns the added node.
232 //
233 TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
234 {
235     //
236     // Like adding binary math, except the conversion can only go
237     // from right to left.
238     //
239     TIntermBinary* node = new TIntermBinary(op);
240     node->setLine(line);
241
242     TIntermTyped* child = addConversion(op, left->getType(), right);
243     if (child == 0)
244         return 0;
245
246     node->setLeft(left);
247     node->setRight(child);
248     if (! node->promote(infoSink))
249         return 0;
250
251     return node;
252 }
253
254 //
255 // Connect two nodes through an index operator, where the left node is the base
256 // of an array or struct, and the right node is a direct or indirect offset.
257 //
258 // Returns the added node.
259 // The caller should set the type of the returned node.
260 //
261 TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line)
262 {
263     TIntermBinary* node = new TIntermBinary(op);
264     node->setLine(line);
265     node->setLeft(base);
266     node->setRight(index);
267
268     // caller should set the type
269
270     return node;
271 }
272
273 //
274 // Add one node as the parent of another that it operates on.
275 //
276 // Returns the added node.
277 //
278 TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line, TSymbolTable& symbolTable)
279 {
280     TIntermUnary* node;
281     TIntermTyped* child = childNode->getAsTyped();
282
283     if (child == 0) {
284         infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath");
285         return 0;
286     }
287
288     switch (op) {
289         case EOpLogicalNot:
290             if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
291                 return 0;
292             }
293             break;
294
295         case EOpPostIncrement:
296         case EOpPreIncrement:
297         case EOpPostDecrement:
298         case EOpPreDecrement:
299         case EOpNegative:
300             if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
301                 return 0;
302         default: break;
303     }
304
305     //
306     // Do we need to promote the operand?
307     //
308     // Note: Implicit promotions were removed from the language.
309     //
310     TBasicType newType = EbtVoid;
311     switch (op) {
312         case EOpConstructInt:   newType = EbtInt;   break;
313         case EOpConstructBool:  newType = EbtBool;  break;
314         case EOpConstructFloat: newType = EbtFloat; break;
315         default: break;
316     }
317
318     if (newType != EbtVoid) {
319         child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
320             child->getNominalSize(),
321             child->isMatrix(),
322             child->isArray()),
323             child);
324         if (child == 0)
325             return 0;
326     }
327
328     //
329     // For constructors, we are now done, it's all in the conversion.
330     //
331     switch (op) {
332         case EOpConstructInt:
333         case EOpConstructBool:
334         case EOpConstructFloat:
335             return child;
336         default: break;
337     }
338
339     TIntermConstantUnion *childTempConstant = 0;
340     if (child->getAsConstantUnion())
341         childTempConstant = child->getAsConstantUnion();
342
343     //
344     // Make a new node for the operator.
345     //
346     node = new TIntermUnary(op);
347     node->setLine(line);
348     node->setOperand(child);
349
350     if (! node->promote(infoSink))
351         return 0;
352
353     if (childTempConstant)  {
354         TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
355
356         if (newChild)
357             return newChild;
358     }
359
360     return node;
361 }
362
363 //
364 // This is the safe way to change the operator on an aggregate, as it
365 // does lots of error checking and fixing.  Especially for establishing
366 // a function call's operation on it's set of parameters.  Sequences
367 // of instructions are also aggregates, but they just direnctly set
368 // their operator to EOpSequence.
369 //
370 // Returns an aggregate node, which could be the one passed in if
371 // it was already an aggregate but no operator was set.
372 //
373 TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line)
374 {
375     TIntermAggregate* aggNode;
376
377     //
378     // Make sure we have an aggregate.  If not turn it into one.
379     //
380     if (node) {
381         aggNode = node->getAsAggregate();
382         if (aggNode == 0 || aggNode->getOp() != EOpNull) {
383             //
384             // Make an aggregate containing this node.
385             //
386             aggNode = new TIntermAggregate();
387             aggNode->getSequence().push_back(node);
388         }
389     } else
390         aggNode = new TIntermAggregate();
391
392     //
393     // Set the operator.
394     //
395     aggNode->setOp(op);
396     aggNode->setLine(line);
397
398     return aggNode;
399 }
400
401 //
402 // Convert one type to another.
403 //
404 // Returns the node representing the conversion, which could be the same
405 // node passed in if no conversion was needed.
406 //
407 // Return 0 if a conversion can't be done.
408 //
409 TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
410 {
411     //
412     // Does the base type allow operation?
413     //
414     switch (node->getBasicType()) {
415         case EbtVoid:
416         case EbtSampler2D:
417         case EbtSamplerCube:
418             return 0;
419         default: break;
420     }
421
422     //
423     // Otherwise, if types are identical, no problem
424     //
425     if (type == node->getType())
426         return node;
427
428     //
429     // If one's a structure, then no conversions.
430     //
431     if (type.getStruct() || node->getType().getStruct())
432         return 0;
433
434     //
435     // If one's an array, then no conversions.
436     //
437     if (type.isArray() || node->getType().isArray())
438         return 0;
439
440     TBasicType promoteTo;
441
442     switch (op) {
443         //
444         // Explicit conversions
445         //
446         case EOpConstructBool:
447             promoteTo = EbtBool;
448             break;
449         case EOpConstructFloat:
450             promoteTo = EbtFloat;
451             break;
452         case EOpConstructInt:
453             promoteTo = EbtInt;
454             break;
455         default:
456             //
457             // implicit conversions were removed from the language.
458             //
459             if (type.getBasicType() != node->getType().getBasicType())
460                 return 0;
461             //
462             // Size and structure could still differ, but that's
463             // handled by operator promotion.
464             //
465             return node;
466     }
467
468     if (node->getAsConstantUnion()) {
469
470         return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
471     } else {
472
473         //
474         // Add a new newNode for the conversion.
475         //
476         TIntermUnary* newNode = 0;
477
478         TOperator newOp = EOpNull;
479         switch (promoteTo) {
480             case EbtFloat:
481                 switch (node->getBasicType()) {
482                     case EbtInt:   newOp = EOpConvIntToFloat;  break;
483                     case EbtBool:  newOp = EOpConvBoolToFloat; break;
484                     default:
485                         infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
486                         return 0;
487                 }
488                 break;
489             case EbtBool:
490                 switch (node->getBasicType()) {
491                     case EbtInt:   newOp = EOpConvIntToBool;   break;
492                     case EbtFloat: newOp = EOpConvFloatToBool; break;
493                     default:
494                         infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
495                         return 0;
496                 }
497                 break;
498             case EbtInt:
499                 switch (node->getBasicType()) {
500                     case EbtBool:   newOp = EOpConvBoolToInt;  break;
501                     case EbtFloat:  newOp = EOpConvFloatToInt; break;
502                     default:
503                         infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
504                         return 0;
505                 }
506                 break;
507             default:
508                 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type");
509                 return 0;
510         }
511
512         TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
513         newNode = new TIntermUnary(newOp, type);
514         newNode->setLine(node->getLine());
515         newNode->setOperand(node);
516
517         return newNode;
518     }
519 }
520
521 //
522 // Safe way to combine two nodes into an aggregate.  Works with null pointers,
523 // a node that's not a aggregate yet, etc.
524 //
525 // Returns the resulting aggregate, unless 0 was passed in for
526 // both existing nodes.
527 //
528 TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line)
529 {
530     if (left == 0 && right == 0)
531         return 0;
532
533     TIntermAggregate* aggNode = 0;
534     if (left)
535         aggNode = left->getAsAggregate();
536     if (!aggNode || aggNode->getOp() != EOpNull) {
537         aggNode = new TIntermAggregate;
538         if (left)
539             aggNode->getSequence().push_back(left);
540     }
541
542     if (right)
543         aggNode->getSequence().push_back(right);
544
545     aggNode->setLine(line);
546
547     return aggNode;
548 }
549
550 //
551 // Turn an existing node into an aggregate.
552 //
553 // Returns an aggregate, unless 0 was passed in for the existing node.
554 //
555 TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line)
556 {
557     if (node == 0)
558         return 0;
559
560     TIntermAggregate* aggNode = new TIntermAggregate;
561     aggNode->getSequence().push_back(node);
562     aggNode->setLine(line);
563
564     return aggNode;
565 }
566
567 //
568 // For "if" test nodes.  There are three children; a condition,
569 // a true path, and a false path.  The two paths are in the
570 // nodePair.
571 //
572 // Returns the selection node created.
573 //
574 TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line)
575 {
576     //
577     // For compile time constant selections, prune the code and
578     // test now.
579     //
580
581     if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
582         if (cond->getAsConstantUnion()->getBConst(0) == true)
583             return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
584         else
585             return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
586     }
587
588     TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
589     node->setLine(line);
590
591     return node;
592 }
593
594
595 TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
596 {
597     if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
598         return right;
599     } else {
600         TIntermTyped *commaAggregate = growAggregate(left, right, line);
601         commaAggregate->getAsAggregate()->setOp(EOpComma);
602         commaAggregate->setType(right->getType());
603         commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
604         return commaAggregate;
605     }
606 }
607
608 //
609 // For "?:" test nodes.  There are three children; a condition,
610 // a true path, and a false path.  The two paths are specified
611 // as separate parameters.
612 //
613 // Returns the selection node created, or 0 if one could not be.
614 //
615 TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line)
616 {
617     //
618     // Get compatible types.
619     //
620     TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
621     if (child)
622         falseBlock = child;
623     else {
624         child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
625         if (child)
626             trueBlock = child;
627         else
628             return 0;
629     }
630
631     //
632     // See if all the operands are constant, then fold it otherwise not.
633     //
634
635     if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
636         if (cond->getAsConstantUnion()->getBConst(0))
637             return trueBlock;
638         else
639             return falseBlock;
640     }
641
642     //
643     // Make a selection node.
644     //
645     TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
646     node->getTypePointer()->setQualifier(EvqTemporary);
647     node->setLine(line);
648
649     return node;
650 }
651
652 //
653 // Constant terminal nodes.  Has a union that contains bool, float or int constants
654 //
655 // Returns the constant union node created.
656 //
657
658 TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line)
659 {
660     TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
661     node->setLine(line);
662
663     return node;
664 }
665
666 TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line)
667 {
668
669     TIntermAggregate* node = new TIntermAggregate(EOpSequence);
670
671     node->setLine(line);
672     TIntermConstantUnion* constIntNode;
673     TIntermSequence &sequenceVector = node->getSequence();
674     ConstantUnion* unionArray;
675
676     for (int i = 0; i < fields.num; i++) {
677         unionArray = new ConstantUnion[1];
678         unionArray->setIConst(fields.offsets[i]);
679         constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
680         sequenceVector.push_back(constIntNode);
681     }
682
683     return node;
684 }
685
686 //
687 // Create loop nodes.
688 //
689 TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line)
690 {
691     TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
692     node->setLine(line);
693
694     return node;
695 }
696
697 //
698 // Add branches.
699 //
700 TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line)
701 {
702     return addBranch(branchOp, 0, line);
703 }
704
705 TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line)
706 {
707     TIntermBranch* node = new TIntermBranch(branchOp, expression);
708     node->setLine(line);
709
710     return node;
711 }
712
713 //
714 // This is to be executed once the final root is put on top by the parsing
715 // process.
716 //
717 bool TIntermediate::postProcess(TIntermNode* root)
718 {
719     if (root == 0)
720         return true;
721
722     //
723     // First, finish off the top level sequence, if any
724     //
725     TIntermAggregate* aggRoot = root->getAsAggregate();
726     if (aggRoot && aggRoot->getOp() == EOpNull)
727         aggRoot->setOp(EOpSequence);
728
729     return true;
730 }
731
732 //
733 // This deletes the tree.
734 //
735 void TIntermediate::remove(TIntermNode* root)
736 {
737     if (root)
738         RemoveAllTreeNodes(root);
739 }
740
741 ////////////////////////////////////////////////////////////////
742 //
743 // Member functions of the nodes used for building the tree.
744 //
745 ////////////////////////////////////////////////////////////////
746
747 #define REPLACE_IF_IS(node, type, original, replacement) \
748     if (node == original) { \
749         node = static_cast<type *>(replacement); \
750         return true; \
751     }
752
753 bool TIntermLoop::replaceChildNode(
754     TIntermNode *original, TIntermNode *replacement)
755 {
756     REPLACE_IF_IS(init, TIntermNode, original, replacement);
757     REPLACE_IF_IS(cond, TIntermTyped, original, replacement);
758     REPLACE_IF_IS(expr, TIntermTyped, original, replacement);
759     REPLACE_IF_IS(body, TIntermNode, original, replacement);
760     return false;
761 }
762
763 bool TIntermBranch::replaceChildNode(
764     TIntermNode *original, TIntermNode *replacement)
765 {
766     REPLACE_IF_IS(expression, TIntermTyped, original, replacement);
767     return false;
768 }
769
770 bool TIntermBinary::replaceChildNode(
771     TIntermNode *original, TIntermNode *replacement)
772 {
773     REPLACE_IF_IS(left, TIntermTyped, original, replacement);
774     REPLACE_IF_IS(right, TIntermTyped, original, replacement);
775     return false;
776 }
777
778 bool TIntermUnary::replaceChildNode(
779     TIntermNode *original, TIntermNode *replacement)
780 {
781     REPLACE_IF_IS(operand, TIntermTyped, original, replacement);
782     return false;
783 }
784
785 bool TIntermAggregate::replaceChildNode(
786     TIntermNode *original, TIntermNode *replacement)
787 {
788     for (size_t ii = 0; ii < sequence.size(); ++ii)
789     {
790         REPLACE_IF_IS(sequence[ii], TIntermNode, original, replacement);
791     }
792     return false;
793 }
794
795 bool TIntermSelection::replaceChildNode(
796     TIntermNode *original, TIntermNode *replacement)
797 {
798     REPLACE_IF_IS(condition, TIntermTyped, original, replacement);
799     REPLACE_IF_IS(trueBlock, TIntermNode, original, replacement);
800     REPLACE_IF_IS(falseBlock, TIntermNode, original, replacement);
801     return false;
802 }
803
804 //
805 // Say whether or not an operation node changes the value of a variable.
806 //
807 bool TIntermOperator::isAssignment() const
808 {
809     switch (op) {
810         case EOpPostIncrement:
811         case EOpPostDecrement:
812         case EOpPreIncrement:
813         case EOpPreDecrement:
814         case EOpAssign:
815         case EOpAddAssign:
816         case EOpSubAssign:
817         case EOpMulAssign:
818         case EOpVectorTimesMatrixAssign:
819         case EOpVectorTimesScalarAssign:
820         case EOpMatrixTimesScalarAssign:
821         case EOpMatrixTimesMatrixAssign:
822         case EOpDivAssign:
823             return true;
824         default:
825             return false;
826     }
827 }
828
829 //
830 // returns true if the operator is for one of the constructors
831 //
832 bool TIntermOperator::isConstructor() const
833 {
834     switch (op) {
835         case EOpConstructVec2:
836         case EOpConstructVec3:
837         case EOpConstructVec4:
838         case EOpConstructMat2:
839         case EOpConstructMat3:
840         case EOpConstructMat4:
841         case EOpConstructFloat:
842         case EOpConstructIVec2:
843         case EOpConstructIVec3:
844         case EOpConstructIVec4:
845         case EOpConstructInt:
846         case EOpConstructBVec2:
847         case EOpConstructBVec3:
848         case EOpConstructBVec4:
849         case EOpConstructBool:
850         case EOpConstructStruct:
851             return true;
852         default:
853             return false;
854     }
855 }
856
857 //
858 // Make sure the type of a unary operator is appropriate for its
859 // combination of operation and operand type.
860 //
861 // Returns false in nothing makes sense.
862 //
863 bool TIntermUnary::promote(TInfoSink&)
864 {
865     switch (op) {
866         case EOpLogicalNot:
867             if (operand->getBasicType() != EbtBool)
868                 return false;
869             break;
870         case EOpNegative:
871         case EOpPostIncrement:
872         case EOpPostDecrement:
873         case EOpPreIncrement:
874         case EOpPreDecrement:
875             if (operand->getBasicType() == EbtBool)
876                 return false;
877             break;
878
879             // operators for built-ins are already type checked against their prototype
880         case EOpAny:
881         case EOpAll:
882         case EOpVectorLogicalNot:
883             return true;
884
885         default:
886             if (operand->getBasicType() != EbtFloat)
887                 return false;
888     }
889
890     setType(operand->getType());
891     type.setQualifier(EvqTemporary);
892
893     return true;
894 }
895
896 //
897 // Establishes the type of the resultant operation, as well as
898 // makes the operator the correct one for the operands.
899 //
900 // Returns false if operator can't work on operands.
901 //
902 bool TIntermBinary::promote(TInfoSink& infoSink)
903 {
904     // This function only handles scalars, vectors, and matrices.
905     if (left->isArray() || right->isArray()) {
906         infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays");
907         return false;
908     }
909
910     // GLSL ES 2.0 does not support implicit type casting.
911     // So the basic type should always match.
912     if (left->getBasicType() != right->getBasicType())
913         return false;
914
915     //
916     // Base assumption:  just make the type the same as the left
917     // operand.  Then only deviations from this need be coded.
918     //
919     setType(left->getType());
920
921     // The result gets promoted to the highest precision.
922     TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
923     getTypePointer()->setPrecision(higherPrecision);
924
925     // Binary operations results in temporary variables unless both
926     // operands are const.
927     if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) {
928         getTypePointer()->setQualifier(EvqTemporary);
929     }
930
931     int size = std::max(left->getNominalSize(), right->getNominalSize());
932
933     //
934     // All scalars. Code after this test assumes this case is removed!
935     //
936     if (size == 1) {
937         switch (op) {
938             //
939             // Promote to conditional
940             //
941             case EOpEqual:
942             case EOpNotEqual:
943             case EOpLessThan:
944             case EOpGreaterThan:
945             case EOpLessThanEqual:
946             case EOpGreaterThanEqual:
947                 setType(TType(EbtBool, EbpUndefined));
948                 break;
949
950             //
951             // And and Or operate on conditionals
952             //
953             case EOpLogicalAnd:
954             case EOpLogicalOr:
955                 // Both operands must be of type bool.
956                 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
957                     return false;
958                 setType(TType(EbtBool, EbpUndefined));
959                 break;
960
961             default:
962                 break;
963         }
964         return true;
965     }
966
967     // If we reach here, at least one of the operands is vector or matrix.
968     // The other operand could be a scalar, vector, or matrix.
969     // Are the sizes compatible?
970     //
971     if (left->getNominalSize() != right->getNominalSize()) {
972         // If the nominal size of operands do not match:
973         // One of them must be scalar.
974         if (left->getNominalSize() != 1 && right->getNominalSize() != 1)
975             return false;
976         // Operator cannot be of type pure assignment.
977         if (op == EOpAssign || op == EOpInitialize)
978             return false;
979     }
980
981     //
982     // Can these two operands be combined?
983     //
984     TBasicType basicType = left->getBasicType();
985     switch (op) {
986         case EOpMul:
987             if (!left->isMatrix() && right->isMatrix()) {
988                 if (left->isVector())
989                     op = EOpVectorTimesMatrix;
990                 else {
991                     op = EOpMatrixTimesScalar;
992                     setType(TType(basicType, higherPrecision, EvqTemporary, size, true));
993                 }
994             } else if (left->isMatrix() && !right->isMatrix()) {
995                 if (right->isVector()) {
996                     op = EOpMatrixTimesVector;
997                     setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
998                 } else {
999                     op = EOpMatrixTimesScalar;
1000                 }
1001             } else if (left->isMatrix() && right->isMatrix()) {
1002                 op = EOpMatrixTimesMatrix;
1003             } else if (!left->isMatrix() && !right->isMatrix()) {
1004                 if (left->isVector() && right->isVector()) {
1005                     // leave as component product
1006                 } else if (left->isVector() || right->isVector()) {
1007                     op = EOpVectorTimesScalar;
1008                     setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
1009                 }
1010             } else {
1011                 infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
1012                 return false;
1013             }
1014             break;
1015         case EOpMulAssign:
1016             if (!left->isMatrix() && right->isMatrix()) {
1017                 if (left->isVector())
1018                     op = EOpVectorTimesMatrixAssign;
1019                 else {
1020                     return false;
1021                 }
1022             } else if (left->isMatrix() && !right->isMatrix()) {
1023                 if (right->isVector()) {
1024                     return false;
1025                 } else {
1026                     op = EOpMatrixTimesScalarAssign;
1027                 }
1028             } else if (left->isMatrix() && right->isMatrix()) {
1029                 op = EOpMatrixTimesMatrixAssign;
1030             } else if (!left->isMatrix() && !right->isMatrix()) {
1031                 if (left->isVector() && right->isVector()) {
1032                     // leave as component product
1033                 } else if (left->isVector() || right->isVector()) {
1034                     if (! left->isVector())
1035                         return false;
1036                     op = EOpVectorTimesScalarAssign;
1037                     setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
1038                 }
1039             } else {
1040                 infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
1041                 return false;
1042             }
1043             break;
1044
1045         case EOpAssign:
1046         case EOpInitialize:
1047         case EOpAdd:
1048         case EOpSub:
1049         case EOpDiv:
1050         case EOpAddAssign:
1051         case EOpSubAssign:
1052         case EOpDivAssign:
1053             if ((left->isMatrix() && right->isVector()) ||
1054                 (left->isVector() && right->isMatrix()))
1055                 return false;
1056             setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
1057             break;
1058
1059         case EOpEqual:
1060         case EOpNotEqual:
1061         case EOpLessThan:
1062         case EOpGreaterThan:
1063         case EOpLessThanEqual:
1064         case EOpGreaterThanEqual:
1065             if ((left->isMatrix() && right->isVector()) ||
1066                 (left->isVector() && right->isMatrix()))
1067                 return false;
1068             setType(TType(EbtBool, EbpUndefined));
1069             break;
1070
1071         default:
1072             return false;
1073     }
1074     
1075     return true;
1076 }
1077
1078 bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1079 {
1080     const TFieldList& fields = leftNodeType.getStruct()->fields();
1081
1082     size_t structSize = fields.size();
1083     size_t index = 0;
1084
1085     for (size_t j = 0; j < structSize; j++) {
1086         size_t size = fields[j]->type()->getObjectSize();
1087         for (size_t i = 0; i < size; i++) {
1088             if (fields[j]->type()->getBasicType() == EbtStruct) {
1089                 if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
1090                     return false;
1091             } else {
1092                 if (leftUnionArray[index] != rightUnionArray[index])
1093                     return false;
1094                 index++;
1095             }
1096         }
1097     }
1098     return true;
1099 }
1100
1101 bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1102 {
1103     if (leftNodeType.isArray()) {
1104         TType typeWithoutArrayness = leftNodeType;
1105         typeWithoutArrayness.clearArrayness();
1106
1107         size_t arraySize = leftNodeType.getArraySize();
1108
1109         for (size_t i = 0; i < arraySize; ++i) {
1110             size_t offset = typeWithoutArrayness.getObjectSize() * i;
1111             if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1112                 return false;
1113         }
1114     } else
1115         return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
1116
1117     return true;
1118 }
1119
1120 //
1121 // The fold functions see if an operation on a constant can be done in place,
1122 // without generating run-time code.
1123 //
1124 // Returns the node to keep using, which may or may not be the node passed in.
1125 //
1126
1127 TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1128 {
1129     ConstantUnion *unionArray = getUnionArrayPointer();
1130     size_t objectSize = getType().getObjectSize();
1131
1132     if (constantNode) {  // binary operations
1133         TIntermConstantUnion *node = constantNode->getAsConstantUnion();
1134         ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
1135         TType returnType = getType();
1136
1137         // for a case like float f = 1.2 + vec4(2,3,4,5);
1138         if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
1139             rightUnionArray = new ConstantUnion[objectSize];
1140             for (size_t i = 0; i < objectSize; ++i)
1141                 rightUnionArray[i] = *node->getUnionArrayPointer();
1142             returnType = getType();
1143         } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1144             // for a case like float f = vec4(2,3,4,5) + 1.2;
1145             unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
1146             for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
1147                 unionArray[i] = *getUnionArrayPointer();
1148             returnType = node->getType();
1149             objectSize = constantNode->getType().getObjectSize();
1150         }
1151
1152         ConstantUnion* tempConstArray = 0;
1153         TIntermConstantUnion *tempNode;
1154
1155         bool boolNodeFlag = false;
1156         switch(op) {
1157             case EOpAdd:
1158                 tempConstArray = new ConstantUnion[objectSize];
1159                 {// support MSVC++6.0
1160                     for (size_t i = 0; i < objectSize; i++)
1161                         tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1162                 }
1163                 break;
1164             case EOpSub:
1165                 tempConstArray = new ConstantUnion[objectSize];
1166                 {// support MSVC++6.0
1167                     for (size_t i = 0; i < objectSize; i++)
1168                         tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1169                 }
1170                 break;
1171
1172             case EOpMul:
1173             case EOpVectorTimesScalar:
1174             case EOpMatrixTimesScalar:
1175                 tempConstArray = new ConstantUnion[objectSize];
1176                 {// support MSVC++6.0
1177                     for (size_t i = 0; i < objectSize; i++)
1178                         tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1179                 }
1180                 break;
1181             case EOpMatrixTimesMatrix:
1182                 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1183                     infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply");
1184                     return 0;
1185                 }
1186                 {// support MSVC++6.0
1187                     int size = getNominalSize();
1188                     tempConstArray = new ConstantUnion[size*size];
1189                     for (int row = 0; row < size; row++) {
1190                         for (int column = 0; column < size; column++) {
1191                             tempConstArray[size * column + row].setFConst(0.0f);
1192                             for (int i = 0; i < size; i++) {
1193                                 tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
1194                             }
1195                         }
1196                     }
1197                 }
1198                 break;
1199             case EOpDiv:
1200                 tempConstArray = new ConstantUnion[objectSize];
1201                 {// support MSVC++6.0
1202                     for (size_t i = 0; i < objectSize; i++) {
1203                         switch (getType().getBasicType()) {
1204             case EbtFloat:
1205                 if (rightUnionArray[i] == 0.0f) {
1206                     infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
1207                     tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
1208                 } else
1209                     tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1210                 break;
1211
1212             case EbtInt:
1213                 if (rightUnionArray[i] == 0) {
1214                     infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
1215                     tempConstArray[i].setIConst(INT_MAX);
1216                 } else
1217                     tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1218                 break;
1219             default:
1220                 infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\"");
1221                 return 0;
1222                         }
1223                     }
1224                 }
1225                 break;
1226
1227             case EOpMatrixTimesVector:
1228                 if (node->getBasicType() != EbtFloat) {
1229                     infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector");
1230                     return 0;
1231                 }
1232                 tempConstArray = new ConstantUnion[getNominalSize()];
1233
1234                 {// support MSVC++6.0
1235                     for (int size = getNominalSize(), i = 0; i < size; i++) {
1236                         tempConstArray[i].setFConst(0.0f);
1237                         for (int j = 0; j < size; j++) {
1238                             tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1239                         }
1240                     }
1241                 }
1242
1243                 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1244                 tempNode->setLine(getLine());
1245
1246                 return tempNode;
1247
1248             case EOpVectorTimesMatrix:
1249                 if (getType().getBasicType() != EbtFloat) {
1250                     infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix");
1251                     return 0;
1252                 }
1253
1254                 tempConstArray = new ConstantUnion[getNominalSize()];
1255                 {// support MSVC++6.0
1256                     for (int size = getNominalSize(), i = 0; i < size; i++) {
1257                         tempConstArray[i].setFConst(0.0f);
1258                         for (int j = 0; j < size; j++) {
1259                             tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1260                         }
1261                     }
1262                 }
1263                 break;
1264
1265             case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1266                 tempConstArray = new ConstantUnion[objectSize];
1267                 {// support MSVC++6.0
1268                     for (size_t i = 0; i < objectSize; i++)
1269                         tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1270                 }
1271                 break;
1272
1273             case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1274                 tempConstArray = new ConstantUnion[objectSize];
1275                 {// support MSVC++6.0
1276                     for (size_t i = 0; i < objectSize; i++)
1277                         tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1278                 }
1279                 break;
1280
1281             case EOpLogicalXor:
1282                 tempConstArray = new ConstantUnion[objectSize];
1283                 {// support MSVC++6.0
1284                     for (size_t i = 0; i < objectSize; i++)
1285                         switch (getType().getBasicType()) {
1286             case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1287             default: assert(false && "Default missing");
1288                     }
1289                 }
1290                 break;
1291
1292             case EOpLessThan:
1293                 assert(objectSize == 1);
1294                 tempConstArray = new ConstantUnion[1];
1295                 tempConstArray->setBConst(*unionArray < *rightUnionArray);
1296                 returnType = TType(EbtBool, EbpUndefined, EvqConst);
1297                 break;
1298             case EOpGreaterThan:
1299                 assert(objectSize == 1);
1300                 tempConstArray = new ConstantUnion[1];
1301                 tempConstArray->setBConst(*unionArray > *rightUnionArray);
1302                 returnType = TType(EbtBool, EbpUndefined, EvqConst);
1303                 break;
1304             case EOpLessThanEqual:
1305                 {
1306                     assert(objectSize == 1);
1307                     ConstantUnion constant;
1308                     constant.setBConst(*unionArray > *rightUnionArray);
1309                     tempConstArray = new ConstantUnion[1];
1310                     tempConstArray->setBConst(!constant.getBConst());
1311                     returnType = TType(EbtBool, EbpUndefined, EvqConst);
1312                     break;
1313                 }
1314             case EOpGreaterThanEqual:
1315                 {
1316                     assert(objectSize == 1);
1317                     ConstantUnion constant;
1318                     constant.setBConst(*unionArray < *rightUnionArray);
1319                     tempConstArray = new ConstantUnion[1];
1320                     tempConstArray->setBConst(!constant.getBConst());
1321                     returnType = TType(EbtBool, EbpUndefined, EvqConst);
1322                     break;
1323                 }
1324
1325             case EOpEqual:
1326                 if (getType().getBasicType() == EbtStruct) {
1327                     if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1328                         boolNodeFlag = true;
1329                 } else {
1330                     for (size_t i = 0; i < objectSize; i++) {
1331                         if (unionArray[i] != rightUnionArray[i]) {
1332                             boolNodeFlag = true;
1333                             break;  // break out of for loop
1334                         }
1335                     }
1336                 }
1337
1338                 tempConstArray = new ConstantUnion[1];
1339                 if (!boolNodeFlag) {
1340                     tempConstArray->setBConst(true);
1341                 }
1342                 else {
1343                     tempConstArray->setBConst(false);
1344                 }
1345
1346                 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
1347                 tempNode->setLine(getLine());
1348
1349                 return tempNode;
1350
1351             case EOpNotEqual:
1352                 if (getType().getBasicType() == EbtStruct) {
1353                     if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1354                         boolNodeFlag = true;
1355                 } else {
1356                     for (size_t i = 0; i < objectSize; i++) {
1357                         if (unionArray[i] == rightUnionArray[i]) {
1358                             boolNodeFlag = true;
1359                             break;  // break out of for loop
1360                         }
1361                     }
1362                 }
1363
1364                 tempConstArray = new ConstantUnion[1];
1365                 if (!boolNodeFlag) {
1366                     tempConstArray->setBConst(true);
1367                 }
1368                 else {
1369                     tempConstArray->setBConst(false);
1370                 }
1371
1372                 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
1373                 tempNode->setLine(getLine());
1374
1375                 return tempNode;
1376
1377             default:
1378                 infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding");
1379                 return 0;
1380         }
1381         tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1382         tempNode->setLine(getLine());
1383
1384         return tempNode;
1385     } else {
1386         //
1387         // Do unary operations
1388         //
1389         TIntermConstantUnion *newNode = 0;
1390         ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
1391         for (size_t i = 0; i < objectSize; i++) {
1392             switch(op) {
1393                 case EOpNegative:
1394                     switch (getType().getBasicType()) {
1395                         case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1396                         case EbtInt:   tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1397                         default:
1398                             infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
1399                             return 0;
1400                     }
1401                     break;
1402                 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1403                     switch (getType().getBasicType()) {
1404                         case EbtBool:  tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1405                         default:
1406                             infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
1407                             return 0;
1408                     }
1409                     break;
1410                 default:
1411                     return 0;
1412             }
1413         }
1414         newNode = new TIntermConstantUnion(tempConstArray, getType());
1415         newNode->setLine(getLine());
1416         return newNode;
1417     }
1418 }
1419
1420 TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1421 {
1422     size_t size = node->getType().getObjectSize();
1423
1424     ConstantUnion *leftUnionArray = new ConstantUnion[size];
1425
1426     for (size_t i = 0; i < size; i++) {
1427
1428         switch (promoteTo) {
1429             case EbtFloat:
1430                 switch (node->getType().getBasicType()) {
1431                     case EbtInt:
1432                         leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
1433                         break;
1434                     case EbtBool:
1435                         leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
1436                         break;
1437                     case EbtFloat:
1438                         leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
1439                         break;
1440                     default:
1441                         infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
1442                         return 0;
1443                 }
1444                 break;
1445             case EbtInt:
1446                 switch (node->getType().getBasicType()) {
1447                     case EbtInt:
1448                         leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
1449                         break;
1450                     case EbtBool:
1451                         leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
1452                         break;
1453                     case EbtFloat:
1454                         leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
1455                         break;
1456                     default:
1457                         infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
1458                         return 0;
1459                 }
1460                 break;
1461             case EbtBool:
1462                 switch (node->getType().getBasicType()) {
1463                     case EbtInt:
1464                         leftUnionArray[i].setBConst(node->getIConst(i) != 0);
1465                         break;
1466                     case EbtBool:
1467                         leftUnionArray[i].setBConst(node->getBConst(i));
1468                         break;
1469                     case EbtFloat:
1470                         leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
1471                         break;
1472                     default:
1473                         infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
1474                         return 0;
1475                 }
1476
1477                 break;
1478             default:
1479                 infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found");
1480                 return 0;
1481         }
1482
1483     }
1484
1485     const TType& t = node->getType();
1486
1487     return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
1488 }
1489
1490 // static
1491 TString TIntermTraverser::hash(const TString& name, ShHashFunction64 hashFunction)
1492 {
1493     if (hashFunction == NULL || name.empty())
1494         return name;
1495     khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
1496     TStringStream stream;
1497     stream << HASHED_NAME_PREFIX << std::hex << number;
1498     TString hashedName = stream.str();
1499     return hashedName;
1500 }