blob: 2a5b60eef4dc4a16f2b4e2cd384c098cb9966821 [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
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135
136//
137// Used by flex/bison to output all syntax and parsing errors.
138//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530139void TParseContext::error(const TSourceLoc &loc,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400140 const char *reason,
141 const char *token,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530142 const char *extraInfo)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000143{
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000144 pp::SourceLocation srcLoc;
Jamie Madill075edd82013-07-08 13:30:19 -0400145 srcLoc.file = loc.first_file;
146 srcLoc.line = loc.first_line;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400147 mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, srcLoc, reason, token, extraInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000148}
149
Arun Patole7e7e68d2015-05-22 12:02:25 +0530150void TParseContext::warning(const TSourceLoc &loc,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400151 const char *reason,
152 const char *token,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530153 const char *extraInfo)
154{
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000155 pp::SourceLocation srcLoc;
Jamie Madill075edd82013-07-08 13:30:19 -0400156 srcLoc.file = loc.first_file;
157 srcLoc.line = loc.first_line;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400158 mDiagnostics.writeInfo(pp::Diagnostics::PP_WARNING, srcLoc, reason, token, extraInfo);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +0000159}
160
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200161void TParseContext::outOfRangeError(bool isError,
162 const TSourceLoc &loc,
163 const char *reason,
164 const char *token,
165 const char *extraInfo)
166{
167 if (isError)
168 {
169 error(loc, reason, token, extraInfo);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200170 }
171 else
172 {
173 warning(loc, reason, token, extraInfo);
174 }
175}
176
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000177//
178// Same error message for all places assignments don't work.
179//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530180void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000181{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000182 std::stringstream extraInfoStream;
183 extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
184 std::string extraInfo = extraInfoStream.str();
185 error(line, "", op, extraInfo.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000186}
187
188//
189// Same error message for all places unary operations don't work.
190//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530191void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000192{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000193 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400194 extraInfoStream << "no operation '" << op << "' exists that takes an operand of type "
195 << operand << " (or there is no acceptable conversion)";
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000196 std::string extraInfo = extraInfoStream.str();
197 error(line, " wrong operand type", op, extraInfo.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000198}
199
200//
201// Same error message for all binary operations don't work.
202//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400203void TParseContext::binaryOpError(const TSourceLoc &line,
204 const char *op,
205 TString left,
206 TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000207{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000208 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400209 extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '"
210 << left << "' and a right operand of type '" << right
211 << "' (or there is no acceptable conversion)";
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000212 std::string extraInfo = extraInfoStream.str();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530213 error(line, " wrong operand types ", op, extraInfo.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000214}
215
Olli Etuaho856c4972016-08-08 11:38:39 +0300216void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
217 TPrecision precision,
218 TBasicType type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530219{
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400220 if (!mChecksPrecisionErrors)
Olli Etuaho383b7912016-08-05 11:22:59 +0300221 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200222 if (precision == EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530223 {
Olli Etuaho183d7e22015-11-20 15:59:09 +0200224 switch (type)
225 {
226 case EbtFloat:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400227 error(line, "No precision specified for (float)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300228 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200229 case EbtInt:
230 case EbtUInt:
231 UNREACHABLE(); // there's always a predeclared qualifier
Jamie Madillb98c3a82015-07-23 14:26:04 -0400232 error(line, "No precision specified (int)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300233 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200234 default:
235 if (IsSampler(type))
236 {
237 error(line, "No precision specified (sampler)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300238 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200239 }
240 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000241 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000242}
243
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244// Both test and if necessary, spit out an error, to see if the node is really
245// an l-value that can be operated on this way.
Olli Etuaho856c4972016-08-08 11:38:39 +0300246bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400248 TIntermSymbol *symNode = node->getAsSymbolNode();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530249 TIntermBinary *binaryNode = node->getAsBinaryNode();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250
Arun Patole7e7e68d2015-05-22 12:02:25 +0530251 if (binaryNode)
252 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400253 switch (binaryNode->getOp())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530254 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400255 case EOpIndexDirect:
256 case EOpIndexIndirect:
257 case EOpIndexDirectStruct:
258 case EOpIndexDirectInterfaceBlock:
Olli Etuaho856c4972016-08-08 11:38:39 +0300259 return checkCanBeLValue(line, op, binaryNode->getLeft());
Jamie Madillb98c3a82015-07-23 14:26:04 -0400260 case EOpVectorSwizzle:
Olli Etuaho8a176262016-08-16 14:23:01 +0300261 {
262 bool ok = checkCanBeLValue(line, op, binaryNode->getLeft());
263 if (ok)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530264 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300265 int offsetCount[4] = {0, 0, 0, 0};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000266
Olli Etuaho8a176262016-08-16 14:23:01 +0300267 TIntermAggregate *swizzleOffsets = binaryNode->getRight()->getAsAggregate();
Jamie Madillb98c3a82015-07-23 14:26:04 -0400268
Olli Etuaho8a176262016-08-16 14:23:01 +0300269 for (const auto &offset : *swizzleOffsets->getSequence())
Jamie Madillb98c3a82015-07-23 14:26:04 -0400270 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300271 int value = offset->getAsTyped()->getAsConstantUnion()->getIConst(0);
272 offsetCount[value]++;
273 if (offsetCount[value] > 1)
Jamie Madillb98c3a82015-07-23 14:26:04 -0400274 {
275 error(line, " l-value of swizzle cannot have duplicate components", op);
Olli Etuaho8a176262016-08-16 14:23:01 +0300276 return false;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400277 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000278 }
279 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000280
Olli Etuaho8a176262016-08-16 14:23:01 +0300281 return ok;
282 }
Jamie Madillb98c3a82015-07-23 14:26:04 -0400283 default:
284 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000285 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000286 error(line, " l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000287
Olli Etuaho8a176262016-08-16 14:23:01 +0300288 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000289 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000290
Arun Patole7e7e68d2015-05-22 12:02:25 +0530291 const char *symbol = 0;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000292 if (symNode != 0)
293 symbol = symNode->getSymbol().c_str();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294
Arun Patole7e7e68d2015-05-22 12:02:25 +0530295 const char *message = 0;
296 switch (node->getQualifier())
297 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400298 case EvqConst:
299 message = "can't modify a const";
300 break;
301 case EvqConstReadOnly:
302 message = "can't modify a const";
303 break;
304 case EvqAttribute:
305 message = "can't modify an attribute";
306 break;
307 case EvqFragmentIn:
308 message = "can't modify an input";
309 break;
310 case EvqVertexIn:
311 message = "can't modify an input";
312 break;
313 case EvqUniform:
314 message = "can't modify a uniform";
315 break;
316 case EvqVaryingIn:
317 message = "can't modify a varying";
318 break;
319 case EvqFragCoord:
320 message = "can't modify gl_FragCoord";
321 break;
322 case EvqFrontFacing:
323 message = "can't modify gl_FrontFacing";
324 break;
325 case EvqPointCoord:
326 message = "can't modify gl_PointCoord";
327 break;
Martin Radevb0883602016-08-04 17:48:58 +0300328 case EvqNumWorkGroups:
329 message = "can't modify gl_NumWorkGroups";
330 break;
331 case EvqWorkGroupSize:
332 message = "can't modify gl_WorkGroupSize";
333 break;
334 case EvqWorkGroupID:
335 message = "can't modify gl_WorkGroupID";
336 break;
337 case EvqLocalInvocationID:
338 message = "can't modify gl_LocalInvocationID";
339 break;
340 case EvqGlobalInvocationID:
341 message = "can't modify gl_GlobalInvocationID";
342 break;
343 case EvqLocalInvocationIndex:
344 message = "can't modify gl_LocalInvocationIndex";
345 break;
Martin Radev802abe02016-08-04 17:48:32 +0300346 case EvqComputeIn:
347 message = "can't modify work group size variable";
348 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400349 default:
350 //
351 // Type that can't be written to?
352 //
353 if (node->getBasicType() == EbtVoid)
354 {
355 message = "can't modify void";
356 }
357 if (IsSampler(node->getBasicType()))
358 {
359 message = "can't modify a sampler";
360 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000361 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000362
Arun Patole7e7e68d2015-05-22 12:02:25 +0530363 if (message == 0 && binaryNode == 0 && symNode == 0)
364 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000365 error(line, " l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000366
Olli Etuaho8a176262016-08-16 14:23:01 +0300367 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000368 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000369
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000370 //
371 // Everything else is okay, no error.
372 //
373 if (message == 0)
Olli Etuaho8a176262016-08-16 14:23:01 +0300374 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000375
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000376 //
377 // If we get here, we have an error and a message.
378 //
Arun Patole7e7e68d2015-05-22 12:02:25 +0530379 if (symNode)
380 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000381 std::stringstream extraInfoStream;
382 extraInfoStream << "\"" << symbol << "\" (" << message << ")";
383 std::string extraInfo = extraInfoStream.str();
384 error(line, " l-value required", op, extraInfo.c_str());
385 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530386 else
387 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000388 std::stringstream extraInfoStream;
389 extraInfoStream << "(" << message << ")";
390 std::string extraInfo = extraInfoStream.str();
391 error(line, " l-value required", op, extraInfo.c_str());
392 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393
Olli Etuaho8a176262016-08-16 14:23:01 +0300394 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000395}
396
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000397// Both test, and if necessary spit out an error, to see if the node is really
398// a constant.
Olli Etuaho856c4972016-08-08 11:38:39 +0300399void TParseContext::checkIsConst(TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000400{
Olli Etuaho383b7912016-08-05 11:22:59 +0300401 if (node->getQualifier() != EvqConst)
402 {
403 error(node->getLine(), "constant expression required", "");
404 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000405}
406
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000407// Both test, and if necessary spit out an error, to see if the node is really
408// an integer.
Olli Etuaho856c4972016-08-08 11:38:39 +0300409void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000410{
Olli Etuaho383b7912016-08-05 11:22:59 +0300411 if (!node->isScalarInt())
412 {
413 error(node->getLine(), "integer expression required", token);
414 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000415}
416
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000417// Both test, and if necessary spit out an error, to see if we are currently
418// globally scoped.
Olli Etuaho856c4972016-08-08 11:38:39 +0300419void TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000420{
Olli Etuaho856c4972016-08-08 11:38:39 +0300421 if (!symbolTable.atGlobalLevel())
Olli Etuaho383b7912016-08-05 11:22:59 +0300422 {
423 error(line, "only allowed at global scope", token);
424 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000425}
426
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000427// For now, keep it simple: if it starts "gl_", it's reserved, independent
428// of scope. Except, if the symbol table is at the built-in push-level,
429// which is when we are parsing built-ins.
alokp@chromium.org613ef312010-07-21 18:54:22 +0000430// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
431// webgl shader.
Olli Etuaho856c4972016-08-08 11:38:39 +0300432bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000433{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530434 static const char *reservedErrMsg = "reserved built-in name";
435 if (!symbolTable.atBuiltInLevel())
436 {
437 if (identifier.compare(0, 3, "gl_") == 0)
438 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000439 error(line, reservedErrMsg, "gl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300440 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000441 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530442 if (IsWebGLBasedSpec(mShaderSpec))
443 {
444 if (identifier.compare(0, 6, "webgl_") == 0)
445 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000446 error(line, reservedErrMsg, "webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300447 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000448 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530449 if (identifier.compare(0, 7, "_webgl_") == 0)
450 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000451 error(line, reservedErrMsg, "_webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300452 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000453 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530454 if (mShaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0)
455 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000456 error(line, reservedErrMsg, "css_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300457 return false;
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +0000458 }
alokp@chromium.org613ef312010-07-21 18:54:22 +0000459 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530460 if (identifier.find("__") != TString::npos)
461 {
462 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400463 "identifiers containing two consecutive underscores (__) are reserved as "
464 "possible future keywords",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530465 identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300466 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000467 }
468 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000469
Olli Etuaho8a176262016-08-16 14:23:01 +0300470 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000471}
472
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000473// Make sure there is enough data provided to the constructor to build
474// something of the type of the constructor. Also returns the type of
475// the constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +0300476bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
477 TIntermNode *argumentsNode,
478 const TFunction &function,
479 TOperator op,
480 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000481{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000482 bool constructingMatrix = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400483 switch (op)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530484 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400485 case EOpConstructMat2:
486 case EOpConstructMat2x3:
487 case EOpConstructMat2x4:
488 case EOpConstructMat3x2:
489 case EOpConstructMat3:
490 case EOpConstructMat3x4:
491 case EOpConstructMat4x2:
492 case EOpConstructMat4x3:
493 case EOpConstructMat4:
494 constructingMatrix = true;
495 break;
496 default:
497 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000498 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000499
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000500 //
501 // Note: It's okay to have too many components available, but not okay to have unused
502 // arguments. 'full' will go to true when enough args have been seen. If we loop
503 // again, there is an extra argument, so 'overfull' will become true.
504 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000505
Jamie Madillb98c3a82015-07-23 14:26:04 -0400506 size_t size = 0;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400507 bool full = false;
508 bool overFull = false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000509 bool matrixInMatrix = false;
510 bool arrayArg = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530511 for (size_t i = 0; i < function.getParamCount(); ++i)
512 {
Dmitry Skibaefa3d8e2015-06-22 14:52:10 -0700513 const TConstParameter &param = function.getParam(i);
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000514 size += param.type->getObjectSize();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530515
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000516 if (constructingMatrix && param.type->isMatrix())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000517 matrixInMatrix = true;
518 if (full)
519 overFull = true;
Olli Etuaho856c4972016-08-08 11:38:39 +0300520 if (op != EOpConstructStruct && !type.isArray() && size >= type.getObjectSize())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000521 full = true;
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000522 if (param.type->isArray())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000523 arrayArg = true;
524 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530525
Olli Etuaho856c4972016-08-08 11:38:39 +0300526 if (type.isArray())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300527 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300528 // The size of an unsized constructor should already have been determined.
529 ASSERT(!type.isUnsizedArray());
530 if (static_cast<size_t>(type.getArraySize()) != function.getParamCount())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300531 {
532 error(line, "array constructor needs one argument per array element", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300533 return false;
Olli Etuaho376f1b52015-04-13 13:23:41 +0300534 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000535 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000536
Arun Patole7e7e68d2015-05-22 12:02:25 +0530537 if (arrayArg && op != EOpConstructStruct)
538 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000539 error(line, "constructing from a non-dereferenced array", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300540 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000541 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000542
Olli Etuaho856c4972016-08-08 11:38:39 +0300543 if (matrixInMatrix && !type.isArray())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530544 {
545 if (function.getParamCount() != 1)
546 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400547 error(line, "constructing matrix from matrix can only take one argument",
548 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300549 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000550 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000551 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000552
Arun Patole7e7e68d2015-05-22 12:02:25 +0530553 if (overFull)
554 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000555 error(line, "too many arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300556 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000557 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530558
Olli Etuaho856c4972016-08-08 11:38:39 +0300559 if (op == EOpConstructStruct && !type.isArray() &&
560 type.getStruct()->fields().size() != function.getParamCount())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530561 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400562 error(line,
563 "Number of constructor parameters does not match the number of structure fields",
564 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300565 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000566 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000567
Olli Etuaho856c4972016-08-08 11:38:39 +0300568 if (!type.isMatrix() || !matrixInMatrix)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530569 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300570 if ((op != EOpConstructStruct && size != 1 && size < type.getObjectSize()) ||
571 (op == EOpConstructStruct && size < type.getObjectSize()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530572 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000573 error(line, "not enough data provided for construction", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300574 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000575 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000576 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000577
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200578 if (argumentsNode == nullptr)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530579 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200580 error(line, "constructor does not have any arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300581 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000582 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200583
584 TIntermAggregate *argumentsAgg = argumentsNode->getAsAggregate();
585 for (TIntermNode *&argNode : *argumentsAgg->getSequence())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530586 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200587 TIntermTyped *argTyped = argNode->getAsTyped();
588 ASSERT(argTyped != nullptr);
589 if (op != EOpConstructStruct && IsSampler(argTyped->getBasicType()))
590 {
591 error(line, "cannot convert a sampler", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300592 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200593 }
594 if (argTyped->getBasicType() == EbtVoid)
595 {
596 error(line, "cannot convert a void", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300597 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200598 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000599 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000600
Olli Etuaho856c4972016-08-08 11:38:39 +0300601 if (type.isArray())
602 {
603 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
604 // the array.
605 for (TIntermNode *&argNode : *argumentsAgg->getSequence())
606 {
607 const TType &argType = argNode->getAsTyped()->getType();
608 // It has already been checked that the argument is not an array.
609 ASSERT(!argType.isArray());
610 if (!argType.sameElementType(type))
611 {
612 error(line, "Array constructor argument has an incorrect type", "Error");
Olli Etuaho8a176262016-08-16 14:23:01 +0300613 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300614 }
615 }
616 }
617 else if (op == EOpConstructStruct)
618 {
619 const TFieldList &fields = type.getStruct()->fields();
620 TIntermSequence *args = argumentsAgg->getSequence();
621
622 for (size_t i = 0; i < fields.size(); i++)
623 {
624 if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type())
625 {
626 error(line, "Structure constructor arguments do not match structure fields",
627 "Error");
Olli Etuaho8a176262016-08-16 14:23:01 +0300628 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300629 }
630 }
631 }
632
Olli Etuaho8a176262016-08-16 14:23:01 +0300633 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000634}
635
Jamie Madillb98c3a82015-07-23 14:26:04 -0400636// This function checks to see if a void variable has been declared and raise an error message for
637// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000638//
639// returns true in case of an error
640//
Olli Etuaho856c4972016-08-08 11:38:39 +0300641bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400642 const TString &identifier,
643 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000644{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300645 if (type == EbtVoid)
646 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000647 error(line, "illegal use of type 'void'", identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300648 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300649 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000650
Olli Etuaho8a176262016-08-16 14:23:01 +0300651 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000652}
653
Jamie Madillb98c3a82015-07-23 14:26:04 -0400654// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300655// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300656void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000657{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530658 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
659 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000660 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530661 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000662}
663
Jamie Madillb98c3a82015-07-23 14:26:04 -0400664// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300665// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300666void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000667{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530668 if (pType.type != EbtBool || pType.isAggregate())
669 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000670 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530671 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000672}
673
Olli Etuaho856c4972016-08-08 11:38:39 +0300674bool TParseContext::checkIsNotSampler(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400675 const TPublicType &pType,
676 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000677{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530678 if (pType.type == EbtStruct)
679 {
680 if (containsSampler(*pType.userDef))
681 {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000682 error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
Olli Etuaho8a176262016-08-16 14:23:01 +0300683 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000684 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530685
Olli Etuaho8a176262016-08-16 14:23:01 +0300686 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530687 }
688 else if (IsSampler(pType.type))
689 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000690 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300691 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000692 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000693
Olli Etuaho8a176262016-08-16 14:23:01 +0300694 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000695}
696
Olli Etuaho856c4972016-08-08 11:38:39 +0300697void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
698 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400699{
700 if (pType.layoutQualifier.location != -1)
701 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400702 error(line, "location must only be specified for a single input or output variable",
703 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400704 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400705}
706
Olli Etuaho856c4972016-08-08 11:38:39 +0300707void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
708 const TLayoutQualifier &layoutQualifier)
709{
710 if (layoutQualifier.location != -1)
711 {
712 error(location, "invalid layout qualifier:", "location",
713 "only valid on program inputs and outputs");
714 }
715}
716
717void TParseContext::checkOutParameterIsNotSampler(const TSourceLoc &line,
718 TQualifier qualifier,
719 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000720{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400721 if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct &&
722 IsSampler(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530723 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000724 error(line, "samplers cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000725 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000726}
727
Arun Patole7e7e68d2015-05-22 12:02:25 +0530728bool TParseContext::containsSampler(const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000729{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000730 if (IsSampler(type.getBasicType()))
731 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000732
Arun Patole7e7e68d2015-05-22 12:02:25 +0530733 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock())
734 {
735 const TFieldList &fields = type.getStruct()->fields();
736 for (unsigned int i = 0; i < fields.size(); ++i)
737 {
Jamie Madill98493dd2013-07-08 14:39:03 -0400738 if (containsSampler(*fields[i]->type()))
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000739 return true;
740 }
741 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000742
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000743 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000744}
745
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000746// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300747unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000748{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530749 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000750
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200751 // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
752 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
753 // fold as array size.
754 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000755 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000756 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300757 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000758 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000759
Olli Etuaho856c4972016-08-08 11:38:39 +0300760 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400761
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000762 if (constant->getBasicType() == EbtUInt)
763 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300764 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000765 }
766 else
767 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300768 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000769
Olli Etuaho856c4972016-08-08 11:38:39 +0300770 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000771 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400772 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300773 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000774 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400775
Olli Etuaho856c4972016-08-08 11:38:39 +0300776 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -0400777 }
778
Olli Etuaho856c4972016-08-08 11:38:39 +0300779 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -0400780 {
781 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300782 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400783 }
784
785 // The size of arrays is restricted here to prevent issues further down the
786 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
787 // 4096 registers so this should be reasonable even for aggressively optimizable code.
788 const unsigned int sizeLimit = 65536;
789
Olli Etuaho856c4972016-08-08 11:38:39 +0300790 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -0400791 {
792 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300793 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000794 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300795
796 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000797}
798
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000799// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +0300800bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
801 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000802{
Olli Etuaho8a176262016-08-16 14:23:01 +0300803 if ((elementQualifier.qualifier == EvqAttribute) ||
804 (elementQualifier.qualifier == EvqVertexIn) ||
805 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +0300806 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400807 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300808 TType(elementQualifier).getQualifierString());
809 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000810 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000811
Olli Etuaho8a176262016-08-16 14:23:01 +0300812 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000813}
814
Olli Etuaho8a176262016-08-16 14:23:01 +0300815// See if this element type can be formed into an array.
816bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000817{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000818 //
819 // Can the type be an array?
820 //
Olli Etuaho8a176262016-08-16 14:23:01 +0300821 if (elementType.array)
Jamie Madill06145232015-05-13 13:10:01 -0400822 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300823 error(line, "cannot declare arrays of arrays",
824 TType(elementType).getCompleteString().c_str());
825 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000826 }
Olli Etuahocc36b982015-07-10 14:14:18 +0300827 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
828 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
829 // 4.3.4).
Olli Etuaho8a176262016-08-16 14:23:01 +0300830 if (mShaderVersion >= 300 && elementType.type == EbtStruct &&
831 sh::IsVarying(elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +0300832 {
833 error(line, "cannot declare arrays of structs of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300834 TType(elementType).getCompleteString().c_str());
835 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +0300836 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000837
Olli Etuaho8a176262016-08-16 14:23:01 +0300838 return true;
839}
840
841// Check if this qualified element type can be formed into an array.
842bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
843 const TPublicType &elementType)
844{
845 if (checkIsValidTypeForArray(indexLocation, elementType))
846 {
847 return checkIsValidQualifierForArray(indexLocation, elementType);
848 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000849 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000850}
851
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000852// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +0300853void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
854 const TString &identifier,
855 TPublicType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000856{
Olli Etuaho3739d232015-04-08 12:23:44 +0300857 ASSERT(type != nullptr);
858 if (type->qualifier == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000859 {
860 // Make the qualifier make sense.
Olli Etuaho3739d232015-04-08 12:23:44 +0300861 type->qualifier = EvqTemporary;
862
863 // Generate informative error messages for ESSL1.
864 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400865 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000866 {
Arun Patole7e7e68d2015-05-22 12:02:25 +0530867 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400868 "structures containing arrays may not be declared constant since they cannot be "
869 "initialized",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530870 identifier.c_str());
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000871 }
872 else
873 {
874 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
875 }
Olli Etuaho383b7912016-08-05 11:22:59 +0300876 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000877 }
Olli Etuaho376f1b52015-04-13 13:23:41 +0300878 if (type->isUnsizedArray())
879 {
880 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
Olli Etuaho376f1b52015-04-13 13:23:41 +0300881 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000882}
883
Olli Etuaho2935c582015-04-08 14:32:06 +0300884// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000885// and update the symbol table.
886//
Olli Etuaho2935c582015-04-08 14:32:06 +0300887// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000888//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400889bool TParseContext::declareVariable(const TSourceLoc &line,
890 const TString &identifier,
891 const TType &type,
Olli Etuaho2935c582015-04-08 14:32:06 +0300892 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000893{
Olli Etuaho2935c582015-04-08 14:32:06 +0300894 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000895
Olli Etuaho856c4972016-08-08 11:38:39 +0300896 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000897
Olli Etuaho2935c582015-04-08 14:32:06 +0300898 // gl_LastFragData may be redeclared with a new precision qualifier
899 if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
900 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400901 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
902 symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Olli Etuaho856c4972016-08-08 11:38:39 +0300903 if (static_cast<int>(type.getArraySize()) == maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +0300904 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400905 if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +0300906 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300907 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
Olli Etuaho2935c582015-04-08 14:32:06 +0300908 }
909 }
910 else
911 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400912 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
913 identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +0300914 return false;
915 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000916 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000917
Olli Etuaho8a176262016-08-16 14:23:01 +0300918 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +0300919 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000920
Olli Etuaho2935c582015-04-08 14:32:06 +0300921 (*variable) = new TVariable(&identifier, type);
922 if (!symbolTable.declare(*variable))
923 {
924 error(line, "redefinition", identifier.c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -0400925 *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +0300926 return false;
927 }
928
Olli Etuaho8a176262016-08-16 14:23:01 +0300929 if (!checkIsNonVoid(line, identifier, type.getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +0300930 return false;
931
932 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000933}
934
Olli Etuaho856c4972016-08-08 11:38:39 +0300935void TParseContext::checkIsParameterQualifierValid(const TSourceLoc &line,
936 TQualifier qualifier,
937 TQualifier paramQualifier,
938 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530939{
940 if (qualifier != EvqConst && qualifier != EvqTemporary)
941 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000942 error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +0300943 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000944 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530945 if (qualifier == EvqConst && paramQualifier != EvqIn)
946 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400947 error(line, "qualifier not allowed with ", getQualifierString(qualifier),
948 getQualifierString(paramQualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +0300949 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000950 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000951
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000952 if (qualifier == EvqConst)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000953 type->setQualifier(EvqConstReadOnly);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000954 else
alokp@chromium.org58e54292010-08-24 21:40:03 +0000955 type->setQualifier(paramQualifier);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000956}
957
Olli Etuaho856c4972016-08-08 11:38:39 +0300958bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000959{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400960 const TExtensionBehavior &extBehavior = extensionBehavior();
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000961 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
Arun Patole7e7e68d2015-05-22 12:02:25 +0530962 if (iter == extBehavior.end())
963 {
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000964 error(line, "extension", extension.c_str(), "is not supported");
Olli Etuaho8a176262016-08-16 14:23:01 +0300965 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000966 }
zmo@google.comf5450912011-09-09 01:37:19 +0000967 // In GLSL ES, an extension's default behavior is "disable".
Arun Patole7e7e68d2015-05-22 12:02:25 +0530968 if (iter->second == EBhDisable || iter->second == EBhUndefined)
969 {
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000970 error(line, "extension", extension.c_str(), "is disabled");
Olli Etuaho8a176262016-08-16 14:23:01 +0300971 return false;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000972 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530973 if (iter->second == EBhWarn)
974 {
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000975 warning(line, "extension", extension.c_str(), "is being used");
Olli Etuaho8a176262016-08-16 14:23:01 +0300976 return true;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000977 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000978
Olli Etuaho8a176262016-08-16 14:23:01 +0300979 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000980}
981
Jamie Madillb98c3a82015-07-23 14:26:04 -0400982// These checks are common for all declarations starting a declarator list, and declarators that
983// follow an empty declaration.
Olli Etuaho383b7912016-08-05 11:22:59 +0300984void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400985 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -0400986{
Olli Etuahofa33d582015-04-09 14:33:12 +0300987 switch (publicType.qualifier)
988 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400989 case EvqVaryingIn:
990 case EvqVaryingOut:
991 case EvqAttribute:
992 case EvqVertexIn:
993 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +0300994 case EvqComputeIn:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400995 if (publicType.type == EbtStruct)
996 {
997 error(identifierLocation, "cannot be used with a structure",
998 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +0300999 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001000 }
Olli Etuahofa33d582015-04-09 14:33:12 +03001001
Jamie Madillb98c3a82015-07-23 14:26:04 -04001002 default:
1003 break;
Olli Etuahofa33d582015-04-09 14:33:12 +03001004 }
1005
Jamie Madillb98c3a82015-07-23 14:26:04 -04001006 if (publicType.qualifier != EvqUniform &&
Olli Etuaho8a176262016-08-16 14:23:01 +03001007 !checkIsNotSampler(identifierLocation, publicType, "samplers must be uniform"))
Olli Etuahofa33d582015-04-09 14:33:12 +03001008 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001009 return;
Olli Etuahofa33d582015-04-09 14:33:12 +03001010 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001011
1012 // check for layout qualifier issues
1013 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
1014
1015 if (layoutQualifier.matrixPacking != EmpUnspecified)
1016 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001017 error(identifierLocation, "layout qualifier",
1018 getMatrixPackingString(layoutQualifier.matrixPacking),
Olli Etuahofa33d582015-04-09 14:33:12 +03001019 "only valid for interface blocks");
Olli Etuaho383b7912016-08-05 11:22:59 +03001020 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001021 }
1022
1023 if (layoutQualifier.blockStorage != EbsUnspecified)
1024 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001025 error(identifierLocation, "layout qualifier",
1026 getBlockStorageString(layoutQualifier.blockStorage),
Olli Etuahofa33d582015-04-09 14:33:12 +03001027 "only valid for interface blocks");
Olli Etuaho383b7912016-08-05 11:22:59 +03001028 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001029 }
1030
Olli Etuaho383b7912016-08-05 11:22:59 +03001031 if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut)
Jamie Madilla5efff92013-06-06 11:56:47 -04001032 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001033 checkLocationIsNotSpecified(identifierLocation, publicType.layoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04001034 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001035}
1036
Olli Etuaho856c4972016-08-08 11:38:39 +03001037void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1038 const TString &layoutQualifierName,
1039 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001040{
1041
1042 if (mShaderVersion < versionRequired)
1043 {
1044 error(location, "invalid layout qualifier:", layoutQualifierName.c_str(), "not supported");
Martin Radev802abe02016-08-04 17:48:32 +03001045 }
1046}
1047
Olli Etuaho856c4972016-08-08 11:38:39 +03001048bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1049 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001050{
1051 const TLocalSize &localSize = layoutQualifier.localSize;
1052 for (size_t i = 0u; i < localSize.size(); ++i)
1053 {
1054 if (localSize[i] != -1)
1055 {
1056 error(location, "invalid layout qualifier:", getLocalSizeString(i),
1057 "only valid when used with 'in' in a compute shader global layout declaration");
Olli Etuaho8a176262016-08-16 14:23:01 +03001058 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001059 }
1060 }
1061
Olli Etuaho8a176262016-08-16 14:23:01 +03001062 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001063}
1064
Olli Etuaho383b7912016-08-05 11:22:59 +03001065void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
Olli Etuaho856c4972016-08-08 11:38:39 +03001066 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001067{
1068 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1069 {
1070 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1071 if (qual == EvqOut || qual == EvqInOut)
1072 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001073 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho8a176262016-08-16 14:23:01 +03001074 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001075 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001076 error(argument->getLine(),
Jamie Madillb98c3a82015-07-23 14:26:04 -04001077 "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
Olli Etuaho383b7912016-08-05 11:22:59 +03001078 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001079 }
1080 }
1081 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001082}
1083
Olli Etuaho856c4972016-08-08 11:38:39 +03001084void TParseContext::checkInvariantIsOutVariableES3(const TQualifier qualifier,
1085 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001086{
1087 if (!sh::IsVaryingOut(qualifier) && qualifier != EvqFragmentOut)
1088 {
1089 error(invariantLocation, "Only out variables can be invariant.", "invariant");
Olli Etuaho37ad4742015-04-27 13:18:50 +03001090 }
1091}
1092
Arun Patole7e7e68d2015-05-22 12:02:25 +05301093bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001094{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001095 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001096 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1097 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001098}
1099
Arun Patole7e7e68d2015-05-22 12:02:25 +05301100bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001101{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001102 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001103}
1104
Jamie Madillb98c3a82015-07-23 14:26:04 -04001105void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1106 const char *extName,
1107 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001108{
1109 pp::SourceLocation srcLoc;
1110 srcLoc.file = loc.first_file;
1111 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001112 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001113}
1114
Jamie Madillb98c3a82015-07-23 14:26:04 -04001115void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1116 const char *name,
1117 const char *value,
1118 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001119{
1120 pp::SourceLocation srcLoc;
1121 srcLoc.file = loc.first_file;
1122 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001123 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001124}
1125
Martin Radev802abe02016-08-04 17:48:32 +03001126TLocalSize TParseContext::getComputeShaderLocalSize() const
1127{
1128 TLocalSize result;
1129 for (size_t i = 0u; i < result.size(); ++i)
1130 {
1131 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1132 {
1133 result[i] = 1;
1134 }
1135 else
1136 {
1137 result[i] = mComputeShaderLocalSize[i];
1138 }
1139 }
1140 return result;
1141}
1142
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001143/////////////////////////////////////////////////////////////////////////////////
1144//
1145// Non-Errors.
1146//
1147/////////////////////////////////////////////////////////////////////////////////
1148
Jamie Madill5c097022014-08-20 16:38:32 -04001149const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1150 const TString *name,
1151 const TSymbol *symbol)
1152{
1153 const TVariable *variable = NULL;
1154
1155 if (!symbol)
1156 {
1157 error(location, "undeclared identifier", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001158 }
1159 else if (!symbol->isVariable())
1160 {
1161 error(location, "variable expected", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001162 }
1163 else
1164 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001165 variable = static_cast<const TVariable *>(symbol);
Jamie Madill5c097022014-08-20 16:38:32 -04001166
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001167 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
Olli Etuaho383b7912016-08-05 11:22:59 +03001168 !variable->getExtension().empty())
Jamie Madill5c097022014-08-20 16:38:32 -04001169 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001170 checkCanUseExtension(location, variable->getExtension());
Jamie Madill5c097022014-08-20 16:38:32 -04001171 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001172
1173 // Reject shaders using both gl_FragData and gl_FragColor
1174 TQualifier qualifier = variable->getType().getQualifier();
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001175 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001176 {
1177 mUsesFragData = true;
1178 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001179 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001180 {
1181 mUsesFragColor = true;
1182 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001183 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1184 {
1185 mUsesSecondaryOutputs = true;
1186 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001187
1188 // This validation is not quite correct - it's only an error to write to
1189 // both FragData and FragColor. For simplicity, and because users shouldn't
1190 // be rewarded for reading from undefined varaibles, return an error
1191 // if they are both referenced, rather than assigned.
1192 if (mUsesFragData && mUsesFragColor)
1193 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001194 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1195 if (mUsesSecondaryOutputs)
1196 {
1197 errorMessage =
1198 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1199 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1200 }
1201 error(location, errorMessage, name->c_str());
Jamie Madill14e95b32015-05-07 10:10:41 -04001202 }
Martin Radevb0883602016-08-04 17:48:58 +03001203
1204 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1205 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1206 qualifier == EvqWorkGroupSize)
1207 {
1208 error(location,
1209 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1210 "gl_WorkGroupSize");
1211 }
Jamie Madill5c097022014-08-20 16:38:32 -04001212 }
1213
1214 if (!variable)
1215 {
1216 TType type(EbtFloat, EbpUndefined);
1217 TVariable *fakeVariable = new TVariable(name, type);
1218 symbolTable.declare(fakeVariable);
1219 variable = fakeVariable;
1220 }
1221
1222 return variable;
1223}
1224
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001225TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1226 const TString *name,
1227 const TSymbol *symbol)
1228{
1229 const TVariable *variable = getNamedVariable(location, name, symbol);
1230
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001231 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001232 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001233 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001234 return intermediate.addConstantUnion(constArray, variable->getType(), location);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001235 }
1236 else
1237 {
1238 return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
1239 variable->getType(), location);
1240 }
1241}
1242
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001243//
1244// Look up a function name in the symbol table, and make sure it is a function.
1245//
1246// Return the function symbol if found, otherwise 0.
1247//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001248const TFunction *TParseContext::findFunction(const TSourceLoc &line,
1249 TFunction *call,
1250 int inputShaderVersion,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301251 bool *builtIn)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001252{
alokp@chromium.org0a576182010-08-09 17:16:27 +00001253 // First find by unmangled name to check whether the function name has been
1254 // hidden by a variable name or struct typename.
Nicolas Capensd4a9b8d2013-07-18 11:01:22 -04001255 // If a function is found, check for one with a matching argument list.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301256 const TSymbol *symbol = symbolTable.find(call->getName(), inputShaderVersion, builtIn);
1257 if (symbol == 0 || symbol->isFunction())
1258 {
Austin Kinross3ae64652015-01-26 15:51:39 -08001259 symbol = symbolTable.find(call->getMangledName(), inputShaderVersion, builtIn);
alokp@chromium.org0a576182010-08-09 17:16:27 +00001260 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001261
Arun Patole7e7e68d2015-05-22 12:02:25 +05301262 if (symbol == 0)
1263 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001264 error(line, "no matching overloaded function found", call->getName().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001265 return 0;
1266 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001267
Arun Patole7e7e68d2015-05-22 12:02:25 +05301268 if (!symbol->isFunction())
1269 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001270 error(line, "function name expected", call->getName().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001271 return 0;
1272 }
alokp@chromium.org0a576182010-08-09 17:16:27 +00001273
Jamie Madillb98c3a82015-07-23 14:26:04 -04001274 return static_cast<const TFunction *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001275}
1276
1277//
1278// Initializers show up in several places in the grammar. Have one set of
1279// code to handle them here.
1280//
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001281// Returns true on error, false if no error
1282//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001283bool TParseContext::executeInitializer(const TSourceLoc &line,
1284 const TString &identifier,
1285 const TPublicType &pType,
1286 TIntermTyped *initializer,
1287 TIntermNode **intermNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001288{
Olli Etuahoe7847b02015-03-16 11:56:12 +02001289 ASSERT(intermNode != nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001290 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001291
Olli Etuaho2935c582015-04-08 14:32:06 +03001292 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001293 if (type.isUnsizedArray())
1294 {
1295 type.setArraySize(initializer->getArraySize());
1296 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001297 if (!declareVariable(line, identifier, type, &variable))
1298 {
1299 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001300 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001301
Olli Etuahob0c645e2015-05-12 14:25:36 +03001302 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001303 if (symbolTable.atGlobalLevel() &&
1304 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001305 {
1306 // Error message does not completely match behavior with ESSL 1.00, but
1307 // we want to steer developers towards only using constant expressions.
1308 error(line, "global variable initializers must be constant expressions", "=");
1309 return true;
1310 }
1311 if (globalInitWarning)
1312 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001313 warning(
1314 line,
1315 "global variable initializers should be constant expressions "
1316 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1317 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001318 }
1319
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001320 //
1321 // identifier must be of type constant, a global, or a temporary
1322 //
1323 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301324 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1325 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001326 error(line, " cannot initialize this type of qualifier ",
1327 variable->getType().getQualifierString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001328 return true;
1329 }
1330 //
1331 // test for and propagate constant
1332 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001333
Arun Patole7e7e68d2015-05-22 12:02:25 +05301334 if (qualifier == EvqConst)
1335 {
1336 if (qualifier != initializer->getType().getQualifier())
1337 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001338 std::stringstream extraInfoStream;
1339 extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
1340 std::string extraInfo = extraInfoStream.str();
1341 error(line, " assigning non-constant to", "=", extraInfo.c_str());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001342 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001343 return true;
1344 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301345 if (type != initializer->getType())
1346 {
1347 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001348 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001349 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001350 return true;
1351 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001352
1353 // Save the constant folded value to the variable if possible. For example array
1354 // initializers are not folded, since that way copying the array literal to multiple places
1355 // in the shader is avoided.
1356 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1357 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301358 if (initializer->getAsConstantUnion())
1359 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001360 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001361 *intermNode = nullptr;
1362 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301363 }
1364 else if (initializer->getAsSymbolNode())
1365 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001366 const TSymbol *symbol =
1367 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1368 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001369
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001370 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001371 if (constArray)
1372 {
1373 variable->shareConstPointer(constArray);
1374 *intermNode = nullptr;
1375 return false;
1376 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001377 }
1378 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001379
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001380 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1381 variable->getUniqueId(), variable->getName(), variable->getType(), line);
1382 *intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1383 if (*intermNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001384 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001385 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1386 return true;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001387 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001388
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001389 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001390}
1391
Jamie Madillb98c3a82015-07-23 14:26:04 -04001392TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier,
1393 bool invariant,
1394 TLayoutQualifier layoutQualifier,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301395 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001396{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001397 TPublicType returnType = typeSpecifier;
1398 returnType.qualifier = qualifier;
1399 returnType.invariant = invariant;
Jamie Madilla5efff92013-06-06 11:56:47 -04001400 returnType.layoutQualifier = layoutQualifier;
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001401
Olli Etuaho856c4972016-08-08 11:38:39 +03001402 checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001403
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001404 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001405 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001406 if (typeSpecifier.array)
1407 {
1408 error(typeSpecifier.line, "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001409 returnType.clearArrayness();
1410 }
1411
Jamie Madillb98c3a82015-07-23 14:26:04 -04001412 if (qualifier == EvqAttribute &&
1413 (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001414 {
1415 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001416 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001417
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001418 if ((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
1419 (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
1420 {
1421 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001422 }
1423 }
1424 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001425 {
Olli Etuahoabb0c382015-07-13 12:01:12 +03001426 if (!layoutQualifier.isEmpty())
1427 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001428 checkIsAtGlobalLevel(typeSpecifier.line, "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03001429 }
Olli Etuahocc36b982015-07-10 14:14:18 +03001430 if (sh::IsVarying(qualifier) || qualifier == EvqVertexIn || qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001431 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001432 checkInputOutputTypeIsValidES3(qualifier, typeSpecifier, typeSpecifier.line);
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001433 }
Martin Radev802abe02016-08-04 17:48:32 +03001434 if (qualifier == EvqComputeIn)
1435 {
1436 error(typeSpecifier.line, "'in' can be only used to specify the local group size",
1437 "in");
Martin Radev802abe02016-08-04 17:48:32 +03001438 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001439 }
1440
1441 return returnType;
1442}
1443
Olli Etuaho856c4972016-08-08 11:38:39 +03001444void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1445 const TPublicType &type,
1446 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03001447{
1448 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
1449 if (type.type == EbtBool)
1450 {
1451 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001452 }
1453
1454 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1455 switch (qualifier)
1456 {
1457 case EvqVertexIn:
1458 // ESSL 3.00 section 4.3.4
1459 if (type.array)
1460 {
1461 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001462 }
1463 // Vertex inputs with a struct type are disallowed in singleDeclarationErrorCheck
1464 return;
1465 case EvqFragmentOut:
1466 // ESSL 3.00 section 4.3.6
1467 if (type.isMatrix())
1468 {
1469 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001470 }
1471 // Fragment outputs with a struct type are disallowed in singleDeclarationErrorCheck
1472 return;
1473 default:
1474 break;
1475 }
1476
1477 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1478 // restrictions.
1479 bool typeContainsIntegers =
1480 (type.type == EbtInt || type.type == EbtUInt || type.isStructureContainingType(EbtInt) ||
1481 type.isStructureContainingType(EbtUInt));
1482 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1483 {
1484 error(qualifierLocation, "must use 'flat' interpolation here",
1485 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001486 }
1487
1488 if (type.type == EbtStruct)
1489 {
1490 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1491 // These restrictions are only implied by the ESSL 3.00 spec, but
1492 // the ESSL 3.10 spec lists these restrictions explicitly.
1493 if (type.array)
1494 {
1495 error(qualifierLocation, "cannot be an array of structures",
1496 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001497 }
1498 if (type.isStructureContainingArrays())
1499 {
1500 error(qualifierLocation, "cannot be a structure containing an array",
1501 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001502 }
1503 if (type.isStructureContainingType(EbtStruct))
1504 {
1505 error(qualifierLocation, "cannot be a structure containing a structure",
1506 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001507 }
1508 if (type.isStructureContainingType(EbtBool))
1509 {
1510 error(qualifierLocation, "cannot be a structure containing a bool",
1511 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001512 }
1513 }
1514}
1515
Olli Etuahofa33d582015-04-09 14:33:12 +03001516TIntermAggregate *TParseContext::parseSingleDeclaration(TPublicType &publicType,
1517 const TSourceLoc &identifierOrTypeLocation,
1518 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04001519{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001520 TIntermSymbol *symbol =
1521 intermediate.addSymbol(0, identifier, TType(publicType), identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001522
Olli Etuahobab4c082015-04-24 16:38:49 +03001523 bool emptyDeclaration = (identifier == "");
Olli Etuahofa33d582015-04-09 14:33:12 +03001524
Olli Etuahobab4c082015-04-24 16:38:49 +03001525 mDeferredSingleDeclarationErrorCheck = emptyDeclaration;
1526
1527 if (emptyDeclaration)
1528 {
1529 if (publicType.isUnsizedArray())
1530 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001531 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1532 // error. It is assumed that this applies to empty declarations as well.
1533 error(identifierOrTypeLocation, "empty array declaration needs to specify a size",
1534 identifier.c_str());
Olli Etuahobab4c082015-04-24 16:38:49 +03001535 }
1536 }
1537 else
Jamie Madill60ed9812013-06-06 11:56:46 -04001538 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001539 singleDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001540
Olli Etuaho856c4972016-08-08 11:38:39 +03001541 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001542
Olli Etuaho2935c582015-04-08 14:32:06 +03001543 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001544 declareVariable(identifierOrTypeLocation, identifier, TType(publicType), &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001545
1546 if (variable && symbol)
Jamie Madill60ed9812013-06-06 11:56:46 -04001547 symbol->setId(variable->getUniqueId());
Jamie Madill60ed9812013-06-06 11:56:46 -04001548 }
1549
Olli Etuahoe7847b02015-03-16 11:56:12 +02001550 return intermediate.makeAggregate(symbol, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001551}
1552
Olli Etuahoe7847b02015-03-16 11:56:12 +02001553TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1554 const TSourceLoc &identifierLocation,
1555 const TString &identifier,
1556 const TSourceLoc &indexLocation,
1557 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04001558{
Olli Etuahofa33d582015-04-09 14:33:12 +03001559 mDeferredSingleDeclarationErrorCheck = false;
1560
Olli Etuaho383b7912016-08-05 11:22:59 +03001561 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001562
Olli Etuaho856c4972016-08-08 11:38:39 +03001563 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001564
Olli Etuaho8a176262016-08-16 14:23:01 +03001565 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001566
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001567 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001568
Olli Etuaho856c4972016-08-08 11:38:39 +03001569 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001570 // Make the type an array even if size check failed.
1571 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1572 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04001573
Olli Etuaho2935c582015-04-08 14:32:06 +03001574 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001575 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001576
Olli Etuahoe7847b02015-03-16 11:56:12 +02001577 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001578 if (variable && symbol)
Jamie Madill60ed9812013-06-06 11:56:46 -04001579 symbol->setId(variable->getUniqueId());
Jamie Madill60ed9812013-06-06 11:56:46 -04001580
Olli Etuahoe7847b02015-03-16 11:56:12 +02001581 return intermediate.makeAggregate(symbol, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001582}
1583
Jamie Madill06145232015-05-13 13:10:01 -04001584TIntermAggregate *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
Olli Etuahoe7847b02015-03-16 11:56:12 +02001585 const TSourceLoc &identifierLocation,
1586 const TString &identifier,
1587 const TSourceLoc &initLocation,
1588 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04001589{
Olli Etuahofa33d582015-04-09 14:33:12 +03001590 mDeferredSingleDeclarationErrorCheck = false;
1591
Olli Etuaho383b7912016-08-05 11:22:59 +03001592 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001593
Olli Etuahoe7847b02015-03-16 11:56:12 +02001594 TIntermNode *intermNode = nullptr;
1595 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04001596 {
1597 //
1598 // Build intermediate representation
1599 //
Olli Etuahoe7847b02015-03-16 11:56:12 +02001600 return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : nullptr;
Jamie Madill60ed9812013-06-06 11:56:46 -04001601 }
1602 else
1603 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001604 return nullptr;
Jamie Madill60ed9812013-06-06 11:56:46 -04001605 }
1606}
1607
Jamie Madillb98c3a82015-07-23 14:26:04 -04001608TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration(
1609 TPublicType &publicType,
1610 const TSourceLoc &identifierLocation,
1611 const TString &identifier,
1612 const TSourceLoc &indexLocation,
1613 TIntermTyped *indexExpression,
1614 const TSourceLoc &initLocation,
1615 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001616{
1617 mDeferredSingleDeclarationErrorCheck = false;
1618
Olli Etuaho383b7912016-08-05 11:22:59 +03001619 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001620
Olli Etuaho8a176262016-08-16 14:23:01 +03001621 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001622
1623 TPublicType arrayType(publicType);
1624
Olli Etuaho856c4972016-08-08 11:38:39 +03001625 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001626 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
1627 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03001628 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001629 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001630 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001631 }
1632 // Make the type an array even if size check failed.
1633 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1634 arrayType.setArraySize(size);
1635
1636 // initNode will correspond to the whole of "type b[n] = initializer".
1637 TIntermNode *initNode = nullptr;
1638 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
1639 {
1640 return initNode ? intermediate.makeAggregate(initNode, initLocation) : nullptr;
1641 }
1642 else
1643 {
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001644 return nullptr;
1645 }
1646}
1647
Olli Etuahoe7847b02015-03-16 11:56:12 +02001648TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc,
Jamie Madill47e3ec02014-08-20 16:38:33 -04001649 const TSourceLoc &identifierLoc,
1650 const TString *identifier,
1651 const TSymbol *symbol)
1652{
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001653 // invariant declaration
Olli Etuaho856c4972016-08-08 11:38:39 +03001654 checkIsAtGlobalLevel(invariantLoc, "invariant varying");
Jamie Madill47e3ec02014-08-20 16:38:33 -04001655
1656 if (!symbol)
1657 {
1658 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001659 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001660 }
1661 else
1662 {
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001663 const TString kGlFrontFacing("gl_FrontFacing");
1664 if (*identifier == kGlFrontFacing)
1665 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001666 error(identifierLoc, "identifier should not be declared as invariant",
1667 identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001668 return nullptr;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001669 }
Jamie Madill2c433252014-12-03 12:36:54 -05001670 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001671 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
1672 ASSERT(variable);
1673 const TType &type = variable->getType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04001674 TIntermSymbol *intermSymbol =
1675 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001676
1677 TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc);
1678 aggregate->setOp(EOpInvariantDeclaration);
1679 return aggregate;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001680 }
1681}
1682
Jamie Madillb98c3a82015-07-23 14:26:04 -04001683TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType,
1684 TIntermAggregate *aggregateDeclaration,
1685 const TSourceLoc &identifierLocation,
1686 const TString &identifier)
Jamie Madill502d66f2013-06-20 11:55:52 -04001687{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001688 // If the declaration starting this declarator list was empty (example: int,), some checks were
1689 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001690 if (mDeferredSingleDeclarationErrorCheck)
1691 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001692 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001693 mDeferredSingleDeclarationErrorCheck = false;
1694 }
1695
Olli Etuaho856c4972016-08-08 11:38:39 +03001696 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001697
Olli Etuaho856c4972016-08-08 11:38:39 +03001698 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04001699
Olli Etuaho2935c582015-04-08 14:32:06 +03001700 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001701 declareVariable(identifierLocation, identifier, TType(publicType), &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001702
Jamie Madillb98c3a82015-07-23 14:26:04 -04001703 TIntermSymbol *symbol =
1704 intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001705 if (variable && symbol)
Jamie Madill502d66f2013-06-20 11:55:52 -04001706 symbol->setId(variable->getUniqueId());
1707
Olli Etuahoe7847b02015-03-16 11:56:12 +02001708 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001709}
1710
Jamie Madillb98c3a82015-07-23 14:26:04 -04001711TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType,
1712 TIntermAggregate *aggregateDeclaration,
1713 const TSourceLoc &identifierLocation,
1714 const TString &identifier,
1715 const TSourceLoc &arrayLocation,
1716 TIntermTyped *indexExpression)
Jamie Madill502d66f2013-06-20 11:55:52 -04001717{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001718 // If the declaration starting this declarator list was empty (example: int,), some checks were
1719 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001720 if (mDeferredSingleDeclarationErrorCheck)
1721 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001722 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001723 mDeferredSingleDeclarationErrorCheck = false;
1724 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001725
Olli Etuaho856c4972016-08-08 11:38:39 +03001726 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001727
Olli Etuaho856c4972016-08-08 11:38:39 +03001728 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04001729
Olli Etuaho8a176262016-08-16 14:23:01 +03001730 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04001731 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001732 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03001733 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03001734 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001735
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001736 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001737 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04001738
Jamie Madillb98c3a82015-07-23 14:26:04 -04001739 TIntermSymbol *symbol =
1740 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001741 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001742 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001743
1744 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001745 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001746
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001747 return nullptr;
Jamie Madill502d66f2013-06-20 11:55:52 -04001748}
1749
Jamie Madillb98c3a82015-07-23 14:26:04 -04001750TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicType,
1751 TIntermAggregate *aggregateDeclaration,
1752 const TSourceLoc &identifierLocation,
1753 const TString &identifier,
1754 const TSourceLoc &initLocation,
1755 TIntermTyped *initializer)
Jamie Madill502d66f2013-06-20 11:55:52 -04001756{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001757 // If the declaration starting this declarator list was empty (example: int,), some checks were
1758 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001759 if (mDeferredSingleDeclarationErrorCheck)
1760 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001761 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001762 mDeferredSingleDeclarationErrorCheck = false;
1763 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001764
Olli Etuaho856c4972016-08-08 11:38:39 +03001765 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001766
Olli Etuahoe7847b02015-03-16 11:56:12 +02001767 TIntermNode *intermNode = nullptr;
1768 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04001769 {
1770 //
1771 // build the intermediate representation
1772 //
1773 if (intermNode)
1774 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001775 return intermediate.growAggregate(aggregateDeclaration, intermNode, initLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001776 }
1777 else
1778 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001779 return aggregateDeclaration;
Jamie Madill502d66f2013-06-20 11:55:52 -04001780 }
1781 }
1782 else
1783 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001784 return nullptr;
Jamie Madill502d66f2013-06-20 11:55:52 -04001785 }
1786}
1787
Jamie Madill06145232015-05-13 13:10:01 -04001788TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001789 TIntermAggregate *aggregateDeclaration,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301790 const TSourceLoc &identifierLocation,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001791 const TString &identifier,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301792 const TSourceLoc &indexLocation,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001793 TIntermTyped *indexExpression,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001794 const TSourceLoc &initLocation,
1795 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001796{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001797 // If the declaration starting this declarator list was empty (example: int,), some checks were
1798 // not performed.
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001799 if (mDeferredSingleDeclarationErrorCheck)
1800 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001801 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001802 mDeferredSingleDeclarationErrorCheck = false;
1803 }
1804
Olli Etuaho856c4972016-08-08 11:38:39 +03001805 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001806
Olli Etuaho8a176262016-08-16 14:23:01 +03001807 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001808
1809 TPublicType arrayType(publicType);
1810
Olli Etuaho856c4972016-08-08 11:38:39 +03001811 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001812 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
1813 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03001814 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001815 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001816 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001817 }
1818 // Make the type an array even if size check failed.
1819 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1820 arrayType.setArraySize(size);
1821
1822 // initNode will correspond to the whole of "b[n] = initializer".
1823 TIntermNode *initNode = nullptr;
1824 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
1825 {
1826 if (initNode)
1827 {
1828 return intermediate.growAggregate(aggregateDeclaration, initNode, initLocation);
1829 }
1830 else
1831 {
1832 return aggregateDeclaration;
1833 }
1834 }
1835 else
1836 {
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001837 return nullptr;
1838 }
1839}
1840
Jamie Madilla295edf2013-06-06 11:56:48 -04001841void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
1842{
Jamie Madilla295edf2013-06-06 11:56:48 -04001843 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04001844
1845 // It should never be the case, but some strange parser errors can send us here.
1846 if (layoutQualifier.isEmpty())
1847 {
1848 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04001849 return;
1850 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001851
Martin Radev802abe02016-08-04 17:48:32 +03001852 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04001853 {
Martin Radev802abe02016-08-04 17:48:32 +03001854 error(typeQualifier.line, "invalid combination:", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04001855 return;
1856 }
1857
Martin Radev802abe02016-08-04 17:48:32 +03001858 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04001859 {
Martin Radev802abe02016-08-04 17:48:32 +03001860 if (mComputeShaderLocalSizeDeclared &&
1861 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
1862 {
1863 error(typeQualifier.line, "Work group size does not match the previous declaration",
1864 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001865 return;
1866 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001867
Martin Radev802abe02016-08-04 17:48:32 +03001868 if (mShaderVersion < 310)
1869 {
1870 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001871 return;
1872 }
Jamie Madill099c0f32013-06-20 11:55:52 -04001873
Martin Radev802abe02016-08-04 17:48:32 +03001874 if (!layoutQualifier.isGroupSizeSpecified())
1875 {
1876 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001877 return;
1878 }
1879
1880 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
1881 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
1882
1883 const TConstantUnion *maxComputeWorkGroupSizeData =
1884 maxComputeWorkGroupSize->getConstPointer();
1885
1886 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
1887 {
1888 if (layoutQualifier.localSize[i] != -1)
1889 {
1890 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
1891 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
1892 if (mComputeShaderLocalSize[i] < 1 ||
1893 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
1894 {
1895 std::stringstream errorMessageStream;
1896 errorMessageStream << "Value must be at least 1 and no greater than "
1897 << maxComputeWorkGroupSizeValue;
1898 const std::string &errorMessage = errorMessageStream.str();
1899
1900 error(typeQualifier.line, "invalid value:", getLocalSizeString(i),
1901 errorMessage.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03001902 return;
1903 }
1904 }
1905 }
1906
1907 mComputeShaderLocalSizeDeclared = true;
1908 }
1909 else
Jamie Madill1566ef72013-06-20 11:55:54 -04001910 {
Martin Radev802abe02016-08-04 17:48:32 +03001911
Olli Etuaho8a176262016-08-16 14:23:01 +03001912 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03001913 {
Martin Radev802abe02016-08-04 17:48:32 +03001914 return;
1915 }
1916
1917 if (typeQualifier.qualifier != EvqUniform)
1918 {
1919 error(typeQualifier.line, "invalid qualifier:",
1920 getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
Martin Radev802abe02016-08-04 17:48:32 +03001921 return;
1922 }
1923
1924 if (mShaderVersion < 300)
1925 {
1926 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
1927 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001928 return;
1929 }
1930
Olli Etuaho856c4972016-08-08 11:38:39 +03001931 checkLocationIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001932
1933 if (layoutQualifier.matrixPacking != EmpUnspecified)
1934 {
1935 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
1936 }
1937
1938 if (layoutQualifier.blockStorage != EbsUnspecified)
1939 {
1940 mDefaultBlockStorage = layoutQualifier.blockStorage;
1941 }
Jamie Madill1566ef72013-06-20 11:55:54 -04001942 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001943}
1944
Olli Etuahoee63f5d2016-01-04 11:34:54 +02001945TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function,
1946 const TSourceLoc &location)
1947{
Olli Etuaho5d653182016-01-04 14:43:28 +02001948 // Note: symbolTableFunction could be the same as function if this is the first declaration.
1949 // Either way the instance in the symbol table is used to track whether the function is declared
1950 // multiple times.
1951 TFunction *symbolTableFunction =
1952 static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion()));
1953 if (symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100)
1954 {
1955 // ESSL 1.00.17 section 4.2.7.
1956 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
1957 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02001958 }
1959 symbolTableFunction->setHasPrototypeDeclaration();
1960
Olli Etuahoee63f5d2016-01-04 11:34:54 +02001961 TIntermAggregate *prototype = new TIntermAggregate;
1962 prototype->setType(function.getReturnType());
1963 prototype->setName(function.getMangledName());
1964 prototype->setFunctionId(function.getUniqueId());
1965
1966 for (size_t i = 0; i < function.getParamCount(); i++)
1967 {
1968 const TConstParameter &param = function.getParam(i);
1969 if (param.name != 0)
1970 {
1971 TVariable variable(param.name, *param.type);
1972
1973 TIntermSymbol *paramSymbol = intermediate.addSymbol(
1974 variable.getUniqueId(), variable.getName(), variable.getType(), location);
1975 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
1976 }
1977 else
1978 {
1979 TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
1980 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
1981 }
1982 }
1983
1984 prototype->setOp(EOpPrototype);
1985
1986 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02001987
1988 if (!symbolTable.atGlobalLevel())
1989 {
1990 // ESSL 3.00.4 section 4.2.4.
1991 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02001992 }
1993
Olli Etuahoee63f5d2016-01-04 11:34:54 +02001994 return prototype;
1995}
1996
1997TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function,
1998 TIntermAggregate *functionPrototype,
1999 TIntermAggregate *functionBody,
2000 const TSourceLoc &location)
2001{
2002 //?? Check that all paths return a value if return type != void ?
2003 // May be best done as post process phase on intermediate code
2004 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2005 {
2006 error(location, "function does not return a value:", "", function.getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002007 }
2008
2009 TIntermAggregate *aggregate =
2010 intermediate.growAggregate(functionPrototype, functionBody, location);
2011 intermediate.setAggregateOperator(aggregate, EOpFunction, location);
2012 aggregate->setName(function.getMangledName().c_str());
2013 aggregate->setType(function.getReturnType());
2014 aggregate->setFunctionId(function.getUniqueId());
2015
2016 symbolTable.pop();
2017 return aggregate;
2018}
2019
Jamie Madill185fb402015-06-12 15:48:48 -04002020void TParseContext::parseFunctionPrototype(const TSourceLoc &location,
2021 TFunction *function,
2022 TIntermAggregate **aggregateOut)
2023{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002024 const TSymbol *builtIn =
2025 symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002026
2027 if (builtIn)
2028 {
2029 error(location, "built-in functions cannot be redefined", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002030 }
2031
Jamie Madillb98c3a82015-07-23 14:26:04 -04002032 TFunction *prevDec =
2033 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Jamie Madill185fb402015-06-12 15:48:48 -04002034 //
2035 // Note: 'prevDec' could be 'function' if this is the first time we've seen function
2036 // as it would have just been put in the symbol table. Otherwise, we're looking up
2037 // an earlier occurance.
2038 //
2039 if (prevDec->isDefined())
2040 {
2041 // Then this function already has a body.
2042 error(location, "function already has a body", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002043 }
2044 prevDec->setDefined();
2045 //
2046 // Overload the unique ID of the definition to be the same unique ID as the declaration.
2047 // Eventually we will probably want to have only a single definition and just swap the
2048 // arguments to be the definition's arguments.
2049 //
2050 function->setUniqueId(prevDec->getUniqueId());
2051
2052 // Raise error message if main function takes any parameters or return anything other than void
2053 if (function->getName() == "main")
2054 {
2055 if (function->getParamCount() > 0)
2056 {
2057 error(location, "function cannot take any parameter(s)", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002058 }
2059 if (function->getReturnType().getBasicType() != EbtVoid)
2060 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002061 error(location, "", function->getReturnType().getBasicString(),
2062 "main function cannot return a value");
Jamie Madill185fb402015-06-12 15:48:48 -04002063 }
2064 }
2065
2066 //
2067 // Remember the return type for later checking for RETURN statements.
2068 //
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002069 mCurrentFunctionType = &(prevDec->getReturnType());
2070 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002071
2072 //
2073 // Insert parameters into the symbol table.
2074 // If the parameter has no name, it's not an error, just don't insert it
2075 // (could be used for unused args).
2076 //
2077 // Also, accumulate the list of parameters into the HIL, so lower level code
2078 // knows where to find parameters.
2079 //
2080 TIntermAggregate *paramNodes = new TIntermAggregate;
2081 for (size_t i = 0; i < function->getParamCount(); i++)
2082 {
2083 const TConstParameter &param = function->getParam(i);
2084 if (param.name != 0)
2085 {
2086 TVariable *variable = new TVariable(param.name, *param.type);
2087 //
2088 // Insert the parameters with name in the symbol table.
2089 //
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002090 if (!symbolTable.declare(variable))
2091 {
Jamie Madill185fb402015-06-12 15:48:48 -04002092 error(location, "redefinition", variable->getName().c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002093 paramNodes = intermediate.growAggregate(
2094 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
2095 continue;
Jamie Madill185fb402015-06-12 15:48:48 -04002096 }
2097
2098 //
2099 // Add the parameter to the HIL
2100 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002101 TIntermSymbol *symbol = intermediate.addSymbol(
2102 variable->getUniqueId(), variable->getName(), variable->getType(), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002103
2104 paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
2105 }
2106 else
2107 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002108 paramNodes = intermediate.growAggregate(
2109 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002110 }
2111 }
2112 intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
2113 *aggregateOut = paramNodes;
2114 setLoopNestingLevel(0);
2115}
2116
Jamie Madillb98c3a82015-07-23 14:26:04 -04002117TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002118{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002119 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002120 // We don't know at this point whether this is a function definition or a prototype.
2121 // The definition production code will check for redefinitions.
2122 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002123 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002124 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2125 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002126 //
2127 TFunction *prevDec =
2128 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302129
2130 if (getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltIn(function->getName().c_str()))
2131 {
2132 // With ESSL 3.00, names of built-in functions cannot be redeclared as functions.
2133 // Therefore overloading or redefining builtin functions is an error.
2134 error(location, "Name of a built-in function cannot be redeclared as function",
2135 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302136 }
2137 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002138 {
2139 if (prevDec->getReturnType() != function->getReturnType())
2140 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002141 error(location, "overloaded functions must have the same return type",
Jamie Madill185fb402015-06-12 15:48:48 -04002142 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002143 }
2144 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2145 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002146 if (prevDec->getParam(i).type->getQualifier() !=
2147 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002148 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002149 error(location, "overloaded functions must have the same parameter qualifiers",
Jamie Madill185fb402015-06-12 15:48:48 -04002150 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002151 }
2152 }
2153 }
2154
2155 //
2156 // Check for previously declared variables using the same name.
2157 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002158 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002159 if (prevSym)
2160 {
2161 if (!prevSym->isFunction())
2162 {
2163 error(location, "redefinition", function->getName().c_str(), "function");
Jamie Madill185fb402015-06-12 15:48:48 -04002164 }
2165 }
2166 else
2167 {
2168 // Insert the unmangled name to detect potential future redefinition as a variable.
Jamie Madillb98c3a82015-07-23 14:26:04 -04002169 TFunction *newFunction =
2170 new TFunction(NewPoolTString(function->getName().c_str()), &function->getReturnType());
Jamie Madill185fb402015-06-12 15:48:48 -04002171 symbolTable.getOuterLevel()->insertUnmangled(newFunction);
2172 }
2173
2174 // We're at the inner scope level of the function's arguments and body statement.
2175 // Add the function prototype to the surrounding scope instead.
2176 symbolTable.getOuterLevel()->insert(function);
2177
2178 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002179 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2180 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002181 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2182 //
2183 return function;
2184}
2185
Olli Etuaho9de84a52016-06-14 17:36:01 +03002186TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2187 const TString *name,
2188 const TSourceLoc &location)
2189{
2190 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2191 {
2192 error(location, "no qualifiers allowed for function return",
2193 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002194 }
2195 if (!type.layoutQualifier.isEmpty())
2196 {
2197 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002198 }
2199 // make sure a sampler is not involved as well...
Olli Etuaho856c4972016-08-08 11:38:39 +03002200 checkIsNotSampler(location, type, "samplers can't be function return values");
Olli Etuahoe29324f2016-06-15 10:58:03 +03002201 if (mShaderVersion < 300)
2202 {
2203 // Array return values are forbidden, but there's also no valid syntax for declaring array
2204 // return values in ESSL 1.00.
2205 ASSERT(type.arraySize == 0 || mDiagnostics.numErrors() > 0);
2206
2207 if (type.isStructureContainingArrays())
2208 {
2209 // ESSL 1.00.17 section 6.1 Function Definitions
2210 error(location, "structures containing arrays can't be function return values",
2211 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002212 }
2213 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002214
2215 // Add the function as a prototype after parsing it (we do not support recursion)
2216 return new TFunction(name, new TType(type));
2217}
2218
Jamie Madill06145232015-05-13 13:10:01 -04002219TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002220{
Jamie Madill06145232015-05-13 13:10:01 -04002221 TPublicType publicType = publicTypeIn;
Olli Etuahobd163f62015-11-13 12:15:38 +02002222 if (publicType.isStructSpecifier)
2223 {
2224 error(publicType.line, "constructor can't be a structure definition",
2225 getBasicString(publicType.type));
Olli Etuahobd163f62015-11-13 12:15:38 +02002226 }
2227
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002228 TOperator op = EOpNull;
2229 if (publicType.userDef)
2230 {
2231 op = EOpConstructStruct;
2232 }
2233 else
2234 {
Geoff Lang156d7192016-07-21 16:11:00 -04002235 op = sh::TypeToConstructorOperator(TType(publicType));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002236 if (op == EOpNull)
2237 {
2238 error(publicType.line, "cannot construct this type", getBasicString(publicType.type));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002239 publicType.type = EbtFloat;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002240 op = EOpConstructFloat;
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002241 }
2242 }
2243
2244 TString tempString;
Dmitry Skiba7f17a502015-06-22 15:08:39 -07002245 const TType *type = new TType(publicType);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002246 return new TFunction(&tempString, type, op);
2247}
2248
Jamie Madillb98c3a82015-07-23 14:26:04 -04002249// This function is used to test for the correctness of the parameters passed to various constructor
2250// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002251//
Olli Etuaho856c4972016-08-08 11:38:39 +03002252// Returns a node to add to the tree regardless of if an error was generated or not.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002253//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002254TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002255 TOperator op,
2256 TFunction *fnCall,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302257 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002258{
Olli Etuaho856c4972016-08-08 11:38:39 +03002259 TType type = fnCall->getReturnType();
2260 if (type.isUnsizedArray())
2261 {
2262 type.setArraySize(static_cast<unsigned int>(fnCall->getParamCount()));
2263 }
2264 bool constType = true;
2265 for (size_t i = 0; i < fnCall->getParamCount(); ++i)
2266 {
2267 const TConstParameter &param = fnCall->getParam(i);
2268 if (param.type->getQualifier() != EvqConst)
2269 constType = false;
2270 }
2271 if (constType)
2272 type.setQualifier(EvqConst);
2273
Olli Etuaho8a176262016-08-16 14:23:01 +03002274 if (!checkConstructorArguments(line, arguments, *fnCall, op, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002275 {
2276 TIntermTyped *dummyNode = intermediate.setAggregateOperator(nullptr, op, line);
2277 dummyNode->setType(type);
2278 return dummyNode;
2279 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002280 TIntermAggregate *constructor = arguments->getAsAggregate();
2281 ASSERT(constructor != nullptr);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002282
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002283 // Turn the argument list itself into a constructor
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002284 constructor->setOp(op);
2285 constructor->setLine(line);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002286 ASSERT(constructor->isConstructor());
2287
2288 // Need to set type before setPrecisionFromChildren() because bool doesn't have precision.
Olli Etuaho856c4972016-08-08 11:38:39 +03002289 constructor->setType(type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002290
Olli Etuaho21203702014-11-13 16:16:21 +02002291 // Structs should not be precision qualified, the individual members may be.
2292 // Built-in types on the other hand should be precision qualified.
2293 if (op != EOpConstructStruct)
2294 {
2295 constructor->setPrecisionFromChildren();
Olli Etuaho856c4972016-08-08 11:38:39 +03002296 type.setPrecision(constructor->getPrecision());
Olli Etuaho21203702014-11-13 16:16:21 +02002297 }
2298
Olli Etuaho856c4972016-08-08 11:38:39 +03002299 constructor->setType(type);
2300
Olli Etuaho1d122782015-11-06 15:35:17 +02002301 TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002302 if (constConstructor)
2303 {
2304 return constConstructor;
2305 }
2306
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002307 return constructor;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002308}
2309
Olli Etuaho90892fb2016-07-14 14:44:51 +03002310// This function returns vector field(s) being accessed from a constant vector.
2311TIntermConstantUnion *TParseContext::foldVectorSwizzle(TVectorFields &fields,
2312 TIntermConstantUnion *baseNode,
2313 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002314{
Olli Etuaho90892fb2016-07-14 14:44:51 +03002315 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002316 ASSERT(unionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002317
Arun Patole7e7e68d2015-05-22 12:02:25 +05302318 TConstantUnion *constArray = new TConstantUnion[fields.num];
Olli Etuaho90892fb2016-07-14 14:44:51 +03002319 const auto &type = baseNode->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002320
Arun Patole7e7e68d2015-05-22 12:02:25 +05302321 for (int i = 0; i < fields.num; i++)
2322 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002323 // Out-of-range indices should already be checked.
2324 ASSERT(fields.offsets[i] < type.getNominalSize());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002325 constArray[i] = unionArray[fields.offsets[i]];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302326 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03002327 return intermediate.addConstantUnion(constArray, type, location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002328}
2329
Olli Etuaho90892fb2016-07-14 14:44:51 +03002330// This function returns the column vector being accessed from a constant matrix.
2331TIntermConstantUnion *TParseContext::foldMatrixSubscript(int index,
2332 TIntermConstantUnion *baseNode,
2333 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002334{
Olli Etuaho90892fb2016-07-14 14:44:51 +03002335 ASSERT(index < baseNode->getType().getCols());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002336
Olli Etuaho90892fb2016-07-14 14:44:51 +03002337 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
2338 int size = baseNode->getType().getRows();
2339 return intermediate.addConstantUnion(&unionArray[size * index], baseNode->getType(), location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002340}
2341
Olli Etuaho90892fb2016-07-14 14:44:51 +03002342// This function returns an element of an array accessed from a constant array.
2343TIntermConstantUnion *TParseContext::foldArraySubscript(int index,
2344 TIntermConstantUnion *baseNode,
2345 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002346{
Olli Etuaho856c4972016-08-08 11:38:39 +03002347 ASSERT(index < static_cast<int>(baseNode->getArraySize()));
Olli Etuaho90892fb2016-07-14 14:44:51 +03002348
2349 TType arrayElementType = baseNode->getType();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002350 arrayElementType.clearArrayness();
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002351 size_t arrayElementSize = arrayElementType.getObjectSize();
Olli Etuaho90892fb2016-07-14 14:44:51 +03002352 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
2353 return intermediate.addConstantUnion(&unionArray[arrayElementSize * index], baseNode->getType(),
2354 location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002355}
2356
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002357//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002358// This function returns the value of a particular field inside a constant structure from the symbol
2359// table.
2360// If there is an embedded/nested struct, it appropriately calls addConstStructNested or
2361// addConstStructFromAggr function and returns the parse-tree with the values of the embedded/nested
2362// struct.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002363//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002364TIntermTyped *TParseContext::addConstStruct(const TString &identifier,
2365 TIntermTyped *node,
2366 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002367{
Arun Patole7e7e68d2015-05-22 12:02:25 +05302368 const TFieldList &fields = node->getType().getStruct()->fields();
Jamie Madillb98c3a82015-07-23 14:26:04 -04002369 size_t instanceSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002370
Arun Patole7e7e68d2015-05-22 12:02:25 +05302371 for (size_t index = 0; index < fields.size(); ++index)
2372 {
2373 if (fields[index]->name() == identifier)
2374 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002375 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302376 }
2377 else
2378 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002379 instanceSize += fields[index]->type()->getObjectSize();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002380 }
2381 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002382
Jamie Madill94bf7f22013-07-08 13:31:15 -04002383 TIntermTyped *typedNode;
2384 TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
Arun Patole7e7e68d2015-05-22 12:02:25 +05302385 if (tempConstantNode)
2386 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002387 const TConstantUnion *constArray = tempConstantNode->getUnionArrayPointer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002388
Jamie Madillb98c3a82015-07-23 14:26:04 -04002389 // type will be changed in the calling function
2390 typedNode = intermediate.addConstantUnion(constArray + instanceSize,
2391 tempConstantNode->getType(), line);
Arun Patole7e7e68d2015-05-22 12:02:25 +05302392 }
2393 else
2394 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002395 error(line, "Cannot offset into the structure", "Error");
Olli Etuaho383b7912016-08-05 11:22:59 +03002396 return nullptr;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002397 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002398
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002399 return typedNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002400}
2401
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002402//
2403// Interface/uniform blocks
2404//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002405TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualifier,
2406 const TSourceLoc &nameLine,
2407 const TString &blockName,
2408 TFieldList *fieldList,
2409 const TString *instanceName,
2410 const TSourceLoc &instanceLine,
2411 TIntermTyped *arrayIndex,
2412 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002413{
Olli Etuaho856c4972016-08-08 11:38:39 +03002414 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002415
2416 if (typeQualifier.qualifier != EvqUniform)
2417 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302418 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier),
2419 "interface blocks must be uniform");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002420 }
2421
Jamie Madill099c0f32013-06-20 11:55:52 -04002422 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03002423 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04002424
Jamie Madill099c0f32013-06-20 11:55:52 -04002425 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2426 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002427 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002428 }
2429
Jamie Madill1566ef72013-06-20 11:55:54 -04002430 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2431 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002432 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002433 }
2434
Olli Etuaho856c4972016-08-08 11:38:39 +03002435 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002436
Arun Patole7e7e68d2015-05-22 12:02:25 +05302437 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2438 if (!symbolTable.declare(blockNameSymbol))
2439 {
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002440 error(nameLine, "redefinition", blockName.c_str(), "interface block name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002441 }
2442
Jamie Madill98493dd2013-07-08 14:39:03 -04002443 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302444 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2445 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002446 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302447 TType *fieldType = field->type();
2448 if (IsSampler(fieldType->getBasicType()))
2449 {
2450 error(field->line(), "unsupported type", fieldType->getBasicString(),
2451 "sampler types are not allowed in interface blocks");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002452 }
2453
Jamie Madill98493dd2013-07-08 14:39:03 -04002454 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002455 switch (qualifier)
2456 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002457 case EvqGlobal:
2458 case EvqUniform:
2459 break;
2460 default:
2461 error(field->line(), "invalid qualifier on interface block member",
2462 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04002463 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002464 }
Jamie Madilla5efff92013-06-06 11:56:47 -04002465
2466 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04002467 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03002468 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Jamie Madill099c0f32013-06-20 11:55:52 -04002469
Jamie Madill98493dd2013-07-08 14:39:03 -04002470 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04002471 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002472 error(field->line(), "invalid layout qualifier:",
2473 getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
Jamie Madill1566ef72013-06-20 11:55:54 -04002474 }
2475
Jamie Madill98493dd2013-07-08 14:39:03 -04002476 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04002477 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002478 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002479 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002480 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04002481 {
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002482 warning(field->line(), "extraneous layout qualifier:",
Jamie Madillb98c3a82015-07-23 14:26:04 -04002483 getMatrixPackingString(fieldLayoutQualifier.matrixPacking),
2484 "only has an effect on matrix types");
Jamie Madill099c0f32013-06-20 11:55:52 -04002485 }
2486
Jamie Madill98493dd2013-07-08 14:39:03 -04002487 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002488 }
2489
Jamie Madill98493dd2013-07-08 14:39:03 -04002490 // add array index
Olli Etuaho856c4972016-08-08 11:38:39 +03002491 unsigned int arraySize = 0;
2492 if (arrayIndex != nullptr)
Jamie Madill98493dd2013-07-08 14:39:03 -04002493 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002494 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
Jamie Madill98493dd2013-07-08 14:39:03 -04002495 }
2496
Jamie Madillb98c3a82015-07-23 14:26:04 -04002497 TInterfaceBlock *interfaceBlock =
2498 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2499 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
2500 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002501
2502 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04002503 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002504
Jamie Madill98493dd2013-07-08 14:39:03 -04002505 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002506 {
2507 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04002508 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2509 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002510 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302511 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04002512
2513 // set parent pointer of the field variable
2514 fieldType->setInterfaceBlock(interfaceBlock);
2515
Arun Patole7e7e68d2015-05-22 12:02:25 +05302516 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04002517 fieldVariable->setQualifier(typeQualifier.qualifier);
2518
Arun Patole7e7e68d2015-05-22 12:02:25 +05302519 if (!symbolTable.declare(fieldVariable))
2520 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002521 error(field->line(), "redefinition", field->name().c_str(),
2522 "interface block member name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002523 }
2524 }
2525 }
2526 else
2527 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002528 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03002529
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002530 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05302531 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002532 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04002533
Arun Patole7e7e68d2015-05-22 12:02:25 +05302534 if (!symbolTable.declare(instanceTypeDef))
2535 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002536 error(instanceLine, "redefinition", instanceName->c_str(),
2537 "interface block instance name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002538 }
2539
Jamie Madillb98c3a82015-07-23 14:26:04 -04002540 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002541 symbolName = instanceTypeDef->getName();
2542 }
2543
Jamie Madillb98c3a82015-07-23 14:26:04 -04002544 TIntermAggregate *aggregate = intermediate.makeAggregate(
2545 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line),
2546 nameLine);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002547 aggregate->setOp(EOpDeclaration);
Jamie Madill98493dd2013-07-08 14:39:03 -04002548
2549 exitStructDeclaration();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002550 return aggregate;
2551}
2552
Olli Etuaho383b7912016-08-05 11:22:59 +03002553void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002554{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002555 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002556
2557 // Embedded structure definitions are not supported per GLSL ES spec.
2558 // They aren't allowed in GLSL either, but we need to detect this here
2559 // so we don't rely on the GLSL compiler to catch it.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302560 if (mStructNestingLevel > 1)
2561 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002562 error(line, "", "Embedded struct definitions are not allowed");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002563 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002564}
2565
2566void TParseContext::exitStructDeclaration()
2567{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002568 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002569}
2570
Jamie Madillb98c3a82015-07-23 14:26:04 -04002571namespace
2572{
kbr@chromium.org476541f2011-10-27 21:14:51 +00002573const int kWebGLMaxStructNesting = 4;
2574
2575} // namespace
2576
Olli Etuaho8a176262016-08-16 14:23:01 +03002577void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002578{
Arun Patole7e7e68d2015-05-22 12:02:25 +05302579 if (!IsWebGLBasedSpec(mShaderSpec))
2580 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002581 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002582 }
2583
Arun Patole7e7e68d2015-05-22 12:02:25 +05302584 if (field.type()->getBasicType() != EbtStruct)
2585 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002586 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002587 }
2588
2589 // We're already inside a structure definition at this point, so add
2590 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302591 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2592 {
Jamie Madill41a49272014-03-18 16:10:13 -04002593 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002594 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
2595 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04002596 std::string reason = reasonStream.str();
2597 error(line, reason.c_str(), field.name().c_str(), "");
Olli Etuaho8a176262016-08-16 14:23:01 +03002598 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002599 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002600}
2601
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00002602//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002603// Parse an array index expression
2604//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002605TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
2606 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302607 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002608{
2609 TIntermTyped *indexedExpression = NULL;
2610
2611 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2612 {
2613 if (baseExpression->getAsSymbolNode())
2614 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302615 error(location, " left of '[' is not of type array, matrix, or vector ",
2616 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002617 }
2618 else
2619 {
2620 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2621 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002622 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002623
Jamie Madill21c1e452014-12-29 11:33:41 -05002624 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2625
Olli Etuaho36b05142015-11-12 13:10:42 +02002626 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
2627 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
2628 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
2629 // index is a constant expression.
2630 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
2631 {
2632 if (baseExpression->isInterfaceBlock())
2633 {
2634 error(
2635 location, "", "[",
2636 "array indexes for interface blocks arrays must be constant integral expressions");
Olli Etuaho36b05142015-11-12 13:10:42 +02002637 }
2638 else if (baseExpression->getQualifier() == EvqFragmentOut)
2639 {
2640 error(location, "", "[",
2641 "array indexes for fragment outputs must be constant integral expressions");
Olli Etuaho36b05142015-11-12 13:10:42 +02002642 }
Olli Etuaho3e960462015-11-12 15:58:39 +02002643 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
2644 {
2645 error(location, "", "[", "array index for gl_FragData must be constant zero");
Olli Etuaho3e960462015-11-12 15:58:39 +02002646 }
Olli Etuaho36b05142015-11-12 13:10:42 +02002647 }
2648
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002649 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04002650 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002651 // If the index is not qualified as constant, the behavior in the spec is undefined. This
2652 // applies even if ANGLE has been able to constant fold it (ANGLE may constant fold
2653 // expressions that are not constant expressions). The most compatible way to handle this
2654 // case is to report a warning instead of an error and force the index to be in the
2655 // correct range.
2656 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madill21c1e452014-12-29 11:33:41 -05002657 int index = indexConstantUnion->getIConst(0);
Olli Etuaho90892fb2016-07-14 14:44:51 +03002658 if (!baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04002659 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002660 // Array checks are done later because a different error message might be generated
2661 // based on the index in some cases.
2662 if (baseExpression->isVector())
2663 {
2664 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2665 baseExpression->getType().getNominalSize(),
2666 "vector field selection out of range", "[]");
2667 }
2668 else if (baseExpression->isMatrix())
2669 {
2670 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2671 baseExpression->getType().getCols(),
2672 "matrix field selection out of range", "[]");
2673 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002674 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03002675
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002676 TIntermConstantUnion *baseConstantUnion = baseExpression->getAsConstantUnion();
2677 if (baseConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04002678 {
2679 if (baseExpression->isArray())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002680 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002681 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2682 baseExpression->getArraySize(),
2683 "array index out of range", "[]");
2684 // Constant folding for array indexing.
2685 indexedExpression = foldArraySubscript(index, baseConstantUnion, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002686 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002687 else if (baseExpression->isVector())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002688 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002689 // Constant folding for vector indexing - reusing vector swizzle folding.
Jamie Madill7164cf42013-07-08 13:30:59 -04002690 TVectorFields fields;
2691 fields.num = 1;
Olli Etuaho90892fb2016-07-14 14:44:51 +03002692 fields.offsets[0] = index;
2693 indexedExpression = foldVectorSwizzle(fields, baseConstantUnion, location);
Jamie Madill7164cf42013-07-08 13:30:59 -04002694 }
2695 else if (baseExpression->isMatrix())
2696 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002697 // Constant folding for matrix indexing.
2698 indexedExpression = foldMatrixSubscript(index, baseConstantUnion, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002699 }
2700 }
2701 else
2702 {
Jamie Madillb11e2482015-05-04 14:21:22 -04002703 int safeIndex = -1;
2704
Jamie Madill7164cf42013-07-08 13:30:59 -04002705 if (baseExpression->isArray())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002706 {
Olli Etuaho3e960462015-11-12 15:58:39 +02002707 if (baseExpression->getQualifier() == EvqFragData && index > 0)
2708 {
2709 if (mShaderSpec == SH_WEBGL2_SPEC)
2710 {
2711 // Error has been already generated if index is not const.
2712 if (indexExpression->getQualifier() == EvqConst)
2713 {
2714 error(location, "", "[",
2715 "array index for gl_FragData must be constant zero");
Olli Etuaho3e960462015-11-12 15:58:39 +02002716 }
2717 safeIndex = 0;
2718 }
2719 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
2720 {
2721 outOfRangeError(outOfRangeIndexIsError, location, "", "[",
2722 "array index for gl_FragData must be zero when "
2723 "GL_EXT_draw_buffers is disabled");
2724 safeIndex = 0;
2725 }
2726 }
2727 // Only do generic out-of-range check if similar error hasn't already been reported.
Olli Etuaho90892fb2016-07-14 14:44:51 +03002728 if (safeIndex < 0)
Jamie Madill7164cf42013-07-08 13:30:59 -04002729 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002730 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2731 baseExpression->getArraySize(),
2732 "array index out of range", "[]");
Jamie Madill7164cf42013-07-08 13:30:59 -04002733 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002734 }
2735
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002736 // Data of constant unions can't be changed, because it may be shared with other
2737 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
2738 // sanitized object.
Jamie Madillb11e2482015-05-04 14:21:22 -04002739 if (safeIndex != -1)
2740 {
2741 TConstantUnion *safeConstantUnion = new TConstantUnion();
2742 safeConstantUnion->setIConst(safeIndex);
2743 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
2744 }
2745
Jamie Madillb98c3a82015-07-23 14:26:04 -04002746 indexedExpression =
2747 intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002748 }
2749 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002750 else
2751 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002752 indexedExpression =
2753 intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
Jamie Madill7164cf42013-07-08 13:30:59 -04002754 }
2755
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002756 if (indexedExpression == 0)
2757 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002758 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002759 unionArray->setFConst(0.0f);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002760 indexedExpression =
2761 intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002762 }
2763 else if (baseExpression->isArray())
2764 {
Olli Etuahob3fbd862015-09-30 17:55:02 +03002765 TType indexedType = baseExpression->getType();
2766 indexedType.clearArrayness();
2767 indexedExpression->setType(indexedType);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002768 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002769 else if (baseExpression->isMatrix())
2770 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002771 indexedExpression->setType(TType(baseExpression->getBasicType(),
Olli Etuahob3fbd862015-09-30 17:55:02 +03002772 baseExpression->getPrecision(), EvqTemporary,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002773 static_cast<unsigned char>(baseExpression->getRows())));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002774 }
2775 else if (baseExpression->isVector())
2776 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002777 indexedExpression->setType(
Olli Etuahob3fbd862015-09-30 17:55:02 +03002778 TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002779 }
2780 else
2781 {
2782 indexedExpression->setType(baseExpression->getType());
2783 }
2784
Olli Etuahob3fbd862015-09-30 17:55:02 +03002785 if (baseExpression->getType().getQualifier() == EvqConst &&
2786 indexExpression->getType().getQualifier() == EvqConst)
2787 {
2788 indexedExpression->getTypePointer()->setQualifier(EvqConst);
2789 }
2790 else
2791 {
2792 indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
2793 }
2794
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002795 return indexedExpression;
2796}
2797
Olli Etuaho90892fb2016-07-14 14:44:51 +03002798int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
2799 const TSourceLoc &location,
2800 int index,
2801 int arraySize,
2802 const char *reason,
2803 const char *token)
2804{
2805 if (index >= arraySize || index < 0)
2806 {
2807 std::stringstream extraInfoStream;
2808 extraInfoStream << "'" << index << "'";
2809 std::string extraInfo = extraInfoStream.str();
2810 outOfRangeError(outOfRangeIndexIsError, location, reason, token, extraInfo.c_str());
2811 if (index < 0)
2812 {
2813 return 0;
2814 }
2815 else
2816 {
2817 return arraySize - 1;
2818 }
2819 }
2820 return index;
2821}
2822
Jamie Madillb98c3a82015-07-23 14:26:04 -04002823TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
2824 const TSourceLoc &dotLocation,
2825 const TString &fieldString,
2826 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002827{
2828 TIntermTyped *indexedExpression = NULL;
2829
2830 if (baseExpression->isArray())
2831 {
2832 error(fieldLocation, "cannot apply dot operator to an array", ".");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002833 }
2834
2835 if (baseExpression->isVector())
2836 {
2837 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002838 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
2839 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002840 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002841 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002842 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002843 }
2844
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002845 if (baseExpression->getAsConstantUnion())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002846 {
2847 // constant folding for vector fields
Olli Etuaho90892fb2016-07-14 14:44:51 +03002848 indexedExpression =
2849 foldVectorSwizzle(fields, baseExpression->getAsConstantUnion(), fieldLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002850 }
2851 else
2852 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302853 TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002854 indexedExpression =
2855 intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002856 }
2857 if (indexedExpression == nullptr)
2858 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002859 indexedExpression = baseExpression;
2860 }
2861 else
2862 {
2863 // Note that the qualifier set here will be corrected later.
Jamie Madillb98c3a82015-07-23 14:26:04 -04002864 indexedExpression->setType(TType(baseExpression->getBasicType(),
2865 baseExpression->getPrecision(), EvqTemporary,
Jamie Madillc2128ff2016-07-04 10:26:17 -04002866 static_cast<unsigned char>(fields.num)));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002867 }
2868 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002869 else if (baseExpression->getBasicType() == EbtStruct)
2870 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002871 bool fieldFound = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302872 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04002873 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002874 {
2875 error(dotLocation, "structure has no fields", "Internal Error");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002876 indexedExpression = baseExpression;
2877 }
2878 else
2879 {
2880 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04002881 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002882 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002883 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002884 {
2885 fieldFound = true;
2886 break;
2887 }
2888 }
2889 if (fieldFound)
2890 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002891 if (baseExpression->getAsConstantUnion())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002892 {
2893 indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
2894 if (indexedExpression == 0)
2895 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002896 indexedExpression = baseExpression;
2897 }
2898 else
2899 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002900 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002901 }
2902 }
2903 else
2904 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002905 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002906 unionArray->setIConst(i);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002907 TIntermTyped *index = intermediate.addConstantUnion(
2908 unionArray, *fields[i]->type(), fieldLocation);
2909 indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression,
2910 index, dotLocation);
Jamie Madill98493dd2013-07-08 14:39:03 -04002911 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002912 }
2913 }
2914 else
2915 {
2916 error(dotLocation, " no such field in structure", fieldString.c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002917 indexedExpression = baseExpression;
2918 }
2919 }
2920 }
Jamie Madill98493dd2013-07-08 14:39:03 -04002921 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002922 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002923 bool fieldFound = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302924 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04002925 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002926 {
2927 error(dotLocation, "interface block has no fields", "Internal Error");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002928 indexedExpression = baseExpression;
2929 }
2930 else
2931 {
2932 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04002933 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002934 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002935 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002936 {
2937 fieldFound = true;
2938 break;
2939 }
2940 }
2941 if (fieldFound)
2942 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002943 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002944 unionArray->setIConst(i);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002945 TIntermTyped *index =
2946 intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
2947 indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock,
2948 baseExpression, index, dotLocation);
Jamie Madill98493dd2013-07-08 14:39:03 -04002949 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002950 }
2951 else
2952 {
2953 error(dotLocation, " no such field in interface block", fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002954 indexedExpression = baseExpression;
2955 }
2956 }
2957 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002958 else
2959 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002960 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002961 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03002962 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05302963 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002964 }
2965 else
2966 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302967 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03002968 " field selection requires structure, vector, or interface block on left hand "
2969 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05302970 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002971 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002972 indexedExpression = baseExpression;
2973 }
2974
Olli Etuahob1edc4f2015-11-02 17:20:03 +02002975 if (baseExpression->getQualifier() == EvqConst)
2976 {
2977 indexedExpression->getTypePointer()->setQualifier(EvqConst);
2978 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002979 else
2980 {
2981 indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
2982 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02002983
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002984 return indexedExpression;
2985}
2986
Jamie Madillb98c3a82015-07-23 14:26:04 -04002987TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
2988 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002989{
Martin Radev802abe02016-08-04 17:48:32 +03002990 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002991
2992 if (qualifierType == "shared")
2993 {
Jamie Madilla5efff92013-06-06 11:56:47 -04002994 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002995 }
2996 else if (qualifierType == "packed")
2997 {
Jamie Madilla5efff92013-06-06 11:56:47 -04002998 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002999 }
3000 else if (qualifierType == "std140")
3001 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003002 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003003 }
3004 else if (qualifierType == "row_major")
3005 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003006 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003007 }
3008 else if (qualifierType == "column_major")
3009 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003010 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003011 }
3012 else if (qualifierType == "location")
3013 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003014 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(),
3015 "location requires an argument");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003016 }
3017 else
3018 {
3019 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003020 }
3021
Jamie Madilla5efff92013-06-06 11:56:47 -04003022 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003023}
3024
Martin Radev802abe02016-08-04 17:48:32 +03003025void TParseContext::parseLocalSize(const TString &qualifierType,
3026 const TSourceLoc &qualifierTypeLine,
3027 int intValue,
3028 const TSourceLoc &intValueLine,
3029 const std::string &intValueString,
3030 size_t index,
3031 TLocalSize *localSize)
3032{
Olli Etuaho856c4972016-08-08 11:38:39 +03003033 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03003034 if (intValue < 1)
3035 {
3036 std::string errorMessage = std::string(getLocalSizeString(index)) + " must be positive";
3037 error(intValueLine, "out of range:", intValueString.c_str(), errorMessage.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003038 }
3039 (*localSize)[index] = intValue;
3040}
3041
Jamie Madillb98c3a82015-07-23 14:26:04 -04003042TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3043 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003044 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303045 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003046{
Martin Radev802abe02016-08-04 17:48:32 +03003047 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003048
Martin Radev802abe02016-08-04 17:48:32 +03003049 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003050
Martin Radev802abe02016-08-04 17:48:32 +03003051 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003052 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003053 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003054 if (intValue < 0)
3055 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003056 error(intValueLine, "out of range:", intValueString.c_str(),
3057 "location must be non-negative");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003058 }
3059 else
3060 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003061 qualifier.location = intValue;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003062 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003063 }
Martin Radev802abe02016-08-04 17:48:32 +03003064 else if (qualifierType == "local_size_x")
3065 {
3066 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3067 &qualifier.localSize);
3068 }
3069 else if (qualifierType == "local_size_y")
3070 {
3071 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3072 &qualifier.localSize);
3073 }
3074 else if (qualifierType == "local_size_z")
3075 {
3076 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3077 &qualifier.localSize);
3078 }
3079 else
3080 {
3081 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003082 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003083
Jamie Madilla5efff92013-06-06 11:56:47 -04003084 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003085}
3086
Jamie Madillb98c3a82015-07-23 14:26:04 -04003087TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003088 TLayoutQualifier rightQualifier,
3089 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003090{
Jamie Madilla5efff92013-06-06 11:56:47 -04003091 TLayoutQualifier joinedQualifier = leftQualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003092
Jamie Madilla5efff92013-06-06 11:56:47 -04003093 if (rightQualifier.location != -1)
3094 {
3095 joinedQualifier.location = rightQualifier.location;
3096 }
3097 if (rightQualifier.matrixPacking != EmpUnspecified)
3098 {
3099 joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
3100 }
3101 if (rightQualifier.blockStorage != EbsUnspecified)
3102 {
3103 joinedQualifier.blockStorage = rightQualifier.blockStorage;
3104 }
3105
Martin Radev802abe02016-08-04 17:48:32 +03003106 for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i)
3107 {
3108 if (rightQualifier.localSize[i] != -1)
3109 {
3110 if (joinedQualifier.localSize[i] != -1 &&
3111 joinedQualifier.localSize[i] != rightQualifier.localSize[i])
3112 {
3113 error(rightQualifierLocation,
3114 "Cannot have multiple different work group size specifiers",
3115 getLocalSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03003116 }
3117 joinedQualifier.localSize[i] = rightQualifier.localSize[i];
3118 }
3119 }
3120
Jamie Madilla5efff92013-06-06 11:56:47 -04003121 return joinedQualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003122}
3123
Arun Patole7e7e68d2015-05-22 12:02:25 +05303124TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc,
3125 TQualifier interpolationQualifier,
3126 const TSourceLoc &storageLoc,
3127 TQualifier storageQualifier)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003128{
3129 TQualifier mergedQualifier = EvqSmoothIn;
3130
Arun Patole7e7e68d2015-05-22 12:02:25 +05303131 if (storageQualifier == EvqFragmentIn)
3132 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003133 if (interpolationQualifier == EvqSmooth)
3134 mergedQualifier = EvqSmoothIn;
3135 else if (interpolationQualifier == EvqFlat)
3136 mergedQualifier = EvqFlatIn;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003137 else
3138 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003139 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303140 else if (storageQualifier == EvqCentroidIn)
3141 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003142 if (interpolationQualifier == EvqSmooth)
3143 mergedQualifier = EvqCentroidIn;
3144 else if (interpolationQualifier == EvqFlat)
3145 mergedQualifier = EvqFlatIn;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003146 else
3147 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003148 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303149 else if (storageQualifier == EvqVertexOut)
3150 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003151 if (interpolationQualifier == EvqSmooth)
3152 mergedQualifier = EvqSmoothOut;
3153 else if (interpolationQualifier == EvqFlat)
3154 mergedQualifier = EvqFlatOut;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003155 else
3156 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003157 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303158 else if (storageQualifier == EvqCentroidOut)
3159 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003160 if (interpolationQualifier == EvqSmooth)
3161 mergedQualifier = EvqCentroidOut;
3162 else if (interpolationQualifier == EvqFlat)
3163 mergedQualifier = EvqFlatOut;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003164 else
3165 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003166 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303167 else
3168 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003169 error(interpolationLoc,
3170 "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303171 getInterpolationString(interpolationQualifier));
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003172
3173 mergedQualifier = storageQualifier;
3174 }
3175
3176 TPublicType type;
3177 type.setBasic(EbtVoid, mergedQualifier, storageLoc);
3178 return type;
3179}
3180
Jamie Madillb98c3a82015-07-23 14:26:04 -04003181TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3182 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003183{
Olli Etuaho856c4972016-08-08 11:38:39 +03003184 checkIsNonVoid(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003185
Olli Etuaho856c4972016-08-08 11:38:39 +03003186 checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003187
Arun Patole7e7e68d2015-05-22 12:02:25 +05303188 for (unsigned int i = 0; i < fieldList->size(); ++i)
3189 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003190 //
3191 // Careful not to replace already known aspects of type, like array-ness
3192 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303193 TType *type = (*fieldList)[i]->type();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003194 type->setBasicType(typeSpecifier.type);
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003195 type->setPrimarySize(typeSpecifier.primarySize);
3196 type->setSecondarySize(typeSpecifier.secondarySize);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003197 type->setPrecision(typeSpecifier.precision);
3198 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003199 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003200
3201 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303202 if (type->isArray())
3203 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003204 checkIsValidTypeForArray(typeSpecifier.line, typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003205 }
3206 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003207 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Arun Patole7e7e68d2015-05-22 12:02:25 +05303208 if (typeSpecifier.userDef)
3209 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003210 type->setStruct(typeSpecifier.userDef->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003211 }
3212
Olli Etuaho8a176262016-08-16 14:23:01 +03003213 checkIsBelowStructNestingLimit(typeSpecifier.line, *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003214 }
3215
Jamie Madill98493dd2013-07-08 14:39:03 -04003216 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003217}
3218
Jamie Madillb98c3a82015-07-23 14:26:04 -04003219TPublicType TParseContext::addStructure(const TSourceLoc &structLine,
3220 const TSourceLoc &nameLine,
3221 const TString *structName,
3222 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003223{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303224 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003225 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003226
Jamie Madill9b820842015-02-12 10:40:10 -05003227 // Store a bool in the struct if we're at global scope, to allow us to
3228 // skip the local struct scoping workaround in HLSL.
Jamie Madillb960cc42015-02-12 15:33:20 +00003229 structure->setUniqueId(TSymbolTable::nextUniqueId());
Jamie Madill9b820842015-02-12 10:40:10 -05003230 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003231
Jamie Madill98493dd2013-07-08 14:39:03 -04003232 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003233 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003234 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303235 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3236 if (!symbolTable.declare(userTypeDef))
3237 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003238 error(nameLine, "redefinition", structName->c_str(), "struct");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003239 }
3240 }
3241
3242 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003243 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003244 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003245 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003246 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003247 switch (qualifier)
3248 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003249 case EvqGlobal:
3250 case EvqTemporary:
3251 break;
3252 default:
3253 error(field.line(), "invalid qualifier on struct member",
3254 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003255 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003256 }
3257 }
3258
3259 TPublicType publicType;
3260 publicType.setBasic(EbtStruct, EvqTemporary, structLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04003261 publicType.userDef = structureType;
Olli Etuahobd163f62015-11-13 12:15:38 +02003262 publicType.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003263 exitStructDeclaration();
3264
3265 return publicType;
3266}
3267
Jamie Madillb98c3a82015-07-23 14:26:04 -04003268TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
3269 TIntermAggregate *statementList,
3270 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003271{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003272 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003273 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003274 init->isVector())
3275 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003276 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3277 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003278 return nullptr;
3279 }
3280
Olli Etuahoac5274d2015-02-20 10:19:08 +02003281 if (statementList)
3282 {
3283 if (!ValidateSwitch::validate(switchType, this, statementList, loc))
3284 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003285 return nullptr;
3286 }
3287 }
3288
Olli Etuahoa3a36662015-02-17 13:46:51 +02003289 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3290 if (node == nullptr)
3291 {
3292 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003293 return nullptr;
3294 }
3295 return node;
3296}
3297
3298TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3299{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003300 if (mSwitchNestingLevel == 0)
3301 {
3302 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003303 return nullptr;
3304 }
3305 if (condition == nullptr)
3306 {
3307 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003308 return nullptr;
3309 }
3310 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003311 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003312 {
3313 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003314 }
3315 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003316 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3317 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3318 // fold in case labels.
3319 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003320 {
3321 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003322 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003323 TIntermCase *node = intermediate.addCase(condition, loc);
3324 if (node == nullptr)
3325 {
3326 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003327 return nullptr;
3328 }
3329 return node;
3330}
3331
3332TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3333{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003334 if (mSwitchNestingLevel == 0)
3335 {
3336 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003337 return nullptr;
3338 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003339 TIntermCase *node = intermediate.addCase(nullptr, loc);
3340 if (node == nullptr)
3341 {
3342 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003343 return nullptr;
3344 }
3345 return node;
3346}
3347
Jamie Madillb98c3a82015-07-23 14:26:04 -04003348TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3349 TIntermTyped *child,
3350 const TSourceLoc &loc,
3351 const TType *funcReturnType)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003352{
3353 if (child == nullptr)
3354 {
3355 return nullptr;
3356 }
3357
3358 switch (op)
3359 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003360 case EOpLogicalNot:
3361 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3362 child->isVector())
3363 {
3364 return nullptr;
3365 }
3366 break;
3367 case EOpBitwiseNot:
3368 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3369 child->isMatrix() || child->isArray())
3370 {
3371 return nullptr;
3372 }
3373 break;
3374 case EOpPostIncrement:
3375 case EOpPreIncrement:
3376 case EOpPostDecrement:
3377 case EOpPreDecrement:
3378 case EOpNegative:
3379 case EOpPositive:
3380 if (child->getBasicType() == EbtStruct || child->getBasicType() == EbtBool ||
3381 child->isArray())
3382 {
3383 return nullptr;
3384 }
3385 // Operators for built-ins are already type checked against their prototype.
3386 default:
3387 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003388 }
3389
Olli Etuahof6c694b2015-03-26 14:50:53 +02003390 return intermediate.addUnaryMath(op, child, loc, funcReturnType);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003391}
3392
Olli Etuaho09b22472015-02-11 11:47:26 +02003393TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3394{
Olli Etuahof6c694b2015-03-26 14:50:53 +02003395 TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003396 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003397 {
3398 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003399 return child;
3400 }
3401 return node;
3402}
3403
Jamie Madillb98c3a82015-07-23 14:26:04 -04003404TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3405 TIntermTyped *child,
3406 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003407{
Olli Etuaho856c4972016-08-08 11:38:39 +03003408 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003409 return addUnaryMath(op, child, loc);
3410}
3411
Jamie Madillb98c3a82015-07-23 14:26:04 -04003412bool TParseContext::binaryOpCommonCheck(TOperator op,
3413 TIntermTyped *left,
3414 TIntermTyped *right,
3415 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003416{
3417 if (left->isArray() || right->isArray())
3418 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003419 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003420 {
3421 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3422 return false;
3423 }
3424
3425 if (left->isArray() != right->isArray())
3426 {
3427 error(loc, "array / non-array mismatch", GetOperatorString(op));
3428 return false;
3429 }
3430
3431 switch (op)
3432 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003433 case EOpEqual:
3434 case EOpNotEqual:
3435 case EOpAssign:
3436 case EOpInitialize:
3437 break;
3438 default:
3439 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3440 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02003441 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03003442 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02003443 if (left->getArraySize() != right->getArraySize())
3444 {
3445 error(loc, "array size mismatch", GetOperatorString(op));
3446 return false;
3447 }
Olli Etuahod6b14282015-03-17 14:31:35 +02003448 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003449
3450 // Check ops which require integer / ivec parameters
3451 bool isBitShift = false;
3452 switch (op)
3453 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003454 case EOpBitShiftLeft:
3455 case EOpBitShiftRight:
3456 case EOpBitShiftLeftAssign:
3457 case EOpBitShiftRightAssign:
3458 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3459 // check that the basic type is an integer type.
3460 isBitShift = true;
3461 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3462 {
3463 return false;
3464 }
3465 break;
3466 case EOpBitwiseAnd:
3467 case EOpBitwiseXor:
3468 case EOpBitwiseOr:
3469 case EOpBitwiseAndAssign:
3470 case EOpBitwiseXorAssign:
3471 case EOpBitwiseOrAssign:
3472 // It is enough to check the type of only one operand, since later it
3473 // is checked that the operand types match.
3474 if (!IsInteger(left->getBasicType()))
3475 {
3476 return false;
3477 }
3478 break;
3479 default:
3480 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003481 }
3482
3483 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3484 // So the basic type should usually match.
3485 if (!isBitShift && left->getBasicType() != right->getBasicType())
3486 {
3487 return false;
3488 }
3489
Olli Etuaho9dd217b2015-03-20 14:24:31 +02003490 // Check that type sizes match exactly on ops that require that.
Olli Etuahoff699002015-03-23 14:38:42 +02003491 // Also check restrictions for structs that contain arrays or samplers.
Jamie Madillb98c3a82015-07-23 14:26:04 -04003492 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003493 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003494 case EOpAssign:
3495 case EOpInitialize:
3496 case EOpEqual:
3497 case EOpNotEqual:
3498 // ESSL 1.00 sections 5.7, 5.8, 5.9
3499 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
3500 {
3501 error(loc, "undefined operation for structs containing arrays",
3502 GetOperatorString(op));
3503 return false;
3504 }
3505 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3506 // we interpret the spec so that this extends to structs containing samplers,
3507 // similarly to ESSL 1.00 spec.
3508 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
3509 left->getType().isStructureContainingSamplers())
3510 {
3511 error(loc, "undefined operation for structs containing samplers",
3512 GetOperatorString(op));
3513 return false;
3514 }
3515 case EOpLessThan:
3516 case EOpGreaterThan:
3517 case EOpLessThanEqual:
3518 case EOpGreaterThanEqual:
3519 if ((left->getNominalSize() != right->getNominalSize()) ||
3520 (left->getSecondarySize() != right->getSecondarySize()))
3521 {
3522 return false;
3523 }
3524 default:
3525 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003526 }
3527
Olli Etuahod6b14282015-03-17 14:31:35 +02003528 return true;
3529}
3530
Jamie Madillb98c3a82015-07-23 14:26:04 -04003531TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
3532 TIntermTyped *left,
3533 TIntermTyped *right,
3534 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02003535{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003536 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003537 return nullptr;
3538
Olli Etuahofc1806e2015-03-17 13:03:11 +02003539 switch (op)
3540 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003541 case EOpEqual:
3542 case EOpNotEqual:
3543 break;
3544 case EOpLessThan:
3545 case EOpGreaterThan:
3546 case EOpLessThanEqual:
3547 case EOpGreaterThanEqual:
3548 ASSERT(!left->isArray() && !right->isArray());
3549 if (left->isMatrix() || left->isVector() || left->getBasicType() == EbtStruct)
3550 {
3551 return nullptr;
3552 }
3553 break;
3554 case EOpLogicalOr:
3555 case EOpLogicalXor:
3556 case EOpLogicalAnd:
3557 ASSERT(!left->isArray() && !right->isArray());
3558 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isVector())
3559 {
3560 return nullptr;
3561 }
3562 break;
3563 case EOpAdd:
3564 case EOpSub:
3565 case EOpDiv:
3566 case EOpMul:
3567 ASSERT(!left->isArray() && !right->isArray());
3568 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
3569 {
3570 return nullptr;
3571 }
3572 break;
3573 case EOpIMod:
3574 ASSERT(!left->isArray() && !right->isArray());
3575 // Note that this is only for the % operator, not for mod()
3576 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool ||
3577 left->getBasicType() == EbtFloat)
3578 {
3579 return nullptr;
3580 }
3581 break;
3582 // Note that for bitwise ops, type checking is done in promote() to
3583 // share code between ops and compound assignment
3584 default:
3585 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02003586 }
3587
Olli Etuahofc1806e2015-03-17 13:03:11 +02003588 return intermediate.addBinaryMath(op, left, right, loc);
3589}
3590
Jamie Madillb98c3a82015-07-23 14:26:04 -04003591TIntermTyped *TParseContext::addBinaryMath(TOperator op,
3592 TIntermTyped *left,
3593 TIntermTyped *right,
3594 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003595{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003596 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003597 if (node == 0)
3598 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003599 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3600 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003601 return left;
3602 }
3603 return node;
3604}
3605
Jamie Madillb98c3a82015-07-23 14:26:04 -04003606TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
3607 TIntermTyped *left,
3608 TIntermTyped *right,
3609 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003610{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003611 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003612 if (node == 0)
3613 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003614 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3615 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003616 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02003617 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003618 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
3619 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003620 }
3621 return node;
3622}
3623
Jamie Madillb98c3a82015-07-23 14:26:04 -04003624TIntermTyped *TParseContext::createAssign(TOperator op,
3625 TIntermTyped *left,
3626 TIntermTyped *right,
3627 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003628{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003629 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003630 {
3631 return intermediate.addAssign(op, left, right, loc);
3632 }
3633 return nullptr;
3634}
3635
Jamie Madillb98c3a82015-07-23 14:26:04 -04003636TIntermTyped *TParseContext::addAssign(TOperator op,
3637 TIntermTyped *left,
3638 TIntermTyped *right,
3639 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003640{
3641 TIntermTyped *node = createAssign(op, left, right, loc);
3642 if (node == nullptr)
3643 {
3644 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02003645 return left;
3646 }
3647 return node;
3648}
3649
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02003650TIntermTyped *TParseContext::addComma(TIntermTyped *left,
3651 TIntermTyped *right,
3652 const TSourceLoc &loc)
3653{
Corentin Wallez0d959252016-07-12 17:26:32 -04003654 // WebGL2 section 5.26, the following results in an error:
3655 // "Sequence operator applied to void, arrays, or structs containing arrays"
3656 if (mShaderSpec == SH_WEBGL2_SPEC && (left->isArray() || left->getBasicType() == EbtVoid ||
3657 left->getType().isStructureContainingArrays() ||
3658 right->isArray() || right->getBasicType() == EbtVoid ||
3659 right->getType().isStructureContainingArrays()))
3660 {
3661 error(loc,
3662 "sequence operator is not allowed for void, arrays, or structs containing arrays",
3663 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04003664 }
3665
Olli Etuaho15200042015-11-04 16:56:31 +02003666 return intermediate.addComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02003667}
3668
Olli Etuaho49300862015-02-20 14:54:49 +02003669TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
3670{
3671 switch (op)
3672 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003673 case EOpContinue:
3674 if (mLoopNestingLevel <= 0)
3675 {
3676 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003677 }
3678 break;
3679 case EOpBreak:
3680 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
3681 {
3682 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003683 }
3684 break;
3685 case EOpReturn:
3686 if (mCurrentFunctionType->getBasicType() != EbtVoid)
3687 {
3688 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003689 }
3690 break;
3691 default:
3692 // No checks for discard
3693 break;
Olli Etuaho49300862015-02-20 14:54:49 +02003694 }
3695 return intermediate.addBranch(op, loc);
3696}
3697
Jamie Madillb98c3a82015-07-23 14:26:04 -04003698TIntermBranch *TParseContext::addBranch(TOperator op,
3699 TIntermTyped *returnValue,
3700 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02003701{
3702 ASSERT(op == EOpReturn);
3703 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003704 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02003705 {
3706 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02003707 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003708 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02003709 {
3710 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02003711 }
3712 return intermediate.addBranch(op, returnValue, loc);
3713}
3714
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003715void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
3716{
3717 ASSERT(!functionCall->isUserDefined());
3718 const TString &name = functionCall->getName();
3719 TIntermNode *offset = nullptr;
3720 TIntermSequence *arguments = functionCall->getSequence();
3721 if (name.compare(0, 16, "texelFetchOffset") == 0 ||
3722 name.compare(0, 16, "textureLodOffset") == 0 ||
3723 name.compare(0, 20, "textureProjLodOffset") == 0 ||
3724 name.compare(0, 17, "textureGradOffset") == 0 ||
3725 name.compare(0, 21, "textureProjGradOffset") == 0)
3726 {
3727 offset = arguments->back();
3728 }
3729 else if (name.compare(0, 13, "textureOffset") == 0 ||
3730 name.compare(0, 17, "textureProjOffset") == 0)
3731 {
3732 // A bias parameter might follow the offset parameter.
3733 ASSERT(arguments->size() >= 3);
3734 offset = (*arguments)[2];
3735 }
3736 if (offset != nullptr)
3737 {
3738 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
3739 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
3740 {
3741 TString unmangledName = TFunction::unmangleName(name);
3742 error(functionCall->getLine(), "Texture offset must be a constant expression",
3743 unmangledName.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003744 }
3745 else
3746 {
3747 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
3748 size_t size = offsetConstantUnion->getType().getObjectSize();
3749 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
3750 for (size_t i = 0u; i < size; ++i)
3751 {
3752 int offsetValue = values[i].getIConst();
3753 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
3754 {
3755 std::stringstream tokenStream;
3756 tokenStream << offsetValue;
3757 std::string token = tokenStream.str();
3758 error(offset->getLine(), "Texture offset value out of valid range",
3759 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003760 }
3761 }
3762 }
3763 }
3764}
3765
Jamie Madillb98c3a82015-07-23 14:26:04 -04003766TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
3767 TIntermNode *paramNode,
3768 TIntermNode *thisNode,
3769 const TSourceLoc &loc,
3770 bool *fatalError)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003771{
Jamie Madillb98c3a82015-07-23 14:26:04 -04003772 *fatalError = false;
3773 TOperator op = fnCall->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003774 TIntermTyped *callNode = nullptr;
3775
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003776 if (thisNode != nullptr)
3777 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003778 TConstantUnion *unionArray = new TConstantUnion[1];
Jamie Madillb98c3a82015-07-23 14:26:04 -04003779 int arraySize = 0;
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003780 TIntermTyped *typedThis = thisNode->getAsTyped();
3781 if (fnCall->getName() != "length")
3782 {
3783 error(loc, "invalid method", fnCall->getName().c_str());
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003784 }
3785 else if (paramNode != nullptr)
3786 {
3787 error(loc, "method takes no parameters", "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003788 }
3789 else if (typedThis == nullptr || !typedThis->isArray())
3790 {
3791 error(loc, "length can only be called on arrays", "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003792 }
3793 else
3794 {
Olli Etuaho96e67382015-04-23 14:27:02 +03003795 arraySize = typedThis->getArraySize();
Olli Etuaho39282e12015-04-23 15:41:48 +03003796 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003797 {
Olli Etuaho39282e12015-04-23 15:41:48 +03003798 // This code path can be hit with expressions like these:
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003799 // (a = b).length()
Olli Etuaho39282e12015-04-23 15:41:48 +03003800 // (func()).length()
3801 // (int[3](0, 1, 2)).length()
Jamie Madillb98c3a82015-07-23 14:26:04 -04003802 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
3803 // expression.
3804 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
3805 // spec section 5.9 which allows "An array, vector or matrix expression with the
3806 // length method applied".
3807 error(loc, "length can only be called on array names, not on array expressions",
3808 "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003809 }
3810 }
Olli Etuaho96e67382015-04-23 14:27:02 +03003811 unionArray->setIConst(arraySize);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003812 callNode =
3813 intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003814 }
3815 else if (op != EOpNull)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003816 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003817 // Then this should be a constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +03003818 callNode = addConstructor(paramNode, op, fnCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003819 }
3820 else
3821 {
3822 //
3823 // Not a constructor. Find it in the symbol table.
3824 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303825 const TFunction *fnCandidate;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003826 bool builtIn;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003827 fnCandidate = findFunction(loc, fnCall, mShaderVersion, &builtIn);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003828 if (fnCandidate)
3829 {
3830 //
3831 // A declared function.
3832 //
Olli Etuaho383b7912016-08-05 11:22:59 +03003833 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003834 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003835 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003836 }
3837 op = fnCandidate->getBuiltInOp();
3838 if (builtIn && op != EOpNull)
3839 {
3840 //
3841 // A function call mapped to a built-in operation.
3842 //
3843 if (fnCandidate->getParamCount() == 1)
3844 {
3845 //
3846 // Treat it like a built-in unary operator.
3847 //
Olli Etuaho15c2ac32015-11-09 15:51:43 +02003848 TIntermAggregate *paramAgg = paramNode->getAsAggregate();
3849 paramNode = paramAgg->getSequence()->front();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003850 callNode = createUnaryMath(op, paramNode->getAsTyped(), loc,
3851 &fnCandidate->getReturnType());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003852 if (callNode == nullptr)
3853 {
3854 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003855 extraInfoStream
3856 << "built in unary operator function. Type: "
3857 << static_cast<TIntermTyped *>(paramNode)->getCompleteString();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003858 std::string extraInfo = extraInfoStream.str();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003859 error(paramNode->getLine(), " wrong operand type", "Internal Error",
3860 extraInfo.c_str());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003861 *fatalError = true;
3862 return nullptr;
3863 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003864 }
3865 else
3866 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003867 TIntermAggregate *aggregate =
3868 intermediate.setAggregateOperator(paramNode, op, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003869 aggregate->setType(fnCandidate->getReturnType());
3870 aggregate->setPrecisionFromChildren();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02003871 if (aggregate->areChildrenConstQualified())
3872 {
3873 aggregate->getTypePointer()->setQualifier(EvqConst);
3874 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003875
3876 // Some built-in functions have out parameters too.
3877 functionCallLValueErrorCheck(fnCandidate, aggregate);
Arun Patole274f0702015-05-05 13:33:30 +05303878
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003879 // See if we can constant fold a built-in. Note that this may be possible even
3880 // if it is not const-qualified.
Olli Etuahob43846e2015-06-02 18:18:57 +03003881 TIntermTyped *foldedNode = intermediate.foldAggregateBuiltIn(aggregate);
Arun Patole274f0702015-05-05 13:33:30 +05303882 if (foldedNode)
3883 {
Arun Patole274f0702015-05-05 13:33:30 +05303884 callNode = foldedNode;
3885 }
Olli Etuahob43846e2015-06-02 18:18:57 +03003886 else
3887 {
3888 callNode = aggregate;
3889 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003890 }
3891 }
3892 else
3893 {
3894 // This is a real function call
Jamie Madillb98c3a82015-07-23 14:26:04 -04003895 TIntermAggregate *aggregate =
3896 intermediate.setAggregateOperator(paramNode, EOpFunctionCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003897 aggregate->setType(fnCandidate->getReturnType());
3898
Jamie Madillb98c3a82015-07-23 14:26:04 -04003899 // this is how we know whether the given function is a builtIn function or a user
3900 // defined function
3901 // if builtIn == false, it's a userDefined -> could be an overloaded
3902 // builtIn function also
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003903 // if builtIn == true, it's definitely a builtIn function with EOpNull
3904 if (!builtIn)
3905 aggregate->setUserDefined();
3906 aggregate->setName(fnCandidate->getMangledName());
Corentin Wallez71d147f2015-02-11 11:15:24 -08003907 aggregate->setFunctionId(fnCandidate->getUniqueId());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003908
3909 // This needs to happen after the name is set
3910 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003911 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003912 aggregate->setBuiltInFunctionPrecision();
3913
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003914 checkTextureOffsetConst(aggregate);
3915 }
3916
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003917 callNode = aggregate;
3918
3919 functionCallLValueErrorCheck(fnCandidate, aggregate);
3920 }
3921 }
3922 else
3923 {
3924 // error message was put out by findFunction()
3925 // Put on a dummy node for error recovery
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003926 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003927 unionArray->setFConst(0.0f);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003928 callNode = intermediate.addConstantUnion(unionArray,
3929 TType(EbtFloat, EbpUndefined, EvqConst), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003930 }
3931 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003932 return callNode;
3933}
3934
Jamie Madillb98c3a82015-07-23 14:26:04 -04003935TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
3936 TIntermTyped *trueBlock,
3937 TIntermTyped *falseBlock,
Olli Etuaho52901742015-04-15 13:42:45 +03003938 const TSourceLoc &loc)
3939{
Olli Etuaho856c4972016-08-08 11:38:39 +03003940 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03003941
3942 if (trueBlock->getType() != falseBlock->getType())
3943 {
3944 binaryOpError(loc, ":", trueBlock->getCompleteString(), falseBlock->getCompleteString());
Olli Etuaho52901742015-04-15 13:42:45 +03003945 return falseBlock;
3946 }
Olli Etuahoa2d53032015-04-15 14:14:44 +03003947 // ESSL1 sections 5.2 and 5.7:
3948 // ESSL3 section 5.7:
3949 // Ternary operator is not among the operators allowed for structures/arrays.
3950 if (trueBlock->isArray() || trueBlock->getBasicType() == EbtStruct)
3951 {
3952 error(loc, "ternary operator is not allowed for structures or arrays", ":");
Olli Etuahoa2d53032015-04-15 14:14:44 +03003953 return falseBlock;
3954 }
Corentin Wallez0d959252016-07-12 17:26:32 -04003955 // WebGL2 section 5.26, the following results in an error:
3956 // "Ternary operator applied to void, arrays, or structs containing arrays"
3957 if (mShaderSpec == SH_WEBGL2_SPEC && trueBlock->getBasicType() == EbtVoid)
3958 {
3959 error(loc, "ternary operator is not allowed for void", ":");
Corentin Wallez0d959252016-07-12 17:26:32 -04003960 return falseBlock;
3961 }
3962
Olli Etuaho52901742015-04-15 13:42:45 +03003963 return intermediate.addSelection(cond, trueBlock, falseBlock, loc);
3964}
Olli Etuaho49300862015-02-20 14:54:49 +02003965
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003966//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003967// Parse an array of strings using yyparse.
3968//
3969// Returns 0 for success.
3970//
Jamie Madillb98c3a82015-07-23 14:26:04 -04003971int PaParseStrings(size_t count,
3972 const char *const string[],
3973 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05303974 TParseContext *context)
3975{
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003976 if ((count == 0) || (string == NULL))
3977 return 1;
3978
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003979 if (glslang_initialize(context))
3980 return 1;
3981
alokp@chromium.org408c45e2012-04-05 15:54:43 +00003982 int error = glslang_scan(count, string, length, context);
3983 if (!error)
3984 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003985
alokp@chromium.org73bc2982012-06-19 18:48:05 +00003986 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00003987
alokp@chromium.org6b495712012-06-29 00:06:58 +00003988 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003989}