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