blob: 3476d8866c39800e4e1bcbf628b7b2fb7f47c0a2 [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{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001520 TType type(publicType);
1521 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
1522 mDirectiveHandler.pragma().stdgl.invariantAll)
1523 {
1524 TQualifier qualifier = type.getQualifier();
1525
1526 // The directive handler has already taken care of rejecting invalid uses of this pragma
1527 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
1528 // affected variable declarations:
1529 //
1530 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
1531 // elsewhere, in TranslatorGLSL.)
1532 //
1533 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
1534 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
1535 // the way this is currently implemented we have to enable this compiler option before
1536 // parsing the shader and determining the shading language version it uses. If this were
1537 // implemented as a post-pass, the workaround could be more targeted.
1538 //
1539 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
1540 // the specification, but there are desktop OpenGL drivers that expect that this is the
1541 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
1542 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
1543 {
1544 type.setInvariant(true);
1545 }
1546 }
1547
1548 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001549
Olli Etuahobab4c082015-04-24 16:38:49 +03001550 bool emptyDeclaration = (identifier == "");
Olli Etuahofa33d582015-04-09 14:33:12 +03001551
Olli Etuahobab4c082015-04-24 16:38:49 +03001552 mDeferredSingleDeclarationErrorCheck = emptyDeclaration;
1553
1554 if (emptyDeclaration)
1555 {
1556 if (publicType.isUnsizedArray())
1557 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001558 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1559 // error. It is assumed that this applies to empty declarations as well.
1560 error(identifierOrTypeLocation, "empty array declaration needs to specify a size",
1561 identifier.c_str());
Olli Etuahobab4c082015-04-24 16:38:49 +03001562 }
1563 }
1564 else
Jamie Madill60ed9812013-06-06 11:56:46 -04001565 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001566 singleDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001567
Olli Etuaho856c4972016-08-08 11:38:39 +03001568 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001569
Olli Etuaho2935c582015-04-08 14:32:06 +03001570 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001571 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001572
1573 if (variable && symbol)
Jamie Madill60ed9812013-06-06 11:56:46 -04001574 symbol->setId(variable->getUniqueId());
Jamie Madill60ed9812013-06-06 11:56:46 -04001575 }
1576
Olli Etuahoe7847b02015-03-16 11:56:12 +02001577 return intermediate.makeAggregate(symbol, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001578}
1579
Olli Etuahoe7847b02015-03-16 11:56:12 +02001580TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1581 const TSourceLoc &identifierLocation,
1582 const TString &identifier,
1583 const TSourceLoc &indexLocation,
1584 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04001585{
Olli Etuahofa33d582015-04-09 14:33:12 +03001586 mDeferredSingleDeclarationErrorCheck = false;
1587
Olli Etuaho383b7912016-08-05 11:22:59 +03001588 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001589
Olli Etuaho856c4972016-08-08 11:38:39 +03001590 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001591
Olli Etuaho8a176262016-08-16 14:23:01 +03001592 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001593
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001594 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001595
Olli Etuaho856c4972016-08-08 11:38:39 +03001596 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001597 // Make the type an array even if size check failed.
1598 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1599 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04001600
Olli Etuaho2935c582015-04-08 14:32:06 +03001601 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001602 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001603
Olli Etuahoe7847b02015-03-16 11:56:12 +02001604 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001605 if (variable && symbol)
Jamie Madill60ed9812013-06-06 11:56:46 -04001606 symbol->setId(variable->getUniqueId());
Jamie Madill60ed9812013-06-06 11:56:46 -04001607
Olli Etuahoe7847b02015-03-16 11:56:12 +02001608 return intermediate.makeAggregate(symbol, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001609}
1610
Jamie Madill06145232015-05-13 13:10:01 -04001611TIntermAggregate *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
Olli Etuahoe7847b02015-03-16 11:56:12 +02001612 const TSourceLoc &identifierLocation,
1613 const TString &identifier,
1614 const TSourceLoc &initLocation,
1615 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04001616{
Olli Etuahofa33d582015-04-09 14:33:12 +03001617 mDeferredSingleDeclarationErrorCheck = false;
1618
Olli Etuaho383b7912016-08-05 11:22:59 +03001619 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001620
Olli Etuahoe7847b02015-03-16 11:56:12 +02001621 TIntermNode *intermNode = nullptr;
1622 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04001623 {
1624 //
1625 // Build intermediate representation
1626 //
Olli Etuahoe7847b02015-03-16 11:56:12 +02001627 return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : nullptr;
Jamie Madill60ed9812013-06-06 11:56:46 -04001628 }
1629 else
1630 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001631 return nullptr;
Jamie Madill60ed9812013-06-06 11:56:46 -04001632 }
1633}
1634
Jamie Madillb98c3a82015-07-23 14:26:04 -04001635TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration(
1636 TPublicType &publicType,
1637 const TSourceLoc &identifierLocation,
1638 const TString &identifier,
1639 const TSourceLoc &indexLocation,
1640 TIntermTyped *indexExpression,
1641 const TSourceLoc &initLocation,
1642 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001643{
1644 mDeferredSingleDeclarationErrorCheck = false;
1645
Olli Etuaho383b7912016-08-05 11:22:59 +03001646 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001647
Olli Etuaho8a176262016-08-16 14:23:01 +03001648 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001649
1650 TPublicType arrayType(publicType);
1651
Olli Etuaho856c4972016-08-08 11:38:39 +03001652 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001653 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
1654 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03001655 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001656 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001657 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001658 }
1659 // Make the type an array even if size check failed.
1660 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1661 arrayType.setArraySize(size);
1662
1663 // initNode will correspond to the whole of "type b[n] = initializer".
1664 TIntermNode *initNode = nullptr;
1665 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
1666 {
1667 return initNode ? intermediate.makeAggregate(initNode, initLocation) : nullptr;
1668 }
1669 else
1670 {
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001671 return nullptr;
1672 }
1673}
1674
Olli Etuahoe7847b02015-03-16 11:56:12 +02001675TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc,
Jamie Madill47e3ec02014-08-20 16:38:33 -04001676 const TSourceLoc &identifierLoc,
1677 const TString *identifier,
1678 const TSymbol *symbol)
1679{
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001680 // invariant declaration
Olli Etuaho856c4972016-08-08 11:38:39 +03001681 checkIsAtGlobalLevel(invariantLoc, "invariant varying");
Jamie Madill47e3ec02014-08-20 16:38:33 -04001682
1683 if (!symbol)
1684 {
1685 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001686 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001687 }
1688 else
1689 {
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001690 const TString kGlFrontFacing("gl_FrontFacing");
1691 if (*identifier == kGlFrontFacing)
1692 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001693 error(identifierLoc, "identifier should not be declared as invariant",
1694 identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001695 return nullptr;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001696 }
Jamie Madill2c433252014-12-03 12:36:54 -05001697 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001698 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
1699 ASSERT(variable);
1700 const TType &type = variable->getType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04001701 TIntermSymbol *intermSymbol =
1702 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001703
1704 TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc);
1705 aggregate->setOp(EOpInvariantDeclaration);
1706 return aggregate;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001707 }
1708}
1709
Jamie Madillb98c3a82015-07-23 14:26:04 -04001710TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType,
1711 TIntermAggregate *aggregateDeclaration,
1712 const TSourceLoc &identifierLocation,
1713 const TString &identifier)
Jamie Madill502d66f2013-06-20 11:55:52 -04001714{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001715 // If the declaration starting this declarator list was empty (example: int,), some checks were
1716 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001717 if (mDeferredSingleDeclarationErrorCheck)
1718 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001719 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001720 mDeferredSingleDeclarationErrorCheck = false;
1721 }
1722
Olli Etuaho856c4972016-08-08 11:38:39 +03001723 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001724
Olli Etuaho856c4972016-08-08 11:38:39 +03001725 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04001726
Olli Etuaho2935c582015-04-08 14:32:06 +03001727 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001728 declareVariable(identifierLocation, identifier, TType(publicType), &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001729
Jamie Madillb98c3a82015-07-23 14:26:04 -04001730 TIntermSymbol *symbol =
1731 intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001732 if (variable && symbol)
Jamie Madill502d66f2013-06-20 11:55:52 -04001733 symbol->setId(variable->getUniqueId());
1734
Olli Etuahoe7847b02015-03-16 11:56:12 +02001735 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001736}
1737
Jamie Madillb98c3a82015-07-23 14:26:04 -04001738TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType,
1739 TIntermAggregate *aggregateDeclaration,
1740 const TSourceLoc &identifierLocation,
1741 const TString &identifier,
1742 const TSourceLoc &arrayLocation,
1743 TIntermTyped *indexExpression)
Jamie Madill502d66f2013-06-20 11:55:52 -04001744{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001745 // If the declaration starting this declarator list was empty (example: int,), some checks were
1746 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001747 if (mDeferredSingleDeclarationErrorCheck)
1748 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001749 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001750 mDeferredSingleDeclarationErrorCheck = false;
1751 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001752
Olli Etuaho856c4972016-08-08 11:38:39 +03001753 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001754
Olli Etuaho856c4972016-08-08 11:38:39 +03001755 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04001756
Olli Etuaho8a176262016-08-16 14:23:01 +03001757 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04001758 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001759 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03001760 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03001761 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001762
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001763 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001764 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04001765
Jamie Madillb98c3a82015-07-23 14:26:04 -04001766 TIntermSymbol *symbol =
1767 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001768 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001769 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001770
1771 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001772 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001773
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001774 return nullptr;
Jamie Madill502d66f2013-06-20 11:55:52 -04001775}
1776
Jamie Madillb98c3a82015-07-23 14:26:04 -04001777TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicType,
1778 TIntermAggregate *aggregateDeclaration,
1779 const TSourceLoc &identifierLocation,
1780 const TString &identifier,
1781 const TSourceLoc &initLocation,
1782 TIntermTyped *initializer)
Jamie Madill502d66f2013-06-20 11:55:52 -04001783{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001784 // If the declaration starting this declarator list was empty (example: int,), some checks were
1785 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001786 if (mDeferredSingleDeclarationErrorCheck)
1787 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001788 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001789 mDeferredSingleDeclarationErrorCheck = false;
1790 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001791
Olli Etuaho856c4972016-08-08 11:38:39 +03001792 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001793
Olli Etuahoe7847b02015-03-16 11:56:12 +02001794 TIntermNode *intermNode = nullptr;
1795 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04001796 {
1797 //
1798 // build the intermediate representation
1799 //
1800 if (intermNode)
1801 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001802 return intermediate.growAggregate(aggregateDeclaration, intermNode, initLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001803 }
1804 else
1805 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001806 return aggregateDeclaration;
Jamie Madill502d66f2013-06-20 11:55:52 -04001807 }
1808 }
1809 else
1810 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001811 return nullptr;
Jamie Madill502d66f2013-06-20 11:55:52 -04001812 }
1813}
1814
Jamie Madill06145232015-05-13 13:10:01 -04001815TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001816 TIntermAggregate *aggregateDeclaration,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301817 const TSourceLoc &identifierLocation,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001818 const TString &identifier,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301819 const TSourceLoc &indexLocation,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001820 TIntermTyped *indexExpression,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001821 const TSourceLoc &initLocation,
1822 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001823{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001824 // If the declaration starting this declarator list was empty (example: int,), some checks were
1825 // not performed.
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001826 if (mDeferredSingleDeclarationErrorCheck)
1827 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001828 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001829 mDeferredSingleDeclarationErrorCheck = false;
1830 }
1831
Olli Etuaho856c4972016-08-08 11:38:39 +03001832 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001833
Olli Etuaho8a176262016-08-16 14:23:01 +03001834 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001835
1836 TPublicType arrayType(publicType);
1837
Olli Etuaho856c4972016-08-08 11:38:39 +03001838 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001839 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
1840 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03001841 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001842 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001843 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001844 }
1845 // Make the type an array even if size check failed.
1846 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1847 arrayType.setArraySize(size);
1848
1849 // initNode will correspond to the whole of "b[n] = initializer".
1850 TIntermNode *initNode = nullptr;
1851 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
1852 {
1853 if (initNode)
1854 {
1855 return intermediate.growAggregate(aggregateDeclaration, initNode, initLocation);
1856 }
1857 else
1858 {
1859 return aggregateDeclaration;
1860 }
1861 }
1862 else
1863 {
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001864 return nullptr;
1865 }
1866}
1867
Jamie Madilla295edf2013-06-06 11:56:48 -04001868void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
1869{
Jamie Madilla295edf2013-06-06 11:56:48 -04001870 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04001871
1872 // It should never be the case, but some strange parser errors can send us here.
1873 if (layoutQualifier.isEmpty())
1874 {
1875 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04001876 return;
1877 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001878
Martin Radev802abe02016-08-04 17:48:32 +03001879 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04001880 {
Martin Radev802abe02016-08-04 17:48:32 +03001881 error(typeQualifier.line, "invalid combination:", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04001882 return;
1883 }
1884
Martin Radev802abe02016-08-04 17:48:32 +03001885 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04001886 {
Martin Radev802abe02016-08-04 17:48:32 +03001887 if (mComputeShaderLocalSizeDeclared &&
1888 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
1889 {
1890 error(typeQualifier.line, "Work group size does not match the previous declaration",
1891 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001892 return;
1893 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001894
Martin Radev802abe02016-08-04 17:48:32 +03001895 if (mShaderVersion < 310)
1896 {
1897 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001898 return;
1899 }
Jamie Madill099c0f32013-06-20 11:55:52 -04001900
Martin Radev802abe02016-08-04 17:48:32 +03001901 if (!layoutQualifier.isGroupSizeSpecified())
1902 {
1903 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001904 return;
1905 }
1906
1907 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
1908 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
1909
1910 const TConstantUnion *maxComputeWorkGroupSizeData =
1911 maxComputeWorkGroupSize->getConstPointer();
1912
1913 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
1914 {
1915 if (layoutQualifier.localSize[i] != -1)
1916 {
1917 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
1918 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
1919 if (mComputeShaderLocalSize[i] < 1 ||
1920 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
1921 {
1922 std::stringstream errorMessageStream;
1923 errorMessageStream << "Value must be at least 1 and no greater than "
1924 << maxComputeWorkGroupSizeValue;
1925 const std::string &errorMessage = errorMessageStream.str();
1926
1927 error(typeQualifier.line, "invalid value:", getLocalSizeString(i),
1928 errorMessage.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03001929 return;
1930 }
1931 }
1932 }
1933
1934 mComputeShaderLocalSizeDeclared = true;
1935 }
1936 else
Jamie Madill1566ef72013-06-20 11:55:54 -04001937 {
Martin Radev802abe02016-08-04 17:48:32 +03001938
Olli Etuaho8a176262016-08-16 14:23:01 +03001939 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03001940 {
Martin Radev802abe02016-08-04 17:48:32 +03001941 return;
1942 }
1943
1944 if (typeQualifier.qualifier != EvqUniform)
1945 {
1946 error(typeQualifier.line, "invalid qualifier:",
1947 getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
Martin Radev802abe02016-08-04 17:48:32 +03001948 return;
1949 }
1950
1951 if (mShaderVersion < 300)
1952 {
1953 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
1954 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001955 return;
1956 }
1957
Olli Etuaho856c4972016-08-08 11:38:39 +03001958 checkLocationIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001959
1960 if (layoutQualifier.matrixPacking != EmpUnspecified)
1961 {
1962 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
1963 }
1964
1965 if (layoutQualifier.blockStorage != EbsUnspecified)
1966 {
1967 mDefaultBlockStorage = layoutQualifier.blockStorage;
1968 }
Jamie Madill1566ef72013-06-20 11:55:54 -04001969 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001970}
1971
Olli Etuahoee63f5d2016-01-04 11:34:54 +02001972TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function,
1973 const TSourceLoc &location)
1974{
Olli Etuaho5d653182016-01-04 14:43:28 +02001975 // Note: symbolTableFunction could be the same as function if this is the first declaration.
1976 // Either way the instance in the symbol table is used to track whether the function is declared
1977 // multiple times.
1978 TFunction *symbolTableFunction =
1979 static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion()));
1980 if (symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100)
1981 {
1982 // ESSL 1.00.17 section 4.2.7.
1983 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
1984 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02001985 }
1986 symbolTableFunction->setHasPrototypeDeclaration();
1987
Olli Etuahoee63f5d2016-01-04 11:34:54 +02001988 TIntermAggregate *prototype = new TIntermAggregate;
1989 prototype->setType(function.getReturnType());
1990 prototype->setName(function.getMangledName());
1991 prototype->setFunctionId(function.getUniqueId());
1992
1993 for (size_t i = 0; i < function.getParamCount(); i++)
1994 {
1995 const TConstParameter &param = function.getParam(i);
1996 if (param.name != 0)
1997 {
1998 TVariable variable(param.name, *param.type);
1999
2000 TIntermSymbol *paramSymbol = intermediate.addSymbol(
2001 variable.getUniqueId(), variable.getName(), variable.getType(), location);
2002 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
2003 }
2004 else
2005 {
2006 TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
2007 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
2008 }
2009 }
2010
2011 prototype->setOp(EOpPrototype);
2012
2013 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002014
2015 if (!symbolTable.atGlobalLevel())
2016 {
2017 // ESSL 3.00.4 section 4.2.4.
2018 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002019 }
2020
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002021 return prototype;
2022}
2023
2024TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function,
2025 TIntermAggregate *functionPrototype,
2026 TIntermAggregate *functionBody,
2027 const TSourceLoc &location)
2028{
2029 //?? Check that all paths return a value if return type != void ?
2030 // May be best done as post process phase on intermediate code
2031 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2032 {
2033 error(location, "function does not return a value:", "", function.getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002034 }
2035
2036 TIntermAggregate *aggregate =
2037 intermediate.growAggregate(functionPrototype, functionBody, location);
2038 intermediate.setAggregateOperator(aggregate, EOpFunction, location);
2039 aggregate->setName(function.getMangledName().c_str());
2040 aggregate->setType(function.getReturnType());
2041 aggregate->setFunctionId(function.getUniqueId());
2042
2043 symbolTable.pop();
2044 return aggregate;
2045}
2046
Jamie Madill185fb402015-06-12 15:48:48 -04002047void TParseContext::parseFunctionPrototype(const TSourceLoc &location,
2048 TFunction *function,
2049 TIntermAggregate **aggregateOut)
2050{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002051 const TSymbol *builtIn =
2052 symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002053
2054 if (builtIn)
2055 {
2056 error(location, "built-in functions cannot be redefined", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002057 }
2058
Jamie Madillb98c3a82015-07-23 14:26:04 -04002059 TFunction *prevDec =
2060 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Jamie Madill185fb402015-06-12 15:48:48 -04002061 //
2062 // Note: 'prevDec' could be 'function' if this is the first time we've seen function
2063 // as it would have just been put in the symbol table. Otherwise, we're looking up
2064 // an earlier occurance.
2065 //
2066 if (prevDec->isDefined())
2067 {
2068 // Then this function already has a body.
2069 error(location, "function already has a body", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002070 }
2071 prevDec->setDefined();
2072 //
2073 // Overload the unique ID of the definition to be the same unique ID as the declaration.
2074 // Eventually we will probably want to have only a single definition and just swap the
2075 // arguments to be the definition's arguments.
2076 //
2077 function->setUniqueId(prevDec->getUniqueId());
2078
2079 // Raise error message if main function takes any parameters or return anything other than void
2080 if (function->getName() == "main")
2081 {
2082 if (function->getParamCount() > 0)
2083 {
2084 error(location, "function cannot take any parameter(s)", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002085 }
2086 if (function->getReturnType().getBasicType() != EbtVoid)
2087 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002088 error(location, "", function->getReturnType().getBasicString(),
2089 "main function cannot return a value");
Jamie Madill185fb402015-06-12 15:48:48 -04002090 }
2091 }
2092
2093 //
2094 // Remember the return type for later checking for RETURN statements.
2095 //
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002096 mCurrentFunctionType = &(prevDec->getReturnType());
2097 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002098
2099 //
2100 // Insert parameters into the symbol table.
2101 // If the parameter has no name, it's not an error, just don't insert it
2102 // (could be used for unused args).
2103 //
2104 // Also, accumulate the list of parameters into the HIL, so lower level code
2105 // knows where to find parameters.
2106 //
2107 TIntermAggregate *paramNodes = new TIntermAggregate;
2108 for (size_t i = 0; i < function->getParamCount(); i++)
2109 {
2110 const TConstParameter &param = function->getParam(i);
2111 if (param.name != 0)
2112 {
2113 TVariable *variable = new TVariable(param.name, *param.type);
2114 //
2115 // Insert the parameters with name in the symbol table.
2116 //
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002117 if (!symbolTable.declare(variable))
2118 {
Jamie Madill185fb402015-06-12 15:48:48 -04002119 error(location, "redefinition", variable->getName().c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002120 paramNodes = intermediate.growAggregate(
2121 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
2122 continue;
Jamie Madill185fb402015-06-12 15:48:48 -04002123 }
2124
2125 //
2126 // Add the parameter to the HIL
2127 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002128 TIntermSymbol *symbol = intermediate.addSymbol(
2129 variable->getUniqueId(), variable->getName(), variable->getType(), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002130
2131 paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
2132 }
2133 else
2134 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002135 paramNodes = intermediate.growAggregate(
2136 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002137 }
2138 }
2139 intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
2140 *aggregateOut = paramNodes;
2141 setLoopNestingLevel(0);
2142}
2143
Jamie Madillb98c3a82015-07-23 14:26:04 -04002144TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002145{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002146 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002147 // We don't know at this point whether this is a function definition or a prototype.
2148 // The definition production code will check for redefinitions.
2149 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002150 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002151 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2152 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002153 //
2154 TFunction *prevDec =
2155 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302156
2157 if (getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltIn(function->getName().c_str()))
2158 {
2159 // With ESSL 3.00, names of built-in functions cannot be redeclared as functions.
2160 // Therefore overloading or redefining builtin functions is an error.
2161 error(location, "Name of a built-in function cannot be redeclared as function",
2162 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302163 }
2164 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002165 {
2166 if (prevDec->getReturnType() != function->getReturnType())
2167 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002168 error(location, "overloaded functions must have the same return type",
Jamie Madill185fb402015-06-12 15:48:48 -04002169 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002170 }
2171 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2172 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002173 if (prevDec->getParam(i).type->getQualifier() !=
2174 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002175 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002176 error(location, "overloaded functions must have the same parameter qualifiers",
Jamie Madill185fb402015-06-12 15:48:48 -04002177 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002178 }
2179 }
2180 }
2181
2182 //
2183 // Check for previously declared variables using the same name.
2184 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002185 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002186 if (prevSym)
2187 {
2188 if (!prevSym->isFunction())
2189 {
2190 error(location, "redefinition", function->getName().c_str(), "function");
Jamie Madill185fb402015-06-12 15:48:48 -04002191 }
2192 }
2193 else
2194 {
2195 // Insert the unmangled name to detect potential future redefinition as a variable.
Jamie Madillb98c3a82015-07-23 14:26:04 -04002196 TFunction *newFunction =
2197 new TFunction(NewPoolTString(function->getName().c_str()), &function->getReturnType());
Jamie Madill185fb402015-06-12 15:48:48 -04002198 symbolTable.getOuterLevel()->insertUnmangled(newFunction);
2199 }
2200
2201 // We're at the inner scope level of the function's arguments and body statement.
2202 // Add the function prototype to the surrounding scope instead.
2203 symbolTable.getOuterLevel()->insert(function);
2204
2205 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002206 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2207 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002208 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2209 //
2210 return function;
2211}
2212
Olli Etuaho9de84a52016-06-14 17:36:01 +03002213TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2214 const TString *name,
2215 const TSourceLoc &location)
2216{
2217 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2218 {
2219 error(location, "no qualifiers allowed for function return",
2220 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002221 }
2222 if (!type.layoutQualifier.isEmpty())
2223 {
2224 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002225 }
2226 // make sure a sampler is not involved as well...
Olli Etuaho856c4972016-08-08 11:38:39 +03002227 checkIsNotSampler(location, type, "samplers can't be function return values");
Olli Etuahoe29324f2016-06-15 10:58:03 +03002228 if (mShaderVersion < 300)
2229 {
2230 // Array return values are forbidden, but there's also no valid syntax for declaring array
2231 // return values in ESSL 1.00.
2232 ASSERT(type.arraySize == 0 || mDiagnostics.numErrors() > 0);
2233
2234 if (type.isStructureContainingArrays())
2235 {
2236 // ESSL 1.00.17 section 6.1 Function Definitions
2237 error(location, "structures containing arrays can't be function return values",
2238 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002239 }
2240 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002241
2242 // Add the function as a prototype after parsing it (we do not support recursion)
2243 return new TFunction(name, new TType(type));
2244}
2245
Jamie Madill06145232015-05-13 13:10:01 -04002246TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002247{
Jamie Madill06145232015-05-13 13:10:01 -04002248 TPublicType publicType = publicTypeIn;
Olli Etuahobd163f62015-11-13 12:15:38 +02002249 if (publicType.isStructSpecifier)
2250 {
2251 error(publicType.line, "constructor can't be a structure definition",
2252 getBasicString(publicType.type));
Olli Etuahobd163f62015-11-13 12:15:38 +02002253 }
2254
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002255 TOperator op = EOpNull;
2256 if (publicType.userDef)
2257 {
2258 op = EOpConstructStruct;
2259 }
2260 else
2261 {
Geoff Lang156d7192016-07-21 16:11:00 -04002262 op = sh::TypeToConstructorOperator(TType(publicType));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002263 if (op == EOpNull)
2264 {
2265 error(publicType.line, "cannot construct this type", getBasicString(publicType.type));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002266 publicType.type = EbtFloat;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002267 op = EOpConstructFloat;
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002268 }
2269 }
2270
2271 TString tempString;
Dmitry Skiba7f17a502015-06-22 15:08:39 -07002272 const TType *type = new TType(publicType);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002273 return new TFunction(&tempString, type, op);
2274}
2275
Jamie Madillb98c3a82015-07-23 14:26:04 -04002276// This function is used to test for the correctness of the parameters passed to various constructor
2277// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002278//
Olli Etuaho856c4972016-08-08 11:38:39 +03002279// 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 +00002280//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002281TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002282 TOperator op,
2283 TFunction *fnCall,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302284 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002285{
Olli Etuaho856c4972016-08-08 11:38:39 +03002286 TType type = fnCall->getReturnType();
2287 if (type.isUnsizedArray())
2288 {
2289 type.setArraySize(static_cast<unsigned int>(fnCall->getParamCount()));
2290 }
2291 bool constType = true;
2292 for (size_t i = 0; i < fnCall->getParamCount(); ++i)
2293 {
2294 const TConstParameter &param = fnCall->getParam(i);
2295 if (param.type->getQualifier() != EvqConst)
2296 constType = false;
2297 }
2298 if (constType)
2299 type.setQualifier(EvqConst);
2300
Olli Etuaho8a176262016-08-16 14:23:01 +03002301 if (!checkConstructorArguments(line, arguments, *fnCall, op, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002302 {
2303 TIntermTyped *dummyNode = intermediate.setAggregateOperator(nullptr, op, line);
2304 dummyNode->setType(type);
2305 return dummyNode;
2306 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002307 TIntermAggregate *constructor = arguments->getAsAggregate();
2308 ASSERT(constructor != nullptr);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002309
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002310 // Turn the argument list itself into a constructor
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002311 constructor->setOp(op);
2312 constructor->setLine(line);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002313 ASSERT(constructor->isConstructor());
2314
2315 // Need to set type before setPrecisionFromChildren() because bool doesn't have precision.
Olli Etuaho856c4972016-08-08 11:38:39 +03002316 constructor->setType(type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002317
Olli Etuaho21203702014-11-13 16:16:21 +02002318 // Structs should not be precision qualified, the individual members may be.
2319 // Built-in types on the other hand should be precision qualified.
2320 if (op != EOpConstructStruct)
2321 {
2322 constructor->setPrecisionFromChildren();
Olli Etuaho856c4972016-08-08 11:38:39 +03002323 type.setPrecision(constructor->getPrecision());
Olli Etuaho21203702014-11-13 16:16:21 +02002324 }
2325
Olli Etuaho856c4972016-08-08 11:38:39 +03002326 constructor->setType(type);
2327
Olli Etuaho1d122782015-11-06 15:35:17 +02002328 TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002329 if (constConstructor)
2330 {
2331 return constConstructor;
2332 }
2333
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002334 return constructor;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002335}
2336
Olli Etuaho90892fb2016-07-14 14:44:51 +03002337// This function returns vector field(s) being accessed from a constant vector.
2338TIntermConstantUnion *TParseContext::foldVectorSwizzle(TVectorFields &fields,
2339 TIntermConstantUnion *baseNode,
2340 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002341{
Olli Etuaho90892fb2016-07-14 14:44:51 +03002342 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002343 ASSERT(unionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002344
Arun Patole7e7e68d2015-05-22 12:02:25 +05302345 TConstantUnion *constArray = new TConstantUnion[fields.num];
Olli Etuaho90892fb2016-07-14 14:44:51 +03002346 const auto &type = baseNode->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002347
Arun Patole7e7e68d2015-05-22 12:02:25 +05302348 for (int i = 0; i < fields.num; i++)
2349 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002350 // Out-of-range indices should already be checked.
2351 ASSERT(fields.offsets[i] < type.getNominalSize());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002352 constArray[i] = unionArray[fields.offsets[i]];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302353 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03002354 return intermediate.addConstantUnion(constArray, type, location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002355}
2356
Olli Etuaho90892fb2016-07-14 14:44:51 +03002357// This function returns the column vector being accessed from a constant matrix.
2358TIntermConstantUnion *TParseContext::foldMatrixSubscript(int index,
2359 TIntermConstantUnion *baseNode,
2360 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002361{
Olli Etuaho90892fb2016-07-14 14:44:51 +03002362 ASSERT(index < baseNode->getType().getCols());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002363
Olli Etuaho90892fb2016-07-14 14:44:51 +03002364 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
2365 int size = baseNode->getType().getRows();
2366 return intermediate.addConstantUnion(&unionArray[size * index], baseNode->getType(), location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002367}
2368
Olli Etuaho90892fb2016-07-14 14:44:51 +03002369// This function returns an element of an array accessed from a constant array.
2370TIntermConstantUnion *TParseContext::foldArraySubscript(int index,
2371 TIntermConstantUnion *baseNode,
2372 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002373{
Olli Etuaho856c4972016-08-08 11:38:39 +03002374 ASSERT(index < static_cast<int>(baseNode->getArraySize()));
Olli Etuaho90892fb2016-07-14 14:44:51 +03002375
2376 TType arrayElementType = baseNode->getType();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002377 arrayElementType.clearArrayness();
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002378 size_t arrayElementSize = arrayElementType.getObjectSize();
Olli Etuaho90892fb2016-07-14 14:44:51 +03002379 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
2380 return intermediate.addConstantUnion(&unionArray[arrayElementSize * index], baseNode->getType(),
2381 location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002382}
2383
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002384//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002385// This function returns the value of a particular field inside a constant structure from the symbol
2386// table.
2387// If there is an embedded/nested struct, it appropriately calls addConstStructNested or
2388// addConstStructFromAggr function and returns the parse-tree with the values of the embedded/nested
2389// struct.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002390//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002391TIntermTyped *TParseContext::addConstStruct(const TString &identifier,
2392 TIntermTyped *node,
2393 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002394{
Arun Patole7e7e68d2015-05-22 12:02:25 +05302395 const TFieldList &fields = node->getType().getStruct()->fields();
Jamie Madillb98c3a82015-07-23 14:26:04 -04002396 size_t instanceSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002397
Arun Patole7e7e68d2015-05-22 12:02:25 +05302398 for (size_t index = 0; index < fields.size(); ++index)
2399 {
2400 if (fields[index]->name() == identifier)
2401 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002402 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302403 }
2404 else
2405 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002406 instanceSize += fields[index]->type()->getObjectSize();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002407 }
2408 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002409
Jamie Madill94bf7f22013-07-08 13:31:15 -04002410 TIntermTyped *typedNode;
2411 TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
Arun Patole7e7e68d2015-05-22 12:02:25 +05302412 if (tempConstantNode)
2413 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002414 const TConstantUnion *constArray = tempConstantNode->getUnionArrayPointer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002415
Jamie Madillb98c3a82015-07-23 14:26:04 -04002416 // type will be changed in the calling function
2417 typedNode = intermediate.addConstantUnion(constArray + instanceSize,
2418 tempConstantNode->getType(), line);
Arun Patole7e7e68d2015-05-22 12:02:25 +05302419 }
2420 else
2421 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002422 error(line, "Cannot offset into the structure", "Error");
Olli Etuaho383b7912016-08-05 11:22:59 +03002423 return nullptr;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002424 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002425
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002426 return typedNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002427}
2428
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002429//
2430// Interface/uniform blocks
2431//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002432TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualifier,
2433 const TSourceLoc &nameLine,
2434 const TString &blockName,
2435 TFieldList *fieldList,
2436 const TString *instanceName,
2437 const TSourceLoc &instanceLine,
2438 TIntermTyped *arrayIndex,
2439 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002440{
Olli Etuaho856c4972016-08-08 11:38:39 +03002441 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002442
2443 if (typeQualifier.qualifier != EvqUniform)
2444 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302445 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier),
2446 "interface blocks must be uniform");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002447 }
2448
Jamie Madill099c0f32013-06-20 11:55:52 -04002449 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03002450 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04002451
Jamie Madill099c0f32013-06-20 11:55:52 -04002452 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2453 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002454 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002455 }
2456
Jamie Madill1566ef72013-06-20 11:55:54 -04002457 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2458 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002459 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002460 }
2461
Olli Etuaho856c4972016-08-08 11:38:39 +03002462 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002463
Arun Patole7e7e68d2015-05-22 12:02:25 +05302464 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2465 if (!symbolTable.declare(blockNameSymbol))
2466 {
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002467 error(nameLine, "redefinition", blockName.c_str(), "interface block name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002468 }
2469
Jamie Madill98493dd2013-07-08 14:39:03 -04002470 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302471 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2472 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002473 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302474 TType *fieldType = field->type();
2475 if (IsSampler(fieldType->getBasicType()))
2476 {
2477 error(field->line(), "unsupported type", fieldType->getBasicString(),
2478 "sampler types are not allowed in interface blocks");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002479 }
2480
Jamie Madill98493dd2013-07-08 14:39:03 -04002481 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002482 switch (qualifier)
2483 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002484 case EvqGlobal:
2485 case EvqUniform:
2486 break;
2487 default:
2488 error(field->line(), "invalid qualifier on interface block member",
2489 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04002490 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002491 }
Jamie Madilla5efff92013-06-06 11:56:47 -04002492
2493 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04002494 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03002495 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Jamie Madill099c0f32013-06-20 11:55:52 -04002496
Jamie Madill98493dd2013-07-08 14:39:03 -04002497 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04002498 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002499 error(field->line(), "invalid layout qualifier:",
2500 getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
Jamie Madill1566ef72013-06-20 11:55:54 -04002501 }
2502
Jamie Madill98493dd2013-07-08 14:39:03 -04002503 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04002504 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002505 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002506 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002507 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04002508 {
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002509 warning(field->line(), "extraneous layout qualifier:",
Jamie Madillb98c3a82015-07-23 14:26:04 -04002510 getMatrixPackingString(fieldLayoutQualifier.matrixPacking),
2511 "only has an effect on matrix types");
Jamie Madill099c0f32013-06-20 11:55:52 -04002512 }
2513
Jamie Madill98493dd2013-07-08 14:39:03 -04002514 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002515 }
2516
Jamie Madill98493dd2013-07-08 14:39:03 -04002517 // add array index
Olli Etuaho856c4972016-08-08 11:38:39 +03002518 unsigned int arraySize = 0;
2519 if (arrayIndex != nullptr)
Jamie Madill98493dd2013-07-08 14:39:03 -04002520 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002521 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
Jamie Madill98493dd2013-07-08 14:39:03 -04002522 }
2523
Jamie Madillb98c3a82015-07-23 14:26:04 -04002524 TInterfaceBlock *interfaceBlock =
2525 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2526 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
2527 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002528
2529 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04002530 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002531
Jamie Madill98493dd2013-07-08 14:39:03 -04002532 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002533 {
2534 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04002535 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2536 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002537 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302538 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04002539
2540 // set parent pointer of the field variable
2541 fieldType->setInterfaceBlock(interfaceBlock);
2542
Arun Patole7e7e68d2015-05-22 12:02:25 +05302543 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04002544 fieldVariable->setQualifier(typeQualifier.qualifier);
2545
Arun Patole7e7e68d2015-05-22 12:02:25 +05302546 if (!symbolTable.declare(fieldVariable))
2547 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002548 error(field->line(), "redefinition", field->name().c_str(),
2549 "interface block member name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002550 }
2551 }
2552 }
2553 else
2554 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002555 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03002556
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002557 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05302558 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002559 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04002560
Arun Patole7e7e68d2015-05-22 12:02:25 +05302561 if (!symbolTable.declare(instanceTypeDef))
2562 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002563 error(instanceLine, "redefinition", instanceName->c_str(),
2564 "interface block instance name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002565 }
2566
Jamie Madillb98c3a82015-07-23 14:26:04 -04002567 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002568 symbolName = instanceTypeDef->getName();
2569 }
2570
Jamie Madillb98c3a82015-07-23 14:26:04 -04002571 TIntermAggregate *aggregate = intermediate.makeAggregate(
2572 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line),
2573 nameLine);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002574 aggregate->setOp(EOpDeclaration);
Jamie Madill98493dd2013-07-08 14:39:03 -04002575
2576 exitStructDeclaration();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002577 return aggregate;
2578}
2579
Olli Etuaho383b7912016-08-05 11:22:59 +03002580void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002581{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002582 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002583
2584 // Embedded structure definitions are not supported per GLSL ES spec.
2585 // They aren't allowed in GLSL either, but we need to detect this here
2586 // so we don't rely on the GLSL compiler to catch it.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302587 if (mStructNestingLevel > 1)
2588 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002589 error(line, "", "Embedded struct definitions are not allowed");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002590 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002591}
2592
2593void TParseContext::exitStructDeclaration()
2594{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002595 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002596}
2597
Jamie Madillb98c3a82015-07-23 14:26:04 -04002598namespace
2599{
kbr@chromium.org476541f2011-10-27 21:14:51 +00002600const int kWebGLMaxStructNesting = 4;
2601
2602} // namespace
2603
Olli Etuaho8a176262016-08-16 14:23:01 +03002604void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002605{
Arun Patole7e7e68d2015-05-22 12:02:25 +05302606 if (!IsWebGLBasedSpec(mShaderSpec))
2607 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002608 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002609 }
2610
Arun Patole7e7e68d2015-05-22 12:02:25 +05302611 if (field.type()->getBasicType() != EbtStruct)
2612 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002613 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002614 }
2615
2616 // We're already inside a structure definition at this point, so add
2617 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302618 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2619 {
Jamie Madill41a49272014-03-18 16:10:13 -04002620 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002621 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
2622 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04002623 std::string reason = reasonStream.str();
2624 error(line, reason.c_str(), field.name().c_str(), "");
Olli Etuaho8a176262016-08-16 14:23:01 +03002625 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002626 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002627}
2628
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00002629//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002630// Parse an array index expression
2631//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002632TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
2633 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302634 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002635{
2636 TIntermTyped *indexedExpression = NULL;
2637
2638 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2639 {
2640 if (baseExpression->getAsSymbolNode())
2641 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302642 error(location, " left of '[' is not of type array, matrix, or vector ",
2643 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002644 }
2645 else
2646 {
2647 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2648 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002649 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002650
Jamie Madill21c1e452014-12-29 11:33:41 -05002651 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2652
Olli Etuaho36b05142015-11-12 13:10:42 +02002653 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
2654 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
2655 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
2656 // index is a constant expression.
2657 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
2658 {
2659 if (baseExpression->isInterfaceBlock())
2660 {
2661 error(
2662 location, "", "[",
2663 "array indexes for interface blocks arrays must be constant integral expressions");
Olli Etuaho36b05142015-11-12 13:10:42 +02002664 }
2665 else if (baseExpression->getQualifier() == EvqFragmentOut)
2666 {
2667 error(location, "", "[",
2668 "array indexes for fragment outputs must be constant integral expressions");
Olli Etuaho36b05142015-11-12 13:10:42 +02002669 }
Olli Etuaho3e960462015-11-12 15:58:39 +02002670 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
2671 {
2672 error(location, "", "[", "array index for gl_FragData must be constant zero");
Olli Etuaho3e960462015-11-12 15:58:39 +02002673 }
Olli Etuaho36b05142015-11-12 13:10:42 +02002674 }
2675
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002676 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04002677 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002678 // If the index is not qualified as constant, the behavior in the spec is undefined. This
2679 // applies even if ANGLE has been able to constant fold it (ANGLE may constant fold
2680 // expressions that are not constant expressions). The most compatible way to handle this
2681 // case is to report a warning instead of an error and force the index to be in the
2682 // correct range.
2683 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madill21c1e452014-12-29 11:33:41 -05002684 int index = indexConstantUnion->getIConst(0);
Olli Etuaho90892fb2016-07-14 14:44:51 +03002685 if (!baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04002686 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002687 // Array checks are done later because a different error message might be generated
2688 // based on the index in some cases.
2689 if (baseExpression->isVector())
2690 {
2691 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2692 baseExpression->getType().getNominalSize(),
2693 "vector field selection out of range", "[]");
2694 }
2695 else if (baseExpression->isMatrix())
2696 {
2697 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2698 baseExpression->getType().getCols(),
2699 "matrix field selection out of range", "[]");
2700 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002701 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03002702
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002703 TIntermConstantUnion *baseConstantUnion = baseExpression->getAsConstantUnion();
2704 if (baseConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04002705 {
2706 if (baseExpression->isArray())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002707 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002708 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2709 baseExpression->getArraySize(),
2710 "array index out of range", "[]");
2711 // Constant folding for array indexing.
2712 indexedExpression = foldArraySubscript(index, baseConstantUnion, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002713 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002714 else if (baseExpression->isVector())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002715 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002716 // Constant folding for vector indexing - reusing vector swizzle folding.
Jamie Madill7164cf42013-07-08 13:30:59 -04002717 TVectorFields fields;
2718 fields.num = 1;
Olli Etuaho90892fb2016-07-14 14:44:51 +03002719 fields.offsets[0] = index;
2720 indexedExpression = foldVectorSwizzle(fields, baseConstantUnion, location);
Jamie Madill7164cf42013-07-08 13:30:59 -04002721 }
2722 else if (baseExpression->isMatrix())
2723 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002724 // Constant folding for matrix indexing.
2725 indexedExpression = foldMatrixSubscript(index, baseConstantUnion, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002726 }
2727 }
2728 else
2729 {
Jamie Madillb11e2482015-05-04 14:21:22 -04002730 int safeIndex = -1;
2731
Jamie Madill7164cf42013-07-08 13:30:59 -04002732 if (baseExpression->isArray())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002733 {
Olli Etuaho3e960462015-11-12 15:58:39 +02002734 if (baseExpression->getQualifier() == EvqFragData && index > 0)
2735 {
2736 if (mShaderSpec == SH_WEBGL2_SPEC)
2737 {
2738 // Error has been already generated if index is not const.
2739 if (indexExpression->getQualifier() == EvqConst)
2740 {
2741 error(location, "", "[",
2742 "array index for gl_FragData must be constant zero");
Olli Etuaho3e960462015-11-12 15:58:39 +02002743 }
2744 safeIndex = 0;
2745 }
2746 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
2747 {
2748 outOfRangeError(outOfRangeIndexIsError, location, "", "[",
2749 "array index for gl_FragData must be zero when "
2750 "GL_EXT_draw_buffers is disabled");
2751 safeIndex = 0;
2752 }
2753 }
2754 // Only do generic out-of-range check if similar error hasn't already been reported.
Olli Etuaho90892fb2016-07-14 14:44:51 +03002755 if (safeIndex < 0)
Jamie Madill7164cf42013-07-08 13:30:59 -04002756 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002757 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2758 baseExpression->getArraySize(),
2759 "array index out of range", "[]");
Jamie Madill7164cf42013-07-08 13:30:59 -04002760 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002761 }
2762
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002763 // Data of constant unions can't be changed, because it may be shared with other
2764 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
2765 // sanitized object.
Jamie Madillb11e2482015-05-04 14:21:22 -04002766 if (safeIndex != -1)
2767 {
2768 TConstantUnion *safeConstantUnion = new TConstantUnion();
2769 safeConstantUnion->setIConst(safeIndex);
2770 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
2771 }
2772
Jamie Madillb98c3a82015-07-23 14:26:04 -04002773 indexedExpression =
2774 intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002775 }
2776 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002777 else
2778 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002779 indexedExpression =
2780 intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
Jamie Madill7164cf42013-07-08 13:30:59 -04002781 }
2782
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002783 if (indexedExpression == 0)
2784 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002785 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002786 unionArray->setFConst(0.0f);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002787 indexedExpression =
2788 intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002789 }
2790 else if (baseExpression->isArray())
2791 {
Olli Etuahob3fbd862015-09-30 17:55:02 +03002792 TType indexedType = baseExpression->getType();
2793 indexedType.clearArrayness();
2794 indexedExpression->setType(indexedType);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002795 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002796 else if (baseExpression->isMatrix())
2797 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002798 indexedExpression->setType(TType(baseExpression->getBasicType(),
Olli Etuahob3fbd862015-09-30 17:55:02 +03002799 baseExpression->getPrecision(), EvqTemporary,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002800 static_cast<unsigned char>(baseExpression->getRows())));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002801 }
2802 else if (baseExpression->isVector())
2803 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002804 indexedExpression->setType(
Olli Etuahob3fbd862015-09-30 17:55:02 +03002805 TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002806 }
2807 else
2808 {
2809 indexedExpression->setType(baseExpression->getType());
2810 }
2811
Olli Etuahob3fbd862015-09-30 17:55:02 +03002812 if (baseExpression->getType().getQualifier() == EvqConst &&
2813 indexExpression->getType().getQualifier() == EvqConst)
2814 {
2815 indexedExpression->getTypePointer()->setQualifier(EvqConst);
2816 }
2817 else
2818 {
2819 indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
2820 }
2821
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002822 return indexedExpression;
2823}
2824
Olli Etuaho90892fb2016-07-14 14:44:51 +03002825int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
2826 const TSourceLoc &location,
2827 int index,
2828 int arraySize,
2829 const char *reason,
2830 const char *token)
2831{
2832 if (index >= arraySize || index < 0)
2833 {
2834 std::stringstream extraInfoStream;
2835 extraInfoStream << "'" << index << "'";
2836 std::string extraInfo = extraInfoStream.str();
2837 outOfRangeError(outOfRangeIndexIsError, location, reason, token, extraInfo.c_str());
2838 if (index < 0)
2839 {
2840 return 0;
2841 }
2842 else
2843 {
2844 return arraySize - 1;
2845 }
2846 }
2847 return index;
2848}
2849
Jamie Madillb98c3a82015-07-23 14:26:04 -04002850TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
2851 const TSourceLoc &dotLocation,
2852 const TString &fieldString,
2853 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002854{
2855 TIntermTyped *indexedExpression = NULL;
2856
2857 if (baseExpression->isArray())
2858 {
2859 error(fieldLocation, "cannot apply dot operator to an array", ".");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002860 }
2861
2862 if (baseExpression->isVector())
2863 {
2864 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002865 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
2866 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002867 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002868 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002869 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002870 }
2871
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002872 if (baseExpression->getAsConstantUnion())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002873 {
2874 // constant folding for vector fields
Olli Etuaho90892fb2016-07-14 14:44:51 +03002875 indexedExpression =
2876 foldVectorSwizzle(fields, baseExpression->getAsConstantUnion(), fieldLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002877 }
2878 else
2879 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302880 TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002881 indexedExpression =
2882 intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002883 }
2884 if (indexedExpression == nullptr)
2885 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002886 indexedExpression = baseExpression;
2887 }
2888 else
2889 {
2890 // Note that the qualifier set here will be corrected later.
Jamie Madillb98c3a82015-07-23 14:26:04 -04002891 indexedExpression->setType(TType(baseExpression->getBasicType(),
2892 baseExpression->getPrecision(), EvqTemporary,
Jamie Madillc2128ff2016-07-04 10:26:17 -04002893 static_cast<unsigned char>(fields.num)));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002894 }
2895 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002896 else if (baseExpression->getBasicType() == EbtStruct)
2897 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002898 bool fieldFound = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302899 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04002900 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002901 {
2902 error(dotLocation, "structure has no fields", "Internal Error");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002903 indexedExpression = baseExpression;
2904 }
2905 else
2906 {
2907 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04002908 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002909 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002910 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002911 {
2912 fieldFound = true;
2913 break;
2914 }
2915 }
2916 if (fieldFound)
2917 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002918 if (baseExpression->getAsConstantUnion())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002919 {
2920 indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
2921 if (indexedExpression == 0)
2922 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002923 indexedExpression = baseExpression;
2924 }
2925 else
2926 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002927 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002928 }
2929 }
2930 else
2931 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002932 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002933 unionArray->setIConst(i);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002934 TIntermTyped *index = intermediate.addConstantUnion(
2935 unionArray, *fields[i]->type(), fieldLocation);
2936 indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression,
2937 index, dotLocation);
Jamie Madill98493dd2013-07-08 14:39:03 -04002938 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002939 }
2940 }
2941 else
2942 {
2943 error(dotLocation, " no such field in structure", fieldString.c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002944 indexedExpression = baseExpression;
2945 }
2946 }
2947 }
Jamie Madill98493dd2013-07-08 14:39:03 -04002948 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002949 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002950 bool fieldFound = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302951 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04002952 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002953 {
2954 error(dotLocation, "interface block has no fields", "Internal Error");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002955 indexedExpression = baseExpression;
2956 }
2957 else
2958 {
2959 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04002960 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002961 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002962 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002963 {
2964 fieldFound = true;
2965 break;
2966 }
2967 }
2968 if (fieldFound)
2969 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002970 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002971 unionArray->setIConst(i);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002972 TIntermTyped *index =
2973 intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
2974 indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock,
2975 baseExpression, index, dotLocation);
Jamie Madill98493dd2013-07-08 14:39:03 -04002976 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002977 }
2978 else
2979 {
2980 error(dotLocation, " no such field in interface block", fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002981 indexedExpression = baseExpression;
2982 }
2983 }
2984 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002985 else
2986 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002987 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002988 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03002989 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05302990 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002991 }
2992 else
2993 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302994 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03002995 " field selection requires structure, vector, or interface block on left hand "
2996 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05302997 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002998 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002999 indexedExpression = baseExpression;
3000 }
3001
Olli Etuahob1edc4f2015-11-02 17:20:03 +02003002 if (baseExpression->getQualifier() == EvqConst)
3003 {
3004 indexedExpression->getTypePointer()->setQualifier(EvqConst);
3005 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003006 else
3007 {
3008 indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
3009 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02003010
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003011 return indexedExpression;
3012}
3013
Jamie Madillb98c3a82015-07-23 14:26:04 -04003014TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3015 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003016{
Martin Radev802abe02016-08-04 17:48:32 +03003017 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003018
3019 if (qualifierType == "shared")
3020 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003021 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003022 }
3023 else if (qualifierType == "packed")
3024 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003025 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003026 }
3027 else if (qualifierType == "std140")
3028 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003029 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003030 }
3031 else if (qualifierType == "row_major")
3032 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003033 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003034 }
3035 else if (qualifierType == "column_major")
3036 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003037 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003038 }
3039 else if (qualifierType == "location")
3040 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003041 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(),
3042 "location requires an argument");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003043 }
3044 else
3045 {
3046 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003047 }
3048
Jamie Madilla5efff92013-06-06 11:56:47 -04003049 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003050}
3051
Martin Radev802abe02016-08-04 17:48:32 +03003052void TParseContext::parseLocalSize(const TString &qualifierType,
3053 const TSourceLoc &qualifierTypeLine,
3054 int intValue,
3055 const TSourceLoc &intValueLine,
3056 const std::string &intValueString,
3057 size_t index,
3058 TLocalSize *localSize)
3059{
Olli Etuaho856c4972016-08-08 11:38:39 +03003060 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03003061 if (intValue < 1)
3062 {
3063 std::string errorMessage = std::string(getLocalSizeString(index)) + " must be positive";
3064 error(intValueLine, "out of range:", intValueString.c_str(), errorMessage.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003065 }
3066 (*localSize)[index] = intValue;
3067}
3068
Jamie Madillb98c3a82015-07-23 14:26:04 -04003069TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3070 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003071 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303072 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003073{
Martin Radev802abe02016-08-04 17:48:32 +03003074 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003075
Martin Radev802abe02016-08-04 17:48:32 +03003076 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003077
Martin Radev802abe02016-08-04 17:48:32 +03003078 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003079 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003080 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003081 if (intValue < 0)
3082 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003083 error(intValueLine, "out of range:", intValueString.c_str(),
3084 "location must be non-negative");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003085 }
3086 else
3087 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003088 qualifier.location = intValue;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003089 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003090 }
Martin Radev802abe02016-08-04 17:48:32 +03003091 else if (qualifierType == "local_size_x")
3092 {
3093 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3094 &qualifier.localSize);
3095 }
3096 else if (qualifierType == "local_size_y")
3097 {
3098 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3099 &qualifier.localSize);
3100 }
3101 else if (qualifierType == "local_size_z")
3102 {
3103 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3104 &qualifier.localSize);
3105 }
3106 else
3107 {
3108 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003109 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003110
Jamie Madilla5efff92013-06-06 11:56:47 -04003111 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003112}
3113
Jamie Madillb98c3a82015-07-23 14:26:04 -04003114TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003115 TLayoutQualifier rightQualifier,
3116 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003117{
Jamie Madilla5efff92013-06-06 11:56:47 -04003118 TLayoutQualifier joinedQualifier = leftQualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003119
Jamie Madilla5efff92013-06-06 11:56:47 -04003120 if (rightQualifier.location != -1)
3121 {
3122 joinedQualifier.location = rightQualifier.location;
3123 }
3124 if (rightQualifier.matrixPacking != EmpUnspecified)
3125 {
3126 joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
3127 }
3128 if (rightQualifier.blockStorage != EbsUnspecified)
3129 {
3130 joinedQualifier.blockStorage = rightQualifier.blockStorage;
3131 }
3132
Martin Radev802abe02016-08-04 17:48:32 +03003133 for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i)
3134 {
3135 if (rightQualifier.localSize[i] != -1)
3136 {
3137 if (joinedQualifier.localSize[i] != -1 &&
3138 joinedQualifier.localSize[i] != rightQualifier.localSize[i])
3139 {
3140 error(rightQualifierLocation,
3141 "Cannot have multiple different work group size specifiers",
3142 getLocalSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03003143 }
3144 joinedQualifier.localSize[i] = rightQualifier.localSize[i];
3145 }
3146 }
3147
Jamie Madilla5efff92013-06-06 11:56:47 -04003148 return joinedQualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003149}
3150
Arun Patole7e7e68d2015-05-22 12:02:25 +05303151TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc,
3152 TQualifier interpolationQualifier,
3153 const TSourceLoc &storageLoc,
3154 TQualifier storageQualifier)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003155{
3156 TQualifier mergedQualifier = EvqSmoothIn;
3157
Arun Patole7e7e68d2015-05-22 12:02:25 +05303158 if (storageQualifier == EvqFragmentIn)
3159 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003160 if (interpolationQualifier == EvqSmooth)
3161 mergedQualifier = EvqSmoothIn;
3162 else if (interpolationQualifier == EvqFlat)
3163 mergedQualifier = EvqFlatIn;
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 if (storageQualifier == EvqCentroidIn)
3168 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003169 if (interpolationQualifier == EvqSmooth)
3170 mergedQualifier = EvqCentroidIn;
3171 else if (interpolationQualifier == EvqFlat)
3172 mergedQualifier = EvqFlatIn;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003173 else
3174 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003175 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303176 else if (storageQualifier == EvqVertexOut)
3177 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003178 if (interpolationQualifier == EvqSmooth)
3179 mergedQualifier = EvqSmoothOut;
3180 else if (interpolationQualifier == EvqFlat)
3181 mergedQualifier = EvqFlatOut;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003182 else
3183 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003184 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303185 else if (storageQualifier == EvqCentroidOut)
3186 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003187 if (interpolationQualifier == EvqSmooth)
3188 mergedQualifier = EvqCentroidOut;
3189 else if (interpolationQualifier == EvqFlat)
3190 mergedQualifier = EvqFlatOut;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003191 else
3192 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003193 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303194 else
3195 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003196 error(interpolationLoc,
3197 "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303198 getInterpolationString(interpolationQualifier));
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003199
3200 mergedQualifier = storageQualifier;
3201 }
3202
3203 TPublicType type;
3204 type.setBasic(EbtVoid, mergedQualifier, storageLoc);
3205 return type;
3206}
3207
Jamie Madillb98c3a82015-07-23 14:26:04 -04003208TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3209 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003210{
Olli Etuaho856c4972016-08-08 11:38:39 +03003211 checkIsNonVoid(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003212
Olli Etuaho856c4972016-08-08 11:38:39 +03003213 checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003214
Arun Patole7e7e68d2015-05-22 12:02:25 +05303215 for (unsigned int i = 0; i < fieldList->size(); ++i)
3216 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003217 //
3218 // Careful not to replace already known aspects of type, like array-ness
3219 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303220 TType *type = (*fieldList)[i]->type();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003221 type->setBasicType(typeSpecifier.type);
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003222 type->setPrimarySize(typeSpecifier.primarySize);
3223 type->setSecondarySize(typeSpecifier.secondarySize);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003224 type->setPrecision(typeSpecifier.precision);
3225 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003226 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003227
3228 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303229 if (type->isArray())
3230 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003231 checkIsValidTypeForArray(typeSpecifier.line, typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003232 }
3233 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003234 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Arun Patole7e7e68d2015-05-22 12:02:25 +05303235 if (typeSpecifier.userDef)
3236 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003237 type->setStruct(typeSpecifier.userDef->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003238 }
3239
Olli Etuaho8a176262016-08-16 14:23:01 +03003240 checkIsBelowStructNestingLimit(typeSpecifier.line, *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003241 }
3242
Jamie Madill98493dd2013-07-08 14:39:03 -04003243 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003244}
3245
Jamie Madillb98c3a82015-07-23 14:26:04 -04003246TPublicType TParseContext::addStructure(const TSourceLoc &structLine,
3247 const TSourceLoc &nameLine,
3248 const TString *structName,
3249 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003250{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303251 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003252 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003253
Jamie Madill9b820842015-02-12 10:40:10 -05003254 // Store a bool in the struct if we're at global scope, to allow us to
3255 // skip the local struct scoping workaround in HLSL.
Jamie Madillb960cc42015-02-12 15:33:20 +00003256 structure->setUniqueId(TSymbolTable::nextUniqueId());
Jamie Madill9b820842015-02-12 10:40:10 -05003257 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003258
Jamie Madill98493dd2013-07-08 14:39:03 -04003259 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003260 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003261 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303262 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3263 if (!symbolTable.declare(userTypeDef))
3264 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003265 error(nameLine, "redefinition", structName->c_str(), "struct");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003266 }
3267 }
3268
3269 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003270 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003271 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003272 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003273 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003274 switch (qualifier)
3275 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003276 case EvqGlobal:
3277 case EvqTemporary:
3278 break;
3279 default:
3280 error(field.line(), "invalid qualifier on struct member",
3281 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003282 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003283 }
3284 }
3285
3286 TPublicType publicType;
3287 publicType.setBasic(EbtStruct, EvqTemporary, structLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04003288 publicType.userDef = structureType;
Olli Etuahobd163f62015-11-13 12:15:38 +02003289 publicType.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003290 exitStructDeclaration();
3291
3292 return publicType;
3293}
3294
Jamie Madillb98c3a82015-07-23 14:26:04 -04003295TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
3296 TIntermAggregate *statementList,
3297 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003298{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003299 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003300 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003301 init->isVector())
3302 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003303 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3304 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003305 return nullptr;
3306 }
3307
Olli Etuahoac5274d2015-02-20 10:19:08 +02003308 if (statementList)
3309 {
3310 if (!ValidateSwitch::validate(switchType, this, statementList, loc))
3311 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003312 return nullptr;
3313 }
3314 }
3315
Olli Etuahoa3a36662015-02-17 13:46:51 +02003316 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3317 if (node == nullptr)
3318 {
3319 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003320 return nullptr;
3321 }
3322 return node;
3323}
3324
3325TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3326{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003327 if (mSwitchNestingLevel == 0)
3328 {
3329 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003330 return nullptr;
3331 }
3332 if (condition == nullptr)
3333 {
3334 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003335 return nullptr;
3336 }
3337 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003338 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003339 {
3340 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003341 }
3342 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003343 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3344 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3345 // fold in case labels.
3346 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003347 {
3348 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003349 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003350 TIntermCase *node = intermediate.addCase(condition, loc);
3351 if (node == nullptr)
3352 {
3353 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003354 return nullptr;
3355 }
3356 return node;
3357}
3358
3359TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3360{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003361 if (mSwitchNestingLevel == 0)
3362 {
3363 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003364 return nullptr;
3365 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003366 TIntermCase *node = intermediate.addCase(nullptr, loc);
3367 if (node == nullptr)
3368 {
3369 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003370 return nullptr;
3371 }
3372 return node;
3373}
3374
Jamie Madillb98c3a82015-07-23 14:26:04 -04003375TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3376 TIntermTyped *child,
3377 const TSourceLoc &loc,
3378 const TType *funcReturnType)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003379{
3380 if (child == nullptr)
3381 {
3382 return nullptr;
3383 }
3384
3385 switch (op)
3386 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003387 case EOpLogicalNot:
3388 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3389 child->isVector())
3390 {
3391 return nullptr;
3392 }
3393 break;
3394 case EOpBitwiseNot:
3395 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3396 child->isMatrix() || child->isArray())
3397 {
3398 return nullptr;
3399 }
3400 break;
3401 case EOpPostIncrement:
3402 case EOpPreIncrement:
3403 case EOpPostDecrement:
3404 case EOpPreDecrement:
3405 case EOpNegative:
3406 case EOpPositive:
3407 if (child->getBasicType() == EbtStruct || child->getBasicType() == EbtBool ||
3408 child->isArray())
3409 {
3410 return nullptr;
3411 }
3412 // Operators for built-ins are already type checked against their prototype.
3413 default:
3414 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003415 }
3416
Olli Etuahof6c694b2015-03-26 14:50:53 +02003417 return intermediate.addUnaryMath(op, child, loc, funcReturnType);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003418}
3419
Olli Etuaho09b22472015-02-11 11:47:26 +02003420TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3421{
Olli Etuahof6c694b2015-03-26 14:50:53 +02003422 TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003423 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003424 {
3425 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003426 return child;
3427 }
3428 return node;
3429}
3430
Jamie Madillb98c3a82015-07-23 14:26:04 -04003431TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3432 TIntermTyped *child,
3433 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003434{
Olli Etuaho856c4972016-08-08 11:38:39 +03003435 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003436 return addUnaryMath(op, child, loc);
3437}
3438
Jamie Madillb98c3a82015-07-23 14:26:04 -04003439bool TParseContext::binaryOpCommonCheck(TOperator op,
3440 TIntermTyped *left,
3441 TIntermTyped *right,
3442 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003443{
3444 if (left->isArray() || right->isArray())
3445 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003446 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003447 {
3448 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3449 return false;
3450 }
3451
3452 if (left->isArray() != right->isArray())
3453 {
3454 error(loc, "array / non-array mismatch", GetOperatorString(op));
3455 return false;
3456 }
3457
3458 switch (op)
3459 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003460 case EOpEqual:
3461 case EOpNotEqual:
3462 case EOpAssign:
3463 case EOpInitialize:
3464 break;
3465 default:
3466 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3467 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02003468 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03003469 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02003470 if (left->getArraySize() != right->getArraySize())
3471 {
3472 error(loc, "array size mismatch", GetOperatorString(op));
3473 return false;
3474 }
Olli Etuahod6b14282015-03-17 14:31:35 +02003475 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003476
3477 // Check ops which require integer / ivec parameters
3478 bool isBitShift = false;
3479 switch (op)
3480 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003481 case EOpBitShiftLeft:
3482 case EOpBitShiftRight:
3483 case EOpBitShiftLeftAssign:
3484 case EOpBitShiftRightAssign:
3485 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3486 // check that the basic type is an integer type.
3487 isBitShift = true;
3488 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3489 {
3490 return false;
3491 }
3492 break;
3493 case EOpBitwiseAnd:
3494 case EOpBitwiseXor:
3495 case EOpBitwiseOr:
3496 case EOpBitwiseAndAssign:
3497 case EOpBitwiseXorAssign:
3498 case EOpBitwiseOrAssign:
3499 // It is enough to check the type of only one operand, since later it
3500 // is checked that the operand types match.
3501 if (!IsInteger(left->getBasicType()))
3502 {
3503 return false;
3504 }
3505 break;
3506 default:
3507 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003508 }
3509
3510 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3511 // So the basic type should usually match.
3512 if (!isBitShift && left->getBasicType() != right->getBasicType())
3513 {
3514 return false;
3515 }
3516
Olli Etuaho9dd217b2015-03-20 14:24:31 +02003517 // Check that type sizes match exactly on ops that require that.
Olli Etuahoff699002015-03-23 14:38:42 +02003518 // Also check restrictions for structs that contain arrays or samplers.
Jamie Madillb98c3a82015-07-23 14:26:04 -04003519 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003520 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003521 case EOpAssign:
3522 case EOpInitialize:
3523 case EOpEqual:
3524 case EOpNotEqual:
3525 // ESSL 1.00 sections 5.7, 5.8, 5.9
3526 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
3527 {
3528 error(loc, "undefined operation for structs containing arrays",
3529 GetOperatorString(op));
3530 return false;
3531 }
3532 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3533 // we interpret the spec so that this extends to structs containing samplers,
3534 // similarly to ESSL 1.00 spec.
3535 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
3536 left->getType().isStructureContainingSamplers())
3537 {
3538 error(loc, "undefined operation for structs containing samplers",
3539 GetOperatorString(op));
3540 return false;
3541 }
3542 case EOpLessThan:
3543 case EOpGreaterThan:
3544 case EOpLessThanEqual:
3545 case EOpGreaterThanEqual:
3546 if ((left->getNominalSize() != right->getNominalSize()) ||
3547 (left->getSecondarySize() != right->getSecondarySize()))
3548 {
3549 return false;
3550 }
3551 default:
3552 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003553 }
3554
Olli Etuahod6b14282015-03-17 14:31:35 +02003555 return true;
3556}
3557
Jamie Madillb98c3a82015-07-23 14:26:04 -04003558TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
3559 TIntermTyped *left,
3560 TIntermTyped *right,
3561 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02003562{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003563 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003564 return nullptr;
3565
Olli Etuahofc1806e2015-03-17 13:03:11 +02003566 switch (op)
3567 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003568 case EOpEqual:
3569 case EOpNotEqual:
3570 break;
3571 case EOpLessThan:
3572 case EOpGreaterThan:
3573 case EOpLessThanEqual:
3574 case EOpGreaterThanEqual:
3575 ASSERT(!left->isArray() && !right->isArray());
3576 if (left->isMatrix() || left->isVector() || left->getBasicType() == EbtStruct)
3577 {
3578 return nullptr;
3579 }
3580 break;
3581 case EOpLogicalOr:
3582 case EOpLogicalXor:
3583 case EOpLogicalAnd:
3584 ASSERT(!left->isArray() && !right->isArray());
3585 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isVector())
3586 {
3587 return nullptr;
3588 }
3589 break;
3590 case EOpAdd:
3591 case EOpSub:
3592 case EOpDiv:
3593 case EOpMul:
3594 ASSERT(!left->isArray() && !right->isArray());
3595 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
3596 {
3597 return nullptr;
3598 }
3599 break;
3600 case EOpIMod:
3601 ASSERT(!left->isArray() && !right->isArray());
3602 // Note that this is only for the % operator, not for mod()
3603 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool ||
3604 left->getBasicType() == EbtFloat)
3605 {
3606 return nullptr;
3607 }
3608 break;
3609 // Note that for bitwise ops, type checking is done in promote() to
3610 // share code between ops and compound assignment
3611 default:
3612 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02003613 }
3614
Olli Etuahofc1806e2015-03-17 13:03:11 +02003615 return intermediate.addBinaryMath(op, left, right, loc);
3616}
3617
Jamie Madillb98c3a82015-07-23 14:26:04 -04003618TIntermTyped *TParseContext::addBinaryMath(TOperator op,
3619 TIntermTyped *left,
3620 TIntermTyped *right,
3621 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003622{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003623 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003624 if (node == 0)
3625 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003626 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3627 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003628 return left;
3629 }
3630 return node;
3631}
3632
Jamie Madillb98c3a82015-07-23 14:26:04 -04003633TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
3634 TIntermTyped *left,
3635 TIntermTyped *right,
3636 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003637{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003638 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003639 if (node == 0)
3640 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003641 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3642 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003643 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02003644 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003645 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
3646 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003647 }
3648 return node;
3649}
3650
Jamie Madillb98c3a82015-07-23 14:26:04 -04003651TIntermTyped *TParseContext::createAssign(TOperator op,
3652 TIntermTyped *left,
3653 TIntermTyped *right,
3654 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003655{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003656 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003657 {
3658 return intermediate.addAssign(op, left, right, loc);
3659 }
3660 return nullptr;
3661}
3662
Jamie Madillb98c3a82015-07-23 14:26:04 -04003663TIntermTyped *TParseContext::addAssign(TOperator op,
3664 TIntermTyped *left,
3665 TIntermTyped *right,
3666 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003667{
3668 TIntermTyped *node = createAssign(op, left, right, loc);
3669 if (node == nullptr)
3670 {
3671 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02003672 return left;
3673 }
3674 return node;
3675}
3676
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02003677TIntermTyped *TParseContext::addComma(TIntermTyped *left,
3678 TIntermTyped *right,
3679 const TSourceLoc &loc)
3680{
Corentin Wallez0d959252016-07-12 17:26:32 -04003681 // WebGL2 section 5.26, the following results in an error:
3682 // "Sequence operator applied to void, arrays, or structs containing arrays"
3683 if (mShaderSpec == SH_WEBGL2_SPEC && (left->isArray() || left->getBasicType() == EbtVoid ||
3684 left->getType().isStructureContainingArrays() ||
3685 right->isArray() || right->getBasicType() == EbtVoid ||
3686 right->getType().isStructureContainingArrays()))
3687 {
3688 error(loc,
3689 "sequence operator is not allowed for void, arrays, or structs containing arrays",
3690 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04003691 }
3692
Olli Etuaho15200042015-11-04 16:56:31 +02003693 return intermediate.addComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02003694}
3695
Olli Etuaho49300862015-02-20 14:54:49 +02003696TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
3697{
3698 switch (op)
3699 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003700 case EOpContinue:
3701 if (mLoopNestingLevel <= 0)
3702 {
3703 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003704 }
3705 break;
3706 case EOpBreak:
3707 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
3708 {
3709 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003710 }
3711 break;
3712 case EOpReturn:
3713 if (mCurrentFunctionType->getBasicType() != EbtVoid)
3714 {
3715 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003716 }
3717 break;
3718 default:
3719 // No checks for discard
3720 break;
Olli Etuaho49300862015-02-20 14:54:49 +02003721 }
3722 return intermediate.addBranch(op, loc);
3723}
3724
Jamie Madillb98c3a82015-07-23 14:26:04 -04003725TIntermBranch *TParseContext::addBranch(TOperator op,
3726 TIntermTyped *returnValue,
3727 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02003728{
3729 ASSERT(op == EOpReturn);
3730 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003731 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02003732 {
3733 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02003734 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003735 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02003736 {
3737 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02003738 }
3739 return intermediate.addBranch(op, returnValue, loc);
3740}
3741
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003742void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
3743{
3744 ASSERT(!functionCall->isUserDefined());
3745 const TString &name = functionCall->getName();
3746 TIntermNode *offset = nullptr;
3747 TIntermSequence *arguments = functionCall->getSequence();
3748 if (name.compare(0, 16, "texelFetchOffset") == 0 ||
3749 name.compare(0, 16, "textureLodOffset") == 0 ||
3750 name.compare(0, 20, "textureProjLodOffset") == 0 ||
3751 name.compare(0, 17, "textureGradOffset") == 0 ||
3752 name.compare(0, 21, "textureProjGradOffset") == 0)
3753 {
3754 offset = arguments->back();
3755 }
3756 else if (name.compare(0, 13, "textureOffset") == 0 ||
3757 name.compare(0, 17, "textureProjOffset") == 0)
3758 {
3759 // A bias parameter might follow the offset parameter.
3760 ASSERT(arguments->size() >= 3);
3761 offset = (*arguments)[2];
3762 }
3763 if (offset != nullptr)
3764 {
3765 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
3766 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
3767 {
3768 TString unmangledName = TFunction::unmangleName(name);
3769 error(functionCall->getLine(), "Texture offset must be a constant expression",
3770 unmangledName.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003771 }
3772 else
3773 {
3774 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
3775 size_t size = offsetConstantUnion->getType().getObjectSize();
3776 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
3777 for (size_t i = 0u; i < size; ++i)
3778 {
3779 int offsetValue = values[i].getIConst();
3780 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
3781 {
3782 std::stringstream tokenStream;
3783 tokenStream << offsetValue;
3784 std::string token = tokenStream.str();
3785 error(offset->getLine(), "Texture offset value out of valid range",
3786 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003787 }
3788 }
3789 }
3790 }
3791}
3792
Jamie Madillb98c3a82015-07-23 14:26:04 -04003793TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
3794 TIntermNode *paramNode,
3795 TIntermNode *thisNode,
3796 const TSourceLoc &loc,
3797 bool *fatalError)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003798{
Jamie Madillb98c3a82015-07-23 14:26:04 -04003799 *fatalError = false;
3800 TOperator op = fnCall->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003801 TIntermTyped *callNode = nullptr;
3802
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003803 if (thisNode != nullptr)
3804 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003805 TConstantUnion *unionArray = new TConstantUnion[1];
Jamie Madillb98c3a82015-07-23 14:26:04 -04003806 int arraySize = 0;
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003807 TIntermTyped *typedThis = thisNode->getAsTyped();
3808 if (fnCall->getName() != "length")
3809 {
3810 error(loc, "invalid method", fnCall->getName().c_str());
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003811 }
3812 else if (paramNode != nullptr)
3813 {
3814 error(loc, "method takes no parameters", "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003815 }
3816 else if (typedThis == nullptr || !typedThis->isArray())
3817 {
3818 error(loc, "length can only be called on arrays", "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003819 }
3820 else
3821 {
Olli Etuaho96e67382015-04-23 14:27:02 +03003822 arraySize = typedThis->getArraySize();
Olli Etuaho39282e12015-04-23 15:41:48 +03003823 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003824 {
Olli Etuaho39282e12015-04-23 15:41:48 +03003825 // This code path can be hit with expressions like these:
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003826 // (a = b).length()
Olli Etuaho39282e12015-04-23 15:41:48 +03003827 // (func()).length()
3828 // (int[3](0, 1, 2)).length()
Jamie Madillb98c3a82015-07-23 14:26:04 -04003829 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
3830 // expression.
3831 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
3832 // spec section 5.9 which allows "An array, vector or matrix expression with the
3833 // length method applied".
3834 error(loc, "length can only be called on array names, not on array expressions",
3835 "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003836 }
3837 }
Olli Etuaho96e67382015-04-23 14:27:02 +03003838 unionArray->setIConst(arraySize);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003839 callNode =
3840 intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003841 }
3842 else if (op != EOpNull)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003843 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003844 // Then this should be a constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +03003845 callNode = addConstructor(paramNode, op, fnCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003846 }
3847 else
3848 {
3849 //
3850 // Not a constructor. Find it in the symbol table.
3851 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303852 const TFunction *fnCandidate;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003853 bool builtIn;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003854 fnCandidate = findFunction(loc, fnCall, mShaderVersion, &builtIn);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003855 if (fnCandidate)
3856 {
3857 //
3858 // A declared function.
3859 //
Olli Etuaho383b7912016-08-05 11:22:59 +03003860 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003861 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003862 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003863 }
3864 op = fnCandidate->getBuiltInOp();
3865 if (builtIn && op != EOpNull)
3866 {
3867 //
3868 // A function call mapped to a built-in operation.
3869 //
3870 if (fnCandidate->getParamCount() == 1)
3871 {
3872 //
3873 // Treat it like a built-in unary operator.
3874 //
Olli Etuaho15c2ac32015-11-09 15:51:43 +02003875 TIntermAggregate *paramAgg = paramNode->getAsAggregate();
3876 paramNode = paramAgg->getSequence()->front();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003877 callNode = createUnaryMath(op, paramNode->getAsTyped(), loc,
3878 &fnCandidate->getReturnType());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003879 if (callNode == nullptr)
3880 {
3881 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003882 extraInfoStream
3883 << "built in unary operator function. Type: "
3884 << static_cast<TIntermTyped *>(paramNode)->getCompleteString();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003885 std::string extraInfo = extraInfoStream.str();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003886 error(paramNode->getLine(), " wrong operand type", "Internal Error",
3887 extraInfo.c_str());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003888 *fatalError = true;
3889 return nullptr;
3890 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003891 }
3892 else
3893 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003894 TIntermAggregate *aggregate =
3895 intermediate.setAggregateOperator(paramNode, op, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003896 aggregate->setType(fnCandidate->getReturnType());
3897 aggregate->setPrecisionFromChildren();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02003898 if (aggregate->areChildrenConstQualified())
3899 {
3900 aggregate->getTypePointer()->setQualifier(EvqConst);
3901 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003902
3903 // Some built-in functions have out parameters too.
3904 functionCallLValueErrorCheck(fnCandidate, aggregate);
Arun Patole274f0702015-05-05 13:33:30 +05303905
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003906 // See if we can constant fold a built-in. Note that this may be possible even
3907 // if it is not const-qualified.
Olli Etuahob43846e2015-06-02 18:18:57 +03003908 TIntermTyped *foldedNode = intermediate.foldAggregateBuiltIn(aggregate);
Arun Patole274f0702015-05-05 13:33:30 +05303909 if (foldedNode)
3910 {
Arun Patole274f0702015-05-05 13:33:30 +05303911 callNode = foldedNode;
3912 }
Olli Etuahob43846e2015-06-02 18:18:57 +03003913 else
3914 {
3915 callNode = aggregate;
3916 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003917 }
3918 }
3919 else
3920 {
3921 // This is a real function call
Jamie Madillb98c3a82015-07-23 14:26:04 -04003922 TIntermAggregate *aggregate =
3923 intermediate.setAggregateOperator(paramNode, EOpFunctionCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003924 aggregate->setType(fnCandidate->getReturnType());
3925
Jamie Madillb98c3a82015-07-23 14:26:04 -04003926 // this is how we know whether the given function is a builtIn function or a user
3927 // defined function
3928 // if builtIn == false, it's a userDefined -> could be an overloaded
3929 // builtIn function also
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003930 // if builtIn == true, it's definitely a builtIn function with EOpNull
3931 if (!builtIn)
3932 aggregate->setUserDefined();
3933 aggregate->setName(fnCandidate->getMangledName());
Corentin Wallez71d147f2015-02-11 11:15:24 -08003934 aggregate->setFunctionId(fnCandidate->getUniqueId());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003935
3936 // This needs to happen after the name is set
3937 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003938 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003939 aggregate->setBuiltInFunctionPrecision();
3940
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003941 checkTextureOffsetConst(aggregate);
3942 }
3943
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003944 callNode = aggregate;
3945
3946 functionCallLValueErrorCheck(fnCandidate, aggregate);
3947 }
3948 }
3949 else
3950 {
3951 // error message was put out by findFunction()
3952 // Put on a dummy node for error recovery
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003953 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003954 unionArray->setFConst(0.0f);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003955 callNode = intermediate.addConstantUnion(unionArray,
3956 TType(EbtFloat, EbpUndefined, EvqConst), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003957 }
3958 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003959 return callNode;
3960}
3961
Jamie Madillb98c3a82015-07-23 14:26:04 -04003962TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
3963 TIntermTyped *trueBlock,
3964 TIntermTyped *falseBlock,
Olli Etuaho52901742015-04-15 13:42:45 +03003965 const TSourceLoc &loc)
3966{
Olli Etuaho856c4972016-08-08 11:38:39 +03003967 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03003968
3969 if (trueBlock->getType() != falseBlock->getType())
3970 {
3971 binaryOpError(loc, ":", trueBlock->getCompleteString(), falseBlock->getCompleteString());
Olli Etuaho52901742015-04-15 13:42:45 +03003972 return falseBlock;
3973 }
Olli Etuahoa2d53032015-04-15 14:14:44 +03003974 // ESSL1 sections 5.2 and 5.7:
3975 // ESSL3 section 5.7:
3976 // Ternary operator is not among the operators allowed for structures/arrays.
3977 if (trueBlock->isArray() || trueBlock->getBasicType() == EbtStruct)
3978 {
3979 error(loc, "ternary operator is not allowed for structures or arrays", ":");
Olli Etuahoa2d53032015-04-15 14:14:44 +03003980 return falseBlock;
3981 }
Corentin Wallez0d959252016-07-12 17:26:32 -04003982 // WebGL2 section 5.26, the following results in an error:
3983 // "Ternary operator applied to void, arrays, or structs containing arrays"
3984 if (mShaderSpec == SH_WEBGL2_SPEC && trueBlock->getBasicType() == EbtVoid)
3985 {
3986 error(loc, "ternary operator is not allowed for void", ":");
Corentin Wallez0d959252016-07-12 17:26:32 -04003987 return falseBlock;
3988 }
3989
Olli Etuaho52901742015-04-15 13:42:45 +03003990 return intermediate.addSelection(cond, trueBlock, falseBlock, loc);
3991}
Olli Etuaho49300862015-02-20 14:54:49 +02003992
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003993//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003994// Parse an array of strings using yyparse.
3995//
3996// Returns 0 for success.
3997//
Jamie Madillb98c3a82015-07-23 14:26:04 -04003998int PaParseStrings(size_t count,
3999 const char *const string[],
4000 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05304001 TParseContext *context)
4002{
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004003 if ((count == 0) || (string == NULL))
4004 return 1;
4005
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004006 if (glslang_initialize(context))
4007 return 1;
4008
alokp@chromium.org408c45e2012-04-05 15:54:43 +00004009 int error = glslang_scan(count, string, length, context);
4010 if (!error)
4011 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004012
alokp@chromium.org73bc2982012-06-19 18:48:05 +00004013 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00004014
alokp@chromium.org6b495712012-06-29 00:06:58 +00004015 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004016}