zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ParseHelper.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2002-2013 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/ParseHelper.h"
8 
9 #include <stdarg.h>
10 #include <stdio.h>
11 
12 #include "compiler/glslang.h"
14 
16 //
17 // Sub- vector and matrix fields
18 //
20 
21 //
22 // Look at a '.' field selector string and change it into offsets
23 // for a vector.
24 //
25 bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc& line)
26 {
27  fields.num = (int) compString.size();
28  if (fields.num > 4) {
29  error(line, "illegal vector field selection", compString.c_str());
30  return false;
31  }
32 
33  enum {
34  exyzw,
35  ergba,
36  estpq
37  } fieldSet[4];
38 
39  for (int i = 0; i < fields.num; ++i) {
40  switch (compString[i]) {
41  case 'x':
42  fields.offsets[i] = 0;
43  fieldSet[i] = exyzw;
44  break;
45  case 'r':
46  fields.offsets[i] = 0;
47  fieldSet[i] = ergba;
48  break;
49  case 's':
50  fields.offsets[i] = 0;
51  fieldSet[i] = estpq;
52  break;
53  case 'y':
54  fields.offsets[i] = 1;
55  fieldSet[i] = exyzw;
56  break;
57  case 'g':
58  fields.offsets[i] = 1;
59  fieldSet[i] = ergba;
60  break;
61  case 't':
62  fields.offsets[i] = 1;
63  fieldSet[i] = estpq;
64  break;
65  case 'z':
66  fields.offsets[i] = 2;
67  fieldSet[i] = exyzw;
68  break;
69  case 'b':
70  fields.offsets[i] = 2;
71  fieldSet[i] = ergba;
72  break;
73  case 'p':
74  fields.offsets[i] = 2;
75  fieldSet[i] = estpq;
76  break;
77 
78  case 'w':
79  fields.offsets[i] = 3;
80  fieldSet[i] = exyzw;
81  break;
82  case 'a':
83  fields.offsets[i] = 3;
84  fieldSet[i] = ergba;
85  break;
86  case 'q':
87  fields.offsets[i] = 3;
88  fieldSet[i] = estpq;
89  break;
90  default:
91  error(line, "illegal vector field selection", compString.c_str());
92  return false;
93  }
94  }
95 
96  for (int i = 0; i < fields.num; ++i) {
97  if (fields.offsets[i] >= vecSize) {
98  error(line, "vector field selection out of range", compString.c_str());
99  return false;
100  }
101 
102  if (i > 0) {
103  if (fieldSet[i] != fieldSet[i-1]) {
104  error(line, "illegal - vector component fields not from the same set", compString.c_str());
105  return false;
106  }
107  }
108  }
109 
110  return true;
111 }
112 
113 
114 //
115 // Look at a '.' field selector string and change it into offsets
116 // for a matrix.
117 //
118 bool TParseContext::parseMatrixFields(const TString& compString, int matSize, 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 >= matSize || fields.col >= matSize) {
155  error(line, "matrix field selection out of range", compString.c_str());
156  return false;
157  }
158 
159  return true;
160 }
161 
163 //
164 // Errors
165 //
167 
168 //
169 // Track whether errors have occurred.
170 //
172 {
173 }
174 
175 //
176 // Used by flex/bison to output all syntax and parsing errors.
177 //
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;
186  srcLoc, reason, token, extraInfo);
187 
188 }
189 
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;
197  srcLoc, reason, token, extraInfo);
198 }
199 
200 void TParseContext::trace(const char* str)
201 {
202  diagnostics.writeDebug(str);
203 }
204 
205 //
206 // Same error message for all places assignments don't work.
207 //
208 void TParseContext::assignError(const TSourceLoc& line, const char* op, TString left, TString right)
209 {
210  std::stringstream extraInfoStream;
211  extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
212  std::string extraInfo = extraInfoStream.str();
213  error(line, "", op, extraInfo.c_str());
214 }
215 
216 //
217 // Same error message for all places unary operations don't work.
218 //
219 void TParseContext::unaryOpError(const TSourceLoc& line, const char* op, TString operand)
220 {
221  std::stringstream extraInfoStream;
222  extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand
223  << " (or there is no acceptable conversion)";
224  std::string extraInfo = extraInfoStream.str();
225  error(line, " wrong operand type", op, extraInfo.c_str());
226 }
227 
228 //
229 // Same error message for all binary operations don't work.
230 //
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 
242  return false;
243  switch( type ){
244  case EbtFloat:
245  if( precision == EbpUndefined ){
246  error( line, "No precision specified for (float)", "" );
247  return true;
248  }
249  break;
250  case EbtInt:
251  if( precision == EbpUndefined ){
252  error( line, "No precision specified (int)", "" );
253  return true;
254  }
255  break;
256  default:
257  return false;
258  }
259  return false;
260 }
261 
262 //
263 // Both test and if necessary, spit out an error, to see if the node is really
264 // an l-value that can be operated on this way.
265 //
266 // Returns true if the was an error.
267 //
268 bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped* node)
269 {
270  TIntermSymbol* symNode = node->getAsSymbolNode();
271  TIntermBinary* binaryNode = node->getAsBinaryNode();
272 
273  if (binaryNode) {
274  bool errorReturn;
275 
276  switch(binaryNode->getOp()) {
277  case EOpIndexDirect:
278  case EOpIndexIndirect:
280  return lValueErrorCheck(line, op, binaryNode->getLeft());
281  case EOpVectorSwizzle:
282  errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
283  if (!errorReturn) {
284  int offset[4] = {0,0,0,0};
285 
286  TIntermTyped* rightNode = binaryNode->getRight();
287  TIntermAggregate *aggrNode = rightNode->getAsAggregate();
288 
289  for (TIntermSequence::iterator p = aggrNode->getSequence().begin();
290  p != aggrNode->getSequence().end(); p++) {
291  int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0);
292  offset[value]++;
293  if (offset[value] > 1) {
294  error(line, " l-value of swizzle cannot have duplicate components", op);
295 
296  return true;
297  }
298  }
299  }
300 
301  return errorReturn;
302  default:
303  break;
304  }
305  error(line, " l-value required", op);
306 
307  return true;
308  }
309 
310 
311  const char* symbol = 0;
312  if (symNode != 0)
313  symbol = symNode->getSymbol().c_str();
314 
315  const char* message = 0;
316  switch (node->getQualifier()) {
317  case EvqConst: message = "can't modify a const"; break;
318  case EvqConstReadOnly: message = "can't modify a const"; break;
319  case EvqAttribute: message = "can't modify an attribute"; break;
320  case EvqUniform: message = "can't modify a uniform"; break;
321  case EvqVaryingIn: message = "can't modify a varying"; break;
322  case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
323  case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break;
324  case EvqPointCoord: message = "can't modify gl_PointCoord"; break;
325  default:
326 
327  //
328  // Type that can't be written to?
329  //
330  switch (node->getBasicType()) {
331  case EbtSampler2D:
332  case EbtSamplerCube:
333  message = "can't modify a sampler";
334  break;
335  case EbtVoid:
336  message = "can't modify void";
337  break;
338  default:
339  break;
340  }
341  }
342 
343  if (message == 0 && binaryNode == 0 && symNode == 0) {
344  error(line, " l-value required", op);
345 
346  return true;
347  }
348 
349 
350  //
351  // Everything else is okay, no error.
352  //
353  if (message == 0)
354  return false;
355 
356  //
357  // If we get here, we have an error and a message.
358  //
359  if (symNode) {
360  std::stringstream extraInfoStream;
361  extraInfoStream << "\"" << symbol << "\" (" << message << ")";
362  std::string extraInfo = extraInfoStream.str();
363  error(line, " l-value required", op, extraInfo.c_str());
364  }
365  else {
366  std::stringstream extraInfoStream;
367  extraInfoStream << "(" << message << ")";
368  std::string extraInfo = extraInfoStream.str();
369  error(line, " l-value required", op, extraInfo.c_str());
370  }
371 
372  return true;
373 }
374 
375 //
376 // Both test, and if necessary spit out an error, to see if the node is really
377 // a constant.
378 //
379 // Returns true if the was an error.
380 //
382 {
383  if (node->getQualifier() == EvqConst)
384  return false;
385 
386  error(node->getLine(), "constant expression required", "");
387 
388  return true;
389 }
390 
391 //
392 // Both test, and if necessary spit out an error, to see if the node is really
393 // an integer.
394 //
395 // Returns true if the was an error.
396 //
397 bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
398 {
399  if (node->getBasicType() == EbtInt && node->getNominalSize() == 1)
400  return false;
401 
402  error(node->getLine(), "integer expression required", token);
403 
404  return true;
405 }
406 
407 //
408 // Both test, and if necessary spit out an error, to see if we are currently
409 // globally scoped.
410 //
411 // Returns true if the was an error.
412 //
413 bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token)
414 {
415  if (global)
416  return false;
417 
418  error(line, "only allowed at global scope", token);
419 
420  return true;
421 }
422 
423 //
424 // For now, keep it simple: if it starts "gl_", it's reserved, independent
425 // of scope. Except, if the symbol table is at the built-in push-level,
426 // which is when we are parsing built-ins.
427 // Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
428 // webgl shader.
429 //
430 // Returns true if there was an error.
431 //
432 bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier)
433 {
434  static const char* reservedErrMsg = "reserved built-in name";
435  if (!symbolTable.atBuiltInLevel()) {
436  if (identifier.compare(0, 3, "gl_") == 0) {
437  error(line, reservedErrMsg, "gl_");
438  return true;
439  }
441  if (identifier.compare(0, 6, "webgl_") == 0) {
442  error(line, reservedErrMsg, "webgl_");
443  return true;
444  }
445  if (identifier.compare(0, 7, "_webgl_") == 0) {
446  error(line, reservedErrMsg, "_webgl_");
447  return true;
448  }
449  if (shaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0) {
450  error(line, reservedErrMsg, "css_");
451  return true;
452  }
453  }
454  if (identifier.find("__") != TString::npos) {
455  error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str());
456  return true;
457  }
458  }
459 
460  return false;
461 }
462 
463 //
464 // Make sure there is enough data provided to the constructor to build
465 // something of the type of the constructor. Also returns the type of
466 // the constructor.
467 //
468 // Returns true if there was an error in construction.
469 //
471 {
472  *type = function.getReturnType();
473 
474  bool constructingMatrix = false;
475  switch(op) {
476  case EOpConstructMat2:
477  case EOpConstructMat3:
478  case EOpConstructMat4:
479  constructingMatrix = true;
480  break;
481  default:
482  break;
483  }
484 
485  //
486  // Note: It's okay to have too many components available, but not okay to have unused
487  // arguments. 'full' will go to true when enough args have been seen. If we loop
488  // again, there is an extra argument, so 'overfull' will become true.
489  //
490 
491  size_t size = 0;
492  bool constType = true;
493  bool full = false;
494  bool overFull = false;
495  bool matrixInMatrix = false;
496  bool arrayArg = false;
497  for (size_t i = 0; i < function.getParamCount(); ++i) {
498  const TParameter& param = function.getParam(i);
499  size += param.type->getObjectSize();
500 
501  if (constructingMatrix && param.type->isMatrix())
502  matrixInMatrix = true;
503  if (full)
504  overFull = true;
505  if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
506  full = true;
507  if (param.type->getQualifier() != EvqConst)
508  constType = false;
509  if (param.type->isArray())
510  arrayArg = true;
511  }
512 
513  if (constType)
514  type->setQualifier(EvqConst);
515 
516  if (type->isArray() && static_cast<size_t>(type->getArraySize()) != function.getParamCount()) {
517  error(line, "array constructor needs one argument per array element", "constructor");
518  return true;
519  }
520 
521  if (arrayArg && op != EOpConstructStruct) {
522  error(line, "constructing from a non-dereferenced array", "constructor");
523  return true;
524  }
525 
526  if (matrixInMatrix && !type->isArray()) {
527  if (function.getParamCount() != 1) {
528  error(line, "constructing matrix from matrix can only take one argument", "constructor");
529  return true;
530  }
531  }
532 
533  if (overFull) {
534  error(line, "too many arguments", "constructor");
535  return true;
536  }
537 
538  if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) {
539  error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
540  return true;
541  }
542 
543  if (!type->isMatrix() || !matrixInMatrix) {
544  if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
545  (op == EOpConstructStruct && size < type->getObjectSize())) {
546  error(line, "not enough data provided for construction", "constructor");
547  return true;
548  }
549  }
550 
551  TIntermTyped *typed = node ? node->getAsTyped() : 0;
552  if (typed == 0) {
553  error(line, "constructor argument does not have a type", "constructor");
554  return true;
555  }
556  if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
557  error(line, "cannot convert a sampler", "constructor");
558  return true;
559  }
560  if (typed->getBasicType() == EbtVoid) {
561  error(line, "cannot convert a void", "constructor");
562  return true;
563  }
564 
565  return false;
566 }
567 
568 // This function checks to see if a void variable has been declared and raise an error message for such a case
569 //
570 // returns true in case of an error
571 //
572 bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType)
573 {
574  if (pubType.type == EbtVoid) {
575  error(line, "illegal use of type 'void'", identifier.c_str());
576  return true;
577  }
578 
579  return false;
580 }
581 
582 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not
583 //
584 // returns true in case of an error
585 //
587 {
588  if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
589  error(line, "boolean expression expected", "");
590  return true;
591  }
592 
593  return false;
594 }
595 
596 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not
597 //
598 // returns true in case of an error
599 //
600 bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType)
601 {
602  if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
603  error(line, "boolean expression expected", "");
604  return true;
605  }
606 
607  return false;
608 }
609 
610 bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason)
611 {
612  if (pType.type == EbtStruct) {
613  if (containsSampler(*pType.userDef)) {
614  error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
615 
616  return true;
617  }
618 
619  return false;
620  } else if (IsSampler(pType.type)) {
621  error(line, reason, getBasicString(pType.type));
622 
623  return true;
624  }
625 
626  return false;
627 }
628 
630 {
631  if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
632  pType.type == EbtStruct) {
633  error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
634 
635  return true;
636  }
637 
638  if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
639  return true;
640 
641  return false;
642 }
643 
645 {
646  if ((qualifier == EvqOut || qualifier == EvqInOut) &&
647  type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
648  error(line, "samplers cannot be output parameters", type.getBasicString());
649  return true;
650  }
651 
652  return false;
653 }
654 
656 {
657  if (IsSampler(type.getBasicType()))
658  return true;
659 
660  if (type.getBasicType() == EbtStruct) {
661  const TFieldList& fields = type.getStruct()->fields();
662  for (unsigned int i = 0; i < fields.size(); ++i) {
663  if (containsSampler(*fields[i]->type()))
664  return true;
665  }
666  }
667 
668  return false;
669 }
670 
671 //
672 // Do size checking for an array type's size.
673 //
674 // Returns true if there was an error.
675 //
677 {
678  TIntermConstantUnion* constant = expr->getAsConstantUnion();
679  if (constant == 0 || constant->getBasicType() != EbtInt) {
680  error(line, "array size must be a constant integer expression", "");
681  return true;
682  }
683 
684  size = constant->getIConst(0);
685 
686  if (size <= 0) {
687  error(line, "array size must be a positive integer", "");
688  size = 1;
689  return true;
690  }
691 
692  return false;
693 }
694 
695 //
696 // See if this qualifier can be an array.
697 //
698 // Returns true if there is an error.
699 //
701 {
702  if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) {
703  error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
704  return true;
705  }
706 
707  return false;
708 }
709 
710 //
711 // See if this type can be an array.
712 //
713 // Returns true if there is an error.
714 //
716 {
717  //
718  // Can the type be an array?
719  //
720  if (type.array) {
721  error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
722  return true;
723  }
724 
725  return false;
726 }
727 
728 //
729 // Do all the semantic checking for declaring an array, with and
730 // without a size, and make the right changes to the symbol table.
731 //
732 // size == 0 means no specified size.
733 //
734 // Returns true if there was an error.
735 //
737 {
738  //
739  // Don't check for reserved word use until after we know it's not in the symbol table,
740  // because reserved arrays can be redeclared.
741  //
742 
743  bool builtIn = false;
744  bool sameScope = false;
745  TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope);
746  if (symbol == 0 || !sameScope) {
747  if (reservedErrorCheck(line, identifier))
748  return true;
749 
750  variable = new TVariable(&identifier, TType(type));
751 
752  if (type.arraySize)
753  variable->getType().setArraySize(type.arraySize);
754 
755  if (! symbolTable.insert(*variable)) {
756  delete variable;
757  error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str());
758  return true;
759  }
760  } else {
761  if (! symbol->isVariable()) {
762  error(line, "variable expected", identifier.c_str());
763  return true;
764  }
765 
766  variable = static_cast<TVariable*>(symbol);
767  if (! variable->getType().isArray()) {
768  error(line, "redeclaring non-array as array", identifier.c_str());
769  return true;
770  }
771  if (variable->getType().getArraySize() > 0) {
772  error(line, "redeclaration of array with size", identifier.c_str());
773  return true;
774  }
775 
776  if (! variable->getType().sameElementType(TType(type))) {
777  error(line, "redeclaration of array with a different type", identifier.c_str());
778  return true;
779  }
780 
781  if (type.arraySize)
782  variable->getType().setArraySize(type.arraySize);
783  }
784 
785  if (voidErrorCheck(line, identifier, type))
786  return true;
787 
788  return false;
789 }
790 
791 //
792 // Enforce non-initializer type/qualifier rules.
793 //
794 // Returns true if there was an error.
795 //
797 {
798  if (type.qualifier == EvqConst)
799  {
800  // Make the qualifier make sense.
801  type.qualifier = EvqTemporary;
802 
803  if (array)
804  {
805  error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
806  }
807  else if (type.isStructureContainingArrays())
808  {
809  error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str());
810  }
811  else
812  {
813  error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
814  }
815 
816  return true;
817  }
818 
819  return false;
820 }
821 
822 //
823 // Do semantic checking for a variable declaration that has no initializer,
824 // and update the symbol table.
825 //
826 // Returns true if there was an error.
827 //
829 {
830  if (reservedErrorCheck(line, identifier))
831  recover();
832 
833  variable = new TVariable(&identifier, TType(type));
834 
835  if (! symbolTable.insert(*variable)) {
836  error(line, "redefinition", variable->getName().c_str());
837  delete variable;
838  variable = 0;
839  return true;
840  }
841 
842  if (voidErrorCheck(line, identifier, type))
843  return true;
844 
845  return false;
846 }
847 
848 bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
849 {
850  if (qualifier != EvqConst && qualifier != EvqTemporary) {
851  error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
852  return true;
853  }
854  if (qualifier == EvqConst && paramQualifier != EvqIn) {
855  error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
856  return true;
857  }
858 
859  if (qualifier == EvqConst)
861  else
862  type->setQualifier(paramQualifier);
863 
864  return false;
865 }
866 
867 bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension)
868 {
869  const TExtensionBehavior& extBehavior = extensionBehavior();
870  TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
871  if (iter == extBehavior.end()) {
872  error(line, "extension", extension.c_str(), "is not supported");
873  return true;
874  }
875  // In GLSL ES, an extension's default behavior is "disable".
876  if (iter->second == EBhDisable || iter->second == EBhUndefined) {
877  error(line, "extension", extension.c_str(), "is disabled");
878  return true;
879  }
880  if (iter->second == EBhWarn) {
881  warning(line, "extension", extension.c_str(), "is being used");
882  return false;
883  }
884 
885  return false;
886 }
887 
888 bool TParseContext::supportsExtension(const char* extension)
889 {
890  const TExtensionBehavior& extbehavior = extensionBehavior();
891  TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
892  return (iter != extbehavior.end());
893 }
894 
895 bool TParseContext::isExtensionEnabled(const char* extension) const
896 {
897  const TExtensionBehavior& extbehavior = extensionBehavior();
898  TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
899 
900  if (iter == extbehavior.end())
901  {
902  return false;
903  }
904 
905  return (iter->second == EBhEnable || iter->second == EBhRequire);
906 }
907 
909 //
910 // Non-Errors.
911 //
913 
914 //
915 // Look up a function name in the symbol table, and make sure it is a function.
916 //
917 // Return the function symbol if found, otherwise 0.
918 //
919 const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn)
920 {
921  // First find by unmangled name to check whether the function name has been
922  // hidden by a variable name or struct typename.
923  // If a function is found, check for one with a matching argument list.
924  const TSymbol* symbol = symbolTable.find(call->getName(), builtIn);
925  if (symbol == 0 || symbol->isFunction()) {
926  symbol = symbolTable.find(call->getMangledName(), builtIn);
927  }
928 
929  if (symbol == 0) {
930  error(line, "no matching overloaded function found", call->getName().c_str());
931  return 0;
932  }
933 
934  if (!symbol->isFunction()) {
935  error(line, "function name expected", call->getName().c_str());
936  return 0;
937  }
938 
939  return static_cast<const TFunction*>(symbol);
940 }
941 
942 //
943 // Initializers show up in several places in the grammar. Have one set of
944 // code to handle them here.
945 //
946 bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType,
947  TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
948 {
949  TType type = TType(pType);
950 
951  if (variable == 0) {
952  if (reservedErrorCheck(line, identifier))
953  return true;
954 
955  if (voidErrorCheck(line, identifier, pType))
956  return true;
957 
958  //
959  // add variable to symbol table
960  //
961  variable = new TVariable(&identifier, type);
962  if (! symbolTable.insert(*variable)) {
963  error(line, "redefinition", variable->getName().c_str());
964  return true;
965  // don't delete variable, it's used by error recovery, and the pool
966  // pop will take care of the memory
967  }
968  }
969 
970  //
971  // identifier must be of type constant, a global, or a temporary
972  //
973  TQualifier qualifier = variable->getType().getQualifier();
974  if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
975  error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString());
976  return true;
977  }
978  //
979  // test for and propagate constant
980  //
981 
982  if (qualifier == EvqConst) {
983  if (qualifier != initializer->getType().getQualifier()) {
984  std::stringstream extraInfoStream;
985  extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
986  std::string extraInfo = extraInfoStream.str();
987  error(line, " assigning non-constant to", "=", extraInfo.c_str());
988  variable->getType().setQualifier(EvqTemporary);
989  return true;
990  }
991  if (type != initializer->getType()) {
992  error(line, " non-matching types for const initializer ",
993  variable->getType().getQualifierString());
994  variable->getType().setQualifier(EvqTemporary);
995  return true;
996  }
997  if (initializer->getAsConstantUnion()) {
998  variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
999  } else if (initializer->getAsSymbolNode()) {
1000  const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
1001  const TVariable* tVar = static_cast<const TVariable*>(symbol);
1002 
1003  ConstantUnion* constArray = tVar->getConstPointer();
1004  variable->shareConstPointer(constArray);
1005  } else {
1006  std::stringstream extraInfoStream;
1007  extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
1008  std::string extraInfo = extraInfoStream.str();
1009  error(line, " cannot assign to", "=", extraInfo.c_str());
1010  variable->getType().setQualifier(EvqTemporary);
1011  return true;
1012  }
1013  }
1014 
1015  if (qualifier != EvqConst) {
1016  TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
1017  intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
1018  if (intermNode == 0) {
1019  assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1020  return true;
1021  }
1022  } else
1023  intermNode = 0;
1024 
1025  return false;
1026 }
1027 
1029 {
1030  ASSERT(aggrNode != NULL);
1031  if (!aggrNode->isConstructor())
1032  return false;
1033 
1034  bool allConstant = true;
1035 
1036  // check if all the child nodes are constants so that they can be inserted into
1037  // the parent node
1038  TIntermSequence &sequence = aggrNode->getSequence() ;
1039  for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) {
1040  if (!(*p)->getAsTyped()->getAsConstantUnion())
1041  return false;
1042  }
1043 
1044  return allConstant;
1045 }
1046 
1047 // This function is used to test for the correctness of the parameters passed to various constructor functions
1048 // and also convert them to the right datatype if it is allowed and required.
1049 //
1050 // Returns 0 for an error or the constructed node (aggregate or typed) for no error.
1051 //
1053 {
1054  if (node == 0)
1055  return 0;
1056 
1057  TIntermAggregate* aggrNode = node->getAsAggregate();
1058 
1059  TFieldList::const_iterator memberFields;
1060  if (op == EOpConstructStruct)
1061  memberFields = type->getStruct()->fields().begin();
1062 
1063  TType elementType = *type;
1064  if (type->isArray())
1065  elementType.clearArrayness();
1066 
1067  bool singleArg;
1068  if (aggrNode) {
1069  if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
1070  singleArg = true;
1071  else
1072  singleArg = false;
1073  } else
1074  singleArg = true;
1075 
1076  TIntermTyped *newNode;
1077  if (singleArg) {
1078  // If structure constructor or array constructor is being called
1079  // for only one parameter inside the structure, we need to call constructStruct function once.
1080  if (type->isArray())
1081  newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
1082  else if (op == EOpConstructStruct)
1083  newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false);
1084  else
1085  newNode = constructBuiltIn(type, op, node, node->getLine(), false);
1086 
1087  if (newNode && newNode->getAsAggregate()) {
1088  TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type);
1089  if (constConstructor)
1090  return constConstructor;
1091  }
1092 
1093  return newNode;
1094  }
1095 
1096  //
1097  // Handle list of arguments.
1098  //
1099  TIntermSequence &sequenceVector = aggrNode->getSequence() ; // Stores the information about the parameter to the constructor
1100  // if the structure constructor contains more than one parameter, then construct
1101  // each parameter
1102 
1103  int paramCount = 0; // keeps a track of the constructor parameter number being checked
1104 
1105  // for each parameter to the constructor call, check to see if the right type is passed or convert them
1106  // to the right type if possible (and allowed).
1107  // for structure constructors, just check if the right type is passed, no conversion is allowed.
1108 
1109  for (TIntermSequence::iterator p = sequenceVector.begin();
1110  p != sequenceVector.end(); p++, paramCount++) {
1111  if (type->isArray())
1112  newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
1113  else if (op == EOpConstructStruct)
1114  newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true);
1115  else
1116  newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
1117 
1118  if (newNode) {
1119  *p = newNode;
1120  }
1121  }
1122 
1123  TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line);
1124  TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
1125  if (constConstructor)
1126  return constConstructor;
1127 
1128  return constructor;
1129 }
1130 
1132 {
1133  bool canBeFolded = areAllChildConst(aggrNode);
1134  aggrNode->setType(type);
1135  if (canBeFolded) {
1136  bool returnVal = false;
1137  ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
1138  if (aggrNode->getSequence().size() == 1) {
1139  returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type, true);
1140  }
1141  else {
1142  returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type);
1143  }
1144  if (returnVal)
1145  return 0;
1146 
1147  return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
1148  }
1149 
1150  return 0;
1151 }
1152 
1153 // Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
1154 // for the parameter to the constructor (passed to this function). Essentially, it converts
1155 // the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a
1156 // float, then float is converted to int.
1157 //
1158 // Returns 0 for an error or the constructed node.
1159 //
1161 {
1162  TIntermTyped* newNode;
1163  TOperator basicOp;
1164 
1165  //
1166  // First, convert types as needed.
1167  //
1168  switch (op) {
1169  case EOpConstructVec2:
1170  case EOpConstructVec3:
1171  case EOpConstructVec4:
1172  case EOpConstructMat2:
1173  case EOpConstructMat3:
1174  case EOpConstructMat4:
1175  case EOpConstructFloat:
1176  basicOp = EOpConstructFloat;
1177  break;
1178 
1179  case EOpConstructIVec2:
1180  case EOpConstructIVec3:
1181  case EOpConstructIVec4:
1182  case EOpConstructInt:
1183  basicOp = EOpConstructInt;
1184  break;
1185 
1186  case EOpConstructBVec2:
1187  case EOpConstructBVec3:
1188  case EOpConstructBVec4:
1189  case EOpConstructBool:
1190  basicOp = EOpConstructBool;
1191  break;
1192 
1193  default:
1194  error(line, "unsupported construction", "");
1195  recover();
1196 
1197  return 0;
1198  }
1199  newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable);
1200  if (newNode == 0) {
1201  error(line, "can't convert", "constructor");
1202  return 0;
1203  }
1204 
1205  //
1206  // Now, if there still isn't an operation to do the construction, and we need one, add one.
1207  //
1208 
1209  // Otherwise, skip out early.
1210  if (subset || (newNode != node && newNode->getType() == *type))
1211  return newNode;
1212 
1213  // setAggregateOperator will insert a new node for the constructor, as needed.
1214  return intermediate.setAggregateOperator(newNode, op, line);
1215 }
1216 
1217 // This function tests for the type of the parameters to the structures constructors. Raises
1218 // an error message if the expected type does not match the parameter passed to the constructor.
1219 //
1220 // Returns 0 for an error or the input node itself if the expected and the given parameter types match.
1221 //
1222 TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset)
1223 {
1224  if (*type == node->getAsTyped()->getType()) {
1225  if (subset)
1226  return node->getAsTyped();
1227  else
1229  } else {
1230  std::stringstream extraInfoStream;
1231  extraInfoStream << "cannot convert parameter " << paramCount
1232  << " from '" << node->getAsTyped()->getType().getBasicString()
1233  << "' to '" << type->getBasicString() << "'";
1234  std::string extraInfo = extraInfoStream.str();
1235  error(line, "", "constructor", extraInfo.c_str());
1236  recover();
1237  }
1238 
1239  return 0;
1240 }
1241 
1242 //
1243 // This function returns the tree representation for the vector field(s) being accessed from contant vector.
1244 // If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
1245 // returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
1246 // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
1247 // a constant matrix.
1248 //
1250 {
1251  TIntermTyped* typedNode;
1252  TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1253 
1254  ConstantUnion *unionArray;
1255  if (tempConstantNode) {
1256  unionArray = tempConstantNode->getUnionArrayPointer();
1257 
1258  if (!unionArray) {
1259  return node;
1260  }
1261  } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
1262  error(line, "Cannot offset into the vector", "Error");
1263  recover();
1264 
1265  return 0;
1266  }
1267 
1268  ConstantUnion* constArray = new ConstantUnion[fields.num];
1269 
1270  for (int i = 0; i < fields.num; i++) {
1271  if (fields.offsets[i] >= node->getType().getNominalSize()) {
1272  std::stringstream extraInfoStream;
1273  extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
1274  std::string extraInfo = extraInfoStream.str();
1275  error(line, "", "[", extraInfo.c_str());
1276  recover();
1277  fields.offsets[i] = 0;
1278  }
1279 
1280  constArray[i] = unionArray[fields.offsets[i]];
1281 
1282  }
1283  typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
1284  return typedNode;
1285 }
1286 
1287 //
1288 // This function returns the column being accessed from a constant matrix. The values are retrieved from
1289 // the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
1290 // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
1291 // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
1292 //
1294 {
1295  TIntermTyped* typedNode;
1296  TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1297 
1298  if (index >= node->getType().getNominalSize()) {
1299  std::stringstream extraInfoStream;
1300  extraInfoStream << "matrix field selection out of range '" << index << "'";
1301  std::string extraInfo = extraInfoStream.str();
1302  error(line, "", "[", extraInfo.c_str());
1303  recover();
1304  index = 0;
1305  }
1306 
1307  if (tempConstantNode) {
1308  ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
1309  int size = tempConstantNode->getType().getNominalSize();
1310  typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
1311  } else {
1312  error(line, "Cannot offset into the matrix", "Error");
1313  recover();
1314 
1315  return 0;
1316  }
1317 
1318  return typedNode;
1319 }
1320 
1321 
1322 //
1323 // This function returns an element of an array accessed from a constant array. The values are retrieved from
1324 // the symbol table and parse-tree is built for the type of the element. The input
1325 // to the function could either be a symbol node (a[0] where a is a constant array)that represents a
1326 // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
1327 //
1329 {
1330  TIntermTyped* typedNode;
1331  TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1332  TType arrayElementType = node->getType();
1333  arrayElementType.clearArrayness();
1334 
1335  if (index >= node->getType().getArraySize()) {
1336  std::stringstream extraInfoStream;
1337  extraInfoStream << "array field selection out of range '" << index << "'";
1338  std::string extraInfo = extraInfoStream.str();
1339  error(line, "", "[", extraInfo.c_str());
1340  recover();
1341  index = 0;
1342  }
1343 
1344  if (tempConstantNode) {
1345  size_t arrayElementSize = arrayElementType.getObjectSize();
1346  ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
1347  typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
1348  } else {
1349  error(line, "Cannot offset into the array", "Error");
1350  recover();
1351 
1352  return 0;
1353  }
1354 
1355  return typedNode;
1356 }
1357 
1358 
1359 //
1360 // This function returns the value of a particular field inside a constant structure from the symbol table.
1361 // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
1362 // function and returns the parse-tree with the values of the embedded/nested struct.
1363 //
1365 {
1366  const TFieldList& fields = node->getType().getStruct()->fields();
1367 
1368  size_t instanceSize = 0;
1369  for (size_t index = 0; index < fields.size(); ++index) {
1370  if (fields[index]->name() == identifier) {
1371  break;
1372  } else {
1373  instanceSize += fields[index]->type()->getObjectSize();
1374  }
1375  }
1376 
1377  TIntermTyped* typedNode = 0;
1378  TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1379  if (tempConstantNode) {
1380  ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
1381 
1382  typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
1383  } else {
1384  error(line, "Cannot offset into the structure", "Error");
1385  recover();
1386 
1387  return 0;
1388  }
1389 
1390  return typedNode;
1391 }
1392 
1393 bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier)
1394 {
1396 
1397  // Embedded structure definitions are not supported per GLSL ES spec.
1398  // They aren't allowed in GLSL either, but we need to detect this here
1399  // so we don't rely on the GLSL compiler to catch it.
1400  if (structNestingLevel > 1) {
1401  error(line, "", "Embedded struct definitions are not allowed");
1402  return true;
1403  }
1404 
1405  return false;
1406 }
1407 
1409 {
1411 }
1412 
1413 namespace {
1414 
1415 const int kWebGLMaxStructNesting = 4;
1416 
1417 } // namespace
1418 
1420 {
1421  if (!isWebGLBasedSpec(shaderSpec)) {
1422  return false;
1423  }
1424 
1425  if (field.type()->getBasicType() != EbtStruct) {
1426  return false;
1427  }
1428 
1429  // We're already inside a structure definition at this point, so add
1430  // one to the field's struct nesting.
1431  if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) {
1432  std::stringstream extraInfoStream;
1433  extraInfoStream << "Reference of struct type " << field.name()
1434  << " exceeds maximum struct nesting of " << kWebGLMaxStructNesting;
1435  std::string extraInfo = extraInfoStream.str();
1436  error(line, "", "", extraInfo.c_str());
1437  return true;
1438  }
1439 
1440  return false;
1441 }
1442 
1443 //
1444 // Parse an array index expression
1445 //
1447 {
1448  TIntermTyped *indexedExpression = NULL;
1449 
1450  if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
1451  {
1452  if (baseExpression->getAsSymbolNode())
1453  {
1454  error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str());
1455  }
1456  else
1457  {
1458  error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
1459  }
1460  recover();
1461  }
1462 
1463  if (indexExpression->getQualifier() == EvqConst)
1464  {
1465  int index = indexExpression->getAsConstantUnion()->getIConst(0);
1466  if (index < 0)
1467  {
1468  std::stringstream infoStream;
1469  infoStream << index;
1470  std::string info = infoStream.str();
1471  error(location, "negative index", info.c_str());
1472  recover();
1473  index = 0;
1474  }
1475  if (baseExpression->getType().getQualifier() == EvqConst)
1476  {
1477  if (baseExpression->isArray())
1478  {
1479  // constant folding for arrays
1480  indexedExpression = addConstArrayNode(index, baseExpression, location);
1481  }
1482  else if (baseExpression->isVector())
1483  {
1484  // constant folding for vectors
1485  TVectorFields fields;
1486  fields.num = 1;
1487  fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
1488  indexedExpression = addConstVectorNode(fields, baseExpression, location);
1489  }
1490  else if (baseExpression->isMatrix())
1491  {
1492  // constant folding for matrices
1493  indexedExpression = addConstMatrixNode(index, baseExpression, location);
1494  }
1495  }
1496  else
1497  {
1498  if (baseExpression->isArray())
1499  {
1500  if (index >= baseExpression->getType().getArraySize())
1501  {
1502  std::stringstream extraInfoStream;
1503  extraInfoStream << "array index out of range '" << index << "'";
1504  std::string extraInfo = extraInfoStream.str();
1505  error(location, "", "[", extraInfo.c_str());
1506  recover();
1507  index = baseExpression->getType().getArraySize() - 1;
1508  }
1509  else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers"))
1510  {
1511  error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled");
1512  recover();
1513  index = 0;
1514  }
1515  }
1516  else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index)
1517  {
1518  std::stringstream extraInfoStream;
1519  extraInfoStream << "field selection out of range '" << index << "'";
1520  std::string extraInfo = extraInfoStream.str();
1521  error(location, "", "[", extraInfo.c_str());
1522  recover();
1523  index = baseExpression->getType().getNominalSize() - 1;
1524  }
1525 
1526  indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
1527  indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
1528  }
1529  }
1530  else
1531  {
1532  indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
1533  }
1534 
1535  if (indexedExpression == 0)
1536  {
1537  ConstantUnion *unionArray = new ConstantUnion[1];
1538  unionArray->setFConst(0.0f);
1539  indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
1540  }
1541  else if (baseExpression->isArray())
1542  {
1543  const TType &baseType = baseExpression->getType();
1544  if (baseType.getStruct())
1545  {
1546  TType copyOfType(baseType.getStruct());
1547  indexedExpression->setType(copyOfType);
1548  }
1549  else
1550  {
1551  indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix()));
1552  }
1553 
1554  if (baseExpression->getType().getQualifier() == EvqConst)
1555  {
1556  indexedExpression->getTypePointer()->setQualifier(EvqConst);
1557  }
1558  }
1559  else if (baseExpression->isMatrix())
1560  {
1561  TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
1562  indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize()));
1563  }
1564  else if (baseExpression->isVector())
1565  {
1566  TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
1567  indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
1568  }
1569  else
1570  {
1571  indexedExpression->setType(baseExpression->getType());
1572  }
1573 
1574  return indexedExpression;
1575 }
1576 
1577 //
1578 // Parse an array of strings using yyparse.
1579 //
1580 // Returns 0 for success.
1581 //
1582 int PaParseStrings(size_t count, const char* const string[], const int length[],
1584  if ((count == 0) || (string == NULL))
1585  return 1;
1586 
1587  if (glslang_initialize(context))
1588  return 1;
1589 
1590  int error = glslang_scan(count, string, length, context);
1591  if (!error)
1592  error = glslang_parse(context);
1593 
1594  glslang_finalize(context);
1595 
1596  return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
1597 }
1598 
1599 
1600 
TOperator
Definition: intermediate.h:29
void error(const TSourceLoc &loc, const char *reason, const char *token, const char *extraInfo="")
TIntermTyped * addIndex(TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &)
bool lValueErrorCheck(const TSourceLoc &line, const char *op, TIntermTyped *)
TSymbolTable & symbolTable
Definition: ParseHelper.h:46
bool checksPrecisionErrors
Definition: ParseHelper.h:56
int getDeepestStructNesting() const
Definition: Types.h:226
TOperator getOp() const
Definition: intermediate.h:389
TQualifier
Definition: BaseTypes.h:81
GLenum GLint param
Definition: gl2ext.h:1491
int getUniqueId() const
Definition: SymbolTable.h:53
TIntermTyped * foldConstConstructor(TIntermAggregate *aggrNode, const TType &type)
TIntermSequence & getSequence()
Definition: intermediate.h:469
std::map< std::string, TBehavior > TExtensionBehavior
Definition: Types.h:19
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
bool voidErrorCheck(const TSourceLoc &, const TString &, const TPublicType &)
GLsizei GLenum GLuint GLuint GLsizei GLchar * message
Definition: glew.h:2540
GLint left
Definition: glew.h:7291
TIntermTyped * getLeft() const
Definition: intermediate.h:413
ShShaderSpec shaderSpec
Definition: ParseHelper.h:48
#define NULL
Definition: ftobjs.h:61
bool arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *expr, int &size)
GLclampf f
Definition: glew.h:3390
GLint location
Definition: gl2ext.h:1164
virtual TIntermAggregate * getAsAggregate()
Definition: intermediate.h:223
int arraySize
Definition: Types.h:267
TIntermConstantUnion * addConstantUnion(ConstantUnion *, const TType &, const TSourceLoc &)
bool IsSampler(TBasicType type)
Definition: BaseTypes.h:70
void setType(const TType &t)
Definition: intermediate.h:250
TString getCompleteString() const
Definition: intermediate.h:265
TIntermTyped * addConstructor(TIntermNode *, const TType *, TOperator, TFunction *, const TSourceLoc &)
TIntermTyped * getRight() const
Definition: intermediate.h:414
void warning(const TSourceLoc &loc, const char *reason, const char *token, const char *extraInfo="")
int glslang_finalize(TParseContext *context)
const char * getQualifierString() const
Definition: Types.h:211
void setArraySize(int s)
Definition: Types.h:164
TIntermAggregate * setAggregateOperator(TIntermNode *, TOperator, const TSourceLoc &)
TIntermTyped * constructBuiltIn(const TType *, TOperator, TIntermNode *, const TSourceLoc &, bool subset)
TBasicType getBasicType() const
Definition: intermediate.h:254
TPrecision getPrecision() const
Definition: intermediate.h:256
int glslang_parse(TParseContext *context)
TIntermTyped * addConstStruct(TString &, TIntermTyped *, const TSourceLoc &)
bool executeInitializer(const TSourceLoc &line, TString &identifier, TPublicType &pType, TIntermTyped *initializer, TIntermNode *&intermNode, TVariable *variable=0)
TBasicType getBasicType() const
Definition: Types.h:108
bool isStructureContainingArrays() const
Definition: Types.h:296
bool globalErrorCheck(const TSourceLoc &line, bool global, const char *token)
int getNominalSize() const
Definition: Types.h:118
bool insert(TSymbol &symbol)
Definition: SymbolTable.h:276
void binaryOpError(const TSourceLoc &line, const char *op, TString left, TString right)
bool isConstructor() const
bool sameElementType(const TType &right) const
Definition: Types.h:181
EGLImageKHR EGLint * name
Definition: eglext.h:284
const TString & name() const
Definition: Types.h:30
GLenum GLenum variable
Definition: glew.h:12631
virtual TIntermBinary * getAsBinaryNode()
Definition: intermediate.h:224
TQualifier getQualifier() const
Definition: intermediate.h:255
Definition: Types.h:93
void setQualifier(TQualifier q)
Definition: Types.h:115
bool isMatrix() const
Definition: intermediate.h:259
virtual bool isVariable() const
Definition: SymbolTable.h:51
GLenum array
Definition: glew.h:8327
void unaryOpError(const TSourceLoc &line, const char *op, TString operand)
bool isArray() const
Definition: Types.h:162
bool extensionErrorCheck(const TSourceLoc &line, const TString &)
bool isVector() const
Definition: intermediate.h:261
int PaParseStrings(size_t count, const char *const string[], const int length[], TParseContext *context)
bool reservedErrorCheck(const TSourceLoc &line, const TString &identifier)
virtual TIntermConstantUnion * getAsConstantUnion()
Definition: intermediate.h:222
const TString & getName() const
Definition: SymbolTable.h:48
bool isWebGLBasedSpec(ShShaderSpec spec)
Definition: Compiler.cpp:24
const TFunction * findFunction(const TSourceLoc &line, TFunction *pfnCall, bool *builtIn=0)
bool array
Definition: Types.h:266
TType * type()
Definition: Types.h:27
TIntermTyped * addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &)
void setFConst(float f)
Definition: ConstantUnion.h:22
#define ASSERT(expression)
Definition: debug.h:36
void exitStructDeclaration()
TQualifier getQualifier() const
Definition: Types.h:114
TIntermSymbol * addSymbol(int Id, const TString &, const TType &, const TSourceLoc &)
int
Definition: SDL_systhread.c:37
GLsizei GLsizei * length
Definition: gl2ext.h:792
TQualifier qualifier
Definition: Types.h:262
const char * getBasicString(TBasicType t)
Definition: BaseTypes.h:53
void assignError(const TSourceLoc &line, const char *op, TString left, TString right)
FT_Error error
Definition: cffdrivr.c:407
void writeInfo(Severity severity, const pp::SourceLocation &loc, const std::string &reason, const std::string &token, const std::string &extra)
Definition: Diagnostics.cpp:24
bool constErrorCheck(TIntermTyped *node)
int size
Definition: Types.h:264
GLint GLsizei count
Definition: gl2ext.h:1011
GLfloat GLfloat p
Definition: glew.h:14938
TIntermTyped * addConstVectorNode(TVectorFields &, TIntermTyped *, const TSourceLoc &)
const TSourceLoc & getLine() const
Definition: intermediate.h:217
const TType & getType() const
Definition: intermediate.h:251
bool samplerErrorCheck(const TSourceLoc &line, const TPublicType &pType, const char *reason)
bool supportsExtension(const char *extension)
void setIConst(int i)
Definition: ConstantUnion.h:21
TType * type
Definition: SymbolTable.h:123
bool matrix
Definition: Types.h:265
ConstantUnion * getUnionArrayPointer() const
Definition: intermediate.h:369
bool containsSampler(TType &type)
void trace(const char *str)
GLuint index
Definition: glew.h:1800
TIntermediate & intermediate
Definition: ParseHelper.h:45
bool parseConstTree(const TSourceLoc &, TIntermNode *, ConstantUnion *, TOperator, TSymbolTable &, TType, bool singleConstantParam=false)
Definition: parseConst.cpp:233
virtual TIntermTyped * getAsTyped()
Definition: intermediate.h:221
void shareConstPointer(ConstantUnion *constArray)
Definition: SymbolTable.h:98
TIntermTyped * addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc &location, TIntermTyped *indexExpression)
TBasicType
Definition: BaseTypes.h:36
bool boolErrorCheck(const TSourceLoc &, const TIntermTyped *)
int getIConst(int index) const
Definition: intermediate.h:371
std::basic_string< char, std::char_traits< char >, TStringAllocator > TString
Definition: Common.h:41
int numErrors() const
Definition: ParseHelper.h:64
virtual bool isFunction() const
Definition: SymbolTable.h:50
bool atBuiltInLevel()
Definition: SymbolTable.h:261
TDiagnostics diagnostics
Definition: ParseHelper.h:59
int structNestingLevel
Definition: ParseHelper.h:53
const TString & getMangledName() const
Definition: SymbolTable.h:157
int first_file
Definition: Common.h:18
void writeDebug(const std::string &str)
Definition: Diagnostics.cpp:53
EGLSurface EGLint void ** value
Definition: eglext.h:301
bool areAllChildConst(TIntermAggregate *aggrNode)
GLintptr offset
Definition: glew.h:1668
TType * getTypePointer()
Definition: intermediate.h:252
bool parameterSamplerErrorCheck(const TSourceLoc &line, TQualifier qualifier, const TType &type)
bool precisionErrorCheck(const TSourceLoc &line, TPrecision precision, TBasicType type)
bool isArray() const
Definition: intermediate.h:260
int getArraySize() const
Definition: Types.h:163
bool arrayErrorCheck(const TSourceLoc &line, TString &identifier, TPublicType type, TVariable *&variable)
GLsizei const GLcharARB ** string
Definition: glew.h:5638
const char * getQualifierString(TQualifier q)
Definition: BaseTypes.h:120
TType & getType()
Definition: SymbolTable.h:81
void clearArrayness()
Definition: Types.h:165
Definition: Common.h:59
bool arrayTypeErrorCheck(const TSourceLoc &line, TPublicType type)
const TExtensionBehavior & extensionBehavior() const
Definition: ParseHelper.h:102
virtual TIntermTyped * getAsTyped()
Definition: intermediate.h:248
TIntermTyped * addConstArrayNode(int index, TIntermTyped *node, const TSourceLoc &line)
TPrecision
Definition: BaseTypes.h:13
bool isMatrix() const
Definition: Types.h:159
TString getCompleteString() const
Definition: intermOut.cpp:38
int glslang_scan(size_t count, const char *const string[], const int length[], TParseContext *context)
int first_line
Definition: Common.h:19
TIntermTyped * addConstMatrixNode(int, TIntermTyped *, const TSourceLoc &)
TIntermTyped * addUnaryMath(TOperator op, TIntermNode *child, const TSourceLoc &, TSymbolTable &)
bool integerErrorCheck(TIntermTyped *node, const char *token)
size_t getObjectSize() const
Definition: SymbolTable.cpp:61
#define str(s)
bool nonInitConstErrorCheck(const TSourceLoc &line, TString &identifier, TPublicType &type, bool array)
const char * getBasicString() const
Definition: Types.h:209
const TFieldList & fields() const
Definition: Types.h:57
TStructure * getStruct() const
Definition: Types.h:170
const TString & getSymbol() const
Definition: intermediate.h:349
TParseContext * context
int i
Definition: pngrutil.c:1377
GLenum GLint GLint * precision
Definition: glew.h:3391
bool parseVectorFields(const TString &, int vecSize, TVectorFields &, const TSourceLoc &line)
Definition: ParseHelper.cpp:25
GLfloat right
Definition: glew.h:13816
TIntermTyped * constructStruct(TIntermNode *, TType *, int, const TSourceLoc &, bool subset)
ConstantUnion * getConstPointer()
Definition: SymbolTable.h:88
bool enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
bool paramErrorCheck(const TSourceLoc &line, TQualifier qualifier, TQualifier paramQualifier, TType *type)
int getNominalSize() const
Definition: intermediate.h:257
int glslang_initialize(TParseContext *context)
TType * userDef
Definition: Types.h:268
virtual TIntermSymbol * getAsSymbolNode()
Definition: intermediate.h:227
TSymbol * find(const TString &name, bool *builtIn=0, bool *sameScope=0)
Definition: SymbolTable.h:311
bool arrayQualifierErrorCheck(const TSourceLoc &line, TPublicType type)
bool isExtensionEnabled(const char *extension) const
bool structQualifierErrorCheck(const TSourceLoc &line, const TPublicType &pType)
TBasicType type
Definition: Types.h:261
bool constructorErrorCheck(const TSourceLoc &line, TIntermNode *, TFunction &, TOperator, TType *)
bool structNestingErrorCheck(const TSourceLoc &line, const TField &field)
bool nonInitErrorCheck(const TSourceLoc &line, TString &identifier, TPublicType &type, TVariable *&variable)
GLsizei size
Definition: gl2ext.h:1467
bool parseMatrixFields(const TString &, int matSize, TMatrixFields &, const TSourceLoc &line)