blob: 5a79d2a19ef9fb387e05612860ad4afb31fbf740 [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.
Olli Etuaho856c4972016-08-08 11:38:39 +0300413void 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);
418 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000419}
420
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000421// For now, keep it simple: if it starts "gl_", it's reserved, independent
422// of scope. Except, if the symbol table is at the built-in push-level,
423// which is when we are parsing built-ins.
alokp@chromium.org613ef312010-07-21 18:54:22 +0000424// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
425// webgl shader.
Olli Etuaho856c4972016-08-08 11:38:39 +0300426bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000427{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530428 static const char *reservedErrMsg = "reserved built-in name";
429 if (!symbolTable.atBuiltInLevel())
430 {
431 if (identifier.compare(0, 3, "gl_") == 0)
432 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000433 error(line, reservedErrMsg, "gl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300434 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000435 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530436 if (IsWebGLBasedSpec(mShaderSpec))
437 {
438 if (identifier.compare(0, 6, "webgl_") == 0)
439 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000440 error(line, reservedErrMsg, "webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300441 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000442 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530443 if (identifier.compare(0, 7, "_webgl_") == 0)
444 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000445 error(line, reservedErrMsg, "_webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300446 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000447 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530448 if (mShaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0)
449 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000450 error(line, reservedErrMsg, "css_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300451 return false;
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +0000452 }
alokp@chromium.org613ef312010-07-21 18:54:22 +0000453 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530454 if (identifier.find("__") != TString::npos)
455 {
456 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400457 "identifiers containing two consecutive underscores (__) are reserved as "
458 "possible future keywords",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530459 identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300460 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000461 }
462 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000463
Olli Etuaho8a176262016-08-16 14:23:01 +0300464 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000465}
466
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000467// Make sure there is enough data provided to the constructor to build
468// something of the type of the constructor. Also returns the type of
469// the constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +0300470bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
471 TIntermNode *argumentsNode,
472 const TFunction &function,
473 TOperator op,
474 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000475{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000476 bool constructingMatrix = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400477 switch (op)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530478 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400479 case EOpConstructMat2:
480 case EOpConstructMat2x3:
481 case EOpConstructMat2x4:
482 case EOpConstructMat3x2:
483 case EOpConstructMat3:
484 case EOpConstructMat3x4:
485 case EOpConstructMat4x2:
486 case EOpConstructMat4x3:
487 case EOpConstructMat4:
488 constructingMatrix = true;
489 break;
490 default:
491 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000492 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000493
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000494 //
495 // Note: It's okay to have too many components available, but not okay to have unused
496 // arguments. 'full' will go to true when enough args have been seen. If we loop
497 // again, there is an extra argument, so 'overfull' will become true.
498 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000499
Jamie Madillb98c3a82015-07-23 14:26:04 -0400500 size_t size = 0;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400501 bool full = false;
502 bool overFull = false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000503 bool matrixInMatrix = false;
504 bool arrayArg = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530505 for (size_t i = 0; i < function.getParamCount(); ++i)
506 {
Dmitry Skibaefa3d8e2015-06-22 14:52:10 -0700507 const TConstParameter &param = function.getParam(i);
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000508 size += param.type->getObjectSize();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530509
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000510 if (constructingMatrix && param.type->isMatrix())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000511 matrixInMatrix = true;
512 if (full)
513 overFull = true;
Olli Etuaho856c4972016-08-08 11:38:39 +0300514 if (op != EOpConstructStruct && !type.isArray() && size >= type.getObjectSize())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000515 full = true;
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000516 if (param.type->isArray())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000517 arrayArg = true;
518 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530519
Olli Etuaho856c4972016-08-08 11:38:39 +0300520 if (type.isArray())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300521 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300522 // The size of an unsized constructor should already have been determined.
523 ASSERT(!type.isUnsizedArray());
524 if (static_cast<size_t>(type.getArraySize()) != function.getParamCount())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300525 {
526 error(line, "array constructor needs one argument per array element", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300527 return false;
Olli Etuaho376f1b52015-04-13 13:23:41 +0300528 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000529 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000530
Arun Patole7e7e68d2015-05-22 12:02:25 +0530531 if (arrayArg && op != EOpConstructStruct)
532 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000533 error(line, "constructing from a non-dereferenced array", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300534 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000535 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000536
Olli Etuaho856c4972016-08-08 11:38:39 +0300537 if (matrixInMatrix && !type.isArray())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530538 {
539 if (function.getParamCount() != 1)
540 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400541 error(line, "constructing matrix from matrix can only take one argument",
542 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300543 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000544 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000545 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000546
Arun Patole7e7e68d2015-05-22 12:02:25 +0530547 if (overFull)
548 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000549 error(line, "too many arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300550 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000551 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530552
Olli Etuaho856c4972016-08-08 11:38:39 +0300553 if (op == EOpConstructStruct && !type.isArray() &&
554 type.getStruct()->fields().size() != function.getParamCount())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530555 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400556 error(line,
557 "Number of constructor parameters does not match the number of structure fields",
558 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300559 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000560 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000561
Olli Etuaho856c4972016-08-08 11:38:39 +0300562 if (!type.isMatrix() || !matrixInMatrix)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530563 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300564 if ((op != EOpConstructStruct && size != 1 && size < type.getObjectSize()) ||
565 (op == EOpConstructStruct && size < type.getObjectSize()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530566 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000567 error(line, "not enough data provided for construction", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300568 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000569 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000570 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000571
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200572 if (argumentsNode == nullptr)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530573 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200574 error(line, "constructor does not have any arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300575 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000576 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200577
578 TIntermAggregate *argumentsAgg = argumentsNode->getAsAggregate();
579 for (TIntermNode *&argNode : *argumentsAgg->getSequence())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530580 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200581 TIntermTyped *argTyped = argNode->getAsTyped();
582 ASSERT(argTyped != nullptr);
583 if (op != EOpConstructStruct && IsSampler(argTyped->getBasicType()))
584 {
585 error(line, "cannot convert a sampler", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300586 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200587 }
588 if (argTyped->getBasicType() == EbtVoid)
589 {
590 error(line, "cannot convert a void", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300591 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200592 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000593 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000594
Olli Etuaho856c4972016-08-08 11:38:39 +0300595 if (type.isArray())
596 {
597 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
598 // the array.
599 for (TIntermNode *&argNode : *argumentsAgg->getSequence())
600 {
601 const TType &argType = argNode->getAsTyped()->getType();
602 // It has already been checked that the argument is not an array.
603 ASSERT(!argType.isArray());
604 if (!argType.sameElementType(type))
605 {
606 error(line, "Array constructor argument has an incorrect type", "Error");
Olli Etuaho8a176262016-08-16 14:23:01 +0300607 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300608 }
609 }
610 }
611 else if (op == EOpConstructStruct)
612 {
613 const TFieldList &fields = type.getStruct()->fields();
614 TIntermSequence *args = argumentsAgg->getSequence();
615
616 for (size_t i = 0; i < fields.size(); i++)
617 {
618 if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type())
619 {
620 error(line, "Structure constructor arguments do not match structure fields",
621 "Error");
Olli Etuaho8a176262016-08-16 14:23:01 +0300622 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300623 }
624 }
625 }
626
Olli Etuaho8a176262016-08-16 14:23:01 +0300627 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000628}
629
Jamie Madillb98c3a82015-07-23 14:26:04 -0400630// This function checks to see if a void variable has been declared and raise an error message for
631// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000632//
633// returns true in case of an error
634//
Olli Etuaho856c4972016-08-08 11:38:39 +0300635bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400636 const TString &identifier,
637 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000638{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300639 if (type == EbtVoid)
640 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000641 error(line, "illegal use of type 'void'", identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300642 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300643 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000644
Olli Etuaho8a176262016-08-16 14:23:01 +0300645 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000646}
647
Jamie Madillb98c3a82015-07-23 14:26:04 -0400648// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300649// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300650void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000651{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530652 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
653 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000654 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530655 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000656}
657
Jamie Madillb98c3a82015-07-23 14:26:04 -0400658// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300659// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300660void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000661{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530662 if (pType.type != EbtBool || pType.isAggregate())
663 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000664 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530665 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000666}
667
Olli Etuaho856c4972016-08-08 11:38:39 +0300668bool TParseContext::checkIsNotSampler(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400669 const TPublicType &pType,
670 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000671{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530672 if (pType.type == EbtStruct)
673 {
674 if (containsSampler(*pType.userDef))
675 {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000676 error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
Olli Etuaho8a176262016-08-16 14:23:01 +0300677 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000678 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530679
Olli Etuaho8a176262016-08-16 14:23:01 +0300680 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530681 }
682 else if (IsSampler(pType.type))
683 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000684 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300685 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000686 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000687
Olli Etuaho8a176262016-08-16 14:23:01 +0300688 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000689}
690
Olli Etuaho856c4972016-08-08 11:38:39 +0300691void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
692 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400693{
694 if (pType.layoutQualifier.location != -1)
695 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400696 error(line, "location must only be specified for a single input or output variable",
697 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400698 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400699}
700
Olli Etuaho856c4972016-08-08 11:38:39 +0300701void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
702 const TLayoutQualifier &layoutQualifier)
703{
704 if (layoutQualifier.location != -1)
705 {
706 error(location, "invalid layout qualifier:", "location",
707 "only valid on program inputs and outputs");
708 }
709}
710
711void TParseContext::checkOutParameterIsNotSampler(const TSourceLoc &line,
712 TQualifier qualifier,
713 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000714{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400715 if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct &&
716 IsSampler(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530717 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000718 error(line, "samplers cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000719 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000720}
721
Arun Patole7e7e68d2015-05-22 12:02:25 +0530722bool TParseContext::containsSampler(const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000723{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000724 if (IsSampler(type.getBasicType()))
725 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000726
Arun Patole7e7e68d2015-05-22 12:02:25 +0530727 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock())
728 {
729 const TFieldList &fields = type.getStruct()->fields();
730 for (unsigned int i = 0; i < fields.size(); ++i)
731 {
Jamie Madill98493dd2013-07-08 14:39:03 -0400732 if (containsSampler(*fields[i]->type()))
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000733 return true;
734 }
735 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000736
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000737 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000738}
739
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000740// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300741unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000742{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530743 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000744
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200745 // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
746 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
747 // fold as array size.
748 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000749 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000750 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300751 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000752 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000753
Olli Etuaho856c4972016-08-08 11:38:39 +0300754 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400755
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000756 if (constant->getBasicType() == EbtUInt)
757 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300758 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000759 }
760 else
761 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300762 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000763
Olli Etuaho856c4972016-08-08 11:38:39 +0300764 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000765 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400766 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300767 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000768 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400769
Olli Etuaho856c4972016-08-08 11:38:39 +0300770 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -0400771 }
772
Olli Etuaho856c4972016-08-08 11:38:39 +0300773 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -0400774 {
775 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300776 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400777 }
778
779 // The size of arrays is restricted here to prevent issues further down the
780 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
781 // 4096 registers so this should be reasonable even for aggressively optimizable code.
782 const unsigned int sizeLimit = 65536;
783
Olli Etuaho856c4972016-08-08 11:38:39 +0300784 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -0400785 {
786 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300787 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000788 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300789
790 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000791}
792
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000793// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +0300794bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
795 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000796{
Olli Etuaho8a176262016-08-16 14:23:01 +0300797 if ((elementQualifier.qualifier == EvqAttribute) ||
798 (elementQualifier.qualifier == EvqVertexIn) ||
799 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +0300800 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400801 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300802 TType(elementQualifier).getQualifierString());
803 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000804 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000805
Olli Etuaho8a176262016-08-16 14:23:01 +0300806 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000807}
808
Olli Etuaho8a176262016-08-16 14:23:01 +0300809// See if this element type can be formed into an array.
810bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000811{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000812 //
813 // Can the type be an array?
814 //
Olli Etuaho8a176262016-08-16 14:23:01 +0300815 if (elementType.array)
Jamie Madill06145232015-05-13 13:10:01 -0400816 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300817 error(line, "cannot declare arrays of arrays",
818 TType(elementType).getCompleteString().c_str());
819 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000820 }
Olli Etuahocc36b982015-07-10 14:14:18 +0300821 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
822 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
823 // 4.3.4).
Olli Etuaho8a176262016-08-16 14:23:01 +0300824 if (mShaderVersion >= 300 && elementType.type == EbtStruct &&
825 sh::IsVarying(elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +0300826 {
827 error(line, "cannot declare arrays of structs of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300828 TType(elementType).getCompleteString().c_str());
829 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +0300830 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000831
Olli Etuaho8a176262016-08-16 14:23:01 +0300832 return true;
833}
834
835// Check if this qualified element type can be formed into an array.
836bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
837 const TPublicType &elementType)
838{
839 if (checkIsValidTypeForArray(indexLocation, elementType))
840 {
841 return checkIsValidQualifierForArray(indexLocation, elementType);
842 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000843 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000844}
845
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000846// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +0300847void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
848 const TString &identifier,
849 TPublicType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000850{
Olli Etuaho3739d232015-04-08 12:23:44 +0300851 ASSERT(type != nullptr);
852 if (type->qualifier == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000853 {
854 // Make the qualifier make sense.
Olli Etuaho3739d232015-04-08 12:23:44 +0300855 type->qualifier = EvqTemporary;
856
857 // Generate informative error messages for ESSL1.
858 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400859 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000860 {
Arun Patole7e7e68d2015-05-22 12:02:25 +0530861 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400862 "structures containing arrays may not be declared constant since they cannot be "
863 "initialized",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530864 identifier.c_str());
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000865 }
866 else
867 {
868 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
869 }
Olli Etuaho383b7912016-08-05 11:22:59 +0300870 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000871 }
Olli Etuaho376f1b52015-04-13 13:23:41 +0300872 if (type->isUnsizedArray())
873 {
874 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
Olli Etuaho376f1b52015-04-13 13:23:41 +0300875 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000876}
877
Olli Etuaho2935c582015-04-08 14:32:06 +0300878// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000879// and update the symbol table.
880//
Olli Etuaho2935c582015-04-08 14:32:06 +0300881// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000882//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400883bool TParseContext::declareVariable(const TSourceLoc &line,
884 const TString &identifier,
885 const TType &type,
Olli Etuaho2935c582015-04-08 14:32:06 +0300886 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000887{
Olli Etuaho2935c582015-04-08 14:32:06 +0300888 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000889
Olli Etuaho856c4972016-08-08 11:38:39 +0300890 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000891
Olli Etuaho2935c582015-04-08 14:32:06 +0300892 // gl_LastFragData may be redeclared with a new precision qualifier
893 if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
894 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400895 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
896 symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Olli Etuaho856c4972016-08-08 11:38:39 +0300897 if (static_cast<int>(type.getArraySize()) == maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +0300898 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400899 if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +0300900 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300901 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
Olli Etuaho2935c582015-04-08 14:32:06 +0300902 }
903 }
904 else
905 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400906 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
907 identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +0300908 return false;
909 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000910 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000911
Olli Etuaho8a176262016-08-16 14:23:01 +0300912 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +0300913 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000914
Olli Etuaho2935c582015-04-08 14:32:06 +0300915 (*variable) = new TVariable(&identifier, type);
916 if (!symbolTable.declare(*variable))
917 {
918 error(line, "redefinition", identifier.c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -0400919 *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +0300920 return false;
921 }
922
Olli Etuaho8a176262016-08-16 14:23:01 +0300923 if (!checkIsNonVoid(line, identifier, type.getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +0300924 return false;
925
926 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000927}
928
Olli Etuaho856c4972016-08-08 11:38:39 +0300929void TParseContext::checkIsParameterQualifierValid(const TSourceLoc &line,
930 TQualifier qualifier,
931 TQualifier paramQualifier,
932 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530933{
934 if (qualifier != EvqConst && qualifier != EvqTemporary)
935 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000936 error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +0300937 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000938 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530939 if (qualifier == EvqConst && paramQualifier != EvqIn)
940 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400941 error(line, "qualifier not allowed with ", getQualifierString(qualifier),
942 getQualifierString(paramQualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +0300943 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000944 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000945
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000946 if (qualifier == EvqConst)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000947 type->setQualifier(EvqConstReadOnly);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000948 else
alokp@chromium.org58e54292010-08-24 21:40:03 +0000949 type->setQualifier(paramQualifier);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000950}
951
Olli Etuaho856c4972016-08-08 11:38:39 +0300952bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000953{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400954 const TExtensionBehavior &extBehavior = extensionBehavior();
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000955 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
Arun Patole7e7e68d2015-05-22 12:02:25 +0530956 if (iter == extBehavior.end())
957 {
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000958 error(line, "extension", extension.c_str(), "is not supported");
Olli Etuaho8a176262016-08-16 14:23:01 +0300959 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000960 }
zmo@google.comf5450912011-09-09 01:37:19 +0000961 // In GLSL ES, an extension's default behavior is "disable".
Arun Patole7e7e68d2015-05-22 12:02:25 +0530962 if (iter->second == EBhDisable || iter->second == EBhUndefined)
963 {
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000964 error(line, "extension", extension.c_str(), "is disabled");
Olli Etuaho8a176262016-08-16 14:23:01 +0300965 return false;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000966 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530967 if (iter->second == EBhWarn)
968 {
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000969 warning(line, "extension", extension.c_str(), "is being used");
Olli Etuaho8a176262016-08-16 14:23:01 +0300970 return true;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000971 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000972
Olli Etuaho8a176262016-08-16 14:23:01 +0300973 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000974}
975
Jamie Madillb98c3a82015-07-23 14:26:04 -0400976// These checks are common for all declarations starting a declarator list, and declarators that
977// follow an empty declaration.
Olli Etuaho383b7912016-08-05 11:22:59 +0300978void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400979 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -0400980{
Olli Etuahofa33d582015-04-09 14:33:12 +0300981 switch (publicType.qualifier)
982 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400983 case EvqVaryingIn:
984 case EvqVaryingOut:
985 case EvqAttribute:
986 case EvqVertexIn:
987 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +0300988 case EvqComputeIn:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400989 if (publicType.type == EbtStruct)
990 {
991 error(identifierLocation, "cannot be used with a structure",
992 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +0300993 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400994 }
Olli Etuahofa33d582015-04-09 14:33:12 +0300995
Jamie Madillb98c3a82015-07-23 14:26:04 -0400996 default:
997 break;
Olli Etuahofa33d582015-04-09 14:33:12 +0300998 }
999
Jamie Madillb98c3a82015-07-23 14:26:04 -04001000 if (publicType.qualifier != EvqUniform &&
Olli Etuaho8a176262016-08-16 14:23:01 +03001001 !checkIsNotSampler(identifierLocation, publicType, "samplers must be uniform"))
Olli Etuahofa33d582015-04-09 14:33:12 +03001002 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001003 return;
Olli Etuahofa33d582015-04-09 14:33:12 +03001004 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001005
1006 // check for layout qualifier issues
1007 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
1008
1009 if (layoutQualifier.matrixPacking != EmpUnspecified)
1010 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001011 error(identifierLocation, "layout qualifier",
1012 getMatrixPackingString(layoutQualifier.matrixPacking),
Olli Etuahofa33d582015-04-09 14:33:12 +03001013 "only valid for interface blocks");
Olli Etuaho383b7912016-08-05 11:22:59 +03001014 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001015 }
1016
1017 if (layoutQualifier.blockStorage != EbsUnspecified)
1018 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001019 error(identifierLocation, "layout qualifier",
1020 getBlockStorageString(layoutQualifier.blockStorage),
Olli Etuahofa33d582015-04-09 14:33:12 +03001021 "only valid for interface blocks");
Olli Etuaho383b7912016-08-05 11:22:59 +03001022 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001023 }
1024
Olli Etuaho383b7912016-08-05 11:22:59 +03001025 if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut)
Jamie Madilla5efff92013-06-06 11:56:47 -04001026 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001027 checkLocationIsNotSpecified(identifierLocation, publicType.layoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04001028 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001029}
1030
Olli Etuaho856c4972016-08-08 11:38:39 +03001031void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1032 const TString &layoutQualifierName,
1033 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001034{
1035
1036 if (mShaderVersion < versionRequired)
1037 {
1038 error(location, "invalid layout qualifier:", layoutQualifierName.c_str(), "not supported");
Martin Radev802abe02016-08-04 17:48:32 +03001039 }
1040}
1041
Olli Etuaho856c4972016-08-08 11:38:39 +03001042bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1043 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001044{
1045 const TLocalSize &localSize = layoutQualifier.localSize;
1046 for (size_t i = 0u; i < localSize.size(); ++i)
1047 {
1048 if (localSize[i] != -1)
1049 {
1050 error(location, "invalid layout qualifier:", getLocalSizeString(i),
1051 "only valid when used with 'in' in a compute shader global layout declaration");
Olli Etuaho8a176262016-08-16 14:23:01 +03001052 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001053 }
1054 }
1055
Olli Etuaho8a176262016-08-16 14:23:01 +03001056 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001057}
1058
Olli Etuaho383b7912016-08-05 11:22:59 +03001059void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
Olli Etuaho856c4972016-08-08 11:38:39 +03001060 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001061{
1062 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1063 {
1064 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1065 if (qual == EvqOut || qual == EvqInOut)
1066 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001067 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho8a176262016-08-16 14:23:01 +03001068 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001069 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001070 error(argument->getLine(),
Jamie Madillb98c3a82015-07-23 14:26:04 -04001071 "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
Olli Etuaho383b7912016-08-05 11:22:59 +03001072 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001073 }
1074 }
1075 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001076}
1077
Olli Etuaho856c4972016-08-08 11:38:39 +03001078void TParseContext::checkInvariantIsOutVariableES3(const TQualifier qualifier,
1079 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001080{
1081 if (!sh::IsVaryingOut(qualifier) && qualifier != EvqFragmentOut)
1082 {
1083 error(invariantLocation, "Only out variables can be invariant.", "invariant");
Olli Etuaho37ad4742015-04-27 13:18:50 +03001084 }
1085}
1086
Arun Patole7e7e68d2015-05-22 12:02:25 +05301087bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001088{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001089 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001090 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1091 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001092}
1093
Arun Patole7e7e68d2015-05-22 12:02:25 +05301094bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001095{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001096 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001097}
1098
Jamie Madillb98c3a82015-07-23 14:26:04 -04001099void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1100 const char *extName,
1101 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001102{
1103 pp::SourceLocation srcLoc;
1104 srcLoc.file = loc.first_file;
1105 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001106 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001107}
1108
Jamie Madillb98c3a82015-07-23 14:26:04 -04001109void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1110 const char *name,
1111 const char *value,
1112 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001113{
1114 pp::SourceLocation srcLoc;
1115 srcLoc.file = loc.first_file;
1116 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001117 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001118}
1119
Martin Radev802abe02016-08-04 17:48:32 +03001120TLocalSize TParseContext::getComputeShaderLocalSize() const
1121{
1122 TLocalSize result;
1123 for (size_t i = 0u; i < result.size(); ++i)
1124 {
1125 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1126 {
1127 result[i] = 1;
1128 }
1129 else
1130 {
1131 result[i] = mComputeShaderLocalSize[i];
1132 }
1133 }
1134 return result;
1135}
1136
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001137/////////////////////////////////////////////////////////////////////////////////
1138//
1139// Non-Errors.
1140//
1141/////////////////////////////////////////////////////////////////////////////////
1142
Jamie Madill5c097022014-08-20 16:38:32 -04001143const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1144 const TString *name,
1145 const TSymbol *symbol)
1146{
1147 const TVariable *variable = NULL;
1148
1149 if (!symbol)
1150 {
1151 error(location, "undeclared identifier", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001152 }
1153 else if (!symbol->isVariable())
1154 {
1155 error(location, "variable expected", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001156 }
1157 else
1158 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001159 variable = static_cast<const TVariable *>(symbol);
Jamie Madill5c097022014-08-20 16:38:32 -04001160
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001161 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
Olli Etuaho383b7912016-08-05 11:22:59 +03001162 !variable->getExtension().empty())
Jamie Madill5c097022014-08-20 16:38:32 -04001163 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001164 checkCanUseExtension(location, variable->getExtension());
Jamie Madill5c097022014-08-20 16:38:32 -04001165 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001166
1167 // Reject shaders using both gl_FragData and gl_FragColor
1168 TQualifier qualifier = variable->getType().getQualifier();
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001169 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001170 {
1171 mUsesFragData = true;
1172 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001173 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001174 {
1175 mUsesFragColor = true;
1176 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001177 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1178 {
1179 mUsesSecondaryOutputs = true;
1180 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001181
1182 // This validation is not quite correct - it's only an error to write to
1183 // both FragData and FragColor. For simplicity, and because users shouldn't
1184 // be rewarded for reading from undefined varaibles, return an error
1185 // if they are both referenced, rather than assigned.
1186 if (mUsesFragData && mUsesFragColor)
1187 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001188 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1189 if (mUsesSecondaryOutputs)
1190 {
1191 errorMessage =
1192 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1193 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1194 }
1195 error(location, errorMessage, name->c_str());
Jamie Madill14e95b32015-05-07 10:10:41 -04001196 }
Martin Radevb0883602016-08-04 17:48:58 +03001197
1198 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1199 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1200 qualifier == EvqWorkGroupSize)
1201 {
1202 error(location,
1203 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1204 "gl_WorkGroupSize");
1205 }
Jamie Madill5c097022014-08-20 16:38:32 -04001206 }
1207
1208 if (!variable)
1209 {
1210 TType type(EbtFloat, EbpUndefined);
1211 TVariable *fakeVariable = new TVariable(name, type);
1212 symbolTable.declare(fakeVariable);
1213 variable = fakeVariable;
1214 }
1215
1216 return variable;
1217}
1218
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001219TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1220 const TString *name,
1221 const TSymbol *symbol)
1222{
1223 const TVariable *variable = getNamedVariable(location, name, symbol);
1224
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001225 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001226 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001227 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001228 return intermediate.addConstantUnion(constArray, variable->getType(), location);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001229 }
1230 else
1231 {
1232 return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
1233 variable->getType(), location);
1234 }
1235}
1236
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001237//
1238// Look up a function name in the symbol table, and make sure it is a function.
1239//
1240// Return the function symbol if found, otherwise 0.
1241//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001242const TFunction *TParseContext::findFunction(const TSourceLoc &line,
1243 TFunction *call,
1244 int inputShaderVersion,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301245 bool *builtIn)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001246{
alokp@chromium.org0a576182010-08-09 17:16:27 +00001247 // First find by unmangled name to check whether the function name has been
1248 // hidden by a variable name or struct typename.
Nicolas Capensd4a9b8d2013-07-18 11:01:22 -04001249 // If a function is found, check for one with a matching argument list.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301250 const TSymbol *symbol = symbolTable.find(call->getName(), inputShaderVersion, builtIn);
1251 if (symbol == 0 || symbol->isFunction())
1252 {
Austin Kinross3ae64652015-01-26 15:51:39 -08001253 symbol = symbolTable.find(call->getMangledName(), inputShaderVersion, builtIn);
alokp@chromium.org0a576182010-08-09 17:16:27 +00001254 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001255
Arun Patole7e7e68d2015-05-22 12:02:25 +05301256 if (symbol == 0)
1257 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001258 error(line, "no matching overloaded function found", call->getName().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001259 return 0;
1260 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001261
Arun Patole7e7e68d2015-05-22 12:02:25 +05301262 if (!symbol->isFunction())
1263 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001264 error(line, "function name expected", call->getName().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001265 return 0;
1266 }
alokp@chromium.org0a576182010-08-09 17:16:27 +00001267
Jamie Madillb98c3a82015-07-23 14:26:04 -04001268 return static_cast<const TFunction *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001269}
1270
1271//
1272// Initializers show up in several places in the grammar. Have one set of
1273// code to handle them here.
1274//
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001275// Returns true on error, false if no error
1276//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001277bool TParseContext::executeInitializer(const TSourceLoc &line,
1278 const TString &identifier,
1279 const TPublicType &pType,
1280 TIntermTyped *initializer,
1281 TIntermNode **intermNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001282{
Olli Etuahoe7847b02015-03-16 11:56:12 +02001283 ASSERT(intermNode != nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001284 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001285
Olli Etuaho2935c582015-04-08 14:32:06 +03001286 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001287 if (type.isUnsizedArray())
1288 {
1289 type.setArraySize(initializer->getArraySize());
1290 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001291 if (!declareVariable(line, identifier, type, &variable))
1292 {
1293 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001294 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001295
Olli Etuahob0c645e2015-05-12 14:25:36 +03001296 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001297 if (symbolTable.atGlobalLevel() &&
1298 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001299 {
1300 // Error message does not completely match behavior with ESSL 1.00, but
1301 // we want to steer developers towards only using constant expressions.
1302 error(line, "global variable initializers must be constant expressions", "=");
1303 return true;
1304 }
1305 if (globalInitWarning)
1306 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001307 warning(
1308 line,
1309 "global variable initializers should be constant expressions "
1310 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1311 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001312 }
1313
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001314 //
1315 // identifier must be of type constant, a global, or a temporary
1316 //
1317 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301318 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1319 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001320 error(line, " cannot initialize this type of qualifier ",
1321 variable->getType().getQualifierString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001322 return true;
1323 }
1324 //
1325 // test for and propagate constant
1326 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001327
Arun Patole7e7e68d2015-05-22 12:02:25 +05301328 if (qualifier == EvqConst)
1329 {
1330 if (qualifier != initializer->getType().getQualifier())
1331 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001332 std::stringstream extraInfoStream;
1333 extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
1334 std::string extraInfo = extraInfoStream.str();
1335 error(line, " assigning non-constant to", "=", extraInfo.c_str());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001336 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001337 return true;
1338 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301339 if (type != initializer->getType())
1340 {
1341 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001342 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001343 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001344 return true;
1345 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001346
1347 // Save the constant folded value to the variable if possible. For example array
1348 // initializers are not folded, since that way copying the array literal to multiple places
1349 // in the shader is avoided.
1350 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1351 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301352 if (initializer->getAsConstantUnion())
1353 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001354 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001355 *intermNode = nullptr;
1356 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301357 }
1358 else if (initializer->getAsSymbolNode())
1359 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001360 const TSymbol *symbol =
1361 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1362 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001363
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001364 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001365 if (constArray)
1366 {
1367 variable->shareConstPointer(constArray);
1368 *intermNode = nullptr;
1369 return false;
1370 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001371 }
1372 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001373
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001374 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1375 variable->getUniqueId(), variable->getName(), variable->getType(), line);
1376 *intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1377 if (*intermNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001378 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001379 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1380 return true;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001381 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001382
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001383 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001384}
1385
Jamie Madillb98c3a82015-07-23 14:26:04 -04001386TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier,
1387 bool invariant,
1388 TLayoutQualifier layoutQualifier,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301389 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001390{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001391 TPublicType returnType = typeSpecifier;
1392 returnType.qualifier = qualifier;
1393 returnType.invariant = invariant;
Jamie Madilla5efff92013-06-06 11:56:47 -04001394 returnType.layoutQualifier = layoutQualifier;
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001395
Olli Etuaho856c4972016-08-08 11:38:39 +03001396 checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001397
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001398 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001399 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001400 if (typeSpecifier.array)
1401 {
1402 error(typeSpecifier.line, "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001403 returnType.clearArrayness();
1404 }
1405
Jamie Madillb98c3a82015-07-23 14:26:04 -04001406 if (qualifier == EvqAttribute &&
1407 (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001408 {
1409 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001410 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001411
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001412 if ((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
1413 (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
1414 {
1415 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001416 }
1417 }
1418 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001419 {
Olli Etuahoabb0c382015-07-13 12:01:12 +03001420 if (!layoutQualifier.isEmpty())
1421 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001422 checkIsAtGlobalLevel(typeSpecifier.line, "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03001423 }
Olli Etuahocc36b982015-07-10 14:14:18 +03001424 if (sh::IsVarying(qualifier) || qualifier == EvqVertexIn || qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001425 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001426 checkInputOutputTypeIsValidES3(qualifier, typeSpecifier, typeSpecifier.line);
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001427 }
Martin Radev802abe02016-08-04 17:48:32 +03001428 if (qualifier == EvqComputeIn)
1429 {
1430 error(typeSpecifier.line, "'in' can be only used to specify the local group size",
1431 "in");
Martin Radev802abe02016-08-04 17:48:32 +03001432 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001433 }
1434
1435 return returnType;
1436}
1437
Olli Etuaho856c4972016-08-08 11:38:39 +03001438void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1439 const TPublicType &type,
1440 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03001441{
1442 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
1443 if (type.type == EbtBool)
1444 {
1445 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001446 }
1447
1448 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1449 switch (qualifier)
1450 {
1451 case EvqVertexIn:
1452 // ESSL 3.00 section 4.3.4
1453 if (type.array)
1454 {
1455 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001456 }
1457 // Vertex inputs with a struct type are disallowed in singleDeclarationErrorCheck
1458 return;
1459 case EvqFragmentOut:
1460 // ESSL 3.00 section 4.3.6
1461 if (type.isMatrix())
1462 {
1463 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001464 }
1465 // Fragment outputs with a struct type are disallowed in singleDeclarationErrorCheck
1466 return;
1467 default:
1468 break;
1469 }
1470
1471 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1472 // restrictions.
1473 bool typeContainsIntegers =
1474 (type.type == EbtInt || type.type == EbtUInt || type.isStructureContainingType(EbtInt) ||
1475 type.isStructureContainingType(EbtUInt));
1476 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1477 {
1478 error(qualifierLocation, "must use 'flat' interpolation here",
1479 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001480 }
1481
1482 if (type.type == EbtStruct)
1483 {
1484 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1485 // These restrictions are only implied by the ESSL 3.00 spec, but
1486 // the ESSL 3.10 spec lists these restrictions explicitly.
1487 if (type.array)
1488 {
1489 error(qualifierLocation, "cannot be an array of structures",
1490 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001491 }
1492 if (type.isStructureContainingArrays())
1493 {
1494 error(qualifierLocation, "cannot be a structure containing an array",
1495 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001496 }
1497 if (type.isStructureContainingType(EbtStruct))
1498 {
1499 error(qualifierLocation, "cannot be a structure containing a structure",
1500 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001501 }
1502 if (type.isStructureContainingType(EbtBool))
1503 {
1504 error(qualifierLocation, "cannot be a structure containing a bool",
1505 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001506 }
1507 }
1508}
1509
Olli Etuahofa33d582015-04-09 14:33:12 +03001510TIntermAggregate *TParseContext::parseSingleDeclaration(TPublicType &publicType,
1511 const TSourceLoc &identifierOrTypeLocation,
1512 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04001513{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001514 TType type(publicType);
1515 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
1516 mDirectiveHandler.pragma().stdgl.invariantAll)
1517 {
1518 TQualifier qualifier = type.getQualifier();
1519
1520 // The directive handler has already taken care of rejecting invalid uses of this pragma
1521 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
1522 // affected variable declarations:
1523 //
1524 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
1525 // elsewhere, in TranslatorGLSL.)
1526 //
1527 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
1528 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
1529 // the way this is currently implemented we have to enable this compiler option before
1530 // parsing the shader and determining the shading language version it uses. If this were
1531 // implemented as a post-pass, the workaround could be more targeted.
1532 //
1533 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
1534 // the specification, but there are desktop OpenGL drivers that expect that this is the
1535 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
1536 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
1537 {
1538 type.setInvariant(true);
1539 }
1540 }
1541
1542 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001543
Olli Etuahobab4c082015-04-24 16:38:49 +03001544 bool emptyDeclaration = (identifier == "");
Olli Etuahofa33d582015-04-09 14:33:12 +03001545
Olli Etuahobab4c082015-04-24 16:38:49 +03001546 mDeferredSingleDeclarationErrorCheck = emptyDeclaration;
1547
1548 if (emptyDeclaration)
1549 {
1550 if (publicType.isUnsizedArray())
1551 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001552 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1553 // error. It is assumed that this applies to empty declarations as well.
1554 error(identifierOrTypeLocation, "empty array declaration needs to specify a size",
1555 identifier.c_str());
Olli Etuahobab4c082015-04-24 16:38:49 +03001556 }
1557 }
1558 else
Jamie Madill60ed9812013-06-06 11:56:46 -04001559 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001560 singleDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001561
Olli Etuaho856c4972016-08-08 11:38:39 +03001562 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001563
Olli Etuaho2935c582015-04-08 14:32:06 +03001564 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001565 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001566
1567 if (variable && symbol)
Jamie Madill60ed9812013-06-06 11:56:46 -04001568 symbol->setId(variable->getUniqueId());
Jamie Madill60ed9812013-06-06 11:56:46 -04001569 }
1570
Olli Etuahoe7847b02015-03-16 11:56:12 +02001571 return intermediate.makeAggregate(symbol, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001572}
1573
Olli Etuahoe7847b02015-03-16 11:56:12 +02001574TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1575 const TSourceLoc &identifierLocation,
1576 const TString &identifier,
1577 const TSourceLoc &indexLocation,
1578 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04001579{
Olli Etuahofa33d582015-04-09 14:33:12 +03001580 mDeferredSingleDeclarationErrorCheck = false;
1581
Olli Etuaho383b7912016-08-05 11:22:59 +03001582 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001583
Olli Etuaho856c4972016-08-08 11:38:39 +03001584 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001585
Olli Etuaho8a176262016-08-16 14:23:01 +03001586 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001587
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001588 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001589
Olli Etuaho856c4972016-08-08 11:38:39 +03001590 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001591 // Make the type an array even if size check failed.
1592 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1593 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04001594
Olli Etuaho2935c582015-04-08 14:32:06 +03001595 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001596 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001597
Olli Etuahoe7847b02015-03-16 11:56:12 +02001598 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001599 if (variable && symbol)
Jamie Madill60ed9812013-06-06 11:56:46 -04001600 symbol->setId(variable->getUniqueId());
Jamie Madill60ed9812013-06-06 11:56:46 -04001601
Olli Etuahoe7847b02015-03-16 11:56:12 +02001602 return intermediate.makeAggregate(symbol, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001603}
1604
Jamie Madill06145232015-05-13 13:10:01 -04001605TIntermAggregate *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
Olli Etuahoe7847b02015-03-16 11:56:12 +02001606 const TSourceLoc &identifierLocation,
1607 const TString &identifier,
1608 const TSourceLoc &initLocation,
1609 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04001610{
Olli Etuahofa33d582015-04-09 14:33:12 +03001611 mDeferredSingleDeclarationErrorCheck = false;
1612
Olli Etuaho383b7912016-08-05 11:22:59 +03001613 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001614
Olli Etuahoe7847b02015-03-16 11:56:12 +02001615 TIntermNode *intermNode = nullptr;
1616 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04001617 {
1618 //
1619 // Build intermediate representation
1620 //
Olli Etuahoe7847b02015-03-16 11:56:12 +02001621 return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : nullptr;
Jamie Madill60ed9812013-06-06 11:56:46 -04001622 }
1623 else
1624 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001625 return nullptr;
Jamie Madill60ed9812013-06-06 11:56:46 -04001626 }
1627}
1628
Jamie Madillb98c3a82015-07-23 14:26:04 -04001629TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration(
1630 TPublicType &publicType,
1631 const TSourceLoc &identifierLocation,
1632 const TString &identifier,
1633 const TSourceLoc &indexLocation,
1634 TIntermTyped *indexExpression,
1635 const TSourceLoc &initLocation,
1636 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001637{
1638 mDeferredSingleDeclarationErrorCheck = false;
1639
Olli Etuaho383b7912016-08-05 11:22:59 +03001640 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001641
Olli Etuaho8a176262016-08-16 14:23:01 +03001642 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001643
1644 TPublicType arrayType(publicType);
1645
Olli Etuaho856c4972016-08-08 11:38:39 +03001646 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001647 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
1648 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03001649 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001650 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001651 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001652 }
1653 // Make the type an array even if size check failed.
1654 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1655 arrayType.setArraySize(size);
1656
1657 // initNode will correspond to the whole of "type b[n] = initializer".
1658 TIntermNode *initNode = nullptr;
1659 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
1660 {
1661 return initNode ? intermediate.makeAggregate(initNode, initLocation) : nullptr;
1662 }
1663 else
1664 {
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001665 return nullptr;
1666 }
1667}
1668
Olli Etuahoe7847b02015-03-16 11:56:12 +02001669TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc,
Jamie Madill47e3ec02014-08-20 16:38:33 -04001670 const TSourceLoc &identifierLoc,
1671 const TString *identifier,
1672 const TSymbol *symbol)
1673{
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001674 // invariant declaration
Olli Etuaho856c4972016-08-08 11:38:39 +03001675 checkIsAtGlobalLevel(invariantLoc, "invariant varying");
Jamie Madill47e3ec02014-08-20 16:38:33 -04001676
1677 if (!symbol)
1678 {
1679 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001680 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001681 }
1682 else
1683 {
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001684 const TString kGlFrontFacing("gl_FrontFacing");
1685 if (*identifier == kGlFrontFacing)
1686 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001687 error(identifierLoc, "identifier should not be declared as invariant",
1688 identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001689 return nullptr;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001690 }
Jamie Madill2c433252014-12-03 12:36:54 -05001691 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001692 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
1693 ASSERT(variable);
1694 const TType &type = variable->getType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04001695 TIntermSymbol *intermSymbol =
1696 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001697
1698 TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc);
1699 aggregate->setOp(EOpInvariantDeclaration);
1700 return aggregate;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001701 }
1702}
1703
Jamie Madillb98c3a82015-07-23 14:26:04 -04001704TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType,
1705 TIntermAggregate *aggregateDeclaration,
1706 const TSourceLoc &identifierLocation,
1707 const TString &identifier)
Jamie Madill502d66f2013-06-20 11:55:52 -04001708{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001709 // If the declaration starting this declarator list was empty (example: int,), some checks were
1710 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001711 if (mDeferredSingleDeclarationErrorCheck)
1712 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001713 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001714 mDeferredSingleDeclarationErrorCheck = false;
1715 }
1716
Olli Etuaho856c4972016-08-08 11:38:39 +03001717 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001718
Olli Etuaho856c4972016-08-08 11:38:39 +03001719 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04001720
Olli Etuaho2935c582015-04-08 14:32:06 +03001721 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001722 declareVariable(identifierLocation, identifier, TType(publicType), &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001723
Jamie Madillb98c3a82015-07-23 14:26:04 -04001724 TIntermSymbol *symbol =
1725 intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001726 if (variable && symbol)
Jamie Madill502d66f2013-06-20 11:55:52 -04001727 symbol->setId(variable->getUniqueId());
1728
Olli Etuahoe7847b02015-03-16 11:56:12 +02001729 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001730}
1731
Jamie Madillb98c3a82015-07-23 14:26:04 -04001732TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType,
1733 TIntermAggregate *aggregateDeclaration,
1734 const TSourceLoc &identifierLocation,
1735 const TString &identifier,
1736 const TSourceLoc &arrayLocation,
1737 TIntermTyped *indexExpression)
Jamie Madill502d66f2013-06-20 11:55:52 -04001738{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001739 // If the declaration starting this declarator list was empty (example: int,), some checks were
1740 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001741 if (mDeferredSingleDeclarationErrorCheck)
1742 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001743 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001744 mDeferredSingleDeclarationErrorCheck = false;
1745 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001746
Olli Etuaho856c4972016-08-08 11:38:39 +03001747 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001748
Olli Etuaho856c4972016-08-08 11:38:39 +03001749 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04001750
Olli Etuaho8a176262016-08-16 14:23:01 +03001751 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04001752 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001753 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03001754 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03001755 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001756
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001757 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001758 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04001759
Jamie Madillb98c3a82015-07-23 14:26:04 -04001760 TIntermSymbol *symbol =
1761 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001762 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001763 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001764
1765 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001766 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001767
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001768 return nullptr;
Jamie Madill502d66f2013-06-20 11:55:52 -04001769}
1770
Jamie Madillb98c3a82015-07-23 14:26:04 -04001771TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicType,
1772 TIntermAggregate *aggregateDeclaration,
1773 const TSourceLoc &identifierLocation,
1774 const TString &identifier,
1775 const TSourceLoc &initLocation,
1776 TIntermTyped *initializer)
Jamie Madill502d66f2013-06-20 11:55:52 -04001777{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001778 // If the declaration starting this declarator list was empty (example: int,), some checks were
1779 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001780 if (mDeferredSingleDeclarationErrorCheck)
1781 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001782 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001783 mDeferredSingleDeclarationErrorCheck = false;
1784 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001785
Olli Etuaho856c4972016-08-08 11:38:39 +03001786 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001787
Olli Etuahoe7847b02015-03-16 11:56:12 +02001788 TIntermNode *intermNode = nullptr;
1789 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04001790 {
1791 //
1792 // build the intermediate representation
1793 //
1794 if (intermNode)
1795 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001796 return intermediate.growAggregate(aggregateDeclaration, intermNode, initLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001797 }
1798 else
1799 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001800 return aggregateDeclaration;
Jamie Madill502d66f2013-06-20 11:55:52 -04001801 }
1802 }
1803 else
1804 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001805 return nullptr;
Jamie Madill502d66f2013-06-20 11:55:52 -04001806 }
1807}
1808
Jamie Madill06145232015-05-13 13:10:01 -04001809TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001810 TIntermAggregate *aggregateDeclaration,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301811 const TSourceLoc &identifierLocation,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001812 const TString &identifier,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301813 const TSourceLoc &indexLocation,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001814 TIntermTyped *indexExpression,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001815 const TSourceLoc &initLocation,
1816 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001817{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001818 // If the declaration starting this declarator list was empty (example: int,), some checks were
1819 // not performed.
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001820 if (mDeferredSingleDeclarationErrorCheck)
1821 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001822 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001823 mDeferredSingleDeclarationErrorCheck = false;
1824 }
1825
Olli Etuaho856c4972016-08-08 11:38:39 +03001826 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001827
Olli Etuaho8a176262016-08-16 14:23:01 +03001828 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001829
1830 TPublicType arrayType(publicType);
1831
Olli Etuaho856c4972016-08-08 11:38:39 +03001832 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001833 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
1834 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03001835 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001836 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001837 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001838 }
1839 // Make the type an array even if size check failed.
1840 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1841 arrayType.setArraySize(size);
1842
1843 // initNode will correspond to the whole of "b[n] = initializer".
1844 TIntermNode *initNode = nullptr;
1845 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
1846 {
1847 if (initNode)
1848 {
1849 return intermediate.growAggregate(aggregateDeclaration, initNode, initLocation);
1850 }
1851 else
1852 {
1853 return aggregateDeclaration;
1854 }
1855 }
1856 else
1857 {
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001858 return nullptr;
1859 }
1860}
1861
Jamie Madilla295edf2013-06-06 11:56:48 -04001862void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
1863{
Jamie Madilla295edf2013-06-06 11:56:48 -04001864 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04001865
1866 // It should never be the case, but some strange parser errors can send us here.
1867 if (layoutQualifier.isEmpty())
1868 {
1869 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04001870 return;
1871 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001872
Martin Radev802abe02016-08-04 17:48:32 +03001873 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04001874 {
Martin Radev802abe02016-08-04 17:48:32 +03001875 error(typeQualifier.line, "invalid combination:", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04001876 return;
1877 }
1878
Martin Radev802abe02016-08-04 17:48:32 +03001879 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04001880 {
Martin Radev802abe02016-08-04 17:48:32 +03001881 if (mComputeShaderLocalSizeDeclared &&
1882 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
1883 {
1884 error(typeQualifier.line, "Work group size does not match the previous declaration",
1885 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001886 return;
1887 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001888
Martin Radev802abe02016-08-04 17:48:32 +03001889 if (mShaderVersion < 310)
1890 {
1891 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001892 return;
1893 }
Jamie Madill099c0f32013-06-20 11:55:52 -04001894
Martin Radev802abe02016-08-04 17:48:32 +03001895 if (!layoutQualifier.isGroupSizeSpecified())
1896 {
1897 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001898 return;
1899 }
1900
1901 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
1902 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
1903
1904 const TConstantUnion *maxComputeWorkGroupSizeData =
1905 maxComputeWorkGroupSize->getConstPointer();
1906
1907 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
1908 {
1909 if (layoutQualifier.localSize[i] != -1)
1910 {
1911 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
1912 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
1913 if (mComputeShaderLocalSize[i] < 1 ||
1914 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
1915 {
1916 std::stringstream errorMessageStream;
1917 errorMessageStream << "Value must be at least 1 and no greater than "
1918 << maxComputeWorkGroupSizeValue;
1919 const std::string &errorMessage = errorMessageStream.str();
1920
1921 error(typeQualifier.line, "invalid value:", getLocalSizeString(i),
1922 errorMessage.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03001923 return;
1924 }
1925 }
1926 }
1927
1928 mComputeShaderLocalSizeDeclared = true;
1929 }
1930 else
Jamie Madill1566ef72013-06-20 11:55:54 -04001931 {
Martin Radev802abe02016-08-04 17:48:32 +03001932
Olli Etuaho8a176262016-08-16 14:23:01 +03001933 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03001934 {
Martin Radev802abe02016-08-04 17:48:32 +03001935 return;
1936 }
1937
1938 if (typeQualifier.qualifier != EvqUniform)
1939 {
1940 error(typeQualifier.line, "invalid qualifier:",
1941 getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
Martin Radev802abe02016-08-04 17:48:32 +03001942 return;
1943 }
1944
1945 if (mShaderVersion < 300)
1946 {
1947 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
1948 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001949 return;
1950 }
1951
Olli Etuaho856c4972016-08-08 11:38:39 +03001952 checkLocationIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001953
1954 if (layoutQualifier.matrixPacking != EmpUnspecified)
1955 {
1956 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
1957 }
1958
1959 if (layoutQualifier.blockStorage != EbsUnspecified)
1960 {
1961 mDefaultBlockStorage = layoutQualifier.blockStorage;
1962 }
Jamie Madill1566ef72013-06-20 11:55:54 -04001963 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001964}
1965
Olli Etuahoee63f5d2016-01-04 11:34:54 +02001966TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function,
1967 const TSourceLoc &location)
1968{
Olli Etuaho5d653182016-01-04 14:43:28 +02001969 // Note: symbolTableFunction could be the same as function if this is the first declaration.
1970 // Either way the instance in the symbol table is used to track whether the function is declared
1971 // multiple times.
1972 TFunction *symbolTableFunction =
1973 static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion()));
1974 if (symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100)
1975 {
1976 // ESSL 1.00.17 section 4.2.7.
1977 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
1978 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02001979 }
1980 symbolTableFunction->setHasPrototypeDeclaration();
1981
Olli Etuahoee63f5d2016-01-04 11:34:54 +02001982 TIntermAggregate *prototype = new TIntermAggregate;
1983 prototype->setType(function.getReturnType());
1984 prototype->setName(function.getMangledName());
1985 prototype->setFunctionId(function.getUniqueId());
1986
1987 for (size_t i = 0; i < function.getParamCount(); i++)
1988 {
1989 const TConstParameter &param = function.getParam(i);
1990 if (param.name != 0)
1991 {
1992 TVariable variable(param.name, *param.type);
1993
1994 TIntermSymbol *paramSymbol = intermediate.addSymbol(
1995 variable.getUniqueId(), variable.getName(), variable.getType(), location);
1996 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
1997 }
1998 else
1999 {
2000 TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
2001 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
2002 }
2003 }
2004
2005 prototype->setOp(EOpPrototype);
2006
2007 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002008
2009 if (!symbolTable.atGlobalLevel())
2010 {
2011 // ESSL 3.00.4 section 4.2.4.
2012 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002013 }
2014
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002015 return prototype;
2016}
2017
2018TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function,
2019 TIntermAggregate *functionPrototype,
2020 TIntermAggregate *functionBody,
2021 const TSourceLoc &location)
2022{
2023 //?? Check that all paths return a value if return type != void ?
2024 // May be best done as post process phase on intermediate code
2025 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2026 {
2027 error(location, "function does not return a value:", "", function.getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002028 }
2029
2030 TIntermAggregate *aggregate =
2031 intermediate.growAggregate(functionPrototype, functionBody, location);
2032 intermediate.setAggregateOperator(aggregate, EOpFunction, location);
2033 aggregate->setName(function.getMangledName().c_str());
2034 aggregate->setType(function.getReturnType());
2035 aggregate->setFunctionId(function.getUniqueId());
2036
2037 symbolTable.pop();
2038 return aggregate;
2039}
2040
Jamie Madill185fb402015-06-12 15:48:48 -04002041void TParseContext::parseFunctionPrototype(const TSourceLoc &location,
2042 TFunction *function,
2043 TIntermAggregate **aggregateOut)
2044{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002045 const TSymbol *builtIn =
2046 symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002047
2048 if (builtIn)
2049 {
2050 error(location, "built-in functions cannot be redefined", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002051 }
2052
Jamie Madillb98c3a82015-07-23 14:26:04 -04002053 TFunction *prevDec =
2054 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Jamie Madill185fb402015-06-12 15:48:48 -04002055 //
2056 // Note: 'prevDec' could be 'function' if this is the first time we've seen function
2057 // as it would have just been put in the symbol table. Otherwise, we're looking up
2058 // an earlier occurance.
2059 //
2060 if (prevDec->isDefined())
2061 {
2062 // Then this function already has a body.
2063 error(location, "function already has a body", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002064 }
2065 prevDec->setDefined();
2066 //
2067 // Overload the unique ID of the definition to be the same unique ID as the declaration.
2068 // Eventually we will probably want to have only a single definition and just swap the
2069 // arguments to be the definition's arguments.
2070 //
2071 function->setUniqueId(prevDec->getUniqueId());
2072
2073 // Raise error message if main function takes any parameters or return anything other than void
2074 if (function->getName() == "main")
2075 {
2076 if (function->getParamCount() > 0)
2077 {
2078 error(location, "function cannot take any parameter(s)", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002079 }
2080 if (function->getReturnType().getBasicType() != EbtVoid)
2081 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002082 error(location, "", function->getReturnType().getBasicString(),
2083 "main function cannot return a value");
Jamie Madill185fb402015-06-12 15:48:48 -04002084 }
2085 }
2086
2087 //
2088 // Remember the return type for later checking for RETURN statements.
2089 //
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002090 mCurrentFunctionType = &(prevDec->getReturnType());
2091 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002092
2093 //
2094 // Insert parameters into the symbol table.
2095 // If the parameter has no name, it's not an error, just don't insert it
2096 // (could be used for unused args).
2097 //
2098 // Also, accumulate the list of parameters into the HIL, so lower level code
2099 // knows where to find parameters.
2100 //
2101 TIntermAggregate *paramNodes = new TIntermAggregate;
2102 for (size_t i = 0; i < function->getParamCount(); i++)
2103 {
2104 const TConstParameter &param = function->getParam(i);
2105 if (param.name != 0)
2106 {
2107 TVariable *variable = new TVariable(param.name, *param.type);
2108 //
2109 // Insert the parameters with name in the symbol table.
2110 //
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002111 if (!symbolTable.declare(variable))
2112 {
Jamie Madill185fb402015-06-12 15:48:48 -04002113 error(location, "redefinition", variable->getName().c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002114 paramNodes = intermediate.growAggregate(
2115 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
2116 continue;
Jamie Madill185fb402015-06-12 15:48:48 -04002117 }
2118
2119 //
2120 // Add the parameter to the HIL
2121 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002122 TIntermSymbol *symbol = intermediate.addSymbol(
2123 variable->getUniqueId(), variable->getName(), variable->getType(), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002124
2125 paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
2126 }
2127 else
2128 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002129 paramNodes = intermediate.growAggregate(
2130 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002131 }
2132 }
2133 intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
2134 *aggregateOut = paramNodes;
2135 setLoopNestingLevel(0);
2136}
2137
Jamie Madillb98c3a82015-07-23 14:26:04 -04002138TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002139{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002140 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002141 // We don't know at this point whether this is a function definition or a prototype.
2142 // The definition production code will check for redefinitions.
2143 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002144 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002145 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2146 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002147 //
2148 TFunction *prevDec =
2149 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302150
2151 if (getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltIn(function->getName().c_str()))
2152 {
2153 // With ESSL 3.00, names of built-in functions cannot be redeclared as functions.
2154 // Therefore overloading or redefining builtin functions is an error.
2155 error(location, "Name of a built-in function cannot be redeclared as function",
2156 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302157 }
2158 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002159 {
2160 if (prevDec->getReturnType() != function->getReturnType())
2161 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002162 error(location, "overloaded functions must have the same return type",
Jamie Madill185fb402015-06-12 15:48:48 -04002163 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002164 }
2165 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2166 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002167 if (prevDec->getParam(i).type->getQualifier() !=
2168 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002169 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002170 error(location, "overloaded functions must have the same parameter qualifiers",
Jamie Madill185fb402015-06-12 15:48:48 -04002171 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002172 }
2173 }
2174 }
2175
2176 //
2177 // Check for previously declared variables using the same name.
2178 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002179 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002180 if (prevSym)
2181 {
2182 if (!prevSym->isFunction())
2183 {
2184 error(location, "redefinition", function->getName().c_str(), "function");
Jamie Madill185fb402015-06-12 15:48:48 -04002185 }
2186 }
2187 else
2188 {
2189 // Insert the unmangled name to detect potential future redefinition as a variable.
Jamie Madillb98c3a82015-07-23 14:26:04 -04002190 TFunction *newFunction =
2191 new TFunction(NewPoolTString(function->getName().c_str()), &function->getReturnType());
Jamie Madill185fb402015-06-12 15:48:48 -04002192 symbolTable.getOuterLevel()->insertUnmangled(newFunction);
2193 }
2194
2195 // We're at the inner scope level of the function's arguments and body statement.
2196 // Add the function prototype to the surrounding scope instead.
2197 symbolTable.getOuterLevel()->insert(function);
2198
2199 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002200 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2201 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002202 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2203 //
2204 return function;
2205}
2206
Olli Etuaho9de84a52016-06-14 17:36:01 +03002207TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2208 const TString *name,
2209 const TSourceLoc &location)
2210{
2211 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2212 {
2213 error(location, "no qualifiers allowed for function return",
2214 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002215 }
2216 if (!type.layoutQualifier.isEmpty())
2217 {
2218 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002219 }
2220 // make sure a sampler is not involved as well...
Olli Etuaho856c4972016-08-08 11:38:39 +03002221 checkIsNotSampler(location, type, "samplers can't be function return values");
Olli Etuahoe29324f2016-06-15 10:58:03 +03002222 if (mShaderVersion < 300)
2223 {
2224 // Array return values are forbidden, but there's also no valid syntax for declaring array
2225 // return values in ESSL 1.00.
2226 ASSERT(type.arraySize == 0 || mDiagnostics.numErrors() > 0);
2227
2228 if (type.isStructureContainingArrays())
2229 {
2230 // ESSL 1.00.17 section 6.1 Function Definitions
2231 error(location, "structures containing arrays can't be function return values",
2232 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002233 }
2234 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002235
2236 // Add the function as a prototype after parsing it (we do not support recursion)
2237 return new TFunction(name, new TType(type));
2238}
2239
Jamie Madill06145232015-05-13 13:10:01 -04002240TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002241{
Jamie Madill06145232015-05-13 13:10:01 -04002242 TPublicType publicType = publicTypeIn;
Olli Etuahobd163f62015-11-13 12:15:38 +02002243 if (publicType.isStructSpecifier)
2244 {
2245 error(publicType.line, "constructor can't be a structure definition",
2246 getBasicString(publicType.type));
Olli Etuahobd163f62015-11-13 12:15:38 +02002247 }
2248
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002249 TOperator op = EOpNull;
2250 if (publicType.userDef)
2251 {
2252 op = EOpConstructStruct;
2253 }
2254 else
2255 {
Geoff Lang156d7192016-07-21 16:11:00 -04002256 op = sh::TypeToConstructorOperator(TType(publicType));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002257 if (op == EOpNull)
2258 {
2259 error(publicType.line, "cannot construct this type", getBasicString(publicType.type));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002260 publicType.type = EbtFloat;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002261 op = EOpConstructFloat;
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002262 }
2263 }
2264
2265 TString tempString;
Dmitry Skiba7f17a502015-06-22 15:08:39 -07002266 const TType *type = new TType(publicType);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002267 return new TFunction(&tempString, type, op);
2268}
2269
Jamie Madillb98c3a82015-07-23 14:26:04 -04002270// This function is used to test for the correctness of the parameters passed to various constructor
2271// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002272//
Olli Etuaho856c4972016-08-08 11:38:39 +03002273// 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 +00002274//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002275TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002276 TOperator op,
2277 TFunction *fnCall,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302278 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002279{
Olli Etuaho856c4972016-08-08 11:38:39 +03002280 TType type = fnCall->getReturnType();
2281 if (type.isUnsizedArray())
2282 {
2283 type.setArraySize(static_cast<unsigned int>(fnCall->getParamCount()));
2284 }
2285 bool constType = true;
2286 for (size_t i = 0; i < fnCall->getParamCount(); ++i)
2287 {
2288 const TConstParameter &param = fnCall->getParam(i);
2289 if (param.type->getQualifier() != EvqConst)
2290 constType = false;
2291 }
2292 if (constType)
2293 type.setQualifier(EvqConst);
2294
Olli Etuaho8a176262016-08-16 14:23:01 +03002295 if (!checkConstructorArguments(line, arguments, *fnCall, op, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002296 {
2297 TIntermTyped *dummyNode = intermediate.setAggregateOperator(nullptr, op, line);
2298 dummyNode->setType(type);
2299 return dummyNode;
2300 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002301 TIntermAggregate *constructor = arguments->getAsAggregate();
2302 ASSERT(constructor != nullptr);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002303
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002304 // Turn the argument list itself into a constructor
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002305 constructor->setOp(op);
2306 constructor->setLine(line);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002307 ASSERT(constructor->isConstructor());
2308
2309 // Need to set type before setPrecisionFromChildren() because bool doesn't have precision.
Olli Etuaho856c4972016-08-08 11:38:39 +03002310 constructor->setType(type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002311
Olli Etuaho21203702014-11-13 16:16:21 +02002312 // Structs should not be precision qualified, the individual members may be.
2313 // Built-in types on the other hand should be precision qualified.
2314 if (op != EOpConstructStruct)
2315 {
2316 constructor->setPrecisionFromChildren();
Olli Etuaho856c4972016-08-08 11:38:39 +03002317 type.setPrecision(constructor->getPrecision());
Olli Etuaho21203702014-11-13 16:16:21 +02002318 }
2319
Olli Etuaho856c4972016-08-08 11:38:39 +03002320 constructor->setType(type);
2321
Olli Etuaho1d122782015-11-06 15:35:17 +02002322 TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002323 if (constConstructor)
2324 {
2325 return constConstructor;
2326 }
2327
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002328 return constructor;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002329}
2330
Olli Etuaho90892fb2016-07-14 14:44:51 +03002331// This function returns vector field(s) being accessed from a constant vector.
2332TIntermConstantUnion *TParseContext::foldVectorSwizzle(TVectorFields &fields,
2333 TIntermConstantUnion *baseNode,
2334 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002335{
Olli Etuaho90892fb2016-07-14 14:44:51 +03002336 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002337 ASSERT(unionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002338
Arun Patole7e7e68d2015-05-22 12:02:25 +05302339 TConstantUnion *constArray = new TConstantUnion[fields.num];
Olli Etuaho90892fb2016-07-14 14:44:51 +03002340 const auto &type = baseNode->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002341
Arun Patole7e7e68d2015-05-22 12:02:25 +05302342 for (int i = 0; i < fields.num; i++)
2343 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002344 // Out-of-range indices should already be checked.
2345 ASSERT(fields.offsets[i] < type.getNominalSize());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002346 constArray[i] = unionArray[fields.offsets[i]];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302347 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03002348 return intermediate.addConstantUnion(constArray, type, location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002349}
2350
Olli Etuaho90892fb2016-07-14 14:44:51 +03002351// This function returns the column vector being accessed from a constant matrix.
2352TIntermConstantUnion *TParseContext::foldMatrixSubscript(int index,
2353 TIntermConstantUnion *baseNode,
2354 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002355{
Olli Etuaho90892fb2016-07-14 14:44:51 +03002356 ASSERT(index < baseNode->getType().getCols());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002357
Olli Etuaho90892fb2016-07-14 14:44:51 +03002358 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
2359 int size = baseNode->getType().getRows();
2360 return intermediate.addConstantUnion(&unionArray[size * index], baseNode->getType(), location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002361}
2362
Olli Etuaho90892fb2016-07-14 14:44:51 +03002363// This function returns an element of an array accessed from a constant array.
2364TIntermConstantUnion *TParseContext::foldArraySubscript(int index,
2365 TIntermConstantUnion *baseNode,
2366 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002367{
Olli Etuaho856c4972016-08-08 11:38:39 +03002368 ASSERT(index < static_cast<int>(baseNode->getArraySize()));
Olli Etuaho90892fb2016-07-14 14:44:51 +03002369
2370 TType arrayElementType = baseNode->getType();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002371 arrayElementType.clearArrayness();
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002372 size_t arrayElementSize = arrayElementType.getObjectSize();
Olli Etuaho90892fb2016-07-14 14:44:51 +03002373 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
2374 return intermediate.addConstantUnion(&unionArray[arrayElementSize * index], baseNode->getType(),
2375 location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002376}
2377
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002378//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002379// This function returns the value of a particular field inside a constant structure from the symbol
2380// table.
2381// If there is an embedded/nested struct, it appropriately calls addConstStructNested or
2382// addConstStructFromAggr function and returns the parse-tree with the values of the embedded/nested
2383// struct.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002384//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002385TIntermTyped *TParseContext::addConstStruct(const TString &identifier,
2386 TIntermTyped *node,
2387 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002388{
Arun Patole7e7e68d2015-05-22 12:02:25 +05302389 const TFieldList &fields = node->getType().getStruct()->fields();
Jamie Madillb98c3a82015-07-23 14:26:04 -04002390 size_t instanceSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002391
Arun Patole7e7e68d2015-05-22 12:02:25 +05302392 for (size_t index = 0; index < fields.size(); ++index)
2393 {
2394 if (fields[index]->name() == identifier)
2395 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002396 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302397 }
2398 else
2399 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002400 instanceSize += fields[index]->type()->getObjectSize();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002401 }
2402 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002403
Jamie Madill94bf7f22013-07-08 13:31:15 -04002404 TIntermTyped *typedNode;
2405 TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
Arun Patole7e7e68d2015-05-22 12:02:25 +05302406 if (tempConstantNode)
2407 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002408 const TConstantUnion *constArray = tempConstantNode->getUnionArrayPointer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002409
Jamie Madillb98c3a82015-07-23 14:26:04 -04002410 // type will be changed in the calling function
2411 typedNode = intermediate.addConstantUnion(constArray + instanceSize,
2412 tempConstantNode->getType(), line);
Arun Patole7e7e68d2015-05-22 12:02:25 +05302413 }
2414 else
2415 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002416 error(line, "Cannot offset into the structure", "Error");
Olli Etuaho383b7912016-08-05 11:22:59 +03002417 return nullptr;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002418 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002419
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002420 return typedNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002421}
2422
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002423//
2424// Interface/uniform blocks
2425//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002426TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualifier,
2427 const TSourceLoc &nameLine,
2428 const TString &blockName,
2429 TFieldList *fieldList,
2430 const TString *instanceName,
2431 const TSourceLoc &instanceLine,
2432 TIntermTyped *arrayIndex,
2433 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002434{
Olli Etuaho856c4972016-08-08 11:38:39 +03002435 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002436
2437 if (typeQualifier.qualifier != EvqUniform)
2438 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302439 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier),
2440 "interface blocks must be uniform");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002441 }
2442
Jamie Madill099c0f32013-06-20 11:55:52 -04002443 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03002444 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04002445
Jamie Madill099c0f32013-06-20 11:55:52 -04002446 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2447 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002448 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002449 }
2450
Jamie Madill1566ef72013-06-20 11:55:54 -04002451 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2452 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002453 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002454 }
2455
Olli Etuaho856c4972016-08-08 11:38:39 +03002456 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002457
Arun Patole7e7e68d2015-05-22 12:02:25 +05302458 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2459 if (!symbolTable.declare(blockNameSymbol))
2460 {
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002461 error(nameLine, "redefinition", blockName.c_str(), "interface block name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002462 }
2463
Jamie Madill98493dd2013-07-08 14:39:03 -04002464 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302465 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2466 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002467 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302468 TType *fieldType = field->type();
2469 if (IsSampler(fieldType->getBasicType()))
2470 {
2471 error(field->line(), "unsupported type", fieldType->getBasicString(),
2472 "sampler types are not allowed in interface blocks");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002473 }
2474
Jamie Madill98493dd2013-07-08 14:39:03 -04002475 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002476 switch (qualifier)
2477 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002478 case EvqGlobal:
2479 case EvqUniform:
2480 break;
2481 default:
2482 error(field->line(), "invalid qualifier on interface block member",
2483 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04002484 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002485 }
Jamie Madilla5efff92013-06-06 11:56:47 -04002486
2487 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04002488 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03002489 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Jamie Madill099c0f32013-06-20 11:55:52 -04002490
Jamie Madill98493dd2013-07-08 14:39:03 -04002491 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04002492 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002493 error(field->line(), "invalid layout qualifier:",
2494 getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
Jamie Madill1566ef72013-06-20 11:55:54 -04002495 }
2496
Jamie Madill98493dd2013-07-08 14:39:03 -04002497 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04002498 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002499 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002500 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002501 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04002502 {
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002503 warning(field->line(), "extraneous layout qualifier:",
Jamie Madillb98c3a82015-07-23 14:26:04 -04002504 getMatrixPackingString(fieldLayoutQualifier.matrixPacking),
2505 "only has an effect on matrix types");
Jamie Madill099c0f32013-06-20 11:55:52 -04002506 }
2507
Jamie Madill98493dd2013-07-08 14:39:03 -04002508 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002509 }
2510
Jamie Madill98493dd2013-07-08 14:39:03 -04002511 // add array index
Olli Etuaho856c4972016-08-08 11:38:39 +03002512 unsigned int arraySize = 0;
2513 if (arrayIndex != nullptr)
Jamie Madill98493dd2013-07-08 14:39:03 -04002514 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002515 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
Jamie Madill98493dd2013-07-08 14:39:03 -04002516 }
2517
Jamie Madillb98c3a82015-07-23 14:26:04 -04002518 TInterfaceBlock *interfaceBlock =
2519 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2520 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
2521 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002522
2523 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04002524 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002525
Jamie Madill98493dd2013-07-08 14:39:03 -04002526 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002527 {
2528 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04002529 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2530 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002531 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302532 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04002533
2534 // set parent pointer of the field variable
2535 fieldType->setInterfaceBlock(interfaceBlock);
2536
Arun Patole7e7e68d2015-05-22 12:02:25 +05302537 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04002538 fieldVariable->setQualifier(typeQualifier.qualifier);
2539
Arun Patole7e7e68d2015-05-22 12:02:25 +05302540 if (!symbolTable.declare(fieldVariable))
2541 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002542 error(field->line(), "redefinition", field->name().c_str(),
2543 "interface block member name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002544 }
2545 }
2546 }
2547 else
2548 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002549 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03002550
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002551 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05302552 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002553 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04002554
Arun Patole7e7e68d2015-05-22 12:02:25 +05302555 if (!symbolTable.declare(instanceTypeDef))
2556 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002557 error(instanceLine, "redefinition", instanceName->c_str(),
2558 "interface block instance name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002559 }
2560
Jamie Madillb98c3a82015-07-23 14:26:04 -04002561 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002562 symbolName = instanceTypeDef->getName();
2563 }
2564
Jamie Madillb98c3a82015-07-23 14:26:04 -04002565 TIntermAggregate *aggregate = intermediate.makeAggregate(
2566 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line),
2567 nameLine);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002568 aggregate->setOp(EOpDeclaration);
Jamie Madill98493dd2013-07-08 14:39:03 -04002569
2570 exitStructDeclaration();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002571 return aggregate;
2572}
2573
Olli Etuaho383b7912016-08-05 11:22:59 +03002574void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002575{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002576 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002577
2578 // Embedded structure definitions are not supported per GLSL ES spec.
2579 // They aren't allowed in GLSL either, but we need to detect this here
2580 // so we don't rely on the GLSL compiler to catch it.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302581 if (mStructNestingLevel > 1)
2582 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002583 error(line, "", "Embedded struct definitions are not allowed");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002584 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002585}
2586
2587void TParseContext::exitStructDeclaration()
2588{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002589 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002590}
2591
Jamie Madillb98c3a82015-07-23 14:26:04 -04002592namespace
2593{
kbr@chromium.org476541f2011-10-27 21:14:51 +00002594const int kWebGLMaxStructNesting = 4;
2595
2596} // namespace
2597
Olli Etuaho8a176262016-08-16 14:23:01 +03002598void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002599{
Arun Patole7e7e68d2015-05-22 12:02:25 +05302600 if (!IsWebGLBasedSpec(mShaderSpec))
2601 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002602 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002603 }
2604
Arun Patole7e7e68d2015-05-22 12:02:25 +05302605 if (field.type()->getBasicType() != EbtStruct)
2606 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002607 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002608 }
2609
2610 // We're already inside a structure definition at this point, so add
2611 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302612 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2613 {
Jamie Madill41a49272014-03-18 16:10:13 -04002614 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002615 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
2616 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04002617 std::string reason = reasonStream.str();
2618 error(line, reason.c_str(), field.name().c_str(), "");
Olli Etuaho8a176262016-08-16 14:23:01 +03002619 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002620 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002621}
2622
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00002623//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002624// Parse an array index expression
2625//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002626TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
2627 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302628 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002629{
2630 TIntermTyped *indexedExpression = NULL;
2631
2632 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2633 {
2634 if (baseExpression->getAsSymbolNode())
2635 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302636 error(location, " left of '[' is not of type array, matrix, or vector ",
2637 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002638 }
2639 else
2640 {
2641 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2642 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002643 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002644
Jamie Madill21c1e452014-12-29 11:33:41 -05002645 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2646
Olli Etuaho36b05142015-11-12 13:10:42 +02002647 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
2648 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
2649 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
2650 // index is a constant expression.
2651 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
2652 {
2653 if (baseExpression->isInterfaceBlock())
2654 {
2655 error(
2656 location, "", "[",
2657 "array indexes for interface blocks arrays must be constant integral expressions");
Olli Etuaho36b05142015-11-12 13:10:42 +02002658 }
2659 else if (baseExpression->getQualifier() == EvqFragmentOut)
2660 {
2661 error(location, "", "[",
2662 "array indexes for fragment outputs must be constant integral expressions");
Olli Etuaho36b05142015-11-12 13:10:42 +02002663 }
Olli Etuaho3e960462015-11-12 15:58:39 +02002664 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
2665 {
2666 error(location, "", "[", "array index for gl_FragData must be constant zero");
Olli Etuaho3e960462015-11-12 15:58:39 +02002667 }
Olli Etuaho36b05142015-11-12 13:10:42 +02002668 }
2669
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002670 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04002671 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002672 // If the index is not qualified as constant, the behavior in the spec is undefined. This
2673 // applies even if ANGLE has been able to constant fold it (ANGLE may constant fold
2674 // expressions that are not constant expressions). The most compatible way to handle this
2675 // case is to report a warning instead of an error and force the index to be in the
2676 // correct range.
2677 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madill21c1e452014-12-29 11:33:41 -05002678 int index = indexConstantUnion->getIConst(0);
Olli Etuaho90892fb2016-07-14 14:44:51 +03002679 if (!baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04002680 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002681 // Array checks are done later because a different error message might be generated
2682 // based on the index in some cases.
2683 if (baseExpression->isVector())
2684 {
2685 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2686 baseExpression->getType().getNominalSize(),
2687 "vector field selection out of range", "[]");
2688 }
2689 else if (baseExpression->isMatrix())
2690 {
2691 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2692 baseExpression->getType().getCols(),
2693 "matrix field selection out of range", "[]");
2694 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002695 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03002696
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002697 TIntermConstantUnion *baseConstantUnion = baseExpression->getAsConstantUnion();
2698 if (baseConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04002699 {
2700 if (baseExpression->isArray())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002701 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002702 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2703 baseExpression->getArraySize(),
2704 "array index out of range", "[]");
2705 // Constant folding for array indexing.
2706 indexedExpression = foldArraySubscript(index, baseConstantUnion, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002707 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002708 else if (baseExpression->isVector())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002709 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002710 // Constant folding for vector indexing - reusing vector swizzle folding.
Jamie Madill7164cf42013-07-08 13:30:59 -04002711 TVectorFields fields;
2712 fields.num = 1;
Olli Etuaho90892fb2016-07-14 14:44:51 +03002713 fields.offsets[0] = index;
2714 indexedExpression = foldVectorSwizzle(fields, baseConstantUnion, location);
Jamie Madill7164cf42013-07-08 13:30:59 -04002715 }
2716 else if (baseExpression->isMatrix())
2717 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002718 // Constant folding for matrix indexing.
2719 indexedExpression = foldMatrixSubscript(index, baseConstantUnion, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002720 }
2721 }
2722 else
2723 {
Jamie Madillb11e2482015-05-04 14:21:22 -04002724 int safeIndex = -1;
2725
Jamie Madill7164cf42013-07-08 13:30:59 -04002726 if (baseExpression->isArray())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002727 {
Olli Etuaho3e960462015-11-12 15:58:39 +02002728 if (baseExpression->getQualifier() == EvqFragData && index > 0)
2729 {
2730 if (mShaderSpec == SH_WEBGL2_SPEC)
2731 {
2732 // Error has been already generated if index is not const.
2733 if (indexExpression->getQualifier() == EvqConst)
2734 {
2735 error(location, "", "[",
2736 "array index for gl_FragData must be constant zero");
Olli Etuaho3e960462015-11-12 15:58:39 +02002737 }
2738 safeIndex = 0;
2739 }
2740 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
2741 {
2742 outOfRangeError(outOfRangeIndexIsError, location, "", "[",
2743 "array index for gl_FragData must be zero when "
2744 "GL_EXT_draw_buffers is disabled");
2745 safeIndex = 0;
2746 }
2747 }
2748 // Only do generic out-of-range check if similar error hasn't already been reported.
Olli Etuaho90892fb2016-07-14 14:44:51 +03002749 if (safeIndex < 0)
Jamie Madill7164cf42013-07-08 13:30:59 -04002750 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002751 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2752 baseExpression->getArraySize(),
2753 "array index out of range", "[]");
Jamie Madill7164cf42013-07-08 13:30:59 -04002754 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002755 }
2756
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002757 // Data of constant unions can't be changed, because it may be shared with other
2758 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
2759 // sanitized object.
Jamie Madillb11e2482015-05-04 14:21:22 -04002760 if (safeIndex != -1)
2761 {
2762 TConstantUnion *safeConstantUnion = new TConstantUnion();
2763 safeConstantUnion->setIConst(safeIndex);
2764 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
2765 }
2766
Jamie Madillb98c3a82015-07-23 14:26:04 -04002767 indexedExpression =
2768 intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002769 }
2770 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002771 else
2772 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002773 indexedExpression =
2774 intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
Jamie Madill7164cf42013-07-08 13:30:59 -04002775 }
2776
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002777 if (indexedExpression == 0)
2778 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002779 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002780 unionArray->setFConst(0.0f);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002781 indexedExpression =
2782 intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002783 }
2784 else if (baseExpression->isArray())
2785 {
Olli Etuahob3fbd862015-09-30 17:55:02 +03002786 TType indexedType = baseExpression->getType();
2787 indexedType.clearArrayness();
2788 indexedExpression->setType(indexedType);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002789 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002790 else if (baseExpression->isMatrix())
2791 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002792 indexedExpression->setType(TType(baseExpression->getBasicType(),
Olli Etuahob3fbd862015-09-30 17:55:02 +03002793 baseExpression->getPrecision(), EvqTemporary,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002794 static_cast<unsigned char>(baseExpression->getRows())));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002795 }
2796 else if (baseExpression->isVector())
2797 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002798 indexedExpression->setType(
Olli Etuahob3fbd862015-09-30 17:55:02 +03002799 TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002800 }
2801 else
2802 {
2803 indexedExpression->setType(baseExpression->getType());
2804 }
2805
Olli Etuahob3fbd862015-09-30 17:55:02 +03002806 if (baseExpression->getType().getQualifier() == EvqConst &&
2807 indexExpression->getType().getQualifier() == EvqConst)
2808 {
2809 indexedExpression->getTypePointer()->setQualifier(EvqConst);
2810 }
2811 else
2812 {
2813 indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
2814 }
2815
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002816 return indexedExpression;
2817}
2818
Olli Etuaho90892fb2016-07-14 14:44:51 +03002819int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
2820 const TSourceLoc &location,
2821 int index,
2822 int arraySize,
2823 const char *reason,
2824 const char *token)
2825{
2826 if (index >= arraySize || index < 0)
2827 {
2828 std::stringstream extraInfoStream;
2829 extraInfoStream << "'" << index << "'";
2830 std::string extraInfo = extraInfoStream.str();
2831 outOfRangeError(outOfRangeIndexIsError, location, reason, token, extraInfo.c_str());
2832 if (index < 0)
2833 {
2834 return 0;
2835 }
2836 else
2837 {
2838 return arraySize - 1;
2839 }
2840 }
2841 return index;
2842}
2843
Jamie Madillb98c3a82015-07-23 14:26:04 -04002844TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
2845 const TSourceLoc &dotLocation,
2846 const TString &fieldString,
2847 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002848{
2849 TIntermTyped *indexedExpression = NULL;
2850
2851 if (baseExpression->isArray())
2852 {
2853 error(fieldLocation, "cannot apply dot operator to an array", ".");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002854 }
2855
2856 if (baseExpression->isVector())
2857 {
2858 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002859 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
2860 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002861 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002862 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002863 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002864 }
2865
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002866 if (baseExpression->getAsConstantUnion())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002867 {
2868 // constant folding for vector fields
Olli Etuaho90892fb2016-07-14 14:44:51 +03002869 indexedExpression =
2870 foldVectorSwizzle(fields, baseExpression->getAsConstantUnion(), fieldLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002871 }
2872 else
2873 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302874 TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002875 indexedExpression =
2876 intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002877 }
2878 if (indexedExpression == nullptr)
2879 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002880 indexedExpression = baseExpression;
2881 }
2882 else
2883 {
2884 // Note that the qualifier set here will be corrected later.
Jamie Madillb98c3a82015-07-23 14:26:04 -04002885 indexedExpression->setType(TType(baseExpression->getBasicType(),
2886 baseExpression->getPrecision(), EvqTemporary,
Jamie Madillc2128ff2016-07-04 10:26:17 -04002887 static_cast<unsigned char>(fields.num)));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002888 }
2889 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002890 else if (baseExpression->getBasicType() == EbtStruct)
2891 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002892 bool fieldFound = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302893 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04002894 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002895 {
2896 error(dotLocation, "structure has no fields", "Internal Error");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002897 indexedExpression = baseExpression;
2898 }
2899 else
2900 {
2901 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04002902 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002903 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002904 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002905 {
2906 fieldFound = true;
2907 break;
2908 }
2909 }
2910 if (fieldFound)
2911 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002912 if (baseExpression->getAsConstantUnion())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002913 {
2914 indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
2915 if (indexedExpression == 0)
2916 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002917 indexedExpression = baseExpression;
2918 }
2919 else
2920 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002921 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002922 }
2923 }
2924 else
2925 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002926 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002927 unionArray->setIConst(i);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002928 TIntermTyped *index = intermediate.addConstantUnion(
2929 unionArray, *fields[i]->type(), fieldLocation);
2930 indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression,
2931 index, dotLocation);
Jamie Madill98493dd2013-07-08 14:39:03 -04002932 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002933 }
2934 }
2935 else
2936 {
2937 error(dotLocation, " no such field in structure", fieldString.c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002938 indexedExpression = baseExpression;
2939 }
2940 }
2941 }
Jamie Madill98493dd2013-07-08 14:39:03 -04002942 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002943 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002944 bool fieldFound = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302945 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04002946 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002947 {
2948 error(dotLocation, "interface block has no fields", "Internal Error");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002949 indexedExpression = baseExpression;
2950 }
2951 else
2952 {
2953 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04002954 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002955 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002956 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002957 {
2958 fieldFound = true;
2959 break;
2960 }
2961 }
2962 if (fieldFound)
2963 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002964 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002965 unionArray->setIConst(i);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002966 TIntermTyped *index =
2967 intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
2968 indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock,
2969 baseExpression, index, dotLocation);
Jamie Madill98493dd2013-07-08 14:39:03 -04002970 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002971 }
2972 else
2973 {
2974 error(dotLocation, " no such field in interface block", fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002975 indexedExpression = baseExpression;
2976 }
2977 }
2978 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002979 else
2980 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002981 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002982 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03002983 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05302984 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002985 }
2986 else
2987 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302988 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03002989 " field selection requires structure, vector, or interface block on left hand "
2990 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05302991 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002992 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002993 indexedExpression = baseExpression;
2994 }
2995
Olli Etuahob1edc4f2015-11-02 17:20:03 +02002996 if (baseExpression->getQualifier() == EvqConst)
2997 {
2998 indexedExpression->getTypePointer()->setQualifier(EvqConst);
2999 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003000 else
3001 {
3002 indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
3003 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02003004
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003005 return indexedExpression;
3006}
3007
Jamie Madillb98c3a82015-07-23 14:26:04 -04003008TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3009 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003010{
Martin Radev802abe02016-08-04 17:48:32 +03003011 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003012
3013 if (qualifierType == "shared")
3014 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003015 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003016 }
3017 else if (qualifierType == "packed")
3018 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003019 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003020 }
3021 else if (qualifierType == "std140")
3022 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003023 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003024 }
3025 else if (qualifierType == "row_major")
3026 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003027 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003028 }
3029 else if (qualifierType == "column_major")
3030 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003031 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003032 }
3033 else if (qualifierType == "location")
3034 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003035 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(),
3036 "location requires an argument");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003037 }
3038 else
3039 {
3040 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003041 }
3042
Jamie Madilla5efff92013-06-06 11:56:47 -04003043 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003044}
3045
Martin Radev802abe02016-08-04 17:48:32 +03003046void TParseContext::parseLocalSize(const TString &qualifierType,
3047 const TSourceLoc &qualifierTypeLine,
3048 int intValue,
3049 const TSourceLoc &intValueLine,
3050 const std::string &intValueString,
3051 size_t index,
3052 TLocalSize *localSize)
3053{
Olli Etuaho856c4972016-08-08 11:38:39 +03003054 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03003055 if (intValue < 1)
3056 {
3057 std::string errorMessage = std::string(getLocalSizeString(index)) + " must be positive";
3058 error(intValueLine, "out of range:", intValueString.c_str(), errorMessage.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003059 }
3060 (*localSize)[index] = intValue;
3061}
3062
Jamie Madillb98c3a82015-07-23 14:26:04 -04003063TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3064 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003065 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303066 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003067{
Martin Radev802abe02016-08-04 17:48:32 +03003068 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003069
Martin Radev802abe02016-08-04 17:48:32 +03003070 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003071
Martin Radev802abe02016-08-04 17:48:32 +03003072 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003073 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003074 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003075 if (intValue < 0)
3076 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003077 error(intValueLine, "out of range:", intValueString.c_str(),
3078 "location must be non-negative");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003079 }
3080 else
3081 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003082 qualifier.location = intValue;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003083 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003084 }
Martin Radev802abe02016-08-04 17:48:32 +03003085 else if (qualifierType == "local_size_x")
3086 {
3087 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3088 &qualifier.localSize);
3089 }
3090 else if (qualifierType == "local_size_y")
3091 {
3092 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3093 &qualifier.localSize);
3094 }
3095 else if (qualifierType == "local_size_z")
3096 {
3097 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3098 &qualifier.localSize);
3099 }
3100 else
3101 {
3102 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003103 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003104
Jamie Madilla5efff92013-06-06 11:56:47 -04003105 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003106}
3107
Jamie Madillb98c3a82015-07-23 14:26:04 -04003108TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003109 TLayoutQualifier rightQualifier,
3110 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003111{
Jamie Madilla5efff92013-06-06 11:56:47 -04003112 TLayoutQualifier joinedQualifier = leftQualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003113
Jamie Madilla5efff92013-06-06 11:56:47 -04003114 if (rightQualifier.location != -1)
3115 {
3116 joinedQualifier.location = rightQualifier.location;
3117 }
3118 if (rightQualifier.matrixPacking != EmpUnspecified)
3119 {
3120 joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
3121 }
3122 if (rightQualifier.blockStorage != EbsUnspecified)
3123 {
3124 joinedQualifier.blockStorage = rightQualifier.blockStorage;
3125 }
3126
Martin Radev802abe02016-08-04 17:48:32 +03003127 for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i)
3128 {
3129 if (rightQualifier.localSize[i] != -1)
3130 {
3131 if (joinedQualifier.localSize[i] != -1 &&
3132 joinedQualifier.localSize[i] != rightQualifier.localSize[i])
3133 {
3134 error(rightQualifierLocation,
3135 "Cannot have multiple different work group size specifiers",
3136 getLocalSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03003137 }
3138 joinedQualifier.localSize[i] = rightQualifier.localSize[i];
3139 }
3140 }
3141
Jamie Madilla5efff92013-06-06 11:56:47 -04003142 return joinedQualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003143}
3144
Arun Patole7e7e68d2015-05-22 12:02:25 +05303145TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc,
3146 TQualifier interpolationQualifier,
3147 const TSourceLoc &storageLoc,
3148 TQualifier storageQualifier)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003149{
3150 TQualifier mergedQualifier = EvqSmoothIn;
3151
Arun Patole7e7e68d2015-05-22 12:02:25 +05303152 if (storageQualifier == EvqFragmentIn)
3153 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003154 if (interpolationQualifier == EvqSmooth)
3155 mergedQualifier = EvqSmoothIn;
3156 else if (interpolationQualifier == EvqFlat)
3157 mergedQualifier = EvqFlatIn;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003158 else
3159 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003160 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303161 else if (storageQualifier == EvqCentroidIn)
3162 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003163 if (interpolationQualifier == EvqSmooth)
3164 mergedQualifier = EvqCentroidIn;
3165 else if (interpolationQualifier == EvqFlat)
3166 mergedQualifier = EvqFlatIn;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003167 else
3168 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003169 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303170 else if (storageQualifier == EvqVertexOut)
3171 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003172 if (interpolationQualifier == EvqSmooth)
3173 mergedQualifier = EvqSmoothOut;
3174 else if (interpolationQualifier == EvqFlat)
3175 mergedQualifier = EvqFlatOut;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003176 else
3177 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003178 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303179 else if (storageQualifier == EvqCentroidOut)
3180 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003181 if (interpolationQualifier == EvqSmooth)
3182 mergedQualifier = EvqCentroidOut;
3183 else if (interpolationQualifier == EvqFlat)
3184 mergedQualifier = EvqFlatOut;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003185 else
3186 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003187 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303188 else
3189 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003190 error(interpolationLoc,
3191 "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303192 getInterpolationString(interpolationQualifier));
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003193
3194 mergedQualifier = storageQualifier;
3195 }
3196
3197 TPublicType type;
3198 type.setBasic(EbtVoid, mergedQualifier, storageLoc);
3199 return type;
3200}
3201
Jamie Madillb98c3a82015-07-23 14:26:04 -04003202TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3203 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003204{
Olli Etuaho856c4972016-08-08 11:38:39 +03003205 checkIsNonVoid(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003206
Olli Etuaho856c4972016-08-08 11:38:39 +03003207 checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003208
Arun Patole7e7e68d2015-05-22 12:02:25 +05303209 for (unsigned int i = 0; i < fieldList->size(); ++i)
3210 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003211 //
3212 // Careful not to replace already known aspects of type, like array-ness
3213 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303214 TType *type = (*fieldList)[i]->type();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003215 type->setBasicType(typeSpecifier.type);
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003216 type->setPrimarySize(typeSpecifier.primarySize);
3217 type->setSecondarySize(typeSpecifier.secondarySize);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003218 type->setPrecision(typeSpecifier.precision);
3219 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003220 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003221
3222 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303223 if (type->isArray())
3224 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003225 checkIsValidTypeForArray(typeSpecifier.line, typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003226 }
3227 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003228 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Arun Patole7e7e68d2015-05-22 12:02:25 +05303229 if (typeSpecifier.userDef)
3230 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003231 type->setStruct(typeSpecifier.userDef->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003232 }
3233
Olli Etuaho8a176262016-08-16 14:23:01 +03003234 checkIsBelowStructNestingLimit(typeSpecifier.line, *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003235 }
3236
Jamie Madill98493dd2013-07-08 14:39:03 -04003237 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003238}
3239
Jamie Madillb98c3a82015-07-23 14:26:04 -04003240TPublicType TParseContext::addStructure(const TSourceLoc &structLine,
3241 const TSourceLoc &nameLine,
3242 const TString *structName,
3243 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003244{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303245 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003246 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003247
Jamie Madill9b820842015-02-12 10:40:10 -05003248 // Store a bool in the struct if we're at global scope, to allow us to
3249 // skip the local struct scoping workaround in HLSL.
Jamie Madillb960cc42015-02-12 15:33:20 +00003250 structure->setUniqueId(TSymbolTable::nextUniqueId());
Jamie Madill9b820842015-02-12 10:40:10 -05003251 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003252
Jamie Madill98493dd2013-07-08 14:39:03 -04003253 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003254 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003255 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303256 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3257 if (!symbolTable.declare(userTypeDef))
3258 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003259 error(nameLine, "redefinition", structName->c_str(), "struct");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003260 }
3261 }
3262
3263 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003264 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003265 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003266 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003267 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003268 switch (qualifier)
3269 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003270 case EvqGlobal:
3271 case EvqTemporary:
3272 break;
3273 default:
3274 error(field.line(), "invalid qualifier on struct member",
3275 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003276 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003277 }
3278 }
3279
3280 TPublicType publicType;
3281 publicType.setBasic(EbtStruct, EvqTemporary, structLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04003282 publicType.userDef = structureType;
Olli Etuahobd163f62015-11-13 12:15:38 +02003283 publicType.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003284 exitStructDeclaration();
3285
3286 return publicType;
3287}
3288
Jamie Madillb98c3a82015-07-23 14:26:04 -04003289TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
3290 TIntermAggregate *statementList,
3291 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003292{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003293 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003294 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003295 init->isVector())
3296 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003297 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3298 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003299 return nullptr;
3300 }
3301
Olli Etuahoac5274d2015-02-20 10:19:08 +02003302 if (statementList)
3303 {
3304 if (!ValidateSwitch::validate(switchType, this, statementList, loc))
3305 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003306 return nullptr;
3307 }
3308 }
3309
Olli Etuahoa3a36662015-02-17 13:46:51 +02003310 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3311 if (node == nullptr)
3312 {
3313 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003314 return nullptr;
3315 }
3316 return node;
3317}
3318
3319TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3320{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003321 if (mSwitchNestingLevel == 0)
3322 {
3323 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003324 return nullptr;
3325 }
3326 if (condition == nullptr)
3327 {
3328 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003329 return nullptr;
3330 }
3331 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003332 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003333 {
3334 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003335 }
3336 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003337 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3338 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3339 // fold in case labels.
3340 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003341 {
3342 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003343 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003344 TIntermCase *node = intermediate.addCase(condition, loc);
3345 if (node == nullptr)
3346 {
3347 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003348 return nullptr;
3349 }
3350 return node;
3351}
3352
3353TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3354{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003355 if (mSwitchNestingLevel == 0)
3356 {
3357 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003358 return nullptr;
3359 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003360 TIntermCase *node = intermediate.addCase(nullptr, loc);
3361 if (node == nullptr)
3362 {
3363 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003364 return nullptr;
3365 }
3366 return node;
3367}
3368
Jamie Madillb98c3a82015-07-23 14:26:04 -04003369TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3370 TIntermTyped *child,
3371 const TSourceLoc &loc,
3372 const TType *funcReturnType)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003373{
3374 if (child == nullptr)
3375 {
3376 return nullptr;
3377 }
3378
3379 switch (op)
3380 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003381 case EOpLogicalNot:
3382 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3383 child->isVector())
3384 {
3385 return nullptr;
3386 }
3387 break;
3388 case EOpBitwiseNot:
3389 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3390 child->isMatrix() || child->isArray())
3391 {
3392 return nullptr;
3393 }
3394 break;
3395 case EOpPostIncrement:
3396 case EOpPreIncrement:
3397 case EOpPostDecrement:
3398 case EOpPreDecrement:
3399 case EOpNegative:
3400 case EOpPositive:
3401 if (child->getBasicType() == EbtStruct || child->getBasicType() == EbtBool ||
3402 child->isArray())
3403 {
3404 return nullptr;
3405 }
3406 // Operators for built-ins are already type checked against their prototype.
3407 default:
3408 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003409 }
3410
Olli Etuahof6c694b2015-03-26 14:50:53 +02003411 return intermediate.addUnaryMath(op, child, loc, funcReturnType);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003412}
3413
Olli Etuaho09b22472015-02-11 11:47:26 +02003414TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3415{
Olli Etuahof6c694b2015-03-26 14:50:53 +02003416 TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003417 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003418 {
3419 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003420 return child;
3421 }
3422 return node;
3423}
3424
Jamie Madillb98c3a82015-07-23 14:26:04 -04003425TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3426 TIntermTyped *child,
3427 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003428{
Olli Etuaho856c4972016-08-08 11:38:39 +03003429 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003430 return addUnaryMath(op, child, loc);
3431}
3432
Jamie Madillb98c3a82015-07-23 14:26:04 -04003433bool TParseContext::binaryOpCommonCheck(TOperator op,
3434 TIntermTyped *left,
3435 TIntermTyped *right,
3436 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003437{
Olli Etuaho244be012016-08-18 15:26:02 +03003438 if (left->getType().getStruct() || right->getType().getStruct())
3439 {
3440 switch (op)
3441 {
3442 case EOpIndexDirectStruct:
3443 ASSERT(left->getType().getStruct());
3444 break;
3445 case EOpEqual:
3446 case EOpNotEqual:
3447 case EOpAssign:
3448 case EOpInitialize:
3449 if (left->getType() != right->getType())
3450 {
3451 return false;
3452 }
3453 break;
3454 default:
3455 error(loc, "Invalid operation for structs", GetOperatorString(op));
3456 return false;
3457 }
3458 }
3459
Olli Etuahod6b14282015-03-17 14:31:35 +02003460 if (left->isArray() || right->isArray())
3461 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003462 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003463 {
3464 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3465 return false;
3466 }
3467
3468 if (left->isArray() != right->isArray())
3469 {
3470 error(loc, "array / non-array mismatch", GetOperatorString(op));
3471 return false;
3472 }
3473
3474 switch (op)
3475 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003476 case EOpEqual:
3477 case EOpNotEqual:
3478 case EOpAssign:
3479 case EOpInitialize:
3480 break;
3481 default:
3482 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3483 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02003484 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03003485 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02003486 if (left->getArraySize() != right->getArraySize())
3487 {
3488 error(loc, "array size mismatch", GetOperatorString(op));
3489 return false;
3490 }
Olli Etuahod6b14282015-03-17 14:31:35 +02003491 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003492
3493 // Check ops which require integer / ivec parameters
3494 bool isBitShift = false;
3495 switch (op)
3496 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003497 case EOpBitShiftLeft:
3498 case EOpBitShiftRight:
3499 case EOpBitShiftLeftAssign:
3500 case EOpBitShiftRightAssign:
3501 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3502 // check that the basic type is an integer type.
3503 isBitShift = true;
3504 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3505 {
3506 return false;
3507 }
3508 break;
3509 case EOpBitwiseAnd:
3510 case EOpBitwiseXor:
3511 case EOpBitwiseOr:
3512 case EOpBitwiseAndAssign:
3513 case EOpBitwiseXorAssign:
3514 case EOpBitwiseOrAssign:
3515 // It is enough to check the type of only one operand, since later it
3516 // is checked that the operand types match.
3517 if (!IsInteger(left->getBasicType()))
3518 {
3519 return false;
3520 }
3521 break;
3522 default:
3523 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003524 }
3525
3526 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3527 // So the basic type should usually match.
3528 if (!isBitShift && left->getBasicType() != right->getBasicType())
3529 {
3530 return false;
3531 }
3532
Olli Etuaho9dd217b2015-03-20 14:24:31 +02003533 // Check that type sizes match exactly on ops that require that.
Olli Etuahoff699002015-03-23 14:38:42 +02003534 // Also check restrictions for structs that contain arrays or samplers.
Jamie Madillb98c3a82015-07-23 14:26:04 -04003535 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003536 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003537 case EOpAssign:
3538 case EOpInitialize:
3539 case EOpEqual:
3540 case EOpNotEqual:
3541 // ESSL 1.00 sections 5.7, 5.8, 5.9
3542 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
3543 {
3544 error(loc, "undefined operation for structs containing arrays",
3545 GetOperatorString(op));
3546 return false;
3547 }
3548 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3549 // we interpret the spec so that this extends to structs containing samplers,
3550 // similarly to ESSL 1.00 spec.
3551 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
3552 left->getType().isStructureContainingSamplers())
3553 {
3554 error(loc, "undefined operation for structs containing samplers",
3555 GetOperatorString(op));
3556 return false;
3557 }
3558 case EOpLessThan:
3559 case EOpGreaterThan:
3560 case EOpLessThanEqual:
3561 case EOpGreaterThanEqual:
3562 if ((left->getNominalSize() != right->getNominalSize()) ||
3563 (left->getSecondarySize() != right->getSecondarySize()))
3564 {
3565 return false;
3566 }
3567 default:
3568 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003569 }
3570
Olli Etuahod6b14282015-03-17 14:31:35 +02003571 return true;
3572}
3573
Jamie Madillb98c3a82015-07-23 14:26:04 -04003574TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
3575 TIntermTyped *left,
3576 TIntermTyped *right,
3577 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02003578{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003579 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003580 return nullptr;
3581
Olli Etuahofc1806e2015-03-17 13:03:11 +02003582 switch (op)
3583 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003584 case EOpEqual:
3585 case EOpNotEqual:
3586 break;
3587 case EOpLessThan:
3588 case EOpGreaterThan:
3589 case EOpLessThanEqual:
3590 case EOpGreaterThanEqual:
Olli Etuaho244be012016-08-18 15:26:02 +03003591 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3592 !right->getType().getStruct());
3593 if (left->isMatrix() || left->isVector())
Jamie Madillb98c3a82015-07-23 14:26:04 -04003594 {
3595 return nullptr;
3596 }
3597 break;
3598 case EOpLogicalOr:
3599 case EOpLogicalXor:
3600 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03003601 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3602 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003603 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isVector())
3604 {
3605 return nullptr;
3606 }
3607 break;
3608 case EOpAdd:
3609 case EOpSub:
3610 case EOpDiv:
3611 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03003612 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3613 !right->getType().getStruct());
3614 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04003615 {
3616 return nullptr;
3617 }
3618 break;
3619 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03003620 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3621 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003622 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03003623 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04003624 {
3625 return nullptr;
3626 }
3627 break;
3628 // Note that for bitwise ops, type checking is done in promote() to
3629 // share code between ops and compound assignment
3630 default:
3631 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02003632 }
3633
Olli Etuahofc1806e2015-03-17 13:03:11 +02003634 return intermediate.addBinaryMath(op, left, right, loc);
3635}
3636
Jamie Madillb98c3a82015-07-23 14:26:04 -04003637TIntermTyped *TParseContext::addBinaryMath(TOperator op,
3638 TIntermTyped *left,
3639 TIntermTyped *right,
3640 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003641{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003642 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003643 if (node == 0)
3644 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003645 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3646 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003647 return left;
3648 }
3649 return node;
3650}
3651
Jamie Madillb98c3a82015-07-23 14:26:04 -04003652TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
3653 TIntermTyped *left,
3654 TIntermTyped *right,
3655 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003656{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003657 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003658 if (node == 0)
3659 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003660 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3661 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003662 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02003663 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003664 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
3665 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003666 }
3667 return node;
3668}
3669
Jamie Madillb98c3a82015-07-23 14:26:04 -04003670TIntermTyped *TParseContext::createAssign(TOperator op,
3671 TIntermTyped *left,
3672 TIntermTyped *right,
3673 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003674{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003675 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003676 {
3677 return intermediate.addAssign(op, left, right, loc);
3678 }
3679 return nullptr;
3680}
3681
Jamie Madillb98c3a82015-07-23 14:26:04 -04003682TIntermTyped *TParseContext::addAssign(TOperator op,
3683 TIntermTyped *left,
3684 TIntermTyped *right,
3685 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003686{
3687 TIntermTyped *node = createAssign(op, left, right, loc);
3688 if (node == nullptr)
3689 {
3690 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02003691 return left;
3692 }
3693 return node;
3694}
3695
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02003696TIntermTyped *TParseContext::addComma(TIntermTyped *left,
3697 TIntermTyped *right,
3698 const TSourceLoc &loc)
3699{
Corentin Wallez0d959252016-07-12 17:26:32 -04003700 // WebGL2 section 5.26, the following results in an error:
3701 // "Sequence operator applied to void, arrays, or structs containing arrays"
3702 if (mShaderSpec == SH_WEBGL2_SPEC && (left->isArray() || left->getBasicType() == EbtVoid ||
3703 left->getType().isStructureContainingArrays() ||
3704 right->isArray() || right->getBasicType() == EbtVoid ||
3705 right->getType().isStructureContainingArrays()))
3706 {
3707 error(loc,
3708 "sequence operator is not allowed for void, arrays, or structs containing arrays",
3709 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04003710 }
3711
Olli Etuaho15200042015-11-04 16:56:31 +02003712 return intermediate.addComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02003713}
3714
Olli Etuaho49300862015-02-20 14:54:49 +02003715TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
3716{
3717 switch (op)
3718 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003719 case EOpContinue:
3720 if (mLoopNestingLevel <= 0)
3721 {
3722 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003723 }
3724 break;
3725 case EOpBreak:
3726 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
3727 {
3728 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003729 }
3730 break;
3731 case EOpReturn:
3732 if (mCurrentFunctionType->getBasicType() != EbtVoid)
3733 {
3734 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003735 }
3736 break;
3737 default:
3738 // No checks for discard
3739 break;
Olli Etuaho49300862015-02-20 14:54:49 +02003740 }
3741 return intermediate.addBranch(op, loc);
3742}
3743
Jamie Madillb98c3a82015-07-23 14:26:04 -04003744TIntermBranch *TParseContext::addBranch(TOperator op,
3745 TIntermTyped *returnValue,
3746 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02003747{
3748 ASSERT(op == EOpReturn);
3749 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003750 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02003751 {
3752 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02003753 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003754 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02003755 {
3756 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02003757 }
3758 return intermediate.addBranch(op, returnValue, loc);
3759}
3760
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003761void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
3762{
3763 ASSERT(!functionCall->isUserDefined());
3764 const TString &name = functionCall->getName();
3765 TIntermNode *offset = nullptr;
3766 TIntermSequence *arguments = functionCall->getSequence();
3767 if (name.compare(0, 16, "texelFetchOffset") == 0 ||
3768 name.compare(0, 16, "textureLodOffset") == 0 ||
3769 name.compare(0, 20, "textureProjLodOffset") == 0 ||
3770 name.compare(0, 17, "textureGradOffset") == 0 ||
3771 name.compare(0, 21, "textureProjGradOffset") == 0)
3772 {
3773 offset = arguments->back();
3774 }
3775 else if (name.compare(0, 13, "textureOffset") == 0 ||
3776 name.compare(0, 17, "textureProjOffset") == 0)
3777 {
3778 // A bias parameter might follow the offset parameter.
3779 ASSERT(arguments->size() >= 3);
3780 offset = (*arguments)[2];
3781 }
3782 if (offset != nullptr)
3783 {
3784 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
3785 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
3786 {
3787 TString unmangledName = TFunction::unmangleName(name);
3788 error(functionCall->getLine(), "Texture offset must be a constant expression",
3789 unmangledName.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003790 }
3791 else
3792 {
3793 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
3794 size_t size = offsetConstantUnion->getType().getObjectSize();
3795 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
3796 for (size_t i = 0u; i < size; ++i)
3797 {
3798 int offsetValue = values[i].getIConst();
3799 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
3800 {
3801 std::stringstream tokenStream;
3802 tokenStream << offsetValue;
3803 std::string token = tokenStream.str();
3804 error(offset->getLine(), "Texture offset value out of valid range",
3805 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003806 }
3807 }
3808 }
3809 }
3810}
3811
Jamie Madillb98c3a82015-07-23 14:26:04 -04003812TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
3813 TIntermNode *paramNode,
3814 TIntermNode *thisNode,
3815 const TSourceLoc &loc,
3816 bool *fatalError)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003817{
Jamie Madillb98c3a82015-07-23 14:26:04 -04003818 *fatalError = false;
3819 TOperator op = fnCall->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003820 TIntermTyped *callNode = nullptr;
3821
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003822 if (thisNode != nullptr)
3823 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003824 TConstantUnion *unionArray = new TConstantUnion[1];
Jamie Madillb98c3a82015-07-23 14:26:04 -04003825 int arraySize = 0;
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003826 TIntermTyped *typedThis = thisNode->getAsTyped();
3827 if (fnCall->getName() != "length")
3828 {
3829 error(loc, "invalid method", fnCall->getName().c_str());
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003830 }
3831 else if (paramNode != nullptr)
3832 {
3833 error(loc, "method takes no parameters", "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003834 }
3835 else if (typedThis == nullptr || !typedThis->isArray())
3836 {
3837 error(loc, "length can only be called on arrays", "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003838 }
3839 else
3840 {
Olli Etuaho96e67382015-04-23 14:27:02 +03003841 arraySize = typedThis->getArraySize();
Olli Etuaho39282e12015-04-23 15:41:48 +03003842 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003843 {
Olli Etuaho39282e12015-04-23 15:41:48 +03003844 // This code path can be hit with expressions like these:
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003845 // (a = b).length()
Olli Etuaho39282e12015-04-23 15:41:48 +03003846 // (func()).length()
3847 // (int[3](0, 1, 2)).length()
Jamie Madillb98c3a82015-07-23 14:26:04 -04003848 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
3849 // expression.
3850 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
3851 // spec section 5.9 which allows "An array, vector or matrix expression with the
3852 // length method applied".
3853 error(loc, "length can only be called on array names, not on array expressions",
3854 "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003855 }
3856 }
Olli Etuaho96e67382015-04-23 14:27:02 +03003857 unionArray->setIConst(arraySize);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003858 callNode =
3859 intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003860 }
3861 else if (op != EOpNull)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003862 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003863 // Then this should be a constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +03003864 callNode = addConstructor(paramNode, op, fnCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003865 }
3866 else
3867 {
3868 //
3869 // Not a constructor. Find it in the symbol table.
3870 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303871 const TFunction *fnCandidate;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003872 bool builtIn;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003873 fnCandidate = findFunction(loc, fnCall, mShaderVersion, &builtIn);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003874 if (fnCandidate)
3875 {
3876 //
3877 // A declared function.
3878 //
Olli Etuaho383b7912016-08-05 11:22:59 +03003879 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003880 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003881 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003882 }
3883 op = fnCandidate->getBuiltInOp();
3884 if (builtIn && op != EOpNull)
3885 {
3886 //
3887 // A function call mapped to a built-in operation.
3888 //
3889 if (fnCandidate->getParamCount() == 1)
3890 {
3891 //
3892 // Treat it like a built-in unary operator.
3893 //
Olli Etuaho15c2ac32015-11-09 15:51:43 +02003894 TIntermAggregate *paramAgg = paramNode->getAsAggregate();
3895 paramNode = paramAgg->getSequence()->front();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003896 callNode = createUnaryMath(op, paramNode->getAsTyped(), loc,
3897 &fnCandidate->getReturnType());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003898 if (callNode == nullptr)
3899 {
3900 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003901 extraInfoStream
3902 << "built in unary operator function. Type: "
3903 << static_cast<TIntermTyped *>(paramNode)->getCompleteString();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003904 std::string extraInfo = extraInfoStream.str();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003905 error(paramNode->getLine(), " wrong operand type", "Internal Error",
3906 extraInfo.c_str());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003907 *fatalError = true;
3908 return nullptr;
3909 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003910 }
3911 else
3912 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003913 TIntermAggregate *aggregate =
3914 intermediate.setAggregateOperator(paramNode, op, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003915 aggregate->setType(fnCandidate->getReturnType());
3916 aggregate->setPrecisionFromChildren();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02003917 if (aggregate->areChildrenConstQualified())
3918 {
3919 aggregate->getTypePointer()->setQualifier(EvqConst);
3920 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003921
3922 // Some built-in functions have out parameters too.
3923 functionCallLValueErrorCheck(fnCandidate, aggregate);
Arun Patole274f0702015-05-05 13:33:30 +05303924
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003925 // See if we can constant fold a built-in. Note that this may be possible even
3926 // if it is not const-qualified.
Olli Etuahob43846e2015-06-02 18:18:57 +03003927 TIntermTyped *foldedNode = intermediate.foldAggregateBuiltIn(aggregate);
Arun Patole274f0702015-05-05 13:33:30 +05303928 if (foldedNode)
3929 {
Arun Patole274f0702015-05-05 13:33:30 +05303930 callNode = foldedNode;
3931 }
Olli Etuahob43846e2015-06-02 18:18:57 +03003932 else
3933 {
3934 callNode = aggregate;
3935 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003936 }
3937 }
3938 else
3939 {
3940 // This is a real function call
Jamie Madillb98c3a82015-07-23 14:26:04 -04003941 TIntermAggregate *aggregate =
3942 intermediate.setAggregateOperator(paramNode, EOpFunctionCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003943 aggregate->setType(fnCandidate->getReturnType());
3944
Jamie Madillb98c3a82015-07-23 14:26:04 -04003945 // this is how we know whether the given function is a builtIn function or a user
3946 // defined function
3947 // if builtIn == false, it's a userDefined -> could be an overloaded
3948 // builtIn function also
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003949 // if builtIn == true, it's definitely a builtIn function with EOpNull
3950 if (!builtIn)
3951 aggregate->setUserDefined();
3952 aggregate->setName(fnCandidate->getMangledName());
Corentin Wallez71d147f2015-02-11 11:15:24 -08003953 aggregate->setFunctionId(fnCandidate->getUniqueId());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003954
3955 // This needs to happen after the name is set
3956 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003957 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003958 aggregate->setBuiltInFunctionPrecision();
3959
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003960 checkTextureOffsetConst(aggregate);
3961 }
3962
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003963 callNode = aggregate;
3964
3965 functionCallLValueErrorCheck(fnCandidate, aggregate);
3966 }
3967 }
3968 else
3969 {
3970 // error message was put out by findFunction()
3971 // Put on a dummy node for error recovery
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003972 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003973 unionArray->setFConst(0.0f);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003974 callNode = intermediate.addConstantUnion(unionArray,
3975 TType(EbtFloat, EbpUndefined, EvqConst), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003976 }
3977 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003978 return callNode;
3979}
3980
Jamie Madillb98c3a82015-07-23 14:26:04 -04003981TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
3982 TIntermTyped *trueBlock,
3983 TIntermTyped *falseBlock,
Olli Etuaho52901742015-04-15 13:42:45 +03003984 const TSourceLoc &loc)
3985{
Olli Etuaho856c4972016-08-08 11:38:39 +03003986 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03003987
3988 if (trueBlock->getType() != falseBlock->getType())
3989 {
3990 binaryOpError(loc, ":", trueBlock->getCompleteString(), falseBlock->getCompleteString());
Olli Etuaho52901742015-04-15 13:42:45 +03003991 return falseBlock;
3992 }
Olli Etuahoa2d53032015-04-15 14:14:44 +03003993 // ESSL1 sections 5.2 and 5.7:
3994 // ESSL3 section 5.7:
3995 // Ternary operator is not among the operators allowed for structures/arrays.
3996 if (trueBlock->isArray() || trueBlock->getBasicType() == EbtStruct)
3997 {
3998 error(loc, "ternary operator is not allowed for structures or arrays", ":");
Olli Etuahoa2d53032015-04-15 14:14:44 +03003999 return falseBlock;
4000 }
Corentin Wallez0d959252016-07-12 17:26:32 -04004001 // WebGL2 section 5.26, the following results in an error:
4002 // "Ternary operator applied to void, arrays, or structs containing arrays"
4003 if (mShaderSpec == SH_WEBGL2_SPEC && trueBlock->getBasicType() == EbtVoid)
4004 {
4005 error(loc, "ternary operator is not allowed for void", ":");
Corentin Wallez0d959252016-07-12 17:26:32 -04004006 return falseBlock;
4007 }
4008
Olli Etuaho52901742015-04-15 13:42:45 +03004009 return intermediate.addSelection(cond, trueBlock, falseBlock, loc);
4010}
Olli Etuaho49300862015-02-20 14:54:49 +02004011
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004012//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004013// Parse an array of strings using yyparse.
4014//
4015// Returns 0 for success.
4016//
Jamie Madillb98c3a82015-07-23 14:26:04 -04004017int PaParseStrings(size_t count,
4018 const char *const string[],
4019 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05304020 TParseContext *context)
4021{
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004022 if ((count == 0) || (string == NULL))
4023 return 1;
4024
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004025 if (glslang_initialize(context))
4026 return 1;
4027
alokp@chromium.org408c45e2012-04-05 15:54:43 +00004028 int error = glslang_scan(count, string, length, context);
4029 if (!error)
4030 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004031
alokp@chromium.org73bc2982012-06-19 18:48:05 +00004032 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00004033
alokp@chromium.org6b495712012-06-29 00:06:58 +00004034 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004035}