blob: 83f58ce4e629188a2b9fbaf8585d7a0c8cc84684 [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman66b8ab22014-05-06 15:57:45 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
John Bauman66b8ab22014-05-06 15:57:45 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
John Bauman66b8ab22014-05-06 15:57:45 -040014
Nicolas Capenscc863da2015-01-21 15:50:55 -050015#include "ParseHelper.h"
John Bauman66b8ab22014-05-06 15:57:45 -040016
17#include <stdarg.h>
18#include <stdio.h>
19
Nicolas Capenscc863da2015-01-21 15:50:55 -050020#include "glslang.h"
21#include "preprocessor/SourceLocation.h"
Alexis Hetue5246692015-06-18 12:34:52 -040022#include "ValidateGlobalInitializer.h"
Alexis Hetu76a343a2015-06-04 17:21:22 -040023#include "ValidateSwitch.h"
John Bauman66b8ab22014-05-06 15:57:45 -040024
25///////////////////////////////////////////////////////////////////////
26//
27// Sub- vector and matrix fields
28//
29////////////////////////////////////////////////////////////////////////
30
Alexis Hetuec93b1d2016-12-09 16:01:29 -050031namespace
32{
33 bool IsVaryingOut(TQualifier qualifier)
34 {
35 switch(qualifier)
36 {
37 case EvqVaryingOut:
38 case EvqSmoothOut:
39 case EvqFlatOut:
40 case EvqCentroidOut:
41 case EvqVertexOut:
42 return true;
43
44 default: break;
45 }
46
47 return false;
48 }
49
50 bool IsVaryingIn(TQualifier qualifier)
51 {
52 switch(qualifier)
53 {
54 case EvqVaryingIn:
55 case EvqSmoothIn:
56 case EvqFlatIn:
57 case EvqCentroidIn:
58 case EvqFragmentIn:
59 return true;
60
61 default: break;
62 }
63
64 return false;
65 }
66
67 bool IsVarying(TQualifier qualifier)
68 {
69 return IsVaryingIn(qualifier) || IsVaryingOut(qualifier);
70 }
71
72 bool IsAssignment(TOperator op)
73 {
74 switch(op)
75 {
76 case EOpPostIncrement:
77 case EOpPostDecrement:
78 case EOpPreIncrement:
79 case EOpPreDecrement:
80 case EOpAssign:
81 case EOpAddAssign:
82 case EOpSubAssign:
83 case EOpMulAssign:
84 case EOpVectorTimesMatrixAssign:
85 case EOpVectorTimesScalarAssign:
86 case EOpMatrixTimesScalarAssign:
87 case EOpMatrixTimesMatrixAssign:
88 case EOpDivAssign:
89 case EOpIModAssign:
90 case EOpBitShiftLeftAssign:
91 case EOpBitShiftRightAssign:
92 case EOpBitwiseAndAssign:
93 case EOpBitwiseXorAssign:
94 case EOpBitwiseOrAssign:
95 return true;
96 default:
97 return false;
98 }
99 }
100}
101
John Bauman66b8ab22014-05-06 15:57:45 -0400102//
103// Look at a '.' field selector string and change it into offsets
104// for a vector.
105//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400106bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400107{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400108 fields.num = (int) compString.size();
109 if (fields.num > 4) {
110 error(line, "illegal vector field selection", compString.c_str());
111 return false;
112 }
John Bauman66b8ab22014-05-06 15:57:45 -0400113
Nicolas Capens0bac2852016-05-07 06:09:58 -0400114 enum {
115 exyzw,
116 ergba,
117 estpq
118 } fieldSet[4];
John Bauman66b8ab22014-05-06 15:57:45 -0400119
Nicolas Capens0bac2852016-05-07 06:09:58 -0400120 for (int i = 0; i < fields.num; ++i) {
121 switch (compString[i]) {
122 case 'x':
123 fields.offsets[i] = 0;
124 fieldSet[i] = exyzw;
125 break;
126 case 'r':
127 fields.offsets[i] = 0;
128 fieldSet[i] = ergba;
129 break;
130 case 's':
131 fields.offsets[i] = 0;
132 fieldSet[i] = estpq;
133 break;
134 case 'y':
135 fields.offsets[i] = 1;
136 fieldSet[i] = exyzw;
137 break;
138 case 'g':
139 fields.offsets[i] = 1;
140 fieldSet[i] = ergba;
141 break;
142 case 't':
143 fields.offsets[i] = 1;
144 fieldSet[i] = estpq;
145 break;
146 case 'z':
147 fields.offsets[i] = 2;
148 fieldSet[i] = exyzw;
149 break;
150 case 'b':
151 fields.offsets[i] = 2;
152 fieldSet[i] = ergba;
153 break;
154 case 'p':
155 fields.offsets[i] = 2;
156 fieldSet[i] = estpq;
157 break;
158 case 'w':
159 fields.offsets[i] = 3;
160 fieldSet[i] = exyzw;
161 break;
162 case 'a':
163 fields.offsets[i] = 3;
164 fieldSet[i] = ergba;
165 break;
166 case 'q':
167 fields.offsets[i] = 3;
168 fieldSet[i] = estpq;
169 break;
170 default:
171 error(line, "illegal vector field selection", compString.c_str());
172 return false;
173 }
174 }
John Bauman66b8ab22014-05-06 15:57:45 -0400175
Nicolas Capens0bac2852016-05-07 06:09:58 -0400176 for (int i = 0; i < fields.num; ++i) {
177 if (fields.offsets[i] >= vecSize) {
178 error(line, "vector field selection out of range", compString.c_str());
179 return false;
180 }
John Bauman66b8ab22014-05-06 15:57:45 -0400181
Nicolas Capens0bac2852016-05-07 06:09:58 -0400182 if (i > 0) {
183 if (fieldSet[i] != fieldSet[i-1]) {
184 error(line, "illegal - vector component fields not from the same set", compString.c_str());
185 return false;
186 }
187 }
188 }
John Bauman66b8ab22014-05-06 15:57:45 -0400189
Nicolas Capens0bac2852016-05-07 06:09:58 -0400190 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400191}
192
193
194//
195// Look at a '.' field selector string and change it into offsets
196// for a matrix.
197//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400198bool TParseContext::parseMatrixFields(const TString& compString, int matCols, int matRows, TMatrixFields& fields, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400199{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400200 fields.wholeRow = false;
201 fields.wholeCol = false;
202 fields.row = -1;
203 fields.col = -1;
John Bauman66b8ab22014-05-06 15:57:45 -0400204
Nicolas Capens0bac2852016-05-07 06:09:58 -0400205 if (compString.size() != 2) {
206 error(line, "illegal length of matrix field selection", compString.c_str());
207 return false;
208 }
John Bauman66b8ab22014-05-06 15:57:45 -0400209
Nicolas Capens0bac2852016-05-07 06:09:58 -0400210 if (compString[0] == '_') {
211 if (compString[1] < '0' || compString[1] > '3') {
212 error(line, "illegal matrix field selection", compString.c_str());
213 return false;
214 }
215 fields.wholeCol = true;
216 fields.col = compString[1] - '0';
217 } else if (compString[1] == '_') {
218 if (compString[0] < '0' || compString[0] > '3') {
219 error(line, "illegal matrix field selection", compString.c_str());
220 return false;
221 }
222 fields.wholeRow = true;
223 fields.row = compString[0] - '0';
224 } else {
225 if (compString[0] < '0' || compString[0] > '3' ||
226 compString[1] < '0' || compString[1] > '3') {
227 error(line, "illegal matrix field selection", compString.c_str());
228 return false;
229 }
230 fields.row = compString[0] - '0';
231 fields.col = compString[1] - '0';
232 }
John Bauman66b8ab22014-05-06 15:57:45 -0400233
Nicolas Capens0bac2852016-05-07 06:09:58 -0400234 if (fields.row >= matRows || fields.col >= matCols) {
235 error(line, "matrix field selection out of range", compString.c_str());
236 return false;
237 }
John Bauman66b8ab22014-05-06 15:57:45 -0400238
Nicolas Capens0bac2852016-05-07 06:09:58 -0400239 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400240}
241
242///////////////////////////////////////////////////////////////////////
243//
244// Errors
245//
246////////////////////////////////////////////////////////////////////////
247
248//
249// Track whether errors have occurred.
250//
251void TParseContext::recover()
252{
253}
254
255//
256// Used by flex/bison to output all syntax and parsing errors.
257//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400258void TParseContext::error(const TSourceLoc& loc,
Nicolas Capens0bac2852016-05-07 06:09:58 -0400259 const char* reason, const char* token,
260 const char* extraInfo)
John Bauman66b8ab22014-05-06 15:57:45 -0400261{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400262 pp::SourceLocation srcLoc(loc.first_file, loc.first_line);
263 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR,
264 srcLoc, reason, token, extraInfo);
John Bauman66b8ab22014-05-06 15:57:45 -0400265
266}
267
Alexis Hetufe1269e2015-06-16 12:43:32 -0400268void TParseContext::warning(const TSourceLoc& loc,
Nicolas Capens0bac2852016-05-07 06:09:58 -0400269 const char* reason, const char* token,
270 const char* extraInfo) {
271 pp::SourceLocation srcLoc(loc.first_file, loc.first_line);
272 mDiagnostics.writeInfo(pp::Diagnostics::PP_WARNING,
273 srcLoc, reason, token, extraInfo);
John Bauman66b8ab22014-05-06 15:57:45 -0400274}
275
276void TParseContext::trace(const char* str)
277{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400278 mDiagnostics.writeDebug(str);
John Bauman66b8ab22014-05-06 15:57:45 -0400279}
280
281//
282// Same error message for all places assignments don't work.
283//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400284void TParseContext::assignError(const TSourceLoc &line, const char* op, TString left, TString right)
John Bauman66b8ab22014-05-06 15:57:45 -0400285{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400286 std::stringstream extraInfoStream;
287 extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
288 std::string extraInfo = extraInfoStream.str();
289 error(line, "", op, extraInfo.c_str());
John Bauman66b8ab22014-05-06 15:57:45 -0400290}
291
292//
293// Same error message for all places unary operations don't work.
294//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400295void TParseContext::unaryOpError(const TSourceLoc &line, const char* op, TString operand)
John Bauman66b8ab22014-05-06 15:57:45 -0400296{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400297 std::stringstream extraInfoStream;
298 extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand
299 << " (or there is no acceptable conversion)";
300 std::string extraInfo = extraInfoStream.str();
301 error(line, " wrong operand type", op, extraInfo.c_str());
John Bauman66b8ab22014-05-06 15:57:45 -0400302}
303
304//
305// Same error message for all binary operations don't work.
306//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400307void TParseContext::binaryOpError(const TSourceLoc &line, const char* op, TString left, TString right)
John Bauman66b8ab22014-05-06 15:57:45 -0400308{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400309 std::stringstream extraInfoStream;
310 extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left
311 << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)";
312 std::string extraInfo = extraInfoStream.str();
313 error(line, " wrong operand types ", op, extraInfo.c_str());
John Bauman66b8ab22014-05-06 15:57:45 -0400314}
315
Alexis Hetufe1269e2015-06-16 12:43:32 -0400316bool TParseContext::precisionErrorCheck(const TSourceLoc &line, TPrecision precision, TBasicType type){
Nicolas Capens0bac2852016-05-07 06:09:58 -0400317 if (!mChecksPrecisionErrors)
318 return false;
319 switch( type ){
320 case EbtFloat:
321 if( precision == EbpUndefined ){
322 error( line, "No precision specified for (float)", "" );
323 return true;
324 }
325 break;
326 case EbtInt:
327 if( precision == EbpUndefined ){
328 error( line, "No precision specified (int)", "" );
329 return true;
330 }
331 break;
332 default:
333 return false;
334 }
335 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400336}
337
338//
339// Both test and if necessary, spit out an error, to see if the node is really
340// an l-value that can be operated on this way.
341//
342// Returns true if the was an error.
343//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400344bool TParseContext::lValueErrorCheck(const TSourceLoc &line, const char* op, TIntermTyped* node)
John Bauman66b8ab22014-05-06 15:57:45 -0400345{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400346 TIntermSymbol* symNode = node->getAsSymbolNode();
347 TIntermBinary* binaryNode = node->getAsBinaryNode();
John Bauman66b8ab22014-05-06 15:57:45 -0400348
Nicolas Capens0bac2852016-05-07 06:09:58 -0400349 if (binaryNode) {
350 bool errorReturn;
John Bauman66b8ab22014-05-06 15:57:45 -0400351
Nicolas Capens0bac2852016-05-07 06:09:58 -0400352 switch(binaryNode->getOp()) {
353 case EOpIndexDirect:
354 case EOpIndexIndirect:
355 case EOpIndexDirectStruct:
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500356 case EOpIndexDirectInterfaceBlock:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400357 return lValueErrorCheck(line, op, binaryNode->getLeft());
358 case EOpVectorSwizzle:
359 errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
360 if (!errorReturn) {
361 int offset[4] = {0,0,0,0};
John Bauman66b8ab22014-05-06 15:57:45 -0400362
Nicolas Capens0bac2852016-05-07 06:09:58 -0400363 TIntermTyped* rightNode = binaryNode->getRight();
364 TIntermAggregate *aggrNode = rightNode->getAsAggregate();
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400365
Nicolas Capens0bac2852016-05-07 06:09:58 -0400366 for (TIntermSequence::iterator p = aggrNode->getSequence().begin();
367 p != aggrNode->getSequence().end(); p++) {
368 int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0);
369 offset[value]++;
370 if (offset[value] > 1) {
371 error(line, " l-value of swizzle cannot have duplicate components", op);
John Bauman66b8ab22014-05-06 15:57:45 -0400372
Nicolas Capens0bac2852016-05-07 06:09:58 -0400373 return true;
374 }
375 }
376 }
John Bauman66b8ab22014-05-06 15:57:45 -0400377
Nicolas Capens0bac2852016-05-07 06:09:58 -0400378 return errorReturn;
379 default:
380 break;
381 }
382 error(line, " l-value required", op);
John Bauman66b8ab22014-05-06 15:57:45 -0400383
Nicolas Capens0bac2852016-05-07 06:09:58 -0400384 return true;
385 }
John Bauman66b8ab22014-05-06 15:57:45 -0400386
387
Nicolas Capens0bac2852016-05-07 06:09:58 -0400388 const char* symbol = 0;
389 if (symNode != 0)
390 symbol = symNode->getSymbol().c_str();
John Bauman66b8ab22014-05-06 15:57:45 -0400391
Nicolas Capens0bac2852016-05-07 06:09:58 -0400392 const char* message = 0;
393 switch (node->getQualifier()) {
394 case EvqConstExpr: message = "can't modify a const"; break;
395 case EvqConstReadOnly: message = "can't modify a const"; break;
396 case EvqAttribute: message = "can't modify an attribute"; break;
397 case EvqFragmentIn: message = "can't modify an input"; break;
398 case EvqVertexIn: message = "can't modify an input"; break;
399 case EvqUniform: message = "can't modify a uniform"; break;
400 case EvqSmoothIn:
401 case EvqFlatIn:
402 case EvqCentroidIn:
403 case EvqVaryingIn: message = "can't modify a varying"; break;
404 case EvqInput: message = "can't modify an input"; break;
405 case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
406 case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break;
407 case EvqPointCoord: message = "can't modify gl_PointCoord"; break;
408 case EvqInstanceID: message = "can't modify gl_InstanceID"; break;
409 default:
John Bauman66b8ab22014-05-06 15:57:45 -0400410
Nicolas Capens0bac2852016-05-07 06:09:58 -0400411 //
412 // Type that can't be written to?
413 //
414 if(IsSampler(node->getBasicType()))
415 {
416 message = "can't modify a sampler";
417 }
418 else if(node->getBasicType() == EbtVoid)
419 {
420 message = "can't modify void";
421 }
422 }
John Bauman66b8ab22014-05-06 15:57:45 -0400423
Nicolas Capens0bac2852016-05-07 06:09:58 -0400424 if (message == 0 && binaryNode == 0 && symNode == 0) {
425 error(line, " l-value required", op);
John Bauman66b8ab22014-05-06 15:57:45 -0400426
Nicolas Capens0bac2852016-05-07 06:09:58 -0400427 return true;
428 }
John Bauman66b8ab22014-05-06 15:57:45 -0400429
430
Nicolas Capens0bac2852016-05-07 06:09:58 -0400431 //
432 // Everything else is okay, no error.
433 //
434 if (message == 0)
435 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400436
Nicolas Capens0bac2852016-05-07 06:09:58 -0400437 //
438 // If we get here, we have an error and a message.
439 //
440 if (symNode) {
441 std::stringstream extraInfoStream;
442 extraInfoStream << "\"" << symbol << "\" (" << message << ")";
443 std::string extraInfo = extraInfoStream.str();
444 error(line, " l-value required", op, extraInfo.c_str());
445 }
446 else {
447 std::stringstream extraInfoStream;
448 extraInfoStream << "(" << message << ")";
449 std::string extraInfo = extraInfoStream.str();
450 error(line, " l-value required", op, extraInfo.c_str());
451 }
John Bauman66b8ab22014-05-06 15:57:45 -0400452
Nicolas Capens0bac2852016-05-07 06:09:58 -0400453 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400454}
455
456//
457// Both test, and if necessary spit out an error, to see if the node is really
458// a constant.
459//
460// Returns true if the was an error.
461//
462bool TParseContext::constErrorCheck(TIntermTyped* node)
463{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400464 if (node->getQualifier() == EvqConstExpr)
465 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400466
Nicolas Capens0bac2852016-05-07 06:09:58 -0400467 error(node->getLine(), "constant expression required", "");
John Bauman66b8ab22014-05-06 15:57:45 -0400468
Nicolas Capens0bac2852016-05-07 06:09:58 -0400469 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400470}
471
472//
473// Both test, and if necessary spit out an error, to see if the node is really
474// an integer.
475//
476// Returns true if the was an error.
477//
478bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
479{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400480 if (node->isScalarInt())
481 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400482
Nicolas Capens0bac2852016-05-07 06:09:58 -0400483 error(node->getLine(), "integer expression required", token);
John Bauman66b8ab22014-05-06 15:57:45 -0400484
Nicolas Capens0bac2852016-05-07 06:09:58 -0400485 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400486}
487
488//
489// Both test, and if necessary spit out an error, to see if we are currently
490// globally scoped.
491//
492// Returns true if the was an error.
493//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400494bool TParseContext::globalErrorCheck(const TSourceLoc &line, bool global, const char* token)
John Bauman66b8ab22014-05-06 15:57:45 -0400495{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400496 if (global)
497 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400498
Nicolas Capens0bac2852016-05-07 06:09:58 -0400499 error(line, "only allowed at global scope", token);
John Bauman66b8ab22014-05-06 15:57:45 -0400500
Nicolas Capens0bac2852016-05-07 06:09:58 -0400501 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400502}
503
504//
505// For now, keep it simple: if it starts "gl_", it's reserved, independent
506// of scope. Except, if the symbol table is at the built-in push-level,
507// which is when we are parsing built-ins.
508// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
509// webgl shader.
510//
511// Returns true if there was an error.
512//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400513bool TParseContext::reservedErrorCheck(const TSourceLoc &line, const TString& identifier)
John Bauman66b8ab22014-05-06 15:57:45 -0400514{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400515 static const char* reservedErrMsg = "reserved built-in name";
516 if (!symbolTable.atBuiltInLevel()) {
517 if (identifier.compare(0, 3, "gl_") == 0) {
518 error(line, reservedErrMsg, "gl_");
519 return true;
520 }
521 if (identifier.find("__") != TString::npos) {
522 error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str());
523 return true;
524 }
525 }
John Bauman66b8ab22014-05-06 15:57:45 -0400526
Nicolas Capens0bac2852016-05-07 06:09:58 -0400527 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400528}
529
530//
531// Make sure there is enough data provided to the constructor to build
532// something of the type of the constructor. Also returns the type of
533// the constructor.
534//
535// Returns true if there was an error in construction.
536//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400537bool TParseContext::constructorErrorCheck(const TSourceLoc &line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
John Bauman66b8ab22014-05-06 15:57:45 -0400538{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400539 *type = function.getReturnType();
John Bauman66b8ab22014-05-06 15:57:45 -0400540
Nicolas Capens0bac2852016-05-07 06:09:58 -0400541 bool constructingMatrix = false;
542 switch(op) {
543 case EOpConstructMat2:
544 case EOpConstructMat2x3:
545 case EOpConstructMat2x4:
546 case EOpConstructMat3x2:
547 case EOpConstructMat3:
548 case EOpConstructMat3x4:
549 case EOpConstructMat4x2:
550 case EOpConstructMat4x3:
551 case EOpConstructMat4:
552 constructingMatrix = true;
553 break;
554 default:
555 break;
556 }
John Bauman66b8ab22014-05-06 15:57:45 -0400557
Nicolas Capens0bac2852016-05-07 06:09:58 -0400558 //
559 // Note: It's okay to have too many components available, but not okay to have unused
560 // arguments. 'full' will go to true when enough args have been seen. If we loop
561 // again, there is an extra argument, so 'overfull' will become true.
562 //
John Bauman66b8ab22014-05-06 15:57:45 -0400563
Nicolas Capens0bac2852016-05-07 06:09:58 -0400564 size_t size = 0;
565 bool full = false;
566 bool overFull = false;
567 bool matrixInMatrix = false;
568 bool arrayArg = false;
569 for (size_t i = 0; i < function.getParamCount(); ++i) {
570 const TParameter& param = function.getParam(i);
571 size += param.type->getObjectSize();
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400572
Nicolas Capens0bac2852016-05-07 06:09:58 -0400573 if (constructingMatrix && param.type->isMatrix())
574 matrixInMatrix = true;
575 if (full)
576 overFull = true;
577 if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
578 full = true;
579 if (param.type->isArray())
580 arrayArg = true;
581 }
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400582
Nicolas Capens0bac2852016-05-07 06:09:58 -0400583 if(type->isArray()) {
584 if(type->getArraySize() == 0) {
585 type->setArraySize(function.getParamCount());
586 } else if(type->getArraySize() != (int)function.getParamCount()) {
587 error(line, "array constructor needs one argument per array element", "constructor");
588 return true;
589 }
590 }
John Bauman66b8ab22014-05-06 15:57:45 -0400591
Nicolas Capens0bac2852016-05-07 06:09:58 -0400592 if (arrayArg && op != EOpConstructStruct) {
593 error(line, "constructing from a non-dereferenced array", "constructor");
594 return true;
595 }
John Bauman66b8ab22014-05-06 15:57:45 -0400596
Nicolas Capens0bac2852016-05-07 06:09:58 -0400597 if (matrixInMatrix && !type->isArray()) {
598 if (function.getParamCount() != 1) {
599 error(line, "constructing matrix from matrix can only take one argument", "constructor");
600 return true;
601 }
602 }
John Bauman66b8ab22014-05-06 15:57:45 -0400603
Nicolas Capens0bac2852016-05-07 06:09:58 -0400604 if (overFull) {
605 error(line, "too many arguments", "constructor");
606 return true;
607 }
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400608
Nicolas Capens0bac2852016-05-07 06:09:58 -0400609 if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->fields().size() != function.getParamCount()) {
610 error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
611 return true;
612 }
John Bauman66b8ab22014-05-06 15:57:45 -0400613
Nicolas Capens0bac2852016-05-07 06:09:58 -0400614 if (!type->isMatrix() || !matrixInMatrix) {
615 if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
616 (op == EOpConstructStruct && size < type->getObjectSize())) {
617 error(line, "not enough data provided for construction", "constructor");
618 return true;
619 }
620 }
John Bauman66b8ab22014-05-06 15:57:45 -0400621
Nicolas Capens0bac2852016-05-07 06:09:58 -0400622 TIntermTyped *typed = node ? node->getAsTyped() : 0;
623 if (typed == 0) {
624 error(line, "constructor argument does not have a type", "constructor");
625 return true;
626 }
627 if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
628 error(line, "cannot convert a sampler", "constructor");
629 return true;
630 }
631 if (typed->getBasicType() == EbtVoid) {
632 error(line, "cannot convert a void", "constructor");
633 return true;
634 }
John Bauman66b8ab22014-05-06 15:57:45 -0400635
Nicolas Capens0bac2852016-05-07 06:09:58 -0400636 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400637}
638
639// This function checks to see if a void variable has been declared and raise an error message for such a case
640//
641// returns true in case of an error
642//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400643bool TParseContext::voidErrorCheck(const TSourceLoc &line, const TString& identifier, const TBasicType& type)
John Bauman66b8ab22014-05-06 15:57:45 -0400644{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400645 if(type == EbtVoid) {
646 error(line, "illegal use of type 'void'", identifier.c_str());
647 return true;
648 }
John Bauman66b8ab22014-05-06 15:57:45 -0400649
Nicolas Capens0bac2852016-05-07 06:09:58 -0400650 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400651}
652
653// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
654//
655// returns true in case of an error
656//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400657bool TParseContext::boolErrorCheck(const TSourceLoc &line, const TIntermTyped* type)
John Bauman66b8ab22014-05-06 15:57:45 -0400658{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400659 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
660 error(line, "boolean expression expected", "");
661 return true;
662 }
John Bauman66b8ab22014-05-06 15:57:45 -0400663
Nicolas Capens0bac2852016-05-07 06:09:58 -0400664 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400665}
666
667// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
668//
669// returns true in case of an error
670//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400671bool TParseContext::boolErrorCheck(const TSourceLoc &line, const TPublicType& pType)
John Bauman66b8ab22014-05-06 15:57:45 -0400672{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400673 if (pType.type != EbtBool || pType.array || (pType.primarySize > 1) || (pType.secondarySize > 1)) {
674 error(line, "boolean expression expected", "");
675 return true;
676 }
John Bauman66b8ab22014-05-06 15:57:45 -0400677
Nicolas Capens0bac2852016-05-07 06:09:58 -0400678 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400679}
680
Alexis Hetufe1269e2015-06-16 12:43:32 -0400681bool TParseContext::samplerErrorCheck(const TSourceLoc &line, const TPublicType& pType, const char* reason)
John Bauman66b8ab22014-05-06 15:57:45 -0400682{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400683 if (pType.type == EbtStruct) {
684 if (containsSampler(*pType.userDef)) {
685 error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400686
Nicolas Capens0bac2852016-05-07 06:09:58 -0400687 return true;
688 }
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400689
Nicolas Capens0bac2852016-05-07 06:09:58 -0400690 return false;
691 } else if (IsSampler(pType.type)) {
692 error(line, reason, getBasicString(pType.type));
John Bauman66b8ab22014-05-06 15:57:45 -0400693
Nicolas Capens0bac2852016-05-07 06:09:58 -0400694 return true;
695 }
John Bauman66b8ab22014-05-06 15:57:45 -0400696
Nicolas Capens0bac2852016-05-07 06:09:58 -0400697 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400698}
699
Alexis Hetufe1269e2015-06-16 12:43:32 -0400700bool TParseContext::structQualifierErrorCheck(const TSourceLoc &line, const TPublicType& pType)
John Bauman66b8ab22014-05-06 15:57:45 -0400701{
Alexis Hetu55a2cbc2015-04-16 10:49:45 -0400702 switch(pType.qualifier)
703 {
704 case EvqVaryingOut:
705 case EvqSmooth:
706 case EvqFlat:
707 case EvqCentroidOut:
708 case EvqVaryingIn:
709 case EvqSmoothIn:
710 case EvqFlatIn:
711 case EvqCentroidIn:
712 case EvqAttribute:
Alexis Hetu42ff6b12015-06-03 16:03:48 -0400713 case EvqVertexIn:
714 case EvqFragmentOut:
Alexis Hetu55a2cbc2015-04-16 10:49:45 -0400715 if(pType.type == EbtStruct)
716 {
717 error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400718
Alexis Hetu55a2cbc2015-04-16 10:49:45 -0400719 return true;
720 }
721 break;
722 default:
723 break;
724 }
John Bauman66b8ab22014-05-06 15:57:45 -0400725
Nicolas Capens0bac2852016-05-07 06:09:58 -0400726 if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
727 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400728
Alexis Hetu42ff6b12015-06-03 16:03:48 -0400729 // check for layout qualifier issues
Alexis Hetu42ff6b12015-06-03 16:03:48 -0400730 if (pType.qualifier != EvqVertexIn && pType.qualifier != EvqFragmentOut &&
Nicolas Capens0bac2852016-05-07 06:09:58 -0400731 layoutLocationErrorCheck(line, pType.layoutQualifier))
Alexis Hetu42ff6b12015-06-03 16:03:48 -0400732 {
733 return true;
734 }
735
Nicolas Capens0bac2852016-05-07 06:09:58 -0400736 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400737}
738
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400739// These checks are common for all declarations starting a declarator list, and declarators that follow an empty
740// declaration.
741//
742bool TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &identifierLocation)
743{
744 switch(publicType.qualifier)
745 {
746 case EvqVaryingIn:
747 case EvqVaryingOut:
748 case EvqAttribute:
749 case EvqVertexIn:
750 case EvqFragmentOut:
751 if(publicType.type == EbtStruct)
752 {
753 error(identifierLocation, "cannot be used with a structure",
754 getQualifierString(publicType.qualifier));
755 return true;
756 }
757
758 default: break;
759 }
760
761 if(publicType.qualifier != EvqUniform && samplerErrorCheck(identifierLocation, publicType,
762 "samplers must be uniform"))
763 {
764 return true;
765 }
766
767 // check for layout qualifier issues
768 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
769
770 if(layoutQualifier.matrixPacking != EmpUnspecified)
771 {
772 error(identifierLocation, "layout qualifier", getMatrixPackingString(layoutQualifier.matrixPacking),
773 "only valid for interface blocks");
774 return true;
775 }
776
777 if(layoutQualifier.blockStorage != EbsUnspecified)
778 {
779 error(identifierLocation, "layout qualifier", getBlockStorageString(layoutQualifier.blockStorage),
780 "only valid for interface blocks");
781 return true;
782 }
783
784 if(publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut &&
785 layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier))
786 {
787 return true;
788 }
789
790 return false;
791}
792
Nicolas Capens3713cd42015-06-22 10:41:54 -0400793bool TParseContext::layoutLocationErrorCheck(const TSourceLoc &location, const TLayoutQualifier &layoutQualifier)
794{
795 if(layoutQualifier.location != -1)
796 {
797 error(location, "invalid layout qualifier:", "location", "only valid on program inputs and outputs");
798 return true;
799 }
800
801 return false;
802}
Alexis Hetu42ff6b12015-06-03 16:03:48 -0400803
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400804bool TParseContext::locationDeclaratorListCheck(const TSourceLoc& line, const TPublicType &pType)
805{
806 if(pType.layoutQualifier.location != -1)
807 {
808 error(line, "location must only be specified for a single input or output variable", "location");
809 return true;
810 }
811
812 return false;
813}
814
Alexis Hetufe1269e2015-06-16 12:43:32 -0400815bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc &line, TQualifier qualifier, const TType& type)
John Bauman66b8ab22014-05-06 15:57:45 -0400816{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400817 if ((qualifier == EvqOut || qualifier == EvqInOut) &&
818 type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
819 error(line, "samplers cannot be output parameters", type.getBasicString());
820 return true;
821 }
John Bauman66b8ab22014-05-06 15:57:45 -0400822
Nicolas Capens0bac2852016-05-07 06:09:58 -0400823 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400824}
825
826bool TParseContext::containsSampler(TType& type)
827{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400828 if (IsSampler(type.getBasicType()))
829 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400830
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500831 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400832 const TFieldList& fields = type.getStruct()->fields();
833 for(unsigned int i = 0; i < fields.size(); ++i) {
834 if (containsSampler(*fields[i]->type()))
835 return true;
836 }
837 }
John Bauman66b8ab22014-05-06 15:57:45 -0400838
Nicolas Capens0bac2852016-05-07 06:09:58 -0400839 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400840}
841
842//
843// Do size checking for an array type's size.
844//
845// Returns true if there was an error.
846//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400847bool TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped* expr, int& size)
John Bauman66b8ab22014-05-06 15:57:45 -0400848{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400849 TIntermConstantUnion* constant = expr->getAsConstantUnion();
Nicolas Capens3c20f802015-02-17 17:17:20 -0500850
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500851 if (expr->getQualifier() != EvqConstExpr || constant == 0 || !constant->isScalarInt())
Nicolas Capens0bac2852016-05-07 06:09:58 -0400852 {
853 error(line, "array size must be a constant integer expression", "");
854 return true;
855 }
John Bauman66b8ab22014-05-06 15:57:45 -0400856
Nicolas Capens0bac2852016-05-07 06:09:58 -0400857 if (constant->getBasicType() == EbtUInt)
858 {
859 unsigned int uintSize = constant->getUConst(0);
860 if (uintSize > static_cast<unsigned int>(std::numeric_limits<int>::max()))
861 {
862 error(line, "array size too large", "");
863 size = 1;
864 return true;
865 }
John Bauman66b8ab22014-05-06 15:57:45 -0400866
Nicolas Capens0bac2852016-05-07 06:09:58 -0400867 size = static_cast<int>(uintSize);
868 }
869 else
870 {
871 size = constant->getIConst(0);
Nicolas Capens3c20f802015-02-17 17:17:20 -0500872
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500873 if (size < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400874 {
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500875 error(line, "array size must be non-negative", "");
Nicolas Capens0bac2852016-05-07 06:09:58 -0400876 size = 1;
877 return true;
878 }
879 }
John Bauman66b8ab22014-05-06 15:57:45 -0400880
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500881 if(size == 0)
882 {
883 error(line, "array size must be greater than zero", "");
884 return true;
885 }
886
Nicolas Capens0bac2852016-05-07 06:09:58 -0400887 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400888}
889
890//
891// See if this qualifier can be an array.
892//
893// Returns true if there is an error.
894//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400895bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc &line, TPublicType type)
John Bauman66b8ab22014-05-06 15:57:45 -0400896{
Alexis Hetud4e2ba52016-12-01 17:02:33 -0500897 if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) || (type.qualifier == EvqConstExpr && mShaderVersion < 300)) {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400898 error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
899 return true;
900 }
John Bauman66b8ab22014-05-06 15:57:45 -0400901
Nicolas Capens0bac2852016-05-07 06:09:58 -0400902 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400903}
904
905//
906// See if this type can be an array.
907//
908// Returns true if there is an error.
909//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400910bool TParseContext::arrayTypeErrorCheck(const TSourceLoc &line, TPublicType type)
John Bauman66b8ab22014-05-06 15:57:45 -0400911{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400912 //
913 // Can the type be an array?
914 //
915 if (type.array) {
916 error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
917 return true;
918 }
John Bauman66b8ab22014-05-06 15:57:45 -0400919
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500920 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
921 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section 4.3.4).
922 if(mShaderVersion >= 300 && type.type == EbtStruct && IsVarying(type.qualifier))
923 {
924 error(line, "cannot declare arrays of structs of this qualifier",
925 TType(type).getCompleteString().c_str());
926 return true;
927 }
928
Nicolas Capens0bac2852016-05-07 06:09:58 -0400929 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400930}
931
Alexis Hetufe1269e2015-06-16 12:43:32 -0400932bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400933{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400934 bool builtIn = false;
935 TSymbol* symbol = symbolTable.find(node->getSymbol(), mShaderVersion, &builtIn);
936 if (symbol == 0) {
937 error(line, " undeclared identifier", node->getSymbol().c_str());
938 return true;
939 }
940 TVariable* variable = static_cast<TVariable*>(symbol);
John Bauman66b8ab22014-05-06 15:57:45 -0400941
Nicolas Capens0bac2852016-05-07 06:09:58 -0400942 type->setArrayInformationType(variable->getArrayInformationType());
943 variable->updateArrayInformationType(type);
John Bauman66b8ab22014-05-06 15:57:45 -0400944
Nicolas Capens0bac2852016-05-07 06:09:58 -0400945 // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
946 // its an error
947 if (node->getSymbol() == "gl_FragData") {
948 TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", mShaderVersion, &builtIn);
949 ASSERT(fragData);
John Bauman66b8ab22014-05-06 15:57:45 -0400950
Nicolas Capens0bac2852016-05-07 06:09:58 -0400951 int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
952 if (fragDataValue <= size) {
953 error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers");
954 return true;
955 }
956 }
John Bauman66b8ab22014-05-06 15:57:45 -0400957
Nicolas Capens0bac2852016-05-07 06:09:58 -0400958 // we dont want to update the maxArraySize when this flag is not set, we just want to include this
959 // node type in the chain of node types so that its updated when a higher maxArraySize comes in.
960 if (!updateFlag)
961 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400962
Nicolas Capens0bac2852016-05-07 06:09:58 -0400963 size++;
964 variable->getType().setMaxArraySize(size);
965 type->setMaxArraySize(size);
966 TType* tt = type;
John Bauman66b8ab22014-05-06 15:57:45 -0400967
Nicolas Capens0bac2852016-05-07 06:09:58 -0400968 while(tt->getArrayInformationType() != 0) {
969 tt = tt->getArrayInformationType();
970 tt->setMaxArraySize(size);
971 }
John Bauman66b8ab22014-05-06 15:57:45 -0400972
Nicolas Capens0bac2852016-05-07 06:09:58 -0400973 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400974}
975
976//
977// Enforce non-initializer type/qualifier rules.
978//
979// Returns true if there was an error.
980//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400981bool TParseContext::nonInitConstErrorCheck(const TSourceLoc &line, TString& identifier, TPublicType& type, bool array)
John Bauman66b8ab22014-05-06 15:57:45 -0400982{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400983 if (type.qualifier == EvqConstExpr)
984 {
985 // Make the qualifier make sense.
986 type.qualifier = EvqTemporary;
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400987
Nicolas Capens0bac2852016-05-07 06:09:58 -0400988 if (array)
989 {
990 error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
991 }
992 else if (type.isStructureContainingArrays())
993 {
994 error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str());
995 }
996 else
997 {
998 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
999 }
John Bauman66b8ab22014-05-06 15:57:45 -04001000
Nicolas Capens0bac2852016-05-07 06:09:58 -04001001 return true;
1002 }
John Bauman66b8ab22014-05-06 15:57:45 -04001003
Nicolas Capens0bac2852016-05-07 06:09:58 -04001004 return false;
John Bauman66b8ab22014-05-06 15:57:45 -04001005}
1006
1007//
1008// Do semantic checking for a variable declaration that has no initializer,
1009// and update the symbol table.
1010//
1011// Returns true if there was an error.
1012//
Alexis Hetufe1269e2015-06-16 12:43:32 -04001013bool TParseContext::nonInitErrorCheck(const TSourceLoc &line, const TString& identifier, TPublicType& type)
John Bauman66b8ab22014-05-06 15:57:45 -04001014{
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001015 if(type.qualifier == EvqConstExpr)
1016 {
1017 // Make the qualifier make sense.
1018 type.qualifier = EvqTemporary;
John Bauman66b8ab22014-05-06 15:57:45 -04001019
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001020 // Generate informative error messages for ESSL1.
1021 // In ESSL3 arrays and structures containing arrays can be constant.
Alexis Hetu0a655842015-06-22 16:52:11 -04001022 if(mShaderVersion < 300 && type.isStructureContainingArrays())
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001023 {
1024 error(line,
1025 "structures containing arrays may not be declared constant since they cannot be initialized",
1026 identifier.c_str());
1027 }
1028 else
1029 {
1030 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
1031 }
John Bauman66b8ab22014-05-06 15:57:45 -04001032
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001033 return true;
1034 }
1035 if(type.isUnsizedArray())
1036 {
1037 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
1038 return true;
1039 }
1040 return false;
1041}
John Bauman66b8ab22014-05-06 15:57:45 -04001042
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001043// Do some simple checks that are shared between all variable declarations,
1044// and update the symbol table.
1045//
1046// Returns true if declaring the variable succeeded.
1047//
1048bool TParseContext::declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type,
1049 TVariable **variable)
1050{
1051 ASSERT((*variable) == nullptr);
John Bauman66b8ab22014-05-06 15:57:45 -04001052
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001053 // gl_LastFragData may be redeclared with a new precision qualifier
1054 if(type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
1055 {
1056 const TVariable *maxDrawBuffers =
Alexis Hetu0a655842015-06-22 16:52:11 -04001057 static_cast<const TVariable *>(symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001058 if(type.getArraySize() != maxDrawBuffers->getConstPointer()->getIConst())
1059 {
1060 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers", identifier.c_str());
1061 return false;
1062 }
1063 }
1064
1065 if(reservedErrorCheck(line, identifier))
1066 return false;
1067
1068 (*variable) = new TVariable(&identifier, type);
1069 if(!symbolTable.declare(**variable))
1070 {
1071 error(line, "redefinition", identifier.c_str());
1072 delete (*variable);
1073 (*variable) = nullptr;
1074 return false;
1075 }
1076
1077 if(voidErrorCheck(line, identifier, type.getBasicType()))
1078 return false;
1079
1080 return true;
John Bauman66b8ab22014-05-06 15:57:45 -04001081}
1082
Alexis Hetufe1269e2015-06-16 12:43:32 -04001083bool TParseContext::paramErrorCheck(const TSourceLoc &line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04001084{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001085 if (qualifier != EvqConstReadOnly && qualifier != EvqTemporary) {
1086 error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
1087 return true;
1088 }
1089 if (qualifier == EvqConstReadOnly && paramQualifier != EvqIn) {
1090 error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
1091 return true;
1092 }
John Bauman66b8ab22014-05-06 15:57:45 -04001093
Nicolas Capens0bac2852016-05-07 06:09:58 -04001094 if (qualifier == EvqConstReadOnly)
1095 type->setQualifier(EvqConstReadOnly);
1096 else
1097 type->setQualifier(paramQualifier);
John Bauman66b8ab22014-05-06 15:57:45 -04001098
Nicolas Capens0bac2852016-05-07 06:09:58 -04001099 return false;
John Bauman66b8ab22014-05-06 15:57:45 -04001100}
1101
Alexis Hetufe1269e2015-06-16 12:43:32 -04001102bool TParseContext::extensionErrorCheck(const TSourceLoc &line, const TString& extension)
John Bauman66b8ab22014-05-06 15:57:45 -04001103{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001104 const TExtensionBehavior& extBehavior = extensionBehavior();
1105 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
1106 if (iter == extBehavior.end()) {
1107 error(line, "extension", extension.c_str(), "is not supported");
1108 return true;
1109 }
1110 // In GLSL ES, an extension's default behavior is "disable".
1111 if (iter->second == EBhDisable || iter->second == EBhUndefined) {
1112 error(line, "extension", extension.c_str(), "is disabled");
1113 return true;
1114 }
1115 if (iter->second == EBhWarn) {
1116 warning(line, "extension", extension.c_str(), "is being used");
1117 return false;
1118 }
John Bauman66b8ab22014-05-06 15:57:45 -04001119
Nicolas Capens0bac2852016-05-07 06:09:58 -04001120 return false;
John Bauman66b8ab22014-05-06 15:57:45 -04001121}
1122
Alexis Hetuad6b8752015-06-09 16:15:30 -04001123bool TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *aggregate)
1124{
1125 for(size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1126 {
1127 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1128 if(qual == EvqOut || qual == EvqInOut)
1129 {
1130 TIntermTyped *node = (aggregate->getSequence())[i]->getAsTyped();
1131 if(lValueErrorCheck(node->getLine(), "assign", node))
1132 {
1133 error(node->getLine(),
1134 "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
1135 recover();
1136 return true;
1137 }
1138 }
1139 }
1140 return false;
1141}
1142
Alexis Hetuad527752015-07-07 13:31:44 -04001143void TParseContext::es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation)
1144{
1145 switch(qualifier)
1146 {
1147 case EvqVaryingOut:
1148 case EvqSmoothOut:
1149 case EvqFlatOut:
1150 case EvqCentroidOut:
1151 case EvqVertexOut:
1152 case EvqFragmentOut:
1153 break;
1154 default:
1155 error(invariantLocation, "Only out variables can be invariant.", "invariant");
1156 recover();
1157 break;
1158 }
1159}
1160
John Bauman66b8ab22014-05-06 15:57:45 -04001161bool TParseContext::supportsExtension(const char* extension)
1162{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001163 const TExtensionBehavior& extbehavior = extensionBehavior();
1164 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1165 return (iter != extbehavior.end());
John Bauman66b8ab22014-05-06 15:57:45 -04001166}
1167
Alexis Hetufe1269e2015-06-16 12:43:32 -04001168void TParseContext::handleExtensionDirective(const TSourceLoc &line, const char* extName, const char* behavior)
John Bauman66b8ab22014-05-06 15:57:45 -04001169{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001170 pp::SourceLocation loc(line.first_file, line.first_line);
1171 mDirectiveHandler.handleExtension(loc, extName, behavior);
John Bauman66b8ab22014-05-06 15:57:45 -04001172}
1173
Alexis Hetufe1269e2015-06-16 12:43:32 -04001174void TParseContext::handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value)
John Bauman66b8ab22014-05-06 15:57:45 -04001175{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001176 pp::SourceLocation loc(line.first_file, line.first_line);
1177 mDirectiveHandler.handlePragma(loc, name, value);
John Bauman66b8ab22014-05-06 15:57:45 -04001178}
1179
1180/////////////////////////////////////////////////////////////////////////////////
1181//
1182// Non-Errors.
1183//
1184/////////////////////////////////////////////////////////////////////////////////
1185
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001186const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1187 const TString *name,
1188 const TSymbol *symbol)
1189{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001190 const TVariable *variable = nullptr;
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001191
1192 if(!symbol)
1193 {
1194 error(location, "undeclared identifier", name->c_str());
1195 recover();
1196 }
1197 else if(!symbol->isVariable())
1198 {
1199 error(location, "variable expected", name->c_str());
1200 recover();
1201 }
1202 else
1203 {
1204 variable = static_cast<const TVariable*>(symbol);
1205
Alexis Hetu0a655842015-06-22 16:52:11 -04001206 if(symbolTable.findBuiltIn(variable->getName(), mShaderVersion))
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001207 {
1208 recover();
1209 }
1210
1211 // Reject shaders using both gl_FragData and gl_FragColor
1212 TQualifier qualifier = variable->getType().getQualifier();
1213 if(qualifier == EvqFragData)
1214 {
1215 mUsesFragData = true;
1216 }
1217 else if(qualifier == EvqFragColor)
1218 {
1219 mUsesFragColor = true;
1220 }
1221
1222 // This validation is not quite correct - it's only an error to write to
1223 // both FragData and FragColor. For simplicity, and because users shouldn't
Nicolas Capens8b124c12016-04-18 14:09:37 -04001224 // be rewarded for reading from undefined variables, return an error
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001225 // if they are both referenced, rather than assigned.
1226 if(mUsesFragData && mUsesFragColor)
1227 {
1228 error(location, "cannot use both gl_FragData and gl_FragColor", name->c_str());
1229 recover();
1230 }
1231 }
1232
1233 if(!variable)
1234 {
1235 TType type(EbtFloat, EbpUndefined);
1236 TVariable *fakeVariable = new TVariable(name, type);
1237 symbolTable.declare(*fakeVariable);
1238 variable = fakeVariable;
1239 }
1240
1241 return variable;
1242}
1243
John Bauman66b8ab22014-05-06 15:57:45 -04001244//
1245// Look up a function name in the symbol table, and make sure it is a function.
1246//
1247// Return the function symbol if found, otherwise 0.
1248//
Alexis Hetufe1269e2015-06-16 12:43:32 -04001249const TFunction* TParseContext::findFunction(const TSourceLoc &line, TFunction* call, bool *builtIn)
John Bauman66b8ab22014-05-06 15:57:45 -04001250{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001251 // First find by unmangled name to check whether the function name has been
1252 // hidden by a variable name or struct typename.
1253 const TSymbol* symbol = symbolTable.find(call->getName(), mShaderVersion, builtIn);
1254 if (symbol == 0) {
1255 symbol = symbolTable.find(call->getMangledName(), mShaderVersion, builtIn);
1256 }
John Bauman66b8ab22014-05-06 15:57:45 -04001257
Nicolas Capens0bac2852016-05-07 06:09:58 -04001258 if (symbol == 0) {
1259 error(line, "no matching overloaded function found", call->getName().c_str());
Alexis Hetuf0005a12016-09-28 15:52:21 -04001260 return nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001261 }
John Bauman66b8ab22014-05-06 15:57:45 -04001262
Nicolas Capens0bac2852016-05-07 06:09:58 -04001263 if (!symbol->isFunction()) {
1264 error(line, "function name expected", call->getName().c_str());
Alexis Hetuf0005a12016-09-28 15:52:21 -04001265 return nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001266 }
John Bauman66b8ab22014-05-06 15:57:45 -04001267
Nicolas Capens0bac2852016-05-07 06:09:58 -04001268 return static_cast<const TFunction*>(symbol);
John Bauman66b8ab22014-05-06 15:57:45 -04001269}
1270
1271//
1272// Initializers show up in several places in the grammar. Have one set of
1273// code to handle them here.
1274//
Alexis Hetufe1269e2015-06-16 12:43:32 -04001275bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& identifier, const TPublicType& pType,
Nicolas Capens0bac2852016-05-07 06:09:58 -04001276 TIntermTyped *initializer, TIntermNode **intermNode)
John Bauman66b8ab22014-05-06 15:57:45 -04001277{
Alexis Hetue5246692015-06-18 12:34:52 -04001278 ASSERT(intermNode != nullptr);
1279 TType type = TType(pType);
John Bauman66b8ab22014-05-06 15:57:45 -04001280
Alexis Hetuec93b1d2016-12-09 16:01:29 -05001281 if(type.isUnsizedArray())
Alexis Hetue5246692015-06-18 12:34:52 -04001282 {
Alexis Hetuec93b1d2016-12-09 16:01:29 -05001283 // We have not checked yet whether the initializer actually is an array or not.
1284 if(initializer->isArray())
1285 {
1286 type.setArraySize(initializer->getArraySize());
1287 }
1288 else
1289 {
1290 // Having a non-array initializer for an unsized array will result in an error later,
1291 // so we don't generate an error message here.
1292 type.setArraySize(1u);
1293 }
Alexis Hetue5246692015-06-18 12:34:52 -04001294 }
Nicolas Capens0863f0d2016-04-10 00:30:02 -04001295
1296 TVariable *variable = nullptr;
Alexis Hetue5246692015-06-18 12:34:52 -04001297 if(!declareVariable(line, identifier, type, &variable))
1298 {
1299 return true;
1300 }
John Bauman66b8ab22014-05-06 15:57:45 -04001301
Alexis Hetue5246692015-06-18 12:34:52 -04001302 bool globalInitWarning = false;
1303 if(symbolTable.atGlobalLevel() && !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
1304 {
1305 // Error message does not completely match behavior with ESSL 1.00, but
1306 // we want to steer developers towards only using constant expressions.
1307 error(line, "global variable initializers must be constant expressions", "=");
1308 return true;
1309 }
1310 if(globalInitWarning)
1311 {
1312 warning(line, "global variable initializers should be constant expressions "
1313 "(uniforms and globals are allowed in global initializers for legacy compatibility)", "=");
Nicolas Capens0bac2852016-05-07 06:09:58 -04001314 }
John Bauman66b8ab22014-05-06 15:57:45 -04001315
Nicolas Capens0bac2852016-05-07 06:09:58 -04001316 //
1317 // identifier must be of type constant, a global, or a temporary
1318 //
1319 TQualifier qualifier = type.getQualifier();
1320 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConstExpr)) {
1321 error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString());
1322 return true;
1323 }
1324 //
1325 // test for and propagate constant
1326 //
John Bauman66b8ab22014-05-06 15:57:45 -04001327
Nicolas Capens0bac2852016-05-07 06:09:58 -04001328 if (qualifier == EvqConstExpr) {
1329 if (qualifier != initializer->getQualifier()) {
1330 std::stringstream extraInfoStream;
1331 extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
1332 std::string extraInfo = extraInfoStream.str();
1333 error(line, " assigning non-constant to", "=", extraInfo.c_str());
1334 variable->getType().setQualifier(EvqTemporary);
1335 return true;
1336 }
Nicolas Capens0863f0d2016-04-10 00:30:02 -04001337
Nicolas Capens0bac2852016-05-07 06:09:58 -04001338 if (type != initializer->getType()) {
1339 error(line, " non-matching types for const initializer ",
1340 variable->getType().getQualifierString());
1341 variable->getType().setQualifier(EvqTemporary);
1342 return true;
1343 }
Nicolas Capens0863f0d2016-04-10 00:30:02 -04001344
Nicolas Capens0bac2852016-05-07 06:09:58 -04001345 if (initializer->getAsConstantUnion()) {
1346 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
1347 } else if (initializer->getAsSymbolNode()) {
1348 const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1349 const TVariable* tVar = static_cast<const TVariable*>(symbol);
John Bauman66b8ab22014-05-06 15:57:45 -04001350
Nicolas Capens0bac2852016-05-07 06:09:58 -04001351 ConstantUnion* constArray = tVar->getConstPointer();
1352 variable->shareConstPointer(constArray);
1353 }
1354 }
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04001355
Nicolas Capens0bac2852016-05-07 06:09:58 -04001356 if (!variable->isConstant()) {
1357 TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
1358 *intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1359 if(*intermNode == nullptr) {
1360 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1361 return true;
1362 }
1363 } else
1364 *intermNode = nullptr;
John Bauman66b8ab22014-05-06 15:57:45 -04001365
Nicolas Capens0bac2852016-05-07 06:09:58 -04001366 return false;
John Bauman66b8ab22014-05-06 15:57:45 -04001367}
1368
Alexis Hetu42ff6b12015-06-03 16:03:48 -04001369TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier)
1370{
1371 TPublicType returnType = typeSpecifier;
1372 returnType.qualifier = qualifier;
1373 returnType.invariant = invariant;
1374 returnType.layoutQualifier = layoutQualifier;
1375
1376 if(typeSpecifier.array)
1377 {
1378 error(typeSpecifier.line, "not supported", "first-class array");
1379 recover();
1380 returnType.clearArrayness();
1381 }
1382
Alexis Hetu0a655842015-06-22 16:52:11 -04001383 if(mShaderVersion < 300)
Alexis Hetu42ff6b12015-06-03 16:03:48 -04001384 {
Alexis Hetuec93b1d2016-12-09 16:01:29 -05001385 if(typeSpecifier.array)
1386 {
1387 error(typeSpecifier.line, "not supported", "first-class array");
1388 returnType.clearArrayness();
1389 }
1390
Alexis Hetu42ff6b12015-06-03 16:03:48 -04001391 if(qualifier == EvqAttribute && (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
1392 {
1393 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
1394 recover();
1395 }
1396
1397 if((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
1398 (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
1399 {
1400 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
1401 recover();
1402 }
1403 }
1404 else
1405 {
Alexis Hetuec93b1d2016-12-09 16:01:29 -05001406 if(!returnType.layoutQualifier.isEmpty())
Alexis Hetu42ff6b12015-06-03 16:03:48 -04001407 {
Alexis Hetuec93b1d2016-12-09 16:01:29 -05001408 globalErrorCheck(typeSpecifier.line, symbolTable.atGlobalLevel(), "layout");
1409 }
Alexis Hetu42ff6b12015-06-03 16:03:48 -04001410
Alexis Hetuec93b1d2016-12-09 16:01:29 -05001411 if(IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn || returnType.qualifier == EvqFragmentOut)
1412 {
1413 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier, typeSpecifier.line);
Alexis Hetu42ff6b12015-06-03 16:03:48 -04001414 }
1415 }
1416
1417 return returnType;
1418}
1419
Alexis Hetuec93b1d2016-12-09 16:01:29 -05001420void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1421 const TPublicType &type,
1422 const TSourceLoc &qualifierLocation)
1423{
1424 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
1425 if(type.type == EbtBool)
1426 {
1427 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
1428 }
1429
1430 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1431 switch(qualifier)
1432 {
1433 case EvqVertexIn:
1434 // ESSL 3.00 section 4.3.4
1435 if(type.array)
1436 {
1437 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
1438 }
1439 // Vertex inputs with a struct type are disallowed in singleDeclarationErrorCheck
1440 return;
1441 case EvqFragmentOut:
1442 // ESSL 3.00 section 4.3.6
1443 if(type.isMatrix())
1444 {
1445 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
1446 }
1447 // Fragment outputs with a struct type are disallowed in singleDeclarationErrorCheck
1448 return;
1449 default:
1450 break;
1451 }
1452
1453 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1454 // restrictions.
1455 bool typeContainsIntegers = (type.type == EbtInt || type.type == EbtUInt ||
1456 type.isStructureContainingType(EbtInt) ||
1457 type.isStructureContainingType(EbtUInt));
1458 if(typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1459 {
1460 error(qualifierLocation, "must use 'flat' interpolation here", getQualifierString(qualifier));
1461 }
1462
1463 if(type.type == EbtStruct)
1464 {
1465 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1466 // These restrictions are only implied by the ESSL 3.00 spec, but
1467 // the ESSL 3.10 spec lists these restrictions explicitly.
1468 if(type.array)
1469 {
1470 error(qualifierLocation, "cannot be an array of structures", getQualifierString(qualifier));
1471 }
1472 if(type.isStructureContainingArrays())
1473 {
1474 error(qualifierLocation, "cannot be a structure containing an array", getQualifierString(qualifier));
1475 }
1476 if(type.isStructureContainingType(EbtStruct))
1477 {
1478 error(qualifierLocation, "cannot be a structure containing a structure", getQualifierString(qualifier));
1479 }
1480 if(type.isStructureContainingType(EbtBool))
1481 {
1482 error(qualifierLocation, "cannot be a structure containing a bool", getQualifierString(qualifier));
1483 }
1484 }
1485}
1486
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001487TIntermAggregate *TParseContext::parseSingleDeclaration(TPublicType &publicType,
1488 const TSourceLoc &identifierOrTypeLocation,
1489 const TString &identifier)
1490{
1491 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierOrTypeLocation);
1492
1493 bool emptyDeclaration = (identifier == "");
1494
1495 mDeferredSingleDeclarationErrorCheck = emptyDeclaration;
1496
1497 if(emptyDeclaration)
1498 {
1499 if(publicType.isUnsizedArray())
1500 {
1501 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an error.
1502 // It is assumed that this applies to empty declarations as well.
1503 error(identifierOrTypeLocation, "empty array declaration needs to specify a size", identifier.c_str());
1504 }
1505 }
1506 else
1507 {
1508 if(singleDeclarationErrorCheck(publicType, identifierOrTypeLocation))
1509 recover();
1510
1511 if(nonInitErrorCheck(identifierOrTypeLocation, identifier, publicType))
1512 recover();
1513
1514 TVariable *variable = nullptr;
1515 if(!declareVariable(identifierOrTypeLocation, identifier, TType(publicType), &variable))
1516 recover();
1517
1518 if(variable && symbol)
1519 symbol->setId(variable->getUniqueId());
1520 }
1521
1522 return intermediate.makeAggregate(symbol, identifierOrTypeLocation);
1523}
1524
1525TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1526 const TSourceLoc &identifierLocation,
1527 const TString &identifier,
1528 const TSourceLoc &indexLocation,
1529 TIntermTyped *indexExpression)
1530{
1531 mDeferredSingleDeclarationErrorCheck = false;
1532
1533 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1534 recover();
1535
1536 if(nonInitErrorCheck(identifierLocation, identifier, publicType))
1537 recover();
1538
1539 if(arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
1540 {
1541 recover();
1542 }
1543
1544 TType arrayType(publicType);
1545
1546 int size;
1547 if(arraySizeErrorCheck(identifierLocation, indexExpression, size))
1548 {
1549 recover();
1550 }
1551 // Make the type an array even if size check failed.
1552 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1553 arrayType.setArraySize(size);
1554
1555 TVariable *variable = nullptr;
1556 if(!declareVariable(identifierLocation, identifier, arrayType, &variable))
1557 recover();
1558
1559 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
1560 if(variable && symbol)
1561 symbol->setId(variable->getUniqueId());
1562
1563 return intermediate.makeAggregate(symbol, identifierLocation);
1564}
1565
1566TIntermAggregate *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
1567 const TSourceLoc &identifierLocation,
1568 const TString &identifier,
1569 const TSourceLoc &initLocation,
1570 TIntermTyped *initializer)
1571{
1572 mDeferredSingleDeclarationErrorCheck = false;
1573
1574 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1575 recover();
1576
1577 TIntermNode *intermNode = nullptr;
Alexis Hetue5246692015-06-18 12:34:52 -04001578 if(!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001579 {
1580 //
1581 // Build intermediate representation
1582 //
1583 return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : nullptr;
1584 }
1585 else
1586 {
1587 recover();
1588 return nullptr;
1589 }
1590}
1591
1592TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration(TPublicType &publicType,
1593 const TSourceLoc &identifierLocation,
1594 const TString &identifier,
1595 const TSourceLoc &indexLocation,
1596 TIntermTyped *indexExpression,
1597 const TSourceLoc &initLocation,
1598 TIntermTyped *initializer)
1599{
1600 mDeferredSingleDeclarationErrorCheck = false;
1601
1602 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1603 recover();
1604
1605 if(arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
1606 {
1607 recover();
1608 }
1609
1610 TPublicType arrayType(publicType);
1611
1612 int size = 0;
1613 // If indexExpression is nullptr, then the array will eventually get its size implicitly from the initializer.
1614 if(indexExpression != nullptr && arraySizeErrorCheck(identifierLocation, indexExpression, size))
1615 {
1616 recover();
1617 }
1618 // Make the type an array even if size check failed.
1619 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1620 arrayType.setArray(true, size);
1621
1622 // initNode will correspond to the whole of "type b[n] = initializer".
1623 TIntermNode *initNode = nullptr;
Alexis Hetue5246692015-06-18 12:34:52 -04001624 if(!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001625 {
1626 return initNode ? intermediate.makeAggregate(initNode, initLocation) : nullptr;
1627 }
1628 else
1629 {
1630 recover();
1631 return nullptr;
1632 }
1633}
1634
1635TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc,
1636 const TSourceLoc &identifierLoc,
1637 const TString *identifier,
1638 const TSymbol *symbol)
1639{
1640 // invariant declaration
1641 if(globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying"))
1642 {
1643 recover();
1644 }
1645
1646 if(!symbol)
1647 {
1648 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
1649 recover();
1650 return nullptr;
1651 }
1652 else
1653 {
1654 const TString kGlFrontFacing("gl_FrontFacing");
1655 if(*identifier == kGlFrontFacing)
1656 {
1657 error(identifierLoc, "identifier should not be declared as invariant", identifier->c_str());
1658 recover();
1659 return nullptr;
1660 }
1661 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
1662 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
1663 ASSERT(variable);
1664 const TType &type = variable->getType();
1665 TIntermSymbol *intermSymbol = intermediate.addSymbol(variable->getUniqueId(),
1666 *identifier, type, identifierLoc);
1667
1668 TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc);
1669 aggregate->setOp(EOpInvariantDeclaration);
1670 return aggregate;
1671 }
1672}
1673
1674TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration,
1675 const TSourceLoc &identifierLocation, const TString &identifier)
1676{
1677 // If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
1678 if(mDeferredSingleDeclarationErrorCheck)
1679 {
1680 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1681 recover();
1682 mDeferredSingleDeclarationErrorCheck = false;
1683 }
1684
1685 if(locationDeclaratorListCheck(identifierLocation, publicType))
1686 recover();
1687
1688 if(nonInitErrorCheck(identifierLocation, identifier, publicType))
1689 recover();
1690
1691 TVariable *variable = nullptr;
1692 if(!declareVariable(identifierLocation, identifier, TType(publicType), &variable))
1693 recover();
1694
1695 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
1696 if(variable && symbol)
1697 symbol->setId(variable->getUniqueId());
1698
1699 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
1700}
1701
1702TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration,
1703 const TSourceLoc &identifierLocation, const TString &identifier,
1704 const TSourceLoc &arrayLocation, TIntermTyped *indexExpression)
1705{
1706 // If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
1707 if(mDeferredSingleDeclarationErrorCheck)
1708 {
1709 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1710 recover();
1711 mDeferredSingleDeclarationErrorCheck = false;
1712 }
1713
1714 if(locationDeclaratorListCheck(identifierLocation, publicType))
1715 recover();
1716
1717 if(nonInitErrorCheck(identifierLocation, identifier, publicType))
1718 recover();
1719
1720 if(arrayTypeErrorCheck(arrayLocation, publicType) || arrayQualifierErrorCheck(arrayLocation, publicType))
1721 {
1722 recover();
1723 }
1724 else
1725 {
1726 TType arrayType = TType(publicType);
1727 int size;
1728 if(arraySizeErrorCheck(arrayLocation, indexExpression, size))
1729 {
1730 recover();
1731 }
1732 arrayType.setArraySize(size);
1733
1734 TVariable *variable = nullptr;
1735 if(!declareVariable(identifierLocation, identifier, arrayType, &variable))
1736 recover();
1737
1738 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
1739 if(variable && symbol)
1740 symbol->setId(variable->getUniqueId());
1741
1742 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
1743 }
1744
1745 return nullptr;
1746}
1747
1748TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicType, TIntermAggregate *aggregateDeclaration,
1749 const TSourceLoc &identifierLocation, const TString &identifier,
1750 const TSourceLoc &initLocation, TIntermTyped *initializer)
1751{
1752 // If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
1753 if(mDeferredSingleDeclarationErrorCheck)
1754 {
1755 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1756 recover();
1757 mDeferredSingleDeclarationErrorCheck = false;
1758 }
1759
1760 if(locationDeclaratorListCheck(identifierLocation, publicType))
1761 recover();
1762
1763 TIntermNode *intermNode = nullptr;
Alexis Hetue5246692015-06-18 12:34:52 -04001764 if(!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001765 {
1766 //
1767 // build the intermediate representation
1768 //
1769 if(intermNode)
1770 {
1771 return intermediate.growAggregate(aggregateDeclaration, intermNode, initLocation);
1772 }
1773 else
1774 {
1775 return aggregateDeclaration;
1776 }
1777 }
1778 else
1779 {
1780 recover();
1781 return nullptr;
1782 }
1783}
1784
1785TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
1786 TIntermAggregate *aggregateDeclaration,
1787 const TSourceLoc &identifierLocation,
1788 const TString &identifier,
1789 const TSourceLoc &indexLocation,
1790 TIntermTyped *indexExpression,
1791 const TSourceLoc &initLocation, TIntermTyped *initializer)
1792{
1793 // If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
1794 if(mDeferredSingleDeclarationErrorCheck)
1795 {
1796 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1797 recover();
1798 mDeferredSingleDeclarationErrorCheck = false;
1799 }
1800
1801 if(locationDeclaratorListCheck(identifierLocation, publicType))
1802 recover();
1803
1804 if(arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
1805 {
1806 recover();
1807 }
1808
1809 TPublicType arrayType(publicType);
1810
1811 int size = 0;
1812 // If indexExpression is nullptr, then the array will eventually get its size implicitly from the initializer.
1813 if(indexExpression != nullptr && arraySizeErrorCheck(identifierLocation, indexExpression, size))
1814 {
1815 recover();
1816 }
1817 // Make the type an array even if size check failed.
1818 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1819 arrayType.setArray(true, size);
1820
1821 // initNode will correspond to the whole of "b[n] = initializer".
1822 TIntermNode *initNode = nullptr;
Alexis Hetue5246692015-06-18 12:34:52 -04001823 if(!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001824 {
1825 if(initNode)
1826 {
1827 return intermediate.growAggregate(aggregateDeclaration, initNode, initLocation);
1828 }
1829 else
1830 {
1831 return aggregateDeclaration;
1832 }
1833 }
1834 else
1835 {
1836 recover();
1837 return nullptr;
1838 }
1839}
1840
Alexis Hetua35d8232015-06-11 17:11:06 -04001841void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
1842{
Alexis Hetu0a655842015-06-22 16:52:11 -04001843 if(mShaderVersion < 300)
Alexis Hetua35d8232015-06-11 17:11:06 -04001844 {
1845 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 only", "layout");
1846 recover();
1847 return;
1848 }
1849
1850 if(typeQualifier.qualifier != EvqUniform)
1851 {
1852 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
1853 recover();
1854 return;
1855 }
1856
1857 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
1858 ASSERT(!layoutQualifier.isEmpty());
1859
1860 if(layoutLocationErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier))
1861 {
1862 recover();
1863 return;
1864 }
1865
1866 if(layoutQualifier.matrixPacking != EmpUnspecified)
1867 {
Alexis Hetu0a655842015-06-22 16:52:11 -04001868 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
Alexis Hetua35d8232015-06-11 17:11:06 -04001869 }
1870
1871 if(layoutQualifier.blockStorage != EbsUnspecified)
1872 {
Alexis Hetu0a655842015-06-22 16:52:11 -04001873 mDefaultBlockStorage = layoutQualifier.blockStorage;
Alexis Hetua35d8232015-06-11 17:11:06 -04001874 }
1875}
1876
Alexis Hetu407813b2016-02-24 16:46:13 -05001877TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function, const TSourceLoc &location)
1878{
1879 // Note: symbolTableFunction could be the same as function if this is the first declaration.
1880 // Either way the instance in the symbol table is used to track whether the function is declared
1881 // multiple times.
1882 TFunction *symbolTableFunction =
1883 static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion()));
1884 if(symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100)
1885 {
1886 // ESSL 1.00.17 section 4.2.7.
1887 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
1888 error(location, "duplicate function prototype declarations are not allowed", "function");
1889 recover();
1890 }
1891 symbolTableFunction->setHasPrototypeDeclaration();
1892
1893 TIntermAggregate *prototype = new TIntermAggregate;
1894 prototype->setType(function.getReturnType());
1895 prototype->setName(function.getMangledName());
1896
1897 for(size_t i = 0; i < function.getParamCount(); i++)
1898 {
1899 const TParameter &param = function.getParam(i);
1900 if(param.name != 0)
1901 {
1902 TVariable variable(param.name, *param.type);
1903
1904 TIntermSymbol *paramSymbol = intermediate.addSymbol(
1905 variable.getUniqueId(), variable.getName(), variable.getType(), location);
1906 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
1907 }
1908 else
1909 {
1910 TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
1911 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
1912 }
1913 }
1914
1915 prototype->setOp(EOpPrototype);
1916
1917 symbolTable.pop();
1918
1919 if(!symbolTable.atGlobalLevel())
1920 {
1921 // ESSL 3.00.4 section 4.2.4.
1922 error(location, "local function prototype declarations are not allowed", "function");
1923 recover();
1924 }
1925
1926 return prototype;
1927}
1928
1929TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function, TIntermAggregate *functionPrototype, TIntermAggregate *functionBody, const TSourceLoc &location)
1930{
1931 //?? Check that all paths return a value if return type != void ?
1932 // May be best done as post process phase on intermediate code
1933 if(mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
1934 {
1935 error(location, "function does not return a value:", "", function.getName().c_str());
1936 recover();
1937 }
1938
1939 TIntermAggregate *aggregate = intermediate.growAggregate(functionPrototype, functionBody, location);
1940 intermediate.setAggregateOperator(aggregate, EOpFunction, location);
1941 aggregate->setName(function.getMangledName().c_str());
1942 aggregate->setType(function.getReturnType());
1943
Nicolas Capens0863f0d2016-04-10 00:30:02 -04001944 // store the pragma information for debug and optimize and other vendor specific
1945 // information. This information can be queried from the parse tree
1946 aggregate->setOptimize(pragma().optimize);
Alexis Hetu407813b2016-02-24 16:46:13 -05001947 aggregate->setDebug(pragma().debug);
1948
Nicolas Capens0863f0d2016-04-10 00:30:02 -04001949 if(functionBody && functionBody->getAsAggregate())
Alexis Hetu407813b2016-02-24 16:46:13 -05001950 aggregate->setEndLine(functionBody->getAsAggregate()->getEndLine());
1951
1952 symbolTable.pop();
1953 return aggregate;
1954}
1955
1956void TParseContext::parseFunctionPrototype(const TSourceLoc &location, TFunction *function, TIntermAggregate **aggregateOut)
1957{
1958 const TSymbol *builtIn = symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
1959
1960 if(builtIn)
1961 {
1962 error(location, "built-in functions cannot be redefined", function->getName().c_str());
1963 recover();
1964 }
1965
1966 TFunction *prevDec = static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
1967 //
1968 // Note: 'prevDec' could be 'function' if this is the first time we've seen function
1969 // as it would have just been put in the symbol table. Otherwise, we're looking up
1970 // an earlier occurance.
1971 //
1972 if(prevDec->isDefined())
1973 {
1974 // Then this function already has a body.
1975 error(location, "function already has a body", function->getName().c_str());
1976 recover();
1977 }
1978 prevDec->setDefined();
1979 //
1980 // Overload the unique ID of the definition to be the same unique ID as the declaration.
1981 // Eventually we will probably want to have only a single definition and just swap the
1982 // arguments to be the definition's arguments.
1983 //
1984 function->setUniqueId(prevDec->getUniqueId());
1985
1986 // Raise error message if main function takes any parameters or return anything other than void
1987 if(function->getName() == "main")
1988 {
1989 if(function->getParamCount() > 0)
1990 {
1991 error(location, "function cannot take any parameter(s)", function->getName().c_str());
1992 recover();
1993 }
1994 if(function->getReturnType().getBasicType() != EbtVoid)
1995 {
1996 error(location, "", function->getReturnType().getBasicString(), "main function cannot return a value");
1997 recover();
1998 }
1999 }
2000
2001 //
2002 // Remember the return type for later checking for RETURN statements.
2003 //
2004 mCurrentFunctionType = &(prevDec->getReturnType());
2005 mFunctionReturnsValue = false;
2006
2007 //
2008 // Insert parameters into the symbol table.
2009 // If the parameter has no name, it's not an error, just don't insert it
2010 // (could be used for unused args).
2011 //
2012 // Also, accumulate the list of parameters into the HIL, so lower level code
2013 // knows where to find parameters.
2014 //
2015 TIntermAggregate *paramNodes = new TIntermAggregate;
2016 for(size_t i = 0; i < function->getParamCount(); i++)
2017 {
2018 const TParameter &param = function->getParam(i);
2019 if(param.name != 0)
2020 {
2021 TVariable *variable = new TVariable(param.name, *param.type);
2022 //
2023 // Insert the parameters with name in the symbol table.
2024 //
2025 if(!symbolTable.declare(*variable))
2026 {
2027 error(location, "redefinition", variable->getName().c_str());
2028 recover();
2029 paramNodes = intermediate.growAggregate(
2030 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
2031 continue;
2032 }
2033
2034 //
2035 // Add the parameter to the HIL
2036 //
2037 TIntermSymbol *symbol = intermediate.addSymbol(
2038 variable->getUniqueId(), variable->getName(), variable->getType(), location);
2039
2040 paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
2041 }
2042 else
2043 {
2044 paramNodes = intermediate.growAggregate(
2045 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
2046 }
2047 }
2048 intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
2049 *aggregateOut = paramNodes;
2050 setLoopNestingLevel(0);
2051}
2052
2053TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
2054{
2055 //
2056 // We don't know at this point whether this is a function definition or a prototype.
2057 // The definition production code will check for redefinitions.
2058 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
2059 //
2060 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2061 // here.
2062 //
2063 TFunction *prevDec = static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Alexis Hetuec93b1d2016-12-09 16:01:29 -05002064 if(getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltIn(function->getName().c_str()))
2065 {
2066 // With ESSL 3.00, names of built-in functions cannot be redeclared as functions.
2067 // Therefore overloading or redefining builtin functions is an error.
2068 error(location, "Name of a built-in function cannot be redeclared as function", function->getName().c_str());
2069 }
2070 else if(prevDec)
Alexis Hetu407813b2016-02-24 16:46:13 -05002071 {
2072 if(prevDec->getReturnType() != function->getReturnType())
2073 {
2074 error(location, "overloaded functions must have the same return type",
2075 function->getReturnType().getBasicString());
2076 recover();
2077 }
2078 for(size_t i = 0; i < prevDec->getParamCount(); ++i)
2079 {
2080 if(prevDec->getParam(i).type->getQualifier() != function->getParam(i).type->getQualifier())
2081 {
2082 error(location, "overloaded functions must have the same parameter qualifiers",
2083 function->getParam(i).type->getQualifierString());
2084 recover();
2085 }
2086 }
2087 }
2088
2089 //
2090 // Check for previously declared variables using the same name.
2091 //
2092 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
2093 if(prevSym)
2094 {
2095 if(!prevSym->isFunction())
2096 {
2097 error(location, "redefinition", function->getName().c_str(), "function");
2098 recover();
2099 }
2100 }
2101
2102 // We're at the inner scope level of the function's arguments and body statement.
2103 // Add the function prototype to the surrounding scope instead.
2104 symbolTable.getOuterLevel()->insert(*function);
2105
2106 //
2107 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2108 // variable names from this one, and not the one that's
2109 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2110 //
2111 return function;
2112}
2113
Alexis Hetue5246692015-06-18 12:34:52 -04002114TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
2115{
2116 TPublicType publicType = publicTypeIn;
2117 TOperator op = EOpNull;
2118 if(publicType.userDef)
2119 {
2120 op = EOpConstructStruct;
2121 }
2122 else
2123 {
Alexis Hetuec93b1d2016-12-09 16:01:29 -05002124 op = TypeToConstructorOperator(TType(publicType));
Alexis Hetue5246692015-06-18 12:34:52 -04002125 if(op == EOpNull)
2126 {
2127 error(publicType.line, "cannot construct this type", getBasicString(publicType.type));
2128 recover();
2129 publicType.type = EbtFloat;
2130 op = EOpConstructFloat;
2131 }
2132 }
2133
2134 TString tempString;
2135 TType type(publicType);
2136 return new TFunction(&tempString, type, op);
2137}
2138
John Bauman66b8ab22014-05-06 15:57:45 -04002139// This function is used to test for the correctness of the parameters passed to various constructor functions
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002140// and also convert them to the right datatype if it is allowed and required.
John Bauman66b8ab22014-05-06 15:57:45 -04002141//
2142// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
2143//
Alexis Hetufe1269e2015-06-16 12:43:32 -04002144TIntermTyped* TParseContext::addConstructor(TIntermNode* arguments, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -04002145{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002146 TIntermAggregate *aggregateArguments = arguments->getAsAggregate();
John Bauman66b8ab22014-05-06 15:57:45 -04002147
Nicolas Capens0bac2852016-05-07 06:09:58 -04002148 if(!aggregateArguments)
2149 {
2150 aggregateArguments = new TIntermAggregate;
2151 aggregateArguments->getSequence().push_back(arguments);
2152 }
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002153
Alexis Hetu2a198552016-09-27 20:50:45 -04002154 if(type->isArray())
2155 {
2156 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
2157 // the array.
2158 for(TIntermNode *&argNode : aggregateArguments->getSequence())
2159 {
2160 const TType &argType = argNode->getAsTyped()->getType();
2161 // It has already been checked that the argument is not an array.
2162 ASSERT(!argType.isArray());
2163 if(!argType.sameElementType(*type))
2164 {
2165 error(line, "Array constructor argument has an incorrect type", "Error");
Alexis Hetuf0005a12016-09-28 15:52:21 -04002166 return nullptr;
Alexis Hetu2a198552016-09-27 20:50:45 -04002167 }
2168 }
2169 }
2170 else if(op == EOpConstructStruct)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002171 {
2172 const TFieldList &fields = type->getStruct()->fields();
2173 TIntermSequence &args = aggregateArguments->getSequence();
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002174
Nicolas Capens0bac2852016-05-07 06:09:58 -04002175 for(size_t i = 0; i < fields.size(); i++)
2176 {
2177 if(args[i]->getAsTyped()->getType() != *fields[i]->type())
2178 {
2179 error(line, "Structure constructor arguments do not match structure fields", "Error");
2180 recover();
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002181
Alexis Hetuf0005a12016-09-28 15:52:21 -04002182 return nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002183 }
2184 }
2185 }
John Bauman66b8ab22014-05-06 15:57:45 -04002186
Nicolas Capens0bac2852016-05-07 06:09:58 -04002187 // Turn the argument list itself into a constructor
2188 TIntermAggregate *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line);
2189 TIntermTyped *constConstructor = foldConstConstructor(constructor, *type);
2190 if(constConstructor)
2191 {
2192 return constConstructor;
2193 }
John Bauman66b8ab22014-05-06 15:57:45 -04002194
Nicolas Capens0bac2852016-05-07 06:09:58 -04002195 return constructor;
John Bauman66b8ab22014-05-06 15:57:45 -04002196}
2197
2198TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
2199{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002200 aggrNode->setType(type);
2201 if (aggrNode->isConstantFoldable()) {
2202 bool returnVal = false;
2203 ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
2204 if (aggrNode->getSequence().size() == 1) {
2205 returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type, true);
2206 }
2207 else {
2208 returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type);
2209 }
2210 if (returnVal)
Alexis Hetuf0005a12016-09-28 15:52:21 -04002211 return nullptr;
John Bauman66b8ab22014-05-06 15:57:45 -04002212
Nicolas Capens0bac2852016-05-07 06:09:58 -04002213 return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
2214 }
John Bauman66b8ab22014-05-06 15:57:45 -04002215
Alexis Hetuf0005a12016-09-28 15:52:21 -04002216 return nullptr;
John Bauman66b8ab22014-05-06 15:57:45 -04002217}
2218
John Bauman66b8ab22014-05-06 15:57:45 -04002219//
2220// This function returns the tree representation for the vector field(s) being accessed from contant vector.
2221// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
2222// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
Nicolas Capens0863f0d2016-04-10 00:30:02 -04002223// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
John Bauman66b8ab22014-05-06 15:57:45 -04002224// a constant matrix.
2225//
Alexis Hetufe1269e2015-06-16 12:43:32 -04002226TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -04002227{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002228 TIntermTyped* typedNode;
2229 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
John Bauman66b8ab22014-05-06 15:57:45 -04002230
Nicolas Capens0bac2852016-05-07 06:09:58 -04002231 ConstantUnion *unionArray;
2232 if (tempConstantNode) {
2233 unionArray = tempConstantNode->getUnionArrayPointer();
John Bauman66b8ab22014-05-06 15:57:45 -04002234
Nicolas Capens0bac2852016-05-07 06:09:58 -04002235 if (!unionArray) {
2236 return node;
2237 }
2238 } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
2239 error(line, "Cannot offset into the vector", "Error");
2240 recover();
John Bauman66b8ab22014-05-06 15:57:45 -04002241
Alexis Hetuf0005a12016-09-28 15:52:21 -04002242 return nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002243 }
John Bauman66b8ab22014-05-06 15:57:45 -04002244
Nicolas Capens0bac2852016-05-07 06:09:58 -04002245 ConstantUnion* constArray = new ConstantUnion[fields.num];
John Bauman66b8ab22014-05-06 15:57:45 -04002246
Alexis Hetub34591a2016-06-28 15:48:35 -04002247 int objSize = static_cast<int>(node->getType().getObjectSize());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002248 for (int i = 0; i < fields.num; i++) {
Alexis Hetub34591a2016-06-28 15:48:35 -04002249 if (fields.offsets[i] >= objSize) {
Nicolas Capens0bac2852016-05-07 06:09:58 -04002250 std::stringstream extraInfoStream;
2251 extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
2252 std::string extraInfo = extraInfoStream.str();
2253 error(line, "", "[", extraInfo.c_str());
2254 recover();
2255 fields.offsets[i] = 0;
2256 }
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002257
Nicolas Capens0bac2852016-05-07 06:09:58 -04002258 constArray[i] = unionArray[fields.offsets[i]];
John Bauman66b8ab22014-05-06 15:57:45 -04002259
Nicolas Capens0bac2852016-05-07 06:09:58 -04002260 }
2261 typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
2262 return typedNode;
John Bauman66b8ab22014-05-06 15:57:45 -04002263}
2264
2265//
2266// This function returns the column being accessed from a constant matrix. The values are retrieved from
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002267// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
2268// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
John Bauman66b8ab22014-05-06 15:57:45 -04002269// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
2270//
Alexis Hetufe1269e2015-06-16 12:43:32 -04002271TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -04002272{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002273 TIntermTyped* typedNode;
2274 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
John Bauman66b8ab22014-05-06 15:57:45 -04002275
Nicolas Capens0bac2852016-05-07 06:09:58 -04002276 if (index >= node->getType().getNominalSize()) {
2277 std::stringstream extraInfoStream;
2278 extraInfoStream << "matrix field selection out of range '" << index << "'";
2279 std::string extraInfo = extraInfoStream.str();
2280 error(line, "", "[", extraInfo.c_str());
2281 recover();
2282 index = 0;
2283 }
John Bauman66b8ab22014-05-06 15:57:45 -04002284
Nicolas Capens0bac2852016-05-07 06:09:58 -04002285 if (tempConstantNode) {
2286 ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
2287 int size = tempConstantNode->getType().getNominalSize();
2288 typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
2289 } else {
2290 error(line, "Cannot offset into the matrix", "Error");
2291 recover();
John Bauman66b8ab22014-05-06 15:57:45 -04002292
Alexis Hetuf0005a12016-09-28 15:52:21 -04002293 return nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002294 }
John Bauman66b8ab22014-05-06 15:57:45 -04002295
Nicolas Capens0bac2852016-05-07 06:09:58 -04002296 return typedNode;
John Bauman66b8ab22014-05-06 15:57:45 -04002297}
2298
2299
2300//
2301// This function returns an element of an array accessed from a constant array. The values are retrieved from
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002302// the symbol table and parse-tree is built for the type of the element. The input
2303// to the function could either be a symbol node (a[0] where a is a constant array)that represents a
John Bauman66b8ab22014-05-06 15:57:45 -04002304// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
2305//
Alexis Hetufe1269e2015-06-16 12:43:32 -04002306TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -04002307{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002308 TIntermTyped* typedNode;
2309 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
2310 TType arrayElementType = node->getType();
2311 arrayElementType.clearArrayness();
John Bauman66b8ab22014-05-06 15:57:45 -04002312
Nicolas Capens0bac2852016-05-07 06:09:58 -04002313 if (index >= node->getType().getArraySize()) {
2314 std::stringstream extraInfoStream;
2315 extraInfoStream << "array field selection out of range '" << index << "'";
2316 std::string extraInfo = extraInfoStream.str();
2317 error(line, "", "[", extraInfo.c_str());
2318 recover();
2319 index = 0;
2320 }
John Bauman66b8ab22014-05-06 15:57:45 -04002321
Nicolas Capens0bac2852016-05-07 06:09:58 -04002322 size_t arrayElementSize = arrayElementType.getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04002323
Nicolas Capens0bac2852016-05-07 06:09:58 -04002324 if (tempConstantNode) {
2325 ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
2326 typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
2327 } else {
2328 error(line, "Cannot offset into the array", "Error");
2329 recover();
John Bauman66b8ab22014-05-06 15:57:45 -04002330
Alexis Hetuf0005a12016-09-28 15:52:21 -04002331 return nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002332 }
John Bauman66b8ab22014-05-06 15:57:45 -04002333
Nicolas Capens0bac2852016-05-07 06:09:58 -04002334 return typedNode;
John Bauman66b8ab22014-05-06 15:57:45 -04002335}
2336
2337
2338//
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002339// This function returns the value of a particular field inside a constant structure from the symbol table.
John Bauman66b8ab22014-05-06 15:57:45 -04002340// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
2341// function and returns the parse-tree with the values of the embedded/nested struct.
2342//
Alexis Hetufe1269e2015-06-16 12:43:32 -04002343TIntermTyped* TParseContext::addConstStruct(const TString& identifier, TIntermTyped* node, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -04002344{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002345 const TFieldList &fields = node->getType().getStruct()->fields();
2346 TIntermTyped *typedNode;
2347 size_t instanceSize = 0;
2348 TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
John Bauman66b8ab22014-05-06 15:57:45 -04002349
Nicolas Capens0bac2852016-05-07 06:09:58 -04002350 for(size_t index = 0; index < fields.size(); ++index) {
2351 if (fields[index]->name() == identifier) {
2352 break;
2353 } else {
2354 instanceSize += fields[index]->type()->getObjectSize();
2355 }
2356 }
John Bauman66b8ab22014-05-06 15:57:45 -04002357
Nicolas Capens0bac2852016-05-07 06:09:58 -04002358 if (tempConstantNode) {
2359 ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
John Bauman66b8ab22014-05-06 15:57:45 -04002360
Nicolas Capens0bac2852016-05-07 06:09:58 -04002361 typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
2362 } else {
2363 error(line, "Cannot offset into the structure", "Error");
2364 recover();
John Bauman66b8ab22014-05-06 15:57:45 -04002365
Alexis Hetuf0005a12016-09-28 15:52:21 -04002366 return nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002367 }
John Bauman66b8ab22014-05-06 15:57:45 -04002368
Nicolas Capens0bac2852016-05-07 06:09:58 -04002369 return typedNode;
John Bauman66b8ab22014-05-06 15:57:45 -04002370}
2371
Alexis Hetuad6b8752015-06-09 16:15:30 -04002372//
Alexis Hetua35d8232015-06-11 17:11:06 -04002373// Interface/uniform blocks
2374//
2375TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList,
Nicolas Capens0bac2852016-05-07 06:09:58 -04002376 const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine)
Alexis Hetua35d8232015-06-11 17:11:06 -04002377{
2378 if(reservedErrorCheck(nameLine, blockName))
2379 recover();
2380
2381 if(typeQualifier.qualifier != EvqUniform)
2382 {
2383 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "interface blocks must be uniform");
2384 recover();
2385 }
2386
2387 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
2388 if(layoutLocationErrorCheck(typeQualifier.line, blockLayoutQualifier))
2389 {
2390 recover();
2391 }
2392
2393 if(blockLayoutQualifier.matrixPacking == EmpUnspecified)
2394 {
Alexis Hetu0a655842015-06-22 16:52:11 -04002395 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Alexis Hetua35d8232015-06-11 17:11:06 -04002396 }
2397
2398 if(blockLayoutQualifier.blockStorage == EbsUnspecified)
2399 {
Alexis Hetu0a655842015-06-22 16:52:11 -04002400 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Alexis Hetua35d8232015-06-11 17:11:06 -04002401 }
2402
2403 TSymbol* blockNameSymbol = new TSymbol(&blockName);
2404 if(!symbolTable.declare(*blockNameSymbol)) {
2405 error(nameLine, "redefinition", blockName.c_str(), "interface block name");
2406 recover();
2407 }
2408
2409 // check for sampler types and apply layout qualifiers
2410 for(size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) {
2411 TField* field = (*fieldList)[memberIndex];
2412 TType* fieldType = field->type();
2413 if(IsSampler(fieldType->getBasicType())) {
2414 error(field->line(), "unsupported type", fieldType->getBasicString(), "sampler types are not allowed in interface blocks");
2415 recover();
2416 }
2417
2418 const TQualifier qualifier = fieldType->getQualifier();
2419 switch(qualifier)
2420 {
2421 case EvqGlobal:
2422 case EvqUniform:
2423 break;
2424 default:
2425 error(field->line(), "invalid qualifier on interface block member", getQualifierString(qualifier));
2426 recover();
2427 break;
2428 }
2429
2430 // check layout qualifiers
2431 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
2432 if(layoutLocationErrorCheck(field->line(), fieldLayoutQualifier))
2433 {
2434 recover();
2435 }
2436
2437 if(fieldLayoutQualifier.blockStorage != EbsUnspecified)
2438 {
2439 error(field->line(), "invalid layout qualifier:", getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
2440 recover();
2441 }
2442
2443 if(fieldLayoutQualifier.matrixPacking == EmpUnspecified)
2444 {
2445 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
2446 }
2447 else if(!fieldType->isMatrix())
2448 {
2449 error(field->line(), "invalid layout qualifier:", getMatrixPackingString(fieldLayoutQualifier.matrixPacking), "can only be used on matrix types");
2450 recover();
2451 }
2452
2453 fieldType->setLayoutQualifier(fieldLayoutQualifier);
2454 }
2455
2456 // add array index
2457 int arraySize = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002458 if(arrayIndex)
Alexis Hetua35d8232015-06-11 17:11:06 -04002459 {
2460 if(arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize))
2461 recover();
2462 }
2463
2464 TInterfaceBlock* interfaceBlock = new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2465 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier, arraySize);
2466
2467 TString symbolName = "";
2468 int symbolId = 0;
2469
2470 if(!instanceName)
2471 {
2472 // define symbols for the members of the interface block
2473 for(size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2474 {
2475 TField* field = (*fieldList)[memberIndex];
2476 TType* fieldType = field->type();
2477
2478 // set parent pointer of the field variable
2479 fieldType->setInterfaceBlock(interfaceBlock);
2480
2481 TVariable* fieldVariable = new TVariable(&field->name(), *fieldType);
2482 fieldVariable->setQualifier(typeQualifier.qualifier);
2483
2484 if(!symbolTable.declare(*fieldVariable)) {
2485 error(field->line(), "redefinition", field->name().c_str(), "interface block member name");
2486 recover();
2487 }
2488 }
2489 }
2490 else
2491 {
2492 // add a symbol for this interface block
2493 TVariable* instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
2494 instanceTypeDef->setQualifier(typeQualifier.qualifier);
2495
2496 if(!symbolTable.declare(*instanceTypeDef)) {
2497 error(instanceLine, "redefinition", instanceName->c_str(), "interface block instance name");
2498 recover();
2499 }
2500
2501 symbolId = instanceTypeDef->getUniqueId();
2502 symbolName = instanceTypeDef->getName();
2503 }
2504
2505 TIntermAggregate *aggregate = intermediate.makeAggregate(intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line), nameLine);
2506 aggregate->setOp(EOpDeclaration);
2507
2508 exitStructDeclaration();
2509 return aggregate;
2510}
2511
2512//
Alexis Hetuad6b8752015-06-09 16:15:30 -04002513// Parse an array index expression
2514//
2515TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc &location, TIntermTyped *indexExpression)
2516{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002517 TIntermTyped *indexedExpression = nullptr;
Alexis Hetuad6b8752015-06-09 16:15:30 -04002518
2519 if(!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2520 {
2521 if(baseExpression->getAsSymbolNode())
2522 {
2523 error(location, " left of '[' is not of type array, matrix, or vector ",
2524 baseExpression->getAsSymbolNode()->getSymbol().c_str());
2525 }
2526 else
2527 {
2528 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2529 }
2530 recover();
2531 }
2532
2533 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2534
2535 if(indexExpression->getQualifier() == EvqConstExpr && indexConstantUnion)
2536 {
2537 int index = indexConstantUnion->getIConst(0);
2538 if(index < 0)
2539 {
2540 std::stringstream infoStream;
2541 infoStream << index;
2542 std::string info = infoStream.str();
2543 error(location, "negative index", info.c_str());
2544 recover();
2545 index = 0;
2546 }
2547 if(baseExpression->getType().getQualifier() == EvqConstExpr)
2548 {
2549 if(baseExpression->isArray())
2550 {
2551 // constant folding for arrays
2552 indexedExpression = addConstArrayNode(index, baseExpression, location);
2553 }
2554 else if(baseExpression->isVector())
2555 {
2556 // constant folding for vectors
2557 TVectorFields fields;
2558 fields.num = 1;
2559 fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
2560 indexedExpression = addConstVectorNode(fields, baseExpression, location);
2561 }
2562 else if(baseExpression->isMatrix())
2563 {
2564 // constant folding for matrices
2565 indexedExpression = addConstMatrixNode(index, baseExpression, location);
2566 }
2567 }
2568 else
2569 {
2570 int safeIndex = -1;
2571
2572 if(baseExpression->isArray())
2573 {
2574 if(index >= baseExpression->getType().getArraySize())
2575 {
2576 std::stringstream extraInfoStream;
2577 extraInfoStream << "array index out of range '" << index << "'";
2578 std::string extraInfo = extraInfoStream.str();
2579 error(location, "", "[", extraInfo.c_str());
2580 recover();
2581 safeIndex = baseExpression->getType().getArraySize() - 1;
2582 }
2583 }
2584 else if((baseExpression->isVector() || baseExpression->isMatrix()) &&
2585 baseExpression->getType().getNominalSize() <= index)
2586 {
2587 std::stringstream extraInfoStream;
2588 extraInfoStream << "field selection out of range '" << index << "'";
2589 std::string extraInfo = extraInfoStream.str();
2590 error(location, "", "[", extraInfo.c_str());
2591 recover();
2592 safeIndex = baseExpression->getType().getNominalSize() - 1;
2593 }
2594
2595 // Don't modify the data of the previous constant union, because it can point
2596 // to builtins, like gl_MaxDrawBuffers. Instead use a new sanitized object.
2597 if(safeIndex != -1)
2598 {
2599 ConstantUnion *safeConstantUnion = new ConstantUnion();
2600 safeConstantUnion->setIConst(safeIndex);
2601 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
2602 }
2603
2604 indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
2605 }
2606 }
2607 else
2608 {
2609 if(baseExpression->isInterfaceBlock())
2610 {
2611 error(location, "",
2612 "[", "array indexes for interface blocks arrays must be constant integral expressions");
2613 recover();
2614 }
Alexis Hetuad6b8752015-06-09 16:15:30 -04002615 else if(baseExpression->getQualifier() == EvqFragmentOut)
2616 {
2617 error(location, "", "[", "array indexes for fragment outputs must be constant integral expressions");
2618 recover();
2619 }
Alexis Hetuad6b8752015-06-09 16:15:30 -04002620
2621 indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
2622 }
2623
2624 if(indexedExpression == 0)
2625 {
2626 ConstantUnion *unionArray = new ConstantUnion[1];
2627 unionArray->setFConst(0.0f);
2628 indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConstExpr), location);
2629 }
2630 else if(baseExpression->isArray())
2631 {
2632 const TType &baseType = baseExpression->getType();
2633 if(baseType.getStruct())
2634 {
2635 TType copyOfType(baseType.getStruct());
2636 indexedExpression->setType(copyOfType);
2637 }
2638 else if(baseType.isInterfaceBlock())
2639 {
Alexis Hetu6c7ac3c2016-01-12 16:13:37 -05002640 TType copyOfType(baseType.getInterfaceBlock(), EvqTemporary, baseType.getLayoutQualifier(), 0);
Alexis Hetuad6b8752015-06-09 16:15:30 -04002641 indexedExpression->setType(copyOfType);
2642 }
2643 else
2644 {
2645 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
2646 EvqTemporary, static_cast<unsigned char>(baseExpression->getNominalSize()),
2647 static_cast<unsigned char>(baseExpression->getSecondarySize())));
2648 }
2649
2650 if(baseExpression->getType().getQualifier() == EvqConstExpr)
2651 {
2652 indexedExpression->getTypePointer()->setQualifier(EvqConstExpr);
2653 }
2654 }
2655 else if(baseExpression->isMatrix())
2656 {
2657 TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConstExpr ? EvqConstExpr : EvqTemporary;
2658 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
2659 qualifier, static_cast<unsigned char>(baseExpression->getSecondarySize())));
2660 }
2661 else if(baseExpression->isVector())
2662 {
2663 TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConstExpr ? EvqConstExpr : EvqTemporary;
2664 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
2665 }
2666 else
2667 {
2668 indexedExpression->setType(baseExpression->getType());
2669 }
2670
2671 return indexedExpression;
2672}
2673
2674TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc &dotLocation,
2675 const TString &fieldString, const TSourceLoc &fieldLocation)
2676{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002677 TIntermTyped *indexedExpression = nullptr;
Alexis Hetuad6b8752015-06-09 16:15:30 -04002678
2679 if(baseExpression->isArray())
2680 {
2681 error(fieldLocation, "cannot apply dot operator to an array", ".");
2682 recover();
2683 }
2684
2685 if(baseExpression->isVector())
2686 {
2687 TVectorFields fields;
2688 if(!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields, fieldLocation))
2689 {
2690 fields.num = 1;
2691 fields.offsets[0] = 0;
2692 recover();
2693 }
2694
Nicolas Capens0863f0d2016-04-10 00:30:02 -04002695 if(baseExpression->getAsConstantUnion())
Alexis Hetuad6b8752015-06-09 16:15:30 -04002696 {
2697 // constant folding for vector fields
2698 indexedExpression = addConstVectorNode(fields, baseExpression, fieldLocation);
2699 if(indexedExpression == 0)
2700 {
2701 recover();
2702 indexedExpression = baseExpression;
2703 }
2704 else
2705 {
2706 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
2707 EvqConstExpr, (unsigned char)(fieldString).size()));
2708 }
2709 }
2710 else
2711 {
2712 TString vectorString = fieldString;
2713 TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation);
2714 indexedExpression = intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation);
2715 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
Nicolas Capens341afbb2016-04-10 01:54:50 -04002716 baseExpression->getQualifier() == EvqConstExpr ? EvqConstExpr : EvqTemporary, (unsigned char)vectorString.size()));
Alexis Hetuad6b8752015-06-09 16:15:30 -04002717 }
2718 }
2719 else if(baseExpression->isMatrix())
2720 {
2721 TMatrixFields fields;
2722 if(!parseMatrixFields(fieldString, baseExpression->getNominalSize(), baseExpression->getSecondarySize(), fields, fieldLocation))
2723 {
2724 fields.wholeRow = false;
2725 fields.wholeCol = false;
2726 fields.row = 0;
2727 fields.col = 0;
2728 recover();
2729 }
2730
2731 if(fields.wholeRow || fields.wholeCol)
2732 {
2733 error(dotLocation, " non-scalar fields not implemented yet", ".");
2734 recover();
2735 ConstantUnion *unionArray = new ConstantUnion[1];
2736 unionArray->setIConst(0);
2737 TIntermTyped *index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr),
2738 fieldLocation);
2739 indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation);
2740 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
2741 EvqTemporary, static_cast<unsigned char>(baseExpression->getNominalSize()),
2742 static_cast<unsigned char>(baseExpression->getSecondarySize())));
2743 }
2744 else
2745 {
2746 ConstantUnion *unionArray = new ConstantUnion[1];
2747 unionArray->setIConst(fields.col * baseExpression->getSecondarySize() + fields.row);
2748 TIntermTyped *index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr),
2749 fieldLocation);
2750 indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation);
2751 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision()));
2752 }
2753 }
2754 else if(baseExpression->getBasicType() == EbtStruct)
2755 {
2756 bool fieldFound = false;
2757 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
2758 if(fields.empty())
2759 {
2760 error(dotLocation, "structure has no fields", "Internal Error");
2761 recover();
2762 indexedExpression = baseExpression;
2763 }
2764 else
2765 {
2766 unsigned int i;
2767 for(i = 0; i < fields.size(); ++i)
2768 {
2769 if(fields[i]->name() == fieldString)
2770 {
2771 fieldFound = true;
2772 break;
2773 }
2774 }
2775 if(fieldFound)
2776 {
2777 if(baseExpression->getType().getQualifier() == EvqConstExpr)
2778 {
2779 indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
2780 if(indexedExpression == 0)
2781 {
2782 recover();
2783 indexedExpression = baseExpression;
2784 }
2785 else
2786 {
2787 indexedExpression->setType(*fields[i]->type());
2788 // change the qualifier of the return type, not of the structure field
2789 // as the structure definition is shared between various structures.
2790 indexedExpression->getTypePointer()->setQualifier(EvqConstExpr);
2791 }
2792 }
2793 else
2794 {
Alexis Hetuec93b1d2016-12-09 16:01:29 -05002795 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
2796 index->setLine(fieldLocation);
Alexis Hetuad6b8752015-06-09 16:15:30 -04002797 indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index, dotLocation);
2798 indexedExpression->setType(*fields[i]->type());
2799 }
2800 }
2801 else
2802 {
2803 error(dotLocation, " no such field in structure", fieldString.c_str());
2804 recover();
2805 indexedExpression = baseExpression;
2806 }
2807 }
2808 }
2809 else if(baseExpression->isInterfaceBlock())
2810 {
2811 bool fieldFound = false;
2812 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
2813 if(fields.empty())
2814 {
2815 error(dotLocation, "interface block has no fields", "Internal Error");
2816 recover();
2817 indexedExpression = baseExpression;
2818 }
2819 else
2820 {
2821 unsigned int i;
2822 for(i = 0; i < fields.size(); ++i)
2823 {
2824 if(fields[i]->name() == fieldString)
2825 {
2826 fieldFound = true;
2827 break;
2828 }
2829 }
2830 if(fieldFound)
2831 {
2832 ConstantUnion *unionArray = new ConstantUnion[1];
2833 unionArray->setIConst(i);
2834 TIntermTyped *index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
2835 indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
2836 dotLocation);
2837 indexedExpression->setType(*fields[i]->type());
2838 }
2839 else
2840 {
2841 error(dotLocation, " no such field in interface block", fieldString.c_str());
2842 recover();
2843 indexedExpression = baseExpression;
2844 }
2845 }
2846 }
2847 else
2848 {
Alexis Hetu0a655842015-06-22 16:52:11 -04002849 if(mShaderVersion < 300)
Alexis Hetuad6b8752015-06-09 16:15:30 -04002850 {
2851 error(dotLocation, " field selection requires structure, vector, or matrix on left hand side",
2852 fieldString.c_str());
2853 }
2854 else
2855 {
2856 error(dotLocation,
2857 " field selection requires structure, vector, matrix, or interface block on left hand side",
2858 fieldString.c_str());
2859 }
2860 recover();
2861 indexedExpression = baseExpression;
2862 }
2863
2864 return indexedExpression;
2865}
2866
Nicolas Capens7d626792015-02-17 17:58:31 -05002867TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine)
2868{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002869 TLayoutQualifier qualifier;
Nicolas Capens7d626792015-02-17 17:58:31 -05002870
Nicolas Capens0bac2852016-05-07 06:09:58 -04002871 qualifier.location = -1;
Alexis Hetuad6b8752015-06-09 16:15:30 -04002872 qualifier.matrixPacking = EmpUnspecified;
2873 qualifier.blockStorage = EbsUnspecified;
Nicolas Capens7d626792015-02-17 17:58:31 -05002874
Alexis Hetuad6b8752015-06-09 16:15:30 -04002875 if(qualifierType == "shared")
2876 {
2877 qualifier.blockStorage = EbsShared;
2878 }
2879 else if(qualifierType == "packed")
2880 {
2881 qualifier.blockStorage = EbsPacked;
2882 }
2883 else if(qualifierType == "std140")
2884 {
2885 qualifier.blockStorage = EbsStd140;
2886 }
2887 else if(qualifierType == "row_major")
2888 {
2889 qualifier.matrixPacking = EmpRowMajor;
2890 }
2891 else if(qualifierType == "column_major")
2892 {
2893 qualifier.matrixPacking = EmpColumnMajor;
2894 }
2895 else if(qualifierType == "location")
Nicolas Capens0bac2852016-05-07 06:09:58 -04002896 {
2897 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "location requires an argument");
2898 recover();
2899 }
2900 else
2901 {
2902 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
2903 recover();
2904 }
Nicolas Capens7d626792015-02-17 17:58:31 -05002905
Nicolas Capens0bac2852016-05-07 06:09:58 -04002906 return qualifier;
Nicolas Capens7d626792015-02-17 17:58:31 -05002907}
2908
2909TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine)
2910{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002911 TLayoutQualifier qualifier;
Nicolas Capens7d626792015-02-17 17:58:31 -05002912
Nicolas Capens0bac2852016-05-07 06:09:58 -04002913 qualifier.location = -1;
2914 qualifier.matrixPacking = EmpUnspecified;
2915 qualifier.blockStorage = EbsUnspecified;
Nicolas Capens7d626792015-02-17 17:58:31 -05002916
Nicolas Capens0bac2852016-05-07 06:09:58 -04002917 if (qualifierType != "location")
2918 {
2919 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "only location may have arguments");
2920 recover();
2921 }
2922 else
2923 {
2924 // must check that location is non-negative
2925 if (intValue < 0)
2926 {
2927 error(intValueLine, "out of range:", intValueString.c_str(), "location must be non-negative");
2928 recover();
2929 }
2930 else
2931 {
2932 qualifier.location = intValue;
2933 }
2934 }
Nicolas Capens7d626792015-02-17 17:58:31 -05002935
Nicolas Capens0bac2852016-05-07 06:09:58 -04002936 return qualifier;
Nicolas Capens7d626792015-02-17 17:58:31 -05002937}
2938
2939TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier)
2940{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002941 TLayoutQualifier joinedQualifier = leftQualifier;
Nicolas Capens7d626792015-02-17 17:58:31 -05002942
Nicolas Capens0bac2852016-05-07 06:09:58 -04002943 if (rightQualifier.location != -1)
2944 {
2945 joinedQualifier.location = rightQualifier.location;
2946 }
Alexis Hetuad6b8752015-06-09 16:15:30 -04002947 if(rightQualifier.matrixPacking != EmpUnspecified)
2948 {
2949 joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
2950 }
2951 if(rightQualifier.blockStorage != EbsUnspecified)
2952 {
2953 joinedQualifier.blockStorage = rightQualifier.blockStorage;
2954 }
Nicolas Capens7d626792015-02-17 17:58:31 -05002955
Nicolas Capens0bac2852016-05-07 06:09:58 -04002956 return joinedQualifier;
Nicolas Capens7d626792015-02-17 17:58:31 -05002957}
2958
Alexis Hetu55a2cbc2015-04-16 10:49:45 -04002959
2960TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier,
2961 const TSourceLoc &storageLoc, TQualifier storageQualifier)
2962{
2963 TQualifier mergedQualifier = EvqSmoothIn;
2964
Alexis Hetu42ff6b12015-06-03 16:03:48 -04002965 if(storageQualifier == EvqFragmentIn) {
Alexis Hetu55a2cbc2015-04-16 10:49:45 -04002966 if(interpolationQualifier == EvqSmooth)
2967 mergedQualifier = EvqSmoothIn;
2968 else if(interpolationQualifier == EvqFlat)
2969 mergedQualifier = EvqFlatIn;
Nicolas Capens3713cd42015-06-22 10:41:54 -04002970 else UNREACHABLE(interpolationQualifier);
Alexis Hetu55a2cbc2015-04-16 10:49:45 -04002971 }
2972 else if(storageQualifier == EvqCentroidIn) {
2973 if(interpolationQualifier == EvqSmooth)
2974 mergedQualifier = EvqCentroidIn;
2975 else if(interpolationQualifier == EvqFlat)
2976 mergedQualifier = EvqFlatIn;
Nicolas Capens3713cd42015-06-22 10:41:54 -04002977 else UNREACHABLE(interpolationQualifier);
Alexis Hetu55a2cbc2015-04-16 10:49:45 -04002978 }
Alexis Hetu42ff6b12015-06-03 16:03:48 -04002979 else if(storageQualifier == EvqVertexOut) {
Alexis Hetu55a2cbc2015-04-16 10:49:45 -04002980 if(interpolationQualifier == EvqSmooth)
2981 mergedQualifier = EvqSmoothOut;
2982 else if(interpolationQualifier == EvqFlat)
2983 mergedQualifier = EvqFlatOut;
Nicolas Capens3713cd42015-06-22 10:41:54 -04002984 else UNREACHABLE(interpolationQualifier);
Alexis Hetu55a2cbc2015-04-16 10:49:45 -04002985 }
2986 else if(storageQualifier == EvqCentroidOut) {
2987 if(interpolationQualifier == EvqSmooth)
2988 mergedQualifier = EvqCentroidOut;
2989 else if(interpolationQualifier == EvqFlat)
2990 mergedQualifier = EvqFlatOut;
Nicolas Capens3713cd42015-06-22 10:41:54 -04002991 else UNREACHABLE(interpolationQualifier);
Alexis Hetu55a2cbc2015-04-16 10:49:45 -04002992 }
2993 else {
2994 error(interpolationLoc, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getQualifierString(interpolationQualifier));
2995 recover();
2996
2997 mergedQualifier = storageQualifier;
2998 }
2999
3000 TPublicType type;
3001 type.setBasic(EbtVoid, mergedQualifier, storageLoc);
3002 return type;
3003}
3004
Alexis Hetuad6b8752015-06-09 16:15:30 -04003005TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList)
3006{
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04003007 if(voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type))
Alexis Hetuad6b8752015-06-09 16:15:30 -04003008 {
3009 recover();
3010 }
3011
3012 for(unsigned int i = 0; i < fieldList->size(); ++i)
3013 {
3014 //
3015 // Careful not to replace already known aspects of type, like array-ness
3016 //
3017 TType *type = (*fieldList)[i]->type();
3018 type->setBasicType(typeSpecifier.type);
3019 type->setNominalSize(typeSpecifier.primarySize);
3020 type->setSecondarySize(typeSpecifier.secondarySize);
3021 type->setPrecision(typeSpecifier.precision);
3022 type->setQualifier(typeSpecifier.qualifier);
3023 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
3024
3025 // don't allow arrays of arrays
3026 if(type->isArray())
3027 {
3028 if(arrayTypeErrorCheck(typeSpecifier.line, typeSpecifier))
3029 recover();
3030 }
3031 if(typeSpecifier.array)
3032 type->setArraySize(typeSpecifier.arraySize);
3033 if(typeSpecifier.userDef)
3034 {
3035 type->setStruct(typeSpecifier.userDef->getStruct());
3036 }
3037
3038 if(structNestingErrorCheck(typeSpecifier.line, *(*fieldList)[i]))
3039 {
3040 recover();
3041 }
3042 }
3043
3044 return fieldList;
3045}
3046
3047TPublicType TParseContext::addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine,
3048 const TString *structName, TFieldList *fieldList)
3049{
3050 TStructure *structure = new TStructure(structName, fieldList);
3051 TType *structureType = new TType(structure);
3052
3053 // Store a bool in the struct if we're at global scope, to allow us to
3054 // skip the local struct scoping workaround in HLSL.
3055 structure->setUniqueId(TSymbolTableLevel::nextUniqueId());
3056 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
3057
3058 if(!structName->empty())
3059 {
3060 if(reservedErrorCheck(nameLine, *structName))
3061 {
3062 recover();
3063 }
3064 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3065 if(!symbolTable.declare(*userTypeDef))
3066 {
3067 error(nameLine, "redefinition", structName->c_str(), "struct");
3068 recover();
3069 }
3070 }
3071
3072 // ensure we do not specify any storage qualifiers on the struct members
3073 for(unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
3074 {
3075 const TField &field = *(*fieldList)[typeListIndex];
3076 const TQualifier qualifier = field.type()->getQualifier();
3077 switch(qualifier)
3078 {
3079 case EvqGlobal:
3080 case EvqTemporary:
3081 break;
3082 default:
3083 error(field.line(), "invalid qualifier on struct member", getQualifierString(qualifier));
3084 recover();
3085 break;
3086 }
3087 }
3088
3089 TPublicType publicType;
3090 publicType.setBasic(EbtStruct, EvqTemporary, structLine);
3091 publicType.userDef = structureType;
3092 exitStructDeclaration();
3093
3094 return publicType;
3095}
3096
Alexis Hetufe1269e2015-06-16 12:43:32 -04003097bool TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString& identifier)
John Bauman66b8ab22014-05-06 15:57:45 -04003098{
Nicolas Capens0bac2852016-05-07 06:09:58 -04003099 ++mStructNestingLevel;
John Bauman66b8ab22014-05-06 15:57:45 -04003100
Nicolas Capens0bac2852016-05-07 06:09:58 -04003101 // Embedded structure definitions are not supported per GLSL ES spec.
3102 // They aren't allowed in GLSL either, but we need to detect this here
3103 // so we don't rely on the GLSL compiler to catch it.
3104 if (mStructNestingLevel > 1) {
3105 error(line, "", "Embedded struct definitions are not allowed");
3106 return true;
3107 }
John Bauman66b8ab22014-05-06 15:57:45 -04003108
Nicolas Capens0bac2852016-05-07 06:09:58 -04003109 return false;
John Bauman66b8ab22014-05-06 15:57:45 -04003110}
3111
3112void TParseContext::exitStructDeclaration()
3113{
Nicolas Capens0bac2852016-05-07 06:09:58 -04003114 --mStructNestingLevel;
John Bauman66b8ab22014-05-06 15:57:45 -04003115}
3116
Alexis Hetuad6b8752015-06-09 16:15:30 -04003117bool TParseContext::structNestingErrorCheck(const TSourceLoc &line, const TField &field)
3118{
3119 static const int kWebGLMaxStructNesting = 4;
3120
3121 if(field.type()->getBasicType() != EbtStruct)
3122 {
3123 return false;
3124 }
3125
3126 // We're already inside a structure definition at this point, so add
3127 // one to the field's struct nesting.
3128 if(1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
3129 {
3130 std::stringstream reasonStream;
3131 reasonStream << "Reference of struct type "
3132 << field.type()->getStruct()->name().c_str()
3133 << " exceeds maximum allowed nesting level of "
3134 << kWebGLMaxStructNesting;
3135 std::string reason = reasonStream.str();
3136 error(line, reason.c_str(), field.name().c_str(), "");
3137 return true;
3138 }
3139
3140 return false;
3141}
3142
3143TIntermTyped *TParseContext::createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc, const TType *funcReturnType)
3144{
3145 if(child == nullptr)
3146 {
3147 return nullptr;
3148 }
3149
3150 switch(op)
3151 {
3152 case EOpLogicalNot:
3153 if(child->getBasicType() != EbtBool ||
3154 child->isMatrix() ||
3155 child->isArray() ||
3156 child->isVector())
3157 {
3158 return nullptr;
3159 }
3160 break;
3161 case EOpBitwiseNot:
3162 if((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3163 child->isMatrix() ||
3164 child->isArray())
3165 {
3166 return nullptr;
3167 }
3168 break;
3169 case EOpPostIncrement:
3170 case EOpPreIncrement:
3171 case EOpPostDecrement:
3172 case EOpPreDecrement:
3173 case EOpNegative:
3174 if(child->getBasicType() == EbtStruct ||
3175 child->getBasicType() == EbtBool ||
3176 child->isArray())
3177 {
3178 return nullptr;
3179 }
3180 // Operators for built-ins are already type checked against their prototype.
3181 default:
3182 break;
3183 }
3184
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -04003185 return intermediate.addUnaryMath(op, child, loc, funcReturnType);
Alexis Hetuad6b8752015-06-09 16:15:30 -04003186}
3187
3188TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3189{
3190 TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
3191 if(node == nullptr)
3192 {
3193 unaryOpError(loc, getOperatorString(op), child->getCompleteString());
3194 recover();
3195 return child;
3196 }
3197 return node;
3198}
3199
3200TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3201{
3202 if(lValueErrorCheck(loc, getOperatorString(op), child))
3203 recover();
3204 return addUnaryMath(op, child, loc);
3205}
3206
3207bool TParseContext::binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
3208{
3209 if(left->isArray() || right->isArray())
3210 {
Alexis Hetu0a655842015-06-22 16:52:11 -04003211 if(mShaderVersion < 300)
Alexis Hetuad6b8752015-06-09 16:15:30 -04003212 {
3213 error(loc, "Invalid operation for arrays", getOperatorString(op));
3214 return false;
3215 }
3216
3217 if(left->isArray() != right->isArray())
3218 {
3219 error(loc, "array / non-array mismatch", getOperatorString(op));
3220 return false;
3221 }
3222
3223 switch(op)
3224 {
3225 case EOpEqual:
3226 case EOpNotEqual:
3227 case EOpAssign:
3228 case EOpInitialize:
3229 break;
3230 default:
3231 error(loc, "Invalid operation for arrays", getOperatorString(op));
3232 return false;
3233 }
3234 // At this point, size of implicitly sized arrays should be resolved.
3235 if(left->getArraySize() != right->getArraySize())
3236 {
3237 error(loc, "array size mismatch", getOperatorString(op));
3238 return false;
3239 }
3240 }
3241
3242 // Check ops which require integer / ivec parameters
3243 bool isBitShift = false;
3244 switch(op)
3245 {
3246 case EOpBitShiftLeft:
3247 case EOpBitShiftRight:
3248 case EOpBitShiftLeftAssign:
3249 case EOpBitShiftRightAssign:
3250 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3251 // check that the basic type is an integer type.
3252 isBitShift = true;
3253 if(!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3254 {
3255 return false;
3256 }
3257 break;
3258 case EOpBitwiseAnd:
3259 case EOpBitwiseXor:
3260 case EOpBitwiseOr:
3261 case EOpBitwiseAndAssign:
3262 case EOpBitwiseXorAssign:
3263 case EOpBitwiseOrAssign:
3264 // It is enough to check the type of only one operand, since later it
3265 // is checked that the operand types match.
3266 if(!IsInteger(left->getBasicType()))
3267 {
3268 return false;
3269 }
3270 break;
3271 default:
3272 break;
3273 }
3274
3275 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3276 // So the basic type should usually match.
3277 if(!isBitShift && left->getBasicType() != right->getBasicType())
3278 {
3279 return false;
3280 }
3281
3282 // Check that type sizes match exactly on ops that require that.
3283 // Also check restrictions for structs that contain arrays or samplers.
3284 switch(op)
3285 {
3286 case EOpAssign:
3287 case EOpInitialize:
3288 case EOpEqual:
3289 case EOpNotEqual:
3290 // ESSL 1.00 sections 5.7, 5.8, 5.9
Alexis Hetu0a655842015-06-22 16:52:11 -04003291 if(mShaderVersion < 300 && left->getType().isStructureContainingArrays())
Alexis Hetuad6b8752015-06-09 16:15:30 -04003292 {
3293 error(loc, "undefined operation for structs containing arrays", getOperatorString(op));
3294 return false;
3295 }
3296 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3297 // we interpret the spec so that this extends to structs containing samplers,
3298 // similarly to ESSL 1.00 spec.
Alexis Hetu0a655842015-06-22 16:52:11 -04003299 if((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
Alexis Hetuad6b8752015-06-09 16:15:30 -04003300 left->getType().isStructureContainingSamplers())
3301 {
3302 error(loc, "undefined operation for structs containing samplers", getOperatorString(op));
3303 return false;
3304 }
3305 case EOpLessThan:
3306 case EOpGreaterThan:
3307 case EOpLessThanEqual:
3308 case EOpGreaterThanEqual:
3309 if((left->getNominalSize() != right->getNominalSize()) ||
3310 (left->getSecondarySize() != right->getSecondarySize()))
3311 {
3312 return false;
3313 }
Alexis Hetuec93b1d2016-12-09 16:01:29 -05003314 break;
3315 case EOpAdd:
3316 case EOpSub:
3317 case EOpDiv:
3318 case EOpIMod:
3319 case EOpBitShiftLeft:
3320 case EOpBitShiftRight:
3321 case EOpBitwiseAnd:
3322 case EOpBitwiseXor:
3323 case EOpBitwiseOr:
3324 case EOpAddAssign:
3325 case EOpSubAssign:
3326 case EOpDivAssign:
3327 case EOpIModAssign:
3328 case EOpBitShiftLeftAssign:
3329 case EOpBitShiftRightAssign:
3330 case EOpBitwiseAndAssign:
3331 case EOpBitwiseXorAssign:
3332 case EOpBitwiseOrAssign:
3333 if((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
3334 {
3335 return false;
3336 }
3337
3338 // Are the sizes compatible?
3339 if(left->getNominalSize() != right->getNominalSize() || left->getSecondarySize() != right->getSecondarySize())
3340 {
3341 // If the nominal sizes of operands do not match:
3342 // One of them must be a scalar.
3343 if(!left->isScalar() && !right->isScalar())
3344 return false;
3345
3346 // In the case of compound assignment other than multiply-assign,
3347 // the right side needs to be a scalar. Otherwise a vector/matrix
3348 // would be assigned to a scalar. A scalar can't be shifted by a
3349 // vector either.
3350 if(!right->isScalar() && (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
3351 return false;
3352 }
3353 break;
Alexis Hetuad6b8752015-06-09 16:15:30 -04003354 default:
3355 break;
3356 }
3357
3358 return true;
3359}
3360
Alexis Hetu76a343a2015-06-04 17:21:22 -04003361TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc)
3362{
3363 TBasicType switchType = init->getBasicType();
3364 if((switchType != EbtInt && switchType != EbtUInt) ||
3365 init->isMatrix() ||
3366 init->isArray() ||
3367 init->isVector())
3368 {
3369 error(init->getLine(), "init-expression in a switch statement must be a scalar integer", "switch");
3370 recover();
3371 return nullptr;
3372 }
3373
3374 if(statementList)
3375 {
3376 if(!ValidateSwitch::validate(switchType, this, statementList, loc))
3377 {
3378 recover();
3379 return nullptr;
3380 }
3381 }
3382
3383 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3384 if(node == nullptr)
3385 {
3386 error(loc, "erroneous switch statement", "switch");
3387 recover();
3388 return nullptr;
3389 }
3390 return node;
3391}
3392
3393TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3394{
Alexis Hetu0a655842015-06-22 16:52:11 -04003395 if(mSwitchNestingLevel == 0)
Alexis Hetu76a343a2015-06-04 17:21:22 -04003396 {
3397 error(loc, "case labels need to be inside switch statements", "case");
3398 recover();
3399 return nullptr;
3400 }
3401 if(condition == nullptr)
3402 {
3403 error(loc, "case label must have a condition", "case");
3404 recover();
3405 return nullptr;
3406 }
3407 if((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
3408 condition->isMatrix() ||
3409 condition->isArray() ||
3410 condition->isVector())
3411 {
3412 error(condition->getLine(), "case label must be a scalar integer", "case");
3413 recover();
3414 }
3415 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
3416 if(conditionConst == nullptr)
3417 {
3418 error(condition->getLine(), "case label must be constant", "case");
3419 recover();
3420 }
3421 TIntermCase *node = intermediate.addCase(condition, loc);
3422 if(node == nullptr)
3423 {
3424 error(loc, "erroneous case statement", "case");
3425 recover();
3426 return nullptr;
3427 }
3428 return node;
3429}
3430
3431TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3432{
Alexis Hetu0a655842015-06-22 16:52:11 -04003433 if(mSwitchNestingLevel == 0)
Alexis Hetu76a343a2015-06-04 17:21:22 -04003434 {
3435 error(loc, "default labels need to be inside switch statements", "default");
3436 recover();
3437 return nullptr;
3438 }
3439 TIntermCase *node = intermediate.addCase(nullptr, loc);
3440 if(node == nullptr)
3441 {
3442 error(loc, "erroneous default statement", "default");
3443 recover();
3444 return nullptr;
3445 }
3446 return node;
3447}
Alexis Hetue5246692015-06-18 12:34:52 -04003448TIntermTyped *TParseContext::createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
3449{
3450 if(binaryOpCommonCheck(op, left, right, loc))
3451 {
3452 return intermediate.addAssign(op, left, right, loc);
3453 }
3454 return nullptr;
3455}
3456
3457TIntermTyped *TParseContext::addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
3458{
3459 TIntermTyped *node = createAssign(op, left, right, loc);
3460 if(node == nullptr)
3461 {
3462 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
3463 recover();
3464 return left;
3465 }
3466 return node;
3467}
Alexis Hetu76a343a2015-06-04 17:21:22 -04003468
Alexis Hetub4769582015-06-16 12:19:50 -04003469TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right,
3470 const TSourceLoc &loc)
3471{
3472 if(!binaryOpCommonCheck(op, left, right, loc))
3473 return nullptr;
3474
3475 switch(op)
3476 {
3477 case EOpEqual:
3478 case EOpNotEqual:
3479 break;
3480 case EOpLessThan:
3481 case EOpGreaterThan:
3482 case EOpLessThanEqual:
3483 case EOpGreaterThanEqual:
3484 ASSERT(!left->isArray() && !right->isArray());
3485 if(left->isMatrix() || left->isVector() ||
3486 left->getBasicType() == EbtStruct)
3487 {
3488 return nullptr;
3489 }
3490 break;
3491 case EOpLogicalOr:
3492 case EOpLogicalXor:
3493 case EOpLogicalAnd:
3494 ASSERT(!left->isArray() && !right->isArray());
3495 if(left->getBasicType() != EbtBool ||
3496 left->isMatrix() || left->isVector())
3497 {
3498 return nullptr;
3499 }
3500 break;
3501 case EOpAdd:
3502 case EOpSub:
3503 case EOpDiv:
3504 case EOpMul:
3505 ASSERT(!left->isArray() && !right->isArray());
3506 if(left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
3507 {
3508 return nullptr;
3509 }
3510 break;
3511 case EOpIMod:
3512 ASSERT(!left->isArray() && !right->isArray());
3513 // Note that this is only for the % operator, not for mod()
3514 if(left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
3515 {
3516 return nullptr;
3517 }
3518 break;
3519 // Note that for bitwise ops, type checking is done in promote() to
3520 // share code between ops and compound assignment
3521 default:
3522 break;
3523 }
3524
3525 return intermediate.addBinaryMath(op, left, right, loc);
3526}
3527
3528TIntermTyped *TParseContext::addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
3529{
3530 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
3531 if(node == 0)
3532 {
3533 binaryOpError(loc, getOperatorString(op), left->getCompleteString(), right->getCompleteString());
3534 recover();
3535 return left;
3536 }
3537 return node;
3538}
3539
3540TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
3541{
3542 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
3543 if(node == 0)
3544 {
3545 binaryOpError(loc, getOperatorString(op), left->getCompleteString(), right->getCompleteString());
3546 recover();
3547 ConstantUnion *unionArray = new ConstantUnion[1];
3548 unionArray->setBConst(false);
3549 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConstExpr), loc);
3550 }
3551 return node;
3552}
3553
Alexis Hetu76a343a2015-06-04 17:21:22 -04003554TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
3555{
3556 switch(op)
3557 {
3558 case EOpContinue:
Alexis Hetu0a655842015-06-22 16:52:11 -04003559 if(mLoopNestingLevel <= 0)
Alexis Hetu76a343a2015-06-04 17:21:22 -04003560 {
3561 error(loc, "continue statement only allowed in loops", "");
3562 recover();
3563 }
3564 break;
3565 case EOpBreak:
Alexis Hetu0a655842015-06-22 16:52:11 -04003566 if(mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
Alexis Hetu76a343a2015-06-04 17:21:22 -04003567 {
3568 error(loc, "break statement only allowed in loops and switch statements", "");
3569 recover();
3570 }
3571 break;
3572 case EOpReturn:
Alexis Hetu0a655842015-06-22 16:52:11 -04003573 if(mCurrentFunctionType->getBasicType() != EbtVoid)
Alexis Hetu76a343a2015-06-04 17:21:22 -04003574 {
3575 error(loc, "non-void function must return a value", "return");
3576 recover();
3577 }
3578 break;
3579 default:
3580 // No checks for discard
3581 break;
3582 }
3583 return intermediate.addBranch(op, loc);
3584}
3585
3586TIntermBranch *TParseContext::addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc)
3587{
3588 ASSERT(op == EOpReturn);
Alexis Hetu0a655842015-06-22 16:52:11 -04003589 mFunctionReturnsValue = true;
3590 if(mCurrentFunctionType->getBasicType() == EbtVoid)
Alexis Hetu76a343a2015-06-04 17:21:22 -04003591 {
3592 error(loc, "void function cannot return a value", "return");
3593 recover();
3594 }
Alexis Hetu0a655842015-06-22 16:52:11 -04003595 else if(*mCurrentFunctionType != returnValue->getType())
Alexis Hetu76a343a2015-06-04 17:21:22 -04003596 {
3597 error(loc, "function return is not matching type:", "return");
3598 recover();
3599 }
3600 return intermediate.addBranch(op, returnValue, loc);
3601}
3602
Alexis Hetub3ff42c2015-07-03 18:19:57 -04003603TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *paramNode, TIntermNode *thisNode, const TSourceLoc &loc, bool *fatalError)
3604{
3605 *fatalError = false;
3606 TOperator op = fnCall->getBuiltInOp();
3607 TIntermTyped *callNode = nullptr;
3608
3609 if(thisNode != nullptr)
3610 {
3611 ConstantUnion *unionArray = new ConstantUnion[1];
3612 int arraySize = 0;
3613 TIntermTyped *typedThis = thisNode->getAsTyped();
3614 if(fnCall->getName() != "length")
3615 {
3616 error(loc, "invalid method", fnCall->getName().c_str());
3617 recover();
3618 }
3619 else if(paramNode != nullptr)
3620 {
3621 error(loc, "method takes no parameters", "length");
3622 recover();
3623 }
3624 else if(typedThis == nullptr || !typedThis->isArray())
3625 {
3626 error(loc, "length can only be called on arrays", "length");
3627 recover();
3628 }
3629 else
3630 {
3631 arraySize = typedThis->getArraySize();
3632 if(typedThis->getAsSymbolNode() == nullptr)
3633 {
3634 // This code path can be hit with expressions like these:
3635 // (a = b).length()
3636 // (func()).length()
3637 // (int[3](0, 1, 2)).length()
3638 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid expression.
3639 // It allows "An array name with the length method applied" in contrast to GLSL 4.4 spec section 5.9
3640 // which allows "An array, vector or matrix expression with the length method applied".
3641 error(loc, "length can only be called on array names, not on array expressions", "length");
3642 recover();
3643 }
3644 }
3645 unionArray->setIConst(arraySize);
3646 callNode = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), loc);
3647 }
3648 else if(op != EOpNull)
3649 {
3650 //
3651 // Then this should be a constructor.
3652 // Don't go through the symbol table for constructors.
3653 // Their parameters will be verified algorithmically.
3654 //
3655 TType type(EbtVoid, EbpUndefined); // use this to get the type back
3656 if(!constructorErrorCheck(loc, paramNode, *fnCall, op, &type))
3657 {
3658 //
3659 // It's a constructor, of type 'type'.
3660 //
3661 callNode = addConstructor(paramNode, &type, op, fnCall, loc);
3662 }
3663
3664 if(callNode == nullptr)
3665 {
3666 recover();
3667 callNode = intermediate.setAggregateOperator(nullptr, op, loc);
3668 }
Alexis Hetub3ff42c2015-07-03 18:19:57 -04003669 }
3670 else
3671 {
3672 //
3673 // Not a constructor. Find it in the symbol table.
3674 //
3675 const TFunction *fnCandidate;
3676 bool builtIn;
3677 fnCandidate = findFunction(loc, fnCall, &builtIn);
3678 if(fnCandidate)
3679 {
3680 //
3681 // A declared function.
3682 //
3683 if(builtIn && !fnCandidate->getExtension().empty() &&
3684 extensionErrorCheck(loc, fnCandidate->getExtension()))
3685 {
3686 recover();
3687 }
3688 op = fnCandidate->getBuiltInOp();
3689 if(builtIn && op != EOpNull)
3690 {
3691 //
3692 // A function call mapped to a built-in operation.
3693 //
3694 if(fnCandidate->getParamCount() == 1)
3695 {
3696 //
3697 // Treat it like a built-in unary operator.
3698 //
3699 callNode = createUnaryMath(op, paramNode->getAsTyped(), loc, &fnCandidate->getReturnType());
3700 if(callNode == nullptr)
3701 {
3702 std::stringstream extraInfoStream;
3703 extraInfoStream << "built in unary operator function. Type: "
3704 << static_cast<TIntermTyped*>(paramNode)->getCompleteString();
3705 std::string extraInfo = extraInfoStream.str();
3706 error(paramNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
3707 *fatalError = true;
3708 return nullptr;
3709 }
3710 }
3711 else
3712 {
3713 TIntermAggregate *aggregate = intermediate.setAggregateOperator(paramNode, op, loc);
3714 aggregate->setType(fnCandidate->getReturnType());
3715
3716 // Some built-in functions have out parameters too.
3717 functionCallLValueErrorCheck(fnCandidate, aggregate);
3718
3719 callNode = aggregate;
Nicolas Capens91dfb972016-04-09 23:45:12 -04003720
3721 if(fnCandidate->getParamCount() == 2)
3722 {
3723 TIntermSequence &parameters = paramNode->getAsAggregate()->getSequence();
3724 TIntermTyped *left = parameters[0]->getAsTyped();
3725 TIntermTyped *right = parameters[1]->getAsTyped();
3726
3727 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
3728 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
3729 if (leftTempConstant && rightTempConstant)
3730 {
3731 TIntermTyped *typedReturnNode = leftTempConstant->fold(op, rightTempConstant, infoSink());
3732
3733 if(typedReturnNode)
3734 {
3735 callNode = typedReturnNode;
3736 }
3737 }
3738 }
Alexis Hetub3ff42c2015-07-03 18:19:57 -04003739 }
3740 }
3741 else
3742 {
3743 // This is a real function call
3744
3745 TIntermAggregate *aggregate = intermediate.setAggregateOperator(paramNode, EOpFunctionCall, loc);
3746 aggregate->setType(fnCandidate->getReturnType());
3747
3748 // this is how we know whether the given function is a builtIn function or a user defined function
3749 // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
3750 // if builtIn == true, it's definitely a builtIn function with EOpNull
3751 if(!builtIn)
3752 aggregate->setUserDefined();
3753 aggregate->setName(fnCandidate->getMangledName());
3754
3755 callNode = aggregate;
3756
3757 functionCallLValueErrorCheck(fnCandidate, aggregate);
3758 }
Alexis Hetub3ff42c2015-07-03 18:19:57 -04003759 }
3760 else
3761 {
3762 // error message was put out by findFunction()
3763 // Put on a dummy node for error recovery
3764 ConstantUnion *unionArray = new ConstantUnion[1];
3765 unionArray->setFConst(0.0f);
3766 callNode = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConstExpr), loc);
3767 recover();
3768 }
3769 }
3770 delete fnCall;
3771 return callNode;
3772}
3773
Alexis Hetueee212e2015-07-07 17:13:30 -04003774TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &loc)
3775{
3776 if(boolErrorCheck(loc, cond))
3777 recover();
3778
3779 if(trueBlock->getType() != falseBlock->getType())
3780 {
3781 binaryOpError(loc, ":", trueBlock->getCompleteString(), falseBlock->getCompleteString());
3782 recover();
3783 return falseBlock;
3784 }
3785 // ESSL1 sections 5.2 and 5.7:
3786 // ESSL3 section 5.7:
3787 // Ternary operator is not among the operators allowed for structures/arrays.
3788 if(trueBlock->isArray() || trueBlock->getBasicType() == EbtStruct)
3789 {
3790 error(loc, "ternary operator is not allowed for structures or arrays", ":");
3791 recover();
3792 return falseBlock;
3793 }
3794 return intermediate.addSelection(cond, trueBlock, falseBlock, loc);
3795}
3796
John Bauman66b8ab22014-05-06 15:57:45 -04003797//
3798// Parse an array of strings using yyparse.
3799//
3800// Returns 0 for success.
3801//
3802int PaParseStrings(int count, const char* const string[], const int length[],
Nicolas Capens0bac2852016-05-07 06:09:58 -04003803 TParseContext* context) {
3804 if ((count == 0) || !string)
3805 return 1;
John Bauman66b8ab22014-05-06 15:57:45 -04003806
Nicolas Capens0bac2852016-05-07 06:09:58 -04003807 if (glslang_initialize(context))
3808 return 1;
John Bauman66b8ab22014-05-06 15:57:45 -04003809
Nicolas Capens0bac2852016-05-07 06:09:58 -04003810 int error = glslang_scan(count, string, length, context);
3811 if (!error)
3812 error = glslang_parse(context);
John Bauman66b8ab22014-05-06 15:57:45 -04003813
Nicolas Capens0bac2852016-05-07 06:09:58 -04003814 glslang_finalize(context);
John Bauman66b8ab22014-05-06 15:57:45 -04003815
Nicolas Capens0bac2852016-05-07 06:09:58 -04003816 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
John Bauman66b8ab22014-05-06 15:57:45 -04003817}
3818
3819
3820