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