blob: 8240f945c9cdd752912bfe737d6ae44c00670133 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Jamie Madill6b9cb252013-10-17 10:45:47 -04007#include "compiler/translator/ParseContext.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +00008
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00009#include <stdarg.h>
apatrick@chromium.org8187fa82010-06-15 22:09:28 +000010#include <stdio.h>
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000011
daniel@transgaming.comb401a922012-10-26 18:58:24 +000012#include "compiler/preprocessor/SourceLocation.h"
Dmitry Skiba01971112015-07-10 14:54:00 -040013#include "compiler/translator/Cache.h"
Olli Etuahoac5274d2015-02-20 10:19:08 +020014#include "compiler/translator/glslang.h"
15#include "compiler/translator/ValidateSwitch.h"
Olli Etuahob0c645e2015-05-12 14:25:36 +030016#include "compiler/translator/ValidateGlobalInitializer.h"
Olli Etuaho37ad4742015-04-27 13:18:50 +030017#include "compiler/translator/util.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000018
alokp@chromium.org8b851c62012-06-15 16:25:11 +000019///////////////////////////////////////////////////////////////////////
20//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000021// Sub- vector and matrix fields
22//
23////////////////////////////////////////////////////////////////////////
24
25//
26// Look at a '.' field selector string and change it into offsets
27// for a vector.
28//
Jamie Madillb98c3a82015-07-23 14:26:04 -040029bool TParseContext::parseVectorFields(const TString &compString,
30 int vecSize,
31 TVectorFields &fields,
Arun Patole7e7e68d2015-05-22 12:02:25 +053032 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000033{
Jamie Madillb98c3a82015-07-23 14:26:04 -040034 fields.num = (int)compString.size();
Arun Patole7e7e68d2015-05-22 12:02:25 +053035 if (fields.num > 4)
36 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +000037 error(line, "illegal vector field selection", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +000038 return false;
39 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000040
Jamie Madillb98c3a82015-07-23 14:26:04 -040041 enum
42 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +000043 exyzw,
44 ergba,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +000045 estpq
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +000046 } fieldSet[4];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000047
Arun Patole7e7e68d2015-05-22 12:02:25 +053048 for (int i = 0; i < fields.num; ++i)
49 {
50 switch (compString[i])
51 {
Jamie Madillb98c3a82015-07-23 14:26:04 -040052 case 'x':
53 fields.offsets[i] = 0;
54 fieldSet[i] = exyzw;
55 break;
56 case 'r':
57 fields.offsets[i] = 0;
58 fieldSet[i] = ergba;
59 break;
60 case 's':
61 fields.offsets[i] = 0;
62 fieldSet[i] = estpq;
63 break;
64 case 'y':
65 fields.offsets[i] = 1;
66 fieldSet[i] = exyzw;
67 break;
68 case 'g':
69 fields.offsets[i] = 1;
70 fieldSet[i] = ergba;
71 break;
72 case 't':
73 fields.offsets[i] = 1;
74 fieldSet[i] = estpq;
75 break;
76 case 'z':
77 fields.offsets[i] = 2;
78 fieldSet[i] = exyzw;
79 break;
80 case 'b':
81 fields.offsets[i] = 2;
82 fieldSet[i] = ergba;
83 break;
84 case 'p':
85 fields.offsets[i] = 2;
86 fieldSet[i] = estpq;
87 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +053088
Jamie Madillb98c3a82015-07-23 14:26:04 -040089 case 'w':
90 fields.offsets[i] = 3;
91 fieldSet[i] = exyzw;
92 break;
93 case 'a':
94 fields.offsets[i] = 3;
95 fieldSet[i] = ergba;
96 break;
97 case 'q':
98 fields.offsets[i] = 3;
99 fieldSet[i] = estpq;
100 break;
101 default:
102 error(line, "illegal vector field selection", compString.c_str());
103 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000104 }
105 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000106
Arun Patole7e7e68d2015-05-22 12:02:25 +0530107 for (int i = 0; i < fields.num; ++i)
108 {
109 if (fields.offsets[i] >= vecSize)
110 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400111 error(line, "vector field selection out of range", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000112 return false;
113 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114
Arun Patole7e7e68d2015-05-22 12:02:25 +0530115 if (i > 0)
116 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400117 if (fieldSet[i] != fieldSet[i - 1])
Arun Patole7e7e68d2015-05-22 12:02:25 +0530118 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400119 error(line, "illegal - vector component fields not from the same set",
120 compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000121 return false;
122 }
123 }
124 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000126 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000127}
128
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129///////////////////////////////////////////////////////////////////////
130//
131// Errors
132//
133////////////////////////////////////////////////////////////////////////
134
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135
136//
137// Used by flex/bison to output all syntax and parsing errors.
138//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530139void TParseContext::error(const TSourceLoc &loc,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400140 const char *reason,
141 const char *token,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530142 const char *extraInfo)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000143{
Olli Etuaho1cc598f2016-08-18 13:50:30 +0300144 mDiagnostics.error(loc, reason, token, extraInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000145}
146
Arun Patole7e7e68d2015-05-22 12:02:25 +0530147void TParseContext::warning(const TSourceLoc &loc,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400148 const char *reason,
149 const char *token,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530150 const char *extraInfo)
151{
Olli Etuaho1cc598f2016-08-18 13:50:30 +0300152 mDiagnostics.warning(loc, reason, token, extraInfo);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +0000153}
154
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200155void TParseContext::outOfRangeError(bool isError,
156 const TSourceLoc &loc,
157 const char *reason,
158 const char *token,
159 const char *extraInfo)
160{
161 if (isError)
162 {
163 error(loc, reason, token, extraInfo);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200164 }
165 else
166 {
167 warning(loc, reason, token, extraInfo);
168 }
169}
170
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000171//
172// Same error message for all places assignments don't work.
173//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530174void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000176 std::stringstream extraInfoStream;
177 extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
178 std::string extraInfo = extraInfoStream.str();
179 error(line, "", op, extraInfo.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000180}
181
182//
183// Same error message for all places unary operations don't work.
184//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530185void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000186{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000187 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400188 extraInfoStream << "no operation '" << op << "' exists that takes an operand of type "
189 << operand << " (or there is no acceptable conversion)";
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000190 std::string extraInfo = extraInfoStream.str();
191 error(line, " wrong operand type", op, extraInfo.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000192}
193
194//
195// Same error message for all binary operations don't work.
196//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400197void TParseContext::binaryOpError(const TSourceLoc &line,
198 const char *op,
199 TString left,
200 TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000201{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000202 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400203 extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '"
204 << left << "' and a right operand of type '" << right
205 << "' (or there is no acceptable conversion)";
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000206 std::string extraInfo = extraInfoStream.str();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530207 error(line, " wrong operand types ", op, extraInfo.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000208}
209
Olli Etuaho856c4972016-08-08 11:38:39 +0300210void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
211 TPrecision precision,
212 TBasicType type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530213{
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400214 if (!mChecksPrecisionErrors)
Olli Etuaho383b7912016-08-05 11:22:59 +0300215 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200216 if (precision == EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530217 {
Olli Etuaho183d7e22015-11-20 15:59:09 +0200218 switch (type)
219 {
220 case EbtFloat:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400221 error(line, "No precision specified for (float)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300222 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200223 case EbtInt:
224 case EbtUInt:
225 UNREACHABLE(); // there's always a predeclared qualifier
Jamie Madillb98c3a82015-07-23 14:26:04 -0400226 error(line, "No precision specified (int)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300227 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200228 default:
229 if (IsSampler(type))
230 {
231 error(line, "No precision specified (sampler)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300232 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200233 }
234 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000235 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000236}
237
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000238// Both test and if necessary, spit out an error, to see if the node is really
239// an l-value that can be operated on this way.
Olli Etuaho856c4972016-08-08 11:38:39 +0300240bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400242 TIntermSymbol *symNode = node->getAsSymbolNode();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530243 TIntermBinary *binaryNode = node->getAsBinaryNode();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244
Arun Patole7e7e68d2015-05-22 12:02:25 +0530245 if (binaryNode)
246 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400247 switch (binaryNode->getOp())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530248 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400249 case EOpIndexDirect:
250 case EOpIndexIndirect:
251 case EOpIndexDirectStruct:
252 case EOpIndexDirectInterfaceBlock:
Olli Etuaho856c4972016-08-08 11:38:39 +0300253 return checkCanBeLValue(line, op, binaryNode->getLeft());
Jamie Madillb98c3a82015-07-23 14:26:04 -0400254 case EOpVectorSwizzle:
Olli Etuaho8a176262016-08-16 14:23:01 +0300255 {
256 bool ok = checkCanBeLValue(line, op, binaryNode->getLeft());
257 if (ok)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530258 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300259 int offsetCount[4] = {0, 0, 0, 0};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260
Olli Etuaho8a176262016-08-16 14:23:01 +0300261 TIntermAggregate *swizzleOffsets = binaryNode->getRight()->getAsAggregate();
Jamie Madillb98c3a82015-07-23 14:26:04 -0400262
Olli Etuaho8a176262016-08-16 14:23:01 +0300263 for (const auto &offset : *swizzleOffsets->getSequence())
Jamie Madillb98c3a82015-07-23 14:26:04 -0400264 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300265 int value = offset->getAsTyped()->getAsConstantUnion()->getIConst(0);
266 offsetCount[value]++;
267 if (offsetCount[value] > 1)
Jamie Madillb98c3a82015-07-23 14:26:04 -0400268 {
269 error(line, " l-value of swizzle cannot have duplicate components", op);
Olli Etuaho8a176262016-08-16 14:23:01 +0300270 return false;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400271 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000272 }
273 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274
Olli Etuaho8a176262016-08-16 14:23:01 +0300275 return ok;
276 }
Jamie Madillb98c3a82015-07-23 14:26:04 -0400277 default:
278 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000279 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000280 error(line, " l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000281
Olli Etuaho8a176262016-08-16 14:23:01 +0300282 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000283 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284
Arun Patole7e7e68d2015-05-22 12:02:25 +0530285 const char *symbol = 0;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000286 if (symNode != 0)
287 symbol = symNode->getSymbol().c_str();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288
Arun Patole7e7e68d2015-05-22 12:02:25 +0530289 const char *message = 0;
290 switch (node->getQualifier())
291 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400292 case EvqConst:
293 message = "can't modify a const";
294 break;
295 case EvqConstReadOnly:
296 message = "can't modify a const";
297 break;
298 case EvqAttribute:
299 message = "can't modify an attribute";
300 break;
301 case EvqFragmentIn:
302 message = "can't modify an input";
303 break;
304 case EvqVertexIn:
305 message = "can't modify an input";
306 break;
307 case EvqUniform:
308 message = "can't modify a uniform";
309 break;
310 case EvqVaryingIn:
311 message = "can't modify a varying";
312 break;
313 case EvqFragCoord:
314 message = "can't modify gl_FragCoord";
315 break;
316 case EvqFrontFacing:
317 message = "can't modify gl_FrontFacing";
318 break;
319 case EvqPointCoord:
320 message = "can't modify gl_PointCoord";
321 break;
Martin Radevb0883602016-08-04 17:48:58 +0300322 case EvqNumWorkGroups:
323 message = "can't modify gl_NumWorkGroups";
324 break;
325 case EvqWorkGroupSize:
326 message = "can't modify gl_WorkGroupSize";
327 break;
328 case EvqWorkGroupID:
329 message = "can't modify gl_WorkGroupID";
330 break;
331 case EvqLocalInvocationID:
332 message = "can't modify gl_LocalInvocationID";
333 break;
334 case EvqGlobalInvocationID:
335 message = "can't modify gl_GlobalInvocationID";
336 break;
337 case EvqLocalInvocationIndex:
338 message = "can't modify gl_LocalInvocationIndex";
339 break;
Martin Radev802abe02016-08-04 17:48:32 +0300340 case EvqComputeIn:
341 message = "can't modify work group size variable";
342 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400343 default:
344 //
345 // Type that can't be written to?
346 //
347 if (node->getBasicType() == EbtVoid)
348 {
349 message = "can't modify void";
350 }
351 if (IsSampler(node->getBasicType()))
352 {
353 message = "can't modify a sampler";
354 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000355 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000356
Arun Patole7e7e68d2015-05-22 12:02:25 +0530357 if (message == 0 && binaryNode == 0 && symNode == 0)
358 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000359 error(line, " l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000360
Olli Etuaho8a176262016-08-16 14:23:01 +0300361 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000362 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000364 //
365 // Everything else is okay, no error.
366 //
367 if (message == 0)
Olli Etuaho8a176262016-08-16 14:23:01 +0300368 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000369
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000370 //
371 // If we get here, we have an error and a message.
372 //
Arun Patole7e7e68d2015-05-22 12:02:25 +0530373 if (symNode)
374 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000375 std::stringstream extraInfoStream;
376 extraInfoStream << "\"" << symbol << "\" (" << message << ")";
377 std::string extraInfo = extraInfoStream.str();
378 error(line, " l-value required", op, extraInfo.c_str());
379 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530380 else
381 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000382 std::stringstream extraInfoStream;
383 extraInfoStream << "(" << message << ")";
384 std::string extraInfo = extraInfoStream.str();
385 error(line, " l-value required", op, extraInfo.c_str());
386 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000387
Olli Etuaho8a176262016-08-16 14:23:01 +0300388 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000389}
390
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000391// Both test, and if necessary spit out an error, to see if the node is really
392// a constant.
Olli Etuaho856c4972016-08-08 11:38:39 +0300393void TParseContext::checkIsConst(TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000394{
Olli Etuaho383b7912016-08-05 11:22:59 +0300395 if (node->getQualifier() != EvqConst)
396 {
397 error(node->getLine(), "constant expression required", "");
398 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000399}
400
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000401// Both test, and if necessary spit out an error, to see if the node is really
402// an integer.
Olli Etuaho856c4972016-08-08 11:38:39 +0300403void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000404{
Olli Etuaho383b7912016-08-05 11:22:59 +0300405 if (!node->isScalarInt())
406 {
407 error(node->getLine(), "integer expression required", token);
408 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000409}
410
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000411// Both test, and if necessary spit out an error, to see if we are currently
412// globally scoped.
Qiankun Miaof69682b2016-08-16 14:50:42 +0800413bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000414{
Olli Etuaho856c4972016-08-08 11:38:39 +0300415 if (!symbolTable.atGlobalLevel())
Olli Etuaho383b7912016-08-05 11:22:59 +0300416 {
417 error(line, "only allowed at global scope", token);
Qiankun Miaof69682b2016-08-16 14:50:42 +0800418 return false;
Olli Etuaho383b7912016-08-05 11:22:59 +0300419 }
Qiankun Miaof69682b2016-08-16 14:50:42 +0800420 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000421}
422
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000423// For now, keep it simple: if it starts "gl_", it's reserved, independent
424// of scope. Except, if the symbol table is at the built-in push-level,
425// which is when we are parsing built-ins.
alokp@chromium.org613ef312010-07-21 18:54:22 +0000426// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
427// webgl shader.
Olli Etuaho856c4972016-08-08 11:38:39 +0300428bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530430 static const char *reservedErrMsg = "reserved built-in name";
431 if (!symbolTable.atBuiltInLevel())
432 {
433 if (identifier.compare(0, 3, "gl_") == 0)
434 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000435 error(line, reservedErrMsg, "gl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300436 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000437 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530438 if (IsWebGLBasedSpec(mShaderSpec))
439 {
440 if (identifier.compare(0, 6, "webgl_") == 0)
441 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000442 error(line, reservedErrMsg, "webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300443 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000444 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530445 if (identifier.compare(0, 7, "_webgl_") == 0)
446 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000447 error(line, reservedErrMsg, "_webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300448 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000449 }
450 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530451 if (identifier.find("__") != TString::npos)
452 {
453 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400454 "identifiers containing two consecutive underscores (__) are reserved as "
455 "possible future keywords",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530456 identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300457 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000458 }
459 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000460
Olli Etuaho8a176262016-08-16 14:23:01 +0300461 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000462}
463
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000464// Make sure there is enough data provided to the constructor to build
465// something of the type of the constructor. Also returns the type of
466// the constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +0300467bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
468 TIntermNode *argumentsNode,
469 const TFunction &function,
470 TOperator op,
471 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000472{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000473 bool constructingMatrix = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400474 switch (op)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530475 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400476 case EOpConstructMat2:
477 case EOpConstructMat2x3:
478 case EOpConstructMat2x4:
479 case EOpConstructMat3x2:
480 case EOpConstructMat3:
481 case EOpConstructMat3x4:
482 case EOpConstructMat4x2:
483 case EOpConstructMat4x3:
484 case EOpConstructMat4:
485 constructingMatrix = true;
486 break;
487 default:
488 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000489 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000490
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000491 //
492 // Note: It's okay to have too many components available, but not okay to have unused
493 // arguments. 'full' will go to true when enough args have been seen. If we loop
494 // again, there is an extra argument, so 'overfull' will become true.
495 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000496
Jamie Madillb98c3a82015-07-23 14:26:04 -0400497 size_t size = 0;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400498 bool full = false;
499 bool overFull = false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000500 bool matrixInMatrix = false;
501 bool arrayArg = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530502 for (size_t i = 0; i < function.getParamCount(); ++i)
503 {
Dmitry Skibaefa3d8e2015-06-22 14:52:10 -0700504 const TConstParameter &param = function.getParam(i);
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000505 size += param.type->getObjectSize();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530506
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000507 if (constructingMatrix && param.type->isMatrix())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000508 matrixInMatrix = true;
509 if (full)
510 overFull = true;
Olli Etuaho856c4972016-08-08 11:38:39 +0300511 if (op != EOpConstructStruct && !type.isArray() && size >= type.getObjectSize())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000512 full = true;
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000513 if (param.type->isArray())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000514 arrayArg = true;
515 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530516
Olli Etuaho856c4972016-08-08 11:38:39 +0300517 if (type.isArray())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300518 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300519 // The size of an unsized constructor should already have been determined.
520 ASSERT(!type.isUnsizedArray());
521 if (static_cast<size_t>(type.getArraySize()) != function.getParamCount())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300522 {
523 error(line, "array constructor needs one argument per array element", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300524 return false;
Olli Etuaho376f1b52015-04-13 13:23:41 +0300525 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000526 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000527
Arun Patole7e7e68d2015-05-22 12:02:25 +0530528 if (arrayArg && op != EOpConstructStruct)
529 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000530 error(line, "constructing from a non-dereferenced array", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300531 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000532 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000533
Olli Etuaho856c4972016-08-08 11:38:39 +0300534 if (matrixInMatrix && !type.isArray())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530535 {
536 if (function.getParamCount() != 1)
537 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400538 error(line, "constructing matrix from matrix can only take one argument",
539 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300540 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000541 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000542 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000543
Arun Patole7e7e68d2015-05-22 12:02:25 +0530544 if (overFull)
545 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000546 error(line, "too many arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300547 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000548 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530549
Olli Etuaho856c4972016-08-08 11:38:39 +0300550 if (op == EOpConstructStruct && !type.isArray() &&
551 type.getStruct()->fields().size() != function.getParamCount())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530552 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400553 error(line,
554 "Number of constructor parameters does not match the number of structure fields",
555 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300556 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000557 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000558
Olli Etuaho856c4972016-08-08 11:38:39 +0300559 if (!type.isMatrix() || !matrixInMatrix)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530560 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300561 if ((op != EOpConstructStruct && size != 1 && size < type.getObjectSize()) ||
562 (op == EOpConstructStruct && size < type.getObjectSize()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530563 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000564 error(line, "not enough data provided for construction", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300565 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000566 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000567 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000568
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200569 if (argumentsNode == nullptr)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530570 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200571 error(line, "constructor does not have any arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300572 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000573 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200574
575 TIntermAggregate *argumentsAgg = argumentsNode->getAsAggregate();
576 for (TIntermNode *&argNode : *argumentsAgg->getSequence())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530577 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200578 TIntermTyped *argTyped = argNode->getAsTyped();
579 ASSERT(argTyped != nullptr);
580 if (op != EOpConstructStruct && IsSampler(argTyped->getBasicType()))
581 {
582 error(line, "cannot convert a sampler", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300583 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200584 }
585 if (argTyped->getBasicType() == EbtVoid)
586 {
587 error(line, "cannot convert a void", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300588 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200589 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000590 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000591
Olli Etuaho856c4972016-08-08 11:38:39 +0300592 if (type.isArray())
593 {
594 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
595 // the array.
596 for (TIntermNode *&argNode : *argumentsAgg->getSequence())
597 {
598 const TType &argType = argNode->getAsTyped()->getType();
599 // It has already been checked that the argument is not an array.
600 ASSERT(!argType.isArray());
601 if (!argType.sameElementType(type))
602 {
603 error(line, "Array constructor argument has an incorrect type", "Error");
Olli Etuaho8a176262016-08-16 14:23:01 +0300604 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300605 }
606 }
607 }
608 else if (op == EOpConstructStruct)
609 {
610 const TFieldList &fields = type.getStruct()->fields();
611 TIntermSequence *args = argumentsAgg->getSequence();
612
613 for (size_t i = 0; i < fields.size(); i++)
614 {
615 if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type())
616 {
617 error(line, "Structure constructor arguments do not match structure fields",
618 "Error");
Olli Etuaho8a176262016-08-16 14:23:01 +0300619 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300620 }
621 }
622 }
623
Olli Etuaho8a176262016-08-16 14:23:01 +0300624 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000625}
626
Jamie Madillb98c3a82015-07-23 14:26:04 -0400627// This function checks to see if a void variable has been declared and raise an error message for
628// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000629//
630// returns true in case of an error
631//
Olli Etuaho856c4972016-08-08 11:38:39 +0300632bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400633 const TString &identifier,
634 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000635{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300636 if (type == EbtVoid)
637 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000638 error(line, "illegal use of type 'void'", identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300639 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300640 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000641
Olli Etuaho8a176262016-08-16 14:23:01 +0300642 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000643}
644
Jamie Madillb98c3a82015-07-23 14:26:04 -0400645// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300646// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300647void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000648{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530649 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
650 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000651 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530652 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000653}
654
Jamie Madillb98c3a82015-07-23 14:26:04 -0400655// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300656// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300657void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000658{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530659 if (pType.type != EbtBool || pType.isAggregate())
660 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000661 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530662 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000663}
664
Olli Etuaho856c4972016-08-08 11:38:39 +0300665bool TParseContext::checkIsNotSampler(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400666 const TPublicType &pType,
667 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000668{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530669 if (pType.type == EbtStruct)
670 {
671 if (containsSampler(*pType.userDef))
672 {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000673 error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
Olli Etuaho8a176262016-08-16 14:23:01 +0300674 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000675 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530676
Olli Etuaho8a176262016-08-16 14:23:01 +0300677 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530678 }
679 else if (IsSampler(pType.type))
680 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000681 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300682 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000683 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000684
Olli Etuaho8a176262016-08-16 14:23:01 +0300685 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000686}
687
Olli Etuaho856c4972016-08-08 11:38:39 +0300688void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
689 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400690{
691 if (pType.layoutQualifier.location != -1)
692 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400693 error(line, "location must only be specified for a single input or output variable",
694 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400695 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400696}
697
Olli Etuaho856c4972016-08-08 11:38:39 +0300698void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
699 const TLayoutQualifier &layoutQualifier)
700{
701 if (layoutQualifier.location != -1)
702 {
703 error(location, "invalid layout qualifier:", "location",
704 "only valid on program inputs and outputs");
705 }
706}
707
708void TParseContext::checkOutParameterIsNotSampler(const TSourceLoc &line,
709 TQualifier qualifier,
710 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000711{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400712 if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct &&
713 IsSampler(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530714 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000715 error(line, "samplers cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000716 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000717}
718
Arun Patole7e7e68d2015-05-22 12:02:25 +0530719bool TParseContext::containsSampler(const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000720{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000721 if (IsSampler(type.getBasicType()))
722 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000723
Arun Patole7e7e68d2015-05-22 12:02:25 +0530724 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock())
725 {
726 const TFieldList &fields = type.getStruct()->fields();
727 for (unsigned int i = 0; i < fields.size(); ++i)
728 {
Jamie Madill98493dd2013-07-08 14:39:03 -0400729 if (containsSampler(*fields[i]->type()))
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000730 return true;
731 }
732 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000733
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000734 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000735}
736
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000737// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300738unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000739{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530740 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000741
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200742 // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
743 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
744 // fold as array size.
745 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000746 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000747 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300748 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000749 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000750
Olli Etuaho856c4972016-08-08 11:38:39 +0300751 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400752
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000753 if (constant->getBasicType() == EbtUInt)
754 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300755 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000756 }
757 else
758 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300759 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000760
Olli Etuaho856c4972016-08-08 11:38:39 +0300761 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000762 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400763 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300764 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000765 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400766
Olli Etuaho856c4972016-08-08 11:38:39 +0300767 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -0400768 }
769
Olli Etuaho856c4972016-08-08 11:38:39 +0300770 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -0400771 {
772 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300773 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400774 }
775
776 // The size of arrays is restricted here to prevent issues further down the
777 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
778 // 4096 registers so this should be reasonable even for aggressively optimizable code.
779 const unsigned int sizeLimit = 65536;
780
Olli Etuaho856c4972016-08-08 11:38:39 +0300781 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -0400782 {
783 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300784 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000785 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300786
787 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000788}
789
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000790// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +0300791bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
792 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000793{
Olli Etuaho8a176262016-08-16 14:23:01 +0300794 if ((elementQualifier.qualifier == EvqAttribute) ||
795 (elementQualifier.qualifier == EvqVertexIn) ||
796 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +0300797 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400798 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300799 TType(elementQualifier).getQualifierString());
800 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000801 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000802
Olli Etuaho8a176262016-08-16 14:23:01 +0300803 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000804}
805
Olli Etuaho8a176262016-08-16 14:23:01 +0300806// See if this element type can be formed into an array.
807bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000808{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000809 //
810 // Can the type be an array?
811 //
Olli Etuaho8a176262016-08-16 14:23:01 +0300812 if (elementType.array)
Jamie Madill06145232015-05-13 13:10:01 -0400813 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300814 error(line, "cannot declare arrays of arrays",
815 TType(elementType).getCompleteString().c_str());
816 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000817 }
Olli Etuahocc36b982015-07-10 14:14:18 +0300818 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
819 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
820 // 4.3.4).
Olli Etuaho8a176262016-08-16 14:23:01 +0300821 if (mShaderVersion >= 300 && elementType.type == EbtStruct &&
822 sh::IsVarying(elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +0300823 {
824 error(line, "cannot declare arrays of structs of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300825 TType(elementType).getCompleteString().c_str());
826 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +0300827 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000828
Olli Etuaho8a176262016-08-16 14:23:01 +0300829 return true;
830}
831
832// Check if this qualified element type can be formed into an array.
833bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
834 const TPublicType &elementType)
835{
836 if (checkIsValidTypeForArray(indexLocation, elementType))
837 {
838 return checkIsValidQualifierForArray(indexLocation, elementType);
839 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000840 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000841}
842
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000843// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +0300844void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
845 const TString &identifier,
846 TPublicType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000847{
Olli Etuaho3739d232015-04-08 12:23:44 +0300848 ASSERT(type != nullptr);
849 if (type->qualifier == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000850 {
851 // Make the qualifier make sense.
Olli Etuaho3739d232015-04-08 12:23:44 +0300852 type->qualifier = EvqTemporary;
853
854 // Generate informative error messages for ESSL1.
855 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400856 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000857 {
Arun Patole7e7e68d2015-05-22 12:02:25 +0530858 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400859 "structures containing arrays may not be declared constant since they cannot be "
860 "initialized",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530861 identifier.c_str());
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000862 }
863 else
864 {
865 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
866 }
Olli Etuaho383b7912016-08-05 11:22:59 +0300867 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000868 }
Olli Etuaho376f1b52015-04-13 13:23:41 +0300869 if (type->isUnsizedArray())
870 {
871 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
Olli Etuaho376f1b52015-04-13 13:23:41 +0300872 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000873}
874
Olli Etuaho2935c582015-04-08 14:32:06 +0300875// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000876// and update the symbol table.
877//
Olli Etuaho2935c582015-04-08 14:32:06 +0300878// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000879//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400880bool TParseContext::declareVariable(const TSourceLoc &line,
881 const TString &identifier,
882 const TType &type,
Olli Etuaho2935c582015-04-08 14:32:06 +0300883 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000884{
Olli Etuaho2935c582015-04-08 14:32:06 +0300885 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000886
Olli Etuaho856c4972016-08-08 11:38:39 +0300887 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000888
Olli Etuaho2935c582015-04-08 14:32:06 +0300889 // gl_LastFragData may be redeclared with a new precision qualifier
890 if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
891 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400892 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
893 symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Olli Etuaho856c4972016-08-08 11:38:39 +0300894 if (static_cast<int>(type.getArraySize()) == maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +0300895 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400896 if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +0300897 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300898 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
Olli Etuaho2935c582015-04-08 14:32:06 +0300899 }
900 }
901 else
902 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400903 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
904 identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +0300905 return false;
906 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000907 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000908
Olli Etuaho8a176262016-08-16 14:23:01 +0300909 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +0300910 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000911
Olli Etuaho2935c582015-04-08 14:32:06 +0300912 (*variable) = new TVariable(&identifier, type);
913 if (!symbolTable.declare(*variable))
914 {
915 error(line, "redefinition", identifier.c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -0400916 *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +0300917 return false;
918 }
919
Olli Etuaho8a176262016-08-16 14:23:01 +0300920 if (!checkIsNonVoid(line, identifier, type.getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +0300921 return false;
922
923 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000924}
925
Olli Etuaho856c4972016-08-08 11:38:39 +0300926void TParseContext::checkIsParameterQualifierValid(const TSourceLoc &line,
927 TQualifier qualifier,
928 TQualifier paramQualifier,
929 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530930{
931 if (qualifier != EvqConst && qualifier != EvqTemporary)
932 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000933 error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +0300934 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000935 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530936 if (qualifier == EvqConst && paramQualifier != EvqIn)
937 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400938 error(line, "qualifier not allowed with ", getQualifierString(qualifier),
939 getQualifierString(paramQualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +0300940 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000941 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000942
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000943 if (qualifier == EvqConst)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000944 type->setQualifier(EvqConstReadOnly);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000945 else
alokp@chromium.org58e54292010-08-24 21:40:03 +0000946 type->setQualifier(paramQualifier);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000947}
948
Olli Etuaho856c4972016-08-08 11:38:39 +0300949bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000950{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400951 const TExtensionBehavior &extBehavior = extensionBehavior();
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000952 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
Arun Patole7e7e68d2015-05-22 12:02:25 +0530953 if (iter == extBehavior.end())
954 {
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000955 error(line, "extension", extension.c_str(), "is not supported");
Olli Etuaho8a176262016-08-16 14:23:01 +0300956 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000957 }
zmo@google.comf5450912011-09-09 01:37:19 +0000958 // In GLSL ES, an extension's default behavior is "disable".
Arun Patole7e7e68d2015-05-22 12:02:25 +0530959 if (iter->second == EBhDisable || iter->second == EBhUndefined)
960 {
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000961 error(line, "extension", extension.c_str(), "is disabled");
Olli Etuaho8a176262016-08-16 14:23:01 +0300962 return false;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000963 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530964 if (iter->second == EBhWarn)
965 {
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000966 warning(line, "extension", extension.c_str(), "is being used");
Olli Etuaho8a176262016-08-16 14:23:01 +0300967 return true;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000968 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000969
Olli Etuaho8a176262016-08-16 14:23:01 +0300970 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000971}
972
Jamie Madillb98c3a82015-07-23 14:26:04 -0400973// These checks are common for all declarations starting a declarator list, and declarators that
974// follow an empty declaration.
Olli Etuaho383b7912016-08-05 11:22:59 +0300975void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400976 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -0400977{
Olli Etuahofa33d582015-04-09 14:33:12 +0300978 switch (publicType.qualifier)
979 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400980 case EvqVaryingIn:
981 case EvqVaryingOut:
982 case EvqAttribute:
983 case EvqVertexIn:
984 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +0300985 case EvqComputeIn:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400986 if (publicType.type == EbtStruct)
987 {
988 error(identifierLocation, "cannot be used with a structure",
989 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +0300990 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400991 }
Olli Etuahofa33d582015-04-09 14:33:12 +0300992
Jamie Madillb98c3a82015-07-23 14:26:04 -0400993 default:
994 break;
Olli Etuahofa33d582015-04-09 14:33:12 +0300995 }
996
Jamie Madillb98c3a82015-07-23 14:26:04 -0400997 if (publicType.qualifier != EvqUniform &&
Olli Etuaho8a176262016-08-16 14:23:01 +0300998 !checkIsNotSampler(identifierLocation, publicType, "samplers must be uniform"))
Olli Etuahofa33d582015-04-09 14:33:12 +0300999 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001000 return;
Olli Etuahofa33d582015-04-09 14:33:12 +03001001 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001002
1003 // check for layout qualifier issues
1004 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
1005
1006 if (layoutQualifier.matrixPacking != EmpUnspecified)
1007 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001008 error(identifierLocation, "layout qualifier",
1009 getMatrixPackingString(layoutQualifier.matrixPacking),
Olli Etuahofa33d582015-04-09 14:33:12 +03001010 "only valid for interface blocks");
Olli Etuaho383b7912016-08-05 11:22:59 +03001011 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001012 }
1013
1014 if (layoutQualifier.blockStorage != EbsUnspecified)
1015 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001016 error(identifierLocation, "layout qualifier",
1017 getBlockStorageString(layoutQualifier.blockStorage),
Olli Etuahofa33d582015-04-09 14:33:12 +03001018 "only valid for interface blocks");
Olli Etuaho383b7912016-08-05 11:22:59 +03001019 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001020 }
1021
Olli Etuaho383b7912016-08-05 11:22:59 +03001022 if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut)
Jamie Madilla5efff92013-06-06 11:56:47 -04001023 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001024 checkLocationIsNotSpecified(identifierLocation, publicType.layoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04001025 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001026}
1027
Olli Etuaho856c4972016-08-08 11:38:39 +03001028void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1029 const TString &layoutQualifierName,
1030 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001031{
1032
1033 if (mShaderVersion < versionRequired)
1034 {
1035 error(location, "invalid layout qualifier:", layoutQualifierName.c_str(), "not supported");
Martin Radev802abe02016-08-04 17:48:32 +03001036 }
1037}
1038
Olli Etuaho856c4972016-08-08 11:38:39 +03001039bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1040 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001041{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001042 const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
Martin Radev802abe02016-08-04 17:48:32 +03001043 for (size_t i = 0u; i < localSize.size(); ++i)
1044 {
1045 if (localSize[i] != -1)
1046 {
Martin Radev4c4c8e72016-08-04 12:25:34 +03001047 error(location, "invalid layout qualifier:", getWorkGroupSizeString(i),
Martin Radev802abe02016-08-04 17:48:32 +03001048 "only valid when used with 'in' in a compute shader global layout declaration");
Olli Etuaho8a176262016-08-16 14:23:01 +03001049 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001050 }
1051 }
1052
Olli Etuaho8a176262016-08-16 14:23:01 +03001053 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001054}
1055
Olli Etuaho383b7912016-08-05 11:22:59 +03001056void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
Olli Etuaho856c4972016-08-08 11:38:39 +03001057 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001058{
1059 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1060 {
1061 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1062 if (qual == EvqOut || qual == EvqInOut)
1063 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001064 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho8a176262016-08-16 14:23:01 +03001065 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001066 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001067 error(argument->getLine(),
Jamie Madillb98c3a82015-07-23 14:26:04 -04001068 "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
Olli Etuaho383b7912016-08-05 11:22:59 +03001069 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001070 }
1071 }
1072 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001073}
1074
Olli Etuaho856c4972016-08-08 11:38:39 +03001075void TParseContext::checkInvariantIsOutVariableES3(const TQualifier qualifier,
1076 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001077{
1078 if (!sh::IsVaryingOut(qualifier) && qualifier != EvqFragmentOut)
1079 {
1080 error(invariantLocation, "Only out variables can be invariant.", "invariant");
Olli Etuaho37ad4742015-04-27 13:18:50 +03001081 }
1082}
1083
Arun Patole7e7e68d2015-05-22 12:02:25 +05301084bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001085{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001086 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001087 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1088 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001089}
1090
Arun Patole7e7e68d2015-05-22 12:02:25 +05301091bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001092{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001093 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001094}
1095
Jamie Madillb98c3a82015-07-23 14:26:04 -04001096void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1097 const char *extName,
1098 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001099{
1100 pp::SourceLocation srcLoc;
1101 srcLoc.file = loc.first_file;
1102 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001103 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001104}
1105
Jamie Madillb98c3a82015-07-23 14:26:04 -04001106void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1107 const char *name,
1108 const char *value,
1109 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001110{
1111 pp::SourceLocation srcLoc;
1112 srcLoc.file = loc.first_file;
1113 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001114 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001115}
1116
Martin Radev4c4c8e72016-08-04 12:25:34 +03001117sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
Martin Radev802abe02016-08-04 17:48:32 +03001118{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001119 sh::WorkGroupSize result;
Martin Radev802abe02016-08-04 17:48:32 +03001120 for (size_t i = 0u; i < result.size(); ++i)
1121 {
1122 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1123 {
1124 result[i] = 1;
1125 }
1126 else
1127 {
1128 result[i] = mComputeShaderLocalSize[i];
1129 }
1130 }
1131 return result;
1132}
1133
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001134/////////////////////////////////////////////////////////////////////////////////
1135//
1136// Non-Errors.
1137//
1138/////////////////////////////////////////////////////////////////////////////////
1139
Jamie Madill5c097022014-08-20 16:38:32 -04001140const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1141 const TString *name,
1142 const TSymbol *symbol)
1143{
1144 const TVariable *variable = NULL;
1145
1146 if (!symbol)
1147 {
1148 error(location, "undeclared identifier", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001149 }
1150 else if (!symbol->isVariable())
1151 {
1152 error(location, "variable expected", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001153 }
1154 else
1155 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001156 variable = static_cast<const TVariable *>(symbol);
Jamie Madill5c097022014-08-20 16:38:32 -04001157
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001158 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
Olli Etuaho383b7912016-08-05 11:22:59 +03001159 !variable->getExtension().empty())
Jamie Madill5c097022014-08-20 16:38:32 -04001160 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001161 checkCanUseExtension(location, variable->getExtension());
Jamie Madill5c097022014-08-20 16:38:32 -04001162 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001163
1164 // Reject shaders using both gl_FragData and gl_FragColor
1165 TQualifier qualifier = variable->getType().getQualifier();
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001166 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001167 {
1168 mUsesFragData = true;
1169 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001170 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001171 {
1172 mUsesFragColor = true;
1173 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001174 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1175 {
1176 mUsesSecondaryOutputs = true;
1177 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001178
1179 // This validation is not quite correct - it's only an error to write to
1180 // both FragData and FragColor. For simplicity, and because users shouldn't
1181 // be rewarded for reading from undefined varaibles, return an error
1182 // if they are both referenced, rather than assigned.
1183 if (mUsesFragData && mUsesFragColor)
1184 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001185 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1186 if (mUsesSecondaryOutputs)
1187 {
1188 errorMessage =
1189 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1190 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1191 }
1192 error(location, errorMessage, name->c_str());
Jamie Madill14e95b32015-05-07 10:10:41 -04001193 }
Martin Radevb0883602016-08-04 17:48:58 +03001194
1195 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1196 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1197 qualifier == EvqWorkGroupSize)
1198 {
1199 error(location,
1200 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1201 "gl_WorkGroupSize");
1202 }
Jamie Madill5c097022014-08-20 16:38:32 -04001203 }
1204
1205 if (!variable)
1206 {
1207 TType type(EbtFloat, EbpUndefined);
1208 TVariable *fakeVariable = new TVariable(name, type);
1209 symbolTable.declare(fakeVariable);
1210 variable = fakeVariable;
1211 }
1212
1213 return variable;
1214}
1215
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001216TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1217 const TString *name,
1218 const TSymbol *symbol)
1219{
1220 const TVariable *variable = getNamedVariable(location, name, symbol);
1221
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001222 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001223 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001224 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001225 return intermediate.addConstantUnion(constArray, variable->getType(), location);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001226 }
1227 else
1228 {
1229 return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
1230 variable->getType(), location);
1231 }
1232}
1233
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001234//
1235// Look up a function name in the symbol table, and make sure it is a function.
1236//
1237// Return the function symbol if found, otherwise 0.
1238//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001239const TFunction *TParseContext::findFunction(const TSourceLoc &line,
1240 TFunction *call,
1241 int inputShaderVersion,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301242 bool *builtIn)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001243{
alokp@chromium.org0a576182010-08-09 17:16:27 +00001244 // First find by unmangled name to check whether the function name has been
1245 // hidden by a variable name or struct typename.
Nicolas Capensd4a9b8d2013-07-18 11:01:22 -04001246 // If a function is found, check for one with a matching argument list.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301247 const TSymbol *symbol = symbolTable.find(call->getName(), inputShaderVersion, builtIn);
1248 if (symbol == 0 || symbol->isFunction())
1249 {
Austin Kinross3ae64652015-01-26 15:51:39 -08001250 symbol = symbolTable.find(call->getMangledName(), inputShaderVersion, builtIn);
alokp@chromium.org0a576182010-08-09 17:16:27 +00001251 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001252
Arun Patole7e7e68d2015-05-22 12:02:25 +05301253 if (symbol == 0)
1254 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001255 error(line, "no matching overloaded function found", call->getName().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001256 return 0;
1257 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001258
Arun Patole7e7e68d2015-05-22 12:02:25 +05301259 if (!symbol->isFunction())
1260 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001261 error(line, "function name expected", call->getName().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001262 return 0;
1263 }
alokp@chromium.org0a576182010-08-09 17:16:27 +00001264
Jamie Madillb98c3a82015-07-23 14:26:04 -04001265 return static_cast<const TFunction *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001266}
1267
1268//
1269// Initializers show up in several places in the grammar. Have one set of
1270// code to handle them here.
1271//
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001272// Returns true on error, false if no error
1273//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001274bool TParseContext::executeInitializer(const TSourceLoc &line,
1275 const TString &identifier,
1276 const TPublicType &pType,
1277 TIntermTyped *initializer,
1278 TIntermNode **intermNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001279{
Olli Etuahoe7847b02015-03-16 11:56:12 +02001280 ASSERT(intermNode != nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001281 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001282
Olli Etuaho2935c582015-04-08 14:32:06 +03001283 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001284 if (type.isUnsizedArray())
1285 {
1286 type.setArraySize(initializer->getArraySize());
1287 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001288 if (!declareVariable(line, identifier, type, &variable))
1289 {
1290 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001291 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001292
Olli Etuahob0c645e2015-05-12 14:25:36 +03001293 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001294 if (symbolTable.atGlobalLevel() &&
1295 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001296 {
1297 // Error message does not completely match behavior with ESSL 1.00, but
1298 // we want to steer developers towards only using constant expressions.
1299 error(line, "global variable initializers must be constant expressions", "=");
1300 return true;
1301 }
1302 if (globalInitWarning)
1303 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001304 warning(
1305 line,
1306 "global variable initializers should be constant expressions "
1307 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1308 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001309 }
1310
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001311 //
1312 // identifier must be of type constant, a global, or a temporary
1313 //
1314 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301315 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1316 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001317 error(line, " cannot initialize this type of qualifier ",
1318 variable->getType().getQualifierString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001319 return true;
1320 }
1321 //
1322 // test for and propagate constant
1323 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001324
Arun Patole7e7e68d2015-05-22 12:02:25 +05301325 if (qualifier == EvqConst)
1326 {
1327 if (qualifier != initializer->getType().getQualifier())
1328 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001329 std::stringstream extraInfoStream;
1330 extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
1331 std::string extraInfo = extraInfoStream.str();
1332 error(line, " assigning non-constant to", "=", extraInfo.c_str());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001333 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001334 return true;
1335 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301336 if (type != initializer->getType())
1337 {
1338 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001339 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001340 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001341 return true;
1342 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001343
1344 // Save the constant folded value to the variable if possible. For example array
1345 // initializers are not folded, since that way copying the array literal to multiple places
1346 // in the shader is avoided.
1347 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1348 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301349 if (initializer->getAsConstantUnion())
1350 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001351 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001352 *intermNode = nullptr;
1353 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301354 }
1355 else if (initializer->getAsSymbolNode())
1356 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001357 const TSymbol *symbol =
1358 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1359 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001360
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001361 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001362 if (constArray)
1363 {
1364 variable->shareConstPointer(constArray);
1365 *intermNode = nullptr;
1366 return false;
1367 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001368 }
1369 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001370
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001371 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1372 variable->getUniqueId(), variable->getName(), variable->getType(), line);
1373 *intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1374 if (*intermNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001375 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001376 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1377 return true;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001378 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001379
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001380 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001381}
1382
Jamie Madillb98c3a82015-07-23 14:26:04 -04001383TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier,
1384 bool invariant,
1385 TLayoutQualifier layoutQualifier,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301386 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001387{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001388 TPublicType returnType = typeSpecifier;
1389 returnType.qualifier = qualifier;
1390 returnType.invariant = invariant;
Jamie Madilla5efff92013-06-06 11:56:47 -04001391 returnType.layoutQualifier = layoutQualifier;
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001392
Olli Etuaho856c4972016-08-08 11:38:39 +03001393 checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001394
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001395 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001396 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001397 if (typeSpecifier.array)
1398 {
1399 error(typeSpecifier.line, "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001400 returnType.clearArrayness();
1401 }
1402
Jamie Madillb98c3a82015-07-23 14:26:04 -04001403 if (qualifier == EvqAttribute &&
1404 (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001405 {
1406 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001407 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001408
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001409 if ((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
1410 (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
1411 {
1412 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001413 }
1414 }
1415 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001416 {
Olli Etuahoabb0c382015-07-13 12:01:12 +03001417 if (!layoutQualifier.isEmpty())
1418 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001419 checkIsAtGlobalLevel(typeSpecifier.line, "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03001420 }
Olli Etuahocc36b982015-07-10 14:14:18 +03001421 if (sh::IsVarying(qualifier) || qualifier == EvqVertexIn || qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001422 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001423 checkInputOutputTypeIsValidES3(qualifier, typeSpecifier, typeSpecifier.line);
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001424 }
Martin Radev802abe02016-08-04 17:48:32 +03001425 if (qualifier == EvqComputeIn)
1426 {
1427 error(typeSpecifier.line, "'in' can be only used to specify the local group size",
1428 "in");
Martin Radev802abe02016-08-04 17:48:32 +03001429 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001430 }
1431
1432 return returnType;
1433}
1434
Olli Etuaho856c4972016-08-08 11:38:39 +03001435void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1436 const TPublicType &type,
1437 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03001438{
1439 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
1440 if (type.type == EbtBool)
1441 {
1442 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001443 }
1444
1445 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1446 switch (qualifier)
1447 {
1448 case EvqVertexIn:
1449 // ESSL 3.00 section 4.3.4
1450 if (type.array)
1451 {
1452 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001453 }
1454 // Vertex inputs with a struct type are disallowed in singleDeclarationErrorCheck
1455 return;
1456 case EvqFragmentOut:
1457 // ESSL 3.00 section 4.3.6
1458 if (type.isMatrix())
1459 {
1460 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001461 }
1462 // Fragment outputs with a struct type are disallowed in singleDeclarationErrorCheck
1463 return;
1464 default:
1465 break;
1466 }
1467
1468 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1469 // restrictions.
1470 bool typeContainsIntegers =
1471 (type.type == EbtInt || type.type == EbtUInt || type.isStructureContainingType(EbtInt) ||
1472 type.isStructureContainingType(EbtUInt));
1473 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1474 {
1475 error(qualifierLocation, "must use 'flat' interpolation here",
1476 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001477 }
1478
1479 if (type.type == EbtStruct)
1480 {
1481 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1482 // These restrictions are only implied by the ESSL 3.00 spec, but
1483 // the ESSL 3.10 spec lists these restrictions explicitly.
1484 if (type.array)
1485 {
1486 error(qualifierLocation, "cannot be an array of structures",
1487 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001488 }
1489 if (type.isStructureContainingArrays())
1490 {
1491 error(qualifierLocation, "cannot be a structure containing an array",
1492 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001493 }
1494 if (type.isStructureContainingType(EbtStruct))
1495 {
1496 error(qualifierLocation, "cannot be a structure containing a structure",
1497 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001498 }
1499 if (type.isStructureContainingType(EbtBool))
1500 {
1501 error(qualifierLocation, "cannot be a structure containing a bool",
1502 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001503 }
1504 }
1505}
1506
Olli Etuahofa33d582015-04-09 14:33:12 +03001507TIntermAggregate *TParseContext::parseSingleDeclaration(TPublicType &publicType,
1508 const TSourceLoc &identifierOrTypeLocation,
1509 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04001510{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001511 TType type(publicType);
1512 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
1513 mDirectiveHandler.pragma().stdgl.invariantAll)
1514 {
1515 TQualifier qualifier = type.getQualifier();
1516
1517 // The directive handler has already taken care of rejecting invalid uses of this pragma
1518 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
1519 // affected variable declarations:
1520 //
1521 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
1522 // elsewhere, in TranslatorGLSL.)
1523 //
1524 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
1525 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
1526 // the way this is currently implemented we have to enable this compiler option before
1527 // parsing the shader and determining the shading language version it uses. If this were
1528 // implemented as a post-pass, the workaround could be more targeted.
1529 //
1530 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
1531 // the specification, but there are desktop OpenGL drivers that expect that this is the
1532 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
1533 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
1534 {
1535 type.setInvariant(true);
1536 }
1537 }
1538
1539 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001540
Olli Etuahobab4c082015-04-24 16:38:49 +03001541 bool emptyDeclaration = (identifier == "");
Olli Etuahofa33d582015-04-09 14:33:12 +03001542
Olli Etuahobab4c082015-04-24 16:38:49 +03001543 mDeferredSingleDeclarationErrorCheck = emptyDeclaration;
1544
1545 if (emptyDeclaration)
1546 {
1547 if (publicType.isUnsizedArray())
1548 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001549 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1550 // error. It is assumed that this applies to empty declarations as well.
1551 error(identifierOrTypeLocation, "empty array declaration needs to specify a size",
1552 identifier.c_str());
Olli Etuahobab4c082015-04-24 16:38:49 +03001553 }
1554 }
1555 else
Jamie Madill60ed9812013-06-06 11:56:46 -04001556 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001557 singleDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001558
Olli Etuaho856c4972016-08-08 11:38:39 +03001559 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001560
Olli Etuaho2935c582015-04-08 14:32:06 +03001561 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001562 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001563
1564 if (variable && symbol)
Jamie Madill60ed9812013-06-06 11:56:46 -04001565 symbol->setId(variable->getUniqueId());
Jamie Madill60ed9812013-06-06 11:56:46 -04001566 }
1567
Olli Etuahoe7847b02015-03-16 11:56:12 +02001568 return intermediate.makeAggregate(symbol, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001569}
1570
Olli Etuahoe7847b02015-03-16 11:56:12 +02001571TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1572 const TSourceLoc &identifierLocation,
1573 const TString &identifier,
1574 const TSourceLoc &indexLocation,
1575 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04001576{
Olli Etuahofa33d582015-04-09 14:33:12 +03001577 mDeferredSingleDeclarationErrorCheck = false;
1578
Olli Etuaho383b7912016-08-05 11:22:59 +03001579 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001580
Olli Etuaho856c4972016-08-08 11:38:39 +03001581 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001582
Olli Etuaho8a176262016-08-16 14:23:01 +03001583 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001584
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001585 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001586
Olli Etuaho856c4972016-08-08 11:38:39 +03001587 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001588 // Make the type an array even if size check failed.
1589 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1590 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04001591
Olli Etuaho2935c582015-04-08 14:32:06 +03001592 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001593 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001594
Olli Etuahoe7847b02015-03-16 11:56:12 +02001595 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001596 if (variable && symbol)
Jamie Madill60ed9812013-06-06 11:56:46 -04001597 symbol->setId(variable->getUniqueId());
Jamie Madill60ed9812013-06-06 11:56:46 -04001598
Olli Etuahoe7847b02015-03-16 11:56:12 +02001599 return intermediate.makeAggregate(symbol, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001600}
1601
Jamie Madill06145232015-05-13 13:10:01 -04001602TIntermAggregate *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
Olli Etuahoe7847b02015-03-16 11:56:12 +02001603 const TSourceLoc &identifierLocation,
1604 const TString &identifier,
1605 const TSourceLoc &initLocation,
1606 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04001607{
Olli Etuahofa33d582015-04-09 14:33:12 +03001608 mDeferredSingleDeclarationErrorCheck = false;
1609
Olli Etuaho383b7912016-08-05 11:22:59 +03001610 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001611
Olli Etuahoe7847b02015-03-16 11:56:12 +02001612 TIntermNode *intermNode = nullptr;
1613 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04001614 {
1615 //
1616 // Build intermediate representation
1617 //
Olli Etuahoe7847b02015-03-16 11:56:12 +02001618 return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : nullptr;
Jamie Madill60ed9812013-06-06 11:56:46 -04001619 }
1620 else
1621 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001622 return nullptr;
Jamie Madill60ed9812013-06-06 11:56:46 -04001623 }
1624}
1625
Jamie Madillb98c3a82015-07-23 14:26:04 -04001626TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration(
1627 TPublicType &publicType,
1628 const TSourceLoc &identifierLocation,
1629 const TString &identifier,
1630 const TSourceLoc &indexLocation,
1631 TIntermTyped *indexExpression,
1632 const TSourceLoc &initLocation,
1633 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001634{
1635 mDeferredSingleDeclarationErrorCheck = false;
1636
Olli Etuaho383b7912016-08-05 11:22:59 +03001637 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001638
Olli Etuaho8a176262016-08-16 14:23:01 +03001639 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001640
1641 TPublicType arrayType(publicType);
1642
Olli Etuaho856c4972016-08-08 11:38:39 +03001643 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001644 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
1645 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03001646 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001647 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001648 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001649 }
1650 // Make the type an array even if size check failed.
1651 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1652 arrayType.setArraySize(size);
1653
1654 // initNode will correspond to the whole of "type b[n] = initializer".
1655 TIntermNode *initNode = nullptr;
1656 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
1657 {
1658 return initNode ? intermediate.makeAggregate(initNode, initLocation) : nullptr;
1659 }
1660 else
1661 {
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001662 return nullptr;
1663 }
1664}
1665
Olli Etuahoe7847b02015-03-16 11:56:12 +02001666TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc,
Jamie Madill47e3ec02014-08-20 16:38:33 -04001667 const TSourceLoc &identifierLoc,
1668 const TString *identifier,
1669 const TSymbol *symbol)
1670{
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001671 // invariant declaration
Qiankun Miaof69682b2016-08-16 14:50:42 +08001672 if (!checkIsAtGlobalLevel(invariantLoc, "invariant varying"))
1673 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001674
1675 if (!symbol)
1676 {
1677 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001678 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001679 }
1680 else
1681 {
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001682 const TString kGlFrontFacing("gl_FrontFacing");
1683 if (*identifier == kGlFrontFacing)
1684 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001685 error(identifierLoc, "identifier should not be declared as invariant",
1686 identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001687 return nullptr;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001688 }
Jamie Madill2c433252014-12-03 12:36:54 -05001689 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001690 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
1691 ASSERT(variable);
1692 const TType &type = variable->getType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04001693 TIntermSymbol *intermSymbol =
1694 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001695
1696 TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc);
1697 aggregate->setOp(EOpInvariantDeclaration);
1698 return aggregate;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001699 }
1700}
1701
Jamie Madillb98c3a82015-07-23 14:26:04 -04001702TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType,
1703 TIntermAggregate *aggregateDeclaration,
1704 const TSourceLoc &identifierLocation,
1705 const TString &identifier)
Jamie Madill502d66f2013-06-20 11:55:52 -04001706{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001707 // If the declaration starting this declarator list was empty (example: int,), some checks were
1708 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001709 if (mDeferredSingleDeclarationErrorCheck)
1710 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001711 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001712 mDeferredSingleDeclarationErrorCheck = false;
1713 }
1714
Olli Etuaho856c4972016-08-08 11:38:39 +03001715 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001716
Olli Etuaho856c4972016-08-08 11:38:39 +03001717 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04001718
Olli Etuaho2935c582015-04-08 14:32:06 +03001719 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001720 declareVariable(identifierLocation, identifier, TType(publicType), &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001721
Jamie Madillb98c3a82015-07-23 14:26:04 -04001722 TIntermSymbol *symbol =
1723 intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001724 if (variable && symbol)
Jamie Madill502d66f2013-06-20 11:55:52 -04001725 symbol->setId(variable->getUniqueId());
1726
Olli Etuahoe7847b02015-03-16 11:56:12 +02001727 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001728}
1729
Jamie Madillb98c3a82015-07-23 14:26:04 -04001730TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType,
1731 TIntermAggregate *aggregateDeclaration,
1732 const TSourceLoc &identifierLocation,
1733 const TString &identifier,
1734 const TSourceLoc &arrayLocation,
1735 TIntermTyped *indexExpression)
Jamie Madill502d66f2013-06-20 11:55:52 -04001736{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001737 // If the declaration starting this declarator list was empty (example: int,), some checks were
1738 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001739 if (mDeferredSingleDeclarationErrorCheck)
1740 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001741 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001742 mDeferredSingleDeclarationErrorCheck = false;
1743 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001744
Olli Etuaho856c4972016-08-08 11:38:39 +03001745 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001746
Olli Etuaho856c4972016-08-08 11:38:39 +03001747 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04001748
Olli Etuaho8a176262016-08-16 14:23:01 +03001749 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04001750 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001751 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03001752 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03001753 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001754
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001755 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001756 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04001757
Jamie Madillb98c3a82015-07-23 14:26:04 -04001758 TIntermSymbol *symbol =
1759 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001760 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001761 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001762
1763 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001764 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001765
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001766 return nullptr;
Jamie Madill502d66f2013-06-20 11:55:52 -04001767}
1768
Jamie Madillb98c3a82015-07-23 14:26:04 -04001769TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicType,
1770 TIntermAggregate *aggregateDeclaration,
1771 const TSourceLoc &identifierLocation,
1772 const TString &identifier,
1773 const TSourceLoc &initLocation,
1774 TIntermTyped *initializer)
Jamie Madill502d66f2013-06-20 11:55:52 -04001775{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001776 // If the declaration starting this declarator list was empty (example: int,), some checks were
1777 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001778 if (mDeferredSingleDeclarationErrorCheck)
1779 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001780 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001781 mDeferredSingleDeclarationErrorCheck = false;
1782 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001783
Olli Etuaho856c4972016-08-08 11:38:39 +03001784 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001785
Olli Etuahoe7847b02015-03-16 11:56:12 +02001786 TIntermNode *intermNode = nullptr;
1787 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04001788 {
1789 //
1790 // build the intermediate representation
1791 //
1792 if (intermNode)
1793 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001794 return intermediate.growAggregate(aggregateDeclaration, intermNode, initLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001795 }
1796 else
1797 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001798 return aggregateDeclaration;
Jamie Madill502d66f2013-06-20 11:55:52 -04001799 }
1800 }
1801 else
1802 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001803 return nullptr;
Jamie Madill502d66f2013-06-20 11:55:52 -04001804 }
1805}
1806
Jamie Madill06145232015-05-13 13:10:01 -04001807TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001808 TIntermAggregate *aggregateDeclaration,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301809 const TSourceLoc &identifierLocation,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001810 const TString &identifier,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301811 const TSourceLoc &indexLocation,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001812 TIntermTyped *indexExpression,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001813 const TSourceLoc &initLocation,
1814 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001815{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001816 // If the declaration starting this declarator list was empty (example: int,), some checks were
1817 // not performed.
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001818 if (mDeferredSingleDeclarationErrorCheck)
1819 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001820 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001821 mDeferredSingleDeclarationErrorCheck = false;
1822 }
1823
Olli Etuaho856c4972016-08-08 11:38:39 +03001824 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001825
Olli Etuaho8a176262016-08-16 14:23:01 +03001826 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001827
1828 TPublicType arrayType(publicType);
1829
Olli Etuaho856c4972016-08-08 11:38:39 +03001830 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001831 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
1832 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03001833 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001834 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001835 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001836 }
1837 // Make the type an array even if size check failed.
1838 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1839 arrayType.setArraySize(size);
1840
1841 // initNode will correspond to the whole of "b[n] = initializer".
1842 TIntermNode *initNode = nullptr;
1843 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
1844 {
1845 if (initNode)
1846 {
1847 return intermediate.growAggregate(aggregateDeclaration, initNode, initLocation);
1848 }
1849 else
1850 {
1851 return aggregateDeclaration;
1852 }
1853 }
1854 else
1855 {
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001856 return nullptr;
1857 }
1858}
1859
Jamie Madilla295edf2013-06-06 11:56:48 -04001860void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
1861{
Jamie Madilla295edf2013-06-06 11:56:48 -04001862 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04001863
1864 // It should never be the case, but some strange parser errors can send us here.
1865 if (layoutQualifier.isEmpty())
1866 {
1867 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04001868 return;
1869 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001870
Martin Radev802abe02016-08-04 17:48:32 +03001871 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04001872 {
Martin Radev802abe02016-08-04 17:48:32 +03001873 error(typeQualifier.line, "invalid combination:", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04001874 return;
1875 }
1876
Martin Radev802abe02016-08-04 17:48:32 +03001877 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04001878 {
Martin Radev802abe02016-08-04 17:48:32 +03001879 if (mComputeShaderLocalSizeDeclared &&
1880 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
1881 {
1882 error(typeQualifier.line, "Work group size does not match the previous declaration",
1883 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001884 return;
1885 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001886
Martin Radev802abe02016-08-04 17:48:32 +03001887 if (mShaderVersion < 310)
1888 {
1889 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001890 return;
1891 }
Jamie Madill099c0f32013-06-20 11:55:52 -04001892
Martin Radev4c4c8e72016-08-04 12:25:34 +03001893 if (!layoutQualifier.localSize.isAnyValueSet())
Martin Radev802abe02016-08-04 17:48:32 +03001894 {
1895 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001896 return;
1897 }
1898
1899 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
1900 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
1901
1902 const TConstantUnion *maxComputeWorkGroupSizeData =
1903 maxComputeWorkGroupSize->getConstPointer();
1904
1905 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
1906 {
1907 if (layoutQualifier.localSize[i] != -1)
1908 {
1909 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
1910 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
1911 if (mComputeShaderLocalSize[i] < 1 ||
1912 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
1913 {
1914 std::stringstream errorMessageStream;
1915 errorMessageStream << "Value must be at least 1 and no greater than "
1916 << maxComputeWorkGroupSizeValue;
1917 const std::string &errorMessage = errorMessageStream.str();
1918
Martin Radev4c4c8e72016-08-04 12:25:34 +03001919 error(typeQualifier.line, "invalid value:", getWorkGroupSizeString(i),
Martin Radev802abe02016-08-04 17:48:32 +03001920 errorMessage.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03001921 return;
1922 }
1923 }
1924 }
1925
1926 mComputeShaderLocalSizeDeclared = true;
1927 }
1928 else
Jamie Madill1566ef72013-06-20 11:55:54 -04001929 {
Martin Radev802abe02016-08-04 17:48:32 +03001930
Olli Etuaho8a176262016-08-16 14:23:01 +03001931 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03001932 {
Martin Radev802abe02016-08-04 17:48:32 +03001933 return;
1934 }
1935
1936 if (typeQualifier.qualifier != EvqUniform)
1937 {
1938 error(typeQualifier.line, "invalid qualifier:",
1939 getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
Martin Radev802abe02016-08-04 17:48:32 +03001940 return;
1941 }
1942
1943 if (mShaderVersion < 300)
1944 {
1945 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
1946 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001947 return;
1948 }
1949
Olli Etuaho856c4972016-08-08 11:38:39 +03001950 checkLocationIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001951
1952 if (layoutQualifier.matrixPacking != EmpUnspecified)
1953 {
1954 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
1955 }
1956
1957 if (layoutQualifier.blockStorage != EbsUnspecified)
1958 {
1959 mDefaultBlockStorage = layoutQualifier.blockStorage;
1960 }
Jamie Madill1566ef72013-06-20 11:55:54 -04001961 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001962}
1963
Olli Etuahoee63f5d2016-01-04 11:34:54 +02001964TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function,
1965 const TSourceLoc &location)
1966{
Olli Etuaho5d653182016-01-04 14:43:28 +02001967 // Note: symbolTableFunction could be the same as function if this is the first declaration.
1968 // Either way the instance in the symbol table is used to track whether the function is declared
1969 // multiple times.
1970 TFunction *symbolTableFunction =
1971 static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion()));
1972 if (symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100)
1973 {
1974 // ESSL 1.00.17 section 4.2.7.
1975 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
1976 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02001977 }
1978 symbolTableFunction->setHasPrototypeDeclaration();
1979
Olli Etuahoee63f5d2016-01-04 11:34:54 +02001980 TIntermAggregate *prototype = new TIntermAggregate;
1981 prototype->setType(function.getReturnType());
1982 prototype->setName(function.getMangledName());
1983 prototype->setFunctionId(function.getUniqueId());
1984
1985 for (size_t i = 0; i < function.getParamCount(); i++)
1986 {
1987 const TConstParameter &param = function.getParam(i);
1988 if (param.name != 0)
1989 {
1990 TVariable variable(param.name, *param.type);
1991
1992 TIntermSymbol *paramSymbol = intermediate.addSymbol(
1993 variable.getUniqueId(), variable.getName(), variable.getType(), location);
1994 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
1995 }
1996 else
1997 {
1998 TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
1999 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
2000 }
2001 }
2002
2003 prototype->setOp(EOpPrototype);
2004
2005 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002006
2007 if (!symbolTable.atGlobalLevel())
2008 {
2009 // ESSL 3.00.4 section 4.2.4.
2010 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002011 }
2012
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002013 return prototype;
2014}
2015
2016TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function,
2017 TIntermAggregate *functionPrototype,
2018 TIntermAggregate *functionBody,
2019 const TSourceLoc &location)
2020{
2021 //?? Check that all paths return a value if return type != void ?
2022 // May be best done as post process phase on intermediate code
2023 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2024 {
2025 error(location, "function does not return a value:", "", function.getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002026 }
2027
2028 TIntermAggregate *aggregate =
2029 intermediate.growAggregate(functionPrototype, functionBody, location);
2030 intermediate.setAggregateOperator(aggregate, EOpFunction, location);
2031 aggregate->setName(function.getMangledName().c_str());
2032 aggregate->setType(function.getReturnType());
2033 aggregate->setFunctionId(function.getUniqueId());
2034
2035 symbolTable.pop();
2036 return aggregate;
2037}
2038
Jamie Madill185fb402015-06-12 15:48:48 -04002039void TParseContext::parseFunctionPrototype(const TSourceLoc &location,
2040 TFunction *function,
2041 TIntermAggregate **aggregateOut)
2042{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002043 const TSymbol *builtIn =
2044 symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002045
2046 if (builtIn)
2047 {
2048 error(location, "built-in functions cannot be redefined", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002049 }
2050
Jamie Madillb98c3a82015-07-23 14:26:04 -04002051 TFunction *prevDec =
2052 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Jamie Madill185fb402015-06-12 15:48:48 -04002053 //
2054 // Note: 'prevDec' could be 'function' if this is the first time we've seen function
2055 // as it would have just been put in the symbol table. Otherwise, we're looking up
2056 // an earlier occurance.
2057 //
2058 if (prevDec->isDefined())
2059 {
2060 // Then this function already has a body.
2061 error(location, "function already has a body", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002062 }
2063 prevDec->setDefined();
2064 //
2065 // Overload the unique ID of the definition to be the same unique ID as the declaration.
2066 // Eventually we will probably want to have only a single definition and just swap the
2067 // arguments to be the definition's arguments.
2068 //
2069 function->setUniqueId(prevDec->getUniqueId());
2070
2071 // Raise error message if main function takes any parameters or return anything other than void
2072 if (function->getName() == "main")
2073 {
2074 if (function->getParamCount() > 0)
2075 {
2076 error(location, "function cannot take any parameter(s)", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002077 }
2078 if (function->getReturnType().getBasicType() != EbtVoid)
2079 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002080 error(location, "", function->getReturnType().getBasicString(),
2081 "main function cannot return a value");
Jamie Madill185fb402015-06-12 15:48:48 -04002082 }
2083 }
2084
2085 //
2086 // Remember the return type for later checking for RETURN statements.
2087 //
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002088 mCurrentFunctionType = &(prevDec->getReturnType());
2089 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002090
2091 //
2092 // Insert parameters into the symbol table.
2093 // If the parameter has no name, it's not an error, just don't insert it
2094 // (could be used for unused args).
2095 //
2096 // Also, accumulate the list of parameters into the HIL, so lower level code
2097 // knows where to find parameters.
2098 //
2099 TIntermAggregate *paramNodes = new TIntermAggregate;
2100 for (size_t i = 0; i < function->getParamCount(); i++)
2101 {
2102 const TConstParameter &param = function->getParam(i);
2103 if (param.name != 0)
2104 {
2105 TVariable *variable = new TVariable(param.name, *param.type);
2106 //
2107 // Insert the parameters with name in the symbol table.
2108 //
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002109 if (!symbolTable.declare(variable))
2110 {
Jamie Madill185fb402015-06-12 15:48:48 -04002111 error(location, "redefinition", variable->getName().c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002112 paramNodes = intermediate.growAggregate(
2113 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
2114 continue;
Jamie Madill185fb402015-06-12 15:48:48 -04002115 }
2116
2117 //
2118 // Add the parameter to the HIL
2119 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002120 TIntermSymbol *symbol = intermediate.addSymbol(
2121 variable->getUniqueId(), variable->getName(), variable->getType(), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002122
2123 paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
2124 }
2125 else
2126 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002127 paramNodes = intermediate.growAggregate(
2128 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002129 }
2130 }
2131 intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
2132 *aggregateOut = paramNodes;
2133 setLoopNestingLevel(0);
2134}
2135
Jamie Madillb98c3a82015-07-23 14:26:04 -04002136TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002137{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002138 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002139 // We don't know at this point whether this is a function definition or a prototype.
2140 // The definition production code will check for redefinitions.
2141 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002142 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002143 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2144 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002145 //
2146 TFunction *prevDec =
2147 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302148
2149 if (getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltIn(function->getName().c_str()))
2150 {
2151 // With ESSL 3.00, names of built-in functions cannot be redeclared as functions.
2152 // Therefore overloading or redefining builtin functions is an error.
2153 error(location, "Name of a built-in function cannot be redeclared as function",
2154 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302155 }
2156 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002157 {
2158 if (prevDec->getReturnType() != function->getReturnType())
2159 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002160 error(location, "overloaded functions must have the same return type",
Jamie Madill185fb402015-06-12 15:48:48 -04002161 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002162 }
2163 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2164 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002165 if (prevDec->getParam(i).type->getQualifier() !=
2166 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002167 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002168 error(location, "overloaded functions must have the same parameter qualifiers",
Jamie Madill185fb402015-06-12 15:48:48 -04002169 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002170 }
2171 }
2172 }
2173
2174 //
2175 // Check for previously declared variables using the same name.
2176 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002177 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002178 if (prevSym)
2179 {
2180 if (!prevSym->isFunction())
2181 {
2182 error(location, "redefinition", function->getName().c_str(), "function");
Jamie Madill185fb402015-06-12 15:48:48 -04002183 }
2184 }
2185 else
2186 {
2187 // Insert the unmangled name to detect potential future redefinition as a variable.
Jamie Madillb98c3a82015-07-23 14:26:04 -04002188 TFunction *newFunction =
2189 new TFunction(NewPoolTString(function->getName().c_str()), &function->getReturnType());
Jamie Madill185fb402015-06-12 15:48:48 -04002190 symbolTable.getOuterLevel()->insertUnmangled(newFunction);
2191 }
2192
2193 // We're at the inner scope level of the function's arguments and body statement.
2194 // Add the function prototype to the surrounding scope instead.
2195 symbolTable.getOuterLevel()->insert(function);
2196
2197 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002198 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2199 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002200 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2201 //
2202 return function;
2203}
2204
Olli Etuaho9de84a52016-06-14 17:36:01 +03002205TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2206 const TString *name,
2207 const TSourceLoc &location)
2208{
2209 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2210 {
2211 error(location, "no qualifiers allowed for function return",
2212 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002213 }
2214 if (!type.layoutQualifier.isEmpty())
2215 {
2216 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002217 }
2218 // make sure a sampler is not involved as well...
Olli Etuaho856c4972016-08-08 11:38:39 +03002219 checkIsNotSampler(location, type, "samplers can't be function return values");
Olli Etuahoe29324f2016-06-15 10:58:03 +03002220 if (mShaderVersion < 300)
2221 {
2222 // Array return values are forbidden, but there's also no valid syntax for declaring array
2223 // return values in ESSL 1.00.
2224 ASSERT(type.arraySize == 0 || mDiagnostics.numErrors() > 0);
2225
2226 if (type.isStructureContainingArrays())
2227 {
2228 // ESSL 1.00.17 section 6.1 Function Definitions
2229 error(location, "structures containing arrays can't be function return values",
2230 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002231 }
2232 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002233
2234 // Add the function as a prototype after parsing it (we do not support recursion)
2235 return new TFunction(name, new TType(type));
2236}
2237
Jamie Madill06145232015-05-13 13:10:01 -04002238TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002239{
Jamie Madill06145232015-05-13 13:10:01 -04002240 TPublicType publicType = publicTypeIn;
Olli Etuahobd163f62015-11-13 12:15:38 +02002241 if (publicType.isStructSpecifier)
2242 {
2243 error(publicType.line, "constructor can't be a structure definition",
2244 getBasicString(publicType.type));
Olli Etuahobd163f62015-11-13 12:15:38 +02002245 }
2246
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002247 TOperator op = EOpNull;
2248 if (publicType.userDef)
2249 {
2250 op = EOpConstructStruct;
2251 }
2252 else
2253 {
Geoff Lang156d7192016-07-21 16:11:00 -04002254 op = sh::TypeToConstructorOperator(TType(publicType));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002255 if (op == EOpNull)
2256 {
2257 error(publicType.line, "cannot construct this type", getBasicString(publicType.type));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002258 publicType.type = EbtFloat;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002259 op = EOpConstructFloat;
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002260 }
2261 }
2262
2263 TString tempString;
Dmitry Skiba7f17a502015-06-22 15:08:39 -07002264 const TType *type = new TType(publicType);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002265 return new TFunction(&tempString, type, op);
2266}
2267
Jamie Madillb98c3a82015-07-23 14:26:04 -04002268// This function is used to test for the correctness of the parameters passed to various constructor
2269// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002270//
Olli Etuaho856c4972016-08-08 11:38:39 +03002271// 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 +00002272//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002273TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002274 TOperator op,
2275 TFunction *fnCall,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302276 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002277{
Olli Etuaho856c4972016-08-08 11:38:39 +03002278 TType type = fnCall->getReturnType();
2279 if (type.isUnsizedArray())
2280 {
2281 type.setArraySize(static_cast<unsigned int>(fnCall->getParamCount()));
2282 }
2283 bool constType = true;
2284 for (size_t i = 0; i < fnCall->getParamCount(); ++i)
2285 {
2286 const TConstParameter &param = fnCall->getParam(i);
2287 if (param.type->getQualifier() != EvqConst)
2288 constType = false;
2289 }
2290 if (constType)
2291 type.setQualifier(EvqConst);
2292
Olli Etuaho8a176262016-08-16 14:23:01 +03002293 if (!checkConstructorArguments(line, arguments, *fnCall, op, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002294 {
2295 TIntermTyped *dummyNode = intermediate.setAggregateOperator(nullptr, op, line);
2296 dummyNode->setType(type);
2297 return dummyNode;
2298 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002299 TIntermAggregate *constructor = arguments->getAsAggregate();
2300 ASSERT(constructor != nullptr);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002301
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002302 // Turn the argument list itself into a constructor
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002303 constructor->setOp(op);
2304 constructor->setLine(line);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002305 ASSERT(constructor->isConstructor());
2306
2307 // Need to set type before setPrecisionFromChildren() because bool doesn't have precision.
Olli Etuaho856c4972016-08-08 11:38:39 +03002308 constructor->setType(type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002309
Olli Etuaho21203702014-11-13 16:16:21 +02002310 // Structs should not be precision qualified, the individual members may be.
2311 // Built-in types on the other hand should be precision qualified.
2312 if (op != EOpConstructStruct)
2313 {
2314 constructor->setPrecisionFromChildren();
Olli Etuaho856c4972016-08-08 11:38:39 +03002315 type.setPrecision(constructor->getPrecision());
Olli Etuaho21203702014-11-13 16:16:21 +02002316 }
2317
Olli Etuaho856c4972016-08-08 11:38:39 +03002318 constructor->setType(type);
2319
Olli Etuaho1d122782015-11-06 15:35:17 +02002320 TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002321 if (constConstructor)
2322 {
2323 return constConstructor;
2324 }
2325
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002326 return constructor;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002327}
2328
Olli Etuaho90892fb2016-07-14 14:44:51 +03002329// This function returns vector field(s) being accessed from a constant vector.
2330TIntermConstantUnion *TParseContext::foldVectorSwizzle(TVectorFields &fields,
2331 TIntermConstantUnion *baseNode,
2332 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002333{
Olli Etuaho90892fb2016-07-14 14:44:51 +03002334 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002335 ASSERT(unionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002336
Arun Patole7e7e68d2015-05-22 12:02:25 +05302337 TConstantUnion *constArray = new TConstantUnion[fields.num];
Olli Etuaho90892fb2016-07-14 14:44:51 +03002338 const auto &type = baseNode->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002339
Arun Patole7e7e68d2015-05-22 12:02:25 +05302340 for (int i = 0; i < fields.num; i++)
2341 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002342 // Out-of-range indices should already be checked.
2343 ASSERT(fields.offsets[i] < type.getNominalSize());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002344 constArray[i] = unionArray[fields.offsets[i]];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302345 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03002346 return intermediate.addConstantUnion(constArray, type, location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002347}
2348
Olli Etuaho90892fb2016-07-14 14:44:51 +03002349// This function returns the column vector being accessed from a constant matrix.
2350TIntermConstantUnion *TParseContext::foldMatrixSubscript(int index,
2351 TIntermConstantUnion *baseNode,
2352 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002353{
Olli Etuaho90892fb2016-07-14 14:44:51 +03002354 ASSERT(index < baseNode->getType().getCols());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002355
Olli Etuaho90892fb2016-07-14 14:44:51 +03002356 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
2357 int size = baseNode->getType().getRows();
2358 return intermediate.addConstantUnion(&unionArray[size * index], baseNode->getType(), location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002359}
2360
Olli Etuaho90892fb2016-07-14 14:44:51 +03002361// This function returns an element of an array accessed from a constant array.
2362TIntermConstantUnion *TParseContext::foldArraySubscript(int index,
2363 TIntermConstantUnion *baseNode,
2364 const TSourceLoc &location)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002365{
Olli Etuaho856c4972016-08-08 11:38:39 +03002366 ASSERT(index < static_cast<int>(baseNode->getArraySize()));
Olli Etuaho90892fb2016-07-14 14:44:51 +03002367
2368 TType arrayElementType = baseNode->getType();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002369 arrayElementType.clearArrayness();
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002370 size_t arrayElementSize = arrayElementType.getObjectSize();
Olli Etuaho90892fb2016-07-14 14:44:51 +03002371 const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
2372 return intermediate.addConstantUnion(&unionArray[arrayElementSize * index], baseNode->getType(),
2373 location);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002374}
2375
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002376//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002377// This function returns the value of a particular field inside a constant structure from the symbol
2378// table.
2379// If there is an embedded/nested struct, it appropriately calls addConstStructNested or
2380// addConstStructFromAggr function and returns the parse-tree with the values of the embedded/nested
2381// struct.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002382//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002383TIntermTyped *TParseContext::addConstStruct(const TString &identifier,
2384 TIntermTyped *node,
2385 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002386{
Arun Patole7e7e68d2015-05-22 12:02:25 +05302387 const TFieldList &fields = node->getType().getStruct()->fields();
Jamie Madillb98c3a82015-07-23 14:26:04 -04002388 size_t instanceSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002389
Arun Patole7e7e68d2015-05-22 12:02:25 +05302390 for (size_t index = 0; index < fields.size(); ++index)
2391 {
2392 if (fields[index]->name() == identifier)
2393 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002394 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302395 }
2396 else
2397 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002398 instanceSize += fields[index]->type()->getObjectSize();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002399 }
2400 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002401
Jamie Madill94bf7f22013-07-08 13:31:15 -04002402 TIntermTyped *typedNode;
2403 TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
Arun Patole7e7e68d2015-05-22 12:02:25 +05302404 if (tempConstantNode)
2405 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002406 const TConstantUnion *constArray = tempConstantNode->getUnionArrayPointer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002407
Jamie Madillb98c3a82015-07-23 14:26:04 -04002408 // type will be changed in the calling function
2409 typedNode = intermediate.addConstantUnion(constArray + instanceSize,
2410 tempConstantNode->getType(), line);
Arun Patole7e7e68d2015-05-22 12:02:25 +05302411 }
2412 else
2413 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002414 error(line, "Cannot offset into the structure", "Error");
Olli Etuaho383b7912016-08-05 11:22:59 +03002415 return nullptr;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002416 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002417
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002418 return typedNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002419}
2420
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002421//
2422// Interface/uniform blocks
2423//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002424TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualifier,
2425 const TSourceLoc &nameLine,
2426 const TString &blockName,
2427 TFieldList *fieldList,
2428 const TString *instanceName,
2429 const TSourceLoc &instanceLine,
2430 TIntermTyped *arrayIndex,
2431 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002432{
Olli Etuaho856c4972016-08-08 11:38:39 +03002433 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002434
2435 if (typeQualifier.qualifier != EvqUniform)
2436 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302437 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier),
2438 "interface blocks must be uniform");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002439 }
2440
Jamie Madill099c0f32013-06-20 11:55:52 -04002441 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03002442 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04002443
Jamie Madill099c0f32013-06-20 11:55:52 -04002444 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2445 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002446 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002447 }
2448
Jamie Madill1566ef72013-06-20 11:55:54 -04002449 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2450 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002451 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002452 }
2453
Olli Etuaho856c4972016-08-08 11:38:39 +03002454 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002455
Arun Patole7e7e68d2015-05-22 12:02:25 +05302456 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2457 if (!symbolTable.declare(blockNameSymbol))
2458 {
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002459 error(nameLine, "redefinition", blockName.c_str(), "interface block name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002460 }
2461
Jamie Madill98493dd2013-07-08 14:39:03 -04002462 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302463 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2464 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002465 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302466 TType *fieldType = field->type();
2467 if (IsSampler(fieldType->getBasicType()))
2468 {
2469 error(field->line(), "unsupported type", fieldType->getBasicString(),
2470 "sampler types are not allowed in interface blocks");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002471 }
2472
Jamie Madill98493dd2013-07-08 14:39:03 -04002473 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002474 switch (qualifier)
2475 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002476 case EvqGlobal:
2477 case EvqUniform:
2478 break;
2479 default:
2480 error(field->line(), "invalid qualifier on interface block member",
2481 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04002482 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002483 }
Jamie Madilla5efff92013-06-06 11:56:47 -04002484
2485 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04002486 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03002487 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Jamie Madill099c0f32013-06-20 11:55:52 -04002488
Jamie Madill98493dd2013-07-08 14:39:03 -04002489 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04002490 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002491 error(field->line(), "invalid layout qualifier:",
2492 getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
Jamie Madill1566ef72013-06-20 11:55:54 -04002493 }
2494
Jamie Madill98493dd2013-07-08 14:39:03 -04002495 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04002496 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002497 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002498 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002499 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04002500 {
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002501 warning(field->line(), "extraneous layout qualifier:",
Jamie Madillb98c3a82015-07-23 14:26:04 -04002502 getMatrixPackingString(fieldLayoutQualifier.matrixPacking),
2503 "only has an effect on matrix types");
Jamie Madill099c0f32013-06-20 11:55:52 -04002504 }
2505
Jamie Madill98493dd2013-07-08 14:39:03 -04002506 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002507 }
2508
Jamie Madill98493dd2013-07-08 14:39:03 -04002509 // add array index
Olli Etuaho856c4972016-08-08 11:38:39 +03002510 unsigned int arraySize = 0;
2511 if (arrayIndex != nullptr)
Jamie Madill98493dd2013-07-08 14:39:03 -04002512 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002513 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
Jamie Madill98493dd2013-07-08 14:39:03 -04002514 }
2515
Jamie Madillb98c3a82015-07-23 14:26:04 -04002516 TInterfaceBlock *interfaceBlock =
2517 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2518 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
2519 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002520
2521 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04002522 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002523
Jamie Madill98493dd2013-07-08 14:39:03 -04002524 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002525 {
2526 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04002527 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2528 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002529 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302530 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04002531
2532 // set parent pointer of the field variable
2533 fieldType->setInterfaceBlock(interfaceBlock);
2534
Arun Patole7e7e68d2015-05-22 12:02:25 +05302535 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04002536 fieldVariable->setQualifier(typeQualifier.qualifier);
2537
Arun Patole7e7e68d2015-05-22 12:02:25 +05302538 if (!symbolTable.declare(fieldVariable))
2539 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002540 error(field->line(), "redefinition", field->name().c_str(),
2541 "interface block member name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002542 }
2543 }
2544 }
2545 else
2546 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002547 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03002548
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002549 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05302550 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002551 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04002552
Arun Patole7e7e68d2015-05-22 12:02:25 +05302553 if (!symbolTable.declare(instanceTypeDef))
2554 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002555 error(instanceLine, "redefinition", instanceName->c_str(),
2556 "interface block instance name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002557 }
2558
Jamie Madillb98c3a82015-07-23 14:26:04 -04002559 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002560 symbolName = instanceTypeDef->getName();
2561 }
2562
Jamie Madillb98c3a82015-07-23 14:26:04 -04002563 TIntermAggregate *aggregate = intermediate.makeAggregate(
2564 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line),
2565 nameLine);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002566 aggregate->setOp(EOpDeclaration);
Jamie Madill98493dd2013-07-08 14:39:03 -04002567
2568 exitStructDeclaration();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002569 return aggregate;
2570}
2571
Olli Etuaho383b7912016-08-05 11:22:59 +03002572void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002573{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002574 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002575
2576 // Embedded structure definitions are not supported per GLSL ES spec.
2577 // They aren't allowed in GLSL either, but we need to detect this here
2578 // so we don't rely on the GLSL compiler to catch it.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302579 if (mStructNestingLevel > 1)
2580 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002581 error(line, "", "Embedded struct definitions are not allowed");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002582 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002583}
2584
2585void TParseContext::exitStructDeclaration()
2586{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002587 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002588}
2589
Jamie Madillb98c3a82015-07-23 14:26:04 -04002590namespace
2591{
kbr@chromium.org476541f2011-10-27 21:14:51 +00002592const int kWebGLMaxStructNesting = 4;
2593
2594} // namespace
2595
Olli Etuaho8a176262016-08-16 14:23:01 +03002596void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002597{
Arun Patole7e7e68d2015-05-22 12:02:25 +05302598 if (!IsWebGLBasedSpec(mShaderSpec))
2599 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002600 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002601 }
2602
Arun Patole7e7e68d2015-05-22 12:02:25 +05302603 if (field.type()->getBasicType() != EbtStruct)
2604 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002605 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002606 }
2607
2608 // We're already inside a structure definition at this point, so add
2609 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302610 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2611 {
Jamie Madill41a49272014-03-18 16:10:13 -04002612 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002613 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
2614 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04002615 std::string reason = reasonStream.str();
2616 error(line, reason.c_str(), field.name().c_str(), "");
Olli Etuaho8a176262016-08-16 14:23:01 +03002617 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002618 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002619}
2620
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00002621//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002622// Parse an array index expression
2623//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002624TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
2625 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302626 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002627{
2628 TIntermTyped *indexedExpression = NULL;
2629
2630 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2631 {
2632 if (baseExpression->getAsSymbolNode())
2633 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302634 error(location, " left of '[' is not of type array, matrix, or vector ",
2635 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002636 }
2637 else
2638 {
2639 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2640 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002641 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002642
Jamie Madill21c1e452014-12-29 11:33:41 -05002643 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2644
Olli Etuaho36b05142015-11-12 13:10:42 +02002645 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
2646 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
2647 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
2648 // index is a constant expression.
2649 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
2650 {
2651 if (baseExpression->isInterfaceBlock())
2652 {
2653 error(
2654 location, "", "[",
2655 "array indexes for interface blocks arrays must be constant integral expressions");
Olli Etuaho36b05142015-11-12 13:10:42 +02002656 }
2657 else if (baseExpression->getQualifier() == EvqFragmentOut)
2658 {
2659 error(location, "", "[",
2660 "array indexes for fragment outputs must be constant integral expressions");
Olli Etuaho36b05142015-11-12 13:10:42 +02002661 }
Olli Etuaho3e960462015-11-12 15:58:39 +02002662 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
2663 {
2664 error(location, "", "[", "array index for gl_FragData must be constant zero");
Olli Etuaho3e960462015-11-12 15:58:39 +02002665 }
Olli Etuaho36b05142015-11-12 13:10:42 +02002666 }
2667
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002668 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04002669 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002670 // If the index is not qualified as constant, the behavior in the spec is undefined. This
2671 // applies even if ANGLE has been able to constant fold it (ANGLE may constant fold
2672 // expressions that are not constant expressions). The most compatible way to handle this
2673 // case is to report a warning instead of an error and force the index to be in the
2674 // correct range.
2675 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madill21c1e452014-12-29 11:33:41 -05002676 int index = indexConstantUnion->getIConst(0);
Olli Etuaho90892fb2016-07-14 14:44:51 +03002677 if (!baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04002678 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002679 // Array checks are done later because a different error message might be generated
2680 // based on the index in some cases.
2681 if (baseExpression->isVector())
2682 {
2683 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2684 baseExpression->getType().getNominalSize(),
2685 "vector field selection out of range", "[]");
2686 }
2687 else if (baseExpression->isMatrix())
2688 {
2689 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2690 baseExpression->getType().getCols(),
2691 "matrix field selection out of range", "[]");
2692 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002693 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03002694
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002695 TIntermConstantUnion *baseConstantUnion = baseExpression->getAsConstantUnion();
2696 if (baseConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04002697 {
2698 if (baseExpression->isArray())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002699 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002700 index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2701 baseExpression->getArraySize(),
2702 "array index out of range", "[]");
2703 // Constant folding for array indexing.
2704 indexedExpression = foldArraySubscript(index, baseConstantUnion, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002705 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002706 else if (baseExpression->isVector())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002707 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002708 // Constant folding for vector indexing - reusing vector swizzle folding.
Jamie Madill7164cf42013-07-08 13:30:59 -04002709 TVectorFields fields;
2710 fields.num = 1;
Olli Etuaho90892fb2016-07-14 14:44:51 +03002711 fields.offsets[0] = index;
2712 indexedExpression = foldVectorSwizzle(fields, baseConstantUnion, location);
Jamie Madill7164cf42013-07-08 13:30:59 -04002713 }
2714 else if (baseExpression->isMatrix())
2715 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002716 // Constant folding for matrix indexing.
2717 indexedExpression = foldMatrixSubscript(index, baseConstantUnion, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002718 }
2719 }
2720 else
2721 {
Jamie Madillb11e2482015-05-04 14:21:22 -04002722 int safeIndex = -1;
2723
Jamie Madill7164cf42013-07-08 13:30:59 -04002724 if (baseExpression->isArray())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002725 {
Olli Etuaho3e960462015-11-12 15:58:39 +02002726 if (baseExpression->getQualifier() == EvqFragData && index > 0)
2727 {
2728 if (mShaderSpec == SH_WEBGL2_SPEC)
2729 {
2730 // Error has been already generated if index is not const.
2731 if (indexExpression->getQualifier() == EvqConst)
2732 {
2733 error(location, "", "[",
2734 "array index for gl_FragData must be constant zero");
Olli Etuaho3e960462015-11-12 15:58:39 +02002735 }
2736 safeIndex = 0;
2737 }
2738 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
2739 {
2740 outOfRangeError(outOfRangeIndexIsError, location, "", "[",
2741 "array index for gl_FragData must be zero when "
2742 "GL_EXT_draw_buffers is disabled");
2743 safeIndex = 0;
2744 }
2745 }
2746 // Only do generic out-of-range check if similar error hasn't already been reported.
Olli Etuaho90892fb2016-07-14 14:44:51 +03002747 if (safeIndex < 0)
Jamie Madill7164cf42013-07-08 13:30:59 -04002748 {
Olli Etuaho90892fb2016-07-14 14:44:51 +03002749 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2750 baseExpression->getArraySize(),
2751 "array index out of range", "[]");
Jamie Madill7164cf42013-07-08 13:30:59 -04002752 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002753 }
2754
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002755 // Data of constant unions can't be changed, because it may be shared with other
2756 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
2757 // sanitized object.
Jamie Madillb11e2482015-05-04 14:21:22 -04002758 if (safeIndex != -1)
2759 {
2760 TConstantUnion *safeConstantUnion = new TConstantUnion();
2761 safeConstantUnion->setIConst(safeIndex);
2762 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
2763 }
2764
Jamie Madillb98c3a82015-07-23 14:26:04 -04002765 indexedExpression =
2766 intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002767 }
2768 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002769 else
2770 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002771 indexedExpression =
2772 intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
Jamie Madill7164cf42013-07-08 13:30:59 -04002773 }
2774
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002775 if (indexedExpression == 0)
2776 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002777 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002778 unionArray->setFConst(0.0f);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002779 indexedExpression =
2780 intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002781 }
2782 else if (baseExpression->isArray())
2783 {
Olli Etuahob3fbd862015-09-30 17:55:02 +03002784 TType indexedType = baseExpression->getType();
2785 indexedType.clearArrayness();
2786 indexedExpression->setType(indexedType);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002787 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002788 else if (baseExpression->isMatrix())
2789 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002790 indexedExpression->setType(TType(baseExpression->getBasicType(),
Olli Etuahob3fbd862015-09-30 17:55:02 +03002791 baseExpression->getPrecision(), EvqTemporary,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002792 static_cast<unsigned char>(baseExpression->getRows())));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002793 }
2794 else if (baseExpression->isVector())
2795 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002796 indexedExpression->setType(
Olli Etuahob3fbd862015-09-30 17:55:02 +03002797 TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002798 }
2799 else
2800 {
2801 indexedExpression->setType(baseExpression->getType());
2802 }
2803
Olli Etuahob3fbd862015-09-30 17:55:02 +03002804 if (baseExpression->getType().getQualifier() == EvqConst &&
2805 indexExpression->getType().getQualifier() == EvqConst)
2806 {
2807 indexedExpression->getTypePointer()->setQualifier(EvqConst);
2808 }
2809 else
2810 {
2811 indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
2812 }
2813
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002814 return indexedExpression;
2815}
2816
Olli Etuaho90892fb2016-07-14 14:44:51 +03002817int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
2818 const TSourceLoc &location,
2819 int index,
2820 int arraySize,
2821 const char *reason,
2822 const char *token)
2823{
2824 if (index >= arraySize || index < 0)
2825 {
2826 std::stringstream extraInfoStream;
2827 extraInfoStream << "'" << index << "'";
2828 std::string extraInfo = extraInfoStream.str();
2829 outOfRangeError(outOfRangeIndexIsError, location, reason, token, extraInfo.c_str());
2830 if (index < 0)
2831 {
2832 return 0;
2833 }
2834 else
2835 {
2836 return arraySize - 1;
2837 }
2838 }
2839 return index;
2840}
2841
Jamie Madillb98c3a82015-07-23 14:26:04 -04002842TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
2843 const TSourceLoc &dotLocation,
2844 const TString &fieldString,
2845 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002846{
2847 TIntermTyped *indexedExpression = NULL;
2848
2849 if (baseExpression->isArray())
2850 {
2851 error(fieldLocation, "cannot apply dot operator to an array", ".");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002852 }
2853
2854 if (baseExpression->isVector())
2855 {
2856 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002857 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
2858 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002859 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002860 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002861 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002862 }
2863
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002864 if (baseExpression->getAsConstantUnion())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002865 {
2866 // constant folding for vector fields
Olli Etuaho90892fb2016-07-14 14:44:51 +03002867 indexedExpression =
2868 foldVectorSwizzle(fields, baseExpression->getAsConstantUnion(), fieldLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002869 }
2870 else
2871 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302872 TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002873 indexedExpression =
2874 intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002875 }
2876 if (indexedExpression == nullptr)
2877 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002878 indexedExpression = baseExpression;
2879 }
2880 else
2881 {
2882 // Note that the qualifier set here will be corrected later.
Jamie Madillb98c3a82015-07-23 14:26:04 -04002883 indexedExpression->setType(TType(baseExpression->getBasicType(),
2884 baseExpression->getPrecision(), EvqTemporary,
Jamie Madillc2128ff2016-07-04 10:26:17 -04002885 static_cast<unsigned char>(fields.num)));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002886 }
2887 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002888 else if (baseExpression->getBasicType() == EbtStruct)
2889 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002890 bool fieldFound = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302891 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04002892 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002893 {
2894 error(dotLocation, "structure has no fields", "Internal Error");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002895 indexedExpression = baseExpression;
2896 }
2897 else
2898 {
2899 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04002900 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002901 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002902 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002903 {
2904 fieldFound = true;
2905 break;
2906 }
2907 }
2908 if (fieldFound)
2909 {
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002910 if (baseExpression->getAsConstantUnion())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002911 {
2912 indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
2913 if (indexedExpression == 0)
2914 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002915 indexedExpression = baseExpression;
2916 }
2917 else
2918 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002919 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002920 }
2921 }
2922 else
2923 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002924 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002925 unionArray->setIConst(i);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002926 TIntermTyped *index = intermediate.addConstantUnion(
2927 unionArray, *fields[i]->type(), fieldLocation);
2928 indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression,
2929 index, dotLocation);
Jamie Madill98493dd2013-07-08 14:39:03 -04002930 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002931 }
2932 }
2933 else
2934 {
2935 error(dotLocation, " no such field in structure", fieldString.c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002936 indexedExpression = baseExpression;
2937 }
2938 }
2939 }
Jamie Madill98493dd2013-07-08 14:39:03 -04002940 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002941 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002942 bool fieldFound = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05302943 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04002944 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002945 {
2946 error(dotLocation, "interface block has no fields", "Internal Error");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002947 indexedExpression = baseExpression;
2948 }
2949 else
2950 {
2951 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04002952 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002953 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002954 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002955 {
2956 fieldFound = true;
2957 break;
2958 }
2959 }
2960 if (fieldFound)
2961 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04002962 TConstantUnion *unionArray = new TConstantUnion[1];
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002963 unionArray->setIConst(i);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002964 TIntermTyped *index =
2965 intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
2966 indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock,
2967 baseExpression, index, dotLocation);
Jamie Madill98493dd2013-07-08 14:39:03 -04002968 indexedExpression->setType(*fields[i]->type());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002969 }
2970 else
2971 {
2972 error(dotLocation, " no such field in interface block", fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002973 indexedExpression = baseExpression;
2974 }
2975 }
2976 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002977 else
2978 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002979 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002980 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03002981 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05302982 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002983 }
2984 else
2985 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302986 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03002987 " field selection requires structure, vector, or interface block on left hand "
2988 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05302989 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002990 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002991 indexedExpression = baseExpression;
2992 }
2993
Olli Etuahob1edc4f2015-11-02 17:20:03 +02002994 if (baseExpression->getQualifier() == EvqConst)
2995 {
2996 indexedExpression->getTypePointer()->setQualifier(EvqConst);
2997 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002998 else
2999 {
3000 indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
3001 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02003002
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003003 return indexedExpression;
3004}
3005
Jamie Madillb98c3a82015-07-23 14:26:04 -04003006TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3007 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003008{
Martin Radev802abe02016-08-04 17:48:32 +03003009 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003010
3011 if (qualifierType == "shared")
3012 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003013 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003014 }
3015 else if (qualifierType == "packed")
3016 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003017 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003018 }
3019 else if (qualifierType == "std140")
3020 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003021 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003022 }
3023 else if (qualifierType == "row_major")
3024 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003025 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003026 }
3027 else if (qualifierType == "column_major")
3028 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003029 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003030 }
3031 else if (qualifierType == "location")
3032 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003033 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(),
3034 "location requires an argument");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003035 }
3036 else
3037 {
3038 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003039 }
3040
Jamie Madilla5efff92013-06-06 11:56:47 -04003041 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003042}
3043
Martin Radev802abe02016-08-04 17:48:32 +03003044void TParseContext::parseLocalSize(const TString &qualifierType,
3045 const TSourceLoc &qualifierTypeLine,
3046 int intValue,
3047 const TSourceLoc &intValueLine,
3048 const std::string &intValueString,
3049 size_t index,
Martin Radev4c4c8e72016-08-04 12:25:34 +03003050 sh::WorkGroupSize *localSize)
Martin Radev802abe02016-08-04 17:48:32 +03003051{
Olli Etuaho856c4972016-08-08 11:38:39 +03003052 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03003053 if (intValue < 1)
3054 {
Martin Radev4c4c8e72016-08-04 12:25:34 +03003055 std::string errorMessage = std::string(getWorkGroupSizeString(index)) + " must be positive";
Martin Radev802abe02016-08-04 17:48:32 +03003056 error(intValueLine, "out of range:", intValueString.c_str(), errorMessage.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003057 }
3058 (*localSize)[index] = intValue;
3059}
3060
Jamie Madillb98c3a82015-07-23 14:26:04 -04003061TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3062 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003063 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303064 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003065{
Martin Radev802abe02016-08-04 17:48:32 +03003066 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003067
Martin Radev802abe02016-08-04 17:48:32 +03003068 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003069
Martin Radev802abe02016-08-04 17:48:32 +03003070 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003071 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003072 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003073 if (intValue < 0)
3074 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003075 error(intValueLine, "out of range:", intValueString.c_str(),
3076 "location must be non-negative");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003077 }
3078 else
3079 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003080 qualifier.location = intValue;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003081 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003082 }
Martin Radev802abe02016-08-04 17:48:32 +03003083 else if (qualifierType == "local_size_x")
3084 {
3085 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3086 &qualifier.localSize);
3087 }
3088 else if (qualifierType == "local_size_y")
3089 {
3090 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3091 &qualifier.localSize);
3092 }
3093 else if (qualifierType == "local_size_z")
3094 {
3095 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3096 &qualifier.localSize);
3097 }
3098 else
3099 {
3100 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003101 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003102
Jamie Madilla5efff92013-06-06 11:56:47 -04003103 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003104}
3105
Jamie Madillb98c3a82015-07-23 14:26:04 -04003106TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003107 TLayoutQualifier rightQualifier,
3108 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003109{
Jamie Madilla5efff92013-06-06 11:56:47 -04003110 TLayoutQualifier joinedQualifier = leftQualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003111
Jamie Madilla5efff92013-06-06 11:56:47 -04003112 if (rightQualifier.location != -1)
3113 {
3114 joinedQualifier.location = rightQualifier.location;
3115 }
3116 if (rightQualifier.matrixPacking != EmpUnspecified)
3117 {
3118 joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
3119 }
3120 if (rightQualifier.blockStorage != EbsUnspecified)
3121 {
3122 joinedQualifier.blockStorage = rightQualifier.blockStorage;
3123 }
3124
Martin Radev802abe02016-08-04 17:48:32 +03003125 for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i)
3126 {
3127 if (rightQualifier.localSize[i] != -1)
3128 {
3129 if (joinedQualifier.localSize[i] != -1 &&
3130 joinedQualifier.localSize[i] != rightQualifier.localSize[i])
3131 {
3132 error(rightQualifierLocation,
3133 "Cannot have multiple different work group size specifiers",
Martin Radev4c4c8e72016-08-04 12:25:34 +03003134 getWorkGroupSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03003135 }
3136 joinedQualifier.localSize[i] = rightQualifier.localSize[i];
3137 }
3138 }
3139
Jamie Madilla5efff92013-06-06 11:56:47 -04003140 return joinedQualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003141}
3142
Arun Patole7e7e68d2015-05-22 12:02:25 +05303143TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc,
3144 TQualifier interpolationQualifier,
3145 const TSourceLoc &storageLoc,
3146 TQualifier storageQualifier)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003147{
3148 TQualifier mergedQualifier = EvqSmoothIn;
3149
Arun Patole7e7e68d2015-05-22 12:02:25 +05303150 if (storageQualifier == EvqFragmentIn)
3151 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003152 if (interpolationQualifier == EvqSmooth)
3153 mergedQualifier = EvqSmoothIn;
3154 else if (interpolationQualifier == EvqFlat)
3155 mergedQualifier = EvqFlatIn;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003156 else
3157 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003158 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303159 else if (storageQualifier == EvqCentroidIn)
3160 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003161 if (interpolationQualifier == EvqSmooth)
3162 mergedQualifier = EvqCentroidIn;
3163 else if (interpolationQualifier == EvqFlat)
3164 mergedQualifier = EvqFlatIn;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003165 else
3166 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003167 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303168 else if (storageQualifier == EvqVertexOut)
3169 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003170 if (interpolationQualifier == EvqSmooth)
3171 mergedQualifier = EvqSmoothOut;
3172 else if (interpolationQualifier == EvqFlat)
3173 mergedQualifier = EvqFlatOut;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003174 else
3175 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003176 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303177 else if (storageQualifier == EvqCentroidOut)
3178 {
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003179 if (interpolationQualifier == EvqSmooth)
3180 mergedQualifier = EvqCentroidOut;
3181 else if (interpolationQualifier == EvqFlat)
3182 mergedQualifier = EvqFlatOut;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003183 else
3184 UNREACHABLE();
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003185 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05303186 else
3187 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003188 error(interpolationLoc,
3189 "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303190 getInterpolationString(interpolationQualifier));
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003191
3192 mergedQualifier = storageQualifier;
3193 }
3194
3195 TPublicType type;
3196 type.setBasic(EbtVoid, mergedQualifier, storageLoc);
3197 return type;
3198}
3199
Jamie Madillb98c3a82015-07-23 14:26:04 -04003200TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3201 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003202{
Olli Etuaho856c4972016-08-08 11:38:39 +03003203 checkIsNonVoid(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003204
Olli Etuaho856c4972016-08-08 11:38:39 +03003205 checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003206
Arun Patole7e7e68d2015-05-22 12:02:25 +05303207 for (unsigned int i = 0; i < fieldList->size(); ++i)
3208 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003209 //
3210 // Careful not to replace already known aspects of type, like array-ness
3211 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303212 TType *type = (*fieldList)[i]->type();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003213 type->setBasicType(typeSpecifier.type);
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003214 type->setPrimarySize(typeSpecifier.primarySize);
3215 type->setSecondarySize(typeSpecifier.secondarySize);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003216 type->setPrecision(typeSpecifier.precision);
3217 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003218 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003219
3220 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303221 if (type->isArray())
3222 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003223 checkIsValidTypeForArray(typeSpecifier.line, typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003224 }
3225 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003226 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Arun Patole7e7e68d2015-05-22 12:02:25 +05303227 if (typeSpecifier.userDef)
3228 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003229 type->setStruct(typeSpecifier.userDef->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003230 }
3231
Olli Etuaho8a176262016-08-16 14:23:01 +03003232 checkIsBelowStructNestingLimit(typeSpecifier.line, *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003233 }
3234
Jamie Madill98493dd2013-07-08 14:39:03 -04003235 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003236}
3237
Jamie Madillb98c3a82015-07-23 14:26:04 -04003238TPublicType TParseContext::addStructure(const TSourceLoc &structLine,
3239 const TSourceLoc &nameLine,
3240 const TString *structName,
3241 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003242{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303243 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003244 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003245
Jamie Madill9b820842015-02-12 10:40:10 -05003246 // Store a bool in the struct if we're at global scope, to allow us to
3247 // skip the local struct scoping workaround in HLSL.
Jamie Madillb960cc42015-02-12 15:33:20 +00003248 structure->setUniqueId(TSymbolTable::nextUniqueId());
Jamie Madill9b820842015-02-12 10:40:10 -05003249 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003250
Jamie Madill98493dd2013-07-08 14:39:03 -04003251 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003252 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003253 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303254 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3255 if (!symbolTable.declare(userTypeDef))
3256 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003257 error(nameLine, "redefinition", structName->c_str(), "struct");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003258 }
3259 }
3260
3261 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003262 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003263 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003264 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003265 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003266 switch (qualifier)
3267 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003268 case EvqGlobal:
3269 case EvqTemporary:
3270 break;
3271 default:
3272 error(field.line(), "invalid qualifier on struct member",
3273 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003274 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003275 }
3276 }
3277
3278 TPublicType publicType;
3279 publicType.setBasic(EbtStruct, EvqTemporary, structLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04003280 publicType.userDef = structureType;
Olli Etuahobd163f62015-11-13 12:15:38 +02003281 publicType.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003282 exitStructDeclaration();
3283
3284 return publicType;
3285}
3286
Jamie Madillb98c3a82015-07-23 14:26:04 -04003287TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
3288 TIntermAggregate *statementList,
3289 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003290{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003291 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003292 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003293 init->isVector())
3294 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003295 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3296 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003297 return nullptr;
3298 }
3299
Olli Etuahoac5274d2015-02-20 10:19:08 +02003300 if (statementList)
3301 {
3302 if (!ValidateSwitch::validate(switchType, this, statementList, loc))
3303 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003304 return nullptr;
3305 }
3306 }
3307
Olli Etuahoa3a36662015-02-17 13:46:51 +02003308 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3309 if (node == nullptr)
3310 {
3311 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003312 return nullptr;
3313 }
3314 return node;
3315}
3316
3317TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3318{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003319 if (mSwitchNestingLevel == 0)
3320 {
3321 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003322 return nullptr;
3323 }
3324 if (condition == nullptr)
3325 {
3326 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003327 return nullptr;
3328 }
3329 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003330 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003331 {
3332 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003333 }
3334 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003335 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3336 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3337 // fold in case labels.
3338 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003339 {
3340 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003341 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003342 TIntermCase *node = intermediate.addCase(condition, loc);
3343 if (node == nullptr)
3344 {
3345 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003346 return nullptr;
3347 }
3348 return node;
3349}
3350
3351TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3352{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003353 if (mSwitchNestingLevel == 0)
3354 {
3355 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003356 return nullptr;
3357 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003358 TIntermCase *node = intermediate.addCase(nullptr, loc);
3359 if (node == nullptr)
3360 {
3361 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003362 return nullptr;
3363 }
3364 return node;
3365}
3366
Jamie Madillb98c3a82015-07-23 14:26:04 -04003367TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3368 TIntermTyped *child,
3369 const TSourceLoc &loc,
3370 const TType *funcReturnType)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003371{
3372 if (child == nullptr)
3373 {
3374 return nullptr;
3375 }
3376
3377 switch (op)
3378 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003379 case EOpLogicalNot:
3380 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3381 child->isVector())
3382 {
3383 return nullptr;
3384 }
3385 break;
3386 case EOpBitwiseNot:
3387 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3388 child->isMatrix() || child->isArray())
3389 {
3390 return nullptr;
3391 }
3392 break;
3393 case EOpPostIncrement:
3394 case EOpPreIncrement:
3395 case EOpPostDecrement:
3396 case EOpPreDecrement:
3397 case EOpNegative:
3398 case EOpPositive:
3399 if (child->getBasicType() == EbtStruct || child->getBasicType() == EbtBool ||
Olli Etuaho558b0382016-08-26 17:54:34 +03003400 child->isArray() || IsSampler(child->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -04003401 {
3402 return nullptr;
3403 }
3404 // Operators for built-ins are already type checked against their prototype.
3405 default:
3406 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003407 }
3408
Olli Etuahof6c694b2015-03-26 14:50:53 +02003409 return intermediate.addUnaryMath(op, child, loc, funcReturnType);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003410}
3411
Olli Etuaho09b22472015-02-11 11:47:26 +02003412TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3413{
Olli Etuahof6c694b2015-03-26 14:50:53 +02003414 TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003415 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003416 {
3417 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003418 return child;
3419 }
3420 return node;
3421}
3422
Jamie Madillb98c3a82015-07-23 14:26:04 -04003423TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3424 TIntermTyped *child,
3425 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003426{
Olli Etuaho856c4972016-08-08 11:38:39 +03003427 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003428 return addUnaryMath(op, child, loc);
3429}
3430
Jamie Madillb98c3a82015-07-23 14:26:04 -04003431bool TParseContext::binaryOpCommonCheck(TOperator op,
3432 TIntermTyped *left,
3433 TIntermTyped *right,
3434 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003435{
Olli Etuaho244be012016-08-18 15:26:02 +03003436 if (left->getType().getStruct() || right->getType().getStruct())
3437 {
3438 switch (op)
3439 {
3440 case EOpIndexDirectStruct:
3441 ASSERT(left->getType().getStruct());
3442 break;
3443 case EOpEqual:
3444 case EOpNotEqual:
3445 case EOpAssign:
3446 case EOpInitialize:
3447 if (left->getType() != right->getType())
3448 {
3449 return false;
3450 }
3451 break;
3452 default:
3453 error(loc, "Invalid operation for structs", GetOperatorString(op));
3454 return false;
3455 }
3456 }
3457
Olli Etuahod6b14282015-03-17 14:31:35 +02003458 if (left->isArray() || right->isArray())
3459 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003460 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003461 {
3462 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3463 return false;
3464 }
3465
3466 if (left->isArray() != right->isArray())
3467 {
3468 error(loc, "array / non-array mismatch", GetOperatorString(op));
3469 return false;
3470 }
3471
3472 switch (op)
3473 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003474 case EOpEqual:
3475 case EOpNotEqual:
3476 case EOpAssign:
3477 case EOpInitialize:
3478 break;
3479 default:
3480 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3481 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02003482 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03003483 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02003484 if (left->getArraySize() != right->getArraySize())
3485 {
3486 error(loc, "array size mismatch", GetOperatorString(op));
3487 return false;
3488 }
Olli Etuahod6b14282015-03-17 14:31:35 +02003489 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003490
3491 // Check ops which require integer / ivec parameters
3492 bool isBitShift = false;
3493 switch (op)
3494 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003495 case EOpBitShiftLeft:
3496 case EOpBitShiftRight:
3497 case EOpBitShiftLeftAssign:
3498 case EOpBitShiftRightAssign:
3499 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3500 // check that the basic type is an integer type.
3501 isBitShift = true;
3502 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3503 {
3504 return false;
3505 }
3506 break;
3507 case EOpBitwiseAnd:
3508 case EOpBitwiseXor:
3509 case EOpBitwiseOr:
3510 case EOpBitwiseAndAssign:
3511 case EOpBitwiseXorAssign:
3512 case EOpBitwiseOrAssign:
3513 // It is enough to check the type of only one operand, since later it
3514 // is checked that the operand types match.
3515 if (!IsInteger(left->getBasicType()))
3516 {
3517 return false;
3518 }
3519 break;
3520 default:
3521 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003522 }
3523
3524 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3525 // So the basic type should usually match.
3526 if (!isBitShift && left->getBasicType() != right->getBasicType())
3527 {
3528 return false;
3529 }
3530
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003531 // Check that:
3532 // 1. Type sizes match exactly on ops that require that.
3533 // 2. Restrictions for structs that contain arrays or samplers are respected.
3534 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
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 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003567 break;
3568 case EOpAdd:
3569 case EOpSub:
3570 case EOpDiv:
3571 case EOpIMod:
3572 case EOpBitShiftLeft:
3573 case EOpBitShiftRight:
3574 case EOpBitwiseAnd:
3575 case EOpBitwiseXor:
3576 case EOpBitwiseOr:
3577 case EOpAddAssign:
3578 case EOpSubAssign:
3579 case EOpDivAssign:
3580 case EOpIModAssign:
3581 case EOpBitShiftLeftAssign:
3582 case EOpBitShiftRightAssign:
3583 case EOpBitwiseAndAssign:
3584 case EOpBitwiseXorAssign:
3585 case EOpBitwiseOrAssign:
3586 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
3587 {
3588 return false;
3589 }
3590
3591 // Are the sizes compatible?
3592 if (left->getNominalSize() != right->getNominalSize() ||
3593 left->getSecondarySize() != right->getSecondarySize())
3594 {
3595 // If the nominal sizes of operands do not match:
3596 // One of them must be a scalar.
3597 if (!left->isScalar() && !right->isScalar())
3598 return false;
3599
3600 // In the case of compound assignment other than multiply-assign,
3601 // the right side needs to be a scalar. Otherwise a vector/matrix
3602 // would be assigned to a scalar. A scalar can't be shifted by a
3603 // vector either.
3604 if (!right->isScalar() &&
3605 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
3606 return false;
3607 }
3608 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003609 default:
3610 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003611 }
3612
Olli Etuahod6b14282015-03-17 14:31:35 +02003613 return true;
3614}
3615
Olli Etuaho1dded802016-08-18 18:13:13 +03003616bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
3617 const TType &left,
3618 const TType &right)
3619{
3620 switch (op)
3621 {
3622 case EOpMul:
3623 case EOpMulAssign:
3624 return left.getNominalSize() == right.getNominalSize() &&
3625 left.getSecondarySize() == right.getSecondarySize();
3626 case EOpVectorTimesScalar:
3627 return true;
3628 case EOpVectorTimesScalarAssign:
3629 ASSERT(!left.isMatrix() && !right.isMatrix());
3630 return left.isVector() && !right.isVector();
3631 case EOpVectorTimesMatrix:
3632 return left.getNominalSize() == right.getRows();
3633 case EOpVectorTimesMatrixAssign:
3634 ASSERT(!left.isMatrix() && right.isMatrix());
3635 return left.isVector() && left.getNominalSize() == right.getRows() &&
3636 left.getNominalSize() == right.getCols();
3637 case EOpMatrixTimesVector:
3638 return left.getCols() == right.getNominalSize();
3639 case EOpMatrixTimesScalar:
3640 return true;
3641 case EOpMatrixTimesScalarAssign:
3642 ASSERT(left.isMatrix() && !right.isMatrix());
3643 return !right.isVector();
3644 case EOpMatrixTimesMatrix:
3645 return left.getCols() == right.getRows();
3646 case EOpMatrixTimesMatrixAssign:
3647 ASSERT(left.isMatrix() && right.isMatrix());
3648 // We need to check two things:
3649 // 1. The matrix multiplication step is valid.
3650 // 2. The result will have the same number of columns as the lvalue.
3651 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
3652
3653 default:
3654 UNREACHABLE();
3655 return false;
3656 }
3657}
3658
Jamie Madillb98c3a82015-07-23 14:26:04 -04003659TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
3660 TIntermTyped *left,
3661 TIntermTyped *right,
3662 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02003663{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003664 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003665 return nullptr;
3666
Olli Etuahofc1806e2015-03-17 13:03:11 +02003667 switch (op)
3668 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003669 case EOpEqual:
3670 case EOpNotEqual:
3671 break;
3672 case EOpLessThan:
3673 case EOpGreaterThan:
3674 case EOpLessThanEqual:
3675 case EOpGreaterThanEqual:
Olli Etuaho244be012016-08-18 15:26:02 +03003676 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3677 !right->getType().getStruct());
3678 if (left->isMatrix() || left->isVector())
Jamie Madillb98c3a82015-07-23 14:26:04 -04003679 {
3680 return nullptr;
3681 }
3682 break;
3683 case EOpLogicalOr:
3684 case EOpLogicalXor:
3685 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03003686 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3687 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003688 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isVector())
3689 {
3690 return nullptr;
3691 }
3692 break;
3693 case EOpAdd:
3694 case EOpSub:
3695 case EOpDiv:
3696 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03003697 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3698 !right->getType().getStruct());
3699 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04003700 {
3701 return nullptr;
3702 }
3703 break;
3704 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03003705 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3706 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003707 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03003708 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04003709 {
3710 return nullptr;
3711 }
3712 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003713 default:
3714 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02003715 }
3716
Olli Etuaho1dded802016-08-18 18:13:13 +03003717 if (op == EOpMul)
3718 {
3719 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
3720 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
3721 {
3722 return nullptr;
3723 }
3724 }
3725
Olli Etuaho3fdec912016-08-18 15:08:06 +03003726 TIntermBinary *node = new TIntermBinary(op, left, right);
3727 node->setLine(loc);
3728
Olli Etuaho3fdec912016-08-18 15:08:06 +03003729 // See if we can fold constants.
3730 TIntermTyped *foldedNode = node->fold(&mDiagnostics);
3731 if (foldedNode)
3732 return foldedNode;
3733
3734 return node;
Olli Etuahofc1806e2015-03-17 13:03:11 +02003735}
3736
Jamie Madillb98c3a82015-07-23 14:26:04 -04003737TIntermTyped *TParseContext::addBinaryMath(TOperator op,
3738 TIntermTyped *left,
3739 TIntermTyped *right,
3740 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003741{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003742 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003743 if (node == 0)
3744 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003745 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3746 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003747 return left;
3748 }
3749 return node;
3750}
3751
Jamie Madillb98c3a82015-07-23 14:26:04 -04003752TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
3753 TIntermTyped *left,
3754 TIntermTyped *right,
3755 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003756{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003757 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003758 if (node == 0)
3759 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003760 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3761 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003762 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02003763 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003764 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
3765 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003766 }
3767 return node;
3768}
3769
Jamie Madillb98c3a82015-07-23 14:26:04 -04003770TIntermTyped *TParseContext::createAssign(TOperator op,
3771 TIntermTyped *left,
3772 TIntermTyped *right,
3773 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003774{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003775 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003776 {
Olli Etuaho1dded802016-08-18 18:13:13 +03003777 if (op == EOpMulAssign)
3778 {
3779 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
3780 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
3781 {
3782 return nullptr;
3783 }
3784 }
Olli Etuaho3fdec912016-08-18 15:08:06 +03003785 TIntermBinary *node = new TIntermBinary(op, left, right);
3786 node->setLine(loc);
3787
Olli Etuaho3fdec912016-08-18 15:08:06 +03003788 return node;
Olli Etuahod6b14282015-03-17 14:31:35 +02003789 }
3790 return nullptr;
3791}
3792
Jamie Madillb98c3a82015-07-23 14:26:04 -04003793TIntermTyped *TParseContext::addAssign(TOperator op,
3794 TIntermTyped *left,
3795 TIntermTyped *right,
3796 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003797{
3798 TIntermTyped *node = createAssign(op, left, right, loc);
3799 if (node == nullptr)
3800 {
3801 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02003802 return left;
3803 }
3804 return node;
3805}
3806
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02003807TIntermTyped *TParseContext::addComma(TIntermTyped *left,
3808 TIntermTyped *right,
3809 const TSourceLoc &loc)
3810{
Corentin Wallez0d959252016-07-12 17:26:32 -04003811 // WebGL2 section 5.26, the following results in an error:
3812 // "Sequence operator applied to void, arrays, or structs containing arrays"
3813 if (mShaderSpec == SH_WEBGL2_SPEC && (left->isArray() || left->getBasicType() == EbtVoid ||
3814 left->getType().isStructureContainingArrays() ||
3815 right->isArray() || right->getBasicType() == EbtVoid ||
3816 right->getType().isStructureContainingArrays()))
3817 {
3818 error(loc,
3819 "sequence operator is not allowed for void, arrays, or structs containing arrays",
3820 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04003821 }
3822
Olli Etuaho15200042015-11-04 16:56:31 +02003823 return intermediate.addComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02003824}
3825
Olli Etuaho49300862015-02-20 14:54:49 +02003826TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
3827{
3828 switch (op)
3829 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003830 case EOpContinue:
3831 if (mLoopNestingLevel <= 0)
3832 {
3833 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003834 }
3835 break;
3836 case EOpBreak:
3837 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
3838 {
3839 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003840 }
3841 break;
3842 case EOpReturn:
3843 if (mCurrentFunctionType->getBasicType() != EbtVoid)
3844 {
3845 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003846 }
3847 break;
3848 default:
3849 // No checks for discard
3850 break;
Olli Etuaho49300862015-02-20 14:54:49 +02003851 }
3852 return intermediate.addBranch(op, loc);
3853}
3854
Jamie Madillb98c3a82015-07-23 14:26:04 -04003855TIntermBranch *TParseContext::addBranch(TOperator op,
3856 TIntermTyped *returnValue,
3857 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02003858{
3859 ASSERT(op == EOpReturn);
3860 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003861 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02003862 {
3863 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02003864 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003865 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02003866 {
3867 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02003868 }
3869 return intermediate.addBranch(op, returnValue, loc);
3870}
3871
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003872void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
3873{
3874 ASSERT(!functionCall->isUserDefined());
3875 const TString &name = functionCall->getName();
3876 TIntermNode *offset = nullptr;
3877 TIntermSequence *arguments = functionCall->getSequence();
3878 if (name.compare(0, 16, "texelFetchOffset") == 0 ||
3879 name.compare(0, 16, "textureLodOffset") == 0 ||
3880 name.compare(0, 20, "textureProjLodOffset") == 0 ||
3881 name.compare(0, 17, "textureGradOffset") == 0 ||
3882 name.compare(0, 21, "textureProjGradOffset") == 0)
3883 {
3884 offset = arguments->back();
3885 }
3886 else if (name.compare(0, 13, "textureOffset") == 0 ||
3887 name.compare(0, 17, "textureProjOffset") == 0)
3888 {
3889 // A bias parameter might follow the offset parameter.
3890 ASSERT(arguments->size() >= 3);
3891 offset = (*arguments)[2];
3892 }
3893 if (offset != nullptr)
3894 {
3895 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
3896 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
3897 {
3898 TString unmangledName = TFunction::unmangleName(name);
3899 error(functionCall->getLine(), "Texture offset must be a constant expression",
3900 unmangledName.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003901 }
3902 else
3903 {
3904 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
3905 size_t size = offsetConstantUnion->getType().getObjectSize();
3906 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
3907 for (size_t i = 0u; i < size; ++i)
3908 {
3909 int offsetValue = values[i].getIConst();
3910 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
3911 {
3912 std::stringstream tokenStream;
3913 tokenStream << offsetValue;
3914 std::string token = tokenStream.str();
3915 error(offset->getLine(), "Texture offset value out of valid range",
3916 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003917 }
3918 }
3919 }
3920 }
3921}
3922
Jamie Madillb98c3a82015-07-23 14:26:04 -04003923TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
3924 TIntermNode *paramNode,
3925 TIntermNode *thisNode,
3926 const TSourceLoc &loc,
3927 bool *fatalError)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003928{
Jamie Madillb98c3a82015-07-23 14:26:04 -04003929 *fatalError = false;
3930 TOperator op = fnCall->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003931 TIntermTyped *callNode = nullptr;
3932
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003933 if (thisNode != nullptr)
3934 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003935 TConstantUnion *unionArray = new TConstantUnion[1];
Jamie Madillb98c3a82015-07-23 14:26:04 -04003936 int arraySize = 0;
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003937 TIntermTyped *typedThis = thisNode->getAsTyped();
3938 if (fnCall->getName() != "length")
3939 {
3940 error(loc, "invalid method", fnCall->getName().c_str());
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003941 }
3942 else if (paramNode != nullptr)
3943 {
3944 error(loc, "method takes no parameters", "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003945 }
3946 else if (typedThis == nullptr || !typedThis->isArray())
3947 {
3948 error(loc, "length can only be called on arrays", "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003949 }
3950 else
3951 {
Olli Etuaho96e67382015-04-23 14:27:02 +03003952 arraySize = typedThis->getArraySize();
Olli Etuaho39282e12015-04-23 15:41:48 +03003953 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003954 {
Olli Etuaho39282e12015-04-23 15:41:48 +03003955 // This code path can be hit with expressions like these:
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003956 // (a = b).length()
Olli Etuaho39282e12015-04-23 15:41:48 +03003957 // (func()).length()
3958 // (int[3](0, 1, 2)).length()
Jamie Madillb98c3a82015-07-23 14:26:04 -04003959 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
3960 // expression.
3961 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
3962 // spec section 5.9 which allows "An array, vector or matrix expression with the
3963 // length method applied".
3964 error(loc, "length can only be called on array names, not on array expressions",
3965 "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003966 }
3967 }
Olli Etuaho96e67382015-04-23 14:27:02 +03003968 unionArray->setIConst(arraySize);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003969 callNode =
3970 intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003971 }
3972 else if (op != EOpNull)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003973 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003974 // Then this should be a constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +03003975 callNode = addConstructor(paramNode, op, fnCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003976 }
3977 else
3978 {
3979 //
3980 // Not a constructor. Find it in the symbol table.
3981 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303982 const TFunction *fnCandidate;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003983 bool builtIn;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003984 fnCandidate = findFunction(loc, fnCall, mShaderVersion, &builtIn);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003985 if (fnCandidate)
3986 {
3987 //
3988 // A declared function.
3989 //
Olli Etuaho383b7912016-08-05 11:22:59 +03003990 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003991 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003992 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003993 }
3994 op = fnCandidate->getBuiltInOp();
3995 if (builtIn && op != EOpNull)
3996 {
3997 //
3998 // A function call mapped to a built-in operation.
3999 //
4000 if (fnCandidate->getParamCount() == 1)
4001 {
4002 //
4003 // Treat it like a built-in unary operator.
4004 //
Olli Etuaho15c2ac32015-11-09 15:51:43 +02004005 TIntermAggregate *paramAgg = paramNode->getAsAggregate();
4006 paramNode = paramAgg->getSequence()->front();
Jamie Madillb98c3a82015-07-23 14:26:04 -04004007 callNode = createUnaryMath(op, paramNode->getAsTyped(), loc,
4008 &fnCandidate->getReturnType());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004009 if (callNode == nullptr)
4010 {
4011 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004012 extraInfoStream
4013 << "built in unary operator function. Type: "
4014 << static_cast<TIntermTyped *>(paramNode)->getCompleteString();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004015 std::string extraInfo = extraInfoStream.str();
Jamie Madillb98c3a82015-07-23 14:26:04 -04004016 error(paramNode->getLine(), " wrong operand type", "Internal Error",
4017 extraInfo.c_str());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004018 *fatalError = true;
4019 return nullptr;
4020 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004021 }
4022 else
4023 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004024 TIntermAggregate *aggregate =
4025 intermediate.setAggregateOperator(paramNode, op, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004026 aggregate->setType(fnCandidate->getReturnType());
4027 aggregate->setPrecisionFromChildren();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02004028 if (aggregate->areChildrenConstQualified())
4029 {
4030 aggregate->getTypePointer()->setQualifier(EvqConst);
4031 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004032
4033 // Some built-in functions have out parameters too.
4034 functionCallLValueErrorCheck(fnCandidate, aggregate);
Arun Patole274f0702015-05-05 13:33:30 +05304035
Olli Etuaho7c3848e2015-11-04 13:19:17 +02004036 // See if we can constant fold a built-in. Note that this may be possible even
4037 // if it is not const-qualified.
Olli Etuahob43846e2015-06-02 18:18:57 +03004038 TIntermTyped *foldedNode = intermediate.foldAggregateBuiltIn(aggregate);
Arun Patole274f0702015-05-05 13:33:30 +05304039 if (foldedNode)
4040 {
Arun Patole274f0702015-05-05 13:33:30 +05304041 callNode = foldedNode;
4042 }
Olli Etuahob43846e2015-06-02 18:18:57 +03004043 else
4044 {
4045 callNode = aggregate;
4046 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004047 }
4048 }
4049 else
4050 {
4051 // This is a real function call
Jamie Madillb98c3a82015-07-23 14:26:04 -04004052 TIntermAggregate *aggregate =
4053 intermediate.setAggregateOperator(paramNode, EOpFunctionCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004054 aggregate->setType(fnCandidate->getReturnType());
4055
Jamie Madillb98c3a82015-07-23 14:26:04 -04004056 // this is how we know whether the given function is a builtIn function or a user
4057 // defined function
4058 // if builtIn == false, it's a userDefined -> could be an overloaded
4059 // builtIn function also
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004060 // if builtIn == true, it's definitely a builtIn function with EOpNull
4061 if (!builtIn)
4062 aggregate->setUserDefined();
4063 aggregate->setName(fnCandidate->getMangledName());
Corentin Wallez71d147f2015-02-11 11:15:24 -08004064 aggregate->setFunctionId(fnCandidate->getUniqueId());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004065
4066 // This needs to happen after the name is set
4067 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004068 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004069 aggregate->setBuiltInFunctionPrecision();
4070
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004071 checkTextureOffsetConst(aggregate);
4072 }
4073
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004074 callNode = aggregate;
4075
4076 functionCallLValueErrorCheck(fnCandidate, aggregate);
4077 }
4078 }
4079 else
4080 {
4081 // error message was put out by findFunction()
4082 // Put on a dummy node for error recovery
Jamie Madill6ba6ead2015-05-04 14:21:21 -04004083 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004084 unionArray->setFConst(0.0f);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004085 callNode = intermediate.addConstantUnion(unionArray,
4086 TType(EbtFloat, EbpUndefined, EvqConst), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004087 }
4088 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004089 return callNode;
4090}
4091
Jamie Madillb98c3a82015-07-23 14:26:04 -04004092TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
4093 TIntermTyped *trueBlock,
4094 TIntermTyped *falseBlock,
Olli Etuaho52901742015-04-15 13:42:45 +03004095 const TSourceLoc &loc)
4096{
Olli Etuaho856c4972016-08-08 11:38:39 +03004097 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03004098
4099 if (trueBlock->getType() != falseBlock->getType())
4100 {
4101 binaryOpError(loc, ":", trueBlock->getCompleteString(), falseBlock->getCompleteString());
Olli Etuaho52901742015-04-15 13:42:45 +03004102 return falseBlock;
4103 }
Olli Etuahoa2d53032015-04-15 14:14:44 +03004104 // ESSL1 sections 5.2 and 5.7:
4105 // ESSL3 section 5.7:
4106 // Ternary operator is not among the operators allowed for structures/arrays.
4107 if (trueBlock->isArray() || trueBlock->getBasicType() == EbtStruct)
4108 {
4109 error(loc, "ternary operator is not allowed for structures or arrays", ":");
Olli Etuahoa2d53032015-04-15 14:14:44 +03004110 return falseBlock;
4111 }
Corentin Wallez0d959252016-07-12 17:26:32 -04004112 // WebGL2 section 5.26, the following results in an error:
4113 // "Ternary operator applied to void, arrays, or structs containing arrays"
4114 if (mShaderSpec == SH_WEBGL2_SPEC && trueBlock->getBasicType() == EbtVoid)
4115 {
4116 error(loc, "ternary operator is not allowed for void", ":");
Corentin Wallez0d959252016-07-12 17:26:32 -04004117 return falseBlock;
4118 }
4119
Olli Etuaho52901742015-04-15 13:42:45 +03004120 return intermediate.addSelection(cond, trueBlock, falseBlock, loc);
4121}
Olli Etuaho49300862015-02-20 14:54:49 +02004122
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004123//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004124// Parse an array of strings using yyparse.
4125//
4126// Returns 0 for success.
4127//
Jamie Madillb98c3a82015-07-23 14:26:04 -04004128int PaParseStrings(size_t count,
4129 const char *const string[],
4130 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05304131 TParseContext *context)
4132{
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004133 if ((count == 0) || (string == NULL))
4134 return 1;
4135
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004136 if (glslang_initialize(context))
4137 return 1;
4138
alokp@chromium.org408c45e2012-04-05 15:54:43 +00004139 int error = glslang_scan(count, string, length, context);
4140 if (!error)
4141 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004142
alokp@chromium.org73bc2982012-06-19 18:48:05 +00004143 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00004144
alokp@chromium.org6b495712012-06-29 00:06:58 +00004145 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004146}