blob: 33ec5bb4c0852e32f15d3c8a760aecfe6ef8c391 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Jamie Madill6b9cb252013-10-17 10:45:47 -04007#include "compiler/translator/ParseContext.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +00008
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00009#include <stdarg.h>
apatrick@chromium.org8187fa82010-06-15 22:09:28 +000010#include <stdio.h>
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000011
daniel@transgaming.comb401a922012-10-26 18:58:24 +000012#include "compiler/preprocessor/SourceLocation.h"
Dmitry Skiba01971112015-07-10 14:54:00 -040013#include "compiler/translator/Cache.h"
Olli Etuahoac5274d2015-02-20 10:19:08 +020014#include "compiler/translator/glslang.h"
15#include "compiler/translator/ValidateSwitch.h"
Olli Etuahob0c645e2015-05-12 14:25:36 +030016#include "compiler/translator/ValidateGlobalInitializer.h"
Olli Etuaho37ad4742015-04-27 13:18:50 +030017#include "compiler/translator/util.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000018
alokp@chromium.org8b851c62012-06-15 16:25:11 +000019///////////////////////////////////////////////////////////////////////
20//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000021// Sub- vector and matrix fields
22//
23////////////////////////////////////////////////////////////////////////
24
25//
26// Look at a '.' field selector string and change it into offsets
27// for a vector.
28//
Jamie Madillb98c3a82015-07-23 14:26:04 -040029bool TParseContext::parseVectorFields(const TString &compString,
30 int vecSize,
31 TVectorFields &fields,
Arun Patole7e7e68d2015-05-22 12:02:25 +053032 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000033{
Jamie Madillb98c3a82015-07-23 14:26:04 -040034 fields.num = (int)compString.size();
Arun Patole7e7e68d2015-05-22 12:02:25 +053035 if (fields.num > 4)
36 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +000037 error(line, "illegal vector field selection", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +000038 return false;
39 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000040
Jamie Madillb98c3a82015-07-23 14:26:04 -040041 enum
42 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +000043 exyzw,
44 ergba,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +000045 estpq
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +000046 } fieldSet[4];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000047
Arun Patole7e7e68d2015-05-22 12:02:25 +053048 for (int i = 0; i < fields.num; ++i)
49 {
50 switch (compString[i])
51 {
Jamie Madillb98c3a82015-07-23 14:26:04 -040052 case 'x':
53 fields.offsets[i] = 0;
54 fieldSet[i] = exyzw;
55 break;
56 case 'r':
57 fields.offsets[i] = 0;
58 fieldSet[i] = ergba;
59 break;
60 case 's':
61 fields.offsets[i] = 0;
62 fieldSet[i] = estpq;
63 break;
64 case 'y':
65 fields.offsets[i] = 1;
66 fieldSet[i] = exyzw;
67 break;
68 case 'g':
69 fields.offsets[i] = 1;
70 fieldSet[i] = ergba;
71 break;
72 case 't':
73 fields.offsets[i] = 1;
74 fieldSet[i] = estpq;
75 break;
76 case 'z':
77 fields.offsets[i] = 2;
78 fieldSet[i] = exyzw;
79 break;
80 case 'b':
81 fields.offsets[i] = 2;
82 fieldSet[i] = ergba;
83 break;
84 case 'p':
85 fields.offsets[i] = 2;
86 fieldSet[i] = estpq;
87 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +053088
Jamie Madillb98c3a82015-07-23 14:26:04 -040089 case 'w':
90 fields.offsets[i] = 3;
91 fieldSet[i] = exyzw;
92 break;
93 case 'a':
94 fields.offsets[i] = 3;
95 fieldSet[i] = ergba;
96 break;
97 case 'q':
98 fields.offsets[i] = 3;
99 fieldSet[i] = estpq;
100 break;
101 default:
102 error(line, "illegal vector field selection", compString.c_str());
103 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000104 }
105 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000106
Arun Patole7e7e68d2015-05-22 12:02:25 +0530107 for (int i = 0; i < fields.num; ++i)
108 {
109 if (fields.offsets[i] >= vecSize)
110 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400111 error(line, "vector field selection out of range", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000112 return false;
113 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114
Arun Patole7e7e68d2015-05-22 12:02:25 +0530115 if (i > 0)
116 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400117 if (fieldSet[i] != fieldSet[i - 1])
Arun Patole7e7e68d2015-05-22 12:02:25 +0530118 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400119 error(line, "illegal - vector component fields not from the same set",
120 compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000121 return false;
122 }
123 }
124 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000126 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000127}
128
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129///////////////////////////////////////////////////////////////////////
130//
131// Errors
132//
133////////////////////////////////////////////////////////////////////////
134
135//
136// Track whether errors have occurred.
137//
138void TParseContext::recover()
139{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000140}
141
142//
143// Used by flex/bison to output all syntax and parsing errors.
144//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530145void TParseContext::error(const TSourceLoc &loc,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400146 const char *reason,
147 const char *token,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530148 const char *extraInfo)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149{
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000150 pp::SourceLocation srcLoc;
Jamie Madill075edd82013-07-08 13:30:19 -0400151 srcLoc.file = loc.first_file;
152 srcLoc.line = loc.first_line;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400153 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, srcLoc, reason, token, extraInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000154}
155
Arun Patole7e7e68d2015-05-22 12:02:25 +0530156void TParseContext::warning(const TSourceLoc &loc,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400157 const char *reason,
158 const char *token,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530159 const char *extraInfo)
160{
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000161 pp::SourceLocation srcLoc;
Jamie Madill075edd82013-07-08 13:30:19 -0400162 srcLoc.file = loc.first_file;
163 srcLoc.line = loc.first_line;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400164 mDiagnostics.writeInfo(pp::Diagnostics::PP_WARNING, srcLoc, reason, token, extraInfo);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +0000165}
166
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200167void TParseContext::outOfRangeError(bool isError,
168 const TSourceLoc &loc,
169 const char *reason,
170 const char *token,
171 const char *extraInfo)
172{
173 if (isError)
174 {
175 error(loc, reason, token, extraInfo);
176 recover();
177 }
178 else
179 {
180 warning(loc, reason, token, extraInfo);
181 }
182}
183
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000184//
185// Same error message for all places assignments don't work.
186//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530187void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000189 std::stringstream extraInfoStream;
190 extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
191 std::string extraInfo = extraInfoStream.str();
192 error(line, "", op, extraInfo.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000193}
194
195//
196// Same error message for all places unary operations don't work.
197//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530198void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000199{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000200 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400201 extraInfoStream << "no operation '" << op << "' exists that takes an operand of type "
202 << operand << " (or there is no acceptable conversion)";
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000203 std::string extraInfo = extraInfoStream.str();
204 error(line, " wrong operand type", op, extraInfo.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000205}
206
207//
208// Same error message for all binary operations don't work.
209//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400210void TParseContext::binaryOpError(const TSourceLoc &line,
211 const char *op,
212 TString left,
213 TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000214{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000215 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400216 extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '"
217 << left << "' and a right operand of type '" << right
218 << "' (or there is no acceptable conversion)";
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000219 std::string extraInfo = extraInfoStream.str();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530220 error(line, " wrong operand types ", op, extraInfo.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221}
222
Jamie Madillb98c3a82015-07-23 14:26:04 -0400223bool TParseContext::precisionErrorCheck(const TSourceLoc &line,
224 TPrecision precision,
225 TBasicType type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530226{
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400227 if (!mChecksPrecisionErrors)
zmo@google.comdc4b4f82011-06-17 00:42:53 +0000228 return false;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200229 if (precision == EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530230 {
Olli Etuaho183d7e22015-11-20 15:59:09 +0200231 switch (type)
232 {
233 case EbtFloat:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400234 error(line, "No precision specified for (float)", "");
235 return true;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200236 case EbtInt:
237 case EbtUInt:
238 UNREACHABLE(); // there's always a predeclared qualifier
Jamie Madillb98c3a82015-07-23 14:26:04 -0400239 error(line, "No precision specified (int)", "");
240 return true;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200241 default:
242 if (IsSampler(type))
243 {
244 error(line, "No precision specified (sampler)", "");
245 return true;
246 }
247 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000248 }
249 return false;
250}
251
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252//
253// Both test and if necessary, spit out an error, to see if the node is really
254// an l-value that can be operated on this way.
255//
256// Returns true if the was an error.
257//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530258bool TParseContext::lValueErrorCheck(const TSourceLoc &line, const char *op, TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400260 TIntermSymbol *symNode = node->getAsSymbolNode();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530261 TIntermBinary *binaryNode = node->getAsBinaryNode();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262
Arun Patole7e7e68d2015-05-22 12:02:25 +0530263 if (binaryNode)
264 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000265 bool errorReturn;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000266
Jamie Madillb98c3a82015-07-23 14:26:04 -0400267 switch (binaryNode->getOp())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530268 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400269 case EOpIndexDirect:
270 case EOpIndexIndirect:
271 case EOpIndexDirectStruct:
272 case EOpIndexDirectInterfaceBlock:
273 return lValueErrorCheck(line, op, binaryNode->getLeft());
274 case EOpVectorSwizzle:
275 errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
276 if (!errorReturn)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530277 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400278 int offset[4] = {0, 0, 0, 0};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279
Jamie Madillb98c3a82015-07-23 14:26:04 -0400280 TIntermTyped *rightNode = binaryNode->getRight();
281 TIntermAggregate *aggrNode = rightNode->getAsAggregate();
282
283 for (TIntermSequence::iterator p = aggrNode->getSequence()->begin();
284 p != aggrNode->getSequence()->end(); p++)
285 {
286 int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0);
287 offset[value]++;
288 if (offset[value] > 1)
289 {
290 error(line, " l-value of swizzle cannot have duplicate components", op);
291
292 return true;
293 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000294 }
295 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000296
Jamie Madillb98c3a82015-07-23 14:26:04 -0400297 return errorReturn;
298 default:
299 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000300 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000301 error(line, " l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000303 return true;
304 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000305
Arun Patole7e7e68d2015-05-22 12:02:25 +0530306 const char *symbol = 0;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000307 if (symNode != 0)
308 symbol = symNode->getSymbol().c_str();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000309
Arun Patole7e7e68d2015-05-22 12:02:25 +0530310 const char *message = 0;
311 switch (node->getQualifier())
312 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400313 case EvqConst:
314 message = "can't modify a const";
315 break;
316 case EvqConstReadOnly:
317 message = "can't modify a const";
318 break;
319 case EvqAttribute:
320 message = "can't modify an attribute";
321 break;
322 case EvqFragmentIn:
323 message = "can't modify an input";
324 break;
325 case EvqVertexIn:
326 message = "can't modify an input";
327 break;
328 case EvqUniform:
329 message = "can't modify a uniform";
330 break;
331 case EvqVaryingIn:
332 message = "can't modify a varying";
333 break;
334 case EvqFragCoord:
335 message = "can't modify gl_FragCoord";
336 break;
337 case EvqFrontFacing:
338 message = "can't modify gl_FrontFacing";
339 break;
340 case EvqPointCoord:
341 message = "can't modify gl_PointCoord";
342 break;
Martin Radevb0883602016-08-04 17:48:58 +0300343 case EvqNumWorkGroups:
344 message = "can't modify gl_NumWorkGroups";
345 break;
346 case EvqWorkGroupSize:
347 message = "can't modify gl_WorkGroupSize";
348 break;
349 case EvqWorkGroupID:
350 message = "can't modify gl_WorkGroupID";
351 break;
352 case EvqLocalInvocationID:
353 message = "can't modify gl_LocalInvocationID";
354 break;
355 case EvqGlobalInvocationID:
356 message = "can't modify gl_GlobalInvocationID";
357 break;
358 case EvqLocalInvocationIndex:
359 message = "can't modify gl_LocalInvocationIndex";
360 break;
Martin Radev802abe02016-08-04 17:48:32 +0300361 case EvqComputeIn:
362 message = "can't modify work group size variable";
363 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400364 default:
365 //
366 // Type that can't be written to?
367 //
368 if (node->getBasicType() == EbtVoid)
369 {
370 message = "can't modify void";
371 }
372 if (IsSampler(node->getBasicType()))
373 {
374 message = "can't modify a sampler";
375 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000376 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000377
Arun Patole7e7e68d2015-05-22 12:02:25 +0530378 if (message == 0 && binaryNode == 0 && symNode == 0)
379 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000380 error(line, " l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000381
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000382 return true;
383 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000384
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000385 //
386 // Everything else is okay, no error.
387 //
388 if (message == 0)
389 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000390
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000391 //
392 // If we get here, we have an error and a message.
393 //
Arun Patole7e7e68d2015-05-22 12:02:25 +0530394 if (symNode)
395 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000396 std::stringstream extraInfoStream;
397 extraInfoStream << "\"" << symbol << "\" (" << message << ")";
398 std::string extraInfo = extraInfoStream.str();
399 error(line, " l-value required", op, extraInfo.c_str());
400 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530401 else
402 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000403 std::stringstream extraInfoStream;
404 extraInfoStream << "(" << message << ")";
405 std::string extraInfo = extraInfoStream.str();
406 error(line, " l-value required", op, extraInfo.c_str());
407 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000408
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000409 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000410}
411
412//
413// Both test, and if necessary spit out an error, to see if the node is really
414// a constant.
415//
416// Returns true if the was an error.
417//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530418bool TParseContext::constErrorCheck(TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000419{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000420 if (node->getQualifier() == EvqConst)
421 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000422
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000423 error(node->getLine(), "constant expression required", "");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000424
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000425 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000426}
427
428//
429// Both test, and if necessary spit out an error, to see if the node is really
430// an integer.
431//
432// Returns true if the was an error.
433//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530434bool TParseContext::integerErrorCheck(TIntermTyped *node, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000435{
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000436 if (node->isScalarInt())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000437 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000438
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000439 error(node->getLine(), "integer expression required", token);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000440
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000441 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000442}
443
444//
445// Both test, and if necessary spit out an error, to see if we are currently
446// globally scoped.
447//
448// Returns true if the was an error.
449//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530450bool TParseContext::globalErrorCheck(const TSourceLoc &line, bool global, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000451{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000452 if (global)
453 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000454
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000455 error(line, "only allowed at global scope", token);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000456
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000457 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000458}
459
460//
461// For now, keep it simple: if it starts "gl_", it's reserved, independent
462// of scope. Except, if the symbol table is at the built-in push-level,
463// which is when we are parsing built-ins.
alokp@chromium.org613ef312010-07-21 18:54:22 +0000464// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
465// webgl shader.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000466//
467// Returns true if there was an error.
468//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530469bool TParseContext::reservedErrorCheck(const TSourceLoc &line, const TString &identifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000470{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530471 static const char *reservedErrMsg = "reserved built-in name";
472 if (!symbolTable.atBuiltInLevel())
473 {
474 if (identifier.compare(0, 3, "gl_") == 0)
475 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000476 error(line, reservedErrMsg, "gl_");
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000477 return true;
478 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530479 if (IsWebGLBasedSpec(mShaderSpec))
480 {
481 if (identifier.compare(0, 6, "webgl_") == 0)
482 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000483 error(line, reservedErrMsg, "webgl_");
alokp@chromium.org613ef312010-07-21 18:54:22 +0000484 return true;
485 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530486 if (identifier.compare(0, 7, "_webgl_") == 0)
487 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000488 error(line, reservedErrMsg, "_webgl_");
alokp@chromium.org613ef312010-07-21 18:54:22 +0000489 return true;
490 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530491 if (mShaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0)
492 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000493 error(line, reservedErrMsg, "css_");
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +0000494 return true;
495 }
alokp@chromium.org613ef312010-07-21 18:54:22 +0000496 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530497 if (identifier.find("__") != TString::npos)
498 {
499 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400500 "identifiers containing two consecutive underscores (__) are reserved as "
501 "possible future keywords",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530502 identifier.c_str());
daniel@transgaming.combeadd5d2012-04-12 02:35:31 +0000503 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000504 }
505 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000506
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000507 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508}
509
510//
511// Make sure there is enough data provided to the constructor to build
512// something of the type of the constructor. Also returns the type of
513// the constructor.
514//
515// Returns true if there was an error in construction.
516//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400517bool TParseContext::constructorErrorCheck(const TSourceLoc &line,
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200518 TIntermNode *argumentsNode,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400519 TFunction &function,
520 TOperator op,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530521 TType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000522{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000523 *type = function.getReturnType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000524
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000525 bool constructingMatrix = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400526 switch (op)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530527 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400528 case EOpConstructMat2:
529 case EOpConstructMat2x3:
530 case EOpConstructMat2x4:
531 case EOpConstructMat3x2:
532 case EOpConstructMat3:
533 case EOpConstructMat3x4:
534 case EOpConstructMat4x2:
535 case EOpConstructMat4x3:
536 case EOpConstructMat4:
537 constructingMatrix = true;
538 break;
539 default:
540 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000541 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000542
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000543 //
544 // Note: It's okay to have too many components available, but not okay to have unused
545 // arguments. 'full' will go to true when enough args have been seen. If we loop
546 // again, there is an extra argument, so 'overfull' will become true.
547 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000548
Jamie Madillb98c3a82015-07-23 14:26:04 -0400549 size_t size = 0;
550 bool constType = true;
551 bool full = false;
552 bool overFull = false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000553 bool matrixInMatrix = false;
554 bool arrayArg = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530555 for (size_t i = 0; i < function.getParamCount(); ++i)
556 {
Dmitry Skibaefa3d8e2015-06-22 14:52:10 -0700557 const TConstParameter &param = function.getParam(i);
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000558 size += param.type->getObjectSize();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530559
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000560 if (constructingMatrix && param.type->isMatrix())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000561 matrixInMatrix = true;
562 if (full)
563 overFull = true;
564 if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
565 full = true;
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000566 if (param.type->getQualifier() != EvqConst)
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000567 constType = false;
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000568 if (param.type->isArray())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000569 arrayArg = true;
570 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530571
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000572 if (constType)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000573 type->setQualifier(EvqConst);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000574
Olli Etuaho376f1b52015-04-13 13:23:41 +0300575 if (type->isArray())
576 {
577 if (type->isUnsizedArray())
578 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700579 type->setArraySize(static_cast<int>(function.getParamCount()));
Olli Etuaho376f1b52015-04-13 13:23:41 +0300580 }
581 else if (static_cast<size_t>(type->getArraySize()) != function.getParamCount())
582 {
583 error(line, "array constructor needs one argument per array element", "constructor");
584 return true;
585 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000586 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000587
Arun Patole7e7e68d2015-05-22 12:02:25 +0530588 if (arrayArg && op != EOpConstructStruct)
589 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000590 error(line, "constructing from a non-dereferenced array", "constructor");
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000591 return true;
592 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000593
Arun Patole7e7e68d2015-05-22 12:02:25 +0530594 if (matrixInMatrix && !type->isArray())
595 {
596 if (function.getParamCount() != 1)
597 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400598 error(line, "constructing matrix from matrix can only take one argument",
599 "constructor");
600 return true;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000601 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000602 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000603
Arun Patole7e7e68d2015-05-22 12:02:25 +0530604 if (overFull)
605 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000606 error(line, "too many arguments", "constructor");
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000607 return true;
608 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530609
Jamie Madillb98c3a82015-07-23 14:26:04 -0400610 if (op == EOpConstructStruct && !type->isArray() &&
611 type->getStruct()->fields().size() != function.getParamCount())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530612 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400613 error(line,
614 "Number of constructor parameters does not match the number of structure fields",
615 "constructor");
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000616 return true;
617 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000618
Arun Patole7e7e68d2015-05-22 12:02:25 +0530619 if (!type->isMatrix() || !matrixInMatrix)
620 {
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000621 if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
Arun Patole7e7e68d2015-05-22 12:02:25 +0530622 (op == EOpConstructStruct && size < type->getObjectSize()))
623 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000624 error(line, "not enough data provided for construction", "constructor");
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000625 return true;
626 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000627 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000628
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200629 if (argumentsNode == nullptr)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530630 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200631 error(line, "constructor does not have any arguments", "constructor");
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000632 return true;
633 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200634
635 TIntermAggregate *argumentsAgg = argumentsNode->getAsAggregate();
636 for (TIntermNode *&argNode : *argumentsAgg->getSequence())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530637 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200638 TIntermTyped *argTyped = argNode->getAsTyped();
639 ASSERT(argTyped != nullptr);
640 if (op != EOpConstructStruct && IsSampler(argTyped->getBasicType()))
641 {
642 error(line, "cannot convert a sampler", "constructor");
643 return true;
644 }
645 if (argTyped->getBasicType() == EbtVoid)
646 {
647 error(line, "cannot convert a void", "constructor");
648 return true;
649 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000650 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000651
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000652 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000653}
654
Jamie Madillb98c3a82015-07-23 14:26:04 -0400655// This function checks to see if a void variable has been declared and raise an error message for
656// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000657//
658// returns true in case of an error
659//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400660bool TParseContext::voidErrorCheck(const TSourceLoc &line,
661 const TString &identifier,
662 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000663{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300664 if (type == EbtVoid)
665 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000666 error(line, "illegal use of type 'void'", identifier.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000667 return true;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300668 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000669
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000670 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000671}
672
Jamie Madillb98c3a82015-07-23 14:26:04 -0400673// This function checks to see if the node (for the expression) contains a scalar boolean expression
674// or not
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000675//
676// returns true in case of an error
677//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530678bool TParseContext::boolErrorCheck(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000679{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530680 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
681 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000682 error(line, "boolean expression expected", "");
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000683 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530684 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000685
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000686 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000687}
688
Jamie Madillb98c3a82015-07-23 14:26:04 -0400689// This function checks to see if the node (for the expression) contains a scalar boolean expression
690// or not
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000691//
692// returns true in case of an error
693//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530694bool TParseContext::boolErrorCheck(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000695{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530696 if (pType.type != EbtBool || pType.isAggregate())
697 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000698 error(line, "boolean expression expected", "");
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000699 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530700 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000701
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000702 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000703}
704
Jamie Madillb98c3a82015-07-23 14:26:04 -0400705bool TParseContext::samplerErrorCheck(const TSourceLoc &line,
706 const TPublicType &pType,
707 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000708{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530709 if (pType.type == EbtStruct)
710 {
711 if (containsSampler(*pType.userDef))
712 {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000713 error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530714
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000715 return true;
716 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530717
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000718 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530719 }
720 else if (IsSampler(pType.type))
721 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000722 error(line, reason, getBasicString(pType.type));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000723
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000724 return true;
725 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000726
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000727 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000728}
729
Arun Patole7e7e68d2015-05-22 12:02:25 +0530730bool TParseContext::locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400731{
732 if (pType.layoutQualifier.location != -1)
733 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400734 error(line, "location must only be specified for a single input or output variable",
735 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400736 return true;
737 }
738
739 return false;
740}
741
Jamie Madillb98c3a82015-07-23 14:26:04 -0400742bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc &line,
743 TQualifier qualifier,
744 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000745{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400746 if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct &&
747 IsSampler(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530748 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000749 error(line, "samplers cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000750 return true;
751 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000752
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000753 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000754}
755
Arun Patole7e7e68d2015-05-22 12:02:25 +0530756bool TParseContext::containsSampler(const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000757{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000758 if (IsSampler(type.getBasicType()))
759 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000760
Arun Patole7e7e68d2015-05-22 12:02:25 +0530761 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock())
762 {
763 const TFieldList &fields = type.getStruct()->fields();
764 for (unsigned int i = 0; i < fields.size(); ++i)
765 {
Jamie Madill98493dd2013-07-08 14:39:03 -0400766 if (containsSampler(*fields[i]->type()))
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000767 return true;
768 }
769 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000770
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000771 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000772}
773
774//
775// Do size checking for an array type's size.
776//
777// Returns true if there was an error.
778//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530779bool TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *expr, int &size)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000780{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530781 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000782
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200783 // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
784 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
785 // fold as array size.
786 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000787 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000788 error(line, "array size must be a constant integer expression", "");
Olli Etuahoe7847b02015-03-16 11:56:12 +0200789 size = 1;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000790 return true;
791 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000792
Nicolas Capens906744a2014-06-06 15:18:07 -0400793 unsigned int unsignedSize = 0;
794
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000795 if (constant->getBasicType() == EbtUInt)
796 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400797 unsignedSize = constant->getUConst(0);
Jamie Madillb98c3a82015-07-23 14:26:04 -0400798 size = static_cast<int>(unsignedSize);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000799 }
800 else
801 {
802 size = constant->getIConst(0);
803
Nicolas Capens906744a2014-06-06 15:18:07 -0400804 if (size < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000805 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400806 error(line, "array size must be non-negative", "");
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000807 size = 1;
808 return true;
809 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400810
811 unsignedSize = static_cast<unsigned int>(size);
812 }
813
814 if (size == 0)
815 {
816 error(line, "array size must be greater than zero", "");
817 size = 1;
818 return true;
819 }
820
821 // The size of arrays is restricted here to prevent issues further down the
822 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
823 // 4096 registers so this should be reasonable even for aggressively optimizable code.
824 const unsigned int sizeLimit = 65536;
825
826 if (unsignedSize > sizeLimit)
827 {
828 error(line, "array size too large", "");
829 size = 1;
830 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000831 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000832
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000833 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000834}
835
836//
837// See if this qualifier can be an array.
838//
839// Returns true if there is an error.
840//
Olli Etuaho3739d232015-04-08 12:23:44 +0300841bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc &line, const TPublicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000842{
Olli Etuaho3739d232015-04-08 12:23:44 +0300843 if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) ||
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400844 (type.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +0300845 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400846 error(line, "cannot declare arrays of this qualifier",
847 TType(type).getCompleteString().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000848 return true;
849 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000850
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000851 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000852}
853
854//
855// See if this type can be an array.
856//
857// Returns true if there is an error.
858//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530859bool TParseContext::arrayTypeErrorCheck(const TSourceLoc &line, const TPublicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000860{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000861 //
862 // Can the type be an array?
863 //
Jamie Madill06145232015-05-13 13:10:01 -0400864 if (type.array)
865 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000866 error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000867 return true;
868 }
Olli Etuahocc36b982015-07-10 14:14:18 +0300869 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
870 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
871 // 4.3.4).
872 if (mShaderVersion >= 300 && type.type == EbtStruct && sh::IsVarying(type.qualifier))
873 {
874 error(line, "cannot declare arrays of structs of this qualifier",
875 TType(type).getCompleteString().c_str());
876 return true;
877 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000878
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000879 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000880}
881
882//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000883// Enforce non-initializer type/qualifier rules.
884//
885// Returns true if there was an error.
886//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400887bool TParseContext::nonInitErrorCheck(const TSourceLoc &line,
888 const TString &identifier,
889 TPublicType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000890{
Olli Etuaho3739d232015-04-08 12:23:44 +0300891 ASSERT(type != nullptr);
892 if (type->qualifier == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000893 {
894 // Make the qualifier make sense.
Olli Etuaho3739d232015-04-08 12:23:44 +0300895 type->qualifier = EvqTemporary;
896
897 // Generate informative error messages for ESSL1.
898 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400899 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000900 {
Arun Patole7e7e68d2015-05-22 12:02:25 +0530901 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400902 "structures containing arrays may not be declared constant since they cannot be "
903 "initialized",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530904 identifier.c_str());
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000905 }
906 else
907 {
908 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
909 }
910
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000911 return true;
912 }
Olli Etuaho376f1b52015-04-13 13:23:41 +0300913 if (type->isUnsizedArray())
914 {
915 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
916 return true;
917 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000918 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000919}
920
Olli Etuaho2935c582015-04-08 14:32:06 +0300921// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000922// and update the symbol table.
923//
Olli Etuaho2935c582015-04-08 14:32:06 +0300924// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000925//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400926bool TParseContext::declareVariable(const TSourceLoc &line,
927 const TString &identifier,
928 const TType &type,
Olli Etuaho2935c582015-04-08 14:32:06 +0300929 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000930{
Olli Etuaho2935c582015-04-08 14:32:06 +0300931 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000932
Olli Etuaho2935c582015-04-08 14:32:06 +0300933 bool needsReservedErrorCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000934
Olli Etuaho2935c582015-04-08 14:32:06 +0300935 // gl_LastFragData may be redeclared with a new precision qualifier
936 if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
937 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400938 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
939 symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Olli Etuaho2935c582015-04-08 14:32:06 +0300940 if (type.getArraySize() == maxDrawBuffers->getConstPointer()->getIConst())
941 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400942 if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +0300943 {
944 needsReservedErrorCheck = extensionErrorCheck(line, builtInSymbol->getExtension());
945 }
946 }
947 else
948 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400949 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
950 identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +0300951 return false;
952 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000953 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000954
Olli Etuaho2935c582015-04-08 14:32:06 +0300955 if (needsReservedErrorCheck && reservedErrorCheck(line, identifier))
956 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000957
Olli Etuaho2935c582015-04-08 14:32:06 +0300958 (*variable) = new TVariable(&identifier, type);
959 if (!symbolTable.declare(*variable))
960 {
961 error(line, "redefinition", identifier.c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -0400962 *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +0300963 return false;
964 }
965
966 if (voidErrorCheck(line, identifier, type.getBasicType()))
967 return false;
968
969 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000970}
971
Jamie Madillb98c3a82015-07-23 14:26:04 -0400972bool TParseContext::paramErrorCheck(const TSourceLoc &line,
973 TQualifier qualifier,
974 TQualifier paramQualifier,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530975 TType *type)
976{
977 if (qualifier != EvqConst && qualifier != EvqTemporary)
978 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000979 error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000980 return true;
981 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530982 if (qualifier == EvqConst && paramQualifier != EvqIn)
983 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400984 error(line, "qualifier not allowed with ", getQualifierString(qualifier),
985 getQualifierString(paramQualifier));
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000986 return true;
987 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000988
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000989 if (qualifier == EvqConst)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000990 type->setQualifier(EvqConstReadOnly);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000991 else
alokp@chromium.org58e54292010-08-24 21:40:03 +0000992 type->setQualifier(paramQualifier);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000993
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000994 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000995}
996
Arun Patole7e7e68d2015-05-22 12:02:25 +0530997bool TParseContext::extensionErrorCheck(const TSourceLoc &line, const TString &extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000998{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400999 const TExtensionBehavior &extBehavior = extensionBehavior();
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001000 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
Arun Patole7e7e68d2015-05-22 12:02:25 +05301001 if (iter == extBehavior.end())
1002 {
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001003 error(line, "extension", extension.c_str(), "is not supported");
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001004 return true;
1005 }
zmo@google.comf5450912011-09-09 01:37:19 +00001006 // In GLSL ES, an extension's default behavior is "disable".
Arun Patole7e7e68d2015-05-22 12:02:25 +05301007 if (iter->second == EBhDisable || iter->second == EBhUndefined)
1008 {
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001009 error(line, "extension", extension.c_str(), "is disabled");
1010 return true;
1011 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301012 if (iter->second == EBhWarn)
1013 {
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001014 warning(line, "extension", extension.c_str(), "is being used");
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001015 return false;
1016 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001017
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001018 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001019}
1020
Jamie Madillb98c3a82015-07-23 14:26:04 -04001021// These checks are common for all declarations starting a declarator list, and declarators that
1022// follow an empty declaration.
Olli Etuahofa33d582015-04-09 14:33:12 +03001023//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001024bool TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
1025 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -04001026{
Olli Etuahofa33d582015-04-09 14:33:12 +03001027 switch (publicType.qualifier)
1028 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001029 case EvqVaryingIn:
1030 case EvqVaryingOut:
1031 case EvqAttribute:
1032 case EvqVertexIn:
1033 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +03001034 case EvqComputeIn:
Jamie Madillb98c3a82015-07-23 14:26:04 -04001035 if (publicType.type == EbtStruct)
1036 {
1037 error(identifierLocation, "cannot be used with a structure",
1038 getQualifierString(publicType.qualifier));
1039 return true;
1040 }
Olli Etuahofa33d582015-04-09 14:33:12 +03001041
Jamie Madillb98c3a82015-07-23 14:26:04 -04001042 default:
1043 break;
Olli Etuahofa33d582015-04-09 14:33:12 +03001044 }
1045
Jamie Madillb98c3a82015-07-23 14:26:04 -04001046 if (publicType.qualifier != EvqUniform &&
1047 samplerErrorCheck(identifierLocation, publicType, "samplers must be uniform"))
Olli Etuahofa33d582015-04-09 14:33:12 +03001048 {
Jamie Madilla5efff92013-06-06 11:56:47 -04001049 return true;
Olli Etuahofa33d582015-04-09 14:33:12 +03001050 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001051
1052 // check for layout qualifier issues
1053 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
1054
1055 if (layoutQualifier.matrixPacking != EmpUnspecified)
1056 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001057 error(identifierLocation, "layout qualifier",
1058 getMatrixPackingString(layoutQualifier.matrixPacking),
Olli Etuahofa33d582015-04-09 14:33:12 +03001059 "only valid for interface blocks");
Jamie Madill51a53c72013-06-19 09:24:43 -04001060 return true;
Jamie Madilla5efff92013-06-06 11:56:47 -04001061 }
1062
1063 if (layoutQualifier.blockStorage != EbsUnspecified)
1064 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001065 error(identifierLocation, "layout qualifier",
1066 getBlockStorageString(layoutQualifier.blockStorage),
Olli Etuahofa33d582015-04-09 14:33:12 +03001067 "only valid for interface blocks");
Jamie Madill51a53c72013-06-19 09:24:43 -04001068 return true;
Jamie Madilla5efff92013-06-06 11:56:47 -04001069 }
1070
Olli Etuahofa33d582015-04-09 14:33:12 +03001071 if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut &&
1072 layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier))
Jamie Madilla5efff92013-06-06 11:56:47 -04001073 {
Jamie Madill51a53c72013-06-19 09:24:43 -04001074 return true;
Jamie Madilla5efff92013-06-06 11:56:47 -04001075 }
1076
1077 return false;
1078}
1079
Jamie Madillb98c3a82015-07-23 14:26:04 -04001080bool TParseContext::layoutLocationErrorCheck(const TSourceLoc &location,
1081 const TLayoutQualifier &layoutQualifier)
Jamie Madilla5efff92013-06-06 11:56:47 -04001082{
1083 if (layoutQualifier.location != -1)
1084 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001085 error(location, "invalid layout qualifier:", "location",
1086 "only valid on program inputs and outputs");
Jamie Madilla5efff92013-06-06 11:56:47 -04001087 return true;
1088 }
1089
1090 return false;
1091}
1092
Martin Radev802abe02016-08-04 17:48:32 +03001093void TParseContext::layoutSupportedErrorCheck(const TSourceLoc &location,
1094 const TString &layoutQualifierName,
1095 int versionRequired)
1096{
1097
1098 if (mShaderVersion < versionRequired)
1099 {
1100 error(location, "invalid layout qualifier:", layoutQualifierName.c_str(), "not supported");
1101 recover();
1102 }
1103}
1104
1105bool TParseContext::layoutWorkGroupSizeErrorCheck(const TSourceLoc &location,
1106 const TLayoutQualifier &layoutQualifier)
1107{
1108 const TLocalSize &localSize = layoutQualifier.localSize;
1109 for (size_t i = 0u; i < localSize.size(); ++i)
1110 {
1111 if (localSize[i] != -1)
1112 {
1113 error(location, "invalid layout qualifier:", getLocalSizeString(i),
1114 "only valid when used with 'in' in a compute shader global layout declaration");
1115 return true;
1116 }
1117 }
1118
1119 return false;
1120}
1121
Jamie Madillb98c3a82015-07-23 14:26:04 -04001122bool TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
1123 TIntermAggregate *aggregate)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001124{
1125 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1126 {
1127 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1128 if (qual == EvqOut || qual == EvqInOut)
1129 {
1130 TIntermTyped *node = (*(aggregate->getSequence()))[i]->getAsTyped();
1131 if (lValueErrorCheck(node->getLine(), "assign", node))
1132 {
1133 error(node->getLine(),
Jamie Madillb98c3a82015-07-23 14:26:04 -04001134 "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
Olli Etuahob6e07a62015-02-16 12:22:10 +02001135 recover();
1136 return true;
1137 }
1138 }
1139 }
1140 return false;
1141}
1142
Jamie Madillb98c3a82015-07-23 14:26:04 -04001143void TParseContext::es3InvariantErrorCheck(const TQualifier qualifier,
1144 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001145{
1146 if (!sh::IsVaryingOut(qualifier) && qualifier != EvqFragmentOut)
1147 {
1148 error(invariantLocation, "Only out variables can be invariant.", "invariant");
1149 recover();
1150 }
1151}
1152
Arun Patole7e7e68d2015-05-22 12:02:25 +05301153bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001154{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001155 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001156 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1157 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001158}
1159
Arun Patole7e7e68d2015-05-22 12:02:25 +05301160bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001161{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001162 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001163}
1164
Jamie Madillb98c3a82015-07-23 14:26:04 -04001165void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1166 const char *extName,
1167 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001168{
1169 pp::SourceLocation srcLoc;
1170 srcLoc.file = loc.first_file;
1171 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001172 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001173}
1174
Jamie Madillb98c3a82015-07-23 14:26:04 -04001175void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1176 const char *name,
1177 const char *value,
1178 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001179{
1180 pp::SourceLocation srcLoc;
1181 srcLoc.file = loc.first_file;
1182 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001183 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001184}
1185
Martin Radev802abe02016-08-04 17:48:32 +03001186TLocalSize TParseContext::getComputeShaderLocalSize() const
1187{
1188 TLocalSize result;
1189 for (size_t i = 0u; i < result.size(); ++i)
1190 {
1191 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1192 {
1193 result[i] = 1;
1194 }
1195 else
1196 {
1197 result[i] = mComputeShaderLocalSize[i];
1198 }
1199 }
1200 return result;
1201}
1202
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001203/////////////////////////////////////////////////////////////////////////////////
1204//
1205// Non-Errors.
1206//
1207/////////////////////////////////////////////////////////////////////////////////
1208
Jamie Madill5c097022014-08-20 16:38:32 -04001209const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1210 const TString *name,
1211 const TSymbol *symbol)
1212{
1213 const TVariable *variable = NULL;
1214
1215 if (!symbol)
1216 {
1217 error(location, "undeclared identifier", name->c_str());
1218 recover();
1219 }
1220 else if (!symbol->isVariable())
1221 {
1222 error(location, "variable expected", name->c_str());
1223 recover();
1224 }
1225 else
1226 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001227 variable = static_cast<const TVariable *>(symbol);
Jamie Madill5c097022014-08-20 16:38:32 -04001228
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001229 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
Jamie Madill5c097022014-08-20 16:38:32 -04001230 !variable->getExtension().empty() &&
1231 extensionErrorCheck(location, variable->getExtension()))
1232 {
1233 recover();
1234 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001235
1236 // Reject shaders using both gl_FragData and gl_FragColor
1237 TQualifier qualifier = variable->getType().getQualifier();
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001238 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001239 {
1240 mUsesFragData = true;
1241 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001242 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001243 {
1244 mUsesFragColor = true;
1245 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001246 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1247 {
1248 mUsesSecondaryOutputs = true;
1249 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001250
1251 // This validation is not quite correct - it's only an error to write to
1252 // both FragData and FragColor. For simplicity, and because users shouldn't
1253 // be rewarded for reading from undefined varaibles, return an error
1254 // if they are both referenced, rather than assigned.
1255 if (mUsesFragData && mUsesFragColor)
1256 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001257 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1258 if (mUsesSecondaryOutputs)
1259 {
1260 errorMessage =
1261 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1262 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1263 }
1264 error(location, errorMessage, name->c_str());
Jamie Madill14e95b32015-05-07 10:10:41 -04001265 recover();
1266 }
Martin Radevb0883602016-08-04 17:48:58 +03001267
1268 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1269 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1270 qualifier == EvqWorkGroupSize)
1271 {
1272 error(location,
1273 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1274 "gl_WorkGroupSize");
1275 }
Jamie Madill5c097022014-08-20 16:38:32 -04001276 }
1277
1278 if (!variable)
1279 {
1280 TType type(EbtFloat, EbpUndefined);
1281 TVariable *fakeVariable = new TVariable(name, type);
1282 symbolTable.declare(fakeVariable);
1283 variable = fakeVariable;
1284 }
1285
1286 return variable;
1287}
1288
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001289TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1290 const TString *name,
1291 const TSymbol *symbol)
1292{
1293 const TVariable *variable = getNamedVariable(location, name, symbol);
1294
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001295 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001296 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001297 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001298 return intermediate.addConstantUnion(constArray, variable->getType(), location);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001299 }
1300 else
1301 {
1302 return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
1303 variable->getType(), location);
1304 }
1305}
1306
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001307//
1308// Look up a function name in the symbol table, and make sure it is a function.
1309//
1310// Return the function symbol if found, otherwise 0.
1311//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001312const TFunction *TParseContext::findFunction(const TSourceLoc &line,
1313 TFunction *call,
1314 int inputShaderVersion,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301315 bool *builtIn)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001316{
alokp@chromium.org0a576182010-08-09 17:16:27 +00001317 // First find by unmangled name to check whether the function name has been
1318 // hidden by a variable name or struct typename.
Nicolas Capensd4a9b8d2013-07-18 11:01:22 -04001319 // If a function is found, check for one with a matching argument list.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301320 const TSymbol *symbol = symbolTable.find(call->getName(), inputShaderVersion, builtIn);
1321 if (symbol == 0 || symbol->isFunction())
1322 {
Austin Kinross3ae64652015-01-26 15:51:39 -08001323 symbol = symbolTable.find(call->getMangledName(), inputShaderVersion, builtIn);
alokp@chromium.org0a576182010-08-09 17:16:27 +00001324 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001325
Arun Patole7e7e68d2015-05-22 12:02:25 +05301326 if (symbol == 0)
1327 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001328 error(line, "no matching overloaded function found", call->getName().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001329 return 0;
1330 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001331
Arun Patole7e7e68d2015-05-22 12:02:25 +05301332 if (!symbol->isFunction())
1333 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001334 error(line, "function name expected", call->getName().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001335 return 0;
1336 }
alokp@chromium.org0a576182010-08-09 17:16:27 +00001337
Jamie Madillb98c3a82015-07-23 14:26:04 -04001338 return static_cast<const TFunction *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001339}
1340
1341//
1342// Initializers show up in several places in the grammar. Have one set of
1343// code to handle them here.
1344//
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001345// Returns true on error, false if no error
1346//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001347bool TParseContext::executeInitializer(const TSourceLoc &line,
1348 const TString &identifier,
1349 const TPublicType &pType,
1350 TIntermTyped *initializer,
1351 TIntermNode **intermNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001352{
Olli Etuahoe7847b02015-03-16 11:56:12 +02001353 ASSERT(intermNode != nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001354 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001355
Olli Etuaho2935c582015-04-08 14:32:06 +03001356 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001357 if (type.isUnsizedArray())
1358 {
1359 type.setArraySize(initializer->getArraySize());
1360 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001361 if (!declareVariable(line, identifier, type, &variable))
1362 {
1363 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001364 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001365
Olli Etuahob0c645e2015-05-12 14:25:36 +03001366 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001367 if (symbolTable.atGlobalLevel() &&
1368 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001369 {
1370 // Error message does not completely match behavior with ESSL 1.00, but
1371 // we want to steer developers towards only using constant expressions.
1372 error(line, "global variable initializers must be constant expressions", "=");
1373 return true;
1374 }
1375 if (globalInitWarning)
1376 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001377 warning(
1378 line,
1379 "global variable initializers should be constant expressions "
1380 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1381 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001382 }
1383
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001384 //
1385 // identifier must be of type constant, a global, or a temporary
1386 //
1387 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301388 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1389 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001390 error(line, " cannot initialize this type of qualifier ",
1391 variable->getType().getQualifierString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001392 return true;
1393 }
1394 //
1395 // test for and propagate constant
1396 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001397
Arun Patole7e7e68d2015-05-22 12:02:25 +05301398 if (qualifier == EvqConst)
1399 {
1400 if (qualifier != initializer->getType().getQualifier())
1401 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001402 std::stringstream extraInfoStream;
1403 extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
1404 std::string extraInfo = extraInfoStream.str();
1405 error(line, " assigning non-constant to", "=", extraInfo.c_str());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001406 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001407 return true;
1408 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301409 if (type != initializer->getType())
1410 {
1411 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001412 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001413 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001414 return true;
1415 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001416
1417 // Save the constant folded value to the variable if possible. For example array
1418 // initializers are not folded, since that way copying the array literal to multiple places
1419 // in the shader is avoided.
1420 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1421 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301422 if (initializer->getAsConstantUnion())
1423 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001424 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001425 *intermNode = nullptr;
1426 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301427 }
1428 else if (initializer->getAsSymbolNode())
1429 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001430 const TSymbol *symbol =
1431 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1432 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001433
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001434 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001435 if (constArray)
1436 {
1437 variable->shareConstPointer(constArray);
1438 *intermNode = nullptr;
1439 return false;
1440 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001441 }
1442 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001443
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001444 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1445 variable->getUniqueId(), variable->getName(), variable->getType(), line);
1446 *intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1447 if (*intermNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001448 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001449 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1450 return true;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001451 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001452
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001453 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001454}
1455
Jamie Madillb98c3a82015-07-23 14:26:04 -04001456TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier,
1457 bool invariant,
1458 TLayoutQualifier layoutQualifier,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301459 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001460{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001461 TPublicType returnType = typeSpecifier;
1462 returnType.qualifier = qualifier;
1463 returnType.invariant = invariant;
Jamie Madilla5efff92013-06-06 11:56:47 -04001464 returnType.layoutQualifier = layoutQualifier;
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001465
Martin Radev802abe02016-08-04 17:48:32 +03001466 if (layoutWorkGroupSizeErrorCheck(typeSpecifier.line, layoutQualifier))
1467 {
1468 recover();
1469 }
1470
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001471 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001472 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001473 if (typeSpecifier.array)
1474 {
1475 error(typeSpecifier.line, "not supported", "first-class array");
1476 recover();
1477 returnType.clearArrayness();
1478 }
1479
Jamie Madillb98c3a82015-07-23 14:26:04 -04001480 if (qualifier == EvqAttribute &&
1481 (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001482 {
1483 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
1484 recover();
1485 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001486
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001487 if ((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
1488 (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
1489 {
1490 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
1491 recover();
1492 }
1493 }
1494 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001495 {
Olli Etuahoabb0c382015-07-13 12:01:12 +03001496 if (!layoutQualifier.isEmpty())
1497 {
1498 if (globalErrorCheck(typeSpecifier.line, symbolTable.atGlobalLevel(), "layout"))
1499 {
1500 recover();
1501 }
1502 }
Olli Etuahocc36b982015-07-10 14:14:18 +03001503 if (sh::IsVarying(qualifier) || qualifier == EvqVertexIn || qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001504 {
Olli Etuahocc36b982015-07-10 14:14:18 +03001505 es3InputOutputTypeCheck(qualifier, typeSpecifier, typeSpecifier.line);
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001506 }
Martin Radev802abe02016-08-04 17:48:32 +03001507 if (qualifier == EvqComputeIn)
1508 {
1509 error(typeSpecifier.line, "'in' can be only used to specify the local group size",
1510 "in");
1511 recover();
1512 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001513 }
1514
1515 return returnType;
1516}
1517
Olli Etuahocc36b982015-07-10 14:14:18 +03001518void TParseContext::es3InputOutputTypeCheck(const TQualifier qualifier,
1519 const TPublicType &type,
1520 const TSourceLoc &qualifierLocation)
1521{
1522 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
1523 if (type.type == EbtBool)
1524 {
1525 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
1526 recover();
1527 }
1528
1529 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1530 switch (qualifier)
1531 {
1532 case EvqVertexIn:
1533 // ESSL 3.00 section 4.3.4
1534 if (type.array)
1535 {
1536 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
1537 recover();
1538 }
1539 // Vertex inputs with a struct type are disallowed in singleDeclarationErrorCheck
1540 return;
1541 case EvqFragmentOut:
1542 // ESSL 3.00 section 4.3.6
1543 if (type.isMatrix())
1544 {
1545 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
1546 recover();
1547 }
1548 // Fragment outputs with a struct type are disallowed in singleDeclarationErrorCheck
1549 return;
1550 default:
1551 break;
1552 }
1553
1554 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1555 // restrictions.
1556 bool typeContainsIntegers =
1557 (type.type == EbtInt || type.type == EbtUInt || type.isStructureContainingType(EbtInt) ||
1558 type.isStructureContainingType(EbtUInt));
1559 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1560 {
1561 error(qualifierLocation, "must use 'flat' interpolation here",
1562 getQualifierString(qualifier));
1563 recover();
1564 }
1565
1566 if (type.type == EbtStruct)
1567 {
1568 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1569 // These restrictions are only implied by the ESSL 3.00 spec, but
1570 // the ESSL 3.10 spec lists these restrictions explicitly.
1571 if (type.array)
1572 {
1573 error(qualifierLocation, "cannot be an array of structures",
1574 getQualifierString(qualifier));
1575 recover();
1576 }
1577 if (type.isStructureContainingArrays())
1578 {
1579 error(qualifierLocation, "cannot be a structure containing an array",
1580 getQualifierString(qualifier));
1581 recover();
1582 }
1583 if (type.isStructureContainingType(EbtStruct))
1584 {
1585 error(qualifierLocation, "cannot be a structure containing a structure",
1586 getQualifierString(qualifier));
1587 recover();
1588 }
1589 if (type.isStructureContainingType(EbtBool))
1590 {
1591 error(qualifierLocation, "cannot be a structure containing a bool",
1592 getQualifierString(qualifier));
1593 recover();
1594 }
1595 }
1596}
1597
Olli Etuahofa33d582015-04-09 14:33:12 +03001598TIntermAggregate *TParseContext::parseSingleDeclaration(TPublicType &publicType,
1599 const TSourceLoc &identifierOrTypeLocation,
1600 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04001601{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001602 TIntermSymbol *symbol =
1603 intermediate.addSymbol(0, identifier, TType(publicType), identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001604
Olli Etuahobab4c082015-04-24 16:38:49 +03001605 bool emptyDeclaration = (identifier == "");
Olli Etuahofa33d582015-04-09 14:33:12 +03001606
Olli Etuahobab4c082015-04-24 16:38:49 +03001607 mDeferredSingleDeclarationErrorCheck = emptyDeclaration;
1608
1609 if (emptyDeclaration)
1610 {
1611 if (publicType.isUnsizedArray())
1612 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001613 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1614 // error. It is assumed that this applies to empty declarations as well.
1615 error(identifierOrTypeLocation, "empty array declaration needs to specify a size",
1616 identifier.c_str());
Olli Etuahobab4c082015-04-24 16:38:49 +03001617 }
1618 }
1619 else
Jamie Madill60ed9812013-06-06 11:56:46 -04001620 {
Olli Etuahofa33d582015-04-09 14:33:12 +03001621 if (singleDeclarationErrorCheck(publicType, identifierOrTypeLocation))
Jamie Madill60ed9812013-06-06 11:56:46 -04001622 recover();
1623
Olli Etuaho376f1b52015-04-13 13:23:41 +03001624 if (nonInitErrorCheck(identifierOrTypeLocation, identifier, &publicType))
Jamie Madill60ed9812013-06-06 11:56:46 -04001625 recover();
1626
Olli Etuaho2935c582015-04-08 14:32:06 +03001627 TVariable *variable = nullptr;
Olli Etuahofa33d582015-04-09 14:33:12 +03001628 if (!declareVariable(identifierOrTypeLocation, identifier, TType(publicType), &variable))
Jamie Madill60ed9812013-06-06 11:56:46 -04001629 recover();
1630
1631 if (variable && symbol)
Jamie Madill60ed9812013-06-06 11:56:46 -04001632 symbol->setId(variable->getUniqueId());
Jamie Madill60ed9812013-06-06 11:56:46 -04001633 }
1634
Olli Etuahoe7847b02015-03-16 11:56:12 +02001635 return intermediate.makeAggregate(symbol, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001636}
1637
Olli Etuahoe7847b02015-03-16 11:56:12 +02001638TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1639 const TSourceLoc &identifierLocation,
1640 const TString &identifier,
1641 const TSourceLoc &indexLocation,
1642 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04001643{
Olli Etuahofa33d582015-04-09 14:33:12 +03001644 mDeferredSingleDeclarationErrorCheck = false;
1645
1646 if (singleDeclarationErrorCheck(publicType, identifierLocation))
Jamie Madill60ed9812013-06-06 11:56:46 -04001647 recover();
1648
Olli Etuaho376f1b52015-04-13 13:23:41 +03001649 if (nonInitErrorCheck(identifierLocation, identifier, &publicType))
Jamie Madill60ed9812013-06-06 11:56:46 -04001650 recover();
1651
Jamie Madillb98c3a82015-07-23 14:26:04 -04001652 if (arrayTypeErrorCheck(indexLocation, publicType) ||
1653 arrayQualifierErrorCheck(indexLocation, publicType))
Jamie Madill60ed9812013-06-06 11:56:46 -04001654 {
1655 recover();
1656 }
1657
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001658 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001659
1660 int size;
1661 if (arraySizeErrorCheck(identifierLocation, indexExpression, size))
1662 {
1663 recover();
1664 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001665 // Make the type an array even if size check failed.
1666 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1667 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04001668
Olli Etuaho2935c582015-04-08 14:32:06 +03001669 TVariable *variable = nullptr;
1670 if (!declareVariable(identifierLocation, identifier, arrayType, &variable))
Jamie Madill60ed9812013-06-06 11:56:46 -04001671 recover();
1672
Olli Etuahoe7847b02015-03-16 11:56:12 +02001673 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001674 if (variable && symbol)
Jamie Madill60ed9812013-06-06 11:56:46 -04001675 symbol->setId(variable->getUniqueId());
Jamie Madill60ed9812013-06-06 11:56:46 -04001676
Olli Etuahoe7847b02015-03-16 11:56:12 +02001677 return intermediate.makeAggregate(symbol, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001678}
1679
Jamie Madill06145232015-05-13 13:10:01 -04001680TIntermAggregate *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
Olli Etuahoe7847b02015-03-16 11:56:12 +02001681 const TSourceLoc &identifierLocation,
1682 const TString &identifier,
1683 const TSourceLoc &initLocation,
1684 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04001685{
Olli Etuahofa33d582015-04-09 14:33:12 +03001686 mDeferredSingleDeclarationErrorCheck = false;
1687
1688 if (singleDeclarationErrorCheck(publicType, identifierLocation))
Jamie Madill60ed9812013-06-06 11:56:46 -04001689 recover();
1690
Olli Etuahoe7847b02015-03-16 11:56:12 +02001691 TIntermNode *intermNode = nullptr;
1692 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04001693 {
1694 //
1695 // Build intermediate representation
1696 //
Olli Etuahoe7847b02015-03-16 11:56:12 +02001697 return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : nullptr;
Jamie Madill60ed9812013-06-06 11:56:46 -04001698 }
1699 else
1700 {
1701 recover();
Olli Etuahoe7847b02015-03-16 11:56:12 +02001702 return nullptr;
Jamie Madill60ed9812013-06-06 11:56:46 -04001703 }
1704}
1705
Jamie Madillb98c3a82015-07-23 14:26:04 -04001706TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration(
1707 TPublicType &publicType,
1708 const TSourceLoc &identifierLocation,
1709 const TString &identifier,
1710 const TSourceLoc &indexLocation,
1711 TIntermTyped *indexExpression,
1712 const TSourceLoc &initLocation,
1713 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001714{
1715 mDeferredSingleDeclarationErrorCheck = false;
1716
1717 if (singleDeclarationErrorCheck(publicType, identifierLocation))
1718 recover();
1719
Jamie Madillb98c3a82015-07-23 14:26:04 -04001720 if (arrayTypeErrorCheck(indexLocation, publicType) ||
1721 arrayQualifierErrorCheck(indexLocation, publicType))
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001722 {
1723 recover();
1724 }
1725
1726 TPublicType arrayType(publicType);
1727
Olli Etuaho376f1b52015-04-13 13:23:41 +03001728 int size = 0;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001729 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
1730 // the initializer.
1731 if (indexExpression != nullptr &&
1732 arraySizeErrorCheck(identifierLocation, indexExpression, size))
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001733 {
1734 recover();
1735 }
1736 // Make the type an array even if size check failed.
1737 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1738 arrayType.setArraySize(size);
1739
1740 // initNode will correspond to the whole of "type b[n] = initializer".
1741 TIntermNode *initNode = nullptr;
1742 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
1743 {
1744 return initNode ? intermediate.makeAggregate(initNode, initLocation) : nullptr;
1745 }
1746 else
1747 {
1748 recover();
1749 return nullptr;
1750 }
1751}
1752
Olli Etuahoe7847b02015-03-16 11:56:12 +02001753TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc,
Jamie Madill47e3ec02014-08-20 16:38:33 -04001754 const TSourceLoc &identifierLoc,
1755 const TString *identifier,
1756 const TSymbol *symbol)
1757{
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001758 // invariant declaration
Jamie Madill47e3ec02014-08-20 16:38:33 -04001759 if (globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying"))
1760 {
1761 recover();
1762 }
1763
1764 if (!symbol)
1765 {
1766 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
1767 recover();
Olli Etuahoe7847b02015-03-16 11:56:12 +02001768 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001769 }
1770 else
1771 {
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001772 const TString kGlFrontFacing("gl_FrontFacing");
1773 if (*identifier == kGlFrontFacing)
1774 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001775 error(identifierLoc, "identifier should not be declared as invariant",
1776 identifier->c_str());
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001777 recover();
Olli Etuahoe7847b02015-03-16 11:56:12 +02001778 return nullptr;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001779 }
Jamie Madill2c433252014-12-03 12:36:54 -05001780 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001781 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
1782 ASSERT(variable);
1783 const TType &type = variable->getType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04001784 TIntermSymbol *intermSymbol =
1785 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001786
1787 TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc);
1788 aggregate->setOp(EOpInvariantDeclaration);
1789 return aggregate;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001790 }
1791}
1792
Jamie Madillb98c3a82015-07-23 14:26:04 -04001793TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType,
1794 TIntermAggregate *aggregateDeclaration,
1795 const TSourceLoc &identifierLocation,
1796 const TString &identifier)
Jamie Madill502d66f2013-06-20 11:55:52 -04001797{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001798 // If the declaration starting this declarator list was empty (example: int,), some checks were
1799 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001800 if (mDeferredSingleDeclarationErrorCheck)
1801 {
1802 if (singleDeclarationErrorCheck(publicType, identifierLocation))
1803 recover();
1804 mDeferredSingleDeclarationErrorCheck = false;
1805 }
1806
Jamie Madill0bd18df2013-06-20 11:55:52 -04001807 if (locationDeclaratorListCheck(identifierLocation, publicType))
1808 recover();
1809
Olli Etuaho376f1b52015-04-13 13:23:41 +03001810 if (nonInitErrorCheck(identifierLocation, identifier, &publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04001811 recover();
1812
Olli Etuaho2935c582015-04-08 14:32:06 +03001813 TVariable *variable = nullptr;
1814 if (!declareVariable(identifierLocation, identifier, TType(publicType), &variable))
Jamie Madill502d66f2013-06-20 11:55:52 -04001815 recover();
Olli Etuahoe7847b02015-03-16 11:56:12 +02001816
Jamie Madillb98c3a82015-07-23 14:26:04 -04001817 TIntermSymbol *symbol =
1818 intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001819 if (variable && symbol)
Jamie Madill502d66f2013-06-20 11:55:52 -04001820 symbol->setId(variable->getUniqueId());
1821
Olli Etuahoe7847b02015-03-16 11:56:12 +02001822 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001823}
1824
Jamie Madillb98c3a82015-07-23 14:26:04 -04001825TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType,
1826 TIntermAggregate *aggregateDeclaration,
1827 const TSourceLoc &identifierLocation,
1828 const TString &identifier,
1829 const TSourceLoc &arrayLocation,
1830 TIntermTyped *indexExpression)
Jamie Madill502d66f2013-06-20 11:55:52 -04001831{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001832 // If the declaration starting this declarator list was empty (example: int,), some checks were
1833 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001834 if (mDeferredSingleDeclarationErrorCheck)
1835 {
1836 if (singleDeclarationErrorCheck(publicType, identifierLocation))
1837 recover();
1838 mDeferredSingleDeclarationErrorCheck = false;
1839 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001840
Jamie Madill0bd18df2013-06-20 11:55:52 -04001841 if (locationDeclaratorListCheck(identifierLocation, publicType))
1842 recover();
1843
Olli Etuaho376f1b52015-04-13 13:23:41 +03001844 if (nonInitErrorCheck(identifierLocation, identifier, &publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04001845 recover();
1846
Jamie Madillb98c3a82015-07-23 14:26:04 -04001847 if (arrayTypeErrorCheck(arrayLocation, publicType) ||
1848 arrayQualifierErrorCheck(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04001849 {
1850 recover();
1851 }
Olli Etuaho93a90fd2015-04-07 18:14:07 +03001852 else
Jamie Madill502d66f2013-06-20 11:55:52 -04001853 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001854 TType arrayType = TType(publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04001855 int size;
1856 if (arraySizeErrorCheck(arrayLocation, indexExpression, size))
Olli Etuahoe7847b02015-03-16 11:56:12 +02001857 {
Jamie Madill502d66f2013-06-20 11:55:52 -04001858 recover();
Olli Etuahoe7847b02015-03-16 11:56:12 +02001859 }
Olli Etuaho693c9aa2015-04-07 17:50:36 +03001860 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001861
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001862 TVariable *variable = nullptr;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001863 if (!declareVariable(identifierLocation, identifier, arrayType, &variable))
Jamie Madill502d66f2013-06-20 11:55:52 -04001864 recover();
Jamie Madill502d66f2013-06-20 11:55:52 -04001865
Jamie Madillb98c3a82015-07-23 14:26:04 -04001866 TIntermSymbol *symbol =
1867 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001868 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001869 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001870
1871 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001872 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001873
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001874 return nullptr;
Jamie Madill502d66f2013-06-20 11:55:52 -04001875}
1876
Jamie Madillb98c3a82015-07-23 14:26:04 -04001877TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicType,
1878 TIntermAggregate *aggregateDeclaration,
1879 const TSourceLoc &identifierLocation,
1880 const TString &identifier,
1881 const TSourceLoc &initLocation,
1882 TIntermTyped *initializer)
Jamie Madill502d66f2013-06-20 11:55:52 -04001883{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001884 // If the declaration starting this declarator list was empty (example: int,), some checks were
1885 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001886 if (mDeferredSingleDeclarationErrorCheck)
1887 {
1888 if (singleDeclarationErrorCheck(publicType, identifierLocation))
1889 recover();
1890 mDeferredSingleDeclarationErrorCheck = false;
1891 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001892
Jamie Madill0bd18df2013-06-20 11:55:52 -04001893 if (locationDeclaratorListCheck(identifierLocation, publicType))
1894 recover();
1895
Olli Etuahoe7847b02015-03-16 11:56:12 +02001896 TIntermNode *intermNode = nullptr;
1897 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04001898 {
1899 //
1900 // build the intermediate representation
1901 //
1902 if (intermNode)
1903 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001904 return intermediate.growAggregate(aggregateDeclaration, intermNode, initLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001905 }
1906 else
1907 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001908 return aggregateDeclaration;
Jamie Madill502d66f2013-06-20 11:55:52 -04001909 }
1910 }
1911 else
1912 {
1913 recover();
Olli Etuahoe7847b02015-03-16 11:56:12 +02001914 return nullptr;
Jamie Madill502d66f2013-06-20 11:55:52 -04001915 }
1916}
1917
Jamie Madill06145232015-05-13 13:10:01 -04001918TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001919 TIntermAggregate *aggregateDeclaration,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301920 const TSourceLoc &identifierLocation,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001921 const TString &identifier,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301922 const TSourceLoc &indexLocation,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001923 TIntermTyped *indexExpression,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001924 const TSourceLoc &initLocation,
1925 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001926{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001927 // If the declaration starting this declarator list was empty (example: int,), some checks were
1928 // not performed.
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001929 if (mDeferredSingleDeclarationErrorCheck)
1930 {
1931 if (singleDeclarationErrorCheck(publicType, identifierLocation))
1932 recover();
1933 mDeferredSingleDeclarationErrorCheck = false;
1934 }
1935
1936 if (locationDeclaratorListCheck(identifierLocation, publicType))
1937 recover();
1938
Jamie Madillb98c3a82015-07-23 14:26:04 -04001939 if (arrayTypeErrorCheck(indexLocation, publicType) ||
1940 arrayQualifierErrorCheck(indexLocation, publicType))
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001941 {
1942 recover();
1943 }
1944
1945 TPublicType arrayType(publicType);
1946
Olli Etuaho376f1b52015-04-13 13:23:41 +03001947 int size = 0;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001948 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
1949 // the initializer.
1950 if (indexExpression != nullptr &&
1951 arraySizeErrorCheck(identifierLocation, indexExpression, size))
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001952 {
1953 recover();
1954 }
1955 // Make the type an array even if size check failed.
1956 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1957 arrayType.setArraySize(size);
1958
1959 // initNode will correspond to the whole of "b[n] = initializer".
1960 TIntermNode *initNode = nullptr;
1961 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
1962 {
1963 if (initNode)
1964 {
1965 return intermediate.growAggregate(aggregateDeclaration, initNode, initLocation);
1966 }
1967 else
1968 {
1969 return aggregateDeclaration;
1970 }
1971 }
1972 else
1973 {
1974 recover();
1975 return nullptr;
1976 }
1977}
1978
Jamie Madilla295edf2013-06-06 11:56:48 -04001979void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
1980{
Jamie Madilla295edf2013-06-06 11:56:48 -04001981
1982 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04001983
1984 // It should never be the case, but some strange parser errors can send us here.
1985 if (layoutQualifier.isEmpty())
1986 {
1987 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
1988 recover();
1989 return;
1990 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001991
Martin Radev802abe02016-08-04 17:48:32 +03001992 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04001993 {
Martin Radev802abe02016-08-04 17:48:32 +03001994 error(typeQualifier.line, "invalid combination:", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04001995 recover();
1996 return;
1997 }
1998
Martin Radev802abe02016-08-04 17:48:32 +03001999 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04002000 {
Martin Radev802abe02016-08-04 17:48:32 +03002001 if (mComputeShaderLocalSizeDeclared &&
2002 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
2003 {
2004 error(typeQualifier.line, "Work group size does not match the previous declaration",
2005 "layout");
2006 recover();
2007 return;
2008 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002009
Martin Radev802abe02016-08-04 17:48:32 +03002010 if (mShaderVersion < 310)
2011 {
2012 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
2013 recover();
2014 return;
2015 }
Jamie Madill099c0f32013-06-20 11:55:52 -04002016
Martin Radev802abe02016-08-04 17:48:32 +03002017 if (!layoutQualifier.isGroupSizeSpecified())
2018 {
2019 error(typeQualifier.line, "No local work group size specified", "layout");
2020 recover();
2021 return;
2022 }
2023
2024 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
2025 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
2026
2027 const TConstantUnion *maxComputeWorkGroupSizeData =
2028 maxComputeWorkGroupSize->getConstPointer();
2029
2030 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
2031 {
2032 if (layoutQualifier.localSize[i] != -1)
2033 {
2034 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
2035 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
2036 if (mComputeShaderLocalSize[i] < 1 ||
2037 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
2038 {
2039 std::stringstream errorMessageStream;
2040 errorMessageStream << "Value must be at least 1 and no greater than "
2041 << maxComputeWorkGroupSizeValue;
2042 const std::string &errorMessage = errorMessageStream.str();
2043
2044 error(typeQualifier.line, "invalid value:", getLocalSizeString(i),
2045 errorMessage.c_str());
2046 recover();
2047 return;
2048 }
2049 }
2050 }
2051
2052 mComputeShaderLocalSizeDeclared = true;
2053 }
2054 else
Jamie Madill1566ef72013-06-20 11:55:54 -04002055 {
Martin Radev802abe02016-08-04 17:48:32 +03002056
2057 if (layoutWorkGroupSizeErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier))
2058 {
2059 recover();
2060 return;
2061 }
2062
2063 if (typeQualifier.qualifier != EvqUniform)
2064 {
2065 error(typeQualifier.line, "invalid qualifier:",
2066 getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
2067 recover();
2068 return;
2069 }
2070
2071 if (mShaderVersion < 300)
2072 {
2073 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
2074 "layout");
2075 recover();
2076 return;
2077 }
2078
2079 if (layoutLocationErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier))
2080 {
2081 recover();
2082 return;
2083 }
2084
2085 if (layoutQualifier.matrixPacking != EmpUnspecified)
2086 {
2087 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
2088 }
2089
2090 if (layoutQualifier.blockStorage != EbsUnspecified)
2091 {
2092 mDefaultBlockStorage = layoutQualifier.blockStorage;
2093 }
Jamie Madill1566ef72013-06-20 11:55:54 -04002094 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002095}
2096
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002097TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function,
2098 const TSourceLoc &location)
2099{
Olli Etuaho5d653182016-01-04 14:43:28 +02002100 // Note: symbolTableFunction could be the same as function if this is the first declaration.
2101 // Either way the instance in the symbol table is used to track whether the function is declared
2102 // multiple times.
2103 TFunction *symbolTableFunction =
2104 static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion()));
2105 if (symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100)
2106 {
2107 // ESSL 1.00.17 section 4.2.7.
2108 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
2109 error(location, "duplicate function prototype declarations are not allowed", "function");
2110 recover();
2111 }
2112 symbolTableFunction->setHasPrototypeDeclaration();
2113
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002114 TIntermAggregate *prototype = new TIntermAggregate;
2115 prototype->setType(function.getReturnType());
2116 prototype->setName(function.getMangledName());
2117 prototype->setFunctionId(function.getUniqueId());
2118
2119 for (size_t i = 0; i < function.getParamCount(); i++)
2120 {
2121 const TConstParameter &param = function.getParam(i);
2122 if (param.name != 0)
2123 {
2124 TVariable variable(param.name, *param.type);
2125
2126 TIntermSymbol *paramSymbol = intermediate.addSymbol(
2127 variable.getUniqueId(), variable.getName(), variable.getType(), location);
2128 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
2129 }
2130 else
2131 {
2132 TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
2133 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
2134 }
2135 }
2136
2137 prototype->setOp(EOpPrototype);
2138
2139 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002140
2141 if (!symbolTable.atGlobalLevel())
2142 {
2143 // ESSL 3.00.4 section 4.2.4.
2144 error(location, "local function prototype declarations are not allowed", "function");
2145 recover();
2146 }
2147
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002148 return prototype;
2149}
2150
2151TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function,
2152 TIntermAggregate *functionPrototype,
2153 TIntermAggregate *functionBody,
2154 const TSourceLoc &location)
2155{
2156 //?? Check that all paths return a value if return type != void ?
2157 // May be best done as post process phase on intermediate code
2158 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2159 {
2160 error(location, "function does not return a value:", "", function.getName().c_str());
2161 recover();
2162 }
2163
2164 TIntermAggregate *aggregate =
2165 intermediate.growAggregate(functionPrototype, functionBody, location);
2166 intermediate.setAggregateOperator(aggregate, EOpFunction, location);
2167 aggregate->setName(function.getMangledName().c_str());
2168 aggregate->setType(function.getReturnType());
2169 aggregate->setFunctionId(function.getUniqueId());
2170
2171 symbolTable.pop();
2172 return aggregate;
2173}
2174
Jamie Madill185fb402015-06-12 15:48:48 -04002175void TParseContext::parseFunctionPrototype(const TSourceLoc &location,
2176 TFunction *function,
2177 TIntermAggregate **aggregateOut)
2178{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002179 const TSymbol *builtIn =
2180 symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002181
2182 if (builtIn)
2183 {
2184 error(location, "built-in functions cannot be redefined", function->getName().c_str());
2185 recover();
2186 }
2187
Jamie Madillb98c3a82015-07-23 14:26:04 -04002188 TFunction *prevDec =
2189 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Jamie Madill185fb402015-06-12 15:48:48 -04002190 //
2191 // Note: 'prevDec' could be 'function' if this is the first time we've seen function
2192 // as it would have just been put in the symbol table. Otherwise, we're looking up
2193 // an earlier occurance.
2194 //
2195 if (prevDec->isDefined())
2196 {
2197 // Then this function already has a body.
2198 error(location, "function already has a body", function->getName().c_str());
2199 recover();
2200 }
2201 prevDec->setDefined();
2202 //
2203 // Overload the unique ID of the definition to be the same unique ID as the declaration.
2204 // Eventually we will probably want to have only a single definition and just swap the
2205 // arguments to be the definition's arguments.
2206 //
2207 function->setUniqueId(prevDec->getUniqueId());
2208
2209 // Raise error message if main function takes any parameters or return anything other than void
2210 if (function->getName() == "main")
2211 {
2212 if (function->getParamCount() > 0)
2213 {
2214 error(location, "function cannot take any parameter(s)", function->getName().c_str());
2215 recover();
2216 }
2217 if (function->getReturnType().getBasicType() != EbtVoid)
2218 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002219 error(location, "", function->getReturnType().getBasicString(),
2220 "main function cannot return a value");
Jamie Madill185fb402015-06-12 15:48:48 -04002221 recover();
2222 }
2223 }
2224
2225 //
2226 // Remember the return type for later checking for RETURN statements.
2227 //
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002228 mCurrentFunctionType = &(prevDec->getReturnType());
2229 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002230
2231 //
2232 // Insert parameters into the symbol table.
2233 // If the parameter has no name, it's not an error, just don't insert it
2234 // (could be used for unused args).
2235 //
2236 // Also, accumulate the list of parameters into the HIL, so lower level code
2237 // knows where to find parameters.
2238 //
2239 TIntermAggregate *paramNodes = new TIntermAggregate;
2240 for (size_t i = 0; i < function->getParamCount(); i++)
2241 {
2242 const TConstParameter &param = function->getParam(i);
2243 if (param.name != 0)
2244 {
2245 TVariable *variable = new TVariable(param.name, *param.type);
2246 //
2247 // Insert the parameters with name in the symbol table.
2248 //
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002249 if (!symbolTable.declare(variable))
2250 {
Jamie Madill185fb402015-06-12 15:48:48 -04002251 error(location, "redefinition", variable->getName().c_str());
2252 recover();
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002253 paramNodes = intermediate.growAggregate(
2254 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
2255 continue;
Jamie Madill185fb402015-06-12 15:48:48 -04002256 }
2257
2258 //
2259 // Add the parameter to the HIL
2260 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002261 TIntermSymbol *symbol = intermediate.addSymbol(
2262 variable->getUniqueId(), variable->getName(), variable->getType(), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002263
2264 paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
2265 }
2266 else
2267 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002268 paramNodes = intermediate.growAggregate(
2269 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002270 }
2271 }
2272 intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
2273 *aggregateOut = paramNodes;
2274 setLoopNestingLevel(0);
2275}
2276
Jamie Madillb98c3a82015-07-23 14:26:04 -04002277TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002278{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002279 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002280 // We don't know at this point whether this is a function definition or a prototype.
2281 // The definition production code will check for redefinitions.
2282 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002283 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002284 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2285 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002286 //
2287 TFunction *prevDec =
2288 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302289
2290 if (getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltIn(function->getName().c_str()))
2291 {
2292 // With ESSL 3.00, names of built-in functions cannot be redeclared as functions.
2293 // Therefore overloading or redefining builtin functions is an error.
2294 error(location, "Name of a built-in function cannot be redeclared as function",
2295 function->getName().c_str());
2296 recover();
2297 }
2298 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002299 {
2300 if (prevDec->getReturnType() != function->getReturnType())
2301 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002302 error(location, "overloaded functions must have the same return type",
Jamie Madill185fb402015-06-12 15:48:48 -04002303 function->getReturnType().getBasicString());
2304 recover();
2305 }
2306 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2307 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002308 if (prevDec->getParam(i).type->getQualifier() !=
2309 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002310 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002311 error(location, "overloaded functions must have the same parameter qualifiers",
Jamie Madill185fb402015-06-12 15:48:48 -04002312 function->getParam(i).type->getQualifierString());
2313 recover();
2314 }
2315 }
2316 }
2317
2318 //
2319 // Check for previously declared variables using the same name.
2320 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002321 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002322 if (prevSym)
2323 {
2324 if (!prevSym->isFunction())
2325 {
2326 error(location, "redefinition", function->getName().c_str(), "function");
2327 recover();
2328 }
2329 }
2330 else
2331 {
2332 // Insert the unmangled name to detect potential future redefinition as a variable.
Jamie Madillb98c3a82015-07-23 14:26:04 -04002333 TFunction *newFunction =
2334 new TFunction(NewPoolTString(function->getName().c_str()), &function->getReturnType());
Jamie Madill185fb402015-06-12 15:48:48 -04002335 symbolTable.getOuterLevel()->insertUnmangled(newFunction);
2336 }
2337
2338 // We're at the inner scope level of the function's arguments and body statement.
2339 // Add the function prototype to the surrounding scope instead.
2340 symbolTable.getOuterLevel()->insert(function);
2341
2342 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002343 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2344 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002345 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2346 //
2347 return function;
2348}
2349
Olli Etuaho9de84a52016-06-14 17:36:01 +03002350TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2351 const TString *name,
2352 const TSourceLoc &location)
2353{
2354 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2355 {
2356 error(location, "no qualifiers allowed for function return",
2357 getQualifierString(type.qualifier));
2358 recover();
2359 }
2360 if (!type.layoutQualifier.isEmpty())
2361 {
2362 error(location, "no qualifiers allowed for function return", "layout");
2363 recover();
2364 }
2365 // make sure a sampler is not involved as well...
2366 if (samplerErrorCheck(location, type, "samplers can't be function return values"))
2367 {
2368 recover();
2369 }
Olli Etuahoe29324f2016-06-15 10:58:03 +03002370 if (mShaderVersion < 300)
2371 {
2372 // Array return values are forbidden, but there's also no valid syntax for declaring array
2373 // return values in ESSL 1.00.
2374 ASSERT(type.arraySize == 0 || mDiagnostics.numErrors() > 0);
2375
2376 if (type.isStructureContainingArrays())
2377 {
2378 // ESSL 1.00.17 section 6.1 Function Definitions
2379 error(location, "structures containing arrays can't be function return values",
2380 TType(type).getCompleteString().c_str());
2381 recover();
2382 }
2383 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002384
2385 // Add the function as a prototype after parsing it (we do not support recursion)
2386 return new TFunction(name, new TType(type));
2387}
2388
Jamie Madill06145232015-05-13 13:10:01 -04002389TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002390{
Jamie Madill06145232015-05-13 13:10:01 -04002391 TPublicType publicType = publicTypeIn;
Olli Etuahobd163f62015-11-13 12:15:38 +02002392 if (publicType.isStructSpecifier)
2393 {
2394 error(publicType.line, "constructor can't be a structure definition",
2395 getBasicString(publicType.type));
2396 recover();
2397 }
2398
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002399 TOperator op = EOpNull;
2400 if (publicType.userDef)
2401 {
2402 op = EOpConstructStruct;
2403 }
2404 else
2405 {
Geoff Lang156d7192016-07-21 16:11:00 -04002406 op = sh::TypeToConstructorOperator(TType(publicType));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002407 if (op == EOpNull)
2408 {
2409 error(publicType.line, "cannot construct this type", getBasicString(publicType.type));
2410 recover();
2411 publicType.type = EbtFloat;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002412 op = EOpConstructFloat;
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002413 }
2414 }
2415
2416 TString tempString;
Dmitry Skiba7f17a502015-06-22 15:08:39 -07002417 const TType *type = new TType(publicType);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002418 return new TFunction(&tempString, type, op);
2419}
2420
Jamie Madillb98c3a82015-07-23 14:26:04 -04002421// This function is used to test for the correctness of the parameters passed to various constructor
2422// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002423//
2424// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
2425//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002426TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments,
2427 TType *type,
2428 TOperator op,
2429 TFunction *fnCall,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302430 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002431{
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002432 TIntermAggregate *constructor = arguments->getAsAggregate();
2433 ASSERT(constructor != nullptr);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002434
Olli Etuahof40319e2015-03-10 14:33:00 +02002435 if (type->isArray())
2436 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002437 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
2438 // the array.
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002439 TIntermSequence *args = constructor->getSequence();
Olli Etuahof40319e2015-03-10 14:33:00 +02002440 for (size_t i = 0; i < args->size(); i++)
2441 {
2442 const TType &argType = (*args)[i]->getAsTyped()->getType();
2443 // It has already been checked that the argument is not an array.
2444 ASSERT(!argType.isArray());
2445 if (!argType.sameElementType(*type))
2446 {
2447 error(line, "Array constructor argument has an incorrect type", "Error");
2448 recover();
2449 return nullptr;
2450 }
2451 }
2452 }
2453 else if (op == EOpConstructStruct)
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002454 {
2455 const TFieldList &fields = type->getStruct()->fields();
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002456 TIntermSequence *args = constructor->getSequence();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002457
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002458 for (size_t i = 0; i < fields.size(); i++)
2459 {
Nicolas Capensffd73872014-08-21 13:49:16 -04002460 if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type())
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002461 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002462 error(line, "Structure constructor arguments do not match structure fields",
2463 "Error");
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002464 recover();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002465
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002466 return 0;
2467 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002468 }
2469 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002470
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002471 // Turn the argument list itself into a constructor
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002472 constructor->setOp(op);
2473 constructor->setLine(line);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002474 ASSERT(constructor->isConstructor());
2475
2476 // Need to set type before setPrecisionFromChildren() because bool doesn't have precision.
2477 constructor->setType(*type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002478
Olli Etuaho21203702014-11-13 16:16:21 +02002479 // Structs should not be precision qualified, the individual members may be.
2480 // Built-in types on the other hand should be precision qualified.
2481 if (op != EOpConstructStruct)
2482 {
2483 constructor->setPrecisionFromChildren();
2484 type->setPrecision(constructor->getPrecision());
2485 }
2486
Olli Etuaho1d122782015-11-06 15:35:17 +02002487 TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002488 if (constConstructor)
2489 {
2490 return constConstructor;
2491 }
2492
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002493 return constructor;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002494}
2495
Olli Etuaho90892fb2016-07-14 14:44:51 +03002496// This function returns vector field(s) being accessed from a constant vector.
2497TIntermConstantUnion *TParseContext::foldVectorSwizzle(TVectorFields &fields,
2498 TIntermConstantUnion *baseNode,
2499 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002500{
Olli Etuaho90892fb2016-07-14 14:44:51 +03002501 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002502 ASSERT(unionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002503
Arun Patole7e7e68d2015-05-22 12:02:25 +05302504 TConstantUnion *constArray = new TConstantUnion[fields.num];
Olli Etuaho90892fb2016-07-14 14:44:51 +03002505 const auto &type = baseNode->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002506
Arun Patole7e7e68d2015-05-22 12:02:25 +05302507 for (int i = 0; i < fields.num; i++)
2508 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002509 // Out-of-range indices should already be checked.
2510 ASSERT(fields.offsets[i] < type.getNominalSize());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002511 constArray[i] = unionArray[fields.offsets[i]];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302512 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03002513 return intermediate.addConstantUnion(constArray, type, location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002514}
2515
Olli Etuaho90892fb2016-07-14 14:44:51 +03002516// This function returns the column vector being accessed from a constant matrix.
2517TIntermConstantUnion *TParseContext::foldMatrixSubscript(int index,
2518 TIntermConstantUnion *baseNode,
2519 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002520{
Olli Etuaho90892fb2016-07-14 14:44:51 +03002521 ASSERT(index < baseNode->getType().getCols());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002522
Olli Etuaho90892fb2016-07-14 14:44:51 +03002523 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
2524 int size = baseNode->getType().getRows();
2525 return intermediate.addConstantUnion(&unionArray[size * index], baseNode->getType(), location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002526}
2527
Olli Etuaho90892fb2016-07-14 14:44:51 +03002528// This function returns an element of an array accessed from a constant array.
2529TIntermConstantUnion *TParseContext::foldArraySubscript(int index,
2530 TIntermConstantUnion *baseNode,
2531 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002532{
Olli Etuaho90892fb2016-07-14 14:44:51 +03002533 ASSERT(index < baseNode->getArraySize());
2534
2535 TType arrayElementType = baseNode->getType();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002536 arrayElementType.clearArrayness();
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002537 size_t arrayElementSize = arrayElementType.getObjectSize();
Olli Etuaho90892fb2016-07-14 14:44:51 +03002538 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
2539 return intermediate.addConstantUnion(&unionArray[arrayElementSize * index], baseNode->getType(),
2540 location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002541}
2542
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002543//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002544// This function returns the value of a particular field inside a constant structure from the symbol
2545// table.
2546// If there is an embedded/nested struct, it appropriately calls addConstStructNested or
2547// addConstStructFromAggr function and returns the parse-tree with the values of the embedded/nested
2548// struct.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002549//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002550TIntermTyped *TParseContext::addConstStruct(const TString &identifier,
2551 TIntermTyped *node,
2552 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002553{
Arun Patole7e7e68d2015-05-22 12:02:25 +05302554 const TFieldList &fields = node->getType().getStruct()->fields();
Jamie Madillb98c3a82015-07-23 14:26:04 -04002555 size_t instanceSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002556
Arun Patole7e7e68d2015-05-22 12:02:25 +05302557 for (size_t index = 0; index < fields.size(); ++index)
2558 {
2559 if (fields[index]->name() == identifier)
2560 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002561 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302562 }
2563 else
2564 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002565 instanceSize += fields[index]->type()->getObjectSize();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002566 }
2567 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002568
Jamie Madill94bf7f22013-07-08 13:31:15 -04002569 TIntermTyped *typedNode;
2570 TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
Arun Patole7e7e68d2015-05-22 12:02:25 +05302571 if (tempConstantNode)
2572 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002573 const TConstantUnion *constArray = tempConstantNode->getUnionArrayPointer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002574
Jamie Madillb98c3a82015-07-23 14:26:04 -04002575 // type will be changed in the calling function
2576 typedNode = intermediate.addConstantUnion(constArray + instanceSize,
2577 tempConstantNode->getType(), line);
Arun Patole7e7e68d2015-05-22 12:02:25 +05302578 }
2579 else
2580 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002581 error(line, "Cannot offset into the structure", "Error");
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002582 recover();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002583
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002584 return 0;
2585 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002586
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002587 return typedNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002588}
2589
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002590//
2591// Interface/uniform blocks
2592//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002593TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualifier,
2594 const TSourceLoc &nameLine,
2595 const TString &blockName,
2596 TFieldList *fieldList,
2597 const TString *instanceName,
2598 const TSourceLoc &instanceLine,
2599 TIntermTyped *arrayIndex,
2600 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002601{
2602 if (reservedErrorCheck(nameLine, blockName))
2603 recover();
2604
2605 if (typeQualifier.qualifier != EvqUniform)
2606 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302607 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier),
2608 "interface blocks must be uniform");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002609 recover();
2610 }
2611
Jamie Madill099c0f32013-06-20 11:55:52 -04002612 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
2613 if (layoutLocationErrorCheck(typeQualifier.line, blockLayoutQualifier))
Jamie Madilla5efff92013-06-06 11:56:47 -04002614 {
2615 recover();
2616 }
2617
Jamie Madill099c0f32013-06-20 11:55:52 -04002618 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2619 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002620 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002621 }
2622
Jamie Madill1566ef72013-06-20 11:55:54 -04002623 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2624 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002625 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002626 }
2627
Martin Radev802abe02016-08-04 17:48:32 +03002628 if (layoutWorkGroupSizeErrorCheck(nameLine, blockLayoutQualifier))
2629 {
2630 recover();
2631 }
2632
Arun Patole7e7e68d2015-05-22 12:02:25 +05302633 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2634 if (!symbolTable.declare(blockNameSymbol))
2635 {
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002636 error(nameLine, "redefinition", blockName.c_str(), "interface block name");
2637 recover();
2638 }
2639
Jamie Madill98493dd2013-07-08 14:39:03 -04002640 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302641 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2642 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002643 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302644 TType *fieldType = field->type();
2645 if (IsSampler(fieldType->getBasicType()))
2646 {
2647 error(field->line(), "unsupported type", fieldType->getBasicString(),
2648 "sampler types are not allowed in interface blocks");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002649 recover();
2650 }
2651
Jamie Madill98493dd2013-07-08 14:39:03 -04002652 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002653 switch (qualifier)
2654 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002655 case EvqGlobal:
2656 case EvqUniform:
2657 break;
2658 default:
2659 error(field->line(), "invalid qualifier on interface block member",
2660 getQualifierString(qualifier));
2661 recover();
2662 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002663 }
Jamie Madilla5efff92013-06-06 11:56:47 -04002664
2665 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04002666 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
2667 if (layoutLocationErrorCheck(field->line(), fieldLayoutQualifier))
Jamie Madilla5efff92013-06-06 11:56:47 -04002668 {
2669 recover();
2670 }
Jamie Madill099c0f32013-06-20 11:55:52 -04002671
Jamie Madill98493dd2013-07-08 14:39:03 -04002672 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04002673 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002674 error(field->line(), "invalid layout qualifier:",
2675 getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
Jamie Madill1566ef72013-06-20 11:55:54 -04002676 recover();
2677 }
2678
Jamie Madill98493dd2013-07-08 14:39:03 -04002679 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04002680 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002681 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002682 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002683 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04002684 {
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002685 warning(field->line(), "extraneous layout qualifier:",
Jamie Madillb98c3a82015-07-23 14:26:04 -04002686 getMatrixPackingString(fieldLayoutQualifier.matrixPacking),
2687 "only has an effect on matrix types");
Jamie Madill099c0f32013-06-20 11:55:52 -04002688 }
2689
Jamie Madill98493dd2013-07-08 14:39:03 -04002690 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002691 }
2692
Jamie Madill98493dd2013-07-08 14:39:03 -04002693 // add array index
2694 int arraySize = 0;
2695 if (arrayIndex != NULL)
2696 {
2697 if (arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize))
2698 recover();
2699 }
2700
Jamie Madillb98c3a82015-07-23 14:26:04 -04002701 TInterfaceBlock *interfaceBlock =
2702 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2703 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
2704 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002705
2706 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04002707 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002708
Jamie Madill98493dd2013-07-08 14:39:03 -04002709 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002710 {
2711 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04002712 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2713 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002714 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302715 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04002716
2717 // set parent pointer of the field variable
2718 fieldType->setInterfaceBlock(interfaceBlock);
2719
Arun Patole7e7e68d2015-05-22 12:02:25 +05302720 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04002721 fieldVariable->setQualifier(typeQualifier.qualifier);
2722
Arun Patole7e7e68d2015-05-22 12:02:25 +05302723 if (!symbolTable.declare(fieldVariable))
2724 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002725 error(field->line(), "redefinition", field->name().c_str(),
2726 "interface block member name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002727 recover();
2728 }
2729 }
2730 }
2731 else
2732 {
Olli Etuahoe0f623a2015-07-10 11:58:30 +03002733 if (reservedErrorCheck(instanceLine, *instanceName))
2734 recover();
2735
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002736 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05302737 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002738 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04002739
Arun Patole7e7e68d2015-05-22 12:02:25 +05302740 if (!symbolTable.declare(instanceTypeDef))
2741 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002742 error(instanceLine, "redefinition", instanceName->c_str(),
2743 "interface block instance name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002744 recover();
2745 }
2746
Jamie Madillb98c3a82015-07-23 14:26:04 -04002747 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002748 symbolName = instanceTypeDef->getName();
2749 }
2750
Jamie Madillb98c3a82015-07-23 14:26:04 -04002751 TIntermAggregate *aggregate = intermediate.makeAggregate(
2752 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line),
2753 nameLine);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002754 aggregate->setOp(EOpDeclaration);
Jamie Madill98493dd2013-07-08 14:39:03 -04002755
2756 exitStructDeclaration();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002757 return aggregate;
2758}
2759
Arun Patole7e7e68d2015-05-22 12:02:25 +05302760bool TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002761{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002762 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002763
2764 // Embedded structure definitions are not supported per GLSL ES spec.
2765 // They aren't allowed in GLSL either, but we need to detect this here
2766 // so we don't rely on the GLSL compiler to catch it.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302767 if (mStructNestingLevel > 1)
2768 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002769 error(line, "", "Embedded struct definitions are not allowed");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002770 return true;
2771 }
2772
2773 return false;
2774}
2775
2776void TParseContext::exitStructDeclaration()
2777{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002778 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002779}
2780
Jamie Madillb98c3a82015-07-23 14:26:04 -04002781namespace
2782{
kbr@chromium.org476541f2011-10-27 21:14:51 +00002783const int kWebGLMaxStructNesting = 4;
2784
2785} // namespace
2786
Arun Patole7e7e68d2015-05-22 12:02:25 +05302787bool TParseContext::structNestingErrorCheck(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002788{
Arun Patole7e7e68d2015-05-22 12:02:25 +05302789 if (!IsWebGLBasedSpec(mShaderSpec))
2790 {
kbr@chromium.org476541f2011-10-27 21:14:51 +00002791 return false;
2792 }
2793
Arun Patole7e7e68d2015-05-22 12:02:25 +05302794 if (field.type()->getBasicType() != EbtStruct)
2795 {
kbr@chromium.org476541f2011-10-27 21:14:51 +00002796 return false;
2797 }
2798
2799 // We're already inside a structure definition at this point, so add
2800 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302801 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2802 {
Jamie Madill41a49272014-03-18 16:10:13 -04002803 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002804 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
2805 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04002806 std::string reason = reasonStream.str();
2807 error(line, reason.c_str(), field.name().c_str(), "");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002808 return true;
2809 }
2810
2811 return false;
2812}
2813
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00002814//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002815// Parse an array index expression
2816//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002817TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
2818 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302819 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002820{
2821 TIntermTyped *indexedExpression = NULL;
2822
2823 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2824 {
2825 if (baseExpression->getAsSymbolNode())
2826 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302827 error(location, " left of '[' is not of type array, matrix, or vector ",
2828 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002829 }
2830 else
2831 {
2832 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2833 }
2834 recover();
2835 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002836
Jamie Madill21c1e452014-12-29 11:33:41 -05002837 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2838
Olli Etuaho36b05142015-11-12 13:10:42 +02002839 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
2840 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
2841 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
2842 // index is a constant expression.
2843 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
2844 {
2845 if (baseExpression->isInterfaceBlock())
2846 {
2847 error(
2848 location, "", "[",
2849 "array indexes for interface blocks arrays must be constant integral expressions");
2850 recover();
2851 }
2852 else if (baseExpression->getQualifier() == EvqFragmentOut)
2853 {
2854 error(location, "", "[",
2855 "array indexes for fragment outputs must be constant integral expressions");
2856 recover();
2857 }
Olli Etuaho3e960462015-11-12 15:58:39 +02002858 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
2859 {
2860 error(location, "", "[", "array index for gl_FragData must be constant zero");
2861 recover();
2862 }
Olli Etuaho36b05142015-11-12 13:10:42 +02002863 }
2864
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002865 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04002866 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002867 // If the index is not qualified as constant, the behavior in the spec is undefined. This
2868 // applies even if ANGLE has been able to constant fold it (ANGLE may constant fold
2869 // expressions that are not constant expressions). The most compatible way to handle this
2870 // case is to report a warning instead of an error and force the index to be in the
2871 // correct range.
2872 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madill21c1e452014-12-29 11:33:41 -05002873 int index = indexConstantUnion->getIConst(0);
Olli Etuaho90892fb2016-07-14 14:44:51 +03002874 if (!baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04002875 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002876 // Array checks are done later because a different error message might be generated
2877 // based on the index in some cases.
2878 if (baseExpression->isVector())
2879 {
2880 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2881 baseExpression->getType().getNominalSize(),
2882 "vector field selection out of range", "[]");
2883 }
2884 else if (baseExpression->isMatrix())
2885 {
2886 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2887 baseExpression->getType().getCols(),
2888 "matrix field selection out of range", "[]");
2889 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002890 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03002891
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002892 TIntermConstantUnion *baseConstantUnion = baseExpression->getAsConstantUnion();
2893 if (baseConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04002894 {
2895 if (baseExpression->isArray())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002896 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002897 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2898 baseExpression->getArraySize(),
2899 "array index out of range", "[]");
2900 // Constant folding for array indexing.
2901 indexedExpression = foldArraySubscript(index, baseConstantUnion, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002902 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002903 else if (baseExpression->isVector())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002904 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002905 // Constant folding for vector indexing - reusing vector swizzle folding.
Jamie Madill7164cf42013-07-08 13:30:59 -04002906 TVectorFields fields;
2907 fields.num = 1;
Olli Etuaho90892fb2016-07-14 14:44:51 +03002908 fields.offsets[0] = index;
2909 indexedExpression = foldVectorSwizzle(fields, baseConstantUnion, location);
Jamie Madill7164cf42013-07-08 13:30:59 -04002910 }
2911 else if (baseExpression->isMatrix())
2912 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002913 // Constant folding for matrix indexing.
2914 indexedExpression = foldMatrixSubscript(index, baseConstantUnion, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002915 }
2916 }
2917 else
2918 {
Jamie Madillb11e2482015-05-04 14:21:22 -04002919 int safeIndex = -1;
2920
Jamie Madill7164cf42013-07-08 13:30:59 -04002921 if (baseExpression->isArray())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002922 {
Olli Etuaho3e960462015-11-12 15:58:39 +02002923 if (baseExpression->getQualifier() == EvqFragData && index > 0)
2924 {
2925 if (mShaderSpec == SH_WEBGL2_SPEC)
2926 {
2927 // Error has been already generated if index is not const.
2928 if (indexExpression->getQualifier() == EvqConst)
2929 {
2930 error(location, "", "[",
2931 "array index for gl_FragData must be constant zero");
2932 recover();
2933 }
2934 safeIndex = 0;
2935 }
2936 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
2937 {
2938 outOfRangeError(outOfRangeIndexIsError, location, "", "[",
2939 "array index for gl_FragData must be zero when "
2940 "GL_EXT_draw_buffers is disabled");
2941 safeIndex = 0;
2942 }
2943 }
2944 // Only do generic out-of-range check if similar error hasn't already been reported.
Olli Etuaho90892fb2016-07-14 14:44:51 +03002945 if (safeIndex < 0)
Jamie Madill7164cf42013-07-08 13:30:59 -04002946 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002947 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2948 baseExpression->getArraySize(),
2949 "array index out of range", "[]");
Jamie Madill7164cf42013-07-08 13:30:59 -04002950 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002951 }
2952
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002953 // Data of constant unions can't be changed, because it may be shared with other
2954 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
2955 // sanitized object.
Jamie Madillb11e2482015-05-04 14:21:22 -04002956 if (safeIndex != -1)
2957 {
2958 TConstantUnion *safeConstantUnion = new TConstantUnion();
2959 safeConstantUnion->setIConst(safeIndex);
2960 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
2961 }
2962
Jamie Madillb98c3a82015-07-23 14:26:04 -04002963 indexedExpression =
2964 intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002965 }
2966 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002967 else
2968 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002969 indexedExpression =
2970 intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
Jamie Madill7164cf42013-07-08 13:30:59 -04002971 }
2972
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002973 if (indexedExpression == 0)
2974 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002975 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002976 unionArray->setFConst(0.0f);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002977 indexedExpression =
2978 intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002979 }
2980 else if (baseExpression->isArray())
2981 {
Olli Etuahob3fbd862015-09-30 17:55:02 +03002982 TType indexedType = baseExpression->getType();
2983 indexedType.clearArrayness();
2984 indexedExpression->setType(indexedType);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002985 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002986 else if (baseExpression->isMatrix())
2987 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002988 indexedExpression->setType(TType(baseExpression->getBasicType(),
Olli Etuahob3fbd862015-09-30 17:55:02 +03002989 baseExpression->getPrecision(), EvqTemporary,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002990 static_cast<unsigned char>(baseExpression->getRows())));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002991 }
2992 else if (baseExpression->isVector())
2993 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002994 indexedExpression->setType(
Olli Etuahob3fbd862015-09-30 17:55:02 +03002995 TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002996 }
2997 else
2998 {
2999 indexedExpression->setType(baseExpression->getType());
3000 }
3001
Olli Etuahob3fbd862015-09-30 17:55:02 +03003002 if (baseExpression->getType().getQualifier() == EvqConst &&
3003 indexExpression->getType().getQualifier() == EvqConst)
3004 {
3005 indexedExpression->getTypePointer()->setQualifier(EvqConst);
3006 }
3007 else
3008 {
3009 indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
3010 }
3011
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003012 return indexedExpression;
3013}
3014
Olli Etuaho90892fb2016-07-14 14:44:51 +03003015int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
3016 const TSourceLoc &location,
3017 int index,
3018 int arraySize,
3019 const char *reason,
3020 const char *token)
3021{
3022 if (index >= arraySize || index < 0)
3023 {
3024 std::stringstream extraInfoStream;
3025 extraInfoStream << "'" << index << "'";
3026 std::string extraInfo = extraInfoStream.str();
3027 outOfRangeError(outOfRangeIndexIsError, location, reason, token, extraInfo.c_str());
3028 if (index < 0)
3029 {
3030 return 0;
3031 }
3032 else
3033 {
3034 return arraySize - 1;
3035 }
3036 }
3037 return index;
3038}
3039
Jamie Madillb98c3a82015-07-23 14:26:04 -04003040TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
3041 const TSourceLoc &dotLocation,
3042 const TString &fieldString,
3043 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003044{
3045 TIntermTyped *indexedExpression = NULL;
3046
3047 if (baseExpression->isArray())
3048 {
3049 error(fieldLocation, "cannot apply dot operator to an array", ".");
3050 recover();
3051 }
3052
3053 if (baseExpression->isVector())
3054 {
3055 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003056 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
3057 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003058 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003059 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003060 fields.offsets[0] = 0;
3061 recover();
3062 }
3063
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003064 if (baseExpression->getAsConstantUnion())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003065 {
3066 // constant folding for vector fields
Olli Etuaho90892fb2016-07-14 14:44:51 +03003067 indexedExpression =
3068 foldVectorSwizzle(fields, baseExpression->getAsConstantUnion(), fieldLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003069 }
3070 else
3071 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303072 TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003073 indexedExpression =
3074 intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003075 }
3076 if (indexedExpression == nullptr)
3077 {
3078 recover();
3079 indexedExpression = baseExpression;
3080 }
3081 else
3082 {
3083 // Note that the qualifier set here will be corrected later.
Jamie Madillb98c3a82015-07-23 14:26:04 -04003084 indexedExpression->setType(TType(baseExpression->getBasicType(),
3085 baseExpression->getPrecision(), EvqTemporary,
Jamie Madillc2128ff2016-07-04 10:26:17 -04003086 static_cast<unsigned char>(fields.num)));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003087 }
3088 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003089 else if (baseExpression->getBasicType() == EbtStruct)
3090 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003091 bool fieldFound = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05303092 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003093 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003094 {
3095 error(dotLocation, "structure has no fields", "Internal Error");
3096 recover();
3097 indexedExpression = baseExpression;
3098 }
3099 else
3100 {
3101 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003102 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003103 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003104 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003105 {
3106 fieldFound = true;
3107 break;
3108 }
3109 }
3110 if (fieldFound)
3111 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003112 if (baseExpression->getAsConstantUnion())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003113 {
3114 indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
3115 if (indexedExpression == 0)
3116 {
3117 recover();
3118 indexedExpression = baseExpression;
3119 }
3120 else
3121 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003122 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003123 }
3124 }
3125 else
3126 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003127 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003128 unionArray->setIConst(i);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003129 TIntermTyped *index = intermediate.addConstantUnion(
3130 unionArray, *fields[i]->type(), fieldLocation);
3131 indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression,
3132 index, dotLocation);
Jamie Madill98493dd2013-07-08 14:39:03 -04003133 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003134 }
3135 }
3136 else
3137 {
3138 error(dotLocation, " no such field in structure", fieldString.c_str());
3139 recover();
3140 indexedExpression = baseExpression;
3141 }
3142 }
3143 }
Jamie Madill98493dd2013-07-08 14:39:03 -04003144 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003145 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003146 bool fieldFound = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05303147 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003148 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003149 {
3150 error(dotLocation, "interface block has no fields", "Internal Error");
3151 recover();
3152 indexedExpression = baseExpression;
3153 }
3154 else
3155 {
3156 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003157 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003158 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003159 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003160 {
3161 fieldFound = true;
3162 break;
3163 }
3164 }
3165 if (fieldFound)
3166 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003167 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003168 unionArray->setIConst(i);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003169 TIntermTyped *index =
3170 intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
3171 indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock,
3172 baseExpression, index, dotLocation);
Jamie Madill98493dd2013-07-08 14:39:03 -04003173 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003174 }
3175 else
3176 {
3177 error(dotLocation, " no such field in interface block", fieldString.c_str());
3178 recover();
3179 indexedExpression = baseExpression;
3180 }
3181 }
3182 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003183 else
3184 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003185 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003186 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03003187 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303188 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003189 }
3190 else
3191 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303192 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03003193 " field selection requires structure, vector, or interface block on left hand "
3194 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303195 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003196 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003197 recover();
3198 indexedExpression = baseExpression;
3199 }
3200
Olli Etuahob1edc4f2015-11-02 17:20:03 +02003201 if (baseExpression->getQualifier() == EvqConst)
3202 {
3203 indexedExpression->getTypePointer()->setQualifier(EvqConst);
3204 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003205 else
3206 {
3207 indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
3208 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02003209
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003210 return indexedExpression;
3211}
3212
Jamie Madillb98c3a82015-07-23 14:26:04 -04003213TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3214 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003215{
Martin Radev802abe02016-08-04 17:48:32 +03003216 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003217
3218 if (qualifierType == "shared")
3219 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003220 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003221 }
3222 else if (qualifierType == "packed")
3223 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003224 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003225 }
3226 else if (qualifierType == "std140")
3227 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003228 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003229 }
3230 else if (qualifierType == "row_major")
3231 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003232 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003233 }
3234 else if (qualifierType == "column_major")
3235 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003236 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003237 }
3238 else if (qualifierType == "location")
3239 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003240 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(),
3241 "location requires an argument");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003242 recover();
3243 }
3244 else
3245 {
3246 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
3247 recover();
3248 }
3249
Jamie Madilla5efff92013-06-06 11:56:47 -04003250 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003251}
3252
Martin Radev802abe02016-08-04 17:48:32 +03003253void TParseContext::parseLocalSize(const TString &qualifierType,
3254 const TSourceLoc &qualifierTypeLine,
3255 int intValue,
3256 const TSourceLoc &intValueLine,
3257 const std::string &intValueString,
3258 size_t index,
3259 TLocalSize *localSize)
3260{
3261 layoutSupportedErrorCheck(qualifierTypeLine, qualifierType, 310);
3262 if (intValue < 1)
3263 {
3264 std::string errorMessage = std::string(getLocalSizeString(index)) + " must be positive";
3265 error(intValueLine, "out of range:", intValueString.c_str(), errorMessage.c_str());
3266 recover();
3267 }
3268 (*localSize)[index] = intValue;
3269}
3270
Jamie Madillb98c3a82015-07-23 14:26:04 -04003271TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3272 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003273 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303274 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003275{
Martin Radev802abe02016-08-04 17:48:32 +03003276 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003277
Martin Radev802abe02016-08-04 17:48:32 +03003278 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003279
Martin Radev802abe02016-08-04 17:48:32 +03003280 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003281 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003282 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003283 if (intValue < 0)
3284 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003285 error(intValueLine, "out of range:", intValueString.c_str(),
3286 "location must be non-negative");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003287 recover();
3288 }
3289 else
3290 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003291 qualifier.location = intValue;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003292 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003293 }
Martin Radev802abe02016-08-04 17:48:32 +03003294 else if (qualifierType == "local_size_x")
3295 {
3296 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3297 &qualifier.localSize);
3298 }
3299 else if (qualifierType == "local_size_y")
3300 {
3301 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3302 &qualifier.localSize);
3303 }
3304 else if (qualifierType == "local_size_z")
3305 {
3306 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3307 &qualifier.localSize);
3308 }
3309 else
3310 {
3311 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
3312 recover();
3313 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003314
Jamie Madilla5efff92013-06-06 11:56:47 -04003315 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003316}
3317
Jamie Madillb98c3a82015-07-23 14:26:04 -04003318TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003319 TLayoutQualifier rightQualifier,
3320 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003321{
Jamie Madilla5efff92013-06-06 11:56:47 -04003322 TLayoutQualifier joinedQualifier = leftQualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003323
Jamie Madilla5efff92013-06-06 11:56:47 -04003324 if (rightQualifier.location != -1)
3325 {
3326 joinedQualifier.location = rightQualifier.location;
3327 }
3328 if (rightQualifier.matrixPacking != EmpUnspecified)
3329 {
3330 joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
3331 }
3332 if (rightQualifier.blockStorage != EbsUnspecified)
3333 {
3334 joinedQualifier.blockStorage = rightQualifier.blockStorage;
3335 }
3336
Martin Radev802abe02016-08-04 17:48:32 +03003337 for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i)
3338 {
3339 if (rightQualifier.localSize[i] != -1)
3340 {
3341 if (joinedQualifier.localSize[i] != -1 &&
3342 joinedQualifier.localSize[i] != rightQualifier.localSize[i])
3343 {
3344 error(rightQualifierLocation,
3345 "Cannot have multiple different work group size specifiers",
3346 getLocalSizeString(i));
3347 recover();
3348 }
3349 joinedQualifier.localSize[i] = rightQualifier.localSize[i];
3350 }
3351 }
3352
Jamie Madilla5efff92013-06-06 11:56:47 -04003353 return joinedQualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003354}
3355
Arun Patole7e7e68d2015-05-22 12:02:25 +05303356TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc,
3357 TQualifier interpolationQualifier,
3358 const TSourceLoc &storageLoc,
3359 TQualifier storageQualifier)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003360{
3361 TQualifier mergedQualifier = EvqSmoothIn;
3362
Arun Patole7e7e68d2015-05-22 12:02:25 +05303363 if (storageQualifier == EvqFragmentIn)
3364 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003365 if (interpolationQualifier == EvqSmooth)
3366 mergedQualifier = EvqSmoothIn;
3367 else if (interpolationQualifier == EvqFlat)
3368 mergedQualifier = EvqFlatIn;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003369 else
3370 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003371 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303372 else if (storageQualifier == EvqCentroidIn)
3373 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003374 if (interpolationQualifier == EvqSmooth)
3375 mergedQualifier = EvqCentroidIn;
3376 else if (interpolationQualifier == EvqFlat)
3377 mergedQualifier = EvqFlatIn;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003378 else
3379 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003380 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303381 else if (storageQualifier == EvqVertexOut)
3382 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003383 if (interpolationQualifier == EvqSmooth)
3384 mergedQualifier = EvqSmoothOut;
3385 else if (interpolationQualifier == EvqFlat)
3386 mergedQualifier = EvqFlatOut;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003387 else
3388 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003389 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303390 else if (storageQualifier == EvqCentroidOut)
3391 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003392 if (interpolationQualifier == EvqSmooth)
3393 mergedQualifier = EvqCentroidOut;
3394 else if (interpolationQualifier == EvqFlat)
3395 mergedQualifier = EvqFlatOut;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003396 else
3397 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003398 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303399 else
3400 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003401 error(interpolationLoc,
3402 "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303403 getInterpolationString(interpolationQualifier));
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003404 recover();
3405
3406 mergedQualifier = storageQualifier;
3407 }
3408
3409 TPublicType type;
3410 type.setBasic(EbtVoid, mergedQualifier, storageLoc);
3411 return type;
3412}
3413
Jamie Madillb98c3a82015-07-23 14:26:04 -04003414TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3415 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003416{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03003417 if (voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type))
3418 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003419 recover();
3420 }
3421
Martin Radev802abe02016-08-04 17:48:32 +03003422 if (layoutWorkGroupSizeErrorCheck(typeSpecifier.line, typeSpecifier.layoutQualifier))
3423 {
3424 recover();
3425 }
3426
Arun Patole7e7e68d2015-05-22 12:02:25 +05303427 for (unsigned int i = 0; i < fieldList->size(); ++i)
3428 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003429 //
3430 // Careful not to replace already known aspects of type, like array-ness
3431 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303432 TType *type = (*fieldList)[i]->type();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003433 type->setBasicType(typeSpecifier.type);
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003434 type->setPrimarySize(typeSpecifier.primarySize);
3435 type->setSecondarySize(typeSpecifier.secondarySize);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003436 type->setPrecision(typeSpecifier.precision);
3437 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003438 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003439
3440 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303441 if (type->isArray())
3442 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003443 if (arrayTypeErrorCheck(typeSpecifier.line, typeSpecifier))
3444 recover();
3445 }
3446 if (typeSpecifier.array)
3447 type->setArraySize(typeSpecifier.arraySize);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303448 if (typeSpecifier.userDef)
3449 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003450 type->setStruct(typeSpecifier.userDef->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003451 }
3452
Arun Patole7e7e68d2015-05-22 12:02:25 +05303453 if (structNestingErrorCheck(typeSpecifier.line, *(*fieldList)[i]))
3454 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003455 recover();
3456 }
3457 }
3458
Jamie Madill98493dd2013-07-08 14:39:03 -04003459 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003460}
3461
Jamie Madillb98c3a82015-07-23 14:26:04 -04003462TPublicType TParseContext::addStructure(const TSourceLoc &structLine,
3463 const TSourceLoc &nameLine,
3464 const TString *structName,
3465 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003466{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303467 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003468 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003469
Jamie Madill9b820842015-02-12 10:40:10 -05003470 // Store a bool in the struct if we're at global scope, to allow us to
3471 // skip the local struct scoping workaround in HLSL.
Jamie Madillb960cc42015-02-12 15:33:20 +00003472 structure->setUniqueId(TSymbolTable::nextUniqueId());
Jamie Madill9b820842015-02-12 10:40:10 -05003473 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003474
Jamie Madill98493dd2013-07-08 14:39:03 -04003475 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003476 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003477 if (reservedErrorCheck(nameLine, *structName))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003478 {
3479 recover();
3480 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303481 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3482 if (!symbolTable.declare(userTypeDef))
3483 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003484 error(nameLine, "redefinition", structName->c_str(), "struct");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003485 recover();
3486 }
3487 }
3488
3489 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003490 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003491 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003492 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003493 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003494 switch (qualifier)
3495 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003496 case EvqGlobal:
3497 case EvqTemporary:
3498 break;
3499 default:
3500 error(field.line(), "invalid qualifier on struct member",
3501 getQualifierString(qualifier));
3502 recover();
3503 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003504 }
3505 }
3506
3507 TPublicType publicType;
3508 publicType.setBasic(EbtStruct, EvqTemporary, structLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04003509 publicType.userDef = structureType;
Olli Etuahobd163f62015-11-13 12:15:38 +02003510 publicType.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003511 exitStructDeclaration();
3512
3513 return publicType;
3514}
3515
Jamie Madillb98c3a82015-07-23 14:26:04 -04003516TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
3517 TIntermAggregate *statementList,
3518 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003519{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003520 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003521 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003522 init->isVector())
3523 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003524 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3525 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003526 recover();
3527 return nullptr;
3528 }
3529
Olli Etuahoac5274d2015-02-20 10:19:08 +02003530 if (statementList)
3531 {
3532 if (!ValidateSwitch::validate(switchType, this, statementList, loc))
3533 {
3534 recover();
3535 return nullptr;
3536 }
3537 }
3538
Olli Etuahoa3a36662015-02-17 13:46:51 +02003539 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3540 if (node == nullptr)
3541 {
3542 error(loc, "erroneous switch statement", "switch");
3543 recover();
3544 return nullptr;
3545 }
3546 return node;
3547}
3548
3549TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3550{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003551 if (mSwitchNestingLevel == 0)
3552 {
3553 error(loc, "case labels need to be inside switch statements", "case");
3554 recover();
3555 return nullptr;
3556 }
3557 if (condition == nullptr)
3558 {
3559 error(loc, "case label must have a condition", "case");
3560 recover();
3561 return nullptr;
3562 }
3563 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003564 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003565 {
3566 error(condition->getLine(), "case label must be a scalar integer", "case");
3567 recover();
3568 }
3569 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003570 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3571 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3572 // fold in case labels.
3573 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003574 {
3575 error(condition->getLine(), "case label must be constant", "case");
3576 recover();
3577 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003578 TIntermCase *node = intermediate.addCase(condition, loc);
3579 if (node == nullptr)
3580 {
3581 error(loc, "erroneous case statement", "case");
3582 recover();
3583 return nullptr;
3584 }
3585 return node;
3586}
3587
3588TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3589{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003590 if (mSwitchNestingLevel == 0)
3591 {
3592 error(loc, "default labels need to be inside switch statements", "default");
3593 recover();
3594 return nullptr;
3595 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003596 TIntermCase *node = intermediate.addCase(nullptr, loc);
3597 if (node == nullptr)
3598 {
3599 error(loc, "erroneous default statement", "default");
3600 recover();
3601 return nullptr;
3602 }
3603 return node;
3604}
3605
Jamie Madillb98c3a82015-07-23 14:26:04 -04003606TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3607 TIntermTyped *child,
3608 const TSourceLoc &loc,
3609 const TType *funcReturnType)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003610{
3611 if (child == nullptr)
3612 {
3613 return nullptr;
3614 }
3615
3616 switch (op)
3617 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003618 case EOpLogicalNot:
3619 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3620 child->isVector())
3621 {
3622 return nullptr;
3623 }
3624 break;
3625 case EOpBitwiseNot:
3626 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3627 child->isMatrix() || child->isArray())
3628 {
3629 return nullptr;
3630 }
3631 break;
3632 case EOpPostIncrement:
3633 case EOpPreIncrement:
3634 case EOpPostDecrement:
3635 case EOpPreDecrement:
3636 case EOpNegative:
3637 case EOpPositive:
3638 if (child->getBasicType() == EbtStruct || child->getBasicType() == EbtBool ||
3639 child->isArray())
3640 {
3641 return nullptr;
3642 }
3643 // Operators for built-ins are already type checked against their prototype.
3644 default:
3645 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003646 }
3647
Olli Etuahof6c694b2015-03-26 14:50:53 +02003648 return intermediate.addUnaryMath(op, child, loc, funcReturnType);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003649}
3650
Olli Etuaho09b22472015-02-11 11:47:26 +02003651TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3652{
Olli Etuahof6c694b2015-03-26 14:50:53 +02003653 TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003654 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003655 {
3656 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
3657 recover();
3658 return child;
3659 }
3660 return node;
3661}
3662
Jamie Madillb98c3a82015-07-23 14:26:04 -04003663TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3664 TIntermTyped *child,
3665 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003666{
3667 if (lValueErrorCheck(loc, GetOperatorString(op), child))
3668 recover();
3669 return addUnaryMath(op, child, loc);
3670}
3671
Jamie Madillb98c3a82015-07-23 14:26:04 -04003672bool TParseContext::binaryOpCommonCheck(TOperator op,
3673 TIntermTyped *left,
3674 TIntermTyped *right,
3675 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003676{
3677 if (left->isArray() || right->isArray())
3678 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003679 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003680 {
3681 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3682 return false;
3683 }
3684
3685 if (left->isArray() != right->isArray())
3686 {
3687 error(loc, "array / non-array mismatch", GetOperatorString(op));
3688 return false;
3689 }
3690
3691 switch (op)
3692 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003693 case EOpEqual:
3694 case EOpNotEqual:
3695 case EOpAssign:
3696 case EOpInitialize:
3697 break;
3698 default:
3699 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3700 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02003701 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03003702 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02003703 if (left->getArraySize() != right->getArraySize())
3704 {
3705 error(loc, "array size mismatch", GetOperatorString(op));
3706 return false;
3707 }
Olli Etuahod6b14282015-03-17 14:31:35 +02003708 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003709
3710 // Check ops which require integer / ivec parameters
3711 bool isBitShift = false;
3712 switch (op)
3713 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003714 case EOpBitShiftLeft:
3715 case EOpBitShiftRight:
3716 case EOpBitShiftLeftAssign:
3717 case EOpBitShiftRightAssign:
3718 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3719 // check that the basic type is an integer type.
3720 isBitShift = true;
3721 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3722 {
3723 return false;
3724 }
3725 break;
3726 case EOpBitwiseAnd:
3727 case EOpBitwiseXor:
3728 case EOpBitwiseOr:
3729 case EOpBitwiseAndAssign:
3730 case EOpBitwiseXorAssign:
3731 case EOpBitwiseOrAssign:
3732 // It is enough to check the type of only one operand, since later it
3733 // is checked that the operand types match.
3734 if (!IsInteger(left->getBasicType()))
3735 {
3736 return false;
3737 }
3738 break;
3739 default:
3740 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003741 }
3742
3743 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3744 // So the basic type should usually match.
3745 if (!isBitShift && left->getBasicType() != right->getBasicType())
3746 {
3747 return false;
3748 }
3749
Olli Etuaho9dd217b2015-03-20 14:24:31 +02003750 // Check that type sizes match exactly on ops that require that.
Olli Etuahoff699002015-03-23 14:38:42 +02003751 // Also check restrictions for structs that contain arrays or samplers.
Jamie Madillb98c3a82015-07-23 14:26:04 -04003752 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003753 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003754 case EOpAssign:
3755 case EOpInitialize:
3756 case EOpEqual:
3757 case EOpNotEqual:
3758 // ESSL 1.00 sections 5.7, 5.8, 5.9
3759 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
3760 {
3761 error(loc, "undefined operation for structs containing arrays",
3762 GetOperatorString(op));
3763 return false;
3764 }
3765 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3766 // we interpret the spec so that this extends to structs containing samplers,
3767 // similarly to ESSL 1.00 spec.
3768 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
3769 left->getType().isStructureContainingSamplers())
3770 {
3771 error(loc, "undefined operation for structs containing samplers",
3772 GetOperatorString(op));
3773 return false;
3774 }
3775 case EOpLessThan:
3776 case EOpGreaterThan:
3777 case EOpLessThanEqual:
3778 case EOpGreaterThanEqual:
3779 if ((left->getNominalSize() != right->getNominalSize()) ||
3780 (left->getSecondarySize() != right->getSecondarySize()))
3781 {
3782 return false;
3783 }
3784 default:
3785 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003786 }
3787
Olli Etuahod6b14282015-03-17 14:31:35 +02003788 return true;
3789}
3790
Jamie Madillb98c3a82015-07-23 14:26:04 -04003791TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
3792 TIntermTyped *left,
3793 TIntermTyped *right,
3794 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02003795{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003796 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003797 return nullptr;
3798
Olli Etuahofc1806e2015-03-17 13:03:11 +02003799 switch (op)
3800 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003801 case EOpEqual:
3802 case EOpNotEqual:
3803 break;
3804 case EOpLessThan:
3805 case EOpGreaterThan:
3806 case EOpLessThanEqual:
3807 case EOpGreaterThanEqual:
3808 ASSERT(!left->isArray() && !right->isArray());
3809 if (left->isMatrix() || left->isVector() || left->getBasicType() == EbtStruct)
3810 {
3811 return nullptr;
3812 }
3813 break;
3814 case EOpLogicalOr:
3815 case EOpLogicalXor:
3816 case EOpLogicalAnd:
3817 ASSERT(!left->isArray() && !right->isArray());
3818 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isVector())
3819 {
3820 return nullptr;
3821 }
3822 break;
3823 case EOpAdd:
3824 case EOpSub:
3825 case EOpDiv:
3826 case EOpMul:
3827 ASSERT(!left->isArray() && !right->isArray());
3828 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
3829 {
3830 return nullptr;
3831 }
3832 break;
3833 case EOpIMod:
3834 ASSERT(!left->isArray() && !right->isArray());
3835 // Note that this is only for the % operator, not for mod()
3836 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool ||
3837 left->getBasicType() == EbtFloat)
3838 {
3839 return nullptr;
3840 }
3841 break;
3842 // Note that for bitwise ops, type checking is done in promote() to
3843 // share code between ops and compound assignment
3844 default:
3845 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02003846 }
3847
Olli Etuahofc1806e2015-03-17 13:03:11 +02003848 return intermediate.addBinaryMath(op, left, right, loc);
3849}
3850
Jamie Madillb98c3a82015-07-23 14:26:04 -04003851TIntermTyped *TParseContext::addBinaryMath(TOperator op,
3852 TIntermTyped *left,
3853 TIntermTyped *right,
3854 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003855{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003856 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003857 if (node == 0)
3858 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003859 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3860 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003861 recover();
3862 return left;
3863 }
3864 return node;
3865}
3866
Jamie Madillb98c3a82015-07-23 14:26:04 -04003867TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
3868 TIntermTyped *left,
3869 TIntermTyped *right,
3870 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003871{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003872 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003873 if (node == 0)
3874 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003875 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3876 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003877 recover();
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003878 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02003879 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003880 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
3881 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003882 }
3883 return node;
3884}
3885
Jamie Madillb98c3a82015-07-23 14:26:04 -04003886TIntermTyped *TParseContext::createAssign(TOperator op,
3887 TIntermTyped *left,
3888 TIntermTyped *right,
3889 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003890{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003891 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003892 {
3893 return intermediate.addAssign(op, left, right, loc);
3894 }
3895 return nullptr;
3896}
3897
Jamie Madillb98c3a82015-07-23 14:26:04 -04003898TIntermTyped *TParseContext::addAssign(TOperator op,
3899 TIntermTyped *left,
3900 TIntermTyped *right,
3901 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003902{
3903 TIntermTyped *node = createAssign(op, left, right, loc);
3904 if (node == nullptr)
3905 {
3906 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
3907 recover();
3908 return left;
3909 }
3910 return node;
3911}
3912
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02003913TIntermTyped *TParseContext::addComma(TIntermTyped *left,
3914 TIntermTyped *right,
3915 const TSourceLoc &loc)
3916{
Corentin Wallez0d959252016-07-12 17:26:32 -04003917 // WebGL2 section 5.26, the following results in an error:
3918 // "Sequence operator applied to void, arrays, or structs containing arrays"
3919 if (mShaderSpec == SH_WEBGL2_SPEC && (left->isArray() || left->getBasicType() == EbtVoid ||
3920 left->getType().isStructureContainingArrays() ||
3921 right->isArray() || right->getBasicType() == EbtVoid ||
3922 right->getType().isStructureContainingArrays()))
3923 {
3924 error(loc,
3925 "sequence operator is not allowed for void, arrays, or structs containing arrays",
3926 ",");
3927 recover();
3928 }
3929
Olli Etuaho15200042015-11-04 16:56:31 +02003930 return intermediate.addComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02003931}
3932
Olli Etuaho49300862015-02-20 14:54:49 +02003933TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
3934{
3935 switch (op)
3936 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003937 case EOpContinue:
3938 if (mLoopNestingLevel <= 0)
3939 {
3940 error(loc, "continue statement only allowed in loops", "");
3941 recover();
3942 }
3943 break;
3944 case EOpBreak:
3945 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
3946 {
3947 error(loc, "break statement only allowed in loops and switch statements", "");
3948 recover();
3949 }
3950 break;
3951 case EOpReturn:
3952 if (mCurrentFunctionType->getBasicType() != EbtVoid)
3953 {
3954 error(loc, "non-void function must return a value", "return");
3955 recover();
3956 }
3957 break;
3958 default:
3959 // No checks for discard
3960 break;
Olli Etuaho49300862015-02-20 14:54:49 +02003961 }
3962 return intermediate.addBranch(op, loc);
3963}
3964
Jamie Madillb98c3a82015-07-23 14:26:04 -04003965TIntermBranch *TParseContext::addBranch(TOperator op,
3966 TIntermTyped *returnValue,
3967 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02003968{
3969 ASSERT(op == EOpReturn);
3970 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003971 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02003972 {
3973 error(loc, "void function cannot return a value", "return");
3974 recover();
3975 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003976 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02003977 {
3978 error(loc, "function return is not matching type:", "return");
3979 recover();
3980 }
3981 return intermediate.addBranch(op, returnValue, loc);
3982}
3983
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003984void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
3985{
3986 ASSERT(!functionCall->isUserDefined());
3987 const TString &name = functionCall->getName();
3988 TIntermNode *offset = nullptr;
3989 TIntermSequence *arguments = functionCall->getSequence();
3990 if (name.compare(0, 16, "texelFetchOffset") == 0 ||
3991 name.compare(0, 16, "textureLodOffset") == 0 ||
3992 name.compare(0, 20, "textureProjLodOffset") == 0 ||
3993 name.compare(0, 17, "textureGradOffset") == 0 ||
3994 name.compare(0, 21, "textureProjGradOffset") == 0)
3995 {
3996 offset = arguments->back();
3997 }
3998 else if (name.compare(0, 13, "textureOffset") == 0 ||
3999 name.compare(0, 17, "textureProjOffset") == 0)
4000 {
4001 // A bias parameter might follow the offset parameter.
4002 ASSERT(arguments->size() >= 3);
4003 offset = (*arguments)[2];
4004 }
4005 if (offset != nullptr)
4006 {
4007 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
4008 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
4009 {
4010 TString unmangledName = TFunction::unmangleName(name);
4011 error(functionCall->getLine(), "Texture offset must be a constant expression",
4012 unmangledName.c_str());
4013 recover();
4014 }
4015 else
4016 {
4017 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
4018 size_t size = offsetConstantUnion->getType().getObjectSize();
4019 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
4020 for (size_t i = 0u; i < size; ++i)
4021 {
4022 int offsetValue = values[i].getIConst();
4023 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
4024 {
4025 std::stringstream tokenStream;
4026 tokenStream << offsetValue;
4027 std::string token = tokenStream.str();
4028 error(offset->getLine(), "Texture offset value out of valid range",
4029 token.c_str());
4030 recover();
4031 }
4032 }
4033 }
4034 }
4035}
4036
Jamie Madillb98c3a82015-07-23 14:26:04 -04004037TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
4038 TIntermNode *paramNode,
4039 TIntermNode *thisNode,
4040 const TSourceLoc &loc,
4041 bool *fatalError)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004042{
Jamie Madillb98c3a82015-07-23 14:26:04 -04004043 *fatalError = false;
4044 TOperator op = fnCall->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004045 TIntermTyped *callNode = nullptr;
4046
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004047 if (thisNode != nullptr)
4048 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04004049 TConstantUnion *unionArray = new TConstantUnion[1];
Jamie Madillb98c3a82015-07-23 14:26:04 -04004050 int arraySize = 0;
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004051 TIntermTyped *typedThis = thisNode->getAsTyped();
4052 if (fnCall->getName() != "length")
4053 {
4054 error(loc, "invalid method", fnCall->getName().c_str());
4055 recover();
4056 }
4057 else if (paramNode != nullptr)
4058 {
4059 error(loc, "method takes no parameters", "length");
4060 recover();
4061 }
4062 else if (typedThis == nullptr || !typedThis->isArray())
4063 {
4064 error(loc, "length can only be called on arrays", "length");
4065 recover();
4066 }
4067 else
4068 {
Olli Etuaho96e67382015-04-23 14:27:02 +03004069 arraySize = typedThis->getArraySize();
Olli Etuaho39282e12015-04-23 15:41:48 +03004070 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004071 {
Olli Etuaho39282e12015-04-23 15:41:48 +03004072 // This code path can be hit with expressions like these:
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004073 // (a = b).length()
Olli Etuaho39282e12015-04-23 15:41:48 +03004074 // (func()).length()
4075 // (int[3](0, 1, 2)).length()
Jamie Madillb98c3a82015-07-23 14:26:04 -04004076 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
4077 // expression.
4078 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
4079 // spec section 5.9 which allows "An array, vector or matrix expression with the
4080 // length method applied".
4081 error(loc, "length can only be called on array names, not on array expressions",
4082 "length");
Olli Etuaho39282e12015-04-23 15:41:48 +03004083 recover();
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004084 }
4085 }
Olli Etuaho96e67382015-04-23 14:27:02 +03004086 unionArray->setIConst(arraySize);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004087 callNode =
4088 intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004089 }
4090 else if (op != EOpNull)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004091 {
4092 //
4093 // Then this should be a constructor.
4094 // Don't go through the symbol table for constructors.
4095 // Their parameters will be verified algorithmically.
4096 //
4097 TType type(EbtVoid, EbpUndefined); // use this to get the type back
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004098 if (!constructorErrorCheck(loc, paramNode, *fnCall, op, &type))
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004099 {
4100 //
4101 // It's a constructor, of type 'type'.
4102 //
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004103 callNode = addConstructor(paramNode, &type, op, fnCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004104 }
Olli Etuaho72ba85b2015-03-04 14:23:26 +02004105
4106 if (callNode == nullptr)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004107 {
4108 recover();
4109 callNode = intermediate.setAggregateOperator(nullptr, op, loc);
4110 }
4111 callNode->setType(type);
4112 }
4113 else
4114 {
4115 //
4116 // Not a constructor. Find it in the symbol table.
4117 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05304118 const TFunction *fnCandidate;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004119 bool builtIn;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004120 fnCandidate = findFunction(loc, fnCall, mShaderVersion, &builtIn);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004121 if (fnCandidate)
4122 {
4123 //
4124 // A declared function.
4125 //
4126 if (builtIn && !fnCandidate->getExtension().empty() &&
4127 extensionErrorCheck(loc, fnCandidate->getExtension()))
4128 {
4129 recover();
4130 }
4131 op = fnCandidate->getBuiltInOp();
4132 if (builtIn && op != EOpNull)
4133 {
4134 //
4135 // A function call mapped to a built-in operation.
4136 //
4137 if (fnCandidate->getParamCount() == 1)
4138 {
4139 //
4140 // Treat it like a built-in unary operator.
4141 //
Olli Etuaho15c2ac32015-11-09 15:51:43 +02004142 TIntermAggregate *paramAgg = paramNode->getAsAggregate();
4143 paramNode = paramAgg->getSequence()->front();
Jamie Madillb98c3a82015-07-23 14:26:04 -04004144 callNode = createUnaryMath(op, paramNode->getAsTyped(), loc,
4145 &fnCandidate->getReturnType());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004146 if (callNode == nullptr)
4147 {
4148 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004149 extraInfoStream
4150 << "built in unary operator function. Type: "
4151 << static_cast<TIntermTyped *>(paramNode)->getCompleteString();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004152 std::string extraInfo = extraInfoStream.str();
Jamie Madillb98c3a82015-07-23 14:26:04 -04004153 error(paramNode->getLine(), " wrong operand type", "Internal Error",
4154 extraInfo.c_str());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004155 *fatalError = true;
4156 return nullptr;
4157 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004158 }
4159 else
4160 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004161 TIntermAggregate *aggregate =
4162 intermediate.setAggregateOperator(paramNode, op, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004163 aggregate->setType(fnCandidate->getReturnType());
4164 aggregate->setPrecisionFromChildren();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02004165 if (aggregate->areChildrenConstQualified())
4166 {
4167 aggregate->getTypePointer()->setQualifier(EvqConst);
4168 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004169
4170 // Some built-in functions have out parameters too.
4171 functionCallLValueErrorCheck(fnCandidate, aggregate);
Arun Patole274f0702015-05-05 13:33:30 +05304172
Olli Etuaho7c3848e2015-11-04 13:19:17 +02004173 // See if we can constant fold a built-in. Note that this may be possible even
4174 // if it is not const-qualified.
Olli Etuahob43846e2015-06-02 18:18:57 +03004175 TIntermTyped *foldedNode = intermediate.foldAggregateBuiltIn(aggregate);
Arun Patole274f0702015-05-05 13:33:30 +05304176 if (foldedNode)
4177 {
Arun Patole274f0702015-05-05 13:33:30 +05304178 callNode = foldedNode;
4179 }
Olli Etuahob43846e2015-06-02 18:18:57 +03004180 else
4181 {
4182 callNode = aggregate;
4183 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004184 }
4185 }
4186 else
4187 {
4188 // This is a real function call
Jamie Madillb98c3a82015-07-23 14:26:04 -04004189 TIntermAggregate *aggregate =
4190 intermediate.setAggregateOperator(paramNode, EOpFunctionCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004191 aggregate->setType(fnCandidate->getReturnType());
4192
Jamie Madillb98c3a82015-07-23 14:26:04 -04004193 // this is how we know whether the given function is a builtIn function or a user
4194 // defined function
4195 // if builtIn == false, it's a userDefined -> could be an overloaded
4196 // builtIn function also
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004197 // if builtIn == true, it's definitely a builtIn function with EOpNull
4198 if (!builtIn)
4199 aggregate->setUserDefined();
4200 aggregate->setName(fnCandidate->getMangledName());
Corentin Wallez71d147f2015-02-11 11:15:24 -08004201 aggregate->setFunctionId(fnCandidate->getUniqueId());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004202
4203 // This needs to happen after the name is set
4204 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004205 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004206 aggregate->setBuiltInFunctionPrecision();
4207
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004208 checkTextureOffsetConst(aggregate);
4209 }
4210
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004211 callNode = aggregate;
4212
4213 functionCallLValueErrorCheck(fnCandidate, aggregate);
4214 }
4215 }
4216 else
4217 {
4218 // error message was put out by findFunction()
4219 // Put on a dummy node for error recovery
Jamie Madill6ba6ead2015-05-04 14:21:21 -04004220 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004221 unionArray->setFConst(0.0f);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004222 callNode = intermediate.addConstantUnion(unionArray,
4223 TType(EbtFloat, EbpUndefined, EvqConst), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004224 recover();
4225 }
4226 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004227 return callNode;
4228}
4229
Jamie Madillb98c3a82015-07-23 14:26:04 -04004230TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
4231 TIntermTyped *trueBlock,
4232 TIntermTyped *falseBlock,
Olli Etuaho52901742015-04-15 13:42:45 +03004233 const TSourceLoc &loc)
4234{
4235 if (boolErrorCheck(loc, cond))
4236 recover();
4237
4238 if (trueBlock->getType() != falseBlock->getType())
4239 {
4240 binaryOpError(loc, ":", trueBlock->getCompleteString(), falseBlock->getCompleteString());
4241 recover();
4242 return falseBlock;
4243 }
Olli Etuahoa2d53032015-04-15 14:14:44 +03004244 // ESSL1 sections 5.2 and 5.7:
4245 // ESSL3 section 5.7:
4246 // Ternary operator is not among the operators allowed for structures/arrays.
4247 if (trueBlock->isArray() || trueBlock->getBasicType() == EbtStruct)
4248 {
4249 error(loc, "ternary operator is not allowed for structures or arrays", ":");
4250 recover();
4251 return falseBlock;
4252 }
Corentin Wallez0d959252016-07-12 17:26:32 -04004253 // WebGL2 section 5.26, the following results in an error:
4254 // "Ternary operator applied to void, arrays, or structs containing arrays"
4255 if (mShaderSpec == SH_WEBGL2_SPEC && trueBlock->getBasicType() == EbtVoid)
4256 {
4257 error(loc, "ternary operator is not allowed for void", ":");
4258 recover();
4259 return falseBlock;
4260 }
4261
Olli Etuaho52901742015-04-15 13:42:45 +03004262 return intermediate.addSelection(cond, trueBlock, falseBlock, loc);
4263}
Olli Etuaho49300862015-02-20 14:54:49 +02004264
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004265//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004266// Parse an array of strings using yyparse.
4267//
4268// Returns 0 for success.
4269//
Jamie Madillb98c3a82015-07-23 14:26:04 -04004270int PaParseStrings(size_t count,
4271 const char *const string[],
4272 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05304273 TParseContext *context)
4274{
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004275 if ((count == 0) || (string == NULL))
4276 return 1;
4277
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004278 if (glslang_initialize(context))
4279 return 1;
4280
alokp@chromium.org408c45e2012-04-05 15:54:43 +00004281 int error = glslang_scan(count, string, length, context);
4282 if (!error)
4283 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004284
alokp@chromium.org73bc2982012-06-19 18:48:05 +00004285 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00004286
alokp@chromium.org6b495712012-06-29 00:06:58 +00004287 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004288}