blob: 7cca42c431888151f136db62b98b2fd294ad0951 [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;
Alexis Hetu877ddfc2017-07-25 17:48:00 -0400409 case EvqVertexID: message = "can't modify gl_VertexID"; break;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400410 default:
John Bauman66b8ab22014-05-06 15:57:45 -0400411
Nicolas Capens0bac2852016-05-07 06:09:58 -0400412 //
413 // Type that can't be written to?
414 //
415 if(IsSampler(node->getBasicType()))
416 {
417 message = "can't modify a sampler";
418 }
419 else if(node->getBasicType() == EbtVoid)
420 {
421 message = "can't modify void";
422 }
423 }
John Bauman66b8ab22014-05-06 15:57:45 -0400424
Nicolas Capens0bac2852016-05-07 06:09:58 -0400425 if (message == 0 && binaryNode == 0 && symNode == 0) {
426 error(line, " l-value required", op);
John Bauman66b8ab22014-05-06 15:57:45 -0400427
Nicolas Capens0bac2852016-05-07 06:09:58 -0400428 return true;
429 }
John Bauman66b8ab22014-05-06 15:57:45 -0400430
431
Nicolas Capens0bac2852016-05-07 06:09:58 -0400432 //
433 // Everything else is okay, no error.
434 //
435 if (message == 0)
436 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400437
Nicolas Capens0bac2852016-05-07 06:09:58 -0400438 //
439 // If we get here, we have an error and a message.
440 //
441 if (symNode) {
442 std::stringstream extraInfoStream;
443 extraInfoStream << "\"" << symbol << "\" (" << message << ")";
444 std::string extraInfo = extraInfoStream.str();
445 error(line, " l-value required", op, extraInfo.c_str());
446 }
447 else {
448 std::stringstream extraInfoStream;
449 extraInfoStream << "(" << message << ")";
450 std::string extraInfo = extraInfoStream.str();
451 error(line, " l-value required", op, extraInfo.c_str());
452 }
John Bauman66b8ab22014-05-06 15:57:45 -0400453
Nicolas Capens0bac2852016-05-07 06:09:58 -0400454 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400455}
456
457//
458// Both test, and if necessary spit out an error, to see if the node is really
459// a constant.
460//
461// Returns true if the was an error.
462//
463bool TParseContext::constErrorCheck(TIntermTyped* node)
464{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400465 if (node->getQualifier() == EvqConstExpr)
466 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400467
Nicolas Capens0bac2852016-05-07 06:09:58 -0400468 error(node->getLine(), "constant expression required", "");
John Bauman66b8ab22014-05-06 15:57:45 -0400469
Nicolas Capens0bac2852016-05-07 06:09:58 -0400470 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400471}
472
473//
474// Both test, and if necessary spit out an error, to see if the node is really
475// an integer.
476//
477// Returns true if the was an error.
478//
479bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
480{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400481 if (node->isScalarInt())
482 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400483
Nicolas Capens0bac2852016-05-07 06:09:58 -0400484 error(node->getLine(), "integer expression required", token);
John Bauman66b8ab22014-05-06 15:57:45 -0400485
Nicolas Capens0bac2852016-05-07 06:09:58 -0400486 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400487}
488
489//
490// Both test, and if necessary spit out an error, to see if we are currently
491// globally scoped.
492//
493// Returns true if the was an error.
494//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400495bool TParseContext::globalErrorCheck(const TSourceLoc &line, bool global, const char* token)
John Bauman66b8ab22014-05-06 15:57:45 -0400496{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400497 if (global)
498 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400499
Nicolas Capens0bac2852016-05-07 06:09:58 -0400500 error(line, "only allowed at global scope", token);
John Bauman66b8ab22014-05-06 15:57:45 -0400501
Nicolas Capens0bac2852016-05-07 06:09:58 -0400502 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400503}
504
505//
506// For now, keep it simple: if it starts "gl_", it's reserved, independent
507// of scope. Except, if the symbol table is at the built-in push-level,
508// which is when we are parsing built-ins.
509// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
510// webgl shader.
511//
512// Returns true if there was an error.
513//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400514bool TParseContext::reservedErrorCheck(const TSourceLoc &line, const TString& identifier)
John Bauman66b8ab22014-05-06 15:57:45 -0400515{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400516 static const char* reservedErrMsg = "reserved built-in name";
517 if (!symbolTable.atBuiltInLevel()) {
518 if (identifier.compare(0, 3, "gl_") == 0) {
519 error(line, reservedErrMsg, "gl_");
520 return true;
521 }
522 if (identifier.find("__") != TString::npos) {
523 error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str());
524 return true;
525 }
526 }
John Bauman66b8ab22014-05-06 15:57:45 -0400527
Nicolas Capens0bac2852016-05-07 06:09:58 -0400528 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400529}
530
531//
532// Make sure there is enough data provided to the constructor to build
533// something of the type of the constructor. Also returns the type of
534// the constructor.
535//
536// Returns true if there was an error in construction.
537//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400538bool TParseContext::constructorErrorCheck(const TSourceLoc &line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
John Bauman66b8ab22014-05-06 15:57:45 -0400539{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400540 *type = function.getReturnType();
John Bauman66b8ab22014-05-06 15:57:45 -0400541
Nicolas Capens0bac2852016-05-07 06:09:58 -0400542 bool constructingMatrix = false;
543 switch(op) {
544 case EOpConstructMat2:
545 case EOpConstructMat2x3:
546 case EOpConstructMat2x4:
547 case EOpConstructMat3x2:
548 case EOpConstructMat3:
549 case EOpConstructMat3x4:
550 case EOpConstructMat4x2:
551 case EOpConstructMat4x3:
552 case EOpConstructMat4:
553 constructingMatrix = true;
554 break;
555 default:
556 break;
557 }
John Bauman66b8ab22014-05-06 15:57:45 -0400558
Nicolas Capens0bac2852016-05-07 06:09:58 -0400559 //
560 // Note: It's okay to have too many components available, but not okay to have unused
561 // arguments. 'full' will go to true when enough args have been seen. If we loop
562 // again, there is an extra argument, so 'overfull' will become true.
563 //
John Bauman66b8ab22014-05-06 15:57:45 -0400564
Nicolas Capens0bac2852016-05-07 06:09:58 -0400565 size_t size = 0;
566 bool full = false;
567 bool overFull = false;
568 bool matrixInMatrix = false;
569 bool arrayArg = false;
570 for (size_t i = 0; i < function.getParamCount(); ++i) {
571 const TParameter& param = function.getParam(i);
572 size += param.type->getObjectSize();
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400573
Nicolas Capens0bac2852016-05-07 06:09:58 -0400574 if (constructingMatrix && param.type->isMatrix())
575 matrixInMatrix = true;
576 if (full)
577 overFull = true;
578 if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
579 full = true;
580 if (param.type->isArray())
581 arrayArg = true;
582 }
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400583
Nicolas Capens0bac2852016-05-07 06:09:58 -0400584 if(type->isArray()) {
585 if(type->getArraySize() == 0) {
586 type->setArraySize(function.getParamCount());
587 } else if(type->getArraySize() != (int)function.getParamCount()) {
588 error(line, "array constructor needs one argument per array element", "constructor");
589 return true;
590 }
591 }
John Bauman66b8ab22014-05-06 15:57:45 -0400592
Nicolas Capens0bac2852016-05-07 06:09:58 -0400593 if (arrayArg && op != EOpConstructStruct) {
594 error(line, "constructing from a non-dereferenced array", "constructor");
595 return true;
596 }
John Bauman66b8ab22014-05-06 15:57:45 -0400597
Nicolas Capens0bac2852016-05-07 06:09:58 -0400598 if (matrixInMatrix && !type->isArray()) {
599 if (function.getParamCount() != 1) {
600 error(line, "constructing matrix from matrix can only take one argument", "constructor");
601 return true;
602 }
603 }
John Bauman66b8ab22014-05-06 15:57:45 -0400604
Nicolas Capens0bac2852016-05-07 06:09:58 -0400605 if (overFull) {
606 error(line, "too many arguments", "constructor");
607 return true;
608 }
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400609
Nicolas Capens0bac2852016-05-07 06:09:58 -0400610 if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->fields().size() != function.getParamCount()) {
611 error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
612 return true;
613 }
John Bauman66b8ab22014-05-06 15:57:45 -0400614
Nicolas Capens0bac2852016-05-07 06:09:58 -0400615 if (!type->isMatrix() || !matrixInMatrix) {
616 if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
617 (op == EOpConstructStruct && size < type->getObjectSize())) {
618 error(line, "not enough data provided for construction", "constructor");
619 return true;
620 }
621 }
John Bauman66b8ab22014-05-06 15:57:45 -0400622
Nicolas Capens0bac2852016-05-07 06:09:58 -0400623 TIntermTyped *typed = node ? node->getAsTyped() : 0;
624 if (typed == 0) {
625 error(line, "constructor argument does not have a type", "constructor");
626 return true;
627 }
628 if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
629 error(line, "cannot convert a sampler", "constructor");
630 return true;
631 }
632 if (typed->getBasicType() == EbtVoid) {
633 error(line, "cannot convert a void", "constructor");
634 return true;
635 }
John Bauman66b8ab22014-05-06 15:57:45 -0400636
Nicolas Capens0bac2852016-05-07 06:09:58 -0400637 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400638}
639
640// This function checks to see if a void variable has been declared and raise an error message for such a case
641//
642// returns true in case of an error
643//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400644bool TParseContext::voidErrorCheck(const TSourceLoc &line, const TString& identifier, const TBasicType& type)
John Bauman66b8ab22014-05-06 15:57:45 -0400645{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400646 if(type == EbtVoid) {
647 error(line, "illegal use of type 'void'", identifier.c_str());
648 return true;
649 }
John Bauman66b8ab22014-05-06 15:57:45 -0400650
Nicolas Capens0bac2852016-05-07 06:09:58 -0400651 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400652}
653
654// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
655//
656// returns true in case of an error
657//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400658bool TParseContext::boolErrorCheck(const TSourceLoc &line, const TIntermTyped* type)
John Bauman66b8ab22014-05-06 15:57:45 -0400659{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400660 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
661 error(line, "boolean expression expected", "");
662 return true;
663 }
John Bauman66b8ab22014-05-06 15:57:45 -0400664
Nicolas Capens0bac2852016-05-07 06:09:58 -0400665 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400666}
667
668// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
669//
670// returns true in case of an error
671//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400672bool TParseContext::boolErrorCheck(const TSourceLoc &line, const TPublicType& pType)
John Bauman66b8ab22014-05-06 15:57:45 -0400673{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400674 if (pType.type != EbtBool || pType.array || (pType.primarySize > 1) || (pType.secondarySize > 1)) {
675 error(line, "boolean expression expected", "");
676 return true;
677 }
John Bauman66b8ab22014-05-06 15:57:45 -0400678
Nicolas Capens0bac2852016-05-07 06:09:58 -0400679 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400680}
681
Alexis Hetufe1269e2015-06-16 12:43:32 -0400682bool TParseContext::samplerErrorCheck(const TSourceLoc &line, const TPublicType& pType, const char* reason)
John Bauman66b8ab22014-05-06 15:57:45 -0400683{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400684 if (pType.type == EbtStruct) {
685 if (containsSampler(*pType.userDef)) {
686 error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400687
Nicolas Capens0bac2852016-05-07 06:09:58 -0400688 return true;
689 }
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400690
Nicolas Capens0bac2852016-05-07 06:09:58 -0400691 return false;
692 } else if (IsSampler(pType.type)) {
693 error(line, reason, getBasicString(pType.type));
John Bauman66b8ab22014-05-06 15:57:45 -0400694
Nicolas Capens0bac2852016-05-07 06:09:58 -0400695 return true;
696 }
John Bauman66b8ab22014-05-06 15:57:45 -0400697
Nicolas Capens0bac2852016-05-07 06:09:58 -0400698 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400699}
700
Alexis Hetufe1269e2015-06-16 12:43:32 -0400701bool TParseContext::structQualifierErrorCheck(const TSourceLoc &line, const TPublicType& pType)
John Bauman66b8ab22014-05-06 15:57:45 -0400702{
Alexis Hetu55a2cbc2015-04-16 10:49:45 -0400703 switch(pType.qualifier)
704 {
705 case EvqVaryingOut:
706 case EvqSmooth:
707 case EvqFlat:
708 case EvqCentroidOut:
709 case EvqVaryingIn:
710 case EvqSmoothIn:
711 case EvqFlatIn:
712 case EvqCentroidIn:
713 case EvqAttribute:
Alexis Hetu42ff6b12015-06-03 16:03:48 -0400714 case EvqVertexIn:
715 case EvqFragmentOut:
Alexis Hetu55a2cbc2015-04-16 10:49:45 -0400716 if(pType.type == EbtStruct)
717 {
718 error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400719
Alexis Hetu55a2cbc2015-04-16 10:49:45 -0400720 return true;
721 }
722 break;
723 default:
724 break;
725 }
John Bauman66b8ab22014-05-06 15:57:45 -0400726
Nicolas Capens0bac2852016-05-07 06:09:58 -0400727 if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
728 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400729
Alexis Hetu42ff6b12015-06-03 16:03:48 -0400730 // check for layout qualifier issues
Alexis Hetu42ff6b12015-06-03 16:03:48 -0400731 if (pType.qualifier != EvqVertexIn && pType.qualifier != EvqFragmentOut &&
Nicolas Capens0bac2852016-05-07 06:09:58 -0400732 layoutLocationErrorCheck(line, pType.layoutQualifier))
Alexis Hetu42ff6b12015-06-03 16:03:48 -0400733 {
734 return true;
735 }
736
Nicolas Capens0bac2852016-05-07 06:09:58 -0400737 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400738}
739
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400740// These checks are common for all declarations starting a declarator list, and declarators that follow an empty
741// declaration.
742//
743bool TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &identifierLocation)
744{
745 switch(publicType.qualifier)
746 {
747 case EvqVaryingIn:
748 case EvqVaryingOut:
749 case EvqAttribute:
750 case EvqVertexIn:
751 case EvqFragmentOut:
752 if(publicType.type == EbtStruct)
753 {
754 error(identifierLocation, "cannot be used with a structure",
755 getQualifierString(publicType.qualifier));
756 return true;
757 }
758
759 default: break;
760 }
761
762 if(publicType.qualifier != EvqUniform && samplerErrorCheck(identifierLocation, publicType,
763 "samplers must be uniform"))
764 {
765 return true;
766 }
767
768 // check for layout qualifier issues
769 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
770
771 if(layoutQualifier.matrixPacking != EmpUnspecified)
772 {
773 error(identifierLocation, "layout qualifier", getMatrixPackingString(layoutQualifier.matrixPacking),
774 "only valid for interface blocks");
775 return true;
776 }
777
778 if(layoutQualifier.blockStorage != EbsUnspecified)
779 {
780 error(identifierLocation, "layout qualifier", getBlockStorageString(layoutQualifier.blockStorage),
781 "only valid for interface blocks");
782 return true;
783 }
784
785 if(publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut &&
786 layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier))
787 {
788 return true;
789 }
790
791 return false;
792}
793
Nicolas Capens3713cd42015-06-22 10:41:54 -0400794bool TParseContext::layoutLocationErrorCheck(const TSourceLoc &location, const TLayoutQualifier &layoutQualifier)
795{
796 if(layoutQualifier.location != -1)
797 {
798 error(location, "invalid layout qualifier:", "location", "only valid on program inputs and outputs");
799 return true;
800 }
801
802 return false;
803}
Alexis Hetu42ff6b12015-06-03 16:03:48 -0400804
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400805bool TParseContext::locationDeclaratorListCheck(const TSourceLoc& line, const TPublicType &pType)
806{
807 if(pType.layoutQualifier.location != -1)
808 {
809 error(line, "location must only be specified for a single input or output variable", "location");
810 return true;
811 }
812
813 return false;
814}
815
Alexis Hetufe1269e2015-06-16 12:43:32 -0400816bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc &line, TQualifier qualifier, const TType& type)
John Bauman66b8ab22014-05-06 15:57:45 -0400817{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400818 if ((qualifier == EvqOut || qualifier == EvqInOut) &&
819 type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
820 error(line, "samplers cannot be output parameters", type.getBasicString());
821 return true;
822 }
John Bauman66b8ab22014-05-06 15:57:45 -0400823
Nicolas Capens0bac2852016-05-07 06:09:58 -0400824 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400825}
826
827bool TParseContext::containsSampler(TType& type)
828{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400829 if (IsSampler(type.getBasicType()))
830 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400831
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500832 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400833 const TFieldList& fields = type.getStruct()->fields();
834 for(unsigned int i = 0; i < fields.size(); ++i) {
835 if (containsSampler(*fields[i]->type()))
836 return true;
837 }
838 }
John Bauman66b8ab22014-05-06 15:57:45 -0400839
Nicolas Capens0bac2852016-05-07 06:09:58 -0400840 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400841}
842
843//
844// Do size checking for an array type's size.
845//
846// Returns true if there was an error.
847//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400848bool TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped* expr, int& size)
John Bauman66b8ab22014-05-06 15:57:45 -0400849{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400850 TIntermConstantUnion* constant = expr->getAsConstantUnion();
Nicolas Capens3c20f802015-02-17 17:17:20 -0500851
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500852 if (expr->getQualifier() != EvqConstExpr || constant == 0 || !constant->isScalarInt())
Nicolas Capens0bac2852016-05-07 06:09:58 -0400853 {
854 error(line, "array size must be a constant integer expression", "");
855 return true;
856 }
John Bauman66b8ab22014-05-06 15:57:45 -0400857
Nicolas Capens0bac2852016-05-07 06:09:58 -0400858 if (constant->getBasicType() == EbtUInt)
859 {
860 unsigned int uintSize = constant->getUConst(0);
861 if (uintSize > static_cast<unsigned int>(std::numeric_limits<int>::max()))
862 {
863 error(line, "array size too large", "");
864 size = 1;
865 return true;
866 }
John Bauman66b8ab22014-05-06 15:57:45 -0400867
Nicolas Capens0bac2852016-05-07 06:09:58 -0400868 size = static_cast<int>(uintSize);
869 }
870 else
871 {
872 size = constant->getIConst(0);
Nicolas Capens3c20f802015-02-17 17:17:20 -0500873
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500874 if (size < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400875 {
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500876 error(line, "array size must be non-negative", "");
Nicolas Capens0bac2852016-05-07 06:09:58 -0400877 size = 1;
878 return true;
879 }
880 }
John Bauman66b8ab22014-05-06 15:57:45 -0400881
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500882 if(size == 0)
883 {
884 error(line, "array size must be greater than zero", "");
885 return true;
886 }
887
Nicolas Capens0bac2852016-05-07 06:09:58 -0400888 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400889}
890
891//
892// See if this qualifier can be an array.
893//
894// Returns true if there is an error.
895//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400896bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc &line, TPublicType type)
John Bauman66b8ab22014-05-06 15:57:45 -0400897{
Alexis Hetud4e2ba52016-12-01 17:02:33 -0500898 if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) || (type.qualifier == EvqConstExpr && mShaderVersion < 300)) {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400899 error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
900 return true;
901 }
John Bauman66b8ab22014-05-06 15:57:45 -0400902
Nicolas Capens0bac2852016-05-07 06:09:58 -0400903 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400904}
905
906//
907// See if this type can be an array.
908//
909// Returns true if there is an error.
910//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400911bool TParseContext::arrayTypeErrorCheck(const TSourceLoc &line, TPublicType type)
John Bauman66b8ab22014-05-06 15:57:45 -0400912{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400913 //
914 // Can the type be an array?
915 //
916 if (type.array) {
917 error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
918 return true;
919 }
John Bauman66b8ab22014-05-06 15:57:45 -0400920
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500921 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
922 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section 4.3.4).
923 if(mShaderVersion >= 300 && type.type == EbtStruct && IsVarying(type.qualifier))
924 {
925 error(line, "cannot declare arrays of structs of this qualifier",
926 TType(type).getCompleteString().c_str());
927 return true;
928 }
929
Nicolas Capens0bac2852016-05-07 06:09:58 -0400930 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400931}
932
Alexis Hetufe1269e2015-06-16 12:43:32 -0400933bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400934{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400935 bool builtIn = false;
936 TSymbol* symbol = symbolTable.find(node->getSymbol(), mShaderVersion, &builtIn);
937 if (symbol == 0) {
938 error(line, " undeclared identifier", node->getSymbol().c_str());
939 return true;
940 }
941 TVariable* variable = static_cast<TVariable*>(symbol);
John Bauman66b8ab22014-05-06 15:57:45 -0400942
Nicolas Capens0bac2852016-05-07 06:09:58 -0400943 type->setArrayInformationType(variable->getArrayInformationType());
944 variable->updateArrayInformationType(type);
John Bauman66b8ab22014-05-06 15:57:45 -0400945
Nicolas Capens0bac2852016-05-07 06:09:58 -0400946 // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
947 // its an error
948 if (node->getSymbol() == "gl_FragData") {
949 TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", mShaderVersion, &builtIn);
950 ASSERT(fragData);
John Bauman66b8ab22014-05-06 15:57:45 -0400951
Nicolas Capens0bac2852016-05-07 06:09:58 -0400952 int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
953 if (fragDataValue <= size) {
954 error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers");
955 return true;
956 }
957 }
John Bauman66b8ab22014-05-06 15:57:45 -0400958
Nicolas Capens0bac2852016-05-07 06:09:58 -0400959 // we dont want to update the maxArraySize when this flag is not set, we just want to include this
960 // node type in the chain of node types so that its updated when a higher maxArraySize comes in.
961 if (!updateFlag)
962 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400963
Nicolas Capens0bac2852016-05-07 06:09:58 -0400964 size++;
965 variable->getType().setMaxArraySize(size);
966 type->setMaxArraySize(size);
967 TType* tt = type;
John Bauman66b8ab22014-05-06 15:57:45 -0400968
Nicolas Capens0bac2852016-05-07 06:09:58 -0400969 while(tt->getArrayInformationType() != 0) {
970 tt = tt->getArrayInformationType();
971 tt->setMaxArraySize(size);
972 }
John Bauman66b8ab22014-05-06 15:57:45 -0400973
Nicolas Capens0bac2852016-05-07 06:09:58 -0400974 return false;
John Bauman66b8ab22014-05-06 15:57:45 -0400975}
976
977//
978// Enforce non-initializer type/qualifier rules.
979//
980// Returns true if there was an error.
981//
Alexis Hetufe1269e2015-06-16 12:43:32 -0400982bool TParseContext::nonInitConstErrorCheck(const TSourceLoc &line, TString& identifier, TPublicType& type, bool array)
John Bauman66b8ab22014-05-06 15:57:45 -0400983{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400984 if (type.qualifier == EvqConstExpr)
985 {
986 // Make the qualifier make sense.
987 type.qualifier = EvqTemporary;
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400988
Nicolas Capens0bac2852016-05-07 06:09:58 -0400989 if (array)
990 {
991 error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
992 }
993 else if (type.isStructureContainingArrays())
994 {
995 error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str());
996 }
997 else
998 {
999 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
1000 }
John Bauman66b8ab22014-05-06 15:57:45 -04001001
Nicolas Capens0bac2852016-05-07 06:09:58 -04001002 return true;
1003 }
John Bauman66b8ab22014-05-06 15:57:45 -04001004
Nicolas Capens0bac2852016-05-07 06:09:58 -04001005 return false;
John Bauman66b8ab22014-05-06 15:57:45 -04001006}
1007
1008//
1009// Do semantic checking for a variable declaration that has no initializer,
1010// and update the symbol table.
1011//
1012// Returns true if there was an error.
1013//
Alexis Hetufe1269e2015-06-16 12:43:32 -04001014bool TParseContext::nonInitErrorCheck(const TSourceLoc &line, const TString& identifier, TPublicType& type)
John Bauman66b8ab22014-05-06 15:57:45 -04001015{
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001016 if(type.qualifier == EvqConstExpr)
1017 {
1018 // Make the qualifier make sense.
1019 type.qualifier = EvqTemporary;
John Bauman66b8ab22014-05-06 15:57:45 -04001020
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001021 // Generate informative error messages for ESSL1.
1022 // In ESSL3 arrays and structures containing arrays can be constant.
Alexis Hetu0a655842015-06-22 16:52:11 -04001023 if(mShaderVersion < 300 && type.isStructureContainingArrays())
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001024 {
1025 error(line,
1026 "structures containing arrays may not be declared constant since they cannot be initialized",
1027 identifier.c_str());
1028 }
1029 else
1030 {
1031 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
1032 }
John Bauman66b8ab22014-05-06 15:57:45 -04001033
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001034 return true;
1035 }
1036 if(type.isUnsizedArray())
1037 {
1038 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
1039 return true;
1040 }
1041 return false;
1042}
John Bauman66b8ab22014-05-06 15:57:45 -04001043
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001044// Do some simple checks that are shared between all variable declarations,
1045// and update the symbol table.
1046//
1047// Returns true if declaring the variable succeeded.
1048//
1049bool TParseContext::declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type,
1050 TVariable **variable)
1051{
1052 ASSERT((*variable) == nullptr);
John Bauman66b8ab22014-05-06 15:57:45 -04001053
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001054 // gl_LastFragData may be redeclared with a new precision qualifier
1055 if(type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
1056 {
1057 const TVariable *maxDrawBuffers =
Alexis Hetu0a655842015-06-22 16:52:11 -04001058 static_cast<const TVariable *>(symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001059 if(type.getArraySize() != maxDrawBuffers->getConstPointer()->getIConst())
1060 {
1061 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers", identifier.c_str());
1062 return false;
1063 }
1064 }
1065
1066 if(reservedErrorCheck(line, identifier))
1067 return false;
1068
1069 (*variable) = new TVariable(&identifier, type);
1070 if(!symbolTable.declare(**variable))
1071 {
1072 error(line, "redefinition", identifier.c_str());
1073 delete (*variable);
1074 (*variable) = nullptr;
1075 return false;
1076 }
1077
1078 if(voidErrorCheck(line, identifier, type.getBasicType()))
1079 return false;
1080
1081 return true;
John Bauman66b8ab22014-05-06 15:57:45 -04001082}
1083
Alexis Hetufe1269e2015-06-16 12:43:32 -04001084bool TParseContext::paramErrorCheck(const TSourceLoc &line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04001085{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001086 if (qualifier != EvqConstReadOnly && qualifier != EvqTemporary) {
1087 error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
1088 return true;
1089 }
1090 if (qualifier == EvqConstReadOnly && paramQualifier != EvqIn) {
1091 error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
1092 return true;
1093 }
John Bauman66b8ab22014-05-06 15:57:45 -04001094
Nicolas Capens0bac2852016-05-07 06:09:58 -04001095 if (qualifier == EvqConstReadOnly)
1096 type->setQualifier(EvqConstReadOnly);
1097 else
1098 type->setQualifier(paramQualifier);
John Bauman66b8ab22014-05-06 15:57:45 -04001099
Nicolas Capens0bac2852016-05-07 06:09:58 -04001100 return false;
John Bauman66b8ab22014-05-06 15:57:45 -04001101}
1102
Alexis Hetufe1269e2015-06-16 12:43:32 -04001103bool TParseContext::extensionErrorCheck(const TSourceLoc &line, const TString& extension)
John Bauman66b8ab22014-05-06 15:57:45 -04001104{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001105 const TExtensionBehavior& extBehavior = extensionBehavior();
1106 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
1107 if (iter == extBehavior.end()) {
1108 error(line, "extension", extension.c_str(), "is not supported");
1109 return true;
1110 }
1111 // In GLSL ES, an extension's default behavior is "disable".
1112 if (iter->second == EBhDisable || iter->second == EBhUndefined) {
1113 error(line, "extension", extension.c_str(), "is disabled");
1114 return true;
1115 }
1116 if (iter->second == EBhWarn) {
1117 warning(line, "extension", extension.c_str(), "is being used");
1118 return false;
1119 }
John Bauman66b8ab22014-05-06 15:57:45 -04001120
Nicolas Capens0bac2852016-05-07 06:09:58 -04001121 return false;
John Bauman66b8ab22014-05-06 15:57:45 -04001122}
1123
Alexis Hetuad6b8752015-06-09 16:15:30 -04001124bool TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *aggregate)
1125{
1126 for(size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1127 {
1128 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1129 if(qual == EvqOut || qual == EvqInOut)
1130 {
1131 TIntermTyped *node = (aggregate->getSequence())[i]->getAsTyped();
1132 if(lValueErrorCheck(node->getLine(), "assign", node))
1133 {
1134 error(node->getLine(),
1135 "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
1136 recover();
1137 return true;
1138 }
1139 }
1140 }
1141 return false;
1142}
1143
Alexis Hetuad527752015-07-07 13:31:44 -04001144void TParseContext::es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation)
1145{
1146 switch(qualifier)
1147 {
1148 case EvqVaryingOut:
1149 case EvqSmoothOut:
1150 case EvqFlatOut:
1151 case EvqCentroidOut:
1152 case EvqVertexOut:
1153 case EvqFragmentOut:
1154 break;
1155 default:
1156 error(invariantLocation, "Only out variables can be invariant.", "invariant");
1157 recover();
1158 break;
1159 }
1160}
1161
John Bauman66b8ab22014-05-06 15:57:45 -04001162bool TParseContext::supportsExtension(const char* extension)
1163{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001164 const TExtensionBehavior& extbehavior = extensionBehavior();
1165 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1166 return (iter != extbehavior.end());
John Bauman66b8ab22014-05-06 15:57:45 -04001167}
1168
Alexis Hetufe1269e2015-06-16 12:43:32 -04001169void TParseContext::handleExtensionDirective(const TSourceLoc &line, const char* extName, const char* behavior)
John Bauman66b8ab22014-05-06 15:57:45 -04001170{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001171 pp::SourceLocation loc(line.first_file, line.first_line);
1172 mDirectiveHandler.handleExtension(loc, extName, behavior);
John Bauman66b8ab22014-05-06 15:57:45 -04001173}
1174
Alexis Hetufe1269e2015-06-16 12:43:32 -04001175void TParseContext::handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value)
John Bauman66b8ab22014-05-06 15:57:45 -04001176{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001177 pp::SourceLocation loc(line.first_file, line.first_line);
1178 mDirectiveHandler.handlePragma(loc, name, value);
John Bauman66b8ab22014-05-06 15:57:45 -04001179}
1180
1181/////////////////////////////////////////////////////////////////////////////////
1182//
1183// Non-Errors.
1184//
1185/////////////////////////////////////////////////////////////////////////////////
1186
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001187const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1188 const TString *name,
1189 const TSymbol *symbol)
1190{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001191 const TVariable *variable = nullptr;
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001192
1193 if(!symbol)
1194 {
1195 error(location, "undeclared identifier", name->c_str());
1196 recover();
1197 }
1198 else if(!symbol->isVariable())
1199 {
1200 error(location, "variable expected", name->c_str());
1201 recover();
1202 }
1203 else
1204 {
1205 variable = static_cast<const TVariable*>(symbol);
1206
Alexis Hetu0a655842015-06-22 16:52:11 -04001207 if(symbolTable.findBuiltIn(variable->getName(), mShaderVersion))
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001208 {
1209 recover();
1210 }
1211
1212 // Reject shaders using both gl_FragData and gl_FragColor
1213 TQualifier qualifier = variable->getType().getQualifier();
1214 if(qualifier == EvqFragData)
1215 {
1216 mUsesFragData = true;
1217 }
1218 else if(qualifier == EvqFragColor)
1219 {
1220 mUsesFragColor = true;
1221 }
1222
1223 // This validation is not quite correct - it's only an error to write to
1224 // both FragData and FragColor. For simplicity, and because users shouldn't
Nicolas Capens8b124c12016-04-18 14:09:37 -04001225 // be rewarded for reading from undefined variables, return an error
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001226 // if they are both referenced, rather than assigned.
1227 if(mUsesFragData && mUsesFragColor)
1228 {
1229 error(location, "cannot use both gl_FragData and gl_FragColor", name->c_str());
1230 recover();
1231 }
1232 }
1233
1234 if(!variable)
1235 {
1236 TType type(EbtFloat, EbpUndefined);
1237 TVariable *fakeVariable = new TVariable(name, type);
1238 symbolTable.declare(*fakeVariable);
1239 variable = fakeVariable;
1240 }
1241
1242 return variable;
1243}
1244
John Bauman66b8ab22014-05-06 15:57:45 -04001245//
1246// Look up a function name in the symbol table, and make sure it is a function.
1247//
1248// Return the function symbol if found, otherwise 0.
1249//
Alexis Hetufe1269e2015-06-16 12:43:32 -04001250const TFunction* TParseContext::findFunction(const TSourceLoc &line, TFunction* call, bool *builtIn)
John Bauman66b8ab22014-05-06 15:57:45 -04001251{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001252 // First find by unmangled name to check whether the function name has been
1253 // hidden by a variable name or struct typename.
1254 const TSymbol* symbol = symbolTable.find(call->getName(), mShaderVersion, builtIn);
1255 if (symbol == 0) {
1256 symbol = symbolTable.find(call->getMangledName(), mShaderVersion, builtIn);
1257 }
John Bauman66b8ab22014-05-06 15:57:45 -04001258
Nicolas Capens0bac2852016-05-07 06:09:58 -04001259 if (symbol == 0) {
1260 error(line, "no matching overloaded function found", call->getName().c_str());
Alexis Hetuf0005a12016-09-28 15:52:21 -04001261 return nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001262 }
John Bauman66b8ab22014-05-06 15:57:45 -04001263
Nicolas Capens0bac2852016-05-07 06:09:58 -04001264 if (!symbol->isFunction()) {
1265 error(line, "function name expected", call->getName().c_str());
Alexis Hetuf0005a12016-09-28 15:52:21 -04001266 return nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001267 }
John Bauman66b8ab22014-05-06 15:57:45 -04001268
Nicolas Capens0bac2852016-05-07 06:09:58 -04001269 return static_cast<const TFunction*>(symbol);
John Bauman66b8ab22014-05-06 15:57:45 -04001270}
1271
1272//
1273// Initializers show up in several places in the grammar. Have one set of
1274// code to handle them here.
1275//
Alexis Hetufe1269e2015-06-16 12:43:32 -04001276bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& identifier, const TPublicType& pType,
Nicolas Capens0bac2852016-05-07 06:09:58 -04001277 TIntermTyped *initializer, TIntermNode **intermNode)
John Bauman66b8ab22014-05-06 15:57:45 -04001278{
Alexis Hetue5246692015-06-18 12:34:52 -04001279 ASSERT(intermNode != nullptr);
1280 TType type = TType(pType);
John Bauman66b8ab22014-05-06 15:57:45 -04001281
Alexis Hetuec93b1d2016-12-09 16:01:29 -05001282 if(type.isUnsizedArray())
Alexis Hetue5246692015-06-18 12:34:52 -04001283 {
Alexis Hetuec93b1d2016-12-09 16:01:29 -05001284 // We have not checked yet whether the initializer actually is an array or not.
1285 if(initializer->isArray())
1286 {
1287 type.setArraySize(initializer->getArraySize());
1288 }
1289 else
1290 {
1291 // Having a non-array initializer for an unsized array will result in an error later,
1292 // so we don't generate an error message here.
1293 type.setArraySize(1u);
1294 }
Alexis Hetue5246692015-06-18 12:34:52 -04001295 }
Nicolas Capens0863f0d2016-04-10 00:30:02 -04001296
1297 TVariable *variable = nullptr;
Alexis Hetue5246692015-06-18 12:34:52 -04001298 if(!declareVariable(line, identifier, type, &variable))
1299 {
1300 return true;
1301 }
John Bauman66b8ab22014-05-06 15:57:45 -04001302
Alexis Hetue5246692015-06-18 12:34:52 -04001303 bool globalInitWarning = false;
1304 if(symbolTable.atGlobalLevel() && !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
1305 {
1306 // Error message does not completely match behavior with ESSL 1.00, but
1307 // we want to steer developers towards only using constant expressions.
1308 error(line, "global variable initializers must be constant expressions", "=");
1309 return true;
1310 }
1311 if(globalInitWarning)
1312 {
1313 warning(line, "global variable initializers should be constant expressions "
1314 "(uniforms and globals are allowed in global initializers for legacy compatibility)", "=");
Nicolas Capens0bac2852016-05-07 06:09:58 -04001315 }
John Bauman66b8ab22014-05-06 15:57:45 -04001316
Nicolas Capens0bac2852016-05-07 06:09:58 -04001317 //
1318 // identifier must be of type constant, a global, or a temporary
1319 //
1320 TQualifier qualifier = type.getQualifier();
1321 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConstExpr)) {
1322 error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString());
1323 return true;
1324 }
1325 //
1326 // test for and propagate constant
1327 //
John Bauman66b8ab22014-05-06 15:57:45 -04001328
Nicolas Capens0bac2852016-05-07 06:09:58 -04001329 if (qualifier == EvqConstExpr) {
1330 if (qualifier != initializer->getQualifier()) {
1331 std::stringstream extraInfoStream;
1332 extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
1333 std::string extraInfo = extraInfoStream.str();
1334 error(line, " assigning non-constant to", "=", extraInfo.c_str());
1335 variable->getType().setQualifier(EvqTemporary);
1336 return true;
1337 }
Nicolas Capens0863f0d2016-04-10 00:30:02 -04001338
Nicolas Capens0bac2852016-05-07 06:09:58 -04001339 if (type != initializer->getType()) {
1340 error(line, " non-matching types for const initializer ",
1341 variable->getType().getQualifierString());
1342 variable->getType().setQualifier(EvqTemporary);
1343 return true;
1344 }
Nicolas Capens0863f0d2016-04-10 00:30:02 -04001345
Nicolas Capens0bac2852016-05-07 06:09:58 -04001346 if (initializer->getAsConstantUnion()) {
1347 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
1348 } else if (initializer->getAsSymbolNode()) {
1349 const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1350 const TVariable* tVar = static_cast<const TVariable*>(symbol);
John Bauman66b8ab22014-05-06 15:57:45 -04001351
Nicolas Capens0bac2852016-05-07 06:09:58 -04001352 ConstantUnion* constArray = tVar->getConstPointer();
1353 variable->shareConstPointer(constArray);
1354 }
1355 }
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04001356
Nicolas Capens0bac2852016-05-07 06:09:58 -04001357 if (!variable->isConstant()) {
1358 TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
1359 *intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1360 if(*intermNode == nullptr) {
1361 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1362 return true;
1363 }
1364 } else
1365 *intermNode = nullptr;
John Bauman66b8ab22014-05-06 15:57:45 -04001366
Nicolas Capens0bac2852016-05-07 06:09:58 -04001367 return false;
John Bauman66b8ab22014-05-06 15:57:45 -04001368}
1369
Alexis Hetu42ff6b12015-06-03 16:03:48 -04001370TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier)
1371{
1372 TPublicType returnType = typeSpecifier;
1373 returnType.qualifier = qualifier;
1374 returnType.invariant = invariant;
1375 returnType.layoutQualifier = layoutQualifier;
1376
1377 if(typeSpecifier.array)
1378 {
1379 error(typeSpecifier.line, "not supported", "first-class array");
1380 recover();
1381 returnType.clearArrayness();
1382 }
1383
Alexis Hetu0a655842015-06-22 16:52:11 -04001384 if(mShaderVersion < 300)
Alexis Hetu42ff6b12015-06-03 16:03:48 -04001385 {
Alexis Hetuec93b1d2016-12-09 16:01:29 -05001386 if(typeSpecifier.array)
1387 {
1388 error(typeSpecifier.line, "not supported", "first-class array");
1389 returnType.clearArrayness();
1390 }
1391
Alexis Hetu42ff6b12015-06-03 16:03:48 -04001392 if(qualifier == EvqAttribute && (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
1393 {
1394 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
1395 recover();
1396 }
1397
1398 if((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
1399 (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
1400 {
1401 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
1402 recover();
1403 }
1404 }
1405 else
1406 {
Alexis Hetuec93b1d2016-12-09 16:01:29 -05001407 if(!returnType.layoutQualifier.isEmpty())
Alexis Hetu42ff6b12015-06-03 16:03:48 -04001408 {
Alexis Hetuec93b1d2016-12-09 16:01:29 -05001409 globalErrorCheck(typeSpecifier.line, symbolTable.atGlobalLevel(), "layout");
1410 }
Alexis Hetu42ff6b12015-06-03 16:03:48 -04001411
Alexis Hetuec93b1d2016-12-09 16:01:29 -05001412 if(IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn || returnType.qualifier == EvqFragmentOut)
1413 {
1414 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier, typeSpecifier.line);
Alexis Hetu42ff6b12015-06-03 16:03:48 -04001415 }
1416 }
1417
1418 return returnType;
1419}
1420
Alexis Hetuec93b1d2016-12-09 16:01:29 -05001421void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1422 const TPublicType &type,
1423 const TSourceLoc &qualifierLocation)
1424{
1425 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
1426 if(type.type == EbtBool)
1427 {
1428 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
1429 }
1430
1431 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1432 switch(qualifier)
1433 {
1434 case EvqVertexIn:
1435 // ESSL 3.00 section 4.3.4
1436 if(type.array)
1437 {
1438 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
1439 }
1440 // Vertex inputs with a struct type are disallowed in singleDeclarationErrorCheck
1441 return;
1442 case EvqFragmentOut:
1443 // ESSL 3.00 section 4.3.6
1444 if(type.isMatrix())
1445 {
1446 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
1447 }
1448 // Fragment outputs with a struct type are disallowed in singleDeclarationErrorCheck
1449 return;
1450 default:
1451 break;
1452 }
1453
1454 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1455 // restrictions.
1456 bool typeContainsIntegers = (type.type == EbtInt || type.type == EbtUInt ||
1457 type.isStructureContainingType(EbtInt) ||
1458 type.isStructureContainingType(EbtUInt));
1459 if(typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1460 {
1461 error(qualifierLocation, "must use 'flat' interpolation here", getQualifierString(qualifier));
1462 }
1463
1464 if(type.type == EbtStruct)
1465 {
1466 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1467 // These restrictions are only implied by the ESSL 3.00 spec, but
1468 // the ESSL 3.10 spec lists these restrictions explicitly.
1469 if(type.array)
1470 {
1471 error(qualifierLocation, "cannot be an array of structures", getQualifierString(qualifier));
1472 }
1473 if(type.isStructureContainingArrays())
1474 {
1475 error(qualifierLocation, "cannot be a structure containing an array", getQualifierString(qualifier));
1476 }
1477 if(type.isStructureContainingType(EbtStruct))
1478 {
1479 error(qualifierLocation, "cannot be a structure containing a structure", getQualifierString(qualifier));
1480 }
1481 if(type.isStructureContainingType(EbtBool))
1482 {
1483 error(qualifierLocation, "cannot be a structure containing a bool", getQualifierString(qualifier));
1484 }
1485 }
1486}
1487
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001488TIntermAggregate *TParseContext::parseSingleDeclaration(TPublicType &publicType,
1489 const TSourceLoc &identifierOrTypeLocation,
1490 const TString &identifier)
1491{
1492 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierOrTypeLocation);
1493
1494 bool emptyDeclaration = (identifier == "");
1495
1496 mDeferredSingleDeclarationErrorCheck = emptyDeclaration;
1497
1498 if(emptyDeclaration)
1499 {
1500 if(publicType.isUnsizedArray())
1501 {
1502 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an error.
1503 // It is assumed that this applies to empty declarations as well.
1504 error(identifierOrTypeLocation, "empty array declaration needs to specify a size", identifier.c_str());
1505 }
1506 }
1507 else
1508 {
1509 if(singleDeclarationErrorCheck(publicType, identifierOrTypeLocation))
1510 recover();
1511
1512 if(nonInitErrorCheck(identifierOrTypeLocation, identifier, publicType))
1513 recover();
1514
1515 TVariable *variable = nullptr;
1516 if(!declareVariable(identifierOrTypeLocation, identifier, TType(publicType), &variable))
1517 recover();
1518
1519 if(variable && symbol)
1520 symbol->setId(variable->getUniqueId());
1521 }
1522
1523 return intermediate.makeAggregate(symbol, identifierOrTypeLocation);
1524}
1525
1526TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1527 const TSourceLoc &identifierLocation,
1528 const TString &identifier,
1529 const TSourceLoc &indexLocation,
1530 TIntermTyped *indexExpression)
1531{
1532 mDeferredSingleDeclarationErrorCheck = false;
1533
1534 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1535 recover();
1536
1537 if(nonInitErrorCheck(identifierLocation, identifier, publicType))
1538 recover();
1539
1540 if(arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
1541 {
1542 recover();
1543 }
1544
1545 TType arrayType(publicType);
1546
1547 int size;
1548 if(arraySizeErrorCheck(identifierLocation, indexExpression, size))
1549 {
1550 recover();
1551 }
1552 // Make the type an array even if size check failed.
1553 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1554 arrayType.setArraySize(size);
1555
1556 TVariable *variable = nullptr;
1557 if(!declareVariable(identifierLocation, identifier, arrayType, &variable))
1558 recover();
1559
1560 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
1561 if(variable && symbol)
1562 symbol->setId(variable->getUniqueId());
1563
1564 return intermediate.makeAggregate(symbol, identifierLocation);
1565}
1566
1567TIntermAggregate *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
1568 const TSourceLoc &identifierLocation,
1569 const TString &identifier,
1570 const TSourceLoc &initLocation,
1571 TIntermTyped *initializer)
1572{
1573 mDeferredSingleDeclarationErrorCheck = false;
1574
1575 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1576 recover();
1577
1578 TIntermNode *intermNode = nullptr;
Alexis Hetue5246692015-06-18 12:34:52 -04001579 if(!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001580 {
1581 //
1582 // Build intermediate representation
1583 //
1584 return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : nullptr;
1585 }
1586 else
1587 {
1588 recover();
1589 return nullptr;
1590 }
1591}
1592
1593TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration(TPublicType &publicType,
1594 const TSourceLoc &identifierLocation,
1595 const TString &identifier,
1596 const TSourceLoc &indexLocation,
1597 TIntermTyped *indexExpression,
1598 const TSourceLoc &initLocation,
1599 TIntermTyped *initializer)
1600{
1601 mDeferredSingleDeclarationErrorCheck = false;
1602
1603 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1604 recover();
1605
1606 if(arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
1607 {
1608 recover();
1609 }
1610
1611 TPublicType arrayType(publicType);
1612
1613 int size = 0;
1614 // If indexExpression is nullptr, then the array will eventually get its size implicitly from the initializer.
1615 if(indexExpression != nullptr && arraySizeErrorCheck(identifierLocation, indexExpression, size))
1616 {
1617 recover();
1618 }
1619 // Make the type an array even if size check failed.
1620 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1621 arrayType.setArray(true, size);
1622
1623 // initNode will correspond to the whole of "type b[n] = initializer".
1624 TIntermNode *initNode = nullptr;
Alexis Hetue5246692015-06-18 12:34:52 -04001625 if(!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001626 {
1627 return initNode ? intermediate.makeAggregate(initNode, initLocation) : nullptr;
1628 }
1629 else
1630 {
1631 recover();
1632 return nullptr;
1633 }
1634}
1635
1636TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc,
1637 const TSourceLoc &identifierLoc,
1638 const TString *identifier,
1639 const TSymbol *symbol)
1640{
1641 // invariant declaration
1642 if(globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying"))
1643 {
1644 recover();
1645 }
1646
1647 if(!symbol)
1648 {
1649 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
1650 recover();
1651 return nullptr;
1652 }
1653 else
1654 {
1655 const TString kGlFrontFacing("gl_FrontFacing");
1656 if(*identifier == kGlFrontFacing)
1657 {
1658 error(identifierLoc, "identifier should not be declared as invariant", identifier->c_str());
1659 recover();
1660 return nullptr;
1661 }
1662 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
1663 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
1664 ASSERT(variable);
1665 const TType &type = variable->getType();
1666 TIntermSymbol *intermSymbol = intermediate.addSymbol(variable->getUniqueId(),
1667 *identifier, type, identifierLoc);
1668
1669 TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc);
1670 aggregate->setOp(EOpInvariantDeclaration);
1671 return aggregate;
1672 }
1673}
1674
1675TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration,
1676 const TSourceLoc &identifierLocation, const TString &identifier)
1677{
1678 // If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
1679 if(mDeferredSingleDeclarationErrorCheck)
1680 {
1681 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1682 recover();
1683 mDeferredSingleDeclarationErrorCheck = false;
1684 }
1685
1686 if(locationDeclaratorListCheck(identifierLocation, publicType))
1687 recover();
1688
1689 if(nonInitErrorCheck(identifierLocation, identifier, publicType))
1690 recover();
1691
1692 TVariable *variable = nullptr;
1693 if(!declareVariable(identifierLocation, identifier, TType(publicType), &variable))
1694 recover();
1695
1696 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
1697 if(variable && symbol)
1698 symbol->setId(variable->getUniqueId());
1699
1700 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
1701}
1702
1703TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration,
1704 const TSourceLoc &identifierLocation, const TString &identifier,
1705 const TSourceLoc &arrayLocation, TIntermTyped *indexExpression)
1706{
1707 // If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
1708 if(mDeferredSingleDeclarationErrorCheck)
1709 {
1710 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1711 recover();
1712 mDeferredSingleDeclarationErrorCheck = false;
1713 }
1714
1715 if(locationDeclaratorListCheck(identifierLocation, publicType))
1716 recover();
1717
1718 if(nonInitErrorCheck(identifierLocation, identifier, publicType))
1719 recover();
1720
1721 if(arrayTypeErrorCheck(arrayLocation, publicType) || arrayQualifierErrorCheck(arrayLocation, publicType))
1722 {
1723 recover();
1724 }
1725 else
1726 {
1727 TType arrayType = TType(publicType);
1728 int size;
1729 if(arraySizeErrorCheck(arrayLocation, indexExpression, size))
1730 {
1731 recover();
1732 }
1733 arrayType.setArraySize(size);
1734
1735 TVariable *variable = nullptr;
1736 if(!declareVariable(identifierLocation, identifier, arrayType, &variable))
1737 recover();
1738
1739 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
1740 if(variable && symbol)
1741 symbol->setId(variable->getUniqueId());
1742
1743 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
1744 }
1745
1746 return nullptr;
1747}
1748
1749TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicType, TIntermAggregate *aggregateDeclaration,
1750 const TSourceLoc &identifierLocation, const TString &identifier,
1751 const TSourceLoc &initLocation, TIntermTyped *initializer)
1752{
1753 // If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
1754 if(mDeferredSingleDeclarationErrorCheck)
1755 {
1756 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1757 recover();
1758 mDeferredSingleDeclarationErrorCheck = false;
1759 }
1760
1761 if(locationDeclaratorListCheck(identifierLocation, publicType))
1762 recover();
1763
1764 TIntermNode *intermNode = nullptr;
Alexis Hetue5246692015-06-18 12:34:52 -04001765 if(!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001766 {
1767 //
1768 // build the intermediate representation
1769 //
1770 if(intermNode)
1771 {
1772 return intermediate.growAggregate(aggregateDeclaration, intermNode, initLocation);
1773 }
1774 else
1775 {
1776 return aggregateDeclaration;
1777 }
1778 }
1779 else
1780 {
1781 recover();
1782 return nullptr;
1783 }
1784}
1785
1786TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
1787 TIntermAggregate *aggregateDeclaration,
1788 const TSourceLoc &identifierLocation,
1789 const TString &identifier,
1790 const TSourceLoc &indexLocation,
1791 TIntermTyped *indexExpression,
1792 const TSourceLoc &initLocation, TIntermTyped *initializer)
1793{
1794 // If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
1795 if(mDeferredSingleDeclarationErrorCheck)
1796 {
1797 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1798 recover();
1799 mDeferredSingleDeclarationErrorCheck = false;
1800 }
1801
1802 if(locationDeclaratorListCheck(identifierLocation, publicType))
1803 recover();
1804
1805 if(arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
1806 {
1807 recover();
1808 }
1809
1810 TPublicType arrayType(publicType);
1811
1812 int size = 0;
1813 // If indexExpression is nullptr, then the array will eventually get its size implicitly from the initializer.
1814 if(indexExpression != nullptr && arraySizeErrorCheck(identifierLocation, indexExpression, size))
1815 {
1816 recover();
1817 }
1818 // Make the type an array even if size check failed.
1819 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1820 arrayType.setArray(true, size);
1821
1822 // initNode will correspond to the whole of "b[n] = initializer".
1823 TIntermNode *initNode = nullptr;
Alexis Hetue5246692015-06-18 12:34:52 -04001824 if(!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04001825 {
1826 if(initNode)
1827 {
1828 return intermediate.growAggregate(aggregateDeclaration, initNode, initLocation);
1829 }
1830 else
1831 {
1832 return aggregateDeclaration;
1833 }
1834 }
1835 else
1836 {
1837 recover();
1838 return nullptr;
1839 }
1840}
1841
Alexis Hetua35d8232015-06-11 17:11:06 -04001842void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
1843{
Alexis Hetu0a655842015-06-22 16:52:11 -04001844 if(mShaderVersion < 300)
Alexis Hetua35d8232015-06-11 17:11:06 -04001845 {
1846 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 only", "layout");
1847 recover();
1848 return;
1849 }
1850
1851 if(typeQualifier.qualifier != EvqUniform)
1852 {
1853 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
1854 recover();
1855 return;
1856 }
1857
1858 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
1859 ASSERT(!layoutQualifier.isEmpty());
1860
1861 if(layoutLocationErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier))
1862 {
1863 recover();
1864 return;
1865 }
1866
1867 if(layoutQualifier.matrixPacking != EmpUnspecified)
1868 {
Alexis Hetu0a655842015-06-22 16:52:11 -04001869 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
Alexis Hetua35d8232015-06-11 17:11:06 -04001870 }
1871
1872 if(layoutQualifier.blockStorage != EbsUnspecified)
1873 {
Alexis Hetu0a655842015-06-22 16:52:11 -04001874 mDefaultBlockStorage = layoutQualifier.blockStorage;
Alexis Hetua35d8232015-06-11 17:11:06 -04001875 }
1876}
1877
Alexis Hetu407813b2016-02-24 16:46:13 -05001878TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function, const TSourceLoc &location)
1879{
1880 // Note: symbolTableFunction could be the same as function if this is the first declaration.
1881 // Either way the instance in the symbol table is used to track whether the function is declared
1882 // multiple times.
1883 TFunction *symbolTableFunction =
1884 static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion()));
1885 if(symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100)
1886 {
1887 // ESSL 1.00.17 section 4.2.7.
1888 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
1889 error(location, "duplicate function prototype declarations are not allowed", "function");
1890 recover();
1891 }
1892 symbolTableFunction->setHasPrototypeDeclaration();
1893
1894 TIntermAggregate *prototype = new TIntermAggregate;
1895 prototype->setType(function.getReturnType());
1896 prototype->setName(function.getMangledName());
1897
1898 for(size_t i = 0; i < function.getParamCount(); i++)
1899 {
1900 const TParameter &param = function.getParam(i);
1901 if(param.name != 0)
1902 {
1903 TVariable variable(param.name, *param.type);
1904
1905 TIntermSymbol *paramSymbol = intermediate.addSymbol(
1906 variable.getUniqueId(), variable.getName(), variable.getType(), location);
1907 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
1908 }
1909 else
1910 {
1911 TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
1912 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
1913 }
1914 }
1915
1916 prototype->setOp(EOpPrototype);
1917
1918 symbolTable.pop();
1919
1920 if(!symbolTable.atGlobalLevel())
1921 {
1922 // ESSL 3.00.4 section 4.2.4.
1923 error(location, "local function prototype declarations are not allowed", "function");
1924 recover();
1925 }
1926
1927 return prototype;
1928}
1929
1930TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function, TIntermAggregate *functionPrototype, TIntermAggregate *functionBody, const TSourceLoc &location)
1931{
1932 //?? Check that all paths return a value if return type != void ?
1933 // May be best done as post process phase on intermediate code
1934 if(mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
1935 {
1936 error(location, "function does not return a value:", "", function.getName().c_str());
1937 recover();
1938 }
1939
1940 TIntermAggregate *aggregate = intermediate.growAggregate(functionPrototype, functionBody, location);
1941 intermediate.setAggregateOperator(aggregate, EOpFunction, location);
1942 aggregate->setName(function.getMangledName().c_str());
1943 aggregate->setType(function.getReturnType());
1944
Nicolas Capens0863f0d2016-04-10 00:30:02 -04001945 // store the pragma information for debug and optimize and other vendor specific
1946 // information. This information can be queried from the parse tree
1947 aggregate->setOptimize(pragma().optimize);
Alexis Hetu407813b2016-02-24 16:46:13 -05001948 aggregate->setDebug(pragma().debug);
1949
Nicolas Capens0863f0d2016-04-10 00:30:02 -04001950 if(functionBody && functionBody->getAsAggregate())
Alexis Hetu407813b2016-02-24 16:46:13 -05001951 aggregate->setEndLine(functionBody->getAsAggregate()->getEndLine());
1952
1953 symbolTable.pop();
1954 return aggregate;
1955}
1956
1957void TParseContext::parseFunctionPrototype(const TSourceLoc &location, TFunction *function, TIntermAggregate **aggregateOut)
1958{
1959 const TSymbol *builtIn = symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
1960
1961 if(builtIn)
1962 {
1963 error(location, "built-in functions cannot be redefined", function->getName().c_str());
1964 recover();
1965 }
1966
1967 TFunction *prevDec = static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
1968 //
1969 // Note: 'prevDec' could be 'function' if this is the first time we've seen function
1970 // as it would have just been put in the symbol table. Otherwise, we're looking up
1971 // an earlier occurance.
1972 //
1973 if(prevDec->isDefined())
1974 {
1975 // Then this function already has a body.
1976 error(location, "function already has a body", function->getName().c_str());
1977 recover();
1978 }
1979 prevDec->setDefined();
1980 //
1981 // Overload the unique ID of the definition to be the same unique ID as the declaration.
1982 // Eventually we will probably want to have only a single definition and just swap the
1983 // arguments to be the definition's arguments.
1984 //
1985 function->setUniqueId(prevDec->getUniqueId());
1986
1987 // Raise error message if main function takes any parameters or return anything other than void
1988 if(function->getName() == "main")
1989 {
1990 if(function->getParamCount() > 0)
1991 {
1992 error(location, "function cannot take any parameter(s)", function->getName().c_str());
1993 recover();
1994 }
1995 if(function->getReturnType().getBasicType() != EbtVoid)
1996 {
1997 error(location, "", function->getReturnType().getBasicString(), "main function cannot return a value");
1998 recover();
1999 }
2000 }
2001
2002 //
2003 // Remember the return type for later checking for RETURN statements.
2004 //
2005 mCurrentFunctionType = &(prevDec->getReturnType());
2006 mFunctionReturnsValue = false;
2007
2008 //
2009 // Insert parameters into the symbol table.
2010 // If the parameter has no name, it's not an error, just don't insert it
2011 // (could be used for unused args).
2012 //
2013 // Also, accumulate the list of parameters into the HIL, so lower level code
2014 // knows where to find parameters.
2015 //
2016 TIntermAggregate *paramNodes = new TIntermAggregate;
2017 for(size_t i = 0; i < function->getParamCount(); i++)
2018 {
2019 const TParameter &param = function->getParam(i);
2020 if(param.name != 0)
2021 {
2022 TVariable *variable = new TVariable(param.name, *param.type);
2023 //
2024 // Insert the parameters with name in the symbol table.
2025 //
2026 if(!symbolTable.declare(*variable))
2027 {
2028 error(location, "redefinition", variable->getName().c_str());
2029 recover();
2030 paramNodes = intermediate.growAggregate(
2031 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
2032 continue;
2033 }
2034
2035 //
2036 // Add the parameter to the HIL
2037 //
2038 TIntermSymbol *symbol = intermediate.addSymbol(
2039 variable->getUniqueId(), variable->getName(), variable->getType(), location);
2040
2041 paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
2042 }
2043 else
2044 {
2045 paramNodes = intermediate.growAggregate(
2046 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
2047 }
2048 }
2049 intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
2050 *aggregateOut = paramNodes;
2051 setLoopNestingLevel(0);
2052}
2053
2054TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
2055{
2056 //
2057 // We don't know at this point whether this is a function definition or a prototype.
2058 // The definition production code will check for redefinitions.
2059 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
2060 //
2061 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2062 // here.
2063 //
2064 TFunction *prevDec = static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Alexis Hetuec93b1d2016-12-09 16:01:29 -05002065 if(getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltIn(function->getName().c_str()))
2066 {
2067 // With ESSL 3.00, names of built-in functions cannot be redeclared as functions.
2068 // Therefore overloading or redefining builtin functions is an error.
2069 error(location, "Name of a built-in function cannot be redeclared as function", function->getName().c_str());
2070 }
2071 else if(prevDec)
Alexis Hetu407813b2016-02-24 16:46:13 -05002072 {
2073 if(prevDec->getReturnType() != function->getReturnType())
2074 {
2075 error(location, "overloaded functions must have the same return type",
2076 function->getReturnType().getBasicString());
2077 recover();
2078 }
2079 for(size_t i = 0; i < prevDec->getParamCount(); ++i)
2080 {
2081 if(prevDec->getParam(i).type->getQualifier() != function->getParam(i).type->getQualifier())
2082 {
2083 error(location, "overloaded functions must have the same parameter qualifiers",
2084 function->getParam(i).type->getQualifierString());
2085 recover();
2086 }
2087 }
2088 }
2089
2090 //
2091 // Check for previously declared variables using the same name.
2092 //
2093 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
2094 if(prevSym)
2095 {
2096 if(!prevSym->isFunction())
2097 {
2098 error(location, "redefinition", function->getName().c_str(), "function");
2099 recover();
2100 }
2101 }
2102
2103 // We're at the inner scope level of the function's arguments and body statement.
2104 // Add the function prototype to the surrounding scope instead.
2105 symbolTable.getOuterLevel()->insert(*function);
2106
2107 //
2108 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2109 // variable names from this one, and not the one that's
2110 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2111 //
2112 return function;
2113}
2114
Alexis Hetue5246692015-06-18 12:34:52 -04002115TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
2116{
2117 TPublicType publicType = publicTypeIn;
2118 TOperator op = EOpNull;
2119 if(publicType.userDef)
2120 {
2121 op = EOpConstructStruct;
2122 }
2123 else
2124 {
Alexis Hetuec93b1d2016-12-09 16:01:29 -05002125 op = TypeToConstructorOperator(TType(publicType));
Alexis Hetue5246692015-06-18 12:34:52 -04002126 if(op == EOpNull)
2127 {
2128 error(publicType.line, "cannot construct this type", getBasicString(publicType.type));
2129 recover();
2130 publicType.type = EbtFloat;
2131 op = EOpConstructFloat;
2132 }
2133 }
2134
2135 TString tempString;
2136 TType type(publicType);
2137 return new TFunction(&tempString, type, op);
2138}
2139
John Bauman66b8ab22014-05-06 15:57:45 -04002140// This function is used to test for the correctness of the parameters passed to various constructor functions
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002141// and also convert them to the right datatype if it is allowed and required.
John Bauman66b8ab22014-05-06 15:57:45 -04002142//
2143// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
2144//
Alexis Hetufe1269e2015-06-16 12:43:32 -04002145TIntermTyped* TParseContext::addConstructor(TIntermNode* arguments, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -04002146{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002147 TIntermAggregate *aggregateArguments = arguments->getAsAggregate();
John Bauman66b8ab22014-05-06 15:57:45 -04002148
Nicolas Capens0bac2852016-05-07 06:09:58 -04002149 if(!aggregateArguments)
2150 {
2151 aggregateArguments = new TIntermAggregate;
2152 aggregateArguments->getSequence().push_back(arguments);
2153 }
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002154
Alexis Hetu2a198552016-09-27 20:50:45 -04002155 if(type->isArray())
2156 {
2157 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
2158 // the array.
2159 for(TIntermNode *&argNode : aggregateArguments->getSequence())
2160 {
2161 const TType &argType = argNode->getAsTyped()->getType();
2162 // It has already been checked that the argument is not an array.
2163 ASSERT(!argType.isArray());
2164 if(!argType.sameElementType(*type))
2165 {
2166 error(line, "Array constructor argument has an incorrect type", "Error");
Alexis Hetuf0005a12016-09-28 15:52:21 -04002167 return nullptr;
Alexis Hetu2a198552016-09-27 20:50:45 -04002168 }
2169 }
2170 }
2171 else if(op == EOpConstructStruct)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002172 {
2173 const TFieldList &fields = type->getStruct()->fields();
2174 TIntermSequence &args = aggregateArguments->getSequence();
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002175
Nicolas Capens0bac2852016-05-07 06:09:58 -04002176 for(size_t i = 0; i < fields.size(); i++)
2177 {
2178 if(args[i]->getAsTyped()->getType() != *fields[i]->type())
2179 {
2180 error(line, "Structure constructor arguments do not match structure fields", "Error");
2181 recover();
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002182
Alexis Hetuf0005a12016-09-28 15:52:21 -04002183 return nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002184 }
2185 }
2186 }
John Bauman66b8ab22014-05-06 15:57:45 -04002187
Nicolas Capens0bac2852016-05-07 06:09:58 -04002188 // Turn the argument list itself into a constructor
2189 TIntermAggregate *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line);
2190 TIntermTyped *constConstructor = foldConstConstructor(constructor, *type);
2191 if(constConstructor)
2192 {
2193 return constConstructor;
2194 }
John Bauman66b8ab22014-05-06 15:57:45 -04002195
Nicolas Capens0bac2852016-05-07 06:09:58 -04002196 return constructor;
John Bauman66b8ab22014-05-06 15:57:45 -04002197}
2198
2199TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
2200{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002201 aggrNode->setType(type);
2202 if (aggrNode->isConstantFoldable()) {
2203 bool returnVal = false;
2204 ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
2205 if (aggrNode->getSequence().size() == 1) {
2206 returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type, true);
2207 }
2208 else {
2209 returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type);
2210 }
2211 if (returnVal)
Alexis Hetuf0005a12016-09-28 15:52:21 -04002212 return nullptr;
John Bauman66b8ab22014-05-06 15:57:45 -04002213
Nicolas Capens0bac2852016-05-07 06:09:58 -04002214 return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
2215 }
John Bauman66b8ab22014-05-06 15:57:45 -04002216
Alexis Hetuf0005a12016-09-28 15:52:21 -04002217 return nullptr;
John Bauman66b8ab22014-05-06 15:57:45 -04002218}
2219
John Bauman66b8ab22014-05-06 15:57:45 -04002220//
2221// This function returns the tree representation for the vector field(s) being accessed from contant vector.
2222// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
2223// 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 -04002224// 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 -04002225// a constant matrix.
2226//
Alexis Hetufe1269e2015-06-16 12:43:32 -04002227TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -04002228{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002229 TIntermTyped* typedNode;
2230 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
John Bauman66b8ab22014-05-06 15:57:45 -04002231
Nicolas Capens0bac2852016-05-07 06:09:58 -04002232 ConstantUnion *unionArray;
2233 if (tempConstantNode) {
2234 unionArray = tempConstantNode->getUnionArrayPointer();
John Bauman66b8ab22014-05-06 15:57:45 -04002235
Nicolas Capens0bac2852016-05-07 06:09:58 -04002236 if (!unionArray) {
2237 return node;
2238 }
2239 } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
2240 error(line, "Cannot offset into the vector", "Error");
2241 recover();
John Bauman66b8ab22014-05-06 15:57:45 -04002242
Alexis Hetuf0005a12016-09-28 15:52:21 -04002243 return nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002244 }
John Bauman66b8ab22014-05-06 15:57:45 -04002245
Nicolas Capens0bac2852016-05-07 06:09:58 -04002246 ConstantUnion* constArray = new ConstantUnion[fields.num];
John Bauman66b8ab22014-05-06 15:57:45 -04002247
Alexis Hetub34591a2016-06-28 15:48:35 -04002248 int objSize = static_cast<int>(node->getType().getObjectSize());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002249 for (int i = 0; i < fields.num; i++) {
Alexis Hetub34591a2016-06-28 15:48:35 -04002250 if (fields.offsets[i] >= objSize) {
Nicolas Capens0bac2852016-05-07 06:09:58 -04002251 std::stringstream extraInfoStream;
2252 extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
2253 std::string extraInfo = extraInfoStream.str();
2254 error(line, "", "[", extraInfo.c_str());
2255 recover();
2256 fields.offsets[i] = 0;
2257 }
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002258
Nicolas Capens0bac2852016-05-07 06:09:58 -04002259 constArray[i] = unionArray[fields.offsets[i]];
John Bauman66b8ab22014-05-06 15:57:45 -04002260
Nicolas Capens0bac2852016-05-07 06:09:58 -04002261 }
2262 typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
2263 return typedNode;
John Bauman66b8ab22014-05-06 15:57:45 -04002264}
2265
2266//
2267// This function returns the column being accessed from a constant matrix. The values are retrieved from
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002268// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
2269// 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 -04002270// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
2271//
Alexis Hetufe1269e2015-06-16 12:43:32 -04002272TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -04002273{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002274 TIntermTyped* typedNode;
2275 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
John Bauman66b8ab22014-05-06 15:57:45 -04002276
Nicolas Capens0bac2852016-05-07 06:09:58 -04002277 if (index >= node->getType().getNominalSize()) {
2278 std::stringstream extraInfoStream;
2279 extraInfoStream << "matrix field selection out of range '" << index << "'";
2280 std::string extraInfo = extraInfoStream.str();
2281 error(line, "", "[", extraInfo.c_str());
2282 recover();
2283 index = 0;
2284 }
John Bauman66b8ab22014-05-06 15:57:45 -04002285
Nicolas Capens0bac2852016-05-07 06:09:58 -04002286 if (tempConstantNode) {
2287 ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
2288 int size = tempConstantNode->getType().getNominalSize();
2289 typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
2290 } else {
2291 error(line, "Cannot offset into the matrix", "Error");
2292 recover();
John Bauman66b8ab22014-05-06 15:57:45 -04002293
Alexis Hetuf0005a12016-09-28 15:52:21 -04002294 return nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002295 }
John Bauman66b8ab22014-05-06 15:57:45 -04002296
Nicolas Capens0bac2852016-05-07 06:09:58 -04002297 return typedNode;
John Bauman66b8ab22014-05-06 15:57:45 -04002298}
2299
2300
2301//
2302// 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 -04002303// the symbol table and parse-tree is built for the type of the element. The input
2304// 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 -04002305// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
2306//
Alexis Hetufe1269e2015-06-16 12:43:32 -04002307TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -04002308{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002309 TIntermTyped* typedNode;
2310 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
2311 TType arrayElementType = node->getType();
2312 arrayElementType.clearArrayness();
John Bauman66b8ab22014-05-06 15:57:45 -04002313
Nicolas Capens0bac2852016-05-07 06:09:58 -04002314 if (index >= node->getType().getArraySize()) {
2315 std::stringstream extraInfoStream;
2316 extraInfoStream << "array field selection out of range '" << index << "'";
2317 std::string extraInfo = extraInfoStream.str();
2318 error(line, "", "[", extraInfo.c_str());
2319 recover();
2320 index = 0;
2321 }
John Bauman66b8ab22014-05-06 15:57:45 -04002322
Nicolas Capens0bac2852016-05-07 06:09:58 -04002323 size_t arrayElementSize = arrayElementType.getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04002324
Nicolas Capens0bac2852016-05-07 06:09:58 -04002325 if (tempConstantNode) {
2326 ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
2327 typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
2328 } else {
2329 error(line, "Cannot offset into the array", "Error");
2330 recover();
John Bauman66b8ab22014-05-06 15:57:45 -04002331
Alexis Hetuf0005a12016-09-28 15:52:21 -04002332 return nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002333 }
John Bauman66b8ab22014-05-06 15:57:45 -04002334
Nicolas Capens0bac2852016-05-07 06:09:58 -04002335 return typedNode;
John Bauman66b8ab22014-05-06 15:57:45 -04002336}
2337
2338
2339//
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -04002340// This function returns the value of a particular field inside a constant structure from the symbol table.
John Bauman66b8ab22014-05-06 15:57:45 -04002341// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
2342// function and returns the parse-tree with the values of the embedded/nested struct.
2343//
Alexis Hetufe1269e2015-06-16 12:43:32 -04002344TIntermTyped* TParseContext::addConstStruct(const TString& identifier, TIntermTyped* node, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -04002345{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002346 const TFieldList &fields = node->getType().getStruct()->fields();
2347 TIntermTyped *typedNode;
2348 size_t instanceSize = 0;
2349 TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
John Bauman66b8ab22014-05-06 15:57:45 -04002350
Nicolas Capens0bac2852016-05-07 06:09:58 -04002351 for(size_t index = 0; index < fields.size(); ++index) {
2352 if (fields[index]->name() == identifier) {
2353 break;
2354 } else {
2355 instanceSize += fields[index]->type()->getObjectSize();
2356 }
2357 }
John Bauman66b8ab22014-05-06 15:57:45 -04002358
Nicolas Capens0bac2852016-05-07 06:09:58 -04002359 if (tempConstantNode) {
2360 ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
John Bauman66b8ab22014-05-06 15:57:45 -04002361
Nicolas Capens0bac2852016-05-07 06:09:58 -04002362 typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
2363 } else {
2364 error(line, "Cannot offset into the structure", "Error");
2365 recover();
John Bauman66b8ab22014-05-06 15:57:45 -04002366
Alexis Hetuf0005a12016-09-28 15:52:21 -04002367 return nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002368 }
John Bauman66b8ab22014-05-06 15:57:45 -04002369
Nicolas Capens0bac2852016-05-07 06:09:58 -04002370 return typedNode;
John Bauman66b8ab22014-05-06 15:57:45 -04002371}
2372
Alexis Hetuad6b8752015-06-09 16:15:30 -04002373//
Alexis Hetua35d8232015-06-11 17:11:06 -04002374// Interface/uniform blocks
2375//
2376TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList,
Nicolas Capens0bac2852016-05-07 06:09:58 -04002377 const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine)
Alexis Hetua35d8232015-06-11 17:11:06 -04002378{
2379 if(reservedErrorCheck(nameLine, blockName))
2380 recover();
2381
2382 if(typeQualifier.qualifier != EvqUniform)
2383 {
2384 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "interface blocks must be uniform");
2385 recover();
2386 }
2387
2388 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
2389 if(layoutLocationErrorCheck(typeQualifier.line, blockLayoutQualifier))
2390 {
2391 recover();
2392 }
2393
2394 if(blockLayoutQualifier.matrixPacking == EmpUnspecified)
2395 {
Alexis Hetu0a655842015-06-22 16:52:11 -04002396 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Alexis Hetua35d8232015-06-11 17:11:06 -04002397 }
2398
2399 if(blockLayoutQualifier.blockStorage == EbsUnspecified)
2400 {
Alexis Hetu0a655842015-06-22 16:52:11 -04002401 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Alexis Hetua35d8232015-06-11 17:11:06 -04002402 }
2403
2404 TSymbol* blockNameSymbol = new TSymbol(&blockName);
2405 if(!symbolTable.declare(*blockNameSymbol)) {
2406 error(nameLine, "redefinition", blockName.c_str(), "interface block name");
2407 recover();
2408 }
2409
2410 // check for sampler types and apply layout qualifiers
2411 for(size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) {
2412 TField* field = (*fieldList)[memberIndex];
2413 TType* fieldType = field->type();
2414 if(IsSampler(fieldType->getBasicType())) {
2415 error(field->line(), "unsupported type", fieldType->getBasicString(), "sampler types are not allowed in interface blocks");
2416 recover();
2417 }
2418
2419 const TQualifier qualifier = fieldType->getQualifier();
2420 switch(qualifier)
2421 {
2422 case EvqGlobal:
2423 case EvqUniform:
2424 break;
2425 default:
2426 error(field->line(), "invalid qualifier on interface block member", getQualifierString(qualifier));
2427 recover();
2428 break;
2429 }
2430
2431 // check layout qualifiers
2432 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
2433 if(layoutLocationErrorCheck(field->line(), fieldLayoutQualifier))
2434 {
2435 recover();
2436 }
2437
2438 if(fieldLayoutQualifier.blockStorage != EbsUnspecified)
2439 {
2440 error(field->line(), "invalid layout qualifier:", getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
2441 recover();
2442 }
2443
2444 if(fieldLayoutQualifier.matrixPacking == EmpUnspecified)
2445 {
2446 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
2447 }
2448 else if(!fieldType->isMatrix())
2449 {
2450 error(field->line(), "invalid layout qualifier:", getMatrixPackingString(fieldLayoutQualifier.matrixPacking), "can only be used on matrix types");
2451 recover();
2452 }
2453
2454 fieldType->setLayoutQualifier(fieldLayoutQualifier);
2455 }
2456
2457 // add array index
2458 int arraySize = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002459 if(arrayIndex)
Alexis Hetua35d8232015-06-11 17:11:06 -04002460 {
2461 if(arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize))
2462 recover();
2463 }
2464
2465 TInterfaceBlock* interfaceBlock = new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2466 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier, arraySize);
2467
2468 TString symbolName = "";
2469 int symbolId = 0;
2470
2471 if(!instanceName)
2472 {
2473 // define symbols for the members of the interface block
2474 for(size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2475 {
2476 TField* field = (*fieldList)[memberIndex];
2477 TType* fieldType = field->type();
2478
2479 // set parent pointer of the field variable
2480 fieldType->setInterfaceBlock(interfaceBlock);
2481
2482 TVariable* fieldVariable = new TVariable(&field->name(), *fieldType);
2483 fieldVariable->setQualifier(typeQualifier.qualifier);
2484
2485 if(!symbolTable.declare(*fieldVariable)) {
2486 error(field->line(), "redefinition", field->name().c_str(), "interface block member name");
2487 recover();
2488 }
2489 }
2490 }
2491 else
2492 {
2493 // add a symbol for this interface block
2494 TVariable* instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
2495 instanceTypeDef->setQualifier(typeQualifier.qualifier);
2496
2497 if(!symbolTable.declare(*instanceTypeDef)) {
2498 error(instanceLine, "redefinition", instanceName->c_str(), "interface block instance name");
2499 recover();
2500 }
2501
2502 symbolId = instanceTypeDef->getUniqueId();
2503 symbolName = instanceTypeDef->getName();
2504 }
2505
2506 TIntermAggregate *aggregate = intermediate.makeAggregate(intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line), nameLine);
2507 aggregate->setOp(EOpDeclaration);
2508
2509 exitStructDeclaration();
2510 return aggregate;
2511}
2512
2513//
Alexis Hetuad6b8752015-06-09 16:15:30 -04002514// Parse an array index expression
2515//
2516TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc &location, TIntermTyped *indexExpression)
2517{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002518 TIntermTyped *indexedExpression = nullptr;
Alexis Hetuad6b8752015-06-09 16:15:30 -04002519
2520 if(!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2521 {
2522 if(baseExpression->getAsSymbolNode())
2523 {
2524 error(location, " left of '[' is not of type array, matrix, or vector ",
2525 baseExpression->getAsSymbolNode()->getSymbol().c_str());
2526 }
2527 else
2528 {
2529 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2530 }
2531 recover();
2532 }
2533
2534 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2535
2536 if(indexExpression->getQualifier() == EvqConstExpr && indexConstantUnion)
2537 {
2538 int index = indexConstantUnion->getIConst(0);
2539 if(index < 0)
2540 {
2541 std::stringstream infoStream;
2542 infoStream << index;
2543 std::string info = infoStream.str();
2544 error(location, "negative index", info.c_str());
2545 recover();
2546 index = 0;
2547 }
2548 if(baseExpression->getType().getQualifier() == EvqConstExpr)
2549 {
2550 if(baseExpression->isArray())
2551 {
2552 // constant folding for arrays
2553 indexedExpression = addConstArrayNode(index, baseExpression, location);
2554 }
2555 else if(baseExpression->isVector())
2556 {
2557 // constant folding for vectors
2558 TVectorFields fields;
2559 fields.num = 1;
2560 fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
2561 indexedExpression = addConstVectorNode(fields, baseExpression, location);
2562 }
2563 else if(baseExpression->isMatrix())
2564 {
2565 // constant folding for matrices
2566 indexedExpression = addConstMatrixNode(index, baseExpression, location);
2567 }
2568 }
2569 else
2570 {
2571 int safeIndex = -1;
2572
2573 if(baseExpression->isArray())
2574 {
2575 if(index >= baseExpression->getType().getArraySize())
2576 {
2577 std::stringstream extraInfoStream;
2578 extraInfoStream << "array index out of range '" << index << "'";
2579 std::string extraInfo = extraInfoStream.str();
2580 error(location, "", "[", extraInfo.c_str());
2581 recover();
2582 safeIndex = baseExpression->getType().getArraySize() - 1;
2583 }
2584 }
2585 else if((baseExpression->isVector() || baseExpression->isMatrix()) &&
2586 baseExpression->getType().getNominalSize() <= index)
2587 {
2588 std::stringstream extraInfoStream;
2589 extraInfoStream << "field selection out of range '" << index << "'";
2590 std::string extraInfo = extraInfoStream.str();
2591 error(location, "", "[", extraInfo.c_str());
2592 recover();
2593 safeIndex = baseExpression->getType().getNominalSize() - 1;
2594 }
2595
2596 // Don't modify the data of the previous constant union, because it can point
2597 // to builtins, like gl_MaxDrawBuffers. Instead use a new sanitized object.
2598 if(safeIndex != -1)
2599 {
2600 ConstantUnion *safeConstantUnion = new ConstantUnion();
2601 safeConstantUnion->setIConst(safeIndex);
2602 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
2603 }
2604
2605 indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
2606 }
2607 }
2608 else
2609 {
2610 if(baseExpression->isInterfaceBlock())
2611 {
2612 error(location, "",
2613 "[", "array indexes for interface blocks arrays must be constant integral expressions");
2614 recover();
2615 }
Alexis Hetuad6b8752015-06-09 16:15:30 -04002616 else if(baseExpression->getQualifier() == EvqFragmentOut)
2617 {
2618 error(location, "", "[", "array indexes for fragment outputs must be constant integral expressions");
2619 recover();
2620 }
Alexis Hetuad6b8752015-06-09 16:15:30 -04002621
2622 indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
2623 }
2624
2625 if(indexedExpression == 0)
2626 {
2627 ConstantUnion *unionArray = new ConstantUnion[1];
2628 unionArray->setFConst(0.0f);
2629 indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConstExpr), location);
2630 }
2631 else if(baseExpression->isArray())
2632 {
2633 const TType &baseType = baseExpression->getType();
2634 if(baseType.getStruct())
2635 {
2636 TType copyOfType(baseType.getStruct());
2637 indexedExpression->setType(copyOfType);
2638 }
2639 else if(baseType.isInterfaceBlock())
2640 {
Alexis Hetu6c7ac3c2016-01-12 16:13:37 -05002641 TType copyOfType(baseType.getInterfaceBlock(), EvqTemporary, baseType.getLayoutQualifier(), 0);
Alexis Hetuad6b8752015-06-09 16:15:30 -04002642 indexedExpression->setType(copyOfType);
2643 }
2644 else
2645 {
2646 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
2647 EvqTemporary, static_cast<unsigned char>(baseExpression->getNominalSize()),
2648 static_cast<unsigned char>(baseExpression->getSecondarySize())));
2649 }
2650
2651 if(baseExpression->getType().getQualifier() == EvqConstExpr)
2652 {
2653 indexedExpression->getTypePointer()->setQualifier(EvqConstExpr);
2654 }
2655 }
2656 else if(baseExpression->isMatrix())
2657 {
2658 TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConstExpr ? EvqConstExpr : EvqTemporary;
2659 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
2660 qualifier, static_cast<unsigned char>(baseExpression->getSecondarySize())));
2661 }
2662 else if(baseExpression->isVector())
2663 {
2664 TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConstExpr ? EvqConstExpr : EvqTemporary;
2665 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
2666 }
2667 else
2668 {
2669 indexedExpression->setType(baseExpression->getType());
2670 }
2671
2672 return indexedExpression;
2673}
2674
2675TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc &dotLocation,
2676 const TString &fieldString, const TSourceLoc &fieldLocation)
2677{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002678 TIntermTyped *indexedExpression = nullptr;
Alexis Hetuad6b8752015-06-09 16:15:30 -04002679
2680 if(baseExpression->isArray())
2681 {
2682 error(fieldLocation, "cannot apply dot operator to an array", ".");
2683 recover();
2684 }
2685
2686 if(baseExpression->isVector())
2687 {
2688 TVectorFields fields;
2689 if(!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields, fieldLocation))
2690 {
2691 fields.num = 1;
2692 fields.offsets[0] = 0;
2693 recover();
2694 }
2695
Nicolas Capens0863f0d2016-04-10 00:30:02 -04002696 if(baseExpression->getAsConstantUnion())
Alexis Hetuad6b8752015-06-09 16:15:30 -04002697 {
2698 // constant folding for vector fields
2699 indexedExpression = addConstVectorNode(fields, baseExpression, fieldLocation);
2700 if(indexedExpression == 0)
2701 {
2702 recover();
2703 indexedExpression = baseExpression;
2704 }
2705 else
2706 {
2707 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
2708 EvqConstExpr, (unsigned char)(fieldString).size()));
2709 }
2710 }
2711 else
2712 {
2713 TString vectorString = fieldString;
2714 TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation);
2715 indexedExpression = intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation);
2716 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
Nicolas Capens341afbb2016-04-10 01:54:50 -04002717 baseExpression->getQualifier() == EvqConstExpr ? EvqConstExpr : EvqTemporary, (unsigned char)vectorString.size()));
Alexis Hetuad6b8752015-06-09 16:15:30 -04002718 }
2719 }
2720 else if(baseExpression->isMatrix())
2721 {
2722 TMatrixFields fields;
2723 if(!parseMatrixFields(fieldString, baseExpression->getNominalSize(), baseExpression->getSecondarySize(), fields, fieldLocation))
2724 {
2725 fields.wholeRow = false;
2726 fields.wholeCol = false;
2727 fields.row = 0;
2728 fields.col = 0;
2729 recover();
2730 }
2731
2732 if(fields.wholeRow || fields.wholeCol)
2733 {
2734 error(dotLocation, " non-scalar fields not implemented yet", ".");
2735 recover();
2736 ConstantUnion *unionArray = new ConstantUnion[1];
2737 unionArray->setIConst(0);
2738 TIntermTyped *index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr),
2739 fieldLocation);
2740 indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation);
2741 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
2742 EvqTemporary, static_cast<unsigned char>(baseExpression->getNominalSize()),
2743 static_cast<unsigned char>(baseExpression->getSecondarySize())));
2744 }
2745 else
2746 {
2747 ConstantUnion *unionArray = new ConstantUnion[1];
2748 unionArray->setIConst(fields.col * baseExpression->getSecondarySize() + fields.row);
2749 TIntermTyped *index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr),
2750 fieldLocation);
2751 indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation);
2752 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision()));
2753 }
2754 }
2755 else if(baseExpression->getBasicType() == EbtStruct)
2756 {
2757 bool fieldFound = false;
2758 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
2759 if(fields.empty())
2760 {
2761 error(dotLocation, "structure has no fields", "Internal Error");
2762 recover();
2763 indexedExpression = baseExpression;
2764 }
2765 else
2766 {
2767 unsigned int i;
2768 for(i = 0; i < fields.size(); ++i)
2769 {
2770 if(fields[i]->name() == fieldString)
2771 {
2772 fieldFound = true;
2773 break;
2774 }
2775 }
2776 if(fieldFound)
2777 {
2778 if(baseExpression->getType().getQualifier() == EvqConstExpr)
2779 {
2780 indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
2781 if(indexedExpression == 0)
2782 {
2783 recover();
2784 indexedExpression = baseExpression;
2785 }
2786 else
2787 {
2788 indexedExpression->setType(*fields[i]->type());
2789 // change the qualifier of the return type, not of the structure field
2790 // as the structure definition is shared between various structures.
2791 indexedExpression->getTypePointer()->setQualifier(EvqConstExpr);
2792 }
2793 }
2794 else
2795 {
Alexis Hetuec93b1d2016-12-09 16:01:29 -05002796 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
2797 index->setLine(fieldLocation);
Alexis Hetuad6b8752015-06-09 16:15:30 -04002798 indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index, dotLocation);
2799 indexedExpression->setType(*fields[i]->type());
2800 }
2801 }
2802 else
2803 {
2804 error(dotLocation, " no such field in structure", fieldString.c_str());
2805 recover();
2806 indexedExpression = baseExpression;
2807 }
2808 }
2809 }
2810 else if(baseExpression->isInterfaceBlock())
2811 {
2812 bool fieldFound = false;
2813 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
2814 if(fields.empty())
2815 {
2816 error(dotLocation, "interface block has no fields", "Internal Error");
2817 recover();
2818 indexedExpression = baseExpression;
2819 }
2820 else
2821 {
2822 unsigned int i;
2823 for(i = 0; i < fields.size(); ++i)
2824 {
2825 if(fields[i]->name() == fieldString)
2826 {
2827 fieldFound = true;
2828 break;
2829 }
2830 }
2831 if(fieldFound)
2832 {
2833 ConstantUnion *unionArray = new ConstantUnion[1];
2834 unionArray->setIConst(i);
2835 TIntermTyped *index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
2836 indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
2837 dotLocation);
2838 indexedExpression->setType(*fields[i]->type());
2839 }
2840 else
2841 {
2842 error(dotLocation, " no such field in interface block", fieldString.c_str());
2843 recover();
2844 indexedExpression = baseExpression;
2845 }
2846 }
2847 }
2848 else
2849 {
Alexis Hetu0a655842015-06-22 16:52:11 -04002850 if(mShaderVersion < 300)
Alexis Hetuad6b8752015-06-09 16:15:30 -04002851 {
2852 error(dotLocation, " field selection requires structure, vector, or matrix on left hand side",
2853 fieldString.c_str());
2854 }
2855 else
2856 {
2857 error(dotLocation,
2858 " field selection requires structure, vector, matrix, or interface block on left hand side",
2859 fieldString.c_str());
2860 }
2861 recover();
2862 indexedExpression = baseExpression;
2863 }
2864
2865 return indexedExpression;
2866}
2867
Nicolas Capens7d626792015-02-17 17:58:31 -05002868TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine)
2869{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002870 TLayoutQualifier qualifier;
Nicolas Capens7d626792015-02-17 17:58:31 -05002871
Nicolas Capens0bac2852016-05-07 06:09:58 -04002872 qualifier.location = -1;
Alexis Hetuad6b8752015-06-09 16:15:30 -04002873 qualifier.matrixPacking = EmpUnspecified;
2874 qualifier.blockStorage = EbsUnspecified;
Nicolas Capens7d626792015-02-17 17:58:31 -05002875
Alexis Hetuad6b8752015-06-09 16:15:30 -04002876 if(qualifierType == "shared")
2877 {
2878 qualifier.blockStorage = EbsShared;
2879 }
2880 else if(qualifierType == "packed")
2881 {
2882 qualifier.blockStorage = EbsPacked;
2883 }
2884 else if(qualifierType == "std140")
2885 {
2886 qualifier.blockStorage = EbsStd140;
2887 }
2888 else if(qualifierType == "row_major")
2889 {
2890 qualifier.matrixPacking = EmpRowMajor;
2891 }
2892 else if(qualifierType == "column_major")
2893 {
2894 qualifier.matrixPacking = EmpColumnMajor;
2895 }
2896 else if(qualifierType == "location")
Nicolas Capens0bac2852016-05-07 06:09:58 -04002897 {
2898 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "location requires an argument");
2899 recover();
2900 }
2901 else
2902 {
2903 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
2904 recover();
2905 }
Nicolas Capens7d626792015-02-17 17:58:31 -05002906
Nicolas Capens0bac2852016-05-07 06:09:58 -04002907 return qualifier;
Nicolas Capens7d626792015-02-17 17:58:31 -05002908}
2909
2910TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine)
2911{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002912 TLayoutQualifier qualifier;
Nicolas Capens7d626792015-02-17 17:58:31 -05002913
Nicolas Capens0bac2852016-05-07 06:09:58 -04002914 qualifier.location = -1;
2915 qualifier.matrixPacking = EmpUnspecified;
2916 qualifier.blockStorage = EbsUnspecified;
Nicolas Capens7d626792015-02-17 17:58:31 -05002917
Nicolas Capens0bac2852016-05-07 06:09:58 -04002918 if (qualifierType != "location")
2919 {
2920 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "only location may have arguments");
2921 recover();
2922 }
2923 else
2924 {
2925 // must check that location is non-negative
2926 if (intValue < 0)
2927 {
2928 error(intValueLine, "out of range:", intValueString.c_str(), "location must be non-negative");
2929 recover();
2930 }
2931 else
2932 {
2933 qualifier.location = intValue;
2934 }
2935 }
Nicolas Capens7d626792015-02-17 17:58:31 -05002936
Nicolas Capens0bac2852016-05-07 06:09:58 -04002937 return qualifier;
Nicolas Capens7d626792015-02-17 17:58:31 -05002938}
2939
2940TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier)
2941{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002942 TLayoutQualifier joinedQualifier = leftQualifier;
Nicolas Capens7d626792015-02-17 17:58:31 -05002943
Nicolas Capens0bac2852016-05-07 06:09:58 -04002944 if (rightQualifier.location != -1)
2945 {
2946 joinedQualifier.location = rightQualifier.location;
2947 }
Alexis Hetuad6b8752015-06-09 16:15:30 -04002948 if(rightQualifier.matrixPacking != EmpUnspecified)
2949 {
2950 joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
2951 }
2952 if(rightQualifier.blockStorage != EbsUnspecified)
2953 {
2954 joinedQualifier.blockStorage = rightQualifier.blockStorage;
2955 }
Nicolas Capens7d626792015-02-17 17:58:31 -05002956
Nicolas Capens0bac2852016-05-07 06:09:58 -04002957 return joinedQualifier;
Nicolas Capens7d626792015-02-17 17:58:31 -05002958}
2959
Alexis Hetu55a2cbc2015-04-16 10:49:45 -04002960
2961TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier,
2962 const TSourceLoc &storageLoc, TQualifier storageQualifier)
2963{
2964 TQualifier mergedQualifier = EvqSmoothIn;
2965
Alexis Hetu42ff6b12015-06-03 16:03:48 -04002966 if(storageQualifier == EvqFragmentIn) {
Alexis Hetu55a2cbc2015-04-16 10:49:45 -04002967 if(interpolationQualifier == EvqSmooth)
2968 mergedQualifier = EvqSmoothIn;
2969 else if(interpolationQualifier == EvqFlat)
2970 mergedQualifier = EvqFlatIn;
Nicolas Capens3713cd42015-06-22 10:41:54 -04002971 else UNREACHABLE(interpolationQualifier);
Alexis Hetu55a2cbc2015-04-16 10:49:45 -04002972 }
2973 else if(storageQualifier == EvqCentroidIn) {
2974 if(interpolationQualifier == EvqSmooth)
2975 mergedQualifier = EvqCentroidIn;
2976 else if(interpolationQualifier == EvqFlat)
2977 mergedQualifier = EvqFlatIn;
Nicolas Capens3713cd42015-06-22 10:41:54 -04002978 else UNREACHABLE(interpolationQualifier);
Alexis Hetu55a2cbc2015-04-16 10:49:45 -04002979 }
Alexis Hetu42ff6b12015-06-03 16:03:48 -04002980 else if(storageQualifier == EvqVertexOut) {
Alexis Hetu55a2cbc2015-04-16 10:49:45 -04002981 if(interpolationQualifier == EvqSmooth)
2982 mergedQualifier = EvqSmoothOut;
2983 else if(interpolationQualifier == EvqFlat)
2984 mergedQualifier = EvqFlatOut;
Nicolas Capens3713cd42015-06-22 10:41:54 -04002985 else UNREACHABLE(interpolationQualifier);
Alexis Hetu55a2cbc2015-04-16 10:49:45 -04002986 }
2987 else if(storageQualifier == EvqCentroidOut) {
2988 if(interpolationQualifier == EvqSmooth)
2989 mergedQualifier = EvqCentroidOut;
2990 else if(interpolationQualifier == EvqFlat)
2991 mergedQualifier = EvqFlatOut;
Nicolas Capens3713cd42015-06-22 10:41:54 -04002992 else UNREACHABLE(interpolationQualifier);
Alexis Hetu55a2cbc2015-04-16 10:49:45 -04002993 }
2994 else {
2995 error(interpolationLoc, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getQualifierString(interpolationQualifier));
2996 recover();
2997
2998 mergedQualifier = storageQualifier;
2999 }
3000
3001 TPublicType type;
3002 type.setBasic(EbtVoid, mergedQualifier, storageLoc);
3003 return type;
3004}
3005
Alexis Hetuad6b8752015-06-09 16:15:30 -04003006TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList)
3007{
Alexis Hetudd7ff7a2015-06-11 08:25:30 -04003008 if(voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type))
Alexis Hetuad6b8752015-06-09 16:15:30 -04003009 {
3010 recover();
3011 }
3012
3013 for(unsigned int i = 0; i < fieldList->size(); ++i)
3014 {
3015 //
3016 // Careful not to replace already known aspects of type, like array-ness
3017 //
3018 TType *type = (*fieldList)[i]->type();
3019 type->setBasicType(typeSpecifier.type);
3020 type->setNominalSize(typeSpecifier.primarySize);
3021 type->setSecondarySize(typeSpecifier.secondarySize);
3022 type->setPrecision(typeSpecifier.precision);
3023 type->setQualifier(typeSpecifier.qualifier);
3024 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
3025
3026 // don't allow arrays of arrays
3027 if(type->isArray())
3028 {
3029 if(arrayTypeErrorCheck(typeSpecifier.line, typeSpecifier))
3030 recover();
3031 }
3032 if(typeSpecifier.array)
3033 type->setArraySize(typeSpecifier.arraySize);
3034 if(typeSpecifier.userDef)
3035 {
3036 type->setStruct(typeSpecifier.userDef->getStruct());
3037 }
3038
3039 if(structNestingErrorCheck(typeSpecifier.line, *(*fieldList)[i]))
3040 {
3041 recover();
3042 }
3043 }
3044
3045 return fieldList;
3046}
3047
3048TPublicType TParseContext::addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine,
3049 const TString *structName, TFieldList *fieldList)
3050{
3051 TStructure *structure = new TStructure(structName, fieldList);
3052 TType *structureType = new TType(structure);
3053
3054 // Store a bool in the struct if we're at global scope, to allow us to
3055 // skip the local struct scoping workaround in HLSL.
3056 structure->setUniqueId(TSymbolTableLevel::nextUniqueId());
3057 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
3058
3059 if(!structName->empty())
3060 {
3061 if(reservedErrorCheck(nameLine, *structName))
3062 {
3063 recover();
3064 }
3065 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3066 if(!symbolTable.declare(*userTypeDef))
3067 {
3068 error(nameLine, "redefinition", structName->c_str(), "struct");
3069 recover();
3070 }
3071 }
3072
3073 // ensure we do not specify any storage qualifiers on the struct members
3074 for(unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
3075 {
3076 const TField &field = *(*fieldList)[typeListIndex];
3077 const TQualifier qualifier = field.type()->getQualifier();
3078 switch(qualifier)
3079 {
3080 case EvqGlobal:
3081 case EvqTemporary:
3082 break;
3083 default:
3084 error(field.line(), "invalid qualifier on struct member", getQualifierString(qualifier));
3085 recover();
3086 break;
3087 }
3088 }
3089
3090 TPublicType publicType;
3091 publicType.setBasic(EbtStruct, EvqTemporary, structLine);
3092 publicType.userDef = structureType;
3093 exitStructDeclaration();
3094
3095 return publicType;
3096}
3097
Alexis Hetufe1269e2015-06-16 12:43:32 -04003098bool TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString& identifier)
John Bauman66b8ab22014-05-06 15:57:45 -04003099{
Nicolas Capens0bac2852016-05-07 06:09:58 -04003100 ++mStructNestingLevel;
John Bauman66b8ab22014-05-06 15:57:45 -04003101
Nicolas Capens0bac2852016-05-07 06:09:58 -04003102 // Embedded structure definitions are not supported per GLSL ES spec.
3103 // They aren't allowed in GLSL either, but we need to detect this here
3104 // so we don't rely on the GLSL compiler to catch it.
3105 if (mStructNestingLevel > 1) {
3106 error(line, "", "Embedded struct definitions are not allowed");
3107 return true;
3108 }
John Bauman66b8ab22014-05-06 15:57:45 -04003109
Nicolas Capens0bac2852016-05-07 06:09:58 -04003110 return false;
John Bauman66b8ab22014-05-06 15:57:45 -04003111}
3112
3113void TParseContext::exitStructDeclaration()
3114{
Nicolas Capens0bac2852016-05-07 06:09:58 -04003115 --mStructNestingLevel;
John Bauman66b8ab22014-05-06 15:57:45 -04003116}
3117
Alexis Hetuad6b8752015-06-09 16:15:30 -04003118bool TParseContext::structNestingErrorCheck(const TSourceLoc &line, const TField &field)
3119{
3120 static const int kWebGLMaxStructNesting = 4;
3121
3122 if(field.type()->getBasicType() != EbtStruct)
3123 {
3124 return false;
3125 }
3126
3127 // We're already inside a structure definition at this point, so add
3128 // one to the field's struct nesting.
3129 if(1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
3130 {
3131 std::stringstream reasonStream;
3132 reasonStream << "Reference of struct type "
3133 << field.type()->getStruct()->name().c_str()
3134 << " exceeds maximum allowed nesting level of "
3135 << kWebGLMaxStructNesting;
3136 std::string reason = reasonStream.str();
3137 error(line, reason.c_str(), field.name().c_str(), "");
3138 return true;
3139 }
3140
3141 return false;
3142}
3143
3144TIntermTyped *TParseContext::createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc, const TType *funcReturnType)
3145{
3146 if(child == nullptr)
3147 {
3148 return nullptr;
3149 }
3150
3151 switch(op)
3152 {
3153 case EOpLogicalNot:
3154 if(child->getBasicType() != EbtBool ||
3155 child->isMatrix() ||
3156 child->isArray() ||
3157 child->isVector())
3158 {
3159 return nullptr;
3160 }
3161 break;
3162 case EOpBitwiseNot:
3163 if((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3164 child->isMatrix() ||
3165 child->isArray())
3166 {
3167 return nullptr;
3168 }
3169 break;
3170 case EOpPostIncrement:
3171 case EOpPreIncrement:
3172 case EOpPostDecrement:
3173 case EOpPreDecrement:
3174 case EOpNegative:
3175 if(child->getBasicType() == EbtStruct ||
3176 child->getBasicType() == EbtBool ||
3177 child->isArray())
3178 {
3179 return nullptr;
3180 }
3181 // Operators for built-ins are already type checked against their prototype.
3182 default:
3183 break;
3184 }
3185
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -04003186 return intermediate.addUnaryMath(op, child, loc, funcReturnType);
Alexis Hetuad6b8752015-06-09 16:15:30 -04003187}
3188
3189TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3190{
3191 TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
3192 if(node == nullptr)
3193 {
3194 unaryOpError(loc, getOperatorString(op), child->getCompleteString());
3195 recover();
3196 return child;
3197 }
3198 return node;
3199}
3200
3201TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3202{
3203 if(lValueErrorCheck(loc, getOperatorString(op), child))
3204 recover();
3205 return addUnaryMath(op, child, loc);
3206}
3207
3208bool TParseContext::binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
3209{
3210 if(left->isArray() || right->isArray())
3211 {
Alexis Hetu0a655842015-06-22 16:52:11 -04003212 if(mShaderVersion < 300)
Alexis Hetuad6b8752015-06-09 16:15:30 -04003213 {
3214 error(loc, "Invalid operation for arrays", getOperatorString(op));
3215 return false;
3216 }
3217
3218 if(left->isArray() != right->isArray())
3219 {
3220 error(loc, "array / non-array mismatch", getOperatorString(op));
3221 return false;
3222 }
3223
3224 switch(op)
3225 {
3226 case EOpEqual:
3227 case EOpNotEqual:
3228 case EOpAssign:
3229 case EOpInitialize:
3230 break;
3231 default:
3232 error(loc, "Invalid operation for arrays", getOperatorString(op));
3233 return false;
3234 }
3235 // At this point, size of implicitly sized arrays should be resolved.
3236 if(left->getArraySize() != right->getArraySize())
3237 {
3238 error(loc, "array size mismatch", getOperatorString(op));
3239 return false;
3240 }
3241 }
3242
3243 // Check ops which require integer / ivec parameters
3244 bool isBitShift = false;
3245 switch(op)
3246 {
3247 case EOpBitShiftLeft:
3248 case EOpBitShiftRight:
3249 case EOpBitShiftLeftAssign:
3250 case EOpBitShiftRightAssign:
3251 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3252 // check that the basic type is an integer type.
3253 isBitShift = true;
3254 if(!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3255 {
3256 return false;
3257 }
3258 break;
3259 case EOpBitwiseAnd:
3260 case EOpBitwiseXor:
3261 case EOpBitwiseOr:
3262 case EOpBitwiseAndAssign:
3263 case EOpBitwiseXorAssign:
3264 case EOpBitwiseOrAssign:
3265 // It is enough to check the type of only one operand, since later it
3266 // is checked that the operand types match.
3267 if(!IsInteger(left->getBasicType()))
3268 {
3269 return false;
3270 }
3271 break;
3272 default:
3273 break;
3274 }
3275
3276 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3277 // So the basic type should usually match.
3278 if(!isBitShift && left->getBasicType() != right->getBasicType())
3279 {
3280 return false;
3281 }
3282
3283 // Check that type sizes match exactly on ops that require that.
3284 // Also check restrictions for structs that contain arrays or samplers.
3285 switch(op)
3286 {
3287 case EOpAssign:
3288 case EOpInitialize:
3289 case EOpEqual:
3290 case EOpNotEqual:
3291 // ESSL 1.00 sections 5.7, 5.8, 5.9
Alexis Hetu0a655842015-06-22 16:52:11 -04003292 if(mShaderVersion < 300 && left->getType().isStructureContainingArrays())
Alexis Hetuad6b8752015-06-09 16:15:30 -04003293 {
3294 error(loc, "undefined operation for structs containing arrays", getOperatorString(op));
3295 return false;
3296 }
3297 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3298 // we interpret the spec so that this extends to structs containing samplers,
3299 // similarly to ESSL 1.00 spec.
Alexis Hetu0a655842015-06-22 16:52:11 -04003300 if((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
Alexis Hetuad6b8752015-06-09 16:15:30 -04003301 left->getType().isStructureContainingSamplers())
3302 {
3303 error(loc, "undefined operation for structs containing samplers", getOperatorString(op));
3304 return false;
3305 }
3306 case EOpLessThan:
3307 case EOpGreaterThan:
3308 case EOpLessThanEqual:
3309 case EOpGreaterThanEqual:
3310 if((left->getNominalSize() != right->getNominalSize()) ||
3311 (left->getSecondarySize() != right->getSecondarySize()))
3312 {
3313 return false;
3314 }
Alexis Hetuec93b1d2016-12-09 16:01:29 -05003315 break;
3316 case EOpAdd:
3317 case EOpSub:
3318 case EOpDiv:
3319 case EOpIMod:
3320 case EOpBitShiftLeft:
3321 case EOpBitShiftRight:
3322 case EOpBitwiseAnd:
3323 case EOpBitwiseXor:
3324 case EOpBitwiseOr:
3325 case EOpAddAssign:
3326 case EOpSubAssign:
3327 case EOpDivAssign:
3328 case EOpIModAssign:
3329 case EOpBitShiftLeftAssign:
3330 case EOpBitShiftRightAssign:
3331 case EOpBitwiseAndAssign:
3332 case EOpBitwiseXorAssign:
3333 case EOpBitwiseOrAssign:
3334 if((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
3335 {
3336 return false;
3337 }
3338
3339 // Are the sizes compatible?
3340 if(left->getNominalSize() != right->getNominalSize() || left->getSecondarySize() != right->getSecondarySize())
3341 {
3342 // If the nominal sizes of operands do not match:
3343 // One of them must be a scalar.
3344 if(!left->isScalar() && !right->isScalar())
3345 return false;
3346
3347 // In the case of compound assignment other than multiply-assign,
3348 // the right side needs to be a scalar. Otherwise a vector/matrix
3349 // would be assigned to a scalar. A scalar can't be shifted by a
3350 // vector either.
3351 if(!right->isScalar() && (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
3352 return false;
3353 }
3354 break;
Alexis Hetuad6b8752015-06-09 16:15:30 -04003355 default:
3356 break;
3357 }
3358
3359 return true;
3360}
3361
Alexis Hetu76a343a2015-06-04 17:21:22 -04003362TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc)
3363{
3364 TBasicType switchType = init->getBasicType();
3365 if((switchType != EbtInt && switchType != EbtUInt) ||
3366 init->isMatrix() ||
3367 init->isArray() ||
3368 init->isVector())
3369 {
3370 error(init->getLine(), "init-expression in a switch statement must be a scalar integer", "switch");
3371 recover();
3372 return nullptr;
3373 }
3374
3375 if(statementList)
3376 {
3377 if(!ValidateSwitch::validate(switchType, this, statementList, loc))
3378 {
3379 recover();
3380 return nullptr;
3381 }
3382 }
3383
3384 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3385 if(node == nullptr)
3386 {
3387 error(loc, "erroneous switch statement", "switch");
3388 recover();
3389 return nullptr;
3390 }
3391 return node;
3392}
3393
3394TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3395{
Alexis Hetu0a655842015-06-22 16:52:11 -04003396 if(mSwitchNestingLevel == 0)
Alexis Hetu76a343a2015-06-04 17:21:22 -04003397 {
3398 error(loc, "case labels need to be inside switch statements", "case");
3399 recover();
3400 return nullptr;
3401 }
3402 if(condition == nullptr)
3403 {
3404 error(loc, "case label must have a condition", "case");
3405 recover();
3406 return nullptr;
3407 }
3408 if((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
3409 condition->isMatrix() ||
3410 condition->isArray() ||
3411 condition->isVector())
3412 {
3413 error(condition->getLine(), "case label must be a scalar integer", "case");
3414 recover();
3415 }
3416 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
3417 if(conditionConst == nullptr)
3418 {
3419 error(condition->getLine(), "case label must be constant", "case");
3420 recover();
3421 }
3422 TIntermCase *node = intermediate.addCase(condition, loc);
3423 if(node == nullptr)
3424 {
3425 error(loc, "erroneous case statement", "case");
3426 recover();
3427 return nullptr;
3428 }
3429 return node;
3430}
3431
3432TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3433{
Alexis Hetu0a655842015-06-22 16:52:11 -04003434 if(mSwitchNestingLevel == 0)
Alexis Hetu76a343a2015-06-04 17:21:22 -04003435 {
3436 error(loc, "default labels need to be inside switch statements", "default");
3437 recover();
3438 return nullptr;
3439 }
3440 TIntermCase *node = intermediate.addCase(nullptr, loc);
3441 if(node == nullptr)
3442 {
3443 error(loc, "erroneous default statement", "default");
3444 recover();
3445 return nullptr;
3446 }
3447 return node;
3448}
Alexis Hetue5246692015-06-18 12:34:52 -04003449TIntermTyped *TParseContext::createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
3450{
3451 if(binaryOpCommonCheck(op, left, right, loc))
3452 {
3453 return intermediate.addAssign(op, left, right, loc);
3454 }
3455 return nullptr;
3456}
3457
3458TIntermTyped *TParseContext::addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
3459{
3460 TIntermTyped *node = createAssign(op, left, right, loc);
3461 if(node == nullptr)
3462 {
3463 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
3464 recover();
3465 return left;
3466 }
3467 return node;
3468}
Alexis Hetu76a343a2015-06-04 17:21:22 -04003469
Alexis Hetub4769582015-06-16 12:19:50 -04003470TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right,
3471 const TSourceLoc &loc)
3472{
3473 if(!binaryOpCommonCheck(op, left, right, loc))
3474 return nullptr;
3475
3476 switch(op)
3477 {
3478 case EOpEqual:
3479 case EOpNotEqual:
3480 break;
3481 case EOpLessThan:
3482 case EOpGreaterThan:
3483 case EOpLessThanEqual:
3484 case EOpGreaterThanEqual:
3485 ASSERT(!left->isArray() && !right->isArray());
3486 if(left->isMatrix() || left->isVector() ||
3487 left->getBasicType() == EbtStruct)
3488 {
3489 return nullptr;
3490 }
3491 break;
3492 case EOpLogicalOr:
3493 case EOpLogicalXor:
3494 case EOpLogicalAnd:
3495 ASSERT(!left->isArray() && !right->isArray());
3496 if(left->getBasicType() != EbtBool ||
3497 left->isMatrix() || left->isVector())
3498 {
3499 return nullptr;
3500 }
3501 break;
3502 case EOpAdd:
3503 case EOpSub:
3504 case EOpDiv:
3505 case EOpMul:
3506 ASSERT(!left->isArray() && !right->isArray());
3507 if(left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
3508 {
3509 return nullptr;
3510 }
3511 break;
3512 case EOpIMod:
3513 ASSERT(!left->isArray() && !right->isArray());
3514 // Note that this is only for the % operator, not for mod()
3515 if(left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
3516 {
3517 return nullptr;
3518 }
3519 break;
3520 // Note that for bitwise ops, type checking is done in promote() to
3521 // share code between ops and compound assignment
3522 default:
3523 break;
3524 }
3525
3526 return intermediate.addBinaryMath(op, left, right, loc);
3527}
3528
3529TIntermTyped *TParseContext::addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
3530{
3531 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
3532 if(node == 0)
3533 {
3534 binaryOpError(loc, getOperatorString(op), left->getCompleteString(), right->getCompleteString());
3535 recover();
3536 return left;
3537 }
3538 return node;
3539}
3540
3541TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
3542{
3543 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
3544 if(node == 0)
3545 {
3546 binaryOpError(loc, getOperatorString(op), left->getCompleteString(), right->getCompleteString());
3547 recover();
3548 ConstantUnion *unionArray = new ConstantUnion[1];
3549 unionArray->setBConst(false);
3550 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConstExpr), loc);
3551 }
3552 return node;
3553}
3554
Alexis Hetu76a343a2015-06-04 17:21:22 -04003555TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
3556{
3557 switch(op)
3558 {
3559 case EOpContinue:
Alexis Hetu0a655842015-06-22 16:52:11 -04003560 if(mLoopNestingLevel <= 0)
Alexis Hetu76a343a2015-06-04 17:21:22 -04003561 {
3562 error(loc, "continue statement only allowed in loops", "");
3563 recover();
3564 }
3565 break;
3566 case EOpBreak:
Alexis Hetu0a655842015-06-22 16:52:11 -04003567 if(mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
Alexis Hetu76a343a2015-06-04 17:21:22 -04003568 {
3569 error(loc, "break statement only allowed in loops and switch statements", "");
3570 recover();
3571 }
3572 break;
3573 case EOpReturn:
Alexis Hetu0a655842015-06-22 16:52:11 -04003574 if(mCurrentFunctionType->getBasicType() != EbtVoid)
Alexis Hetu76a343a2015-06-04 17:21:22 -04003575 {
3576 error(loc, "non-void function must return a value", "return");
3577 recover();
3578 }
3579 break;
3580 default:
3581 // No checks for discard
3582 break;
3583 }
3584 return intermediate.addBranch(op, loc);
3585}
3586
3587TIntermBranch *TParseContext::addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc)
3588{
3589 ASSERT(op == EOpReturn);
Alexis Hetu0a655842015-06-22 16:52:11 -04003590 mFunctionReturnsValue = true;
3591 if(mCurrentFunctionType->getBasicType() == EbtVoid)
Alexis Hetu76a343a2015-06-04 17:21:22 -04003592 {
3593 error(loc, "void function cannot return a value", "return");
3594 recover();
3595 }
Alexis Hetu0a655842015-06-22 16:52:11 -04003596 else if(*mCurrentFunctionType != returnValue->getType())
Alexis Hetu76a343a2015-06-04 17:21:22 -04003597 {
3598 error(loc, "function return is not matching type:", "return");
3599 recover();
3600 }
3601 return intermediate.addBranch(op, returnValue, loc);
3602}
3603
Alexis Hetub3ff42c2015-07-03 18:19:57 -04003604TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *paramNode, TIntermNode *thisNode, const TSourceLoc &loc, bool *fatalError)
3605{
3606 *fatalError = false;
3607 TOperator op = fnCall->getBuiltInOp();
3608 TIntermTyped *callNode = nullptr;
3609
3610 if(thisNode != nullptr)
3611 {
3612 ConstantUnion *unionArray = new ConstantUnion[1];
3613 int arraySize = 0;
3614 TIntermTyped *typedThis = thisNode->getAsTyped();
3615 if(fnCall->getName() != "length")
3616 {
3617 error(loc, "invalid method", fnCall->getName().c_str());
3618 recover();
3619 }
3620 else if(paramNode != nullptr)
3621 {
3622 error(loc, "method takes no parameters", "length");
3623 recover();
3624 }
3625 else if(typedThis == nullptr || !typedThis->isArray())
3626 {
3627 error(loc, "length can only be called on arrays", "length");
3628 recover();
3629 }
3630 else
3631 {
3632 arraySize = typedThis->getArraySize();
3633 if(typedThis->getAsSymbolNode() == nullptr)
3634 {
3635 // This code path can be hit with expressions like these:
3636 // (a = b).length()
3637 // (func()).length()
3638 // (int[3](0, 1, 2)).length()
3639 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid expression.
3640 // It allows "An array name with the length method applied" in contrast to GLSL 4.4 spec section 5.9
3641 // which allows "An array, vector or matrix expression with the length method applied".
3642 error(loc, "length can only be called on array names, not on array expressions", "length");
3643 recover();
3644 }
3645 }
3646 unionArray->setIConst(arraySize);
3647 callNode = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), loc);
3648 }
3649 else if(op != EOpNull)
3650 {
3651 //
3652 // Then this should be a constructor.
3653 // Don't go through the symbol table for constructors.
3654 // Their parameters will be verified algorithmically.
3655 //
3656 TType type(EbtVoid, EbpUndefined); // use this to get the type back
3657 if(!constructorErrorCheck(loc, paramNode, *fnCall, op, &type))
3658 {
3659 //
3660 // It's a constructor, of type 'type'.
3661 //
3662 callNode = addConstructor(paramNode, &type, op, fnCall, loc);
3663 }
3664
3665 if(callNode == nullptr)
3666 {
3667 recover();
3668 callNode = intermediate.setAggregateOperator(nullptr, op, loc);
3669 }
Alexis Hetub3ff42c2015-07-03 18:19:57 -04003670 }
3671 else
3672 {
3673 //
3674 // Not a constructor. Find it in the symbol table.
3675 //
3676 const TFunction *fnCandidate;
3677 bool builtIn;
3678 fnCandidate = findFunction(loc, fnCall, &builtIn);
3679 if(fnCandidate)
3680 {
3681 //
3682 // A declared function.
3683 //
3684 if(builtIn && !fnCandidate->getExtension().empty() &&
3685 extensionErrorCheck(loc, fnCandidate->getExtension()))
3686 {
3687 recover();
3688 }
3689 op = fnCandidate->getBuiltInOp();
3690 if(builtIn && op != EOpNull)
3691 {
3692 //
3693 // A function call mapped to a built-in operation.
3694 //
3695 if(fnCandidate->getParamCount() == 1)
3696 {
3697 //
3698 // Treat it like a built-in unary operator.
3699 //
3700 callNode = createUnaryMath(op, paramNode->getAsTyped(), loc, &fnCandidate->getReturnType());
3701 if(callNode == nullptr)
3702 {
3703 std::stringstream extraInfoStream;
3704 extraInfoStream << "built in unary operator function. Type: "
3705 << static_cast<TIntermTyped*>(paramNode)->getCompleteString();
3706 std::string extraInfo = extraInfoStream.str();
3707 error(paramNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
3708 *fatalError = true;
3709 return nullptr;
3710 }
3711 }
3712 else
3713 {
3714 TIntermAggregate *aggregate = intermediate.setAggregateOperator(paramNode, op, loc);
3715 aggregate->setType(fnCandidate->getReturnType());
3716
3717 // Some built-in functions have out parameters too.
3718 functionCallLValueErrorCheck(fnCandidate, aggregate);
3719
3720 callNode = aggregate;
Nicolas Capens91dfb972016-04-09 23:45:12 -04003721
3722 if(fnCandidate->getParamCount() == 2)
3723 {
3724 TIntermSequence &parameters = paramNode->getAsAggregate()->getSequence();
3725 TIntermTyped *left = parameters[0]->getAsTyped();
3726 TIntermTyped *right = parameters[1]->getAsTyped();
3727
3728 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
3729 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
3730 if (leftTempConstant && rightTempConstant)
3731 {
3732 TIntermTyped *typedReturnNode = leftTempConstant->fold(op, rightTempConstant, infoSink());
3733
3734 if(typedReturnNode)
3735 {
3736 callNode = typedReturnNode;
3737 }
3738 }
3739 }
Alexis Hetub3ff42c2015-07-03 18:19:57 -04003740 }
3741 }
3742 else
3743 {
3744 // This is a real function call
3745
3746 TIntermAggregate *aggregate = intermediate.setAggregateOperator(paramNode, EOpFunctionCall, loc);
3747 aggregate->setType(fnCandidate->getReturnType());
3748
3749 // this is how we know whether the given function is a builtIn function or a user defined function
3750 // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
3751 // if builtIn == true, it's definitely a builtIn function with EOpNull
3752 if(!builtIn)
3753 aggregate->setUserDefined();
3754 aggregate->setName(fnCandidate->getMangledName());
3755
3756 callNode = aggregate;
3757
3758 functionCallLValueErrorCheck(fnCandidate, aggregate);
3759 }
Alexis Hetub3ff42c2015-07-03 18:19:57 -04003760 }
3761 else
3762 {
3763 // error message was put out by findFunction()
3764 // Put on a dummy node for error recovery
3765 ConstantUnion *unionArray = new ConstantUnion[1];
3766 unionArray->setFConst(0.0f);
3767 callNode = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConstExpr), loc);
3768 recover();
3769 }
3770 }
3771 delete fnCall;
3772 return callNode;
3773}
3774
Alexis Hetueee212e2015-07-07 17:13:30 -04003775TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &loc)
3776{
3777 if(boolErrorCheck(loc, cond))
3778 recover();
3779
3780 if(trueBlock->getType() != falseBlock->getType())
3781 {
3782 binaryOpError(loc, ":", trueBlock->getCompleteString(), falseBlock->getCompleteString());
3783 recover();
3784 return falseBlock;
3785 }
3786 // ESSL1 sections 5.2 and 5.7:
3787 // ESSL3 section 5.7:
3788 // Ternary operator is not among the operators allowed for structures/arrays.
3789 if(trueBlock->isArray() || trueBlock->getBasicType() == EbtStruct)
3790 {
3791 error(loc, "ternary operator is not allowed for structures or arrays", ":");
3792 recover();
3793 return falseBlock;
3794 }
3795 return intermediate.addSelection(cond, trueBlock, falseBlock, loc);
3796}
3797
John Bauman66b8ab22014-05-06 15:57:45 -04003798//
3799// Parse an array of strings using yyparse.
3800//
3801// Returns 0 for success.
3802//
3803int PaParseStrings(int count, const char* const string[], const int length[],
Nicolas Capens0bac2852016-05-07 06:09:58 -04003804 TParseContext* context) {
3805 if ((count == 0) || !string)
3806 return 1;
John Bauman66b8ab22014-05-06 15:57:45 -04003807
Nicolas Capens0bac2852016-05-07 06:09:58 -04003808 if (glslang_initialize(context))
3809 return 1;
John Bauman66b8ab22014-05-06 15:57:45 -04003810
Nicolas Capens0bac2852016-05-07 06:09:58 -04003811 int error = glslang_scan(count, string, length, context);
3812 if (!error)
3813 error = glslang_parse(context);
John Bauman66b8ab22014-05-06 15:57:45 -04003814
Nicolas Capens0bac2852016-05-07 06:09:58 -04003815 glslang_finalize(context);
John Bauman66b8ab22014-05-06 15:57:45 -04003816
Nicolas Capens0bac2852016-05-07 06:09:58 -04003817 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
John Bauman66b8ab22014-05-06 15:57:45 -04003818}
3819
3820
3821