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

       1                 : //
       2                 : // Copyright (c) 2002-2011 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                 : #include "compiler/OutputGLSLBase.h"
       8                 : #include "compiler/compilerdebug.h"
       9                 : 
      10                 : namespace
      11                 : {
      12               0 : TString getTypeName(const TType& type)
      13                 : {
      14               0 :     TInfoSinkBase out;
      15               0 :     if (type.isMatrix())
      16                 :     {
      17               0 :         out << "mat";
      18               0 :         out << type.getNominalSize();
      19                 :     }
      20               0 :     else if (type.isVector())
      21                 :     {
      22               0 :         switch (type.getBasicType())
      23                 :         {
      24               0 :             case EbtFloat: out << "vec"; break;
      25               0 :             case EbtInt: out << "ivec"; break;
      26               0 :             case EbtBool: out << "bvec"; break;
      27               0 :             default: UNREACHABLE(); break;
      28                 :         }
      29               0 :         out << type.getNominalSize();
      30                 :     }
      31                 :     else
      32                 :     {
      33               0 :         if (type.getBasicType() == EbtStruct)
      34               0 :             out << type.getTypeName();
      35                 :         else
      36               0 :             out << type.getBasicString();
      37                 :     }
      38               0 :     return TString(out.c_str());
      39                 : }
      40                 : 
      41               0 : TString arrayBrackets(const TType& type)
      42                 : {
      43               0 :     ASSERT(type.isArray());
      44               0 :     TInfoSinkBase out;
      45               0 :     out << "[" << type.getArraySize() << "]";
      46               0 :     return TString(out.c_str());
      47                 : }
      48                 : 
      49               0 : bool isSingleStatement(TIntermNode* node) {
      50               0 :     if (const TIntermAggregate* aggregate = node->getAsAggregate())
      51                 :     {
      52               0 :         return (aggregate->getOp() != EOpFunction) &&
      53               0 :                (aggregate->getOp() != EOpSequence);
      54                 :     }
      55               0 :     else if (const TIntermSelection* selection = node->getAsSelectionNode())
      56                 :     {
      57                 :         // Ternary operators are usually part of an assignment operator.
      58                 :         // This handles those rare cases in which they are all by themselves.
      59               0 :         return selection->usesTernaryOperator();
      60                 :     }
      61               0 :     else if (node->getAsLoopNode())
      62                 :     {
      63               0 :         return false;
      64                 :     }
      65               0 :     return true;
      66                 : }
      67                 : }  // namespace
      68                 : 
      69               0 : TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink)
      70                 :     : TIntermTraverser(true, true, true),
      71                 :       mObjSink(objSink),
      72               0 :       mDeclaringVariables(false)
      73                 : {
      74               0 : }
      75                 : 
      76               0 : void TOutputGLSLBase::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr)
      77                 : {
      78               0 :     TInfoSinkBase& out = objSink();
      79               0 :     if (visit == PreVisit && preStr)
      80                 :     {
      81               0 :         out << preStr;
      82                 :     }
      83               0 :     else if (visit == InVisit && inStr)
      84                 :     {
      85               0 :         out << inStr;
      86                 :     }
      87               0 :     else if (visit == PostVisit && postStr)
      88                 :     {
      89               0 :         out << postStr;
      90                 :     }
      91               0 : }
      92                 : 
      93               0 : void TOutputGLSLBase::writeVariableType(const TType& type)
      94                 : {
      95               0 :     TInfoSinkBase& out = objSink();
      96               0 :     TQualifier qualifier = type.getQualifier();
      97                 :     // TODO(alokp): Validate qualifier for variable declarations.
      98               0 :     if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
      99               0 :         out << type.getQualifierString() << " ";
     100                 :     // Declare the struct if we have not done so already.
     101               0 :     if ((type.getBasicType() == EbtStruct) &&
     102               0 :         (mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end()))
     103                 :     {
     104               0 :         out << "struct " << type.getTypeName() << "{\n";
     105               0 :         const TTypeList* structure = type.getStruct();
     106               0 :         ASSERT(structure != NULL);
     107               0 :         for (size_t i = 0; i < structure->size(); ++i)
     108                 :         {
     109               0 :             const TType* fieldType = (*structure)[i].type;
     110               0 :             ASSERT(fieldType != NULL);
     111               0 :             if (writeVariablePrecision(fieldType->getPrecision()))
     112               0 :                 out << " ";
     113               0 :             out << getTypeName(*fieldType) << " " << fieldType->getFieldName();
     114               0 :             if (fieldType->isArray())
     115               0 :                 out << arrayBrackets(*fieldType);
     116               0 :             out << ";\n";
     117                 :         }
     118               0 :         out << "}";
     119               0 :         mDeclaredStructs.insert(type.getTypeName());
     120                 :     }
     121                 :     else
     122                 :     {
     123               0 :         if (writeVariablePrecision(type.getPrecision()))
     124               0 :             out << " ";
     125               0 :         out << getTypeName(type);
     126                 :     }
     127               0 : }
     128                 : 
     129               0 : void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args)
     130                 : {
     131               0 :     TInfoSinkBase& out = objSink();
     132               0 :     for (TIntermSequence::const_iterator iter = args.begin();
     133               0 :          iter != args.end(); ++iter)
     134                 :     {
     135               0 :         const TIntermSymbol* arg = (*iter)->getAsSymbolNode();
     136               0 :         ASSERT(arg != NULL);
     137                 : 
     138               0 :         const TType& type = arg->getType();
     139               0 :         writeVariableType(type);
     140                 : 
     141               0 :         const TString& name = arg->getSymbol();
     142               0 :         if (!name.empty())
     143               0 :             out << " " << name;
     144               0 :         if (type.isArray())
     145               0 :             out << arrayBrackets(type);
     146                 : 
     147                 :         // Put a comma if this is not the last argument.
     148               0 :         if (iter != args.end() - 1)
     149               0 :             out << ", ";
     150                 :     }
     151               0 : }
     152                 : 
     153               0 : const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type,
     154                 :                                                          const ConstantUnion* pConstUnion)
     155                 : {
     156               0 :     TInfoSinkBase& out = objSink();
     157                 : 
     158               0 :     if (type.getBasicType() == EbtStruct)
     159                 :     {
     160               0 :         out << type.getTypeName() << "(";
     161               0 :         const TTypeList* structure = type.getStruct();
     162               0 :         ASSERT(structure != NULL);
     163               0 :         for (size_t i = 0; i < structure->size(); ++i)
     164                 :         {
     165               0 :             const TType* fieldType = (*structure)[i].type;
     166               0 :             ASSERT(fieldType != NULL);
     167               0 :             pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
     168               0 :             if (i != structure->size() - 1) out << ", ";
     169                 :         }
     170               0 :         out << ")";
     171                 :     }
     172                 :     else
     173                 :     {
     174               0 :         int size = type.getObjectSize();
     175               0 :         bool writeType = size > 1;
     176               0 :         if (writeType) out << getTypeName(type) << "(";
     177               0 :         for (int i = 0; i < size; ++i, ++pConstUnion)
     178                 :         {
     179               0 :             switch (pConstUnion->getType())
     180                 :             {
     181               0 :                 case EbtFloat: out << pConstUnion->getFConst(); break;
     182               0 :                 case EbtInt: out << pConstUnion->getIConst(); break;
     183               0 :                 case EbtBool: out << pConstUnion->getBConst(); break;
     184               0 :                 default: UNREACHABLE();
     185                 :             }
     186               0 :             if (i != size - 1) out << ", ";
     187                 :         }
     188               0 :         if (writeType) out << ")";
     189                 :     }
     190               0 :     return pConstUnion;
     191                 : }
     192                 : 
     193               0 : void TOutputGLSLBase::visitSymbol(TIntermSymbol* node)
     194                 : {
     195               0 :     TInfoSinkBase& out = objSink();
     196               0 :     if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node))
     197               0 :         out << mLoopUnroll.GetLoopIndexValue(node);
     198                 :     else
     199               0 :         out << node->getSymbol();
     200                 : 
     201               0 :     if (mDeclaringVariables && node->getType().isArray())
     202               0 :         out << arrayBrackets(node->getType());
     203               0 : }
     204                 : 
     205               0 : void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion* node)
     206                 : {
     207               0 :     writeConstantUnion(node->getType(), node->getUnionArrayPointer());
     208               0 : }
     209                 : 
     210               0 : bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
     211                 : {
     212               0 :     bool visitChildren = true;
     213               0 :     TInfoSinkBase& out = objSink();
     214               0 :     switch (node->getOp())
     215                 :     {
     216                 :         case EOpInitialize:
     217               0 :             if (visit == InVisit)
     218                 :             {
     219               0 :                 out << " = ";
     220                 :                 // RHS of initialize is not being declared.
     221               0 :                 mDeclaringVariables = false;
     222                 :             }
     223               0 :             break;
     224               0 :         case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break;
     225               0 :         case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break;
     226               0 :         case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break;
     227               0 :         case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break;
     228                 :         // Notice the fall-through.
     229                 :         case EOpMulAssign: 
     230                 :         case EOpVectorTimesMatrixAssign:
     231                 :         case EOpVectorTimesScalarAssign:
     232                 :         case EOpMatrixTimesScalarAssign:
     233                 :         case EOpMatrixTimesMatrixAssign:
     234               0 :             writeTriplet(visit, "(", " *= ", ")");
     235               0 :             break;
     236                 : 
     237                 :         case EOpIndexDirect:
     238                 :         case EOpIndexIndirect:
     239               0 :             writeTriplet(visit, NULL, "[", "]");
     240               0 :             break;
     241                 :         case EOpIndexDirectStruct:
     242               0 :             if (visit == InVisit)
     243                 :             {
     244               0 :                 out << ".";
     245                 :                 // TODO(alokp): ASSERT
     246               0 :                 out << node->getType().getFieldName();
     247               0 :                 visitChildren = false;
     248                 :             }
     249               0 :             break;
     250                 :         case EOpVectorSwizzle:
     251               0 :             if (visit == InVisit)
     252                 :             {
     253               0 :                 out << ".";
     254               0 :                 TIntermAggregate* rightChild = node->getRight()->getAsAggregate();
     255               0 :                 TIntermSequence& sequence = rightChild->getSequence();
     256               0 :                 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
     257                 :                 {
     258               0 :                     TIntermConstantUnion* element = (*sit)->getAsConstantUnion();
     259               0 :                     ASSERT(element->getBasicType() == EbtInt);
     260               0 :                     ASSERT(element->getNominalSize() == 1);
     261               0 :                     const ConstantUnion& data = element->getUnionArrayPointer()[0];
     262               0 :                     ASSERT(data.getType() == EbtInt);
     263               0 :                     switch (data.getIConst())
     264                 :                     {
     265               0 :                         case 0: out << "x"; break;
     266               0 :                         case 1: out << "y"; break;
     267               0 :                         case 2: out << "z"; break;
     268               0 :                         case 3: out << "w"; break;
     269               0 :                         default: UNREACHABLE(); break;
     270                 :                     }
     271                 :                 }
     272               0 :                 visitChildren = false;
     273                 :             }
     274               0 :             break;
     275                 : 
     276               0 :         case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break;
     277               0 :         case EOpSub: writeTriplet(visit, "(", " - ", ")"); break;
     278               0 :         case EOpMul: writeTriplet(visit, "(", " * ", ")"); break;
     279               0 :         case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break;
     280               0 :         case EOpMod: UNIMPLEMENTED(); break;
     281               0 :         case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break;
     282               0 :         case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break;
     283               0 :         case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break;
     284               0 :         case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break;
     285               0 :         case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break;
     286               0 :         case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break;
     287                 : 
     288                 :         // Notice the fall-through.
     289                 :         case EOpVectorTimesScalar:
     290                 :         case EOpVectorTimesMatrix:
     291                 :         case EOpMatrixTimesVector:
     292                 :         case EOpMatrixTimesScalar:
     293                 :         case EOpMatrixTimesMatrix:
     294               0 :             writeTriplet(visit, "(", " * ", ")");
     295               0 :             break;
     296                 : 
     297               0 :         case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break;
     298               0 :         case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break;
     299               0 :         case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break;
     300               0 :         default: UNREACHABLE(); break;
     301                 :     }
     302                 : 
     303               0 :     return visitChildren;
     304                 : }
     305                 : 
     306               0 : bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node)
     307                 : {
     308               0 :     TString preString;
     309               0 :     TString postString = ")";
     310                 : 
     311               0 :     switch (node->getOp())
     312                 :     {
     313               0 :         case EOpNegative: preString = "(-"; break;
     314               0 :         case EOpVectorLogicalNot: preString = "not("; break;
     315               0 :         case EOpLogicalNot: preString = "(!"; break;
     316                 : 
     317               0 :         case EOpPostIncrement: preString = "("; postString = "++)"; break;
     318               0 :         case EOpPostDecrement: preString = "("; postString = "--)"; break;
     319               0 :         case EOpPreIncrement: preString = "(++"; break;
     320               0 :         case EOpPreDecrement: preString = "(--"; break;
     321                 : 
     322                 :         case EOpConvIntToBool:
     323                 :         case EOpConvFloatToBool:
     324               0 :             switch (node->getOperand()->getType().getNominalSize())
     325                 :             {
     326               0 :                 case 1: preString =  "bool(";  break;
     327               0 :                 case 2: preString = "bvec2("; break;
     328               0 :                 case 3: preString = "bvec3("; break;
     329               0 :                 case 4: preString = "bvec4("; break;
     330               0 :                 default: UNREACHABLE();
     331                 :             }
     332               0 :             break;
     333                 :         case EOpConvBoolToFloat:
     334                 :         case EOpConvIntToFloat:
     335               0 :             switch (node->getOperand()->getType().getNominalSize())
     336                 :             {
     337               0 :                 case 1: preString = "float(";  break;
     338               0 :                 case 2: preString = "vec2("; break;
     339               0 :                 case 3: preString = "vec3("; break;
     340               0 :                 case 4: preString = "vec4("; break;
     341               0 :                 default: UNREACHABLE();
     342                 :             }
     343               0 :             break;
     344                 :         case EOpConvFloatToInt:
     345                 :         case EOpConvBoolToInt:
     346               0 :             switch (node->getOperand()->getType().getNominalSize())
     347                 :             {
     348               0 :                 case 1: preString = "int(";  break;
     349               0 :                 case 2: preString = "ivec2("; break;
     350               0 :                 case 3: preString = "ivec3("; break;
     351               0 :                 case 4: preString = "ivec4("; break;
     352               0 :                 default: UNREACHABLE();
     353                 :             }
     354               0 :             break;
     355                 : 
     356               0 :         case EOpRadians: preString = "radians("; break;
     357               0 :         case EOpDegrees: preString = "degrees("; break;
     358               0 :         case EOpSin: preString = "sin("; break;
     359               0 :         case EOpCos: preString = "cos("; break;
     360               0 :         case EOpTan: preString = "tan("; break;
     361               0 :         case EOpAsin: preString = "asin("; break;
     362               0 :         case EOpAcos: preString = "acos("; break;
     363               0 :         case EOpAtan: preString = "atan("; break;
     364                 : 
     365               0 :         case EOpExp: preString = "exp("; break;
     366               0 :         case EOpLog: preString = "log("; break;
     367               0 :         case EOpExp2: preString = "exp2("; break;
     368               0 :         case EOpLog2: preString = "log2("; break;
     369               0 :         case EOpSqrt: preString = "sqrt("; break;
     370               0 :         case EOpInverseSqrt: preString = "inversesqrt("; break;
     371                 : 
     372               0 :         case EOpAbs: preString = "abs("; break;
     373               0 :         case EOpSign: preString = "sign("; break;
     374               0 :         case EOpFloor: preString = "floor("; break;
     375               0 :         case EOpCeil: preString = "ceil("; break;
     376               0 :         case EOpFract: preString = "fract("; break;
     377                 : 
     378               0 :         case EOpLength: preString = "length("; break;
     379               0 :         case EOpNormalize: preString = "normalize("; break;
     380                 : 
     381               0 :         case EOpDFdx: preString = "dFdx("; break;
     382               0 :         case EOpDFdy: preString = "dFdy("; break;
     383               0 :         case EOpFwidth: preString = "fwidth("; break;
     384                 : 
     385               0 :         case EOpAny: preString = "any("; break;
     386               0 :         case EOpAll: preString = "all("; break;
     387                 : 
     388               0 :         default: UNREACHABLE(); break;
     389                 :     }
     390                 : 
     391               0 :     if (visit == PreVisit && node->getUseEmulatedFunction())
     392               0 :         preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
     393               0 :     writeTriplet(visit, preString.c_str(), NULL, postString.c_str());
     394                 : 
     395               0 :     return true;
     396                 : }
     397                 : 
     398               0 : bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node)
     399                 : {
     400               0 :     TInfoSinkBase& out = objSink();
     401                 : 
     402               0 :     if (node->usesTernaryOperator())
     403                 :     {
     404                 :         // Notice two brackets at the beginning and end. The outer ones
     405                 :         // encapsulate the whole ternary expression. This preserves the
     406                 :         // order of precedence when ternary expressions are used in a
     407                 :         // compound expression, i.e., c = 2 * (a < b ? 1 : 2).
     408               0 :         out << "((";
     409               0 :         node->getCondition()->traverse(this);
     410               0 :         out << ") ? (";
     411               0 :         node->getTrueBlock()->traverse(this);
     412               0 :         out << ") : (";
     413               0 :         node->getFalseBlock()->traverse(this);
     414               0 :         out << "))";
     415                 :     }
     416                 :     else
     417                 :     {
     418               0 :         out << "if (";
     419               0 :         node->getCondition()->traverse(this);
     420               0 :         out << ")\n";
     421                 : 
     422               0 :         incrementDepth();
     423               0 :         visitCodeBlock(node->getTrueBlock());
     424                 : 
     425               0 :         if (node->getFalseBlock())
     426                 :         {
     427               0 :             out << "else\n";
     428               0 :             visitCodeBlock(node->getFalseBlock());
     429                 :         }
     430               0 :         decrementDepth();
     431                 :     }
     432               0 :     return false;
     433                 : }
     434                 : 
     435               0 : bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
     436                 : {
     437               0 :     bool visitChildren = true;
     438               0 :     TInfoSinkBase& out = objSink();
     439               0 :     TString preString;
     440               0 :     bool delayedWrite = false;
     441               0 :     switch (node->getOp())
     442                 :     {
     443                 :         case EOpSequence: {
     444                 :             // Scope the sequences except when at the global scope.
     445               0 :             if (depth > 0) out << "{\n";
     446                 : 
     447               0 :             incrementDepth();
     448               0 :             const TIntermSequence& sequence = node->getSequence();
     449               0 :             for (TIntermSequence::const_iterator iter = sequence.begin();
     450               0 :                  iter != sequence.end(); ++iter)
     451                 :             {
     452               0 :                 TIntermNode* node = *iter;
     453               0 :                 ASSERT(node != NULL);
     454               0 :                 node->traverse(this);
     455                 : 
     456               0 :                 if (isSingleStatement(node))
     457               0 :                     out << ";\n";
     458                 :             }
     459               0 :             decrementDepth();
     460                 : 
     461                 :             // Scope the sequences except when at the global scope.
     462               0 :             if (depth > 0) out << "}\n";
     463               0 :             visitChildren = false;
     464               0 :             break;
     465                 :         }
     466                 :         case EOpPrototype: {
     467                 :             // Function declaration.
     468               0 :             ASSERT(visit == PreVisit);
     469               0 :             writeVariableType(node->getType());
     470               0 :             out << " " << node->getName();
     471                 : 
     472               0 :             out << "(";
     473               0 :             writeFunctionParameters(node->getSequence());
     474               0 :             out << ")";
     475                 : 
     476               0 :             visitChildren = false;
     477               0 :             break;
     478                 :         }
     479                 :         case EOpFunction: {
     480                 :             // Function definition.
     481               0 :             ASSERT(visit == PreVisit);
     482               0 :             writeVariableType(node->getType());
     483               0 :             out << " " << TFunction::unmangleName(node->getName());
     484                 : 
     485               0 :             incrementDepth();
     486                 :             // Function definition node contains one or two children nodes
     487                 :             // representing function parameters and function body. The latter
     488                 :             // is not present in case of empty function bodies.
     489               0 :             const TIntermSequence& sequence = node->getSequence();
     490               0 :             ASSERT((sequence.size() == 1) || (sequence.size() == 2));
     491               0 :             TIntermSequence::const_iterator seqIter = sequence.begin();
     492                 : 
     493                 :             // Traverse function parameters.
     494               0 :             TIntermAggregate* params = (*seqIter)->getAsAggregate();
     495               0 :             ASSERT(params != NULL);
     496               0 :             ASSERT(params->getOp() == EOpParameters);
     497               0 :             params->traverse(this);
     498                 : 
     499                 :             // Traverse function body.
     500               0 :             TIntermAggregate* body = ++seqIter != sequence.end() ?
     501               0 :                 (*seqIter)->getAsAggregate() : NULL;
     502               0 :             visitCodeBlock(body);
     503               0 :             decrementDepth();
     504                 :  
     505                 :             // Fully processed; no need to visit children.
     506               0 :             visitChildren = false;
     507               0 :             break;
     508                 :         }
     509                 :         case EOpFunctionCall:
     510                 :             // Function call.
     511               0 :             if (visit == PreVisit)
     512                 :             {
     513               0 :                 TString functionName = TFunction::unmangleName(node->getName());
     514               0 :                 out << functionName << "(";
     515                 :             }
     516               0 :             else if (visit == InVisit)
     517                 :             {
     518               0 :                 out << ", ";
     519                 :             }
     520                 :             else
     521                 :             {
     522               0 :                 out << ")";
     523                 :             }
     524               0 :             break;
     525                 :         case EOpParameters: {
     526                 :             // Function parameters.
     527               0 :             ASSERT(visit == PreVisit);
     528               0 :             out << "(";
     529               0 :             writeFunctionParameters(node->getSequence());
     530               0 :             out << ")";
     531               0 :             visitChildren = false;
     532               0 :             break;
     533                 :         }
     534                 :         case EOpDeclaration: {
     535                 :             // Variable declaration.
     536               0 :             if (visit == PreVisit)
     537                 :             {
     538               0 :                 const TIntermSequence& sequence = node->getSequence();
     539               0 :                 const TIntermTyped* variable = sequence.front()->getAsTyped();
     540               0 :                 writeVariableType(variable->getType());
     541               0 :                 out << " ";
     542               0 :                 mDeclaringVariables = true;
     543                 :             }
     544               0 :             else if (visit == InVisit)
     545                 :             {
     546               0 :                 out << ", ";
     547               0 :                 mDeclaringVariables = true;
     548                 :             }
     549                 :             else
     550                 :             {
     551               0 :                 mDeclaringVariables = false;
     552                 :             }
     553               0 :             break;
     554                 :         }
     555               0 :         case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break;
     556               0 :         case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break;
     557               0 :         case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break;
     558               0 :         case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break;
     559               0 :         case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break;
     560               0 :         case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break;
     561               0 :         case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break;
     562               0 :         case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break;
     563               0 :         case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break;
     564               0 :         case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break;
     565               0 :         case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break;
     566               0 :         case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break;
     567               0 :         case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break;
     568               0 :         case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break;
     569               0 :         case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break;
     570                 :         case EOpConstructStruct:
     571               0 :             if (visit == PreVisit)
     572                 :             {
     573               0 :                 const TType& type = node->getType();
     574               0 :                 ASSERT(type.getBasicType() == EbtStruct);
     575               0 :                 out << type.getTypeName() << "(";
     576                 :             }
     577               0 :             else if (visit == InVisit)
     578                 :             {
     579               0 :                 out << ", ";
     580                 :             }
     581                 :             else
     582                 :             {
     583               0 :                 out << ")";
     584                 :             }
     585               0 :             break;
     586                 : 
     587               0 :         case EOpLessThan: preString = "lessThan("; delayedWrite = true; break;
     588               0 :         case EOpGreaterThan: preString = "greaterThan("; delayedWrite = true; break;
     589               0 :         case EOpLessThanEqual: preString = "lessThanEqual("; delayedWrite = true; break;
     590               0 :         case EOpGreaterThanEqual: preString = "greaterThanEqual("; delayedWrite = true; break;
     591               0 :         case EOpVectorEqual: preString = "equal("; delayedWrite = true; break;
     592               0 :         case EOpVectorNotEqual: preString = "notEqual("; delayedWrite = true; break;
     593               0 :         case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break;
     594                 : 
     595               0 :         case EOpMod: preString = "mod("; delayedWrite = true; break;
     596               0 :         case EOpPow: preString = "pow("; delayedWrite = true; break;
     597               0 :         case EOpAtan: preString = "atan("; delayedWrite = true; break;
     598               0 :         case EOpMin: preString = "min("; delayedWrite = true; break;
     599               0 :         case EOpMax: preString = "max("; delayedWrite = true; break;
     600               0 :         case EOpClamp: preString = "clamp("; delayedWrite = true; break;
     601               0 :         case EOpMix: preString = "mix("; delayedWrite = true; break;
     602               0 :         case EOpStep: preString = "step("; delayedWrite = true; break;
     603               0 :         case EOpSmoothStep: preString = "smoothstep("; delayedWrite = true; break;
     604                 : 
     605               0 :         case EOpDistance: preString = "distance("; delayedWrite = true; break;
     606               0 :         case EOpDot: preString = "dot("; delayedWrite = true; break;
     607               0 :         case EOpCross: preString = "cross("; delayedWrite = true; break;
     608               0 :         case EOpFaceForward: preString = "faceforward("; delayedWrite = true; break;
     609               0 :         case EOpReflect: preString = "reflect("; delayedWrite = true; break;
     610               0 :         case EOpRefract: preString = "refract("; delayedWrite = true; break;
     611               0 :         case EOpMul: preString = "matrixCompMult("; delayedWrite = true; break;
     612                 : 
     613               0 :         default: UNREACHABLE(); break;
     614                 :     }
     615               0 :     if (delayedWrite && visit == PreVisit && node->getUseEmulatedFunction())
     616               0 :         preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
     617               0 :     if (delayedWrite)
     618               0 :         writeTriplet(visit, preString.c_str(), ", ", ")");
     619               0 :     return visitChildren;
     620                 : }
     621                 : 
     622               0 : bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node)
     623                 : {
     624               0 :     TInfoSinkBase& out = objSink();
     625                 : 
     626               0 :     incrementDepth();
     627                 :     // Loop header.
     628               0 :     TLoopType loopType = node->getType();
     629               0 :     if (loopType == ELoopFor)  // for loop
     630                 :     {
     631               0 :         if (!node->getUnrollFlag()) {
     632               0 :             out << "for (";
     633               0 :             if (node->getInit())
     634               0 :                 node->getInit()->traverse(this);
     635               0 :             out << "; ";
     636                 : 
     637               0 :             if (node->getCondition())
     638               0 :                 node->getCondition()->traverse(this);
     639               0 :             out << "; ";
     640                 : 
     641               0 :             if (node->getExpression())
     642               0 :                 node->getExpression()->traverse(this);
     643               0 :             out << ")\n";
     644                 :         }
     645                 :     }
     646               0 :     else if (loopType == ELoopWhile)  // while loop
     647                 :     {
     648               0 :         out << "while (";
     649               0 :         ASSERT(node->getCondition() != NULL);
     650               0 :         node->getCondition()->traverse(this);
     651               0 :         out << ")\n";
     652                 :     }
     653                 :     else  // do-while loop
     654                 :     {
     655               0 :         ASSERT(loopType == ELoopDoWhile);
     656               0 :         out << "do\n";
     657                 :     }
     658                 : 
     659                 :     // Loop body.
     660               0 :     if (node->getUnrollFlag())
     661                 :     {
     662                 :         TLoopIndexInfo indexInfo;
     663               0 :         mLoopUnroll.FillLoopIndexInfo(node, indexInfo);
     664               0 :         mLoopUnroll.Push(indexInfo);
     665               0 :         while (mLoopUnroll.SatisfiesLoopCondition())
     666                 :         {
     667               0 :             visitCodeBlock(node->getBody());
     668               0 :             mLoopUnroll.Step();
     669                 :         }
     670               0 :         mLoopUnroll.Pop();
     671                 :     }
     672                 :     else
     673                 :     {
     674               0 :         visitCodeBlock(node->getBody());
     675                 :     }
     676                 : 
     677                 :     // Loop footer.
     678               0 :     if (loopType == ELoopDoWhile)  // do-while loop
     679                 :     {
     680               0 :         out << "while (";
     681               0 :         ASSERT(node->getCondition() != NULL);
     682               0 :         node->getCondition()->traverse(this);
     683               0 :         out << ");\n";
     684                 :     }
     685               0 :     decrementDepth();
     686                 : 
     687                 :     // No need to visit children. They have been already processed in
     688                 :     // this function.
     689               0 :     return false;
     690                 : }
     691                 : 
     692               0 : bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch* node)
     693                 : {
     694               0 :     switch (node->getFlowOp())
     695                 :     {
     696               0 :         case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break;
     697               0 :         case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break;
     698               0 :         case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break;
     699               0 :         case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break;
     700               0 :         default: UNREACHABLE(); break;
     701                 :     }
     702                 : 
     703               0 :     return true;
     704                 : }
     705                 : 
     706               0 : void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) {
     707               0 :     TInfoSinkBase &out = objSink();
     708               0 :     if (node != NULL)
     709                 :     {
     710               0 :         node->traverse(this);
     711                 :         // Single statements not part of a sequence need to be terminated
     712                 :         // with semi-colon.
     713               0 :         if (isSingleStatement(node))
     714               0 :             out << ";\n";
     715                 :     }
     716                 :     else
     717                 :     {
     718               0 :         out << "{\n}\n";  // Empty code block.
     719                 :     }
     720               0 : }

Generated by: LCOV version 1.7