Home | History | Annotate | Download | only in translator
      1 //
      2 // Copyright (c) 2002-2014 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/translator/ParseContext.h"
      8 
      9 #include <stdarg.h>
     10 #include <stdio.h>
     11 
     12 #include "compiler/translator/glslang.h"
     13 #include "compiler/preprocessor/SourceLocation.h"
     14 
     15 ///////////////////////////////////////////////////////////////////////
     16 //
     17 // Sub- vector and matrix fields
     18 //
     19 ////////////////////////////////////////////////////////////////////////
     20 
     21 //
     22 // Look at a '.' field selector string and change it into offsets
     23 // for a vector.
     24 //
     25 bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc& line)
     26 {
     27     fields.num = (int) compString.size();
     28     if (fields.num > 4) {
     29         error(line, "illegal vector field selection", compString.c_str());
     30         return false;
     31     }
     32 
     33     enum {
     34         exyzw,
     35         ergba,
     36         estpq
     37     } fieldSet[4];
     38 
     39     for (int i = 0; i < fields.num; ++i) {
     40         switch (compString[i])  {
     41         case 'x':
     42             fields.offsets[i] = 0;
     43             fieldSet[i] = exyzw;
     44             break;
     45         case 'r':
     46             fields.offsets[i] = 0;
     47             fieldSet[i] = ergba;
     48             break;
     49         case 's':
     50             fields.offsets[i] = 0;
     51             fieldSet[i] = estpq;
     52             break;
     53         case 'y':
     54             fields.offsets[i] = 1;
     55             fieldSet[i] = exyzw;
     56             break;
     57         case 'g':
     58             fields.offsets[i] = 1;
     59             fieldSet[i] = ergba;
     60             break;
     61         case 't':
     62             fields.offsets[i] = 1;
     63             fieldSet[i] = estpq;
     64             break;
     65         case 'z':
     66             fields.offsets[i] = 2;
     67             fieldSet[i] = exyzw;
     68             break;
     69         case 'b':
     70             fields.offsets[i] = 2;
     71             fieldSet[i] = ergba;
     72             break;
     73         case 'p':
     74             fields.offsets[i] = 2;
     75             fieldSet[i] = estpq;
     76             break;
     77 
     78         case 'w':
     79             fields.offsets[i] = 3;
     80             fieldSet[i] = exyzw;
     81             break;
     82         case 'a':
     83             fields.offsets[i] = 3;
     84             fieldSet[i] = ergba;
     85             break;
     86         case 'q':
     87             fields.offsets[i] = 3;
     88             fieldSet[i] = estpq;
     89             break;
     90         default:
     91             error(line, "illegal vector field selection", compString.c_str());
     92             return false;
     93         }
     94     }
     95 
     96     for (int i = 0; i < fields.num; ++i) {
     97         if (fields.offsets[i] >= vecSize) {
     98             error(line, "vector field selection out of range",  compString.c_str());
     99             return false;
    100         }
    101 
    102         if (i > 0) {
    103             if (fieldSet[i] != fieldSet[i-1]) {
    104                 error(line, "illegal - vector component fields not from the same set", compString.c_str());
    105                 return false;
    106             }
    107         }
    108     }
    109 
    110     return true;
    111 }
    112 
    113 
    114 //
    115 // Look at a '.' field selector string and change it into offsets
    116 // for a matrix.
    117 //
    118 bool TParseContext::parseMatrixFields(const TString& compString, int matCols, int matRows, TMatrixFields& fields, const TSourceLoc& line)
    119 {
    120     fields.wholeRow = false;
    121     fields.wholeCol = false;
    122     fields.row = -1;
    123     fields.col = -1;
    124 
    125     if (compString.size() != 2) {
    126         error(line, "illegal length of matrix field selection", compString.c_str());
    127         return false;
    128     }
    129 
    130     if (compString[0] == '_') {
    131         if (compString[1] < '0' || compString[1] > '3') {
    132             error(line, "illegal matrix field selection", compString.c_str());
    133             return false;
    134         }
    135         fields.wholeCol = true;
    136         fields.col = compString[1] - '0';
    137     } else if (compString[1] == '_') {
    138         if (compString[0] < '0' || compString[0] > '3') {
    139             error(line, "illegal matrix field selection", compString.c_str());
    140             return false;
    141         }
    142         fields.wholeRow = true;
    143         fields.row = compString[0] - '0';
    144     } else {
    145         if (compString[0] < '0' || compString[0] > '3' ||
    146             compString[1] < '0' || compString[1] > '3') {
    147             error(line, "illegal matrix field selection", compString.c_str());
    148             return false;
    149         }
    150         fields.row = compString[0] - '0';
    151         fields.col = compString[1] - '0';
    152     }
    153 
    154     if (fields.row >= matRows || fields.col >= matCols) {
    155         error(line, "matrix field selection out of range", compString.c_str());
    156         return false;
    157     }
    158 
    159     return true;
    160 }
    161 
    162 ///////////////////////////////////////////////////////////////////////
    163 //
    164 // Errors
    165 //
    166 ////////////////////////////////////////////////////////////////////////
    167 
    168 //
    169 // Track whether errors have occurred.
    170 //
    171 void TParseContext::recover()
    172 {
    173 }
    174 
    175 //
    176 // Used by flex/bison to output all syntax and parsing errors.
    177 //
    178 void TParseContext::error(const TSourceLoc& loc,
    179                           const char* reason, const char* token,
    180                           const char* extraInfo)
    181 {
    182     pp::SourceLocation srcLoc;
    183     srcLoc.file = loc.first_file;
    184     srcLoc.line = loc.first_line;
    185     diagnostics.writeInfo(pp::Diagnostics::PP_ERROR,
    186                           srcLoc, reason, token, extraInfo);
    187 
    188 }
    189 
    190 void TParseContext::warning(const TSourceLoc& loc,
    191                             const char* reason, const char* token,
    192                             const char* extraInfo) {
    193     pp::SourceLocation srcLoc;
    194     srcLoc.file = loc.first_file;
    195     srcLoc.line = loc.first_line;
    196     diagnostics.writeInfo(pp::Diagnostics::PP_WARNING,
    197                           srcLoc, reason, token, extraInfo);
    198 }
    199 
    200 void TParseContext::trace(const char* str)
    201 {
    202     diagnostics.writeDebug(str);
    203 }
    204 
    205 //
    206 // Same error message for all places assignments don't work.
    207 //
    208 void TParseContext::assignError(const TSourceLoc& line, const char* op, TString left, TString right)
    209 {
    210     std::stringstream extraInfoStream;
    211     extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
    212     std::string extraInfo = extraInfoStream.str();
    213     error(line, "", op, extraInfo.c_str());
    214 }
    215 
    216 //
    217 // Same error message for all places unary operations don't work.
    218 //
    219 void TParseContext::unaryOpError(const TSourceLoc& line, const char* op, TString operand)
    220 {
    221     std::stringstream extraInfoStream;
    222     extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand
    223                     << " (or there is no acceptable conversion)";
    224     std::string extraInfo = extraInfoStream.str();
    225     error(line, " wrong operand type", op, extraInfo.c_str());
    226 }
    227 
    228 //
    229 // Same error message for all binary operations don't work.
    230 //
    231 void TParseContext::binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right)
    232 {
    233     std::stringstream extraInfoStream;
    234     extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left
    235                     << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)";
    236     std::string extraInfo = extraInfoStream.str();
    237     error(line, " wrong operand types ", op, extraInfo.c_str());
    238 }
    239 
    240 bool TParseContext::precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type){
    241     if (!checksPrecisionErrors)
    242         return false;
    243     switch( type ){
    244     case EbtFloat:
    245         if( precision == EbpUndefined ){
    246             error( line, "No precision specified for (float)", "" );
    247             return true;
    248         }
    249         break;
    250     case EbtInt:
    251         if( precision == EbpUndefined ){
    252             error( line, "No precision specified (int)", "" );
    253             return true;
    254         }
    255         break;
    256     default:
    257         return false;
    258     }
    259     return false;
    260 }
    261 
    262 //
    263 // Both test and if necessary, spit out an error, to see if the node is really
    264 // an l-value that can be operated on this way.
    265 //
    266 // Returns true if the was an error.
    267 //
    268 bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped* node)
    269 {
    270     TIntermSymbol* symNode = node->getAsSymbolNode();
    271     TIntermBinary* binaryNode = node->getAsBinaryNode();
    272 
    273     if (binaryNode) {
    274         bool errorReturn;
    275 
    276         switch(binaryNode->getOp()) {
    277         case EOpIndexDirect:
    278         case EOpIndexIndirect:
    279         case EOpIndexDirectStruct:
    280         case EOpIndexDirectInterfaceBlock:
    281             return lValueErrorCheck(line, op, binaryNode->getLeft());
    282         case EOpVectorSwizzle:
    283             errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
    284             if (!errorReturn) {
    285                 int offset[4] = {0,0,0,0};
    286 
    287                 TIntermTyped* rightNode = binaryNode->getRight();
    288                 TIntermAggregate *aggrNode = rightNode->getAsAggregate();
    289 
    290                 for (TIntermSequence::iterator p = aggrNode->getSequence()->begin();
    291                                                p != aggrNode->getSequence()->end(); p++) {
    292                     int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0);
    293                     offset[value]++;
    294                     if (offset[value] > 1) {
    295                         error(line, " l-value of swizzle cannot have duplicate components", op);
    296 
    297                         return true;
    298                     }
    299                 }
    300             }
    301 
    302             return errorReturn;
    303         default:
    304             break;
    305         }
    306         error(line, " l-value required", op);
    307 
    308         return true;
    309     }
    310 
    311 
    312     const char* symbol = 0;
    313     if (symNode != 0)
    314         symbol = symNode->getSymbol().c_str();
    315 
    316     const char* message = 0;
    317     switch (node->getQualifier()) {
    318     case EvqConst:          message = "can't modify a const";        break;
    319     case EvqConstReadOnly:  message = "can't modify a const";        break;
    320     case EvqAttribute:      message = "can't modify an attribute";   break;
    321     case EvqFragmentIn:     message = "can't modify an input";       break;
    322     case EvqVertexIn:       message = "can't modify an input";       break;
    323     case EvqUniform:        message = "can't modify a uniform";      break;
    324     case EvqVaryingIn:      message = "can't modify a varying";      break;
    325     case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
    326     case EvqFrontFacing:    message = "can't modify gl_FrontFacing"; break;
    327     case EvqPointCoord:     message = "can't modify gl_PointCoord";  break;
    328     default:
    329 
    330         //
    331         // Type that can't be written to?
    332         //
    333         if (node->getBasicType() == EbtVoid) {
    334             message = "can't modify void";
    335         }
    336         if (IsSampler(node->getBasicType())) {
    337             message = "can't modify a sampler";
    338         }
    339     }
    340 
    341     if (message == 0 && binaryNode == 0 && symNode == 0) {
    342         error(line, " l-value required", op);
    343 
    344         return true;
    345     }
    346 
    347 
    348     //
    349     // Everything else is okay, no error.
    350     //
    351     if (message == 0)
    352         return false;
    353 
    354     //
    355     // If we get here, we have an error and a message.
    356     //
    357     if (symNode) {
    358         std::stringstream extraInfoStream;
    359         extraInfoStream << "\"" << symbol << "\" (" << message << ")";
    360         std::string extraInfo = extraInfoStream.str();
    361         error(line, " l-value required", op, extraInfo.c_str());
    362     }
    363     else {
    364         std::stringstream extraInfoStream;
    365         extraInfoStream << "(" << message << ")";
    366         std::string extraInfo = extraInfoStream.str();
    367         error(line, " l-value required", op, extraInfo.c_str());
    368     }
    369 
    370     return true;
    371 }
    372 
    373 //
    374 // Both test, and if necessary spit out an error, to see if the node is really
    375 // a constant.
    376 //
    377 // Returns true if the was an error.
    378 //
    379 bool TParseContext::constErrorCheck(TIntermTyped* node)
    380 {
    381     if (node->getQualifier() == EvqConst)
    382         return false;
    383 
    384     error(node->getLine(), "constant expression required", "");
    385 
    386     return true;
    387 }
    388 
    389 //
    390 // Both test, and if necessary spit out an error, to see if the node is really
    391 // an integer.
    392 //
    393 // Returns true if the was an error.
    394 //
    395 bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
    396 {
    397     if (node->isScalarInt())
    398         return false;
    399 
    400     error(node->getLine(), "integer expression required", token);
    401 
    402     return true;
    403 }
    404 
    405 //
    406 // Both test, and if necessary spit out an error, to see if we are currently
    407 // globally scoped.
    408 //
    409 // Returns true if the was an error.
    410 //
    411 bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token)
    412 {
    413     if (global)
    414         return false;
    415 
    416     error(line, "only allowed at global scope", token);
    417 
    418     return true;
    419 }
    420 
    421 //
    422 // For now, keep it simple:  if it starts "gl_", it's reserved, independent
    423 // of scope.  Except, if the symbol table is at the built-in push-level,
    424 // which is when we are parsing built-ins.
    425 // Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
    426 // webgl shader.
    427 //
    428 // Returns true if there was an error.
    429 //
    430 bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier)
    431 {
    432     static const char* reservedErrMsg = "reserved built-in name";
    433     if (!symbolTable.atBuiltInLevel()) {
    434         if (identifier.compare(0, 3, "gl_") == 0) {
    435             error(line, reservedErrMsg, "gl_");
    436             return true;
    437         }
    438         if (IsWebGLBasedSpec(shaderSpec)) {
    439             if (identifier.compare(0, 6, "webgl_") == 0) {
    440                 error(line, reservedErrMsg, "webgl_");
    441                 return true;
    442             }
    443             if (identifier.compare(0, 7, "_webgl_") == 0) {
    444                 error(line, reservedErrMsg, "_webgl_");
    445                 return true;
    446             }
    447             if (shaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0) {
    448                 error(line, reservedErrMsg, "css_");
    449                 return true;
    450             }
    451         }
    452         if (identifier.find("__") != TString::npos) {
    453             error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str());
    454             return true;
    455         }
    456     }
    457 
    458     return false;
    459 }
    460 
    461 //
    462 // Make sure there is enough data provided to the constructor to build
    463 // something of the type of the constructor.  Also returns the type of
    464 // the constructor.
    465 //
    466 // Returns true if there was an error in construction.
    467 //
    468 bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
    469 {
    470     *type = function.getReturnType();
    471 
    472     bool constructingMatrix = false;
    473     switch(op) {
    474     case EOpConstructMat2:
    475     case EOpConstructMat3:
    476     case EOpConstructMat4:
    477         constructingMatrix = true;
    478         break;
    479     default:
    480         break;
    481     }
    482 
    483     //
    484     // Note: It's okay to have too many components available, but not okay to have unused
    485     // arguments.  'full' will go to true when enough args have been seen.  If we loop
    486     // again, there is an extra argument, so 'overfull' will become true.
    487     //
    488 
    489     size_t size = 0;
    490     bool constType = true;
    491     bool full = false;
    492     bool overFull = false;
    493     bool matrixInMatrix = false;
    494     bool arrayArg = false;
    495     for (size_t i = 0; i < function.getParamCount(); ++i) {
    496         const TParameter& param = function.getParam(i);
    497         size += param.type->getObjectSize();
    498 
    499         if (constructingMatrix && param.type->isMatrix())
    500             matrixInMatrix = true;
    501         if (full)
    502             overFull = true;
    503         if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
    504             full = true;
    505         if (param.type->getQualifier() != EvqConst)
    506             constType = false;
    507         if (param.type->isArray())
    508             arrayArg = true;
    509     }
    510 
    511     if (constType)
    512         type->setQualifier(EvqConst);
    513 
    514     if (type->isArray() && static_cast<size_t>(type->getArraySize()) != function.getParamCount()) {
    515         error(line, "array constructor needs one argument per array element", "constructor");
    516         return true;
    517     }
    518 
    519     if (arrayArg && op != EOpConstructStruct) {
    520         error(line, "constructing from a non-dereferenced array", "constructor");
    521         return true;
    522     }
    523 
    524     if (matrixInMatrix && !type->isArray()) {
    525         if (function.getParamCount() != 1) {
    526           error(line, "constructing matrix from matrix can only take one argument", "constructor");
    527           return true;
    528         }
    529     }
    530 
    531     if (overFull) {
    532         error(line, "too many arguments", "constructor");
    533         return true;
    534     }
    535 
    536     if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->fields().size() != function.getParamCount()) {
    537         error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
    538         return true;
    539     }
    540 
    541     if (!type->isMatrix() || !matrixInMatrix) {
    542         if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
    543             (op == EOpConstructStruct && size < type->getObjectSize())) {
    544             error(line, "not enough data provided for construction", "constructor");
    545             return true;
    546         }
    547     }
    548 
    549     TIntermTyped *typed = node ? node->getAsTyped() : 0;
    550     if (typed == 0) {
    551         error(line, "constructor argument does not have a type", "constructor");
    552         return true;
    553     }
    554     if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
    555         error(line, "cannot convert a sampler", "constructor");
    556         return true;
    557     }
    558     if (typed->getBasicType() == EbtVoid) {
    559         error(line, "cannot convert a void", "constructor");
    560         return true;
    561     }
    562 
    563     return false;
    564 }
    565 
    566 // This function checks to see if a void variable has been declared and raise an error message for such a case
    567 //
    568 // returns true in case of an error
    569 //
    570 bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType)
    571 {
    572     if (pubType.type == EbtVoid) {
    573         error(line, "illegal use of type 'void'", identifier.c_str());
    574         return true;
    575     }
    576 
    577     return false;
    578 }
    579 
    580 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not
    581 //
    582 // returns true in case of an error
    583 //
    584 bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type)
    585 {
    586     if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
    587         error(line, "boolean expression expected", "");
    588         return true;
    589     }
    590 
    591     return false;
    592 }
    593 
    594 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not
    595 //
    596 // returns true in case of an error
    597 //
    598 bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType)
    599 {
    600     if (pType.type != EbtBool || pType.isAggregate()) {
    601         error(line, "boolean expression expected", "");
    602         return true;
    603     }
    604 
    605     return false;
    606 }
    607 
    608 bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason)
    609 {
    610     if (pType.type == EbtStruct) {
    611         if (containsSampler(*pType.userDef)) {
    612             error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
    613 
    614             return true;
    615         }
    616 
    617         return false;
    618     } else if (IsSampler(pType.type)) {
    619         error(line, reason, getBasicString(pType.type));
    620 
    621         return true;
    622     }
    623 
    624     return false;
    625 }
    626 
    627 bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType)
    628 {
    629     switch (pType.qualifier)
    630     {
    631       case EvqVaryingIn:
    632       case EvqVaryingOut:
    633       case EvqAttribute:
    634       case EvqVertexIn:
    635       case EvqFragmentOut:
    636         if (pType.type == EbtStruct)
    637         {
    638             error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
    639             return true;
    640         }
    641 
    642       default: break;
    643     }
    644 
    645     if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
    646         return true;
    647 
    648     return false;
    649 }
    650 
    651 bool TParseContext::locationDeclaratorListCheck(const TSourceLoc& line, const TPublicType &pType)
    652 {
    653     if (pType.layoutQualifier.location != -1)
    654     {
    655         error(line, "location must only be specified for a single input or output variable", "location");
    656         return true;
    657     }
    658 
    659     return false;
    660 }
    661 
    662 bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type)
    663 {
    664     if ((qualifier == EvqOut || qualifier == EvqInOut) &&
    665              type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
    666         error(line, "samplers cannot be output parameters", type.getBasicString());
    667         return true;
    668     }
    669 
    670     return false;
    671 }
    672 
    673 bool TParseContext::containsSampler(TType& type)
    674 {
    675     if (IsSampler(type.getBasicType()))
    676         return true;
    677 
    678     if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) {
    679         const TFieldList& fields = type.getStruct()->fields();
    680         for (unsigned int i = 0; i < fields.size(); ++i) {
    681             if (containsSampler(*fields[i]->type()))
    682                 return true;
    683         }
    684     }
    685 
    686     return false;
    687 }
    688 
    689 //
    690 // Do size checking for an array type's size.
    691 //
    692 // Returns true if there was an error.
    693 //
    694 bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size)
    695 {
    696     TIntermConstantUnion* constant = expr->getAsConstantUnion();
    697 
    698     if (constant == 0 || !constant->isScalarInt())
    699     {
    700         error(line, "array size must be a constant integer expression", "");
    701         return true;
    702     }
    703 
    704     unsigned int unsignedSize = 0;
    705 
    706     if (constant->getBasicType() == EbtUInt)
    707     {
    708         unsignedSize = constant->getUConst(0);
    709         size = static_cast<int>(unsignedSize);
    710     }
    711     else
    712     {
    713         size = constant->getIConst(0);
    714 
    715         if (size < 0)
    716         {
    717             error(line, "array size must be non-negative", "");
    718             size = 1;
    719             return true;
    720         }
    721 
    722         unsignedSize = static_cast<unsigned int>(size);
    723     }
    724 
    725     if (size == 0)
    726     {
    727         error(line, "array size must be greater than zero", "");
    728         size = 1;
    729         return true;
    730     }
    731 
    732     // The size of arrays is restricted here to prevent issues further down the
    733     // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
    734     // 4096 registers so this should be reasonable even for aggressively optimizable code.
    735     const unsigned int sizeLimit = 65536;
    736 
    737     if (unsignedSize > sizeLimit)
    738     {
    739         error(line, "array size too large", "");
    740         size = 1;
    741         return true;
    742     }
    743 
    744     return false;
    745 }
    746 
    747 //
    748 // See if this qualifier can be an array.
    749 //
    750 // Returns true if there is an error.
    751 //
    752 bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type)
    753 {
    754     if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) || (type.qualifier == EvqConst)) {
    755         error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
    756         return true;
    757     }
    758 
    759     return false;
    760 }
    761 
    762 //
    763 // See if this type can be an array.
    764 //
    765 // Returns true if there is an error.
    766 //
    767 bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type)
    768 {
    769     //
    770     // Can the type be an array?
    771     //
    772     if (type.array) {
    773         error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
    774         return true;
    775     }
    776 
    777     return false;
    778 }
    779 
    780 //
    781 // Do all the semantic checking for declaring an array, with and
    782 // without a size, and make the right changes to the symbol table.
    783 //
    784 // size == 0 means no specified size.
    785 //
    786 // Returns true if there was an error.
    787 //
    788 bool TParseContext::arrayErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType &type, TVariable*& variable)
    789 {
    790     //
    791     // Don't check for reserved word use until after we know it's not in the symbol table,
    792     // because reserved arrays can be redeclared.
    793     //
    794 
    795     bool builtIn = false;
    796     bool sameScope = false;
    797     TSymbol* symbol = symbolTable.find(identifier, 0, &builtIn, &sameScope);
    798     if (symbol == 0 || !sameScope) {
    799         if (reservedErrorCheck(line, identifier))
    800             return true;
    801 
    802         variable = new TVariable(&identifier, TType(type));
    803 
    804         if (type.arraySize)
    805             variable->getType().setArraySize(type.arraySize);
    806 
    807         if (! symbolTable.declare(variable)) {
    808             delete variable;
    809             error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str());
    810             return true;
    811         }
    812     } else {
    813         if (! symbol->isVariable()) {
    814             error(line, "variable expected", identifier.c_str());
    815             return true;
    816         }
    817 
    818         variable = static_cast<TVariable*>(symbol);
    819         if (! variable->getType().isArray()) {
    820             error(line, "redeclaring non-array as array", identifier.c_str());
    821             return true;
    822         }
    823         if (variable->getType().getArraySize() > 0) {
    824             error(line, "redeclaration of array with size", identifier.c_str());
    825             return true;
    826         }
    827 
    828         if (! variable->getType().sameElementType(TType(type))) {
    829             error(line, "redeclaration of array with a different type", identifier.c_str());
    830             return true;
    831         }
    832 
    833         if (type.arraySize)
    834             variable->getType().setArraySize(type.arraySize);
    835     }
    836 
    837     if (voidErrorCheck(line, identifier, type))
    838         return true;
    839 
    840     return false;
    841 }
    842 
    843 //
    844 // Enforce non-initializer type/qualifier rules.
    845 //
    846 // Returns true if there was an error.
    847 //
    848 bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, const TString& identifier, TPublicType& type, bool array)
    849 {
    850     if (type.qualifier == EvqConst)
    851     {
    852         // Make the qualifier make sense.
    853         type.qualifier = EvqTemporary;
    854 
    855         if (array)
    856         {
    857             error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
    858         }
    859         else if (type.isStructureContainingArrays())
    860         {
    861             error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str());
    862         }
    863         else
    864         {
    865             error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
    866         }
    867 
    868         return true;
    869     }
    870 
    871     return false;
    872 }
    873 
    874 //
    875 // Do semantic checking for a variable declaration that has no initializer,
    876 // and update the symbol table.
    877 //
    878 // Returns true if there was an error.
    879 //
    880 bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& type, TVariable*& variable)
    881 {
    882     if (reservedErrorCheck(line, identifier))
    883         recover();
    884 
    885     variable = new TVariable(&identifier, TType(type));
    886 
    887     if (! symbolTable.declare(variable)) {
    888         error(line, "redefinition", variable->getName().c_str());
    889         delete variable;
    890         variable = 0;
    891         return true;
    892     }
    893 
    894     if (voidErrorCheck(line, identifier, type))
    895         return true;
    896 
    897     return false;
    898 }
    899 
    900 bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
    901 {
    902     if (qualifier != EvqConst && qualifier != EvqTemporary) {
    903         error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
    904         return true;
    905     }
    906     if (qualifier == EvqConst && paramQualifier != EvqIn) {
    907         error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
    908         return true;
    909     }
    910 
    911     if (qualifier == EvqConst)
    912         type->setQualifier(EvqConstReadOnly);
    913     else
    914         type->setQualifier(paramQualifier);
    915 
    916     return false;
    917 }
    918 
    919 bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension)
    920 {
    921     const TExtensionBehavior& extBehavior = extensionBehavior();
    922     TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
    923     if (iter == extBehavior.end()) {
    924         error(line, "extension", extension.c_str(), "is not supported");
    925         return true;
    926     }
    927     // In GLSL ES, an extension's default behavior is "disable".
    928     if (iter->second == EBhDisable || iter->second == EBhUndefined) {
    929         error(line, "extension", extension.c_str(), "is disabled");
    930         return true;
    931     }
    932     if (iter->second == EBhWarn) {
    933         warning(line, "extension", extension.c_str(), "is being used");
    934         return false;
    935     }
    936 
    937     return false;
    938 }
    939 
    940 bool TParseContext::singleDeclarationErrorCheck(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier)
    941 {
    942     if (structQualifierErrorCheck(identifierLocation, publicType))
    943         return true;
    944 
    945     // check for layout qualifier issues
    946     const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
    947 
    948     if (layoutQualifier.matrixPacking != EmpUnspecified)
    949     {
    950         error(identifierLocation, "layout qualifier", getMatrixPackingString(layoutQualifier.matrixPacking), "only valid for interface blocks");
    951         return true;
    952     }
    953 
    954     if (layoutQualifier.blockStorage != EbsUnspecified)
    955     {
    956         error(identifierLocation, "layout qualifier", getBlockStorageString(layoutQualifier.blockStorage), "only valid for interface blocks");
    957         return true;
    958     }
    959 
    960     if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut && layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier))
    961     {
    962         return true;
    963     }
    964 
    965     return false;
    966 }
    967 
    968 bool TParseContext::layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier)
    969 {
    970     if (layoutQualifier.location != -1)
    971     {
    972         error(location, "invalid layout qualifier:", "location", "only valid on program inputs and outputs");
    973         return true;
    974     }
    975 
    976     return false;
    977 }
    978 
    979 bool TParseContext::supportsExtension(const char* extension)
    980 {
    981     const TExtensionBehavior& extbehavior = extensionBehavior();
    982     TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
    983     return (iter != extbehavior.end());
    984 }
    985 
    986 bool TParseContext::isExtensionEnabled(const char* extension) const
    987 {
    988     const TExtensionBehavior& extbehavior = extensionBehavior();
    989     TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
    990 
    991     if (iter == extbehavior.end())
    992     {
    993         return false;
    994     }
    995 
    996     return (iter->second == EBhEnable || iter->second == EBhRequire);
    997 }
    998 
    999 void TParseContext::handleExtensionDirective(const TSourceLoc& loc, const char* extName, const char* behavior)
   1000 {
   1001     pp::SourceLocation srcLoc;
   1002     srcLoc.file = loc.first_file;
   1003     srcLoc.line = loc.first_line;
   1004     directiveHandler.handleExtension(srcLoc, extName, behavior);
   1005 }
   1006 
   1007 void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value)
   1008 {
   1009     pp::SourceLocation srcLoc;
   1010     srcLoc.file = loc.first_file;
   1011     srcLoc.line = loc.first_line;
   1012     directiveHandler.handlePragma(srcLoc, name, value);
   1013 }
   1014 
   1015 /////////////////////////////////////////////////////////////////////////////////
   1016 //
   1017 // Non-Errors.
   1018 //
   1019 /////////////////////////////////////////////////////////////////////////////////
   1020 
   1021 const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
   1022                                                  const TString *name,
   1023                                                  const TSymbol *symbol)
   1024 {
   1025     const TVariable *variable = NULL;
   1026 
   1027     if (!symbol)
   1028     {
   1029         error(location, "undeclared identifier", name->c_str());
   1030         recover();
   1031     }
   1032     else if (!symbol->isVariable())
   1033     {
   1034         error(location, "variable expected", name->c_str());
   1035         recover();
   1036     }
   1037     else
   1038     {
   1039         variable = static_cast<const TVariable*>(symbol);
   1040 
   1041         if (symbolTable.findBuiltIn(variable->getName(), shaderVersion) &&
   1042             !variable->getExtension().empty() &&
   1043             extensionErrorCheck(location, variable->getExtension()))
   1044         {
   1045             recover();
   1046         }
   1047     }
   1048 
   1049     if (!variable)
   1050     {
   1051         TType type(EbtFloat, EbpUndefined);
   1052         TVariable *fakeVariable = new TVariable(name, type);
   1053         symbolTable.declare(fakeVariable);
   1054         variable = fakeVariable;
   1055     }
   1056 
   1057     return variable;
   1058 }
   1059 
   1060 //
   1061 // Look up a function name in the symbol table, and make sure it is a function.
   1062 //
   1063 // Return the function symbol if found, otherwise 0.
   1064 //
   1065 const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, int shaderVersion, bool *builtIn)
   1066 {
   1067     // First find by unmangled name to check whether the function name has been
   1068     // hidden by a variable name or struct typename.
   1069     // If a function is found, check for one with a matching argument list.
   1070     const TSymbol* symbol = symbolTable.find(call->getName(), shaderVersion, builtIn);
   1071     if (symbol == 0 || symbol->isFunction()) {
   1072         symbol = symbolTable.find(call->getMangledName(), shaderVersion, builtIn);
   1073     }
   1074 
   1075     if (symbol == 0) {
   1076         error(line, "no matching overloaded function found", call->getName().c_str());
   1077         return 0;
   1078     }
   1079 
   1080     if (!symbol->isFunction()) {
   1081         error(line, "function name expected", call->getName().c_str());
   1082         return 0;
   1083     }
   1084 
   1085     return static_cast<const TFunction*>(symbol);
   1086 }
   1087 
   1088 //
   1089 // Initializers show up in several places in the grammar.  Have one set of
   1090 // code to handle them here.
   1091 //
   1092 // Returns true on error, false if no error
   1093 //
   1094 bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& identifier, TPublicType& pType,
   1095                                        TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
   1096 {
   1097     TType type = TType(pType);
   1098 
   1099     if (variable == 0) {
   1100         if (reservedErrorCheck(line, identifier))
   1101             return true;
   1102 
   1103         if (voidErrorCheck(line, identifier, pType))
   1104             return true;
   1105 
   1106         //
   1107         // add variable to symbol table
   1108         //
   1109         variable = new TVariable(&identifier, type);
   1110         if (! symbolTable.declare(variable)) {
   1111             error(line, "redefinition", variable->getName().c_str());
   1112             return true;
   1113             // don't delete variable, it's used by error recovery, and the pool
   1114             // pop will take care of the memory
   1115         }
   1116     }
   1117 
   1118     //
   1119     // identifier must be of type constant, a global, or a temporary
   1120     //
   1121     TQualifier qualifier = variable->getType().getQualifier();
   1122     if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
   1123         error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString());
   1124         return true;
   1125     }
   1126     //
   1127     // test for and propagate constant
   1128     //
   1129 
   1130     if (qualifier == EvqConst) {
   1131         if (qualifier != initializer->getType().getQualifier()) {
   1132             std::stringstream extraInfoStream;
   1133             extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
   1134             std::string extraInfo = extraInfoStream.str();
   1135             error(line, " assigning non-constant to", "=", extraInfo.c_str());
   1136             variable->getType().setQualifier(EvqTemporary);
   1137             return true;
   1138         }
   1139         if (type != initializer->getType()) {
   1140             error(line, " non-matching types for const initializer ",
   1141                 variable->getType().getQualifierString());
   1142             variable->getType().setQualifier(EvqTemporary);
   1143             return true;
   1144         }
   1145         if (initializer->getAsConstantUnion()) {
   1146             variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
   1147         } else if (initializer->getAsSymbolNode()) {
   1148             const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
   1149             const TVariable* tVar = static_cast<const TVariable*>(symbol);
   1150 
   1151             ConstantUnion* constArray = tVar->getConstPointer();
   1152             variable->shareConstPointer(constArray);
   1153         } else {
   1154             std::stringstream extraInfoStream;
   1155             extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
   1156             std::string extraInfo = extraInfoStream.str();
   1157             error(line, " cannot assign to", "=", extraInfo.c_str());
   1158             variable->getType().setQualifier(EvqTemporary);
   1159             return true;
   1160         }
   1161     }
   1162 
   1163     if (qualifier != EvqConst) {
   1164         TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
   1165         intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
   1166         if (intermNode == 0) {
   1167             assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
   1168             return true;
   1169         }
   1170     } else
   1171         intermNode = 0;
   1172 
   1173     return false;
   1174 }
   1175 
   1176 bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
   1177 {
   1178     ASSERT(aggrNode != NULL);
   1179     if (!aggrNode->isConstructor())
   1180         return false;
   1181 
   1182     bool allConstant = true;
   1183 
   1184     // check if all the child nodes are constants so that they can be inserted into
   1185     // the parent node
   1186     TIntermSequence *sequence = aggrNode->getSequence() ;
   1187     for (TIntermSequence::iterator p = sequence->begin(); p != sequence->end(); ++p) {
   1188         if (!(*p)->getAsTyped()->getAsConstantUnion())
   1189             return false;
   1190     }
   1191 
   1192     return allConstant;
   1193 }
   1194 
   1195 TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, TLayoutQualifier layoutQualifier, const TPublicType& typeSpecifier)
   1196 {
   1197     TPublicType returnType = typeSpecifier;
   1198     returnType.qualifier = qualifier;
   1199     returnType.layoutQualifier = layoutQualifier;
   1200 
   1201     if (typeSpecifier.array)
   1202     {
   1203         error(typeSpecifier.line, "not supported", "first-class array");
   1204         recover();
   1205         returnType.setArray(false);
   1206     }
   1207 
   1208     if (shaderVersion < 300)
   1209     {
   1210         if (qualifier == EvqAttribute && (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
   1211         {
   1212             error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
   1213             recover();
   1214         }
   1215 
   1216         if ((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
   1217             (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
   1218         {
   1219             error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
   1220             recover();
   1221         }
   1222     }
   1223     else
   1224     {
   1225         switch (qualifier)
   1226         {
   1227           case EvqSmoothIn:
   1228           case EvqSmoothOut:
   1229           case EvqVertexOut:
   1230           case EvqFragmentIn:
   1231           case EvqCentroidOut:
   1232           case EvqCentroidIn:
   1233             if (typeSpecifier.type == EbtBool)
   1234             {
   1235                 error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier));
   1236                 recover();
   1237             }
   1238             if (typeSpecifier.type == EbtInt || typeSpecifier.type == EbtUInt)
   1239             {
   1240                 error(typeSpecifier.line, "must use 'flat' interpolation here", getQualifierString(qualifier));
   1241                 recover();
   1242             }
   1243             break;
   1244 
   1245           case EvqVertexIn:
   1246           case EvqFragmentOut:
   1247           case EvqFlatIn:
   1248           case EvqFlatOut:
   1249             if (typeSpecifier.type == EbtBool)
   1250             {
   1251                 error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier));
   1252                 recover();
   1253             }
   1254             break;
   1255 
   1256           default: break;
   1257         }
   1258     }
   1259 
   1260     return returnType;
   1261 }
   1262 
   1263 TIntermAggregate* TParseContext::parseSingleDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier)
   1264 {
   1265     TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
   1266     TIntermAggregate* aggregate = intermediate.makeAggregate(symbol, identifierLocation);
   1267 
   1268     if (identifier != "")
   1269     {
   1270         if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier))
   1271             recover();
   1272 
   1273         // this error check can mutate the type
   1274         if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, false))
   1275             recover();
   1276 
   1277         TVariable* variable = 0;
   1278 
   1279         if (nonInitErrorCheck(identifierLocation, identifier, publicType, variable))
   1280             recover();
   1281 
   1282         if (variable && symbol)
   1283         {
   1284             symbol->setId(variable->getUniqueId());
   1285         }
   1286     }
   1287 
   1288     return aggregate;
   1289 }
   1290 
   1291 TIntermAggregate* TParseContext::parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& indexLocation, TIntermTyped *indexExpression)
   1292 {
   1293     if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier))
   1294         recover();
   1295 
   1296     // this error check can mutate the type
   1297     if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, true))
   1298         recover();
   1299 
   1300     if (arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
   1301     {
   1302         recover();
   1303     }
   1304 
   1305     TPublicType arrayType = publicType;
   1306 
   1307     int size;
   1308     if (arraySizeErrorCheck(identifierLocation, indexExpression, size))
   1309     {
   1310         recover();
   1311     }
   1312     else
   1313     {
   1314         arrayType.setArray(true, size);
   1315     }
   1316 
   1317     TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(arrayType), identifierLocation);
   1318     TIntermAggregate* aggregate = intermediate.makeAggregate(symbol, identifierLocation);
   1319     TVariable* variable = 0;
   1320 
   1321     if (arrayErrorCheck(identifierLocation, identifier, arrayType, variable))
   1322         recover();
   1323 
   1324     if (variable && symbol)
   1325     {
   1326         symbol->setId(variable->getUniqueId());
   1327     }
   1328 
   1329     return aggregate;
   1330 }
   1331 
   1332 TIntermAggregate* TParseContext::parseSingleInitDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer)
   1333 {
   1334     if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier))
   1335         recover();
   1336 
   1337     TIntermNode* intermNode;
   1338     if (!executeInitializer(identifierLocation, identifier, publicType, initializer, intermNode))
   1339     {
   1340         //
   1341         // Build intermediate representation
   1342         //
   1343         return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : NULL;
   1344     }
   1345     else
   1346     {
   1347         recover();
   1348         return NULL;
   1349     }
   1350 }
   1351 
   1352 TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc,
   1353                                                            const TSourceLoc &identifierLoc,
   1354                                                            const TString *identifier,
   1355                                                            const TSymbol *symbol)
   1356 {
   1357     // invariant declaration
   1358     if (globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying"))
   1359     {
   1360         recover();
   1361     }
   1362 
   1363     if (!symbol)
   1364     {
   1365         error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
   1366         recover();
   1367 
   1368         return NULL;
   1369     }
   1370     else
   1371     {
   1372         const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
   1373         ASSERT(variable);
   1374         const TType &type = variable->getType();
   1375         TIntermSymbol *intermSymbol = intermediate.addSymbol(variable->getUniqueId(),
   1376                                                              *identifier, type, identifierLoc);
   1377 
   1378         TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc);
   1379         aggregate->setOp(EOpInvariantDeclaration);
   1380         return aggregate;
   1381     }
   1382 }
   1383 
   1384 TIntermAggregate* TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier)
   1385 {
   1386     TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
   1387     TIntermAggregate* intermAggregate = intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
   1388 
   1389     if (structQualifierErrorCheck(identifierLocation, publicType))
   1390         recover();
   1391 
   1392     if (locationDeclaratorListCheck(identifierLocation, publicType))
   1393         recover();
   1394 
   1395     if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, false))
   1396         recover();
   1397 
   1398     TVariable* variable = 0;
   1399     if (nonInitErrorCheck(identifierLocation, identifier, publicType, variable))
   1400         recover();
   1401     if (symbol && variable)
   1402         symbol->setId(variable->getUniqueId());
   1403 
   1404     return intermAggregate;
   1405 }
   1406 
   1407 TIntermAggregate* TParseContext::parseArrayDeclarator(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& arrayLocation, TIntermNode *declaratorList, TIntermTyped *indexExpression)
   1408 {
   1409     if (structQualifierErrorCheck(identifierLocation, publicType))
   1410         recover();
   1411 
   1412     if (locationDeclaratorListCheck(identifierLocation, publicType))
   1413         recover();
   1414 
   1415     if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, true))
   1416         recover();
   1417 
   1418     if (arrayTypeErrorCheck(arrayLocation, publicType) || arrayQualifierErrorCheck(arrayLocation, publicType))
   1419     {
   1420         recover();
   1421     }
   1422     else if (indexExpression)
   1423     {
   1424         int size;
   1425         if (arraySizeErrorCheck(arrayLocation, indexExpression, size))
   1426             recover();
   1427         TPublicType arrayType(publicType);
   1428         arrayType.setArray(true, size);
   1429         TVariable* variable = NULL;
   1430         if (arrayErrorCheck(arrayLocation, identifier, arrayType, variable))
   1431             recover();
   1432         TType type = TType(arrayType);
   1433         type.setArraySize(size);
   1434 
   1435         return intermediate.growAggregate(declaratorList, intermediate.addSymbol(variable ? variable->getUniqueId() : 0, identifier, type, identifierLocation), identifierLocation);
   1436     }
   1437     else
   1438     {
   1439         TPublicType arrayType(publicType);
   1440         arrayType.setArray(true);
   1441         TVariable* variable = NULL;
   1442         if (arrayErrorCheck(arrayLocation, identifier, arrayType, variable))
   1443             recover();
   1444     }
   1445 
   1446     return NULL;
   1447 }
   1448 
   1449 TIntermAggregate* TParseContext::parseInitDeclarator(TPublicType &publicType, TIntermAggregate *declaratorList, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer)
   1450 {
   1451     if (structQualifierErrorCheck(identifierLocation, publicType))
   1452         recover();
   1453 
   1454     if (locationDeclaratorListCheck(identifierLocation, publicType))
   1455         recover();
   1456 
   1457     TIntermNode* intermNode;
   1458     if (!executeInitializer(identifierLocation, identifier, publicType, initializer, intermNode))
   1459     {
   1460         //
   1461         // build the intermediate representation
   1462         //
   1463         if (intermNode)
   1464         {
   1465             return intermediate.growAggregate(declaratorList, intermNode, initLocation);
   1466         }
   1467         else
   1468         {
   1469             return declaratorList;
   1470         }
   1471     }
   1472     else
   1473     {
   1474         recover();
   1475         return NULL;
   1476     }
   1477 }
   1478 
   1479 void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
   1480 {
   1481     if (typeQualifier.qualifier != EvqUniform)
   1482     {
   1483         error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
   1484         recover();
   1485         return;
   1486     }
   1487 
   1488     const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
   1489     ASSERT(!layoutQualifier.isEmpty());
   1490 
   1491     if (shaderVersion < 300)
   1492     {
   1493         error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 only", "layout");
   1494         recover();
   1495         return;
   1496     }
   1497 
   1498     if (layoutLocationErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier))
   1499     {
   1500         recover();
   1501         return;
   1502     }
   1503 
   1504     if (layoutQualifier.matrixPacking != EmpUnspecified)
   1505     {
   1506         defaultMatrixPacking = layoutQualifier.matrixPacking;
   1507     }
   1508 
   1509     if (layoutQualifier.blockStorage != EbsUnspecified)
   1510     {
   1511         defaultBlockStorage = layoutQualifier.blockStorage;
   1512     }
   1513 }
   1514 
   1515 TFunction *TParseContext::addConstructorFunc(TPublicType publicType)
   1516 {
   1517     TOperator op = EOpNull;
   1518     if (publicType.userDef)
   1519     {
   1520         op = EOpConstructStruct;
   1521     }
   1522     else
   1523     {
   1524         switch (publicType.type)
   1525         {
   1526           case EbtFloat:
   1527             if (publicType.isMatrix())
   1528             {
   1529                 // TODO: non-square matrices
   1530                 switch(publicType.getCols())
   1531                 {
   1532                   case 2: op = EOpConstructMat2;  break;
   1533                   case 3: op = EOpConstructMat3;  break;
   1534                   case 4: op = EOpConstructMat4;  break;
   1535                 }
   1536             }
   1537             else
   1538             {
   1539                 switch(publicType.getNominalSize())
   1540                 {
   1541                   case 1: op = EOpConstructFloat; break;
   1542                   case 2: op = EOpConstructVec2;  break;
   1543                   case 3: op = EOpConstructVec3;  break;
   1544                   case 4: op = EOpConstructVec4;  break;
   1545                 }
   1546             }
   1547             break;
   1548 
   1549           case EbtInt:
   1550             switch(publicType.getNominalSize())
   1551             {
   1552               case 1: op = EOpConstructInt;   break;
   1553               case 2: op = EOpConstructIVec2; break;
   1554               case 3: op = EOpConstructIVec3; break;
   1555               case 4: op = EOpConstructIVec4; break;
   1556             }
   1557             break;
   1558 
   1559           case EbtUInt:
   1560             switch(publicType.getNominalSize())
   1561             {
   1562               case 1: op = EOpConstructUInt;  break;
   1563               case 2: op = EOpConstructUVec2; break;
   1564               case 3: op = EOpConstructUVec3; break;
   1565               case 4: op = EOpConstructUVec4; break;
   1566             }
   1567             break;
   1568 
   1569           case EbtBool:
   1570             switch(publicType.getNominalSize())
   1571             {
   1572                 case 1: op = EOpConstructBool;  break;
   1573                 case 2: op = EOpConstructBVec2; break;
   1574                 case 3: op = EOpConstructBVec3; break;
   1575                 case 4: op = EOpConstructBVec4; break;
   1576             }
   1577             break;
   1578 
   1579           default: break;
   1580         }
   1581 
   1582         if (op == EOpNull)
   1583         {
   1584             error(publicType.line, "cannot construct this type", getBasicString(publicType.type));
   1585             recover();
   1586             publicType.type = EbtFloat;
   1587             op = EOpConstructFloat;
   1588         }
   1589     }
   1590 
   1591     TString tempString;
   1592     TType type(publicType);
   1593     return new TFunction(&tempString, type, op);
   1594 }
   1595 
   1596 // This function is used to test for the correctness of the parameters passed to various constructor functions
   1597 // and also convert them to the right datatype if it is allowed and required.
   1598 //
   1599 // Returns 0 for an error or the constructed node (aggregate or typed) for no error.
   1600 //
   1601 TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType *type, TOperator op, TFunction *fnCall, const TSourceLoc &line)
   1602 {
   1603     TIntermAggregate *aggregateArguments = arguments->getAsAggregate();
   1604 
   1605     if (!aggregateArguments)
   1606     {
   1607         aggregateArguments = new TIntermAggregate;
   1608         aggregateArguments->getSequence()->push_back(arguments);
   1609     }
   1610 
   1611     if (op == EOpConstructStruct)
   1612     {
   1613         const TFieldList &fields = type->getStruct()->fields();
   1614         TIntermSequence *args = aggregateArguments->getSequence();
   1615 
   1616         for (size_t i = 0; i < fields.size(); i++)
   1617         {
   1618             if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type())
   1619             {
   1620                 error(line, "Structure constructor arguments do not match structure fields", "Error");
   1621                 recover();
   1622 
   1623                 return 0;
   1624             }
   1625         }
   1626     }
   1627 
   1628     // Turn the argument list itself into a constructor
   1629     TIntermTyped *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line);
   1630     TIntermTyped *constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
   1631     if (constConstructor)
   1632     {
   1633         return constConstructor;
   1634     }
   1635 
   1636     return constructor;
   1637 }
   1638 
   1639 TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
   1640 {
   1641     bool canBeFolded = areAllChildConst(aggrNode);
   1642     aggrNode->setType(type);
   1643     if (canBeFolded) {
   1644         bool returnVal = false;
   1645         ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
   1646         if (aggrNode->getSequence()->size() == 1)  {
   1647             returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type, true);
   1648         }
   1649         else {
   1650             returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type);
   1651         }
   1652         if (returnVal)
   1653             return 0;
   1654 
   1655         return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
   1656     }
   1657 
   1658     return 0;
   1659 }
   1660 
   1661 //
   1662 // This function returns the tree representation for the vector field(s) being accessed from contant vector.
   1663 // If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
   1664 // returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
   1665 // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
   1666 // a constant matrix.
   1667 //
   1668 TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line)
   1669 {
   1670     TIntermTyped* typedNode;
   1671     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
   1672 
   1673     ConstantUnion *unionArray;
   1674     if (tempConstantNode) {
   1675         unionArray = tempConstantNode->getUnionArrayPointer();
   1676 
   1677         if (!unionArray) {
   1678             return node;
   1679         }
   1680     } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
   1681         error(line, "Cannot offset into the vector", "Error");
   1682         recover();
   1683 
   1684         return 0;
   1685     }
   1686 
   1687     ConstantUnion* constArray = new ConstantUnion[fields.num];
   1688 
   1689     for (int i = 0; i < fields.num; i++) {
   1690         if (fields.offsets[i] >= node->getType().getNominalSize()) {
   1691             std::stringstream extraInfoStream;
   1692             extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
   1693             std::string extraInfo = extraInfoStream.str();
   1694             error(line, "", "[", extraInfo.c_str());
   1695             recover();
   1696             fields.offsets[i] = 0;
   1697         }
   1698 
   1699         constArray[i] = unionArray[fields.offsets[i]];
   1700 
   1701     }
   1702     typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
   1703     return typedNode;
   1704 }
   1705 
   1706 //
   1707 // This function returns the column being accessed from a constant matrix. The values are retrieved from
   1708 // the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
   1709 // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
   1710 // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
   1711 //
   1712 TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line)
   1713 {
   1714     TIntermTyped* typedNode;
   1715     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
   1716 
   1717     if (index >= node->getType().getCols()) {
   1718         std::stringstream extraInfoStream;
   1719         extraInfoStream << "matrix field selection out of range '" << index << "'";
   1720         std::string extraInfo = extraInfoStream.str();
   1721         error(line, "", "[", extraInfo.c_str());
   1722         recover();
   1723         index = 0;
   1724     }
   1725 
   1726     if (tempConstantNode) {
   1727          ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
   1728          int size = tempConstantNode->getType().getCols();
   1729          typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
   1730     } else {
   1731         error(line, "Cannot offset into the matrix", "Error");
   1732         recover();
   1733 
   1734         return 0;
   1735     }
   1736 
   1737     return typedNode;
   1738 }
   1739 
   1740 
   1741 //
   1742 // This function returns an element of an array accessed from a constant array. The values are retrieved from
   1743 // the symbol table and parse-tree is built for the type of the element. The input
   1744 // to the function could either be a symbol node (a[0] where a is a constant array)that represents a
   1745 // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
   1746 //
   1747 TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line)
   1748 {
   1749     TIntermTyped* typedNode;
   1750     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
   1751     TType arrayElementType = node->getType();
   1752     arrayElementType.clearArrayness();
   1753 
   1754     if (index >= node->getType().getArraySize()) {
   1755         std::stringstream extraInfoStream;
   1756         extraInfoStream << "array field selection out of range '" << index << "'";
   1757         std::string extraInfo = extraInfoStream.str();
   1758         error(line, "", "[", extraInfo.c_str());
   1759         recover();
   1760         index = 0;
   1761     }
   1762 
   1763     if (tempConstantNode) {
   1764         size_t arrayElementSize = arrayElementType.getObjectSize();
   1765         ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
   1766         typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
   1767     } else {
   1768         error(line, "Cannot offset into the array", "Error");
   1769         recover();
   1770 
   1771         return 0;
   1772     }
   1773 
   1774     return typedNode;
   1775 }
   1776 
   1777 
   1778 //
   1779 // This function returns the value of a particular field inside a constant structure from the symbol table.
   1780 // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
   1781 // function and returns the parse-tree with the values of the embedded/nested struct.
   1782 //
   1783 TIntermTyped* TParseContext::addConstStruct(const TString &identifier, TIntermTyped *node, const TSourceLoc& line)
   1784 {
   1785     const TFieldList& fields = node->getType().getStruct()->fields();
   1786     size_t instanceSize = 0;
   1787 
   1788     for (size_t index = 0; index < fields.size(); ++index) {
   1789         if (fields[index]->name() == identifier) {
   1790             break;
   1791         } else {
   1792             instanceSize += fields[index]->type()->getObjectSize();
   1793         }
   1794     }
   1795 
   1796     TIntermTyped *typedNode;
   1797     TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
   1798     if (tempConstantNode) {
   1799          ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
   1800 
   1801          typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
   1802     } else {
   1803         error(line, "Cannot offset into the structure", "Error");
   1804         recover();
   1805 
   1806         return 0;
   1807     }
   1808 
   1809     return typedNode;
   1810 }
   1811 
   1812 //
   1813 // Interface/uniform blocks
   1814 //
   1815 TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList,
   1816                                                    const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine)
   1817 {
   1818     if (reservedErrorCheck(nameLine, blockName))
   1819         recover();
   1820 
   1821     if (typeQualifier.qualifier != EvqUniform)
   1822     {
   1823         error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "interface blocks must be uniform");
   1824         recover();
   1825     }
   1826 
   1827     TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
   1828     if (layoutLocationErrorCheck(typeQualifier.line, blockLayoutQualifier))
   1829     {
   1830         recover();
   1831     }
   1832 
   1833     if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
   1834     {
   1835         blockLayoutQualifier.matrixPacking = defaultMatrixPacking;
   1836     }
   1837 
   1838     if (blockLayoutQualifier.blockStorage == EbsUnspecified)
   1839     {
   1840         blockLayoutQualifier.blockStorage = defaultBlockStorage;
   1841     }
   1842 
   1843     TSymbol* blockNameSymbol = new TInterfaceBlockName(&blockName);
   1844     if (!symbolTable.declare(blockNameSymbol)) {
   1845         error(nameLine, "redefinition", blockName.c_str(), "interface block name");
   1846         recover();
   1847     }
   1848 
   1849     // check for sampler types and apply layout qualifiers
   1850     for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) {
   1851         TField* field = (*fieldList)[memberIndex];
   1852         TType* fieldType = field->type();
   1853         if (IsSampler(fieldType->getBasicType())) {
   1854             error(field->line(), "unsupported type", fieldType->getBasicString(), "sampler types are not allowed in interface blocks");
   1855             recover();
   1856         }
   1857 
   1858         const TQualifier qualifier = fieldType->getQualifier();
   1859         switch (qualifier)
   1860         {
   1861           case EvqGlobal:
   1862           case EvqUniform:
   1863             break;
   1864           default:
   1865             error(field->line(), "invalid qualifier on interface block member", getQualifierString(qualifier));
   1866             recover();
   1867             break;
   1868         }
   1869 
   1870         // check layout qualifiers
   1871         TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
   1872         if (layoutLocationErrorCheck(field->line(), fieldLayoutQualifier))
   1873         {
   1874             recover();
   1875         }
   1876 
   1877         if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
   1878         {
   1879             error(field->line(), "invalid layout qualifier:", getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
   1880             recover();
   1881         }
   1882 
   1883         if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
   1884         {
   1885             fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
   1886         }
   1887         else if (!fieldType->isMatrix())
   1888         {
   1889             error(field->line(), "invalid layout qualifier:", getMatrixPackingString(fieldLayoutQualifier.matrixPacking), "can only be used on matrix types");
   1890             recover();
   1891         }
   1892 
   1893         fieldType->setLayoutQualifier(fieldLayoutQualifier);
   1894     }
   1895 
   1896     // add array index
   1897     int arraySize = 0;
   1898     if (arrayIndex != NULL)
   1899     {
   1900         if (arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize))
   1901             recover();
   1902     }
   1903 
   1904     TInterfaceBlock* interfaceBlock = new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
   1905     TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier, arraySize);
   1906 
   1907     TString symbolName = "";
   1908     int symbolId = 0;
   1909 
   1910     if (!instanceName)
   1911     {
   1912         // define symbols for the members of the interface block
   1913         for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
   1914         {
   1915             TField* field = (*fieldList)[memberIndex];
   1916             TType* fieldType = field->type();
   1917 
   1918             // set parent pointer of the field variable
   1919             fieldType->setInterfaceBlock(interfaceBlock);
   1920 
   1921             TVariable* fieldVariable = new TVariable(&field->name(), *fieldType);
   1922             fieldVariable->setQualifier(typeQualifier.qualifier);
   1923 
   1924             if (!symbolTable.declare(fieldVariable)) {
   1925                 error(field->line(), "redefinition", field->name().c_str(), "interface block member name");
   1926                 recover();
   1927             }
   1928         }
   1929     }
   1930     else
   1931     {
   1932         // add a symbol for this interface block
   1933         TVariable* instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
   1934         instanceTypeDef->setQualifier(typeQualifier.qualifier);
   1935 
   1936         if (!symbolTable.declare(instanceTypeDef)) {
   1937             error(instanceLine, "redefinition", instanceName->c_str(), "interface block instance name");
   1938             recover();
   1939         }
   1940 
   1941         symbolId = instanceTypeDef->getUniqueId();
   1942         symbolName = instanceTypeDef->getName();
   1943     }
   1944 
   1945     TIntermAggregate *aggregate = intermediate.makeAggregate(intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line), nameLine);
   1946     aggregate->setOp(EOpDeclaration);
   1947 
   1948     exitStructDeclaration();
   1949     return aggregate;
   1950 }
   1951 
   1952 bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier)
   1953 {
   1954     ++structNestingLevel;
   1955 
   1956     // Embedded structure definitions are not supported per GLSL ES spec.
   1957     // They aren't allowed in GLSL either, but we need to detect this here
   1958     // so we don't rely on the GLSL compiler to catch it.
   1959     if (structNestingLevel > 1) {
   1960         error(line, "", "Embedded struct definitions are not allowed");
   1961         return true;
   1962     }
   1963 
   1964     return false;
   1965 }
   1966 
   1967 void TParseContext::exitStructDeclaration()
   1968 {
   1969     --structNestingLevel;
   1970 }
   1971 
   1972 namespace {
   1973 
   1974 const int kWebGLMaxStructNesting = 4;
   1975 
   1976 }  // namespace
   1977 
   1978 bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field)
   1979 {
   1980     if (!IsWebGLBasedSpec(shaderSpec)) {
   1981         return false;
   1982     }
   1983 
   1984     if (field.type()->getBasicType() != EbtStruct) {
   1985         return false;
   1986     }
   1987 
   1988     // We're already inside a structure definition at this point, so add
   1989     // one to the field's struct nesting.
   1990     if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) {
   1991         std::stringstream reasonStream;
   1992         reasonStream << "Reference of struct type "
   1993                      << field.type()->getStruct()->name().c_str()
   1994                      << " exceeds maximum allowed nesting level of "
   1995                      << kWebGLMaxStructNesting;
   1996         std::string reason = reasonStream.str();
   1997         error(line, reason.c_str(), field.name().c_str(), "");
   1998         return true;
   1999     }
   2000 
   2001     return false;
   2002 }
   2003 
   2004 //
   2005 // Parse an array index expression
   2006 //
   2007 TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression)
   2008 {
   2009     TIntermTyped *indexedExpression = NULL;
   2010 
   2011     if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
   2012     {
   2013         if (baseExpression->getAsSymbolNode())
   2014         {
   2015             error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str());
   2016         }
   2017         else
   2018         {
   2019             error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
   2020         }
   2021         recover();
   2022     }
   2023 
   2024     if (indexExpression->getQualifier() == EvqConst)
   2025     {
   2026         int index = indexExpression->getAsConstantUnion()->getIConst(0);
   2027         if (index < 0)
   2028         {
   2029             std::stringstream infoStream;
   2030             infoStream << index;
   2031             std::string info = infoStream.str();
   2032             error(location, "negative index", info.c_str());
   2033             recover();
   2034             index = 0;
   2035         }
   2036         if (baseExpression->getType().getQualifier() == EvqConst)
   2037         {
   2038             if (baseExpression->isArray())
   2039             {
   2040                 // constant folding for arrays
   2041                 indexedExpression = addConstArrayNode(index, baseExpression, location);
   2042             }
   2043             else if (baseExpression->isVector())
   2044             {
   2045                 // constant folding for vectors
   2046                 TVectorFields fields;
   2047                 fields.num = 1;
   2048                 fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
   2049                 indexedExpression = addConstVectorNode(fields, baseExpression, location);
   2050             }
   2051             else if (baseExpression->isMatrix())
   2052             {
   2053                 // constant folding for matrices
   2054                 indexedExpression = addConstMatrixNode(index, baseExpression, location);
   2055             }
   2056         }
   2057         else
   2058         {
   2059             if (baseExpression->isArray())
   2060             {
   2061                 if (index >= baseExpression->getType().getArraySize())
   2062                 {
   2063                     std::stringstream extraInfoStream;
   2064                     extraInfoStream << "array index out of range '" << index << "'";
   2065                     std::string extraInfo = extraInfoStream.str();
   2066                     error(location, "", "[", extraInfo.c_str());
   2067                     recover();
   2068                     index = baseExpression->getType().getArraySize() - 1;
   2069                 }
   2070                 else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers"))
   2071                 {
   2072                     error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled");
   2073                     recover();
   2074                     index = 0;
   2075                 }
   2076             }
   2077             else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index)
   2078             {
   2079                 std::stringstream extraInfoStream;
   2080                 extraInfoStream << "field selection out of range '" << index << "'";
   2081                 std::string extraInfo = extraInfoStream.str();
   2082                 error(location, "", "[", extraInfo.c_str());
   2083                 recover();
   2084                 index = baseExpression->getType().getNominalSize() - 1;
   2085             }
   2086 
   2087             indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
   2088             indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
   2089         }
   2090     }
   2091     else
   2092     {
   2093         if (baseExpression->isInterfaceBlock())
   2094         {
   2095             error(location, "", "[", "array indexes for interface blocks arrays must be constant integral expressions");
   2096             recover();
   2097         }
   2098         else if (baseExpression->getQualifier() == EvqFragmentOut)
   2099         {
   2100             error(location, "", "[", "array indexes for fragment outputs must be constant integral expressions");
   2101             recover();
   2102         }
   2103 
   2104         indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
   2105     }
   2106 
   2107     if (indexedExpression == 0)
   2108     {
   2109         ConstantUnion *unionArray = new ConstantUnion[1];
   2110         unionArray->setFConst(0.0f);
   2111         indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
   2112     }
   2113     else if (baseExpression->isArray())
   2114     {
   2115         const TType &baseType = baseExpression->getType();
   2116         if (baseType.getStruct())
   2117         {
   2118             TType copyOfType(baseType.getStruct());
   2119             indexedExpression->setType(copyOfType);
   2120         }
   2121         else if (baseType.isInterfaceBlock())
   2122         {
   2123             TType copyOfType(baseType.getInterfaceBlock(), baseType.getQualifier(), baseType.getLayoutQualifier(), 0);
   2124             indexedExpression->setType(copyOfType);
   2125         }
   2126         else
   2127         {
   2128             indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->getSecondarySize()));
   2129         }
   2130 
   2131         if (baseExpression->getType().getQualifier() == EvqConst)
   2132         {
   2133             indexedExpression->getTypePointer()->setQualifier(EvqConst);
   2134         }
   2135     }
   2136     else if (baseExpression->isMatrix())
   2137     {
   2138         TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
   2139         indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getRows()));
   2140     }
   2141     else if (baseExpression->isVector())
   2142     {
   2143         TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
   2144         indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
   2145     }
   2146     else
   2147     {
   2148         indexedExpression->setType(baseExpression->getType());
   2149     }
   2150 
   2151     return indexedExpression;
   2152 }
   2153 
   2154 TIntermTyped* TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc& dotLocation, const TString &fieldString, const TSourceLoc& fieldLocation)
   2155 {
   2156     TIntermTyped *indexedExpression = NULL;
   2157 
   2158     if (baseExpression->isArray())
   2159     {
   2160         error(fieldLocation, "cannot apply dot operator to an array", ".");
   2161         recover();
   2162     }
   2163 
   2164     if (baseExpression->isVector())
   2165     {
   2166         TVectorFields fields;
   2167         if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields, fieldLocation))
   2168         {
   2169             fields.num = 1;
   2170             fields.offsets[0] = 0;
   2171             recover();
   2172         }
   2173 
   2174         if (baseExpression->getType().getQualifier() == EvqConst)
   2175         {
   2176             // constant folding for vector fields
   2177             indexedExpression = addConstVectorNode(fields, baseExpression, fieldLocation);
   2178             if (indexedExpression == 0)
   2179             {
   2180                 recover();
   2181                 indexedExpression = baseExpression;
   2182             }
   2183             else
   2184             {
   2185                 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqConst, (int) (fieldString).size()));
   2186             }
   2187         }
   2188         else
   2189         {
   2190             TString vectorString = fieldString;
   2191             TIntermTyped* index = intermediate.addSwizzle(fields, fieldLocation);
   2192             indexedExpression = intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation);
   2193             indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, (int) vectorString.size()));
   2194         }
   2195     }
   2196     else if (baseExpression->isMatrix())
   2197     {
   2198         TMatrixFields fields;
   2199         if (!parseMatrixFields(fieldString, baseExpression->getCols(), baseExpression->getRows(), fields, fieldLocation))
   2200         {
   2201             fields.wholeRow = false;
   2202             fields.wholeCol = false;
   2203             fields.row = 0;
   2204             fields.col = 0;
   2205             recover();
   2206         }
   2207 
   2208         if (fields.wholeRow || fields.wholeCol)
   2209         {
   2210             error(dotLocation, " non-scalar fields not implemented yet", ".");
   2211             recover();
   2212             ConstantUnion *unionArray = new ConstantUnion[1];
   2213             unionArray->setIConst(0);
   2214             TIntermTyped* index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), fieldLocation);
   2215             indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation);
   2216             indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),EvqTemporary, baseExpression->getCols(), baseExpression->getRows()));
   2217         }
   2218         else
   2219         {
   2220             ConstantUnion *unionArray = new ConstantUnion[1];
   2221             unionArray->setIConst(fields.col * baseExpression->getRows() + fields.row);
   2222             TIntermTyped* index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), fieldLocation);
   2223             indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation);
   2224             indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision()));
   2225         }
   2226     }
   2227     else if (baseExpression->getBasicType() == EbtStruct)
   2228     {
   2229         bool fieldFound = false;
   2230         const TFieldList& fields = baseExpression->getType().getStruct()->fields();
   2231         if (fields.empty())
   2232         {
   2233             error(dotLocation, "structure has no fields", "Internal Error");
   2234             recover();
   2235             indexedExpression = baseExpression;
   2236         }
   2237         else
   2238         {
   2239             unsigned int i;
   2240             for (i = 0; i < fields.size(); ++i)
   2241             {
   2242                 if (fields[i]->name() == fieldString)
   2243                 {
   2244                     fieldFound = true;
   2245                     break;
   2246                 }
   2247             }
   2248             if (fieldFound)
   2249             {
   2250                 if (baseExpression->getType().getQualifier() == EvqConst)
   2251                 {
   2252                     indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
   2253                     if (indexedExpression == 0)
   2254                     {
   2255                         recover();
   2256                         indexedExpression = baseExpression;
   2257                     }
   2258                     else
   2259                     {
   2260                         indexedExpression->setType(*fields[i]->type());
   2261                         // change the qualifier of the return type, not of the structure field
   2262                         // as the structure definition is shared between various structures.
   2263                         indexedExpression->getTypePointer()->setQualifier(EvqConst);
   2264                     }
   2265                 }
   2266                 else
   2267                 {
   2268                     ConstantUnion *unionArray = new ConstantUnion[1];
   2269                     unionArray->setIConst(i);
   2270                     TIntermTyped* index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
   2271                     indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index, dotLocation);
   2272                     indexedExpression->setType(*fields[i]->type());
   2273                 }
   2274             }
   2275             else
   2276             {
   2277                 error(dotLocation, " no such field in structure", fieldString.c_str());
   2278                 recover();
   2279                 indexedExpression = baseExpression;
   2280             }
   2281         }
   2282     }
   2283     else if (baseExpression->isInterfaceBlock())
   2284     {
   2285         bool fieldFound = false;
   2286         const TFieldList& fields = baseExpression->getType().getInterfaceBlock()->fields();
   2287         if (fields.empty())
   2288         {
   2289             error(dotLocation, "interface block has no fields", "Internal Error");
   2290             recover();
   2291             indexedExpression = baseExpression;
   2292         }
   2293         else
   2294         {
   2295             unsigned int i;
   2296             for (i = 0; i < fields.size(); ++i)
   2297             {
   2298                 if (fields[i]->name() == fieldString)
   2299                 {
   2300                     fieldFound = true;
   2301                     break;
   2302                 }
   2303             }
   2304             if (fieldFound)
   2305             {
   2306                 ConstantUnion *unionArray = new ConstantUnion[1];
   2307                 unionArray->setIConst(i);
   2308                 TIntermTyped* index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
   2309                 indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index, dotLocation);
   2310                 indexedExpression->setType(*fields[i]->type());
   2311             }
   2312             else
   2313             {
   2314                 error(dotLocation, " no such field in interface block", fieldString.c_str());
   2315                 recover();
   2316                 indexedExpression = baseExpression;
   2317             }
   2318         }
   2319     }
   2320     else
   2321     {
   2322         if (shaderVersion < 300)
   2323         {
   2324             error(dotLocation, " field selection requires structure, vector, or matrix on left hand side", fieldString.c_str());
   2325         }
   2326         else
   2327         {
   2328             error(dotLocation, " field selection requires structure, vector, matrix, or interface block on left hand side", fieldString.c_str());
   2329         }
   2330         recover();
   2331         indexedExpression = baseExpression;
   2332     }
   2333 
   2334     return indexedExpression;
   2335 }
   2336 
   2337 TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine)
   2338 {
   2339     TLayoutQualifier qualifier;
   2340 
   2341     qualifier.location = -1;
   2342     qualifier.matrixPacking = EmpUnspecified;
   2343     qualifier.blockStorage = EbsUnspecified;
   2344 
   2345     if (qualifierType == "shared")
   2346     {
   2347         qualifier.blockStorage = EbsShared;
   2348     }
   2349     else if (qualifierType == "packed")
   2350     {
   2351         qualifier.blockStorage = EbsPacked;
   2352     }
   2353     else if (qualifierType == "std140")
   2354     {
   2355         qualifier.blockStorage = EbsStd140;
   2356     }
   2357     else if (qualifierType == "row_major")
   2358     {
   2359         qualifier.matrixPacking = EmpRowMajor;
   2360     }
   2361     else if (qualifierType == "column_major")
   2362     {
   2363         qualifier.matrixPacking = EmpColumnMajor;
   2364     }
   2365     else if (qualifierType == "location")
   2366     {
   2367         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "location requires an argument");
   2368         recover();
   2369     }
   2370     else
   2371     {
   2372         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
   2373         recover();
   2374     }
   2375 
   2376     return qualifier;
   2377 }
   2378 
   2379 TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine)
   2380 {
   2381     TLayoutQualifier qualifier;
   2382 
   2383     qualifier.location = -1;
   2384     qualifier.matrixPacking = EmpUnspecified;
   2385     qualifier.blockStorage = EbsUnspecified;
   2386 
   2387     if (qualifierType != "location")
   2388     {
   2389         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "only location may have arguments");
   2390         recover();
   2391     }
   2392     else
   2393     {
   2394         // must check that location is non-negative
   2395         if (intValue < 0)
   2396         {
   2397             error(intValueLine, "out of range:", intValueString.c_str(), "location must be non-negative");
   2398             recover();
   2399         }
   2400         else
   2401         {
   2402             qualifier.location = intValue;
   2403         }
   2404     }
   2405 
   2406     return qualifier;
   2407 }
   2408 
   2409 TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier)
   2410 {
   2411     TLayoutQualifier joinedQualifier = leftQualifier;
   2412 
   2413     if (rightQualifier.location != -1)
   2414     {
   2415         joinedQualifier.location = rightQualifier.location;
   2416     }
   2417     if (rightQualifier.matrixPacking != EmpUnspecified)
   2418     {
   2419         joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
   2420     }
   2421     if (rightQualifier.blockStorage != EbsUnspecified)
   2422     {
   2423         joinedQualifier.blockStorage = rightQualifier.blockStorage;
   2424     }
   2425 
   2426     return joinedQualifier;
   2427 }
   2428 
   2429 TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier,
   2430                                                        const TSourceLoc &storageLoc, TQualifier storageQualifier)
   2431 {
   2432     TQualifier mergedQualifier = EvqSmoothIn;
   2433 
   2434     if (storageQualifier == EvqFragmentIn) {
   2435         if (interpolationQualifier == EvqSmooth)
   2436             mergedQualifier = EvqSmoothIn;
   2437         else if (interpolationQualifier == EvqFlat)
   2438             mergedQualifier = EvqFlatIn;
   2439         else UNREACHABLE();
   2440     }
   2441     else if (storageQualifier == EvqCentroidIn) {
   2442         if (interpolationQualifier == EvqSmooth)
   2443             mergedQualifier = EvqCentroidIn;
   2444         else if (interpolationQualifier == EvqFlat)
   2445             mergedQualifier = EvqFlatIn;
   2446         else UNREACHABLE();
   2447     }
   2448     else if (storageQualifier == EvqVertexOut) {
   2449         if (interpolationQualifier == EvqSmooth)
   2450             mergedQualifier = EvqSmoothOut;
   2451         else if (interpolationQualifier == EvqFlat)
   2452             mergedQualifier = EvqFlatOut;
   2453         else UNREACHABLE();
   2454     }
   2455     else if (storageQualifier == EvqCentroidOut) {
   2456         if (interpolationQualifier == EvqSmooth)
   2457             mergedQualifier = EvqCentroidOut;
   2458         else if (interpolationQualifier == EvqFlat)
   2459             mergedQualifier = EvqFlatOut;
   2460         else UNREACHABLE();
   2461     }
   2462     else {
   2463         error(interpolationLoc, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getInterpolationString(interpolationQualifier));
   2464         recover();
   2465 
   2466         mergedQualifier = storageQualifier;
   2467     }
   2468 
   2469     TPublicType type;
   2470     type.setBasic(EbtVoid, mergedQualifier, storageLoc);
   2471     return type;
   2472 }
   2473 
   2474 TFieldList *TParseContext::addStructDeclaratorList(const TPublicType& typeSpecifier, TFieldList *fieldList)
   2475 {
   2476     if (voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier)) {
   2477         recover();
   2478     }
   2479 
   2480     for (unsigned int i = 0; i < fieldList->size(); ++i) {
   2481         //
   2482         // Careful not to replace already known aspects of type, like array-ness
   2483         //
   2484         TType* type = (*fieldList)[i]->type();
   2485         type->setBasicType(typeSpecifier.type);
   2486         type->setPrimarySize(typeSpecifier.primarySize);
   2487         type->setSecondarySize(typeSpecifier.secondarySize);
   2488         type->setPrecision(typeSpecifier.precision);
   2489         type->setQualifier(typeSpecifier.qualifier);
   2490         type->setLayoutQualifier(typeSpecifier.layoutQualifier);
   2491 
   2492         // don't allow arrays of arrays
   2493         if (type->isArray()) {
   2494             if (arrayTypeErrorCheck(typeSpecifier.line, typeSpecifier))
   2495                 recover();
   2496         }
   2497         if (typeSpecifier.array)
   2498             type->setArraySize(typeSpecifier.arraySize);
   2499         if (typeSpecifier.userDef) {
   2500             type->setStruct(typeSpecifier.userDef->getStruct());
   2501         }
   2502 
   2503         if (structNestingErrorCheck(typeSpecifier.line, *(*fieldList)[i])) {
   2504             recover();
   2505         }
   2506     }
   2507 
   2508     return fieldList;
   2509 }
   2510 
   2511 TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSourceLoc& nameLine, const TString *structName, TFieldList* fieldList)
   2512 {
   2513     TStructure* structure = new TStructure(structName, fieldList);
   2514     TType* structureType = new TType(structure);
   2515 
   2516     structure->setUniqueId(TSymbolTable::nextUniqueId());
   2517 
   2518     if (!structName->empty())
   2519     {
   2520         if (reservedErrorCheck(nameLine, *structName))
   2521         {
   2522             recover();
   2523         }
   2524         TVariable* userTypeDef = new TVariable(structName, *structureType, true);
   2525         if (!symbolTable.declare(userTypeDef)) {
   2526             error(nameLine, "redefinition", structName->c_str(), "struct");
   2527             recover();
   2528         }
   2529     }
   2530 
   2531     // ensure we do not specify any storage qualifiers on the struct members
   2532     for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
   2533     {
   2534         const TField &field = *(*fieldList)[typeListIndex];
   2535         const TQualifier qualifier = field.type()->getQualifier();
   2536         switch (qualifier)
   2537         {
   2538           case EvqGlobal:
   2539           case EvqTemporary:
   2540             break;
   2541           default:
   2542             error(field.line(), "invalid qualifier on struct member", getQualifierString(qualifier));
   2543             recover();
   2544             break;
   2545         }
   2546     }
   2547 
   2548     TPublicType publicType;
   2549     publicType.setBasic(EbtStruct, EvqTemporary, structLine);
   2550     publicType.userDef = structureType;
   2551     exitStructDeclaration();
   2552 
   2553     return publicType;
   2554 }
   2555 
   2556 //
   2557 // Parse an array of strings using yyparse.
   2558 //
   2559 // Returns 0 for success.
   2560 //
   2561 int PaParseStrings(size_t count, const char* const string[], const int length[],
   2562                    TParseContext* context) {
   2563     if ((count == 0) || (string == NULL))
   2564         return 1;
   2565 
   2566     if (glslang_initialize(context))
   2567         return 1;
   2568 
   2569     int error = glslang_scan(count, string, length, context);
   2570     if (!error)
   2571         error = glslang_parse(context);
   2572 
   2573     glslang_finalize(context);
   2574 
   2575     return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
   2576 }
   2577 
   2578 
   2579 
   2580