• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //
parseVectorFields(const TString & compString,int vecSize,TVectorFields & fields,const TSourceLoc & line)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 //
parseMatrixFields(const TString & compString,int matCols,int matRows,TMatrixFields & fields,const TSourceLoc & line)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 //
recover()171 void TParseContext::recover()
172 {
173 }
174 
175 //
176 // Used by flex/bison to output all syntax and parsing errors.
177 //
error(const TSourceLoc & loc,const char * reason,const char * token,const char * extraInfo)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 
warning(const TSourceLoc & loc,const char * reason,const char * token,const char * extraInfo)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 
trace(const char * str)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 //
assignError(const TSourceLoc & line,const char * op,TString left,TString right)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 //
unaryOpError(const TSourceLoc & line,const char * op,TString operand)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 //
binaryOpError(const TSourceLoc & line,const char * op,TString left,TString right)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 
precisionErrorCheck(const TSourceLoc & line,TPrecision precision,TBasicType type)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 //
lValueErrorCheck(const TSourceLoc & line,const char * op,TIntermTyped * node)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 //
constErrorCheck(TIntermTyped * node)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 //
integerErrorCheck(TIntermTyped * node,const char * token)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 //
globalErrorCheck(const TSourceLoc & line,bool global,const char * token)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 //
reservedErrorCheck(const TSourceLoc & line,const TString & identifier)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 //
constructorErrorCheck(const TSourceLoc & line,TIntermNode * node,TFunction & function,TOperator op,TType * type)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 //
voidErrorCheck(const TSourceLoc & line,const TString & identifier,const TPublicType & pubType)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 //
boolErrorCheck(const TSourceLoc & line,const TIntermTyped * type)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 //
boolErrorCheck(const TSourceLoc & line,const TPublicType & pType)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 
samplerErrorCheck(const TSourceLoc & line,const TPublicType & pType,const char * reason)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 
structQualifierErrorCheck(const TSourceLoc & line,const TPublicType & pType)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 
locationDeclaratorListCheck(const TSourceLoc & line,const TPublicType & pType)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 
parameterSamplerErrorCheck(const TSourceLoc & line,TQualifier qualifier,const TType & type)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 
containsSampler(TType & type)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 //
arraySizeErrorCheck(const TSourceLoc & line,TIntermTyped * expr,int & size)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 //
arrayQualifierErrorCheck(const TSourceLoc & line,TPublicType type)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 //
arrayTypeErrorCheck(const TSourceLoc & line,TPublicType type)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 //
arrayErrorCheck(const TSourceLoc & line,const TString & identifier,const TPublicType & type,TVariable * & variable)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 //
nonInitConstErrorCheck(const TSourceLoc & line,const TString & identifier,TPublicType & type,bool array)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 //
nonInitErrorCheck(const TSourceLoc & line,const TString & identifier,const TPublicType & type,TVariable * & variable)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 
paramErrorCheck(const TSourceLoc & line,TQualifier qualifier,TQualifier paramQualifier,TType * type)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 
extensionErrorCheck(const TSourceLoc & line,const TString & extension)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 
singleDeclarationErrorCheck(TPublicType & publicType,const TSourceLoc & identifierLocation,const TString & identifier)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 
layoutLocationErrorCheck(const TSourceLoc & location,const TLayoutQualifier & layoutQualifier)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 
supportsExtension(const char * extension)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 
isExtensionEnabled(const char * extension) const986 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 
handleExtensionDirective(const TSourceLoc & loc,const char * extName,const char * behavior)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 
handlePragmaDirective(const TSourceLoc & loc,const char * name,const char * value)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 
getNamedVariable(const TSourceLoc & location,const TString * name,const TSymbol * symbol)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 //
findFunction(const TSourceLoc & line,TFunction * call,int shaderVersion,bool * builtIn)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 //
executeInitializer(const TSourceLoc & line,const TString & identifier,TPublicType & pType,TIntermTyped * initializer,TIntermNode * & intermNode,TVariable * variable)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 
areAllChildConst(TIntermAggregate * aggrNode)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 
addFullySpecifiedType(TQualifier qualifier,TLayoutQualifier layoutQualifier,const TPublicType & typeSpecifier)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 
parseSingleDeclaration(TPublicType & publicType,const TSourceLoc & identifierLocation,const TString & identifier)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 
parseSingleArrayDeclaration(TPublicType & publicType,const TSourceLoc & identifierLocation,const TString & identifier,const TSourceLoc & indexLocation,TIntermTyped * indexExpression)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 
parseSingleInitDeclaration(TPublicType & publicType,const TSourceLoc & identifierLocation,const TString & identifier,const TSourceLoc & initLocation,TIntermTyped * initializer)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 
parseInvariantDeclaration(const TSourceLoc & invariantLoc,const TSourceLoc & identifierLoc,const TString * identifier,const TSymbol * symbol)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 
parseDeclarator(TPublicType & publicType,TIntermAggregate * aggregateDeclaration,TSymbol * identifierSymbol,const TSourceLoc & identifierLocation,const TString & identifier)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 
parseArrayDeclarator(TPublicType & publicType,const TSourceLoc & identifierLocation,const TString & identifier,const TSourceLoc & arrayLocation,TIntermNode * declaratorList,TIntermTyped * indexExpression)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 
parseInitDeclarator(TPublicType & publicType,TIntermAggregate * declaratorList,const TSourceLoc & identifierLocation,const TString & identifier,const TSourceLoc & initLocation,TIntermTyped * initializer)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 
parseGlobalLayoutQualifier(const TPublicType & typeQualifier)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 
addConstructorFunc(TPublicType publicType)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 //
addConstructor(TIntermNode * arguments,const TType * type,TOperator op,TFunction * fnCall,const TSourceLoc & line)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 
foldConstConstructor(TIntermAggregate * aggrNode,const TType & type)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 //
addConstVectorNode(TVectorFields & fields,TIntermTyped * node,const TSourceLoc & line)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 //
addConstMatrixNode(int index,TIntermTyped * node,const TSourceLoc & line)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 //
addConstArrayNode(int index,TIntermTyped * node,const TSourceLoc & line)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 //
addConstStruct(const TString & identifier,TIntermTyped * node,const TSourceLoc & line)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 //
addInterfaceBlock(const TPublicType & typeQualifier,const TSourceLoc & nameLine,const TString & blockName,TFieldList * fieldList,const TString * instanceName,const TSourceLoc & instanceLine,TIntermTyped * arrayIndex,const TSourceLoc & arrayIndexLine)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 
enterStructDeclaration(const TSourceLoc & line,const TString & identifier)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 
exitStructDeclaration()1967 void TParseContext::exitStructDeclaration()
1968 {
1969     --structNestingLevel;
1970 }
1971 
1972 namespace {
1973 
1974 const int kWebGLMaxStructNesting = 4;
1975 
1976 }  // namespace
1977 
structNestingErrorCheck(const TSourceLoc & line,const TField & field)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 //
addIndexExpression(TIntermTyped * baseExpression,const TSourceLoc & location,TIntermTyped * indexExpression)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 
addFieldSelectionExpression(TIntermTyped * baseExpression,const TSourceLoc & dotLocation,const TString & fieldString,const TSourceLoc & fieldLocation)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 
parseLayoutQualifier(const TString & qualifierType,const TSourceLoc & qualifierTypeLine)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 
parseLayoutQualifier(const TString & qualifierType,const TSourceLoc & qualifierTypeLine,const TString & intValueString,int intValue,const TSourceLoc & intValueLine)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 
joinLayoutQualifiers(TLayoutQualifier leftQualifier,TLayoutQualifier rightQualifier)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 
joinInterpolationQualifiers(const TSourceLoc & interpolationLoc,TQualifier interpolationQualifier,const TSourceLoc & storageLoc,TQualifier storageQualifier)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 
addStructDeclaratorList(const TPublicType & typeSpecifier,TFieldList * fieldList)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 
addStructure(const TSourceLoc & structLine,const TSourceLoc & nameLine,const TString * structName,TFieldList * fieldList)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 //
PaParseStrings(size_t count,const char * const string[],const int length[],TParseContext * context)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