blob: eac0702df82a2594600113fd07cef33c6f4841a7 [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{
Olli Etuaho1cc598f2016-08-18 13:50:30 +0300144 mDiagnostics.error(loc, reason, token, extraInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000145}
146
Arun Patole7e7e68d2015-05-22 12:02:25 +0530147void TParseContext::warning(const TSourceLoc &loc,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400148 const char *reason,
149 const char *token,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530150 const char *extraInfo)
151{
Olli Etuaho1cc598f2016-08-18 13:50:30 +0300152 mDiagnostics.warning(loc, reason, token, extraInfo);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +0000153}
154
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200155void TParseContext::outOfRangeError(bool isError,
156 const TSourceLoc &loc,
157 const char *reason,
158 const char *token,
159 const char *extraInfo)
160{
161 if (isError)
162 {
163 error(loc, reason, token, extraInfo);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200164 }
165 else
166 {
167 warning(loc, reason, token, extraInfo);
168 }
169}
170
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000171//
172// Same error message for all places assignments don't work.
173//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530174void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000176 std::stringstream extraInfoStream;
177 extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
178 std::string extraInfo = extraInfoStream.str();
179 error(line, "", op, extraInfo.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000180}
181
182//
183// Same error message for all places unary operations don't work.
184//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530185void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000186{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000187 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400188 extraInfoStream << "no operation '" << op << "' exists that takes an operand of type "
189 << operand << " (or there is no acceptable conversion)";
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000190 std::string extraInfo = extraInfoStream.str();
191 error(line, " wrong operand type", op, extraInfo.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000192}
193
194//
195// Same error message for all binary operations don't work.
196//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400197void TParseContext::binaryOpError(const TSourceLoc &line,
198 const char *op,
199 TString left,
200 TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000201{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000202 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400203 extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '"
204 << left << "' and a right operand of type '" << right
205 << "' (or there is no acceptable conversion)";
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000206 std::string extraInfo = extraInfoStream.str();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530207 error(line, " wrong operand types ", op, extraInfo.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000208}
209
Olli Etuaho856c4972016-08-08 11:38:39 +0300210void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
211 TPrecision precision,
212 TBasicType type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530213{
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400214 if (!mChecksPrecisionErrors)
Olli Etuaho383b7912016-08-05 11:22:59 +0300215 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200216 if (precision == EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530217 {
Olli Etuaho183d7e22015-11-20 15:59:09 +0200218 switch (type)
219 {
220 case EbtFloat:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400221 error(line, "No precision specified for (float)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300222 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200223 case EbtInt:
224 case EbtUInt:
225 UNREACHABLE(); // there's always a predeclared qualifier
Jamie Madillb98c3a82015-07-23 14:26:04 -0400226 error(line, "No precision specified (int)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300227 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200228 default:
229 if (IsSampler(type))
230 {
231 error(line, "No precision specified (sampler)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300232 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200233 }
234 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000235 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000236}
237
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000238// Both test and if necessary, spit out an error, to see if the node is really
239// an l-value that can be operated on this way.
Olli Etuaho856c4972016-08-08 11:38:39 +0300240bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400242 TIntermSymbol *symNode = node->getAsSymbolNode();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530243 TIntermBinary *binaryNode = node->getAsBinaryNode();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244
Arun Patole7e7e68d2015-05-22 12:02:25 +0530245 if (binaryNode)
246 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400247 switch (binaryNode->getOp())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530248 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400249 case EOpIndexDirect:
250 case EOpIndexIndirect:
251 case EOpIndexDirectStruct:
252 case EOpIndexDirectInterfaceBlock:
Olli Etuaho856c4972016-08-08 11:38:39 +0300253 return checkCanBeLValue(line, op, binaryNode->getLeft());
Jamie Madillb98c3a82015-07-23 14:26:04 -0400254 case EOpVectorSwizzle:
Olli Etuaho8a176262016-08-16 14:23:01 +0300255 {
256 bool ok = checkCanBeLValue(line, op, binaryNode->getLeft());
257 if (ok)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530258 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300259 int offsetCount[4] = {0, 0, 0, 0};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260
Olli Etuaho8a176262016-08-16 14:23:01 +0300261 TIntermAggregate *swizzleOffsets = binaryNode->getRight()->getAsAggregate();
Jamie Madillb98c3a82015-07-23 14:26:04 -0400262
Olli Etuaho8a176262016-08-16 14:23:01 +0300263 for (const auto &offset : *swizzleOffsets->getSequence())
Jamie Madillb98c3a82015-07-23 14:26:04 -0400264 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300265 int value = offset->getAsTyped()->getAsConstantUnion()->getIConst(0);
266 offsetCount[value]++;
267 if (offsetCount[value] > 1)
Jamie Madillb98c3a82015-07-23 14:26:04 -0400268 {
269 error(line, " l-value of swizzle cannot have duplicate components", op);
Olli Etuaho8a176262016-08-16 14:23:01 +0300270 return false;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400271 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000272 }
273 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274
Olli Etuaho8a176262016-08-16 14:23:01 +0300275 return ok;
276 }
Jamie Madillb98c3a82015-07-23 14:26:04 -0400277 default:
278 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000279 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000280 error(line, " l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000281
Olli Etuaho8a176262016-08-16 14:23:01 +0300282 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000283 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284
Arun Patole7e7e68d2015-05-22 12:02:25 +0530285 const char *symbol = 0;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000286 if (symNode != 0)
287 symbol = symNode->getSymbol().c_str();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288
Arun Patole7e7e68d2015-05-22 12:02:25 +0530289 const char *message = 0;
290 switch (node->getQualifier())
291 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400292 case EvqConst:
293 message = "can't modify a const";
294 break;
295 case EvqConstReadOnly:
296 message = "can't modify a const";
297 break;
298 case EvqAttribute:
299 message = "can't modify an attribute";
300 break;
301 case EvqFragmentIn:
302 message = "can't modify an input";
303 break;
304 case EvqVertexIn:
305 message = "can't modify an input";
306 break;
307 case EvqUniform:
308 message = "can't modify a uniform";
309 break;
310 case EvqVaryingIn:
311 message = "can't modify a varying";
312 break;
313 case EvqFragCoord:
314 message = "can't modify gl_FragCoord";
315 break;
316 case EvqFrontFacing:
317 message = "can't modify gl_FrontFacing";
318 break;
319 case EvqPointCoord:
320 message = "can't modify gl_PointCoord";
321 break;
Martin Radevb0883602016-08-04 17:48:58 +0300322 case EvqNumWorkGroups:
323 message = "can't modify gl_NumWorkGroups";
324 break;
325 case EvqWorkGroupSize:
326 message = "can't modify gl_WorkGroupSize";
327 break;
328 case EvqWorkGroupID:
329 message = "can't modify gl_WorkGroupID";
330 break;
331 case EvqLocalInvocationID:
332 message = "can't modify gl_LocalInvocationID";
333 break;
334 case EvqGlobalInvocationID:
335 message = "can't modify gl_GlobalInvocationID";
336 break;
337 case EvqLocalInvocationIndex:
338 message = "can't modify gl_LocalInvocationIndex";
339 break;
Martin Radev802abe02016-08-04 17:48:32 +0300340 case EvqComputeIn:
341 message = "can't modify work group size variable";
342 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400343 default:
344 //
345 // Type that can't be written to?
346 //
347 if (node->getBasicType() == EbtVoid)
348 {
349 message = "can't modify void";
350 }
351 if (IsSampler(node->getBasicType()))
352 {
353 message = "can't modify a sampler";
354 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000355 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000356
Arun Patole7e7e68d2015-05-22 12:02:25 +0530357 if (message == 0 && binaryNode == 0 && symNode == 0)
358 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000359 error(line, " l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000360
Olli Etuaho8a176262016-08-16 14:23:01 +0300361 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000362 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000364 //
365 // Everything else is okay, no error.
366 //
367 if (message == 0)
Olli Etuaho8a176262016-08-16 14:23:01 +0300368 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000369
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000370 //
371 // If we get here, we have an error and a message.
372 //
Arun Patole7e7e68d2015-05-22 12:02:25 +0530373 if (symNode)
374 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000375 std::stringstream extraInfoStream;
376 extraInfoStream << "\"" << symbol << "\" (" << message << ")";
377 std::string extraInfo = extraInfoStream.str();
378 error(line, " l-value required", op, extraInfo.c_str());
379 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530380 else
381 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000382 std::stringstream extraInfoStream;
383 extraInfoStream << "(" << message << ")";
384 std::string extraInfo = extraInfoStream.str();
385 error(line, " l-value required", op, extraInfo.c_str());
386 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000387
Olli Etuaho8a176262016-08-16 14:23:01 +0300388 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000389}
390
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000391// Both test, and if necessary spit out an error, to see if the node is really
392// a constant.
Olli Etuaho856c4972016-08-08 11:38:39 +0300393void TParseContext::checkIsConst(TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000394{
Olli Etuaho383b7912016-08-05 11:22:59 +0300395 if (node->getQualifier() != EvqConst)
396 {
397 error(node->getLine(), "constant expression required", "");
398 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000399}
400
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000401// Both test, and if necessary spit out an error, to see if the node is really
402// an integer.
Olli Etuaho856c4972016-08-08 11:38:39 +0300403void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000404{
Olli Etuaho383b7912016-08-05 11:22:59 +0300405 if (!node->isScalarInt())
406 {
407 error(node->getLine(), "integer expression required", token);
408 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000409}
410
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000411// Both test, and if necessary spit out an error, to see if we are currently
412// globally scoped.
Qiankun Miaof69682b2016-08-16 14:50:42 +0800413bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000414{
Olli Etuaho856c4972016-08-08 11:38:39 +0300415 if (!symbolTable.atGlobalLevel())
Olli Etuaho383b7912016-08-05 11:22:59 +0300416 {
417 error(line, "only allowed at global scope", token);
Qiankun Miaof69682b2016-08-16 14:50:42 +0800418 return false;
Olli Etuaho383b7912016-08-05 11:22:59 +0300419 }
Qiankun Miaof69682b2016-08-16 14:50:42 +0800420 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000421}
422
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000423// For now, keep it simple: if it starts "gl_", it's reserved, independent
424// of scope. Except, if the symbol table is at the built-in push-level,
425// which is when we are parsing built-ins.
alokp@chromium.org613ef312010-07-21 18:54:22 +0000426// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
427// webgl shader.
Olli Etuaho856c4972016-08-08 11:38:39 +0300428bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530430 static const char *reservedErrMsg = "reserved built-in name";
431 if (!symbolTable.atBuiltInLevel())
432 {
433 if (identifier.compare(0, 3, "gl_") == 0)
434 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000435 error(line, reservedErrMsg, "gl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300436 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000437 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530438 if (IsWebGLBasedSpec(mShaderSpec))
439 {
440 if (identifier.compare(0, 6, "webgl_") == 0)
441 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000442 error(line, reservedErrMsg, "webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300443 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000444 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530445 if (identifier.compare(0, 7, "_webgl_") == 0)
446 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000447 error(line, reservedErrMsg, "_webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300448 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000449 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530450 if (mShaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0)
451 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000452 error(line, reservedErrMsg, "css_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300453 return false;
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +0000454 }
alokp@chromium.org613ef312010-07-21 18:54:22 +0000455 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530456 if (identifier.find("__") != TString::npos)
457 {
458 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400459 "identifiers containing two consecutive underscores (__) are reserved as "
460 "possible future keywords",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530461 identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300462 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000463 }
464 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000465
Olli Etuaho8a176262016-08-16 14:23:01 +0300466 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000467}
468
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000469// Make sure there is enough data provided to the constructor to build
470// something of the type of the constructor. Also returns the type of
471// the constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +0300472bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
473 TIntermNode *argumentsNode,
474 const TFunction &function,
475 TOperator op,
476 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000477{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000478 bool constructingMatrix = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400479 switch (op)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530480 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400481 case EOpConstructMat2:
482 case EOpConstructMat2x3:
483 case EOpConstructMat2x4:
484 case EOpConstructMat3x2:
485 case EOpConstructMat3:
486 case EOpConstructMat3x4:
487 case EOpConstructMat4x2:
488 case EOpConstructMat4x3:
489 case EOpConstructMat4:
490 constructingMatrix = true;
491 break;
492 default:
493 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000494 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000495
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000496 //
497 // Note: It's okay to have too many components available, but not okay to have unused
498 // arguments. 'full' will go to true when enough args have been seen. If we loop
499 // again, there is an extra argument, so 'overfull' will become true.
500 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000501
Jamie Madillb98c3a82015-07-23 14:26:04 -0400502 size_t size = 0;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400503 bool full = false;
504 bool overFull = false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000505 bool matrixInMatrix = false;
506 bool arrayArg = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530507 for (size_t i = 0; i < function.getParamCount(); ++i)
508 {
Dmitry Skibaefa3d8e2015-06-22 14:52:10 -0700509 const TConstParameter &param = function.getParam(i);
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000510 size += param.type->getObjectSize();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530511
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000512 if (constructingMatrix && param.type->isMatrix())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000513 matrixInMatrix = true;
514 if (full)
515 overFull = true;
Olli Etuaho856c4972016-08-08 11:38:39 +0300516 if (op != EOpConstructStruct && !type.isArray() && size >= type.getObjectSize())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000517 full = true;
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000518 if (param.type->isArray())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000519 arrayArg = true;
520 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530521
Olli Etuaho856c4972016-08-08 11:38:39 +0300522 if (type.isArray())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300523 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300524 // The size of an unsized constructor should already have been determined.
525 ASSERT(!type.isUnsizedArray());
526 if (static_cast<size_t>(type.getArraySize()) != function.getParamCount())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300527 {
528 error(line, "array constructor needs one argument per array element", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300529 return false;
Olli Etuaho376f1b52015-04-13 13:23:41 +0300530 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000531 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000532
Arun Patole7e7e68d2015-05-22 12:02:25 +0530533 if (arrayArg && op != EOpConstructStruct)
534 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000535 error(line, "constructing from a non-dereferenced array", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300536 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000537 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000538
Olli Etuaho856c4972016-08-08 11:38:39 +0300539 if (matrixInMatrix && !type.isArray())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530540 {
541 if (function.getParamCount() != 1)
542 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400543 error(line, "constructing matrix from matrix can only take one argument",
544 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300545 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000546 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000547 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000548
Arun Patole7e7e68d2015-05-22 12:02:25 +0530549 if (overFull)
550 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000551 error(line, "too many arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300552 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000553 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530554
Olli Etuaho856c4972016-08-08 11:38:39 +0300555 if (op == EOpConstructStruct && !type.isArray() &&
556 type.getStruct()->fields().size() != function.getParamCount())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530557 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400558 error(line,
559 "Number of constructor parameters does not match the number of structure fields",
560 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300561 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000562 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000563
Olli Etuaho856c4972016-08-08 11:38:39 +0300564 if (!type.isMatrix() || !matrixInMatrix)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530565 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300566 if ((op != EOpConstructStruct && size != 1 && size < type.getObjectSize()) ||
567 (op == EOpConstructStruct && size < type.getObjectSize()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530568 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000569 error(line, "not enough data provided for construction", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300570 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000571 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000572 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000573
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200574 if (argumentsNode == nullptr)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530575 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200576 error(line, "constructor does not have any arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300577 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000578 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200579
580 TIntermAggregate *argumentsAgg = argumentsNode->getAsAggregate();
581 for (TIntermNode *&argNode : *argumentsAgg->getSequence())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530582 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200583 TIntermTyped *argTyped = argNode->getAsTyped();
584 ASSERT(argTyped != nullptr);
585 if (op != EOpConstructStruct && IsSampler(argTyped->getBasicType()))
586 {
587 error(line, "cannot convert a sampler", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300588 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200589 }
590 if (argTyped->getBasicType() == EbtVoid)
591 {
592 error(line, "cannot convert a void", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300593 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200594 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000595 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000596
Olli Etuaho856c4972016-08-08 11:38:39 +0300597 if (type.isArray())
598 {
599 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
600 // the array.
601 for (TIntermNode *&argNode : *argumentsAgg->getSequence())
602 {
603 const TType &argType = argNode->getAsTyped()->getType();
604 // It has already been checked that the argument is not an array.
605 ASSERT(!argType.isArray());
606 if (!argType.sameElementType(type))
607 {
608 error(line, "Array constructor argument has an incorrect type", "Error");
Olli Etuaho8a176262016-08-16 14:23:01 +0300609 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300610 }
611 }
612 }
613 else if (op == EOpConstructStruct)
614 {
615 const TFieldList &fields = type.getStruct()->fields();
616 TIntermSequence *args = argumentsAgg->getSequence();
617
618 for (size_t i = 0; i < fields.size(); i++)
619 {
620 if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type())
621 {
622 error(line, "Structure constructor arguments do not match structure fields",
623 "Error");
Olli Etuaho8a176262016-08-16 14:23:01 +0300624 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300625 }
626 }
627 }
628
Olli Etuaho8a176262016-08-16 14:23:01 +0300629 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000630}
631
Jamie Madillb98c3a82015-07-23 14:26:04 -0400632// This function checks to see if a void variable has been declared and raise an error message for
633// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000634//
635// returns true in case of an error
636//
Olli Etuaho856c4972016-08-08 11:38:39 +0300637bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400638 const TString &identifier,
639 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000640{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300641 if (type == EbtVoid)
642 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000643 error(line, "illegal use of type 'void'", identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300644 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300645 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000646
Olli Etuaho8a176262016-08-16 14:23:01 +0300647 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000648}
649
Jamie Madillb98c3a82015-07-23 14:26:04 -0400650// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300651// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300652void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000653{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530654 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
655 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000656 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530657 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000658}
659
Jamie Madillb98c3a82015-07-23 14:26:04 -0400660// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300661// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300662void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000663{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530664 if (pType.type != EbtBool || pType.isAggregate())
665 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000666 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530667 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000668}
669
Olli Etuaho856c4972016-08-08 11:38:39 +0300670bool TParseContext::checkIsNotSampler(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400671 const TPublicType &pType,
672 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000673{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530674 if (pType.type == EbtStruct)
675 {
676 if (containsSampler(*pType.userDef))
677 {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000678 error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
Olli Etuaho8a176262016-08-16 14:23:01 +0300679 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000680 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530681
Olli Etuaho8a176262016-08-16 14:23:01 +0300682 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530683 }
684 else if (IsSampler(pType.type))
685 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000686 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300687 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000688 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000689
Olli Etuaho8a176262016-08-16 14:23:01 +0300690 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000691}
692
Olli Etuaho856c4972016-08-08 11:38:39 +0300693void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
694 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400695{
696 if (pType.layoutQualifier.location != -1)
697 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400698 error(line, "location must only be specified for a single input or output variable",
699 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400700 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400701}
702
Olli Etuaho856c4972016-08-08 11:38:39 +0300703void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
704 const TLayoutQualifier &layoutQualifier)
705{
706 if (layoutQualifier.location != -1)
707 {
708 error(location, "invalid layout qualifier:", "location",
709 "only valid on program inputs and outputs");
710 }
711}
712
713void TParseContext::checkOutParameterIsNotSampler(const TSourceLoc &line,
714 TQualifier qualifier,
715 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000716{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400717 if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct &&
718 IsSampler(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530719 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000720 error(line, "samplers cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000721 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000722}
723
Arun Patole7e7e68d2015-05-22 12:02:25 +0530724bool TParseContext::containsSampler(const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000725{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000726 if (IsSampler(type.getBasicType()))
727 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000728
Arun Patole7e7e68d2015-05-22 12:02:25 +0530729 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock())
730 {
731 const TFieldList &fields = type.getStruct()->fields();
732 for (unsigned int i = 0; i < fields.size(); ++i)
733 {
Jamie Madill98493dd2013-07-08 14:39:03 -0400734 if (containsSampler(*fields[i]->type()))
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000735 return true;
736 }
737 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000738
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000739 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000740}
741
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000742// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300743unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000744{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530745 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000746
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200747 // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
748 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
749 // fold as array size.
750 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000751 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000752 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300753 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000754 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000755
Olli Etuaho856c4972016-08-08 11:38:39 +0300756 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400757
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000758 if (constant->getBasicType() == EbtUInt)
759 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300760 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000761 }
762 else
763 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300764 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000765
Olli Etuaho856c4972016-08-08 11:38:39 +0300766 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000767 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400768 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300769 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000770 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400771
Olli Etuaho856c4972016-08-08 11:38:39 +0300772 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -0400773 }
774
Olli Etuaho856c4972016-08-08 11:38:39 +0300775 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -0400776 {
777 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300778 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400779 }
780
781 // The size of arrays is restricted here to prevent issues further down the
782 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
783 // 4096 registers so this should be reasonable even for aggressively optimizable code.
784 const unsigned int sizeLimit = 65536;
785
Olli Etuaho856c4972016-08-08 11:38:39 +0300786 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -0400787 {
788 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300789 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000790 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300791
792 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000793}
794
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000795// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +0300796bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
797 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000798{
Olli Etuaho8a176262016-08-16 14:23:01 +0300799 if ((elementQualifier.qualifier == EvqAttribute) ||
800 (elementQualifier.qualifier == EvqVertexIn) ||
801 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +0300802 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400803 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300804 TType(elementQualifier).getQualifierString());
805 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000806 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000807
Olli Etuaho8a176262016-08-16 14:23:01 +0300808 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000809}
810
Olli Etuaho8a176262016-08-16 14:23:01 +0300811// See if this element type can be formed into an array.
812bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000813{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000814 //
815 // Can the type be an array?
816 //
Olli Etuaho8a176262016-08-16 14:23:01 +0300817 if (elementType.array)
Jamie Madill06145232015-05-13 13:10:01 -0400818 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300819 error(line, "cannot declare arrays of arrays",
820 TType(elementType).getCompleteString().c_str());
821 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000822 }
Olli Etuahocc36b982015-07-10 14:14:18 +0300823 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
824 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
825 // 4.3.4).
Olli Etuaho8a176262016-08-16 14:23:01 +0300826 if (mShaderVersion >= 300 && elementType.type == EbtStruct &&
827 sh::IsVarying(elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +0300828 {
829 error(line, "cannot declare arrays of structs of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300830 TType(elementType).getCompleteString().c_str());
831 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +0300832 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000833
Olli Etuaho8a176262016-08-16 14:23:01 +0300834 return true;
835}
836
837// Check if this qualified element type can be formed into an array.
838bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
839 const TPublicType &elementType)
840{
841 if (checkIsValidTypeForArray(indexLocation, elementType))
842 {
843 return checkIsValidQualifierForArray(indexLocation, elementType);
844 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000845 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000846}
847
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000848// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +0300849void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
850 const TString &identifier,
851 TPublicType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000852{
Olli Etuaho3739d232015-04-08 12:23:44 +0300853 ASSERT(type != nullptr);
854 if (type->qualifier == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000855 {
856 // Make the qualifier make sense.
Olli Etuaho3739d232015-04-08 12:23:44 +0300857 type->qualifier = EvqTemporary;
858
859 // Generate informative error messages for ESSL1.
860 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400861 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000862 {
Arun Patole7e7e68d2015-05-22 12:02:25 +0530863 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400864 "structures containing arrays may not be declared constant since they cannot be "
865 "initialized",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530866 identifier.c_str());
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000867 }
868 else
869 {
870 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
871 }
Olli Etuaho383b7912016-08-05 11:22:59 +0300872 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000873 }
Olli Etuaho376f1b52015-04-13 13:23:41 +0300874 if (type->isUnsizedArray())
875 {
876 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
Olli Etuaho376f1b52015-04-13 13:23:41 +0300877 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000878}
879
Olli Etuaho2935c582015-04-08 14:32:06 +0300880// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000881// and update the symbol table.
882//
Olli Etuaho2935c582015-04-08 14:32:06 +0300883// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000884//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400885bool TParseContext::declareVariable(const TSourceLoc &line,
886 const TString &identifier,
887 const TType &type,
Olli Etuaho2935c582015-04-08 14:32:06 +0300888 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000889{
Olli Etuaho2935c582015-04-08 14:32:06 +0300890 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000891
Olli Etuaho856c4972016-08-08 11:38:39 +0300892 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000893
Olli Etuaho2935c582015-04-08 14:32:06 +0300894 // gl_LastFragData may be redeclared with a new precision qualifier
895 if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
896 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400897 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
898 symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Olli Etuaho856c4972016-08-08 11:38:39 +0300899 if (static_cast<int>(type.getArraySize()) == maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +0300900 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400901 if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +0300902 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300903 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
Olli Etuaho2935c582015-04-08 14:32:06 +0300904 }
905 }
906 else
907 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400908 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
909 identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +0300910 return false;
911 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000912 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000913
Olli Etuaho8a176262016-08-16 14:23:01 +0300914 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +0300915 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000916
Olli Etuaho2935c582015-04-08 14:32:06 +0300917 (*variable) = new TVariable(&identifier, type);
918 if (!symbolTable.declare(*variable))
919 {
920 error(line, "redefinition", identifier.c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -0400921 *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +0300922 return false;
923 }
924
Olli Etuaho8a176262016-08-16 14:23:01 +0300925 if (!checkIsNonVoid(line, identifier, type.getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +0300926 return false;
927
928 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000929}
930
Olli Etuaho856c4972016-08-08 11:38:39 +0300931void TParseContext::checkIsParameterQualifierValid(const TSourceLoc &line,
932 TQualifier qualifier,
933 TQualifier paramQualifier,
934 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530935{
936 if (qualifier != EvqConst && qualifier != EvqTemporary)
937 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000938 error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +0300939 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000940 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530941 if (qualifier == EvqConst && paramQualifier != EvqIn)
942 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400943 error(line, "qualifier not allowed with ", getQualifierString(qualifier),
944 getQualifierString(paramQualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +0300945 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000946 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000947
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000948 if (qualifier == EvqConst)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000949 type->setQualifier(EvqConstReadOnly);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000950 else
alokp@chromium.org58e54292010-08-24 21:40:03 +0000951 type->setQualifier(paramQualifier);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000952}
953
Olli Etuaho856c4972016-08-08 11:38:39 +0300954bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000955{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400956 const TExtensionBehavior &extBehavior = extensionBehavior();
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000957 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
Arun Patole7e7e68d2015-05-22 12:02:25 +0530958 if (iter == extBehavior.end())
959 {
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000960 error(line, "extension", extension.c_str(), "is not supported");
Olli Etuaho8a176262016-08-16 14:23:01 +0300961 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000962 }
zmo@google.comf5450912011-09-09 01:37:19 +0000963 // In GLSL ES, an extension's default behavior is "disable".
Arun Patole7e7e68d2015-05-22 12:02:25 +0530964 if (iter->second == EBhDisable || iter->second == EBhUndefined)
965 {
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000966 error(line, "extension", extension.c_str(), "is disabled");
Olli Etuaho8a176262016-08-16 14:23:01 +0300967 return false;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000968 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530969 if (iter->second == EBhWarn)
970 {
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000971 warning(line, "extension", extension.c_str(), "is being used");
Olli Etuaho8a176262016-08-16 14:23:01 +0300972 return true;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000973 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000974
Olli Etuaho8a176262016-08-16 14:23:01 +0300975 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000976}
977
Jamie Madillb98c3a82015-07-23 14:26:04 -0400978// These checks are common for all declarations starting a declarator list, and declarators that
979// follow an empty declaration.
Olli Etuaho383b7912016-08-05 11:22:59 +0300980void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400981 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -0400982{
Olli Etuahofa33d582015-04-09 14:33:12 +0300983 switch (publicType.qualifier)
984 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400985 case EvqVaryingIn:
986 case EvqVaryingOut:
987 case EvqAttribute:
988 case EvqVertexIn:
989 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +0300990 case EvqComputeIn:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400991 if (publicType.type == EbtStruct)
992 {
993 error(identifierLocation, "cannot be used with a structure",
994 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +0300995 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400996 }
Olli Etuahofa33d582015-04-09 14:33:12 +0300997
Jamie Madillb98c3a82015-07-23 14:26:04 -0400998 default:
999 break;
Olli Etuahofa33d582015-04-09 14:33:12 +03001000 }
1001
Jamie Madillb98c3a82015-07-23 14:26:04 -04001002 if (publicType.qualifier != EvqUniform &&
Olli Etuaho8a176262016-08-16 14:23:01 +03001003 !checkIsNotSampler(identifierLocation, publicType, "samplers must be uniform"))
Olli Etuahofa33d582015-04-09 14:33:12 +03001004 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001005 return;
Olli Etuahofa33d582015-04-09 14:33:12 +03001006 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001007
1008 // check for layout qualifier issues
1009 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
1010
1011 if (layoutQualifier.matrixPacking != EmpUnspecified)
1012 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001013 error(identifierLocation, "layout qualifier",
1014 getMatrixPackingString(layoutQualifier.matrixPacking),
Olli Etuahofa33d582015-04-09 14:33:12 +03001015 "only valid for interface blocks");
Olli Etuaho383b7912016-08-05 11:22:59 +03001016 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001017 }
1018
1019 if (layoutQualifier.blockStorage != EbsUnspecified)
1020 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001021 error(identifierLocation, "layout qualifier",
1022 getBlockStorageString(layoutQualifier.blockStorage),
Olli Etuahofa33d582015-04-09 14:33:12 +03001023 "only valid for interface blocks");
Olli Etuaho383b7912016-08-05 11:22:59 +03001024 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001025 }
1026
Olli Etuaho383b7912016-08-05 11:22:59 +03001027 if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut)
Jamie Madilla5efff92013-06-06 11:56:47 -04001028 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001029 checkLocationIsNotSpecified(identifierLocation, publicType.layoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04001030 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001031}
1032
Olli Etuaho856c4972016-08-08 11:38:39 +03001033void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1034 const TString &layoutQualifierName,
1035 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001036{
1037
1038 if (mShaderVersion < versionRequired)
1039 {
1040 error(location, "invalid layout qualifier:", layoutQualifierName.c_str(), "not supported");
Martin Radev802abe02016-08-04 17:48:32 +03001041 }
1042}
1043
Olli Etuaho856c4972016-08-08 11:38:39 +03001044bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1045 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001046{
1047 const TLocalSize &localSize = layoutQualifier.localSize;
1048 for (size_t i = 0u; i < localSize.size(); ++i)
1049 {
1050 if (localSize[i] != -1)
1051 {
1052 error(location, "invalid layout qualifier:", getLocalSizeString(i),
1053 "only valid when used with 'in' in a compute shader global layout declaration");
Olli Etuaho8a176262016-08-16 14:23:01 +03001054 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001055 }
1056 }
1057
Olli Etuaho8a176262016-08-16 14:23:01 +03001058 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001059}
1060
Olli Etuaho383b7912016-08-05 11:22:59 +03001061void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
Olli Etuaho856c4972016-08-08 11:38:39 +03001062 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001063{
1064 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1065 {
1066 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1067 if (qual == EvqOut || qual == EvqInOut)
1068 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001069 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho8a176262016-08-16 14:23:01 +03001070 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001071 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001072 error(argument->getLine(),
Jamie Madillb98c3a82015-07-23 14:26:04 -04001073 "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
Olli Etuaho383b7912016-08-05 11:22:59 +03001074 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001075 }
1076 }
1077 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001078}
1079
Olli Etuaho856c4972016-08-08 11:38:39 +03001080void TParseContext::checkInvariantIsOutVariableES3(const TQualifier qualifier,
1081 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001082{
1083 if (!sh::IsVaryingOut(qualifier) && qualifier != EvqFragmentOut)
1084 {
1085 error(invariantLocation, "Only out variables can be invariant.", "invariant");
Olli Etuaho37ad4742015-04-27 13:18:50 +03001086 }
1087}
1088
Arun Patole7e7e68d2015-05-22 12:02:25 +05301089bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001090{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001091 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001092 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1093 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001094}
1095
Arun Patole7e7e68d2015-05-22 12:02:25 +05301096bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001097{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001098 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001099}
1100
Jamie Madillb98c3a82015-07-23 14:26:04 -04001101void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1102 const char *extName,
1103 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001104{
1105 pp::SourceLocation srcLoc;
1106 srcLoc.file = loc.first_file;
1107 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001108 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001109}
1110
Jamie Madillb98c3a82015-07-23 14:26:04 -04001111void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1112 const char *name,
1113 const char *value,
1114 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001115{
1116 pp::SourceLocation srcLoc;
1117 srcLoc.file = loc.first_file;
1118 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001119 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001120}
1121
Martin Radev802abe02016-08-04 17:48:32 +03001122TLocalSize TParseContext::getComputeShaderLocalSize() const
1123{
1124 TLocalSize result;
1125 for (size_t i = 0u; i < result.size(); ++i)
1126 {
1127 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1128 {
1129 result[i] = 1;
1130 }
1131 else
1132 {
1133 result[i] = mComputeShaderLocalSize[i];
1134 }
1135 }
1136 return result;
1137}
1138
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001139/////////////////////////////////////////////////////////////////////////////////
1140//
1141// Non-Errors.
1142//
1143/////////////////////////////////////////////////////////////////////////////////
1144
Jamie Madill5c097022014-08-20 16:38:32 -04001145const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1146 const TString *name,
1147 const TSymbol *symbol)
1148{
1149 const TVariable *variable = NULL;
1150
1151 if (!symbol)
1152 {
1153 error(location, "undeclared identifier", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001154 }
1155 else if (!symbol->isVariable())
1156 {
1157 error(location, "variable expected", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001158 }
1159 else
1160 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001161 variable = static_cast<const TVariable *>(symbol);
Jamie Madill5c097022014-08-20 16:38:32 -04001162
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001163 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
Olli Etuaho383b7912016-08-05 11:22:59 +03001164 !variable->getExtension().empty())
Jamie Madill5c097022014-08-20 16:38:32 -04001165 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001166 checkCanUseExtension(location, variable->getExtension());
Jamie Madill5c097022014-08-20 16:38:32 -04001167 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001168
1169 // Reject shaders using both gl_FragData and gl_FragColor
1170 TQualifier qualifier = variable->getType().getQualifier();
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001171 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001172 {
1173 mUsesFragData = true;
1174 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001175 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001176 {
1177 mUsesFragColor = true;
1178 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001179 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1180 {
1181 mUsesSecondaryOutputs = true;
1182 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001183
1184 // This validation is not quite correct - it's only an error to write to
1185 // both FragData and FragColor. For simplicity, and because users shouldn't
1186 // be rewarded for reading from undefined varaibles, return an error
1187 // if they are both referenced, rather than assigned.
1188 if (mUsesFragData && mUsesFragColor)
1189 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001190 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1191 if (mUsesSecondaryOutputs)
1192 {
1193 errorMessage =
1194 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1195 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1196 }
1197 error(location, errorMessage, name->c_str());
Jamie Madill14e95b32015-05-07 10:10:41 -04001198 }
Martin Radevb0883602016-08-04 17:48:58 +03001199
1200 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1201 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1202 qualifier == EvqWorkGroupSize)
1203 {
1204 error(location,
1205 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1206 "gl_WorkGroupSize");
1207 }
Jamie Madill5c097022014-08-20 16:38:32 -04001208 }
1209
1210 if (!variable)
1211 {
1212 TType type(EbtFloat, EbpUndefined);
1213 TVariable *fakeVariable = new TVariable(name, type);
1214 symbolTable.declare(fakeVariable);
1215 variable = fakeVariable;
1216 }
1217
1218 return variable;
1219}
1220
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001221TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1222 const TString *name,
1223 const TSymbol *symbol)
1224{
1225 const TVariable *variable = getNamedVariable(location, name, symbol);
1226
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001227 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001228 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001229 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001230 return intermediate.addConstantUnion(constArray, variable->getType(), location);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001231 }
1232 else
1233 {
1234 return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
1235 variable->getType(), location);
1236 }
1237}
1238
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001239//
1240// Look up a function name in the symbol table, and make sure it is a function.
1241//
1242// Return the function symbol if found, otherwise 0.
1243//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001244const TFunction *TParseContext::findFunction(const TSourceLoc &line,
1245 TFunction *call,
1246 int inputShaderVersion,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301247 bool *builtIn)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001248{
alokp@chromium.org0a576182010-08-09 17:16:27 +00001249 // First find by unmangled name to check whether the function name has been
1250 // hidden by a variable name or struct typename.
Nicolas Capensd4a9b8d2013-07-18 11:01:22 -04001251 // If a function is found, check for one with a matching argument list.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301252 const TSymbol *symbol = symbolTable.find(call->getName(), inputShaderVersion, builtIn);
1253 if (symbol == 0 || symbol->isFunction())
1254 {
Austin Kinross3ae64652015-01-26 15:51:39 -08001255 symbol = symbolTable.find(call->getMangledName(), inputShaderVersion, builtIn);
alokp@chromium.org0a576182010-08-09 17:16:27 +00001256 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001257
Arun Patole7e7e68d2015-05-22 12:02:25 +05301258 if (symbol == 0)
1259 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001260 error(line, "no matching overloaded function found", call->getName().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001261 return 0;
1262 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001263
Arun Patole7e7e68d2015-05-22 12:02:25 +05301264 if (!symbol->isFunction())
1265 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001266 error(line, "function name expected", call->getName().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001267 return 0;
1268 }
alokp@chromium.org0a576182010-08-09 17:16:27 +00001269
Jamie Madillb98c3a82015-07-23 14:26:04 -04001270 return static_cast<const TFunction *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001271}
1272
1273//
1274// Initializers show up in several places in the grammar. Have one set of
1275// code to handle them here.
1276//
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001277// Returns true on error, false if no error
1278//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001279bool TParseContext::executeInitializer(const TSourceLoc &line,
1280 const TString &identifier,
1281 const TPublicType &pType,
1282 TIntermTyped *initializer,
1283 TIntermNode **intermNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001284{
Olli Etuahoe7847b02015-03-16 11:56:12 +02001285 ASSERT(intermNode != nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001286 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001287
Olli Etuaho2935c582015-04-08 14:32:06 +03001288 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001289 if (type.isUnsizedArray())
1290 {
1291 type.setArraySize(initializer->getArraySize());
1292 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001293 if (!declareVariable(line, identifier, type, &variable))
1294 {
1295 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001296 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001297
Olli Etuahob0c645e2015-05-12 14:25:36 +03001298 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001299 if (symbolTable.atGlobalLevel() &&
1300 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001301 {
1302 // Error message does not completely match behavior with ESSL 1.00, but
1303 // we want to steer developers towards only using constant expressions.
1304 error(line, "global variable initializers must be constant expressions", "=");
1305 return true;
1306 }
1307 if (globalInitWarning)
1308 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001309 warning(
1310 line,
1311 "global variable initializers should be constant expressions "
1312 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1313 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001314 }
1315
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001316 //
1317 // identifier must be of type constant, a global, or a temporary
1318 //
1319 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301320 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1321 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001322 error(line, " cannot initialize this type of qualifier ",
1323 variable->getType().getQualifierString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001324 return true;
1325 }
1326 //
1327 // test for and propagate constant
1328 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001329
Arun Patole7e7e68d2015-05-22 12:02:25 +05301330 if (qualifier == EvqConst)
1331 {
1332 if (qualifier != initializer->getType().getQualifier())
1333 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001334 std::stringstream extraInfoStream;
1335 extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
1336 std::string extraInfo = extraInfoStream.str();
1337 error(line, " assigning non-constant to", "=", extraInfo.c_str());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001338 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001339 return true;
1340 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301341 if (type != initializer->getType())
1342 {
1343 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001344 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001345 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001346 return true;
1347 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001348
1349 // Save the constant folded value to the variable if possible. For example array
1350 // initializers are not folded, since that way copying the array literal to multiple places
1351 // in the shader is avoided.
1352 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1353 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301354 if (initializer->getAsConstantUnion())
1355 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001356 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001357 *intermNode = nullptr;
1358 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301359 }
1360 else if (initializer->getAsSymbolNode())
1361 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001362 const TSymbol *symbol =
1363 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1364 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001365
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001366 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001367 if (constArray)
1368 {
1369 variable->shareConstPointer(constArray);
1370 *intermNode = nullptr;
1371 return false;
1372 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001373 }
1374 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001375
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001376 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1377 variable->getUniqueId(), variable->getName(), variable->getType(), line);
1378 *intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1379 if (*intermNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001380 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001381 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1382 return true;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001383 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001384
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001385 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001386}
1387
Jamie Madillb98c3a82015-07-23 14:26:04 -04001388TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier,
1389 bool invariant,
1390 TLayoutQualifier layoutQualifier,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301391 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001392{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001393 TPublicType returnType = typeSpecifier;
1394 returnType.qualifier = qualifier;
1395 returnType.invariant = invariant;
Jamie Madilla5efff92013-06-06 11:56:47 -04001396 returnType.layoutQualifier = layoutQualifier;
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001397
Olli Etuaho856c4972016-08-08 11:38:39 +03001398 checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001399
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001400 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001401 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001402 if (typeSpecifier.array)
1403 {
1404 error(typeSpecifier.line, "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001405 returnType.clearArrayness();
1406 }
1407
Jamie Madillb98c3a82015-07-23 14:26:04 -04001408 if (qualifier == EvqAttribute &&
1409 (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001410 {
1411 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001412 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001413
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001414 if ((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
1415 (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
1416 {
1417 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001418 }
1419 }
1420 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001421 {
Olli Etuahoabb0c382015-07-13 12:01:12 +03001422 if (!layoutQualifier.isEmpty())
1423 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001424 checkIsAtGlobalLevel(typeSpecifier.line, "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03001425 }
Olli Etuahocc36b982015-07-10 14:14:18 +03001426 if (sh::IsVarying(qualifier) || qualifier == EvqVertexIn || qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001427 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001428 checkInputOutputTypeIsValidES3(qualifier, typeSpecifier, typeSpecifier.line);
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001429 }
Martin Radev802abe02016-08-04 17:48:32 +03001430 if (qualifier == EvqComputeIn)
1431 {
1432 error(typeSpecifier.line, "'in' can be only used to specify the local group size",
1433 "in");
Martin Radev802abe02016-08-04 17:48:32 +03001434 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001435 }
1436
1437 return returnType;
1438}
1439
Olli Etuaho856c4972016-08-08 11:38:39 +03001440void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1441 const TPublicType &type,
1442 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03001443{
1444 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
1445 if (type.type == EbtBool)
1446 {
1447 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001448 }
1449
1450 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1451 switch (qualifier)
1452 {
1453 case EvqVertexIn:
1454 // ESSL 3.00 section 4.3.4
1455 if (type.array)
1456 {
1457 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001458 }
1459 // Vertex inputs with a struct type are disallowed in singleDeclarationErrorCheck
1460 return;
1461 case EvqFragmentOut:
1462 // ESSL 3.00 section 4.3.6
1463 if (type.isMatrix())
1464 {
1465 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001466 }
1467 // Fragment outputs with a struct type are disallowed in singleDeclarationErrorCheck
1468 return;
1469 default:
1470 break;
1471 }
1472
1473 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1474 // restrictions.
1475 bool typeContainsIntegers =
1476 (type.type == EbtInt || type.type == EbtUInt || type.isStructureContainingType(EbtInt) ||
1477 type.isStructureContainingType(EbtUInt));
1478 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1479 {
1480 error(qualifierLocation, "must use 'flat' interpolation here",
1481 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001482 }
1483
1484 if (type.type == EbtStruct)
1485 {
1486 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1487 // These restrictions are only implied by the ESSL 3.00 spec, but
1488 // the ESSL 3.10 spec lists these restrictions explicitly.
1489 if (type.array)
1490 {
1491 error(qualifierLocation, "cannot be an array of structures",
1492 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001493 }
1494 if (type.isStructureContainingArrays())
1495 {
1496 error(qualifierLocation, "cannot be a structure containing an array",
1497 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001498 }
1499 if (type.isStructureContainingType(EbtStruct))
1500 {
1501 error(qualifierLocation, "cannot be a structure containing a structure",
1502 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001503 }
1504 if (type.isStructureContainingType(EbtBool))
1505 {
1506 error(qualifierLocation, "cannot be a structure containing a bool",
1507 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001508 }
1509 }
1510}
1511
Olli Etuahofa33d582015-04-09 14:33:12 +03001512TIntermAggregate *TParseContext::parseSingleDeclaration(TPublicType &publicType,
1513 const TSourceLoc &identifierOrTypeLocation,
1514 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04001515{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001516 TType type(publicType);
1517 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
1518 mDirectiveHandler.pragma().stdgl.invariantAll)
1519 {
1520 TQualifier qualifier = type.getQualifier();
1521
1522 // The directive handler has already taken care of rejecting invalid uses of this pragma
1523 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
1524 // affected variable declarations:
1525 //
1526 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
1527 // elsewhere, in TranslatorGLSL.)
1528 //
1529 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
1530 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
1531 // the way this is currently implemented we have to enable this compiler option before
1532 // parsing the shader and determining the shading language version it uses. If this were
1533 // implemented as a post-pass, the workaround could be more targeted.
1534 //
1535 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
1536 // the specification, but there are desktop OpenGL drivers that expect that this is the
1537 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
1538 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
1539 {
1540 type.setInvariant(true);
1541 }
1542 }
1543
1544 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001545
Olli Etuahobab4c082015-04-24 16:38:49 +03001546 bool emptyDeclaration = (identifier == "");
Olli Etuahofa33d582015-04-09 14:33:12 +03001547
Olli Etuahobab4c082015-04-24 16:38:49 +03001548 mDeferredSingleDeclarationErrorCheck = emptyDeclaration;
1549
1550 if (emptyDeclaration)
1551 {
1552 if (publicType.isUnsizedArray())
1553 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001554 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1555 // error. It is assumed that this applies to empty declarations as well.
1556 error(identifierOrTypeLocation, "empty array declaration needs to specify a size",
1557 identifier.c_str());
Olli Etuahobab4c082015-04-24 16:38:49 +03001558 }
1559 }
1560 else
Jamie Madill60ed9812013-06-06 11:56:46 -04001561 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001562 singleDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001563
Olli Etuaho856c4972016-08-08 11:38:39 +03001564 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001565
Olli Etuaho2935c582015-04-08 14:32:06 +03001566 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001567 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001568
1569 if (variable && symbol)
Jamie Madill60ed9812013-06-06 11:56:46 -04001570 symbol->setId(variable->getUniqueId());
Jamie Madill60ed9812013-06-06 11:56:46 -04001571 }
1572
Olli Etuahoe7847b02015-03-16 11:56:12 +02001573 return intermediate.makeAggregate(symbol, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001574}
1575
Olli Etuahoe7847b02015-03-16 11:56:12 +02001576TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1577 const TSourceLoc &identifierLocation,
1578 const TString &identifier,
1579 const TSourceLoc &indexLocation,
1580 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04001581{
Olli Etuahofa33d582015-04-09 14:33:12 +03001582 mDeferredSingleDeclarationErrorCheck = false;
1583
Olli Etuaho383b7912016-08-05 11:22:59 +03001584 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001585
Olli Etuaho856c4972016-08-08 11:38:39 +03001586 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001587
Olli Etuaho8a176262016-08-16 14:23:01 +03001588 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001589
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001590 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001591
Olli Etuaho856c4972016-08-08 11:38:39 +03001592 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001593 // Make the type an array even if size check failed.
1594 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1595 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04001596
Olli Etuaho2935c582015-04-08 14:32:06 +03001597 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001598 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001599
Olli Etuahoe7847b02015-03-16 11:56:12 +02001600 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001601 if (variable && symbol)
Jamie Madill60ed9812013-06-06 11:56:46 -04001602 symbol->setId(variable->getUniqueId());
Jamie Madill60ed9812013-06-06 11:56:46 -04001603
Olli Etuahoe7847b02015-03-16 11:56:12 +02001604 return intermediate.makeAggregate(symbol, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001605}
1606
Jamie Madill06145232015-05-13 13:10:01 -04001607TIntermAggregate *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
Olli Etuahoe7847b02015-03-16 11:56:12 +02001608 const TSourceLoc &identifierLocation,
1609 const TString &identifier,
1610 const TSourceLoc &initLocation,
1611 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04001612{
Olli Etuahofa33d582015-04-09 14:33:12 +03001613 mDeferredSingleDeclarationErrorCheck = false;
1614
Olli Etuaho383b7912016-08-05 11:22:59 +03001615 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001616
Olli Etuahoe7847b02015-03-16 11:56:12 +02001617 TIntermNode *intermNode = nullptr;
1618 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04001619 {
1620 //
1621 // Build intermediate representation
1622 //
Olli Etuahoe7847b02015-03-16 11:56:12 +02001623 return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : nullptr;
Jamie Madill60ed9812013-06-06 11:56:46 -04001624 }
1625 else
1626 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001627 return nullptr;
Jamie Madill60ed9812013-06-06 11:56:46 -04001628 }
1629}
1630
Jamie Madillb98c3a82015-07-23 14:26:04 -04001631TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration(
1632 TPublicType &publicType,
1633 const TSourceLoc &identifierLocation,
1634 const TString &identifier,
1635 const TSourceLoc &indexLocation,
1636 TIntermTyped *indexExpression,
1637 const TSourceLoc &initLocation,
1638 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001639{
1640 mDeferredSingleDeclarationErrorCheck = false;
1641
Olli Etuaho383b7912016-08-05 11:22:59 +03001642 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001643
Olli Etuaho8a176262016-08-16 14:23:01 +03001644 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001645
1646 TPublicType arrayType(publicType);
1647
Olli Etuaho856c4972016-08-08 11:38:39 +03001648 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001649 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
1650 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03001651 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001652 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001653 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001654 }
1655 // Make the type an array even if size check failed.
1656 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1657 arrayType.setArraySize(size);
1658
1659 // initNode will correspond to the whole of "type b[n] = initializer".
1660 TIntermNode *initNode = nullptr;
1661 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
1662 {
1663 return initNode ? intermediate.makeAggregate(initNode, initLocation) : nullptr;
1664 }
1665 else
1666 {
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001667 return nullptr;
1668 }
1669}
1670
Olli Etuahoe7847b02015-03-16 11:56:12 +02001671TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc,
Jamie Madill47e3ec02014-08-20 16:38:33 -04001672 const TSourceLoc &identifierLoc,
1673 const TString *identifier,
1674 const TSymbol *symbol)
1675{
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001676 // invariant declaration
Qiankun Miaof69682b2016-08-16 14:50:42 +08001677 if (!checkIsAtGlobalLevel(invariantLoc, "invariant varying"))
1678 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001679
1680 if (!symbol)
1681 {
1682 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001683 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001684 }
1685 else
1686 {
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001687 const TString kGlFrontFacing("gl_FrontFacing");
1688 if (*identifier == kGlFrontFacing)
1689 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001690 error(identifierLoc, "identifier should not be declared as invariant",
1691 identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001692 return nullptr;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001693 }
Jamie Madill2c433252014-12-03 12:36:54 -05001694 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001695 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
1696 ASSERT(variable);
1697 const TType &type = variable->getType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04001698 TIntermSymbol *intermSymbol =
1699 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001700
1701 TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc);
1702 aggregate->setOp(EOpInvariantDeclaration);
1703 return aggregate;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001704 }
1705}
1706
Jamie Madillb98c3a82015-07-23 14:26:04 -04001707TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType,
1708 TIntermAggregate *aggregateDeclaration,
1709 const TSourceLoc &identifierLocation,
1710 const TString &identifier)
Jamie Madill502d66f2013-06-20 11:55:52 -04001711{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001712 // If the declaration starting this declarator list was empty (example: int,), some checks were
1713 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001714 if (mDeferredSingleDeclarationErrorCheck)
1715 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001716 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001717 mDeferredSingleDeclarationErrorCheck = false;
1718 }
1719
Olli Etuaho856c4972016-08-08 11:38:39 +03001720 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001721
Olli Etuaho856c4972016-08-08 11:38:39 +03001722 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04001723
Olli Etuaho2935c582015-04-08 14:32:06 +03001724 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001725 declareVariable(identifierLocation, identifier, TType(publicType), &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001726
Jamie Madillb98c3a82015-07-23 14:26:04 -04001727 TIntermSymbol *symbol =
1728 intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001729 if (variable && symbol)
Jamie Madill502d66f2013-06-20 11:55:52 -04001730 symbol->setId(variable->getUniqueId());
1731
Olli Etuahoe7847b02015-03-16 11:56:12 +02001732 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001733}
1734
Jamie Madillb98c3a82015-07-23 14:26:04 -04001735TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType,
1736 TIntermAggregate *aggregateDeclaration,
1737 const TSourceLoc &identifierLocation,
1738 const TString &identifier,
1739 const TSourceLoc &arrayLocation,
1740 TIntermTyped *indexExpression)
Jamie Madill502d66f2013-06-20 11:55:52 -04001741{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001742 // If the declaration starting this declarator list was empty (example: int,), some checks were
1743 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001744 if (mDeferredSingleDeclarationErrorCheck)
1745 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001746 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001747 mDeferredSingleDeclarationErrorCheck = false;
1748 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001749
Olli Etuaho856c4972016-08-08 11:38:39 +03001750 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001751
Olli Etuaho856c4972016-08-08 11:38:39 +03001752 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04001753
Olli Etuaho8a176262016-08-16 14:23:01 +03001754 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04001755 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001756 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03001757 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03001758 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001759
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001760 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001761 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04001762
Jamie Madillb98c3a82015-07-23 14:26:04 -04001763 TIntermSymbol *symbol =
1764 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001765 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001766 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001767
1768 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001769 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001770
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001771 return nullptr;
Jamie Madill502d66f2013-06-20 11:55:52 -04001772}
1773
Jamie Madillb98c3a82015-07-23 14:26:04 -04001774TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicType,
1775 TIntermAggregate *aggregateDeclaration,
1776 const TSourceLoc &identifierLocation,
1777 const TString &identifier,
1778 const TSourceLoc &initLocation,
1779 TIntermTyped *initializer)
Jamie Madill502d66f2013-06-20 11:55:52 -04001780{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001781 // If the declaration starting this declarator list was empty (example: int,), some checks were
1782 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001783 if (mDeferredSingleDeclarationErrorCheck)
1784 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001785 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001786 mDeferredSingleDeclarationErrorCheck = false;
1787 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001788
Olli Etuaho856c4972016-08-08 11:38:39 +03001789 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001790
Olli Etuahoe7847b02015-03-16 11:56:12 +02001791 TIntermNode *intermNode = nullptr;
1792 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04001793 {
1794 //
1795 // build the intermediate representation
1796 //
1797 if (intermNode)
1798 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001799 return intermediate.growAggregate(aggregateDeclaration, intermNode, initLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001800 }
1801 else
1802 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001803 return aggregateDeclaration;
Jamie Madill502d66f2013-06-20 11:55:52 -04001804 }
1805 }
1806 else
1807 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001808 return nullptr;
Jamie Madill502d66f2013-06-20 11:55:52 -04001809 }
1810}
1811
Jamie Madill06145232015-05-13 13:10:01 -04001812TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001813 TIntermAggregate *aggregateDeclaration,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301814 const TSourceLoc &identifierLocation,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001815 const TString &identifier,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301816 const TSourceLoc &indexLocation,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001817 TIntermTyped *indexExpression,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001818 const TSourceLoc &initLocation,
1819 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001820{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001821 // If the declaration starting this declarator list was empty (example: int,), some checks were
1822 // not performed.
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001823 if (mDeferredSingleDeclarationErrorCheck)
1824 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001825 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001826 mDeferredSingleDeclarationErrorCheck = false;
1827 }
1828
Olli Etuaho856c4972016-08-08 11:38:39 +03001829 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001830
Olli Etuaho8a176262016-08-16 14:23:01 +03001831 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001832
1833 TPublicType arrayType(publicType);
1834
Olli Etuaho856c4972016-08-08 11:38:39 +03001835 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001836 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
1837 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03001838 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001839 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001840 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001841 }
1842 // Make the type an array even if size check failed.
1843 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1844 arrayType.setArraySize(size);
1845
1846 // initNode will correspond to the whole of "b[n] = initializer".
1847 TIntermNode *initNode = nullptr;
1848 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
1849 {
1850 if (initNode)
1851 {
1852 return intermediate.growAggregate(aggregateDeclaration, initNode, initLocation);
1853 }
1854 else
1855 {
1856 return aggregateDeclaration;
1857 }
1858 }
1859 else
1860 {
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001861 return nullptr;
1862 }
1863}
1864
Jamie Madilla295edf2013-06-06 11:56:48 -04001865void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
1866{
Jamie Madilla295edf2013-06-06 11:56:48 -04001867 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04001868
1869 // It should never be the case, but some strange parser errors can send us here.
1870 if (layoutQualifier.isEmpty())
1871 {
1872 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04001873 return;
1874 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001875
Martin Radev802abe02016-08-04 17:48:32 +03001876 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04001877 {
Martin Radev802abe02016-08-04 17:48:32 +03001878 error(typeQualifier.line, "invalid combination:", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04001879 return;
1880 }
1881
Martin Radev802abe02016-08-04 17:48:32 +03001882 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04001883 {
Martin Radev802abe02016-08-04 17:48:32 +03001884 if (mComputeShaderLocalSizeDeclared &&
1885 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
1886 {
1887 error(typeQualifier.line, "Work group size does not match the previous declaration",
1888 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001889 return;
1890 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001891
Martin Radev802abe02016-08-04 17:48:32 +03001892 if (mShaderVersion < 310)
1893 {
1894 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001895 return;
1896 }
Jamie Madill099c0f32013-06-20 11:55:52 -04001897
Martin Radev802abe02016-08-04 17:48:32 +03001898 if (!layoutQualifier.isGroupSizeSpecified())
1899 {
1900 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001901 return;
1902 }
1903
1904 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
1905 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
1906
1907 const TConstantUnion *maxComputeWorkGroupSizeData =
1908 maxComputeWorkGroupSize->getConstPointer();
1909
1910 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
1911 {
1912 if (layoutQualifier.localSize[i] != -1)
1913 {
1914 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
1915 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
1916 if (mComputeShaderLocalSize[i] < 1 ||
1917 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
1918 {
1919 std::stringstream errorMessageStream;
1920 errorMessageStream << "Value must be at least 1 and no greater than "
1921 << maxComputeWorkGroupSizeValue;
1922 const std::string &errorMessage = errorMessageStream.str();
1923
1924 error(typeQualifier.line, "invalid value:", getLocalSizeString(i),
1925 errorMessage.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03001926 return;
1927 }
1928 }
1929 }
1930
1931 mComputeShaderLocalSizeDeclared = true;
1932 }
1933 else
Jamie Madill1566ef72013-06-20 11:55:54 -04001934 {
Martin Radev802abe02016-08-04 17:48:32 +03001935
Olli Etuaho8a176262016-08-16 14:23:01 +03001936 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03001937 {
Martin Radev802abe02016-08-04 17:48:32 +03001938 return;
1939 }
1940
1941 if (typeQualifier.qualifier != EvqUniform)
1942 {
1943 error(typeQualifier.line, "invalid qualifier:",
1944 getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
Martin Radev802abe02016-08-04 17:48:32 +03001945 return;
1946 }
1947
1948 if (mShaderVersion < 300)
1949 {
1950 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
1951 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001952 return;
1953 }
1954
Olli Etuaho856c4972016-08-08 11:38:39 +03001955 checkLocationIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001956
1957 if (layoutQualifier.matrixPacking != EmpUnspecified)
1958 {
1959 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
1960 }
1961
1962 if (layoutQualifier.blockStorage != EbsUnspecified)
1963 {
1964 mDefaultBlockStorage = layoutQualifier.blockStorage;
1965 }
Jamie Madill1566ef72013-06-20 11:55:54 -04001966 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001967}
1968
Olli Etuahoee63f5d2016-01-04 11:34:54 +02001969TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function,
1970 const TSourceLoc &location)
1971{
Olli Etuaho5d653182016-01-04 14:43:28 +02001972 // Note: symbolTableFunction could be the same as function if this is the first declaration.
1973 // Either way the instance in the symbol table is used to track whether the function is declared
1974 // multiple times.
1975 TFunction *symbolTableFunction =
1976 static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion()));
1977 if (symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100)
1978 {
1979 // ESSL 1.00.17 section 4.2.7.
1980 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
1981 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02001982 }
1983 symbolTableFunction->setHasPrototypeDeclaration();
1984
Olli Etuahoee63f5d2016-01-04 11:34:54 +02001985 TIntermAggregate *prototype = new TIntermAggregate;
1986 prototype->setType(function.getReturnType());
1987 prototype->setName(function.getMangledName());
1988 prototype->setFunctionId(function.getUniqueId());
1989
1990 for (size_t i = 0; i < function.getParamCount(); i++)
1991 {
1992 const TConstParameter &param = function.getParam(i);
1993 if (param.name != 0)
1994 {
1995 TVariable variable(param.name, *param.type);
1996
1997 TIntermSymbol *paramSymbol = intermediate.addSymbol(
1998 variable.getUniqueId(), variable.getName(), variable.getType(), location);
1999 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
2000 }
2001 else
2002 {
2003 TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
2004 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
2005 }
2006 }
2007
2008 prototype->setOp(EOpPrototype);
2009
2010 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002011
2012 if (!symbolTable.atGlobalLevel())
2013 {
2014 // ESSL 3.00.4 section 4.2.4.
2015 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002016 }
2017
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002018 return prototype;
2019}
2020
2021TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function,
2022 TIntermAggregate *functionPrototype,
2023 TIntermAggregate *functionBody,
2024 const TSourceLoc &location)
2025{
2026 //?? Check that all paths return a value if return type != void ?
2027 // May be best done as post process phase on intermediate code
2028 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2029 {
2030 error(location, "function does not return a value:", "", function.getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002031 }
2032
2033 TIntermAggregate *aggregate =
2034 intermediate.growAggregate(functionPrototype, functionBody, location);
2035 intermediate.setAggregateOperator(aggregate, EOpFunction, location);
2036 aggregate->setName(function.getMangledName().c_str());
2037 aggregate->setType(function.getReturnType());
2038 aggregate->setFunctionId(function.getUniqueId());
2039
2040 symbolTable.pop();
2041 return aggregate;
2042}
2043
Jamie Madill185fb402015-06-12 15:48:48 -04002044void TParseContext::parseFunctionPrototype(const TSourceLoc &location,
2045 TFunction *function,
2046 TIntermAggregate **aggregateOut)
2047{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002048 const TSymbol *builtIn =
2049 symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002050
2051 if (builtIn)
2052 {
2053 error(location, "built-in functions cannot be redefined", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002054 }
2055
Jamie Madillb98c3a82015-07-23 14:26:04 -04002056 TFunction *prevDec =
2057 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Jamie Madill185fb402015-06-12 15:48:48 -04002058 //
2059 // Note: 'prevDec' could be 'function' if this is the first time we've seen function
2060 // as it would have just been put in the symbol table. Otherwise, we're looking up
2061 // an earlier occurance.
2062 //
2063 if (prevDec->isDefined())
2064 {
2065 // Then this function already has a body.
2066 error(location, "function already has a body", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002067 }
2068 prevDec->setDefined();
2069 //
2070 // Overload the unique ID of the definition to be the same unique ID as the declaration.
2071 // Eventually we will probably want to have only a single definition and just swap the
2072 // arguments to be the definition's arguments.
2073 //
2074 function->setUniqueId(prevDec->getUniqueId());
2075
2076 // Raise error message if main function takes any parameters or return anything other than void
2077 if (function->getName() == "main")
2078 {
2079 if (function->getParamCount() > 0)
2080 {
2081 error(location, "function cannot take any parameter(s)", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002082 }
2083 if (function->getReturnType().getBasicType() != EbtVoid)
2084 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002085 error(location, "", function->getReturnType().getBasicString(),
2086 "main function cannot return a value");
Jamie Madill185fb402015-06-12 15:48:48 -04002087 }
2088 }
2089
2090 //
2091 // Remember the return type for later checking for RETURN statements.
2092 //
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002093 mCurrentFunctionType = &(prevDec->getReturnType());
2094 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002095
2096 //
2097 // Insert parameters into the symbol table.
2098 // If the parameter has no name, it's not an error, just don't insert it
2099 // (could be used for unused args).
2100 //
2101 // Also, accumulate the list of parameters into the HIL, so lower level code
2102 // knows where to find parameters.
2103 //
2104 TIntermAggregate *paramNodes = new TIntermAggregate;
2105 for (size_t i = 0; i < function->getParamCount(); i++)
2106 {
2107 const TConstParameter &param = function->getParam(i);
2108 if (param.name != 0)
2109 {
2110 TVariable *variable = new TVariable(param.name, *param.type);
2111 //
2112 // Insert the parameters with name in the symbol table.
2113 //
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002114 if (!symbolTable.declare(variable))
2115 {
Jamie Madill185fb402015-06-12 15:48:48 -04002116 error(location, "redefinition", variable->getName().c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002117 paramNodes = intermediate.growAggregate(
2118 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
2119 continue;
Jamie Madill185fb402015-06-12 15:48:48 -04002120 }
2121
2122 //
2123 // Add the parameter to the HIL
2124 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002125 TIntermSymbol *symbol = intermediate.addSymbol(
2126 variable->getUniqueId(), variable->getName(), variable->getType(), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002127
2128 paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
2129 }
2130 else
2131 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002132 paramNodes = intermediate.growAggregate(
2133 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002134 }
2135 }
2136 intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
2137 *aggregateOut = paramNodes;
2138 setLoopNestingLevel(0);
2139}
2140
Jamie Madillb98c3a82015-07-23 14:26:04 -04002141TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002142{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002143 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002144 // We don't know at this point whether this is a function definition or a prototype.
2145 // The definition production code will check for redefinitions.
2146 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002147 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002148 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2149 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002150 //
2151 TFunction *prevDec =
2152 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302153
2154 if (getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltIn(function->getName().c_str()))
2155 {
2156 // With ESSL 3.00, names of built-in functions cannot be redeclared as functions.
2157 // Therefore overloading or redefining builtin functions is an error.
2158 error(location, "Name of a built-in function cannot be redeclared as function",
2159 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302160 }
2161 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002162 {
2163 if (prevDec->getReturnType() != function->getReturnType())
2164 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002165 error(location, "overloaded functions must have the same return type",
Jamie Madill185fb402015-06-12 15:48:48 -04002166 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002167 }
2168 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2169 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002170 if (prevDec->getParam(i).type->getQualifier() !=
2171 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002172 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002173 error(location, "overloaded functions must have the same parameter qualifiers",
Jamie Madill185fb402015-06-12 15:48:48 -04002174 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002175 }
2176 }
2177 }
2178
2179 //
2180 // Check for previously declared variables using the same name.
2181 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002182 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002183 if (prevSym)
2184 {
2185 if (!prevSym->isFunction())
2186 {
2187 error(location, "redefinition", function->getName().c_str(), "function");
Jamie Madill185fb402015-06-12 15:48:48 -04002188 }
2189 }
2190 else
2191 {
2192 // Insert the unmangled name to detect potential future redefinition as a variable.
Jamie Madillb98c3a82015-07-23 14:26:04 -04002193 TFunction *newFunction =
2194 new TFunction(NewPoolTString(function->getName().c_str()), &function->getReturnType());
Jamie Madill185fb402015-06-12 15:48:48 -04002195 symbolTable.getOuterLevel()->insertUnmangled(newFunction);
2196 }
2197
2198 // We're at the inner scope level of the function's arguments and body statement.
2199 // Add the function prototype to the surrounding scope instead.
2200 symbolTable.getOuterLevel()->insert(function);
2201
2202 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002203 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2204 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002205 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2206 //
2207 return function;
2208}
2209
Olli Etuaho9de84a52016-06-14 17:36:01 +03002210TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2211 const TString *name,
2212 const TSourceLoc &location)
2213{
2214 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2215 {
2216 error(location, "no qualifiers allowed for function return",
2217 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002218 }
2219 if (!type.layoutQualifier.isEmpty())
2220 {
2221 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002222 }
2223 // make sure a sampler is not involved as well...
Olli Etuaho856c4972016-08-08 11:38:39 +03002224 checkIsNotSampler(location, type, "samplers can't be function return values");
Olli Etuahoe29324f2016-06-15 10:58:03 +03002225 if (mShaderVersion < 300)
2226 {
2227 // Array return values are forbidden, but there's also no valid syntax for declaring array
2228 // return values in ESSL 1.00.
2229 ASSERT(type.arraySize == 0 || mDiagnostics.numErrors() > 0);
2230
2231 if (type.isStructureContainingArrays())
2232 {
2233 // ESSL 1.00.17 section 6.1 Function Definitions
2234 error(location, "structures containing arrays can't be function return values",
2235 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002236 }
2237 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002238
2239 // Add the function as a prototype after parsing it (we do not support recursion)
2240 return new TFunction(name, new TType(type));
2241}
2242
Jamie Madill06145232015-05-13 13:10:01 -04002243TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002244{
Jamie Madill06145232015-05-13 13:10:01 -04002245 TPublicType publicType = publicTypeIn;
Olli Etuahobd163f62015-11-13 12:15:38 +02002246 if (publicType.isStructSpecifier)
2247 {
2248 error(publicType.line, "constructor can't be a structure definition",
2249 getBasicString(publicType.type));
Olli Etuahobd163f62015-11-13 12:15:38 +02002250 }
2251
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002252 TOperator op = EOpNull;
2253 if (publicType.userDef)
2254 {
2255 op = EOpConstructStruct;
2256 }
2257 else
2258 {
Geoff Lang156d7192016-07-21 16:11:00 -04002259 op = sh::TypeToConstructorOperator(TType(publicType));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002260 if (op == EOpNull)
2261 {
2262 error(publicType.line, "cannot construct this type", getBasicString(publicType.type));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002263 publicType.type = EbtFloat;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002264 op = EOpConstructFloat;
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002265 }
2266 }
2267
2268 TString tempString;
Dmitry Skiba7f17a502015-06-22 15:08:39 -07002269 const TType *type = new TType(publicType);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002270 return new TFunction(&tempString, type, op);
2271}
2272
Jamie Madillb98c3a82015-07-23 14:26:04 -04002273// This function is used to test for the correctness of the parameters passed to various constructor
2274// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002275//
Olli Etuaho856c4972016-08-08 11:38:39 +03002276// 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 +00002277//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002278TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002279 TOperator op,
2280 TFunction *fnCall,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302281 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002282{
Olli Etuaho856c4972016-08-08 11:38:39 +03002283 TType type = fnCall->getReturnType();
2284 if (type.isUnsizedArray())
2285 {
2286 type.setArraySize(static_cast<unsigned int>(fnCall->getParamCount()));
2287 }
2288 bool constType = true;
2289 for (size_t i = 0; i < fnCall->getParamCount(); ++i)
2290 {
2291 const TConstParameter &param = fnCall->getParam(i);
2292 if (param.type->getQualifier() != EvqConst)
2293 constType = false;
2294 }
2295 if (constType)
2296 type.setQualifier(EvqConst);
2297
Olli Etuaho8a176262016-08-16 14:23:01 +03002298 if (!checkConstructorArguments(line, arguments, *fnCall, op, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002299 {
2300 TIntermTyped *dummyNode = intermediate.setAggregateOperator(nullptr, op, line);
2301 dummyNode->setType(type);
2302 return dummyNode;
2303 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002304 TIntermAggregate *constructor = arguments->getAsAggregate();
2305 ASSERT(constructor != nullptr);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002306
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002307 // Turn the argument list itself into a constructor
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002308 constructor->setOp(op);
2309 constructor->setLine(line);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002310 ASSERT(constructor->isConstructor());
2311
2312 // Need to set type before setPrecisionFromChildren() because bool doesn't have precision.
Olli Etuaho856c4972016-08-08 11:38:39 +03002313 constructor->setType(type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002314
Olli Etuaho21203702014-11-13 16:16:21 +02002315 // Structs should not be precision qualified, the individual members may be.
2316 // Built-in types on the other hand should be precision qualified.
2317 if (op != EOpConstructStruct)
2318 {
2319 constructor->setPrecisionFromChildren();
Olli Etuaho856c4972016-08-08 11:38:39 +03002320 type.setPrecision(constructor->getPrecision());
Olli Etuaho21203702014-11-13 16:16:21 +02002321 }
2322
Olli Etuaho856c4972016-08-08 11:38:39 +03002323 constructor->setType(type);
2324
Olli Etuaho1d122782015-11-06 15:35:17 +02002325 TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002326 if (constConstructor)
2327 {
2328 return constConstructor;
2329 }
2330
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002331 return constructor;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002332}
2333
Olli Etuaho90892fb2016-07-14 14:44:51 +03002334// This function returns vector field(s) being accessed from a constant vector.
2335TIntermConstantUnion *TParseContext::foldVectorSwizzle(TVectorFields &fields,
2336 TIntermConstantUnion *baseNode,
2337 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002338{
Olli Etuaho90892fb2016-07-14 14:44:51 +03002339 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002340 ASSERT(unionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002341
Arun Patole7e7e68d2015-05-22 12:02:25 +05302342 TConstantUnion *constArray = new TConstantUnion[fields.num];
Olli Etuaho90892fb2016-07-14 14:44:51 +03002343 const auto &type = baseNode->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002344
Arun Patole7e7e68d2015-05-22 12:02:25 +05302345 for (int i = 0; i < fields.num; i++)
2346 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002347 // Out-of-range indices should already be checked.
2348 ASSERT(fields.offsets[i] < type.getNominalSize());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002349 constArray[i] = unionArray[fields.offsets[i]];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302350 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03002351 return intermediate.addConstantUnion(constArray, type, location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002352}
2353
Olli Etuaho90892fb2016-07-14 14:44:51 +03002354// This function returns the column vector being accessed from a constant matrix.
2355TIntermConstantUnion *TParseContext::foldMatrixSubscript(int index,
2356 TIntermConstantUnion *baseNode,
2357 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002358{
Olli Etuaho90892fb2016-07-14 14:44:51 +03002359 ASSERT(index < baseNode->getType().getCols());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002360
Olli Etuaho90892fb2016-07-14 14:44:51 +03002361 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
2362 int size = baseNode->getType().getRows();
2363 return intermediate.addConstantUnion(&unionArray[size * index], baseNode->getType(), location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002364}
2365
Olli Etuaho90892fb2016-07-14 14:44:51 +03002366// This function returns an element of an array accessed from a constant array.
2367TIntermConstantUnion *TParseContext::foldArraySubscript(int index,
2368 TIntermConstantUnion *baseNode,
2369 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002370{
Olli Etuaho856c4972016-08-08 11:38:39 +03002371 ASSERT(index < static_cast<int>(baseNode->getArraySize()));
Olli Etuaho90892fb2016-07-14 14:44:51 +03002372
2373 TType arrayElementType = baseNode->getType();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002374 arrayElementType.clearArrayness();
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002375 size_t arrayElementSize = arrayElementType.getObjectSize();
Olli Etuaho90892fb2016-07-14 14:44:51 +03002376 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
2377 return intermediate.addConstantUnion(&unionArray[arrayElementSize * index], baseNode->getType(),
2378 location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002379}
2380
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002381//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002382// This function returns the value of a particular field inside a constant structure from the symbol
2383// table.
2384// If there is an embedded/nested struct, it appropriately calls addConstStructNested or
2385// addConstStructFromAggr function and returns the parse-tree with the values of the embedded/nested
2386// struct.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002387//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002388TIntermTyped *TParseContext::addConstStruct(const TString &identifier,
2389 TIntermTyped *node,
2390 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002391{
Arun Patole7e7e68d2015-05-22 12:02:25 +05302392 const TFieldList &fields = node->getType().getStruct()->fields();
Jamie Madillb98c3a82015-07-23 14:26:04 -04002393 size_t instanceSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002394
Arun Patole7e7e68d2015-05-22 12:02:25 +05302395 for (size_t index = 0; index < fields.size(); ++index)
2396 {
2397 if (fields[index]->name() == identifier)
2398 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002399 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302400 }
2401 else
2402 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002403 instanceSize += fields[index]->type()->getObjectSize();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002404 }
2405 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002406
Jamie Madill94bf7f22013-07-08 13:31:15 -04002407 TIntermTyped *typedNode;
2408 TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
Arun Patole7e7e68d2015-05-22 12:02:25 +05302409 if (tempConstantNode)
2410 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002411 const TConstantUnion *constArray = tempConstantNode->getUnionArrayPointer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002412
Jamie Madillb98c3a82015-07-23 14:26:04 -04002413 // type will be changed in the calling function
2414 typedNode = intermediate.addConstantUnion(constArray + instanceSize,
2415 tempConstantNode->getType(), line);
Arun Patole7e7e68d2015-05-22 12:02:25 +05302416 }
2417 else
2418 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002419 error(line, "Cannot offset into the structure", "Error");
Olli Etuaho383b7912016-08-05 11:22:59 +03002420 return nullptr;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002421 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002422
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002423 return typedNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002424}
2425
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002426//
2427// Interface/uniform blocks
2428//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002429TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualifier,
2430 const TSourceLoc &nameLine,
2431 const TString &blockName,
2432 TFieldList *fieldList,
2433 const TString *instanceName,
2434 const TSourceLoc &instanceLine,
2435 TIntermTyped *arrayIndex,
2436 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002437{
Olli Etuaho856c4972016-08-08 11:38:39 +03002438 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002439
2440 if (typeQualifier.qualifier != EvqUniform)
2441 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302442 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier),
2443 "interface blocks must be uniform");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002444 }
2445
Jamie Madill099c0f32013-06-20 11:55:52 -04002446 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03002447 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04002448
Jamie Madill099c0f32013-06-20 11:55:52 -04002449 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2450 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002451 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002452 }
2453
Jamie Madill1566ef72013-06-20 11:55:54 -04002454 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2455 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002456 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002457 }
2458
Olli Etuaho856c4972016-08-08 11:38:39 +03002459 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002460
Arun Patole7e7e68d2015-05-22 12:02:25 +05302461 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2462 if (!symbolTable.declare(blockNameSymbol))
2463 {
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002464 error(nameLine, "redefinition", blockName.c_str(), "interface block name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002465 }
2466
Jamie Madill98493dd2013-07-08 14:39:03 -04002467 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302468 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2469 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002470 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302471 TType *fieldType = field->type();
2472 if (IsSampler(fieldType->getBasicType()))
2473 {
2474 error(field->line(), "unsupported type", fieldType->getBasicString(),
2475 "sampler types are not allowed in interface blocks");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002476 }
2477
Jamie Madill98493dd2013-07-08 14:39:03 -04002478 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002479 switch (qualifier)
2480 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002481 case EvqGlobal:
2482 case EvqUniform:
2483 break;
2484 default:
2485 error(field->line(), "invalid qualifier on interface block member",
2486 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04002487 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002488 }
Jamie Madilla5efff92013-06-06 11:56:47 -04002489
2490 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04002491 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03002492 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Jamie Madill099c0f32013-06-20 11:55:52 -04002493
Jamie Madill98493dd2013-07-08 14:39:03 -04002494 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04002495 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002496 error(field->line(), "invalid layout qualifier:",
2497 getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
Jamie Madill1566ef72013-06-20 11:55:54 -04002498 }
2499
Jamie Madill98493dd2013-07-08 14:39:03 -04002500 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04002501 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002502 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002503 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002504 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04002505 {
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002506 warning(field->line(), "extraneous layout qualifier:",
Jamie Madillb98c3a82015-07-23 14:26:04 -04002507 getMatrixPackingString(fieldLayoutQualifier.matrixPacking),
2508 "only has an effect on matrix types");
Jamie Madill099c0f32013-06-20 11:55:52 -04002509 }
2510
Jamie Madill98493dd2013-07-08 14:39:03 -04002511 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002512 }
2513
Jamie Madill98493dd2013-07-08 14:39:03 -04002514 // add array index
Olli Etuaho856c4972016-08-08 11:38:39 +03002515 unsigned int arraySize = 0;
2516 if (arrayIndex != nullptr)
Jamie Madill98493dd2013-07-08 14:39:03 -04002517 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002518 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
Jamie Madill98493dd2013-07-08 14:39:03 -04002519 }
2520
Jamie Madillb98c3a82015-07-23 14:26:04 -04002521 TInterfaceBlock *interfaceBlock =
2522 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2523 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
2524 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002525
2526 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04002527 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002528
Jamie Madill98493dd2013-07-08 14:39:03 -04002529 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002530 {
2531 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04002532 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2533 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002534 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302535 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04002536
2537 // set parent pointer of the field variable
2538 fieldType->setInterfaceBlock(interfaceBlock);
2539
Arun Patole7e7e68d2015-05-22 12:02:25 +05302540 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04002541 fieldVariable->setQualifier(typeQualifier.qualifier);
2542
Arun Patole7e7e68d2015-05-22 12:02:25 +05302543 if (!symbolTable.declare(fieldVariable))
2544 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002545 error(field->line(), "redefinition", field->name().c_str(),
2546 "interface block member name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002547 }
2548 }
2549 }
2550 else
2551 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002552 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03002553
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002554 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05302555 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002556 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04002557
Arun Patole7e7e68d2015-05-22 12:02:25 +05302558 if (!symbolTable.declare(instanceTypeDef))
2559 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002560 error(instanceLine, "redefinition", instanceName->c_str(),
2561 "interface block instance name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002562 }
2563
Jamie Madillb98c3a82015-07-23 14:26:04 -04002564 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002565 symbolName = instanceTypeDef->getName();
2566 }
2567
Jamie Madillb98c3a82015-07-23 14:26:04 -04002568 TIntermAggregate *aggregate = intermediate.makeAggregate(
2569 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line),
2570 nameLine);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002571 aggregate->setOp(EOpDeclaration);
Jamie Madill98493dd2013-07-08 14:39:03 -04002572
2573 exitStructDeclaration();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002574 return aggregate;
2575}
2576
Olli Etuaho383b7912016-08-05 11:22:59 +03002577void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002578{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002579 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002580
2581 // Embedded structure definitions are not supported per GLSL ES spec.
2582 // They aren't allowed in GLSL either, but we need to detect this here
2583 // so we don't rely on the GLSL compiler to catch it.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302584 if (mStructNestingLevel > 1)
2585 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002586 error(line, "", "Embedded struct definitions are not allowed");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002587 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002588}
2589
2590void TParseContext::exitStructDeclaration()
2591{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002592 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002593}
2594
Jamie Madillb98c3a82015-07-23 14:26:04 -04002595namespace
2596{
kbr@chromium.org476541f2011-10-27 21:14:51 +00002597const int kWebGLMaxStructNesting = 4;
2598
2599} // namespace
2600
Olli Etuaho8a176262016-08-16 14:23:01 +03002601void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002602{
Arun Patole7e7e68d2015-05-22 12:02:25 +05302603 if (!IsWebGLBasedSpec(mShaderSpec))
2604 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002605 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002606 }
2607
Arun Patole7e7e68d2015-05-22 12:02:25 +05302608 if (field.type()->getBasicType() != EbtStruct)
2609 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002610 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002611 }
2612
2613 // We're already inside a structure definition at this point, so add
2614 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302615 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2616 {
Jamie Madill41a49272014-03-18 16:10:13 -04002617 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002618 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
2619 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04002620 std::string reason = reasonStream.str();
2621 error(line, reason.c_str(), field.name().c_str(), "");
Olli Etuaho8a176262016-08-16 14:23:01 +03002622 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002623 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002624}
2625
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00002626//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002627// Parse an array index expression
2628//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002629TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
2630 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302631 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002632{
2633 TIntermTyped *indexedExpression = NULL;
2634
2635 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2636 {
2637 if (baseExpression->getAsSymbolNode())
2638 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302639 error(location, " left of '[' is not of type array, matrix, or vector ",
2640 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002641 }
2642 else
2643 {
2644 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2645 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002646 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002647
Jamie Madill21c1e452014-12-29 11:33:41 -05002648 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2649
Olli Etuaho36b05142015-11-12 13:10:42 +02002650 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
2651 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
2652 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
2653 // index is a constant expression.
2654 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
2655 {
2656 if (baseExpression->isInterfaceBlock())
2657 {
2658 error(
2659 location, "", "[",
2660 "array indexes for interface blocks arrays must be constant integral expressions");
Olli Etuaho36b05142015-11-12 13:10:42 +02002661 }
2662 else if (baseExpression->getQualifier() == EvqFragmentOut)
2663 {
2664 error(location, "", "[",
2665 "array indexes for fragment outputs must be constant integral expressions");
Olli Etuaho36b05142015-11-12 13:10:42 +02002666 }
Olli Etuaho3e960462015-11-12 15:58:39 +02002667 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
2668 {
2669 error(location, "", "[", "array index for gl_FragData must be constant zero");
Olli Etuaho3e960462015-11-12 15:58:39 +02002670 }
Olli Etuaho36b05142015-11-12 13:10:42 +02002671 }
2672
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002673 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04002674 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002675 // If the index is not qualified as constant, the behavior in the spec is undefined. This
2676 // applies even if ANGLE has been able to constant fold it (ANGLE may constant fold
2677 // expressions that are not constant expressions). The most compatible way to handle this
2678 // case is to report a warning instead of an error and force the index to be in the
2679 // correct range.
2680 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madill21c1e452014-12-29 11:33:41 -05002681 int index = indexConstantUnion->getIConst(0);
Olli Etuaho90892fb2016-07-14 14:44:51 +03002682 if (!baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04002683 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002684 // Array checks are done later because a different error message might be generated
2685 // based on the index in some cases.
2686 if (baseExpression->isVector())
2687 {
2688 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2689 baseExpression->getType().getNominalSize(),
2690 "vector field selection out of range", "[]");
2691 }
2692 else if (baseExpression->isMatrix())
2693 {
2694 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2695 baseExpression->getType().getCols(),
2696 "matrix field selection out of range", "[]");
2697 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002698 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03002699
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002700 TIntermConstantUnion *baseConstantUnion = baseExpression->getAsConstantUnion();
2701 if (baseConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04002702 {
2703 if (baseExpression->isArray())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002704 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002705 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2706 baseExpression->getArraySize(),
2707 "array index out of range", "[]");
2708 // Constant folding for array indexing.
2709 indexedExpression = foldArraySubscript(index, baseConstantUnion, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002710 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002711 else if (baseExpression->isVector())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002712 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002713 // Constant folding for vector indexing - reusing vector swizzle folding.
Jamie Madill7164cf42013-07-08 13:30:59 -04002714 TVectorFields fields;
2715 fields.num = 1;
Olli Etuaho90892fb2016-07-14 14:44:51 +03002716 fields.offsets[0] = index;
2717 indexedExpression = foldVectorSwizzle(fields, baseConstantUnion, location);
Jamie Madill7164cf42013-07-08 13:30:59 -04002718 }
2719 else if (baseExpression->isMatrix())
2720 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002721 // Constant folding for matrix indexing.
2722 indexedExpression = foldMatrixSubscript(index, baseConstantUnion, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002723 }
2724 }
2725 else
2726 {
Jamie Madillb11e2482015-05-04 14:21:22 -04002727 int safeIndex = -1;
2728
Jamie Madill7164cf42013-07-08 13:30:59 -04002729 if (baseExpression->isArray())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002730 {
Olli Etuaho3e960462015-11-12 15:58:39 +02002731 if (baseExpression->getQualifier() == EvqFragData && index > 0)
2732 {
2733 if (mShaderSpec == SH_WEBGL2_SPEC)
2734 {
2735 // Error has been already generated if index is not const.
2736 if (indexExpression->getQualifier() == EvqConst)
2737 {
2738 error(location, "", "[",
2739 "array index for gl_FragData must be constant zero");
Olli Etuaho3e960462015-11-12 15:58:39 +02002740 }
2741 safeIndex = 0;
2742 }
2743 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
2744 {
2745 outOfRangeError(outOfRangeIndexIsError, location, "", "[",
2746 "array index for gl_FragData must be zero when "
2747 "GL_EXT_draw_buffers is disabled");
2748 safeIndex = 0;
2749 }
2750 }
2751 // Only do generic out-of-range check if similar error hasn't already been reported.
Olli Etuaho90892fb2016-07-14 14:44:51 +03002752 if (safeIndex < 0)
Jamie Madill7164cf42013-07-08 13:30:59 -04002753 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002754 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2755 baseExpression->getArraySize(),
2756 "array index out of range", "[]");
Jamie Madill7164cf42013-07-08 13:30:59 -04002757 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002758 }
2759
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002760 // Data of constant unions can't be changed, because it may be shared with other
2761 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
2762 // sanitized object.
Jamie Madillb11e2482015-05-04 14:21:22 -04002763 if (safeIndex != -1)
2764 {
2765 TConstantUnion *safeConstantUnion = new TConstantUnion();
2766 safeConstantUnion->setIConst(safeIndex);
2767 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
2768 }
2769
Jamie Madillb98c3a82015-07-23 14:26:04 -04002770 indexedExpression =
2771 intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002772 }
2773 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002774 else
2775 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002776 indexedExpression =
2777 intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
Jamie Madill7164cf42013-07-08 13:30:59 -04002778 }
2779
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002780 if (indexedExpression == 0)
2781 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002782 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002783 unionArray->setFConst(0.0f);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002784 indexedExpression =
2785 intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002786 }
2787 else if (baseExpression->isArray())
2788 {
Olli Etuahob3fbd862015-09-30 17:55:02 +03002789 TType indexedType = baseExpression->getType();
2790 indexedType.clearArrayness();
2791 indexedExpression->setType(indexedType);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002792 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002793 else if (baseExpression->isMatrix())
2794 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002795 indexedExpression->setType(TType(baseExpression->getBasicType(),
Olli Etuahob3fbd862015-09-30 17:55:02 +03002796 baseExpression->getPrecision(), EvqTemporary,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002797 static_cast<unsigned char>(baseExpression->getRows())));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002798 }
2799 else if (baseExpression->isVector())
2800 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002801 indexedExpression->setType(
Olli Etuahob3fbd862015-09-30 17:55:02 +03002802 TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002803 }
2804 else
2805 {
2806 indexedExpression->setType(baseExpression->getType());
2807 }
2808
Olli Etuahob3fbd862015-09-30 17:55:02 +03002809 if (baseExpression->getType().getQualifier() == EvqConst &&
2810 indexExpression->getType().getQualifier() == EvqConst)
2811 {
2812 indexedExpression->getTypePointer()->setQualifier(EvqConst);
2813 }
2814 else
2815 {
2816 indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
2817 }
2818
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002819 return indexedExpression;
2820}
2821
Olli Etuaho90892fb2016-07-14 14:44:51 +03002822int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
2823 const TSourceLoc &location,
2824 int index,
2825 int arraySize,
2826 const char *reason,
2827 const char *token)
2828{
2829 if (index >= arraySize || index < 0)
2830 {
2831 std::stringstream extraInfoStream;
2832 extraInfoStream << "'" << index << "'";
2833 std::string extraInfo = extraInfoStream.str();
2834 outOfRangeError(outOfRangeIndexIsError, location, reason, token, extraInfo.c_str());
2835 if (index < 0)
2836 {
2837 return 0;
2838 }
2839 else
2840 {
2841 return arraySize - 1;
2842 }
2843 }
2844 return index;
2845}
2846
Jamie Madillb98c3a82015-07-23 14:26:04 -04002847TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
2848 const TSourceLoc &dotLocation,
2849 const TString &fieldString,
2850 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002851{
2852 TIntermTyped *indexedExpression = NULL;
2853
2854 if (baseExpression->isArray())
2855 {
2856 error(fieldLocation, "cannot apply dot operator to an array", ".");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002857 }
2858
2859 if (baseExpression->isVector())
2860 {
2861 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002862 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
2863 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002864 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002865 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002866 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002867 }
2868
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002869 if (baseExpression->getAsConstantUnion())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002870 {
2871 // constant folding for vector fields
Olli Etuaho90892fb2016-07-14 14:44:51 +03002872 indexedExpression =
2873 foldVectorSwizzle(fields, baseExpression->getAsConstantUnion(), fieldLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002874 }
2875 else
2876 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302877 TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002878 indexedExpression =
2879 intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002880 }
2881 if (indexedExpression == nullptr)
2882 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002883 indexedExpression = baseExpression;
2884 }
2885 else
2886 {
2887 // Note that the qualifier set here will be corrected later.
Jamie Madillb98c3a82015-07-23 14:26:04 -04002888 indexedExpression->setType(TType(baseExpression->getBasicType(),
2889 baseExpression->getPrecision(), EvqTemporary,
Jamie Madillc2128ff2016-07-04 10:26:17 -04002890 static_cast<unsigned char>(fields.num)));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002891 }
2892 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002893 else if (baseExpression->getBasicType() == EbtStruct)
2894 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002895 bool fieldFound = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302896 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04002897 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002898 {
2899 error(dotLocation, "structure has no fields", "Internal Error");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002900 indexedExpression = baseExpression;
2901 }
2902 else
2903 {
2904 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04002905 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002906 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002907 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002908 {
2909 fieldFound = true;
2910 break;
2911 }
2912 }
2913 if (fieldFound)
2914 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002915 if (baseExpression->getAsConstantUnion())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002916 {
2917 indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
2918 if (indexedExpression == 0)
2919 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002920 indexedExpression = baseExpression;
2921 }
2922 else
2923 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002924 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002925 }
2926 }
2927 else
2928 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002929 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002930 unionArray->setIConst(i);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002931 TIntermTyped *index = intermediate.addConstantUnion(
2932 unionArray, *fields[i]->type(), fieldLocation);
2933 indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression,
2934 index, dotLocation);
Jamie Madill98493dd2013-07-08 14:39:03 -04002935 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002936 }
2937 }
2938 else
2939 {
2940 error(dotLocation, " no such field in structure", fieldString.c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002941 indexedExpression = baseExpression;
2942 }
2943 }
2944 }
Jamie Madill98493dd2013-07-08 14:39:03 -04002945 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002946 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002947 bool fieldFound = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302948 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04002949 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002950 {
2951 error(dotLocation, "interface block has no fields", "Internal Error");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002952 indexedExpression = baseExpression;
2953 }
2954 else
2955 {
2956 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04002957 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002958 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002959 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002960 {
2961 fieldFound = true;
2962 break;
2963 }
2964 }
2965 if (fieldFound)
2966 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002967 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002968 unionArray->setIConst(i);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002969 TIntermTyped *index =
2970 intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
2971 indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock,
2972 baseExpression, index, dotLocation);
Jamie Madill98493dd2013-07-08 14:39:03 -04002973 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002974 }
2975 else
2976 {
2977 error(dotLocation, " no such field in interface block", fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002978 indexedExpression = baseExpression;
2979 }
2980 }
2981 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002982 else
2983 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002984 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002985 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03002986 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05302987 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002988 }
2989 else
2990 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302991 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03002992 " field selection requires structure, vector, or interface block on left hand "
2993 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05302994 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002995 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002996 indexedExpression = baseExpression;
2997 }
2998
Olli Etuahob1edc4f2015-11-02 17:20:03 +02002999 if (baseExpression->getQualifier() == EvqConst)
3000 {
3001 indexedExpression->getTypePointer()->setQualifier(EvqConst);
3002 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003003 else
3004 {
3005 indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
3006 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02003007
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003008 return indexedExpression;
3009}
3010
Jamie Madillb98c3a82015-07-23 14:26:04 -04003011TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3012 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003013{
Martin Radev802abe02016-08-04 17:48:32 +03003014 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003015
3016 if (qualifierType == "shared")
3017 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003018 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003019 }
3020 else if (qualifierType == "packed")
3021 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003022 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003023 }
3024 else if (qualifierType == "std140")
3025 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003026 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003027 }
3028 else if (qualifierType == "row_major")
3029 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003030 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003031 }
3032 else if (qualifierType == "column_major")
3033 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003034 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003035 }
3036 else if (qualifierType == "location")
3037 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003038 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(),
3039 "location requires an argument");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003040 }
3041 else
3042 {
3043 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003044 }
3045
Jamie Madilla5efff92013-06-06 11:56:47 -04003046 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003047}
3048
Martin Radev802abe02016-08-04 17:48:32 +03003049void TParseContext::parseLocalSize(const TString &qualifierType,
3050 const TSourceLoc &qualifierTypeLine,
3051 int intValue,
3052 const TSourceLoc &intValueLine,
3053 const std::string &intValueString,
3054 size_t index,
3055 TLocalSize *localSize)
3056{
Olli Etuaho856c4972016-08-08 11:38:39 +03003057 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03003058 if (intValue < 1)
3059 {
3060 std::string errorMessage = std::string(getLocalSizeString(index)) + " must be positive";
3061 error(intValueLine, "out of range:", intValueString.c_str(), errorMessage.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003062 }
3063 (*localSize)[index] = intValue;
3064}
3065
Jamie Madillb98c3a82015-07-23 14:26:04 -04003066TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3067 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003068 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303069 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003070{
Martin Radev802abe02016-08-04 17:48:32 +03003071 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003072
Martin Radev802abe02016-08-04 17:48:32 +03003073 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003074
Martin Radev802abe02016-08-04 17:48:32 +03003075 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003076 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003077 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003078 if (intValue < 0)
3079 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003080 error(intValueLine, "out of range:", intValueString.c_str(),
3081 "location must be non-negative");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003082 }
3083 else
3084 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003085 qualifier.location = intValue;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003086 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003087 }
Martin Radev802abe02016-08-04 17:48:32 +03003088 else if (qualifierType == "local_size_x")
3089 {
3090 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3091 &qualifier.localSize);
3092 }
3093 else if (qualifierType == "local_size_y")
3094 {
3095 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3096 &qualifier.localSize);
3097 }
3098 else if (qualifierType == "local_size_z")
3099 {
3100 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3101 &qualifier.localSize);
3102 }
3103 else
3104 {
3105 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003106 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003107
Jamie Madilla5efff92013-06-06 11:56:47 -04003108 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003109}
3110
Jamie Madillb98c3a82015-07-23 14:26:04 -04003111TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003112 TLayoutQualifier rightQualifier,
3113 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003114{
Jamie Madilla5efff92013-06-06 11:56:47 -04003115 TLayoutQualifier joinedQualifier = leftQualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003116
Jamie Madilla5efff92013-06-06 11:56:47 -04003117 if (rightQualifier.location != -1)
3118 {
3119 joinedQualifier.location = rightQualifier.location;
3120 }
3121 if (rightQualifier.matrixPacking != EmpUnspecified)
3122 {
3123 joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
3124 }
3125 if (rightQualifier.blockStorage != EbsUnspecified)
3126 {
3127 joinedQualifier.blockStorage = rightQualifier.blockStorage;
3128 }
3129
Martin Radev802abe02016-08-04 17:48:32 +03003130 for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i)
3131 {
3132 if (rightQualifier.localSize[i] != -1)
3133 {
3134 if (joinedQualifier.localSize[i] != -1 &&
3135 joinedQualifier.localSize[i] != rightQualifier.localSize[i])
3136 {
3137 error(rightQualifierLocation,
3138 "Cannot have multiple different work group size specifiers",
3139 getLocalSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03003140 }
3141 joinedQualifier.localSize[i] = rightQualifier.localSize[i];
3142 }
3143 }
3144
Jamie Madilla5efff92013-06-06 11:56:47 -04003145 return joinedQualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003146}
3147
Arun Patole7e7e68d2015-05-22 12:02:25 +05303148TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc,
3149 TQualifier interpolationQualifier,
3150 const TSourceLoc &storageLoc,
3151 TQualifier storageQualifier)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003152{
3153 TQualifier mergedQualifier = EvqSmoothIn;
3154
Arun Patole7e7e68d2015-05-22 12:02:25 +05303155 if (storageQualifier == EvqFragmentIn)
3156 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003157 if (interpolationQualifier == EvqSmooth)
3158 mergedQualifier = EvqSmoothIn;
3159 else if (interpolationQualifier == EvqFlat)
3160 mergedQualifier = EvqFlatIn;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003161 else
3162 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003163 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303164 else if (storageQualifier == EvqCentroidIn)
3165 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003166 if (interpolationQualifier == EvqSmooth)
3167 mergedQualifier = EvqCentroidIn;
3168 else if (interpolationQualifier == EvqFlat)
3169 mergedQualifier = EvqFlatIn;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003170 else
3171 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003172 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303173 else if (storageQualifier == EvqVertexOut)
3174 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003175 if (interpolationQualifier == EvqSmooth)
3176 mergedQualifier = EvqSmoothOut;
3177 else if (interpolationQualifier == EvqFlat)
3178 mergedQualifier = EvqFlatOut;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003179 else
3180 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003181 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303182 else if (storageQualifier == EvqCentroidOut)
3183 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003184 if (interpolationQualifier == EvqSmooth)
3185 mergedQualifier = EvqCentroidOut;
3186 else if (interpolationQualifier == EvqFlat)
3187 mergedQualifier = EvqFlatOut;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003188 else
3189 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003190 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303191 else
3192 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003193 error(interpolationLoc,
3194 "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303195 getInterpolationString(interpolationQualifier));
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003196
3197 mergedQualifier = storageQualifier;
3198 }
3199
3200 TPublicType type;
3201 type.setBasic(EbtVoid, mergedQualifier, storageLoc);
3202 return type;
3203}
3204
Jamie Madillb98c3a82015-07-23 14:26:04 -04003205TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3206 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003207{
Olli Etuaho856c4972016-08-08 11:38:39 +03003208 checkIsNonVoid(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003209
Olli Etuaho856c4972016-08-08 11:38:39 +03003210 checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003211
Arun Patole7e7e68d2015-05-22 12:02:25 +05303212 for (unsigned int i = 0; i < fieldList->size(); ++i)
3213 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003214 //
3215 // Careful not to replace already known aspects of type, like array-ness
3216 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303217 TType *type = (*fieldList)[i]->type();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003218 type->setBasicType(typeSpecifier.type);
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003219 type->setPrimarySize(typeSpecifier.primarySize);
3220 type->setSecondarySize(typeSpecifier.secondarySize);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003221 type->setPrecision(typeSpecifier.precision);
3222 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003223 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003224
3225 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303226 if (type->isArray())
3227 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003228 checkIsValidTypeForArray(typeSpecifier.line, typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003229 }
3230 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003231 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Arun Patole7e7e68d2015-05-22 12:02:25 +05303232 if (typeSpecifier.userDef)
3233 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003234 type->setStruct(typeSpecifier.userDef->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003235 }
3236
Olli Etuaho8a176262016-08-16 14:23:01 +03003237 checkIsBelowStructNestingLimit(typeSpecifier.line, *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003238 }
3239
Jamie Madill98493dd2013-07-08 14:39:03 -04003240 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003241}
3242
Jamie Madillb98c3a82015-07-23 14:26:04 -04003243TPublicType TParseContext::addStructure(const TSourceLoc &structLine,
3244 const TSourceLoc &nameLine,
3245 const TString *structName,
3246 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003247{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303248 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003249 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003250
Jamie Madill9b820842015-02-12 10:40:10 -05003251 // Store a bool in the struct if we're at global scope, to allow us to
3252 // skip the local struct scoping workaround in HLSL.
Jamie Madillb960cc42015-02-12 15:33:20 +00003253 structure->setUniqueId(TSymbolTable::nextUniqueId());
Jamie Madill9b820842015-02-12 10:40:10 -05003254 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003255
Jamie Madill98493dd2013-07-08 14:39:03 -04003256 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003257 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003258 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303259 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3260 if (!symbolTable.declare(userTypeDef))
3261 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003262 error(nameLine, "redefinition", structName->c_str(), "struct");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003263 }
3264 }
3265
3266 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003267 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003268 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003269 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003270 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003271 switch (qualifier)
3272 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003273 case EvqGlobal:
3274 case EvqTemporary:
3275 break;
3276 default:
3277 error(field.line(), "invalid qualifier on struct member",
3278 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003279 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003280 }
3281 }
3282
3283 TPublicType publicType;
3284 publicType.setBasic(EbtStruct, EvqTemporary, structLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04003285 publicType.userDef = structureType;
Olli Etuahobd163f62015-11-13 12:15:38 +02003286 publicType.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003287 exitStructDeclaration();
3288
3289 return publicType;
3290}
3291
Jamie Madillb98c3a82015-07-23 14:26:04 -04003292TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
3293 TIntermAggregate *statementList,
3294 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003295{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003296 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003297 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003298 init->isVector())
3299 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003300 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3301 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003302 return nullptr;
3303 }
3304
Olli Etuahoac5274d2015-02-20 10:19:08 +02003305 if (statementList)
3306 {
3307 if (!ValidateSwitch::validate(switchType, this, statementList, loc))
3308 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003309 return nullptr;
3310 }
3311 }
3312
Olli Etuahoa3a36662015-02-17 13:46:51 +02003313 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3314 if (node == nullptr)
3315 {
3316 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003317 return nullptr;
3318 }
3319 return node;
3320}
3321
3322TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3323{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003324 if (mSwitchNestingLevel == 0)
3325 {
3326 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003327 return nullptr;
3328 }
3329 if (condition == nullptr)
3330 {
3331 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003332 return nullptr;
3333 }
3334 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003335 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003336 {
3337 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003338 }
3339 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003340 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3341 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3342 // fold in case labels.
3343 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003344 {
3345 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003346 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003347 TIntermCase *node = intermediate.addCase(condition, loc);
3348 if (node == nullptr)
3349 {
3350 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003351 return nullptr;
3352 }
3353 return node;
3354}
3355
3356TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3357{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003358 if (mSwitchNestingLevel == 0)
3359 {
3360 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003361 return nullptr;
3362 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003363 TIntermCase *node = intermediate.addCase(nullptr, loc);
3364 if (node == nullptr)
3365 {
3366 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003367 return nullptr;
3368 }
3369 return node;
3370}
3371
Jamie Madillb98c3a82015-07-23 14:26:04 -04003372TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3373 TIntermTyped *child,
3374 const TSourceLoc &loc,
3375 const TType *funcReturnType)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003376{
3377 if (child == nullptr)
3378 {
3379 return nullptr;
3380 }
3381
3382 switch (op)
3383 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003384 case EOpLogicalNot:
3385 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3386 child->isVector())
3387 {
3388 return nullptr;
3389 }
3390 break;
3391 case EOpBitwiseNot:
3392 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3393 child->isMatrix() || child->isArray())
3394 {
3395 return nullptr;
3396 }
3397 break;
3398 case EOpPostIncrement:
3399 case EOpPreIncrement:
3400 case EOpPostDecrement:
3401 case EOpPreDecrement:
3402 case EOpNegative:
3403 case EOpPositive:
3404 if (child->getBasicType() == EbtStruct || child->getBasicType() == EbtBool ||
3405 child->isArray())
3406 {
3407 return nullptr;
3408 }
3409 // Operators for built-ins are already type checked against their prototype.
3410 default:
3411 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003412 }
3413
Olli Etuahof6c694b2015-03-26 14:50:53 +02003414 return intermediate.addUnaryMath(op, child, loc, funcReturnType);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003415}
3416
Olli Etuaho09b22472015-02-11 11:47:26 +02003417TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3418{
Olli Etuahof6c694b2015-03-26 14:50:53 +02003419 TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003420 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003421 {
3422 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003423 return child;
3424 }
3425 return node;
3426}
3427
Jamie Madillb98c3a82015-07-23 14:26:04 -04003428TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3429 TIntermTyped *child,
3430 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003431{
Olli Etuaho856c4972016-08-08 11:38:39 +03003432 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003433 return addUnaryMath(op, child, loc);
3434}
3435
Jamie Madillb98c3a82015-07-23 14:26:04 -04003436bool TParseContext::binaryOpCommonCheck(TOperator op,
3437 TIntermTyped *left,
3438 TIntermTyped *right,
3439 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003440{
Olli Etuaho244be012016-08-18 15:26:02 +03003441 if (left->getType().getStruct() || right->getType().getStruct())
3442 {
3443 switch (op)
3444 {
3445 case EOpIndexDirectStruct:
3446 ASSERT(left->getType().getStruct());
3447 break;
3448 case EOpEqual:
3449 case EOpNotEqual:
3450 case EOpAssign:
3451 case EOpInitialize:
3452 if (left->getType() != right->getType())
3453 {
3454 return false;
3455 }
3456 break;
3457 default:
3458 error(loc, "Invalid operation for structs", GetOperatorString(op));
3459 return false;
3460 }
3461 }
3462
Olli Etuahod6b14282015-03-17 14:31:35 +02003463 if (left->isArray() || right->isArray())
3464 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003465 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003466 {
3467 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3468 return false;
3469 }
3470
3471 if (left->isArray() != right->isArray())
3472 {
3473 error(loc, "array / non-array mismatch", GetOperatorString(op));
3474 return false;
3475 }
3476
3477 switch (op)
3478 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003479 case EOpEqual:
3480 case EOpNotEqual:
3481 case EOpAssign:
3482 case EOpInitialize:
3483 break;
3484 default:
3485 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3486 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02003487 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03003488 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02003489 if (left->getArraySize() != right->getArraySize())
3490 {
3491 error(loc, "array size mismatch", GetOperatorString(op));
3492 return false;
3493 }
Olli Etuahod6b14282015-03-17 14:31:35 +02003494 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003495
3496 // Check ops which require integer / ivec parameters
3497 bool isBitShift = false;
3498 switch (op)
3499 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003500 case EOpBitShiftLeft:
3501 case EOpBitShiftRight:
3502 case EOpBitShiftLeftAssign:
3503 case EOpBitShiftRightAssign:
3504 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3505 // check that the basic type is an integer type.
3506 isBitShift = true;
3507 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3508 {
3509 return false;
3510 }
3511 break;
3512 case EOpBitwiseAnd:
3513 case EOpBitwiseXor:
3514 case EOpBitwiseOr:
3515 case EOpBitwiseAndAssign:
3516 case EOpBitwiseXorAssign:
3517 case EOpBitwiseOrAssign:
3518 // It is enough to check the type of only one operand, since later it
3519 // is checked that the operand types match.
3520 if (!IsInteger(left->getBasicType()))
3521 {
3522 return false;
3523 }
3524 break;
3525 default:
3526 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003527 }
3528
3529 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3530 // So the basic type should usually match.
3531 if (!isBitShift && left->getBasicType() != right->getBasicType())
3532 {
3533 return false;
3534 }
3535
Olli Etuaho9dd217b2015-03-20 14:24:31 +02003536 // Check that type sizes match exactly on ops that require that.
Olli Etuahoff699002015-03-23 14:38:42 +02003537 // Also check restrictions for structs that contain arrays or samplers.
Jamie Madillb98c3a82015-07-23 14:26:04 -04003538 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003539 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003540 case EOpAssign:
3541 case EOpInitialize:
3542 case EOpEqual:
3543 case EOpNotEqual:
3544 // ESSL 1.00 sections 5.7, 5.8, 5.9
3545 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
3546 {
3547 error(loc, "undefined operation for structs containing arrays",
3548 GetOperatorString(op));
3549 return false;
3550 }
3551 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3552 // we interpret the spec so that this extends to structs containing samplers,
3553 // similarly to ESSL 1.00 spec.
3554 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
3555 left->getType().isStructureContainingSamplers())
3556 {
3557 error(loc, "undefined operation for structs containing samplers",
3558 GetOperatorString(op));
3559 return false;
3560 }
3561 case EOpLessThan:
3562 case EOpGreaterThan:
3563 case EOpLessThanEqual:
3564 case EOpGreaterThanEqual:
3565 if ((left->getNominalSize() != right->getNominalSize()) ||
3566 (left->getSecondarySize() != right->getSecondarySize()))
3567 {
3568 return false;
3569 }
3570 default:
3571 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003572 }
3573
Olli Etuahod6b14282015-03-17 14:31:35 +02003574 return true;
3575}
3576
Jamie Madillb98c3a82015-07-23 14:26:04 -04003577TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
3578 TIntermTyped *left,
3579 TIntermTyped *right,
3580 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02003581{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003582 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003583 return nullptr;
3584
Olli Etuahofc1806e2015-03-17 13:03:11 +02003585 switch (op)
3586 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003587 case EOpEqual:
3588 case EOpNotEqual:
3589 break;
3590 case EOpLessThan:
3591 case EOpGreaterThan:
3592 case EOpLessThanEqual:
3593 case EOpGreaterThanEqual:
Olli Etuaho244be012016-08-18 15:26:02 +03003594 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3595 !right->getType().getStruct());
3596 if (left->isMatrix() || left->isVector())
Jamie Madillb98c3a82015-07-23 14:26:04 -04003597 {
3598 return nullptr;
3599 }
3600 break;
3601 case EOpLogicalOr:
3602 case EOpLogicalXor:
3603 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03003604 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3605 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003606 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isVector())
3607 {
3608 return nullptr;
3609 }
3610 break;
3611 case EOpAdd:
3612 case EOpSub:
3613 case EOpDiv:
3614 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03003615 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3616 !right->getType().getStruct());
3617 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04003618 {
3619 return nullptr;
3620 }
3621 break;
3622 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03003623 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3624 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003625 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03003626 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04003627 {
3628 return nullptr;
3629 }
3630 break;
3631 // Note that for bitwise ops, type checking is done in promote() to
3632 // share code between ops and compound assignment
3633 default:
3634 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02003635 }
3636
Olli Etuaho3fdec912016-08-18 15:08:06 +03003637 TIntermBinary *node = new TIntermBinary(op, left, right);
3638 node->setLine(loc);
3639
3640 if (!node->promote())
3641 return nullptr;
3642
3643 // See if we can fold constants.
3644 TIntermTyped *foldedNode = node->fold(&mDiagnostics);
3645 if (foldedNode)
3646 return foldedNode;
3647
3648 return node;
Olli Etuahofc1806e2015-03-17 13:03:11 +02003649}
3650
Jamie Madillb98c3a82015-07-23 14:26:04 -04003651TIntermTyped *TParseContext::addBinaryMath(TOperator op,
3652 TIntermTyped *left,
3653 TIntermTyped *right,
3654 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003655{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003656 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003657 if (node == 0)
3658 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003659 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3660 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003661 return left;
3662 }
3663 return node;
3664}
3665
Jamie Madillb98c3a82015-07-23 14:26:04 -04003666TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
3667 TIntermTyped *left,
3668 TIntermTyped *right,
3669 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003670{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003671 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003672 if (node == 0)
3673 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003674 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3675 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003676 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02003677 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003678 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
3679 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003680 }
3681 return node;
3682}
3683
Jamie Madillb98c3a82015-07-23 14:26:04 -04003684TIntermTyped *TParseContext::createAssign(TOperator op,
3685 TIntermTyped *left,
3686 TIntermTyped *right,
3687 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003688{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003689 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003690 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03003691 TIntermBinary *node = new TIntermBinary(op, left, right);
3692 node->setLine(loc);
3693
3694 if (!node->promote())
3695 return nullptr;
3696
3697 return node;
Olli Etuahod6b14282015-03-17 14:31:35 +02003698 }
3699 return nullptr;
3700}
3701
Jamie Madillb98c3a82015-07-23 14:26:04 -04003702TIntermTyped *TParseContext::addAssign(TOperator op,
3703 TIntermTyped *left,
3704 TIntermTyped *right,
3705 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003706{
3707 TIntermTyped *node = createAssign(op, left, right, loc);
3708 if (node == nullptr)
3709 {
3710 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02003711 return left;
3712 }
3713 return node;
3714}
3715
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02003716TIntermTyped *TParseContext::addComma(TIntermTyped *left,
3717 TIntermTyped *right,
3718 const TSourceLoc &loc)
3719{
Corentin Wallez0d959252016-07-12 17:26:32 -04003720 // WebGL2 section 5.26, the following results in an error:
3721 // "Sequence operator applied to void, arrays, or structs containing arrays"
3722 if (mShaderSpec == SH_WEBGL2_SPEC && (left->isArray() || left->getBasicType() == EbtVoid ||
3723 left->getType().isStructureContainingArrays() ||
3724 right->isArray() || right->getBasicType() == EbtVoid ||
3725 right->getType().isStructureContainingArrays()))
3726 {
3727 error(loc,
3728 "sequence operator is not allowed for void, arrays, or structs containing arrays",
3729 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04003730 }
3731
Olli Etuaho15200042015-11-04 16:56:31 +02003732 return intermediate.addComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02003733}
3734
Olli Etuaho49300862015-02-20 14:54:49 +02003735TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
3736{
3737 switch (op)
3738 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003739 case EOpContinue:
3740 if (mLoopNestingLevel <= 0)
3741 {
3742 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003743 }
3744 break;
3745 case EOpBreak:
3746 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
3747 {
3748 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003749 }
3750 break;
3751 case EOpReturn:
3752 if (mCurrentFunctionType->getBasicType() != EbtVoid)
3753 {
3754 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003755 }
3756 break;
3757 default:
3758 // No checks for discard
3759 break;
Olli Etuaho49300862015-02-20 14:54:49 +02003760 }
3761 return intermediate.addBranch(op, loc);
3762}
3763
Jamie Madillb98c3a82015-07-23 14:26:04 -04003764TIntermBranch *TParseContext::addBranch(TOperator op,
3765 TIntermTyped *returnValue,
3766 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02003767{
3768 ASSERT(op == EOpReturn);
3769 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003770 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02003771 {
3772 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02003773 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003774 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02003775 {
3776 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02003777 }
3778 return intermediate.addBranch(op, returnValue, loc);
3779}
3780
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003781void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
3782{
3783 ASSERT(!functionCall->isUserDefined());
3784 const TString &name = functionCall->getName();
3785 TIntermNode *offset = nullptr;
3786 TIntermSequence *arguments = functionCall->getSequence();
3787 if (name.compare(0, 16, "texelFetchOffset") == 0 ||
3788 name.compare(0, 16, "textureLodOffset") == 0 ||
3789 name.compare(0, 20, "textureProjLodOffset") == 0 ||
3790 name.compare(0, 17, "textureGradOffset") == 0 ||
3791 name.compare(0, 21, "textureProjGradOffset") == 0)
3792 {
3793 offset = arguments->back();
3794 }
3795 else if (name.compare(0, 13, "textureOffset") == 0 ||
3796 name.compare(0, 17, "textureProjOffset") == 0)
3797 {
3798 // A bias parameter might follow the offset parameter.
3799 ASSERT(arguments->size() >= 3);
3800 offset = (*arguments)[2];
3801 }
3802 if (offset != nullptr)
3803 {
3804 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
3805 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
3806 {
3807 TString unmangledName = TFunction::unmangleName(name);
3808 error(functionCall->getLine(), "Texture offset must be a constant expression",
3809 unmangledName.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003810 }
3811 else
3812 {
3813 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
3814 size_t size = offsetConstantUnion->getType().getObjectSize();
3815 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
3816 for (size_t i = 0u; i < size; ++i)
3817 {
3818 int offsetValue = values[i].getIConst();
3819 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
3820 {
3821 std::stringstream tokenStream;
3822 tokenStream << offsetValue;
3823 std::string token = tokenStream.str();
3824 error(offset->getLine(), "Texture offset value out of valid range",
3825 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003826 }
3827 }
3828 }
3829 }
3830}
3831
Jamie Madillb98c3a82015-07-23 14:26:04 -04003832TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
3833 TIntermNode *paramNode,
3834 TIntermNode *thisNode,
3835 const TSourceLoc &loc,
3836 bool *fatalError)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003837{
Jamie Madillb98c3a82015-07-23 14:26:04 -04003838 *fatalError = false;
3839 TOperator op = fnCall->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003840 TIntermTyped *callNode = nullptr;
3841
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003842 if (thisNode != nullptr)
3843 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003844 TConstantUnion *unionArray = new TConstantUnion[1];
Jamie Madillb98c3a82015-07-23 14:26:04 -04003845 int arraySize = 0;
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003846 TIntermTyped *typedThis = thisNode->getAsTyped();
3847 if (fnCall->getName() != "length")
3848 {
3849 error(loc, "invalid method", fnCall->getName().c_str());
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003850 }
3851 else if (paramNode != nullptr)
3852 {
3853 error(loc, "method takes no parameters", "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003854 }
3855 else if (typedThis == nullptr || !typedThis->isArray())
3856 {
3857 error(loc, "length can only be called on arrays", "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003858 }
3859 else
3860 {
Olli Etuaho96e67382015-04-23 14:27:02 +03003861 arraySize = typedThis->getArraySize();
Olli Etuaho39282e12015-04-23 15:41:48 +03003862 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003863 {
Olli Etuaho39282e12015-04-23 15:41:48 +03003864 // This code path can be hit with expressions like these:
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003865 // (a = b).length()
Olli Etuaho39282e12015-04-23 15:41:48 +03003866 // (func()).length()
3867 // (int[3](0, 1, 2)).length()
Jamie Madillb98c3a82015-07-23 14:26:04 -04003868 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
3869 // expression.
3870 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
3871 // spec section 5.9 which allows "An array, vector or matrix expression with the
3872 // length method applied".
3873 error(loc, "length can only be called on array names, not on array expressions",
3874 "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003875 }
3876 }
Olli Etuaho96e67382015-04-23 14:27:02 +03003877 unionArray->setIConst(arraySize);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003878 callNode =
3879 intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003880 }
3881 else if (op != EOpNull)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003882 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003883 // Then this should be a constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +03003884 callNode = addConstructor(paramNode, op, fnCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003885 }
3886 else
3887 {
3888 //
3889 // Not a constructor. Find it in the symbol table.
3890 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303891 const TFunction *fnCandidate;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003892 bool builtIn;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003893 fnCandidate = findFunction(loc, fnCall, mShaderVersion, &builtIn);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003894 if (fnCandidate)
3895 {
3896 //
3897 // A declared function.
3898 //
Olli Etuaho383b7912016-08-05 11:22:59 +03003899 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003900 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003901 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003902 }
3903 op = fnCandidate->getBuiltInOp();
3904 if (builtIn && op != EOpNull)
3905 {
3906 //
3907 // A function call mapped to a built-in operation.
3908 //
3909 if (fnCandidate->getParamCount() == 1)
3910 {
3911 //
3912 // Treat it like a built-in unary operator.
3913 //
Olli Etuaho15c2ac32015-11-09 15:51:43 +02003914 TIntermAggregate *paramAgg = paramNode->getAsAggregate();
3915 paramNode = paramAgg->getSequence()->front();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003916 callNode = createUnaryMath(op, paramNode->getAsTyped(), loc,
3917 &fnCandidate->getReturnType());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003918 if (callNode == nullptr)
3919 {
3920 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003921 extraInfoStream
3922 << "built in unary operator function. Type: "
3923 << static_cast<TIntermTyped *>(paramNode)->getCompleteString();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003924 std::string extraInfo = extraInfoStream.str();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003925 error(paramNode->getLine(), " wrong operand type", "Internal Error",
3926 extraInfo.c_str());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003927 *fatalError = true;
3928 return nullptr;
3929 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003930 }
3931 else
3932 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003933 TIntermAggregate *aggregate =
3934 intermediate.setAggregateOperator(paramNode, op, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003935 aggregate->setType(fnCandidate->getReturnType());
3936 aggregate->setPrecisionFromChildren();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02003937 if (aggregate->areChildrenConstQualified())
3938 {
3939 aggregate->getTypePointer()->setQualifier(EvqConst);
3940 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003941
3942 // Some built-in functions have out parameters too.
3943 functionCallLValueErrorCheck(fnCandidate, aggregate);
Arun Patole274f0702015-05-05 13:33:30 +05303944
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003945 // See if we can constant fold a built-in. Note that this may be possible even
3946 // if it is not const-qualified.
Olli Etuahob43846e2015-06-02 18:18:57 +03003947 TIntermTyped *foldedNode = intermediate.foldAggregateBuiltIn(aggregate);
Arun Patole274f0702015-05-05 13:33:30 +05303948 if (foldedNode)
3949 {
Arun Patole274f0702015-05-05 13:33:30 +05303950 callNode = foldedNode;
3951 }
Olli Etuahob43846e2015-06-02 18:18:57 +03003952 else
3953 {
3954 callNode = aggregate;
3955 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003956 }
3957 }
3958 else
3959 {
3960 // This is a real function call
Jamie Madillb98c3a82015-07-23 14:26:04 -04003961 TIntermAggregate *aggregate =
3962 intermediate.setAggregateOperator(paramNode, EOpFunctionCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003963 aggregate->setType(fnCandidate->getReturnType());
3964
Jamie Madillb98c3a82015-07-23 14:26:04 -04003965 // this is how we know whether the given function is a builtIn function or a user
3966 // defined function
3967 // if builtIn == false, it's a userDefined -> could be an overloaded
3968 // builtIn function also
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003969 // if builtIn == true, it's definitely a builtIn function with EOpNull
3970 if (!builtIn)
3971 aggregate->setUserDefined();
3972 aggregate->setName(fnCandidate->getMangledName());
Corentin Wallez71d147f2015-02-11 11:15:24 -08003973 aggregate->setFunctionId(fnCandidate->getUniqueId());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003974
3975 // This needs to happen after the name is set
3976 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003977 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003978 aggregate->setBuiltInFunctionPrecision();
3979
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003980 checkTextureOffsetConst(aggregate);
3981 }
3982
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003983 callNode = aggregate;
3984
3985 functionCallLValueErrorCheck(fnCandidate, aggregate);
3986 }
3987 }
3988 else
3989 {
3990 // error message was put out by findFunction()
3991 // Put on a dummy node for error recovery
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003992 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003993 unionArray->setFConst(0.0f);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003994 callNode = intermediate.addConstantUnion(unionArray,
3995 TType(EbtFloat, EbpUndefined, EvqConst), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003996 }
3997 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003998 return callNode;
3999}
4000
Jamie Madillb98c3a82015-07-23 14:26:04 -04004001TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
4002 TIntermTyped *trueBlock,
4003 TIntermTyped *falseBlock,
Olli Etuaho52901742015-04-15 13:42:45 +03004004 const TSourceLoc &loc)
4005{
Olli Etuaho856c4972016-08-08 11:38:39 +03004006 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03004007
4008 if (trueBlock->getType() != falseBlock->getType())
4009 {
4010 binaryOpError(loc, ":", trueBlock->getCompleteString(), falseBlock->getCompleteString());
Olli Etuaho52901742015-04-15 13:42:45 +03004011 return falseBlock;
4012 }
Olli Etuahoa2d53032015-04-15 14:14:44 +03004013 // ESSL1 sections 5.2 and 5.7:
4014 // ESSL3 section 5.7:
4015 // Ternary operator is not among the operators allowed for structures/arrays.
4016 if (trueBlock->isArray() || trueBlock->getBasicType() == EbtStruct)
4017 {
4018 error(loc, "ternary operator is not allowed for structures or arrays", ":");
Olli Etuahoa2d53032015-04-15 14:14:44 +03004019 return falseBlock;
4020 }
Corentin Wallez0d959252016-07-12 17:26:32 -04004021 // WebGL2 section 5.26, the following results in an error:
4022 // "Ternary operator applied to void, arrays, or structs containing arrays"
4023 if (mShaderSpec == SH_WEBGL2_SPEC && trueBlock->getBasicType() == EbtVoid)
4024 {
4025 error(loc, "ternary operator is not allowed for void", ":");
Corentin Wallez0d959252016-07-12 17:26:32 -04004026 return falseBlock;
4027 }
4028
Olli Etuaho52901742015-04-15 13:42:45 +03004029 return intermediate.addSelection(cond, trueBlock, falseBlock, loc);
4030}
Olli Etuaho49300862015-02-20 14:54:49 +02004031
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004032//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004033// Parse an array of strings using yyparse.
4034//
4035// Returns 0 for success.
4036//
Jamie Madillb98c3a82015-07-23 14:26:04 -04004037int PaParseStrings(size_t count,
4038 const char *const string[],
4039 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05304040 TParseContext *context)
4041{
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004042 if ((count == 0) || (string == NULL))
4043 return 1;
4044
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004045 if (glslang_initialize(context))
4046 return 1;
4047
alokp@chromium.org408c45e2012-04-05 15:54:43 +00004048 int error = glslang_scan(count, string, length, context);
4049 if (!error)
4050 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004051
alokp@chromium.org73bc2982012-06-19 18:48:05 +00004052 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00004053
alokp@chromium.org6b495712012-06-29 00:06:58 +00004054 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004055}