LCOV - app.info - gfx/angle/src/compiler/Intermediate.cpp

LCOV - code coverage report
| Current view: | directory - gfx/angle/src/compiler - Intermediate.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 663 | 0 | 0.0 %
| Date: | 2012-06-02 | Functions: | 30 | 0 | 0.0 %

           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               0 : static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){
          22               0 :     return left > right ? left : right;
          23                 : }
          24                 :
          25               0 : const char* getOperatorString(TOperator op) {
          26               0 :     switch (op) {
          27               0 :       case EOpInitialize: return "=";
          28               0 :       case EOpAssign: return "=";
          29               0 :       case EOpAddAssign: return "+=";
          30               0 :       case EOpSubAssign: return "-=";
          31               0 :       case EOpDivAssign: return "/=";
          32                 :
          33                 :       // Fall-through.
          34                 :       case EOpMulAssign:
          35                 :       case EOpVectorTimesMatrixAssign:
          36                 :       case EOpVectorTimesScalarAssign:
          37                 :       case EOpMatrixTimesScalarAssign:
          38               0 :       case EOpMatrixTimesMatrixAssign: return "*=";
          39                 :
          40                 :       // Fall-through.
          41                 :       case EOpIndexDirect:
          42               0 :       case EOpIndexIndirect: return "[]";
          43                 :
          44               0 :       case EOpIndexDirectStruct: return ".";
          45               0 :       case EOpVectorSwizzle: return ".";
          46               0 :       case EOpAdd: return "+";
          47               0 :       case EOpSub: return "-";
          48               0 :       case EOpMul: return "*";
          49               0 :       case EOpDiv: return "/";
          50               0 :       case EOpMod: UNIMPLEMENTED(); break;
          51               0 :       case EOpEqual: return "==";
          52               0 :       case EOpNotEqual: return "!=";
          53               0 :       case EOpLessThan: return "<";
          54               0 :       case EOpGreaterThan: return ">";
          55               0 :       case EOpLessThanEqual: return "<=";
          56               0 :       case EOpGreaterThanEqual: return ">=";
          57                 :
          58                 :       // Fall-through.
          59                 :       case EOpVectorTimesScalar:
          60                 :       case EOpVectorTimesMatrix:
          61                 :       case EOpMatrixTimesVector:
          62                 :       case EOpMatrixTimesScalar:
          63               0 :       case EOpMatrixTimesMatrix: return "*";
          64                 :
          65               0 :       case EOpLogicalOr: return "||";
          66               0 :       case EOpLogicalXor: return "^^";
          67               0 :       case EOpLogicalAnd: return "&&";
          68               0 :       case EOpNegative: return "-";
          69               0 :       case EOpVectorLogicalNot: return "not";
          70               0 :       case EOpLogicalNot: return "!";
          71               0 :       case EOpPostIncrement: return "++";
          72               0 :       case EOpPostDecrement: return "--";
          73               0 :       case EOpPreIncrement: return "++";
          74               0 :       case EOpPreDecrement: return "--";
          75                 :
          76                 :       // Fall-through.
          77                 :       case EOpConvIntToBool:
          78               0 :       case EOpConvFloatToBool: return "bool";
          79                 :
          80                 :       // Fall-through.
          81                 :       case EOpConvBoolToFloat:
          82               0 :       case EOpConvIntToFloat: return "float";
          83                 :
          84                 :       // Fall-through.
          85                 :       case EOpConvFloatToInt:
          86               0 :       case EOpConvBoolToInt: return "int";
          87                 :
          88               0 :       case EOpRadians: return "radians";
          89               0 :       case EOpDegrees: return "degrees";
          90               0 :       case EOpSin: return "sin";
          91               0 :       case EOpCos: return "cos";
          92               0 :       case EOpTan: return "tan";
          93               0 :       case EOpAsin: return "asin";
          94               0 :       case EOpAcos: return "acos";
          95               0 :       case EOpAtan: return "atan";
          96               0 :       case EOpExp: return "exp";
          97               0 :       case EOpLog: return "log";
          98               0 :       case EOpExp2: return "exp2";
          99               0 :       case EOpLog2: return "log2";
         100               0 :       case EOpSqrt: return "sqrt";
         101               0 :       case EOpInverseSqrt: return "inversesqrt";
         102               0 :       case EOpAbs: return "abs";
         103               0 :       case EOpSign: return "sign";
         104               0 :       case EOpFloor: return "floor";
         105               0 :       case EOpCeil: return "ceil";
         106               0 :       case EOpFract: return "fract";
         107               0 :       case EOpLength: return "length";
         108               0 :       case EOpNormalize: return "normalize";
         109               0 :       case EOpDFdx: return "dFdx";
         110               0 :       case EOpDFdy: return "dFdy";
         111               0 :       case EOpFwidth: return "fwidth";
         112               0 :       case EOpAny: return "any";
         113               0 :       case EOpAll: return "all";
         114                 :
         115                 :       default: break;
         116                 :     }
         117               0 :     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               0 : TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
         134                 : {
         135               0 :     TIntermSymbol* node = new TIntermSymbol(id, name, type);
         136               0 :     node->setLine(line);
         137                 :
         138               0 :     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               0 : TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable)
         147                 : {
         148               0 :     switch (op) {
         149                 :         case EOpEqual:
         150                 :         case EOpNotEqual:
         151               0 :             if (left->isArray())
         152               0 :                 return 0;
         153               0 :             break;
         154                 :         case EOpLessThan:
         155                 :         case EOpGreaterThan:
         156                 :         case EOpLessThanEqual:
         157                 :         case EOpGreaterThanEqual:
         158               0 :             if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
         159               0 :                 return 0;
         160                 :             }
         161               0 :             break;
         162                 :         case EOpLogicalOr:
         163                 :         case EOpLogicalXor:
         164                 :         case EOpLogicalAnd:
         165               0 :             if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
         166               0 :                 return 0;
         167                 :             }
         168               0 :             break;
         169                 :         case EOpAdd:
         170                 :         case EOpSub:
         171                 :         case EOpDiv:
         172                 :         case EOpMul:
         173               0 :             if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
         174               0 :                 return 0;
         175               0 :         default: break;
         176                 :     }
         177                 :
         178                 :     //
         179                 :     // First try converting the children to compatible types.
         180                 :     //
         181               0 :     if (left->getType().getStruct() && right->getType().getStruct()) {
         182               0 :         if (left->getType() != right->getType())
         183               0 :             return 0;
         184                 :     } else {
         185               0 :         TIntermTyped* child = addConversion(op, left->getType(), right);
         186               0 :         if (child)
         187               0 :             right = child;
         188                 :         else {
         189               0 :             child = addConversion(op, right->getType(), left);
         190               0 :             if (child)
         191               0 :                 left = child;
         192                 :             else
         193               0 :                 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               0 :     TIntermBinary* node = new TIntermBinary(op);
         202               0 :     if (line == 0)
         203               0 :         line = right->getLine();
         204               0 :     node->setLine(line);
         205                 :
         206               0 :     node->setLeft(left);
         207               0 :     node->setRight(right);
         208               0 :     if (!node->promote(infoSink))
         209               0 :         return 0;
         210                 :
         211                 :     //
         212                 :     // See if we can fold constants.
         213                 :     //
         214               0 :     TIntermTyped* typedReturnNode = 0;
         215               0 :     TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
         216               0 :     TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
         217               0 :     if (leftTempConstant && rightTempConstant) {
         218               0 :         typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
         219                 :
         220               0 :         if (typedReturnNode)
         221               0 :             return typedReturnNode;
         222                 :     }
         223                 :
         224               0 :     return node;
         225                 : }
         226                 :
         227                 : //
         228                 : // Connect two nodes through an assignment.
         229                 : //
         230                 : // Returns the added node.
         231                 : //
         232               0 : 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               0 :     TIntermBinary* node = new TIntermBinary(op);
         239               0 :     if (line == 0)
         240               0 :         line = left->getLine();
         241               0 :     node->setLine(line);
         242                 :
         243               0 :     TIntermTyped* child = addConversion(op, left->getType(), right);
         244               0 :     if (child == 0)
         245               0 :         return 0;
         246                 :
         247               0 :     node->setLeft(left);
         248               0 :     node->setRight(child);
         249               0 :     if (! node->promote(infoSink))
         250               0 :         return 0;
         251                 :
         252               0 :     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               0 : TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
         263                 : {
         264               0 :     TIntermBinary* node = new TIntermBinary(op);
         265               0 :     if (line == 0)
         266               0 :         line = index->getLine();
         267               0 :     node->setLine(line);
         268               0 :     node->setLeft(base);
         269               0 :     node->setRight(index);
         270                 :
         271                 :     // caller should set the type
         272                 :
         273               0 :     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               0 : TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
         282                 : {
         283                 :     TIntermUnary* node;
         284               0 :     TIntermTyped* child = childNode->getAsTyped();
         285                 :
         286               0 :     if (child == 0) {
         287               0 :         infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
         288               0 :         return 0;
         289                 :     }
         290                 :
         291               0 :     switch (op) {
         292                 :         case EOpLogicalNot:
         293               0 :             if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
         294               0 :                 return 0;
         295                 :             }
         296               0 :             break;
         297                 :
         298                 :         case EOpPostIncrement:
         299                 :         case EOpPreIncrement:
         300                 :         case EOpPostDecrement:
         301                 :         case EOpPreDecrement:
         302                 :         case EOpNegative:
         303               0 :             if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
         304               0 :                 return 0;
         305               0 :         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               0 :     TBasicType newType = EbtVoid;
         314               0 :     switch (op) {
         315               0 :         case EOpConstructInt:   newType = EbtInt;   break;
         316               0 :         case EOpConstructBool:  newType = EbtBool;  break;
         317               0 :         case EOpConstructFloat: newType = EbtFloat; break;
         318               0 :         default: break;
         319                 :     }
         320                 :
         321               0 :     if (newType != EbtVoid) {
         322                 :         child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
         323                 :             child->getNominalSize(),
         324               0 :             child->isMatrix(),
         325               0 :             child->isArray()),
         326               0 :             child);
         327               0 :         if (child == 0)
         328               0 :             return 0;
         329                 :     }
         330                 :
         331                 :     //
         332                 :     // For constructors, we are now done, it's all in the conversion.
         333                 :     //
         334               0 :     switch (op) {
         335                 :         case EOpConstructInt:
         336                 :         case EOpConstructBool:
         337                 :         case EOpConstructFloat:
         338               0 :             return child;
         339                 :         default: break;
         340                 :     }
         341                 :
         342               0 :     TIntermConstantUnion *childTempConstant = 0;
         343               0 :     if (child->getAsConstantUnion())
         344               0 :         childTempConstant = child->getAsConstantUnion();
         345                 :
         346                 :     //
         347                 :     // Make a new node for the operator.
         348                 :     //
         349               0 :     node = new TIntermUnary(op);
         350               0 :     if (line == 0)
         351               0 :         line = child->getLine();
         352               0 :     node->setLine(line);
         353               0 :     node->setOperand(child);
         354                 :
         355               0 :     if (! node->promote(infoSink))
         356               0 :         return 0;
         357                 :
         358               0 :     if (childTempConstant)  {
         359               0 :         TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
         360                 :
         361               0 :         if (newChild)
         362               0 :             return newChild;
         363                 :     }
         364                 :
         365               0 :     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               0 : 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               0 :     if (node) {
         386               0 :         aggNode = node->getAsAggregate();
         387               0 :         if (aggNode == 0 || aggNode->getOp() != EOpNull) {
         388                 :             //
         389                 :             // Make an aggregate containing this node.
         390                 :             //
         391               0 :             aggNode = new TIntermAggregate();
         392               0 :             aggNode->getSequence().push_back(node);
         393               0 :             if (line == 0)
         394               0 :                 line = node->getLine();
         395                 :         }
         396                 :     } else
         397               0 :         aggNode = new TIntermAggregate();
         398                 :
         399                 :     //
         400                 :     // Set the operator.
         401                 :     //
         402               0 :     aggNode->setOp(op);
         403               0 :     if (line != 0)
         404               0 :         aggNode->setLine(line);
         405                 :
         406               0 :     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               0 : TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
         418                 : {
         419                 :     //
         420                 :     // Does the base type allow operation?
         421                 :     //
         422               0 :     switch (node->getBasicType()) {
         423                 :         case EbtVoid:
         424                 :         case EbtSampler2D:
         425                 :         case EbtSamplerCube:
         426               0 :             return 0;
         427                 :         default: break;
         428                 :     }
         429                 :
         430                 :     //
         431                 :     // Otherwise, if types are identical, no problem
         432                 :     //
         433               0 :     if (type == node->getType())
         434               0 :         return node;
         435                 :
         436                 :     //
         437                 :     // If one's a structure, then no conversions.
         438                 :     //
         439               0 :     if (type.getStruct() || node->getType().getStruct())
         440               0 :         return 0;
         441                 :
         442                 :     //
         443                 :     // If one's an array, then no conversions.
         444                 :     //
         445               0 :     if (type.isArray() || node->getType().isArray())
         446               0 :         return 0;
         447                 :
         448                 :     TBasicType promoteTo;
         449                 :
         450               0 :     switch (op) {
         451                 :         //
         452                 :         // Explicit conversions
         453                 :         //
         454                 :         case EOpConstructBool:
         455               0 :             promoteTo = EbtBool;
         456               0 :             break;
         457                 :         case EOpConstructFloat:
         458               0 :             promoteTo = EbtFloat;
         459               0 :             break;
         460                 :         case EOpConstructInt:
         461               0 :             promoteTo = EbtInt;
         462               0 :             break;
         463                 :         default:
         464                 :             //
         465                 :             // implicit conversions were removed from the language.
         466                 :             //
         467               0 :             if (type.getBasicType() != node->getType().getBasicType())
         468               0 :                 return 0;
         469                 :             //
         470                 :             // Size and structure could still differ, but that's
         471                 :             // handled by operator promotion.
         472                 :             //
         473               0 :             return node;
         474                 :     }
         475                 :
         476               0 :     if (node->getAsConstantUnion()) {
         477                 :
         478               0 :         return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
         479                 :     } else {
         480                 :
         481                 :         //
         482                 :         // Add a new newNode for the conversion.
         483                 :         //
         484               0 :         TIntermUnary* newNode = 0;
         485                 :
         486               0 :         TOperator newOp = EOpNull;
         487               0 :         switch (promoteTo) {
         488                 :             case EbtFloat:
         489               0 :                 switch (node->getBasicType()) {
         490               0 :                     case EbtInt:   newOp = EOpConvIntToFloat;  break;
         491               0 :                     case EbtBool:  newOp = EOpConvBoolToFloat; break;
         492                 :                     default:
         493               0 :                         infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
         494               0 :                         return 0;
         495                 :                 }
         496               0 :                 break;
         497                 :             case EbtBool:
         498               0 :                 switch (node->getBasicType()) {
         499               0 :                     case EbtInt:   newOp = EOpConvIntToBool;   break;
         500               0 :                     case EbtFloat: newOp = EOpConvFloatToBool; break;
         501                 :                     default:
         502               0 :                         infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
         503               0 :                         return 0;
         504                 :                 }
         505               0 :                 break;
         506                 :             case EbtInt:
         507               0 :                 switch (node->getBasicType()) {
         508               0 :                     case EbtBool:   newOp = EOpConvBoolToInt;  break;
         509               0 :                     case EbtFloat:  newOp = EOpConvFloatToInt; break;
         510                 :                     default:
         511               0 :                         infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
         512               0 :                         return 0;
         513                 :                 }
         514               0 :                 break;
         515                 :             default:
         516               0 :                 infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine());
         517               0 :                 return 0;
         518                 :         }
         519                 :
         520               0 :         TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
         521               0 :         newNode = new TIntermUnary(newOp, type);
         522               0 :         newNode->setLine(node->getLine());
         523               0 :         newNode->setOperand(node);
         524                 :
         525               0 :         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               0 : TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
         537                 : {
         538               0 :     if (left == 0 && right == 0)
         539               0 :         return 0;
         540                 :
         541               0 :     TIntermAggregate* aggNode = 0;
         542               0 :     if (left)
         543               0 :         aggNode = left->getAsAggregate();
         544               0 :     if (!aggNode || aggNode->getOp() != EOpNull) {
         545               0 :         aggNode = new TIntermAggregate;
         546               0 :         if (left)
         547               0 :             aggNode->getSequence().push_back(left);
         548                 :     }
         549                 :
         550               0 :     if (right)
         551               0 :         aggNode->getSequence().push_back(right);
         552                 :
         553               0 :     if (line != 0)
         554               0 :         aggNode->setLine(line);
         555                 :
         556               0 :     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               0 : TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
         565                 : {
         566               0 :     if (node == 0)
         567               0 :         return 0;
         568                 :
         569               0 :     TIntermAggregate* aggNode = new TIntermAggregate;
         570               0 :     aggNode->getSequence().push_back(node);
         571                 :
         572               0 :     if (line != 0)
         573               0 :         aggNode->setLine(line);
         574                 :     else
         575               0 :         aggNode->setLine(node->getLine());
         576                 :
         577               0 :     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               0 : 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               0 :     if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
         595               0 :         if (cond->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
         596               0 :             return nodePair.node1;
         597                 :         else
         598               0 :             return nodePair.node2;
         599                 :     }
         600                 :
         601               0 :     TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
         602               0 :     node->setLine(line);
         603                 :
         604               0 :     return node;
         605                 : }
         606                 :
         607                 :
         608               0 : TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
         609                 : {
         610               0 :     if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
         611               0 :         return right;
         612                 :     } else {
         613               0 :         TIntermTyped *commaAggregate = growAggregate(left, right, line);
         614               0 :         commaAggregate->getAsAggregate()->setOp(EOpComma);
         615               0 :         commaAggregate->setType(right->getType());
         616               0 :         commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
         617               0 :         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               0 : TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
         629                 : {
         630                 :     //
         631                 :     // Get compatible types.
         632                 :     //
         633               0 :     TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
         634               0 :     if (child)
         635               0 :         falseBlock = child;
         636                 :     else {
         637               0 :         child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
         638               0 :         if (child)
         639               0 :             trueBlock = child;
         640                 :         else
         641               0 :             return 0;
         642                 :     }
         643                 :
         644                 :     //
         645                 :     // See if all the operands are constant, then fold it otherwise not.
         646                 :     //
         647                 :
         648               0 :     if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
         649               0 :         if (cond->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
         650               0 :             return trueBlock;
         651                 :         else
         652               0 :             return falseBlock;
         653                 :     }
         654                 :
         655                 :     //
         656                 :     // Make a selection node.
         657                 :     //
         658               0 :     TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
         659               0 :     node->setLine(line);
         660                 :
         661               0 :     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               0 : TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line)
         671                 : {
         672               0 :     TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
         673               0 :     node->setLine(line);
         674                 :
         675               0 :     return node;
         676                 : }
         677                 :
         678               0 : TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
         679                 : {
         680                 :
         681               0 :     TIntermAggregate* node = new TIntermAggregate(EOpSequence);
         682                 :
         683               0 :     node->setLine(line);
         684                 :     TIntermConstantUnion* constIntNode;
         685               0 :     TIntermSequence &sequenceVector = node->getSequence();
         686                 :     ConstantUnion* unionArray;
         687                 :
         688               0 :     for (int i = 0; i < fields.num; i++) {
         689               0 :         unionArray = new ConstantUnion[1];
         690               0 :         unionArray->setIConst(fields.offsets[i]);
         691               0 :         constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
         692               0 :         sequenceVector.push_back(constIntNode);
         693                 :     }
         694                 :
         695               0 :     return node;
         696                 : }
         697                 :
         698                 : //
         699                 : // Create loop nodes.
         700                 : //
         701               0 : TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, TSourceLoc line)
         702                 : {
         703               0 :     TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
         704               0 :     node->setLine(line);
         705                 :
         706               0 :     return node;
         707                 : }
         708                 :
         709                 : //
         710                 : // Add branches.
         711                 : //
         712               0 : TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
         713                 : {
         714               0 :     return addBranch(branchOp, 0, line);
         715                 : }
         716                 :
         717               0 : TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
         718                 : {
         719               0 :     TIntermBranch* node = new TIntermBranch(branchOp, expression);
         720               0 :     node->setLine(line);
         721                 :
         722               0 :     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               0 : bool TIntermediate::postProcess(TIntermNode* root)
         730                 : {
         731               0 :     if (root == 0)
         732               0 :         return true;
         733                 :
         734                 :     //
         735                 :     // First, finish off the top level sequence, if any
         736                 :     //
         737               0 :     TIntermAggregate* aggRoot = root->getAsAggregate();
         738               0 :     if (aggRoot && aggRoot->getOp() == EOpNull)
         739               0 :         aggRoot->setOp(EOpSequence);
         740                 :
         741               0 :     return true;
         742                 : }
         743                 :
         744                 : //
         745                 : // This deletes the tree.
         746                 : //
         747               0 : void TIntermediate::remove(TIntermNode* root)
         748                 : {
         749               0 :     if (root)
         750               0 :         RemoveAllTreeNodes(root);
         751               0 : }
         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               0 : bool TIntermOperator::modifiesState() const
         765                 : {
         766               0 :     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               0 :             return true;
         781                 :         default:
         782               0 :             return false;
         783                 :     }
         784                 : }
         785                 :
         786                 : //
         787                 : // returns true if the operator is for one of the constructors
         788                 : //
         789               0 : bool TIntermOperator::isConstructor() const
         790                 : {
         791               0 :     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               0 :             return true;
         809                 :         default:
         810               0 :             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               0 : bool TIntermUnary::promote(TInfoSink&)
         820                 : {
         821               0 :     switch (op) {
         822                 :         case EOpLogicalNot:
         823               0 :             if (operand->getBasicType() != EbtBool)
         824               0 :                 return false;
         825               0 :             break;
         826                 :         case EOpNegative:
         827                 :         case EOpPostIncrement:
         828                 :         case EOpPostDecrement:
         829                 :         case EOpPreIncrement:
         830                 :         case EOpPreDecrement:
         831               0 :             if (operand->getBasicType() == EbtBool)
         832               0 :                 return false;
         833               0 :             break;
         834                 :
         835                 :             // operators for built-ins are already type checked against their prototype
         836                 :         case EOpAny:
         837                 :         case EOpAll:
         838                 :         case EOpVectorLogicalNot:
         839               0 :             return true;
         840                 :
         841                 :         default:
         842               0 :             if (operand->getBasicType() != EbtFloat)
         843               0 :                 return false;
         844                 :     }
         845                 :
         846               0 :     setType(operand->getType());
         847                 :
         848               0 :     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               0 : bool TIntermBinary::promote(TInfoSink& infoSink)
         858                 : {
         859                 :     // This function only handles scalars, vectors, and matrices.
         860               0 :     if (left->isArray() || right->isArray()) {
         861               0 :         infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine());
         862               0 :         return false;
         863                 :     }
         864                 :
         865                 :     // GLSL ES 2.0 does not support implicit type casting.
         866                 :     // So the basic type should always match.
         867               0 :     if (left->getBasicType() != right->getBasicType())
         868               0 :         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               0 :     setType(left->getType());
         875                 :
         876                 :     // The result gets promoted to the highest precision.
         877               0 :     TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
         878               0 :     getTypePointer()->setPrecision(higherPrecision);
         879                 :
         880                 :     // Binary operations results in temporary variables unless both
         881                 :     // operands are const.
         882               0 :     if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) {
         883               0 :         getTypePointer()->setQualifier(EvqTemporary);
         884                 :     }
         885                 :
         886               0 :     int size = std::max(left->getNominalSize(), right->getNominalSize());
         887                 :
         888                 :     //
         889                 :     // All scalars. Code after this test assumes this case is removed!
         890                 :     //
         891               0 :     if (size == 1) {
         892               0 :         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               0 :                 setType(TType(EbtBool, EbpUndefined));
         903               0 :                 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               0 :                 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
         912               0 :                     return false;
         913               0 :                 setType(TType(EbtBool, EbpUndefined));
         914               0 :                 break;
         915                 :
         916                 :             default:
         917               0 :                 break;
         918                 :         }
         919               0 :         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               0 :     if (left->getNominalSize() != right->getNominalSize()) {
         927                 :         // If the nominal size of operands do not match:
         928                 :         // One of them must be scalar.
         929               0 :         if (left->getNominalSize() != 1 && right->getNominalSize() != 1)
         930               0 :             return false;
         931                 :         // Operator cannot be of type pure assignment.
         932               0 :         if (op == EOpAssign || op == EOpInitialize)
         933               0 :             return false;
         934                 :     }
         935                 :
         936                 :     //
         937                 :     // Can these two operands be combined?
         938                 :     //
         939               0 :     TBasicType basicType = left->getBasicType();
         940               0 :     switch (op) {
         941                 :         case EOpMul:
         942               0 :             if (!left->isMatrix() && right->isMatrix()) {
         943               0 :                 if (left->isVector())
         944               0 :                     op = EOpVectorTimesMatrix;
         945                 :                 else {
         946               0 :                     op = EOpMatrixTimesScalar;
         947               0 :                     setType(TType(basicType, higherPrecision, EvqTemporary, size, true));
         948                 :                 }
         949               0 :             } else if (left->isMatrix() && !right->isMatrix()) {
         950               0 :                 if (right->isVector()) {
         951               0 :                     op = EOpMatrixTimesVector;
         952               0 :                     setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
         953                 :                 } else {
         954               0 :                     op = EOpMatrixTimesScalar;
         955                 :                 }
         956               0 :             } else if (left->isMatrix() && right->isMatrix()) {
         957               0 :                 op = EOpMatrixTimesMatrix;
         958               0 :             } else if (!left->isMatrix() && !right->isMatrix()) {
         959               0 :                 if (left->isVector() && right->isVector()) {
         960                 :                     // leave as component product
         961               0 :                 } else if (left->isVector() || right->isVector()) {
         962               0 :                     op = EOpVectorTimesScalar;
         963               0 :                     setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
         964                 :                 }
         965                 :             } else {
         966               0 :                 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
         967               0 :                 return false;
         968                 :             }
         969               0 :             break;
         970                 :         case EOpMulAssign:
         971               0 :             if (!left->isMatrix() && right->isMatrix()) {
         972               0 :                 if (left->isVector())
         973               0 :                     op = EOpVectorTimesMatrixAssign;
         974                 :                 else {
         975               0 :                     return false;
         976                 :                 }
         977               0 :             } else if (left->isMatrix() && !right->isMatrix()) {
         978               0 :                 if (right->isVector()) {
         979               0 :                     return false;
         980                 :                 } else {
         981               0 :                     op = EOpMatrixTimesScalarAssign;
         982                 :                 }
         983               0 :             } else if (left->isMatrix() && right->isMatrix()) {
         984               0 :                 op = EOpMatrixTimesMatrixAssign;
         985               0 :             } else if (!left->isMatrix() && !right->isMatrix()) {
         986               0 :                 if (left->isVector() && right->isVector()) {
         987                 :                     // leave as component product
         988               0 :                 } else if (left->isVector() || right->isVector()) {
         989               0 :                     if (! left->isVector())
         990               0 :                         return false;
         991               0 :                     op = EOpVectorTimesScalarAssign;
         992               0 :                     setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
         993                 :                 }
         994                 :             } else {
         995               0 :                 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
         996               0 :                 return false;
         997                 :             }
         998               0 :             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               0 :             if ((left->isMatrix() && right->isVector()) ||
        1009               0 :                 (left->isVector() && right->isMatrix()))
        1010               0 :                 return false;
        1011               0 :             setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
        1012               0 :             break;
        1013                 :
        1014                 :         case EOpEqual:
        1015                 :         case EOpNotEqual:
        1016                 :         case EOpLessThan:
        1017                 :         case EOpGreaterThan:
        1018                 :         case EOpLessThanEqual:
        1019                 :         case EOpGreaterThanEqual:
        1020               0 :             if ((left->isMatrix() && right->isVector()) ||
        1021               0 :                 (left->isVector() && right->isMatrix()))
        1022               0 :                 return false;
        1023               0 :             setType(TType(EbtBool, EbpUndefined));
        1024               0 :             break;
        1025                 :
        1026                 :         default:
        1027               0 :             return false;
        1028                 :     }
        1029                 :
        1030               0 :     return true;
        1031                 : }
        1032                 :
        1033               0 : bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
        1034                 : {
        1035               0 :     const TTypeList* fields = leftNodeType.getStruct();
        1036                 :
        1037               0 :     size_t structSize = fields->size();
        1038               0 :     int index = 0;
        1039                 :
        1040               0 :     for (size_t j = 0; j < structSize; j++) {
        1041               0 :         int size = (*fields)[j].type->getObjectSize();
        1042               0 :         for (int i = 0; i < size; i++) {
        1043               0 :             if ((*fields)[j].type->getBasicType() == EbtStruct) {
        1044               0 :                 if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index]))
        1045               0 :                     return false;
        1046                 :             } else {
        1047               0 :                 if (leftUnionArray[index] != rightUnionArray[index])
        1048               0 :                     return false;
        1049               0 :                 index++;
        1050                 :             }
        1051                 :
        1052                 :         }
        1053                 :     }
        1054               0 :     return true;
        1055                 : }
        1056                 :
        1057               0 : bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
        1058                 : {
        1059               0 :     if (leftNodeType.isArray()) {
        1060               0 :         TType typeWithoutArrayness = leftNodeType;
        1061               0 :         typeWithoutArrayness.clearArrayness();
        1062                 :
        1063               0 :         int arraySize = leftNodeType.getArraySize();
        1064                 :
        1065               0 :         for (int i = 0; i < arraySize; ++i) {
        1066               0 :             int offset = typeWithoutArrayness.getObjectSize() * i;
        1067               0 :             if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
        1068               0 :                 return false;
        1069                 :         }
        1070                 :     } else
        1071               0 :         return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
        1072                 :
        1073               0 :     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               0 : TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
        1084                 : {
        1085               0 :     ConstantUnion *unionArray = getUnionArrayPointer();
        1086               0 :     int objectSize = getType().getObjectSize();
        1087                 :
        1088               0 :     if (constantNode) {  // binary operations
        1089               0 :         TIntermConstantUnion *node = constantNode->getAsConstantUnion();
        1090               0 :         ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
        1091               0 :         TType returnType = getType();
        1092                 :
        1093                 :         // for a case like float f = 1.2 + vec4(2,3,4,5);
        1094               0 :         if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
        1095               0 :             rightUnionArray = new ConstantUnion[objectSize];
        1096               0 :             for (int i = 0; i < objectSize; ++i)
        1097               0 :                 rightUnionArray[i] = *node->getUnionArrayPointer();
        1098               0 :             returnType = getType();
        1099               0 :         } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
        1100                 :             // for a case like float f = vec4(2,3,4,5) + 1.2;
        1101               0 :             unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
        1102               0 :             for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
        1103               0 :                 unionArray[i] = *getUnionArrayPointer();
        1104               0 :             returnType = node->getType();
        1105               0 :             objectSize = constantNode->getType().getObjectSize();
        1106                 :         }
        1107                 :
        1108               0 :         ConstantUnion* tempConstArray = 0;
        1109                 :         TIntermConstantUnion *tempNode;
        1110                 :
        1111               0 :         bool boolNodeFlag = false;
        1112               0 :         switch(op) {
        1113                 :             case EOpAdd:
        1114               0 :                 tempConstArray = new ConstantUnion[objectSize];
        1115                 :                 {// support MSVC++6.0
        1116               0 :                     for (int i = 0; i < objectSize; i++)
        1117               0 :                         tempConstArray[i] = unionArray[i] + rightUnionArray[i];
        1118                 :                 }
        1119               0 :                 break;
        1120                 :             case EOpSub:
        1121               0 :                 tempConstArray = new ConstantUnion[objectSize];
        1122                 :                 {// support MSVC++6.0
        1123               0 :                     for (int i = 0; i < objectSize; i++)
        1124               0 :                         tempConstArray[i] = unionArray[i] - rightUnionArray[i];
        1125                 :                 }
        1126               0 :                 break;
        1127                 :
        1128                 :             case EOpMul:
        1129                 :             case EOpVectorTimesScalar:
        1130                 :             case EOpMatrixTimesScalar:
        1131               0 :                 tempConstArray = new ConstantUnion[objectSize];
        1132                 :                 {// support MSVC++6.0
        1133               0 :                     for (int i = 0; i < objectSize; i++)
        1134               0 :                         tempConstArray[i] = unionArray[i] * rightUnionArray[i];
        1135                 :                 }
        1136               0 :                 break;
        1137                 :             case EOpMatrixTimesMatrix:
        1138               0 :                 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
        1139               0 :                     infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
        1140               0 :                     return 0;
        1141                 :                 }
        1142                 :                 {// support MSVC++6.0
        1143               0 :                     int size = getNominalSize();
        1144               0 :                     tempConstArray = new ConstantUnion[size*size];
        1145               0 :                     for (int row = 0; row < size; row++) {
        1146               0 :                         for (int column = 0; column < size; column++) {
        1147               0 :                             tempConstArray[size * column + row].setFConst(0.0f);
        1148               0 :                             for (int i = 0; i < size; i++) {
        1149               0 :                                 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               0 :                 break;
        1155                 :             case EOpDiv:
        1156               0 :                 tempConstArray = new ConstantUnion[objectSize];
        1157                 :                 {// support MSVC++6.0
        1158               0 :                     for (int i = 0; i < objectSize; i++) {
        1159               0 :                         switch (getType().getBasicType()) {
        1160                 :             case EbtFloat:
        1161               0 :                 if (rightUnionArray[i] == 0.0f) {
        1162               0 :                     infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
        1163               0 :                     tempConstArray[i].setFConst(FLT_MAX);
        1164                 :                 } else
        1165               0 :                     tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
        1166               0 :                 break;
        1167                 :
        1168                 :             case EbtInt:
        1169               0 :                 if (rightUnionArray[i] == 0) {
        1170               0 :                     infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
        1171               0 :                     tempConstArray[i].setIConst(INT_MAX);
        1172                 :                 } else
        1173               0 :                     tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
        1174               0 :                 break;
        1175                 :             default:
        1176               0 :                 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
        1177               0 :                 return 0;
        1178                 :                         }
        1179                 :                     }
        1180                 :                 }
        1181               0 :                 break;
        1182                 :
        1183                 :             case EOpMatrixTimesVector:
        1184               0 :                 if (node->getBasicType() != EbtFloat) {
        1185               0 :                     infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
        1186               0 :                     return 0;
        1187                 :                 }
        1188               0 :                 tempConstArray = new ConstantUnion[getNominalSize()];
        1189                 :
        1190                 :                 {// support MSVC++6.0
        1191               0 :                     for (int size = getNominalSize(), i = 0; i < size; i++) {
        1192               0 :                         tempConstArray[i].setFConst(0.0f);
        1193               0 :                         for (int j = 0; j < size; j++) {
        1194               0 :                             tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
        1195                 :                         }
        1196                 :                     }
        1197                 :                 }
        1198                 :
        1199               0 :                 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
        1200               0 :                 tempNode->setLine(getLine());
        1201                 :
        1202               0 :                 return tempNode;
        1203                 :
        1204                 :             case EOpVectorTimesMatrix:
        1205               0 :                 if (getType().getBasicType() != EbtFloat) {
        1206               0 :                     infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
        1207               0 :                     return 0;
        1208                 :                 }
        1209                 :
        1210               0 :                 tempConstArray = new ConstantUnion[getNominalSize()];
        1211                 :                 {// support MSVC++6.0
        1212               0 :                     for (int size = getNominalSize(), i = 0; i < size; i++) {
        1213               0 :                         tempConstArray[i].setFConst(0.0f);
        1214               0 :                         for (int j = 0; j < size; j++) {
        1215               0 :                             tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
        1216                 :                         }
        1217                 :                     }
        1218                 :                 }
        1219               0 :                 break;
        1220                 :
        1221                 :             case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
        1222               0 :                 tempConstArray = new ConstantUnion[objectSize];
        1223                 :                 {// support MSVC++6.0
        1224               0 :                     for (int i = 0; i < objectSize; i++)
        1225               0 :                         tempConstArray[i] = unionArray[i] && rightUnionArray[i];
        1226                 :                 }
        1227               0 :                 break;
        1228                 :
        1229                 :             case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
        1230               0 :                 tempConstArray = new ConstantUnion[objectSize];
        1231                 :                 {// support MSVC++6.0
        1232               0 :                     for (int i = 0; i < objectSize; i++)
        1233               0 :                         tempConstArray[i] = unionArray[i] || rightUnionArray[i];
        1234                 :                 }
        1235               0 :                 break;
        1236                 :
        1237                 :             case EOpLogicalXor:
        1238               0 :                 tempConstArray = new ConstantUnion[objectSize];
        1239                 :                 {// support MSVC++6.0
        1240               0 :                     for (int i = 0; i < objectSize; i++)
        1241               0 :                         switch (getType().getBasicType()) {
        1242               0 :             case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
        1243               0 :             default: assert(false && "Default missing");
        1244                 :                     }
        1245                 :                 }
        1246               0 :                 break;
        1247                 :
        1248                 :             case EOpLessThan:
        1249               0 :                 assert(objectSize == 1);
        1250               0 :                 tempConstArray = new ConstantUnion[1];
        1251               0 :                 tempConstArray->setBConst(*unionArray < *rightUnionArray);
        1252               0 :                 returnType = TType(EbtBool, EbpUndefined, EvqConst);
        1253               0 :                 break;
        1254                 :             case EOpGreaterThan:
        1255               0 :                 assert(objectSize == 1);
        1256               0 :                 tempConstArray = new ConstantUnion[1];
        1257               0 :                 tempConstArray->setBConst(*unionArray > *rightUnionArray);
        1258               0 :                 returnType = TType(EbtBool, EbpUndefined, EvqConst);
        1259               0 :                 break;
        1260                 :             case EOpLessThanEqual:
        1261                 :                 {
        1262               0 :                     assert(objectSize == 1);
        1263                 :                     ConstantUnion constant;
        1264               0 :                     constant.setBConst(*unionArray > *rightUnionArray);
        1265               0 :                     tempConstArray = new ConstantUnion[1];
        1266               0 :                     tempConstArray->setBConst(!constant.getBConst());
        1267               0 :                     returnType = TType(EbtBool, EbpUndefined, EvqConst);
        1268               0 :                     break;
        1269                 :                 }
        1270                 :             case EOpGreaterThanEqual:
        1271                 :                 {
        1272               0 :                     assert(objectSize == 1);
        1273                 :                     ConstantUnion constant;
        1274               0 :                     constant.setBConst(*unionArray < *rightUnionArray);
        1275               0 :                     tempConstArray = new ConstantUnion[1];
        1276               0 :                     tempConstArray->setBConst(!constant.getBConst());
        1277               0 :                     returnType = TType(EbtBool, EbpUndefined, EvqConst);
        1278               0 :                     break;
        1279                 :                 }
        1280                 :
        1281                 :             case EOpEqual:
        1282               0 :                 if (getType().getBasicType() == EbtStruct) {
        1283               0 :                     if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
        1284               0 :                         boolNodeFlag = true;
        1285                 :                 } else {
        1286               0 :                     for (int i = 0; i < objectSize; i++) {
        1287               0 :                         if (unionArray[i] != rightUnionArray[i]) {
        1288               0 :                             boolNodeFlag = true;
        1289               0 :                             break;  // break out of for loop
        1290                 :                         }
        1291                 :                     }
        1292                 :                 }
        1293                 :
        1294               0 :                 tempConstArray = new ConstantUnion[1];
        1295               0 :                 if (!boolNodeFlag) {
        1296               0 :                     tempConstArray->setBConst(true);
        1297                 :                 }
        1298                 :                 else {
        1299               0 :                     tempConstArray->setBConst(false);
        1300                 :                 }
        1301                 :
        1302               0 :                 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
        1303               0 :                 tempNode->setLine(getLine());
        1304                 :
        1305               0 :                 return tempNode;
        1306                 :
        1307                 :             case EOpNotEqual:
        1308               0 :                 if (getType().getBasicType() == EbtStruct) {
        1309               0 :                     if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
        1310               0 :                         boolNodeFlag = true;
        1311                 :                 } else {
        1312               0 :                     for (int i = 0; i < objectSize; i++) {
        1313               0 :                         if (unionArray[i] == rightUnionArray[i]) {
        1314               0 :                             boolNodeFlag = true;
        1315               0 :                             break;  // break out of for loop
        1316                 :                         }
        1317                 :                     }
        1318                 :                 }
        1319                 :
        1320               0 :                 tempConstArray = new ConstantUnion[1];
        1321               0 :                 if (!boolNodeFlag) {
        1322               0 :                     tempConstArray->setBConst(true);
        1323                 :                 }
        1324                 :                 else {
        1325               0 :                     tempConstArray->setBConst(false);
        1326                 :                 }
        1327                 :
        1328               0 :                 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
        1329               0 :                 tempNode->setLine(getLine());
        1330                 :
        1331               0 :                 return tempNode;
        1332                 :
        1333                 :             default:
        1334               0 :                 infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
        1335               0 :                 return 0;
        1336                 :         }
        1337               0 :         tempNode = new TIntermConstantUnion(tempConstArray, returnType);
        1338               0 :         tempNode->setLine(getLine());
        1339                 :
        1340               0 :         return tempNode;
        1341                 :     } else {
        1342                 :         //
        1343                 :         // Do unary operations
        1344                 :         //
        1345               0 :         TIntermConstantUnion *newNode = 0;
        1346               0 :         ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
        1347               0 :         for (int i = 0; i < objectSize; i++) {
        1348               0 :             switch(op) {
        1349                 :                 case EOpNegative:
        1350               0 :                     switch (getType().getBasicType()) {
        1351               0 :                         case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
        1352               0 :                         case EbtInt:   tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
        1353                 :                         default:
        1354               0 :                             infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
        1355               0 :                             return 0;
        1356                 :                     }
        1357               0 :                     break;
        1358                 :                 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
        1359               0 :                     switch (getType().getBasicType()) {
        1360               0 :                         case EbtBool:  tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
        1361                 :                         default:
        1362               0 :                             infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
        1363               0 :                             return 0;
        1364                 :                     }
        1365               0 :                     break;
        1366                 :                 default:
        1367               0 :                     return 0;
        1368                 :             }
        1369                 :         }
        1370               0 :         newNode = new TIntermConstantUnion(tempConstArray, getType());
        1371               0 :         newNode->setLine(getLine());
        1372               0 :         return newNode;
        1373                 :     }
        1374                 :
        1375                 :     return this;
        1376                 : }
        1377                 :
        1378               0 : TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
        1379                 : {
        1380               0 :     ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
        1381               0 :     int size = node->getType().getObjectSize();
        1382                 :
        1383               0 :     ConstantUnion *leftUnionArray = new ConstantUnion[size];
        1384                 :
        1385               0 :     for (int i=0; i < size; i++) {
        1386                 :
        1387               0 :         switch (promoteTo) {
        1388                 :             case EbtFloat:
        1389               0 :                 switch (node->getType().getBasicType()) {
        1390                 :                     case EbtInt:
        1391               0 :                         leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getIConst()));
        1392               0 :                         break;
        1393                 :                     case EbtBool:
        1394               0 :                         leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getBConst()));
        1395               0 :                         break;
        1396                 :                     case EbtFloat:
        1397               0 :                         leftUnionArray[i] = rightUnionArray[i];
        1398               0 :                         break;
        1399                 :                     default:
        1400               0 :                         infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
        1401               0 :                         return 0;
        1402                 :                 }
        1403               0 :                 break;
        1404                 :             case EbtInt:
        1405               0 :                 switch (node->getType().getBasicType()) {
        1406                 :                     case EbtInt:
        1407               0 :                         leftUnionArray[i] = rightUnionArray[i];
        1408               0 :                         break;
        1409                 :                     case EbtBool:
        1410               0 :                         leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getBConst()));
        1411               0 :                         break;
        1412                 :                     case EbtFloat:
        1413               0 :                         leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getFConst()));
        1414               0 :                         break;
        1415                 :                     default:
        1416               0 :                         infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
        1417               0 :                         return 0;
        1418                 :                 }
        1419               0 :                 break;
        1420                 :             case EbtBool:
        1421               0 :                 switch (node->getType().getBasicType()) {
        1422                 :                     case EbtInt:
        1423               0 :                         leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0);
        1424               0 :                         break;
        1425                 :                     case EbtBool:
        1426               0 :                         leftUnionArray[i] = rightUnionArray[i];
        1427               0 :                         break;
        1428                 :                     case EbtFloat:
        1429               0 :                         leftUnionArray[i].setBConst(rightUnionArray[i].getFConst() != 0.0f);
        1430               0 :                         break;
        1431                 :                     default:
        1432               0 :                         infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
        1433               0 :                         return 0;
        1434                 :                 }
        1435                 :
        1436               0 :                 break;
        1437                 :             default:
        1438               0 :                 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
        1439               0 :                 return 0;
        1440                 :         }
        1441                 :
        1442                 :     }
        1443                 :
        1444               0 :     const TType& t = node->getType();
        1445                 :
        1446               0 :     return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
        1447                 : }
        1448                 :
        1449               0 : void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
        1450                 : {
        1451               0 :     assert(!pragmaTable);
        1452               0 :     pragmaTable = new TPragmaTable();
        1453               0 :     *pragmaTable = pTable;
        1454               0 : }

Generated by: LCOV version 1.7