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