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