blob: e67f0d003bee61e881557e357b725f8fbd59ddf4 [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;
Martin Radev70866b82016-07-22 15:27:42 +0300216
217 if (precision != EbpUndefined && !SupportsPrecision(type))
218 {
219 error(line, "illegal type for precision qualifier", getBasicString(type));
220 }
221
Olli Etuaho183d7e22015-11-20 15:59:09 +0200222 if (precision == EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530223 {
Olli Etuaho183d7e22015-11-20 15:59:09 +0200224 switch (type)
225 {
226 case EbtFloat:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400227 error(line, "No precision specified for (float)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300228 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200229 case EbtInt:
230 case EbtUInt:
231 UNREACHABLE(); // there's always a predeclared qualifier
Jamie Madillb98c3a82015-07-23 14:26:04 -0400232 error(line, "No precision specified (int)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300233 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200234 default:
235 if (IsSampler(type))
236 {
237 error(line, "No precision specified (sampler)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300238 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200239 }
240 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000241 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000242}
243
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244// Both test and if necessary, spit out an error, to see if the node is really
245// an l-value that can be operated on this way.
Olli Etuaho856c4972016-08-08 11:38:39 +0300246bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400248 TIntermSymbol *symNode = node->getAsSymbolNode();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530249 TIntermBinary *binaryNode = node->getAsBinaryNode();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250
Arun Patole7e7e68d2015-05-22 12:02:25 +0530251 if (binaryNode)
252 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400253 switch (binaryNode->getOp())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530254 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400255 case EOpIndexDirect:
256 case EOpIndexIndirect:
257 case EOpIndexDirectStruct:
258 case EOpIndexDirectInterfaceBlock:
Olli Etuaho856c4972016-08-08 11:38:39 +0300259 return checkCanBeLValue(line, op, binaryNode->getLeft());
Jamie Madillb98c3a82015-07-23 14:26:04 -0400260 case EOpVectorSwizzle:
Olli Etuaho8a176262016-08-16 14:23:01 +0300261 {
262 bool ok = checkCanBeLValue(line, op, binaryNode->getLeft());
263 if (ok)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530264 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300265 int offsetCount[4] = {0, 0, 0, 0};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000266
Olli Etuaho8a176262016-08-16 14:23:01 +0300267 TIntermAggregate *swizzleOffsets = binaryNode->getRight()->getAsAggregate();
Jamie Madillb98c3a82015-07-23 14:26:04 -0400268
Olli Etuaho8a176262016-08-16 14:23:01 +0300269 for (const auto &offset : *swizzleOffsets->getSequence())
Jamie Madillb98c3a82015-07-23 14:26:04 -0400270 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300271 int value = offset->getAsTyped()->getAsConstantUnion()->getIConst(0);
272 offsetCount[value]++;
273 if (offsetCount[value] > 1)
Jamie Madillb98c3a82015-07-23 14:26:04 -0400274 {
275 error(line, " l-value of swizzle cannot have duplicate components", op);
Olli Etuaho8a176262016-08-16 14:23:01 +0300276 return false;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400277 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000278 }
279 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000280
Olli Etuaho8a176262016-08-16 14:23:01 +0300281 return ok;
282 }
Jamie Madillb98c3a82015-07-23 14:26:04 -0400283 default:
284 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000285 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000286 error(line, " l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000287
Olli Etuaho8a176262016-08-16 14:23:01 +0300288 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000289 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000290
Arun Patole7e7e68d2015-05-22 12:02:25 +0530291 const char *symbol = 0;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000292 if (symNode != 0)
293 symbol = symNode->getSymbol().c_str();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294
Arun Patole7e7e68d2015-05-22 12:02:25 +0530295 const char *message = 0;
296 switch (node->getQualifier())
297 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400298 case EvqConst:
299 message = "can't modify a const";
300 break;
301 case EvqConstReadOnly:
302 message = "can't modify a const";
303 break;
304 case EvqAttribute:
305 message = "can't modify an attribute";
306 break;
307 case EvqFragmentIn:
308 message = "can't modify an input";
309 break;
310 case EvqVertexIn:
311 message = "can't modify an input";
312 break;
313 case EvqUniform:
314 message = "can't modify a uniform";
315 break;
316 case EvqVaryingIn:
317 message = "can't modify a varying";
318 break;
319 case EvqFragCoord:
320 message = "can't modify gl_FragCoord";
321 break;
322 case EvqFrontFacing:
323 message = "can't modify gl_FrontFacing";
324 break;
325 case EvqPointCoord:
326 message = "can't modify gl_PointCoord";
327 break;
Martin Radevb0883602016-08-04 17:48:58 +0300328 case EvqNumWorkGroups:
329 message = "can't modify gl_NumWorkGroups";
330 break;
331 case EvqWorkGroupSize:
332 message = "can't modify gl_WorkGroupSize";
333 break;
334 case EvqWorkGroupID:
335 message = "can't modify gl_WorkGroupID";
336 break;
337 case EvqLocalInvocationID:
338 message = "can't modify gl_LocalInvocationID";
339 break;
340 case EvqGlobalInvocationID:
341 message = "can't modify gl_GlobalInvocationID";
342 break;
343 case EvqLocalInvocationIndex:
344 message = "can't modify gl_LocalInvocationIndex";
345 break;
Martin Radev802abe02016-08-04 17:48:32 +0300346 case EvqComputeIn:
347 message = "can't modify work group size variable";
348 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400349 default:
350 //
351 // Type that can't be written to?
352 //
353 if (node->getBasicType() == EbtVoid)
354 {
355 message = "can't modify void";
356 }
357 if (IsSampler(node->getBasicType()))
358 {
359 message = "can't modify a sampler";
360 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000361 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000362
Arun Patole7e7e68d2015-05-22 12:02:25 +0530363 if (message == 0 && binaryNode == 0 && symNode == 0)
364 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000365 error(line, " l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000366
Olli Etuaho8a176262016-08-16 14:23:01 +0300367 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000368 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000369
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000370 //
371 // Everything else is okay, no error.
372 //
373 if (message == 0)
Olli Etuaho8a176262016-08-16 14:23:01 +0300374 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000375
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000376 //
377 // If we get here, we have an error and a message.
378 //
Arun Patole7e7e68d2015-05-22 12:02:25 +0530379 if (symNode)
380 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000381 std::stringstream extraInfoStream;
382 extraInfoStream << "\"" << symbol << "\" (" << message << ")";
383 std::string extraInfo = extraInfoStream.str();
384 error(line, " l-value required", op, extraInfo.c_str());
385 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530386 else
387 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000388 std::stringstream extraInfoStream;
389 extraInfoStream << "(" << message << ")";
390 std::string extraInfo = extraInfoStream.str();
391 error(line, " l-value required", op, extraInfo.c_str());
392 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393
Olli Etuaho8a176262016-08-16 14:23:01 +0300394 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000395}
396
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000397// Both test, and if necessary spit out an error, to see if the node is really
398// a constant.
Olli Etuaho856c4972016-08-08 11:38:39 +0300399void TParseContext::checkIsConst(TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000400{
Olli Etuaho383b7912016-08-05 11:22:59 +0300401 if (node->getQualifier() != EvqConst)
402 {
403 error(node->getLine(), "constant expression required", "");
404 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000405}
406
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000407// Both test, and if necessary spit out an error, to see if the node is really
408// an integer.
Olli Etuaho856c4972016-08-08 11:38:39 +0300409void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000410{
Olli Etuaho383b7912016-08-05 11:22:59 +0300411 if (!node->isScalarInt())
412 {
413 error(node->getLine(), "integer expression required", token);
414 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000415}
416
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000417// Both test, and if necessary spit out an error, to see if we are currently
418// globally scoped.
Qiankun Miaof69682b2016-08-16 14:50:42 +0800419bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000420{
Olli Etuaho856c4972016-08-08 11:38:39 +0300421 if (!symbolTable.atGlobalLevel())
Olli Etuaho383b7912016-08-05 11:22:59 +0300422 {
423 error(line, "only allowed at global scope", token);
Qiankun Miaof69682b2016-08-16 14:50:42 +0800424 return false;
Olli Etuaho383b7912016-08-05 11:22:59 +0300425 }
Qiankun Miaof69682b2016-08-16 14:50:42 +0800426 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000427}
428
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429// For now, keep it simple: if it starts "gl_", it's reserved, independent
430// of scope. Except, if the symbol table is at the built-in push-level,
431// which is when we are parsing built-ins.
alokp@chromium.org613ef312010-07-21 18:54:22 +0000432// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
433// webgl shader.
Olli Etuaho856c4972016-08-08 11:38:39 +0300434bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000435{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530436 static const char *reservedErrMsg = "reserved built-in name";
437 if (!symbolTable.atBuiltInLevel())
438 {
439 if (identifier.compare(0, 3, "gl_") == 0)
440 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000441 error(line, reservedErrMsg, "gl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300442 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000443 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530444 if (IsWebGLBasedSpec(mShaderSpec))
445 {
446 if (identifier.compare(0, 6, "webgl_") == 0)
447 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000448 error(line, reservedErrMsg, "webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300449 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000450 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530451 if (identifier.compare(0, 7, "_webgl_") == 0)
452 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000453 error(line, reservedErrMsg, "_webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300454 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000455 }
456 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530457 if (identifier.find("__") != TString::npos)
458 {
459 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400460 "identifiers containing two consecutive underscores (__) are reserved as "
461 "possible future keywords",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530462 identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300463 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000464 }
465 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000466
Olli Etuaho8a176262016-08-16 14:23:01 +0300467 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000468}
469
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000470// Make sure there is enough data provided to the constructor to build
471// something of the type of the constructor. Also returns the type of
472// the constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +0300473bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
474 TIntermNode *argumentsNode,
475 const TFunction &function,
476 TOperator op,
477 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000478{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000479 bool constructingMatrix = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400480 switch (op)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530481 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400482 case EOpConstructMat2:
483 case EOpConstructMat2x3:
484 case EOpConstructMat2x4:
485 case EOpConstructMat3x2:
486 case EOpConstructMat3:
487 case EOpConstructMat3x4:
488 case EOpConstructMat4x2:
489 case EOpConstructMat4x3:
490 case EOpConstructMat4:
491 constructingMatrix = true;
492 break;
493 default:
494 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000495 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000496
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000497 //
498 // Note: It's okay to have too many components available, but not okay to have unused
499 // arguments. 'full' will go to true when enough args have been seen. If we loop
500 // again, there is an extra argument, so 'overfull' will become true.
501 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000502
Jamie Madillb98c3a82015-07-23 14:26:04 -0400503 size_t size = 0;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400504 bool full = false;
505 bool overFull = false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000506 bool matrixInMatrix = false;
507 bool arrayArg = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530508 for (size_t i = 0; i < function.getParamCount(); ++i)
509 {
Dmitry Skibaefa3d8e2015-06-22 14:52:10 -0700510 const TConstParameter &param = function.getParam(i);
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000511 size += param.type->getObjectSize();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530512
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000513 if (constructingMatrix && param.type->isMatrix())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000514 matrixInMatrix = true;
515 if (full)
516 overFull = true;
Olli Etuaho856c4972016-08-08 11:38:39 +0300517 if (op != EOpConstructStruct && !type.isArray() && size >= type.getObjectSize())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000518 full = true;
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000519 if (param.type->isArray())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000520 arrayArg = true;
521 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530522
Olli Etuaho856c4972016-08-08 11:38:39 +0300523 if (type.isArray())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300524 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300525 // The size of an unsized constructor should already have been determined.
526 ASSERT(!type.isUnsizedArray());
527 if (static_cast<size_t>(type.getArraySize()) != function.getParamCount())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300528 {
529 error(line, "array constructor needs one argument per array element", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300530 return false;
Olli Etuaho376f1b52015-04-13 13:23:41 +0300531 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000532 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000533
Arun Patole7e7e68d2015-05-22 12:02:25 +0530534 if (arrayArg && op != EOpConstructStruct)
535 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000536 error(line, "constructing from a non-dereferenced array", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300537 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000538 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000539
Olli Etuaho856c4972016-08-08 11:38:39 +0300540 if (matrixInMatrix && !type.isArray())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530541 {
542 if (function.getParamCount() != 1)
543 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400544 error(line, "constructing matrix from matrix can only take one argument",
545 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300546 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000547 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000548 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000549
Arun Patole7e7e68d2015-05-22 12:02:25 +0530550 if (overFull)
551 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000552 error(line, "too many arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300553 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000554 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530555
Olli Etuaho856c4972016-08-08 11:38:39 +0300556 if (op == EOpConstructStruct && !type.isArray() &&
557 type.getStruct()->fields().size() != function.getParamCount())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530558 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400559 error(line,
560 "Number of constructor parameters does not match the number of structure fields",
561 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300562 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000563 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000564
Olli Etuaho856c4972016-08-08 11:38:39 +0300565 if (!type.isMatrix() || !matrixInMatrix)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530566 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300567 if ((op != EOpConstructStruct && size != 1 && size < type.getObjectSize()) ||
568 (op == EOpConstructStruct && size < type.getObjectSize()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530569 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000570 error(line, "not enough data provided for construction", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300571 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000572 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000573 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000574
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200575 if (argumentsNode == nullptr)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530576 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200577 error(line, "constructor does not have any arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300578 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000579 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200580
581 TIntermAggregate *argumentsAgg = argumentsNode->getAsAggregate();
582 for (TIntermNode *&argNode : *argumentsAgg->getSequence())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530583 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200584 TIntermTyped *argTyped = argNode->getAsTyped();
585 ASSERT(argTyped != nullptr);
586 if (op != EOpConstructStruct && IsSampler(argTyped->getBasicType()))
587 {
588 error(line, "cannot convert a sampler", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300589 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200590 }
591 if (argTyped->getBasicType() == EbtVoid)
592 {
593 error(line, "cannot convert a void", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300594 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200595 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000596 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000597
Olli Etuaho856c4972016-08-08 11:38:39 +0300598 if (type.isArray())
599 {
600 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
601 // the array.
602 for (TIntermNode *&argNode : *argumentsAgg->getSequence())
603 {
604 const TType &argType = argNode->getAsTyped()->getType();
605 // It has already been checked that the argument is not an array.
606 ASSERT(!argType.isArray());
607 if (!argType.sameElementType(type))
608 {
609 error(line, "Array constructor argument has an incorrect type", "Error");
Olli Etuaho8a176262016-08-16 14:23:01 +0300610 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300611 }
612 }
613 }
614 else if (op == EOpConstructStruct)
615 {
616 const TFieldList &fields = type.getStruct()->fields();
617 TIntermSequence *args = argumentsAgg->getSequence();
618
619 for (size_t i = 0; i < fields.size(); i++)
620 {
621 if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type())
622 {
623 error(line, "Structure constructor arguments do not match structure fields",
624 "Error");
Olli Etuaho8a176262016-08-16 14:23:01 +0300625 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300626 }
627 }
628 }
629
Olli Etuaho8a176262016-08-16 14:23:01 +0300630 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000631}
632
Jamie Madillb98c3a82015-07-23 14:26:04 -0400633// This function checks to see if a void variable has been declared and raise an error message for
634// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000635//
636// returns true in case of an error
637//
Olli Etuaho856c4972016-08-08 11:38:39 +0300638bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400639 const TString &identifier,
640 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000641{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300642 if (type == EbtVoid)
643 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000644 error(line, "illegal use of type 'void'", identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300645 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300646 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000647
Olli Etuaho8a176262016-08-16 14:23:01 +0300648 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000649}
650
Jamie Madillb98c3a82015-07-23 14:26:04 -0400651// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300652// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300653void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000654{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530655 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
656 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000657 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530658 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000659}
660
Jamie Madillb98c3a82015-07-23 14:26:04 -0400661// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300662// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300663void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000664{
Martin Radev4a9cd802016-09-01 16:51:51 +0300665 if (pType.getBasicType() != EbtBool || pType.isAggregate())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530666 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000667 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530668 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000669}
670
Olli Etuaho856c4972016-08-08 11:38:39 +0300671bool TParseContext::checkIsNotSampler(const TSourceLoc &line,
Martin Radev4a9cd802016-09-01 16:51:51 +0300672 const TTypeSpecifierNonArray &pType,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400673 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000674{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530675 if (pType.type == EbtStruct)
676 {
677 if (containsSampler(*pType.userDef))
678 {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000679 error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
Olli Etuaho8a176262016-08-16 14:23:01 +0300680 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000681 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530682
Olli Etuaho8a176262016-08-16 14:23:01 +0300683 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530684 }
685 else if (IsSampler(pType.type))
686 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000687 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300688 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000689 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000690
Olli Etuaho8a176262016-08-16 14:23:01 +0300691 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000692}
693
Olli Etuaho856c4972016-08-08 11:38:39 +0300694void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
695 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400696{
697 if (pType.layoutQualifier.location != -1)
698 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400699 error(line, "location must only be specified for a single input or output variable",
700 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400701 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400702}
703
Olli Etuaho856c4972016-08-08 11:38:39 +0300704void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
705 const TLayoutQualifier &layoutQualifier)
706{
707 if (layoutQualifier.location != -1)
708 {
709 error(location, "invalid layout qualifier:", "location",
710 "only valid on program inputs and outputs");
711 }
712}
713
714void TParseContext::checkOutParameterIsNotSampler(const TSourceLoc &line,
715 TQualifier qualifier,
716 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000717{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400718 if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct &&
719 IsSampler(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530720 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000721 error(line, "samplers cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000722 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000723}
724
Arun Patole7e7e68d2015-05-22 12:02:25 +0530725bool TParseContext::containsSampler(const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000726{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000727 if (IsSampler(type.getBasicType()))
728 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000729
Arun Patole7e7e68d2015-05-22 12:02:25 +0530730 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock())
731 {
732 const TFieldList &fields = type.getStruct()->fields();
733 for (unsigned int i = 0; i < fields.size(); ++i)
734 {
Jamie Madill98493dd2013-07-08 14:39:03 -0400735 if (containsSampler(*fields[i]->type()))
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000736 return true;
737 }
738 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000739
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000740 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000741}
742
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000743// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300744unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000745{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530746 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000747
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200748 // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
749 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
750 // fold as array size.
751 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000752 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000753 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300754 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000755 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000756
Olli Etuaho856c4972016-08-08 11:38:39 +0300757 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400758
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000759 if (constant->getBasicType() == EbtUInt)
760 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300761 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000762 }
763 else
764 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300765 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000766
Olli Etuaho856c4972016-08-08 11:38:39 +0300767 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000768 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400769 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300770 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000771 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400772
Olli Etuaho856c4972016-08-08 11:38:39 +0300773 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -0400774 }
775
Olli Etuaho856c4972016-08-08 11:38:39 +0300776 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -0400777 {
778 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300779 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400780 }
781
782 // The size of arrays is restricted here to prevent issues further down the
783 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
784 // 4096 registers so this should be reasonable even for aggressively optimizable code.
785 const unsigned int sizeLimit = 65536;
786
Olli Etuaho856c4972016-08-08 11:38:39 +0300787 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -0400788 {
789 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300790 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000791 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300792
793 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000794}
795
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000796// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +0300797bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
798 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000799{
Olli Etuaho8a176262016-08-16 14:23:01 +0300800 if ((elementQualifier.qualifier == EvqAttribute) ||
801 (elementQualifier.qualifier == EvqVertexIn) ||
802 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +0300803 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400804 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300805 TType(elementQualifier).getQualifierString());
806 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000807 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000808
Olli Etuaho8a176262016-08-16 14:23:01 +0300809 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000810}
811
Olli Etuaho8a176262016-08-16 14:23:01 +0300812// See if this element type can be formed into an array.
813bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000814{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000815 //
816 // Can the type be an array?
817 //
Olli Etuaho8a176262016-08-16 14:23:01 +0300818 if (elementType.array)
Jamie Madill06145232015-05-13 13:10:01 -0400819 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300820 error(line, "cannot declare arrays of arrays",
821 TType(elementType).getCompleteString().c_str());
822 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000823 }
Olli Etuahocc36b982015-07-10 14:14:18 +0300824 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
825 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
826 // 4.3.4).
Martin Radev4a9cd802016-09-01 16:51:51 +0300827 if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
Olli Etuaho8a176262016-08-16 14:23:01 +0300828 sh::IsVarying(elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +0300829 {
830 error(line, "cannot declare arrays of structs of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300831 TType(elementType).getCompleteString().c_str());
832 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +0300833 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000834
Olli Etuaho8a176262016-08-16 14:23:01 +0300835 return true;
836}
837
838// Check if this qualified element type can be formed into an array.
839bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
840 const TPublicType &elementType)
841{
842 if (checkIsValidTypeForArray(indexLocation, elementType))
843 {
844 return checkIsValidQualifierForArray(indexLocation, elementType);
845 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000846 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000847}
848
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000849// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +0300850void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
851 const TString &identifier,
852 TPublicType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000853{
Olli Etuaho3739d232015-04-08 12:23:44 +0300854 ASSERT(type != nullptr);
855 if (type->qualifier == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000856 {
857 // Make the qualifier make sense.
Olli Etuaho3739d232015-04-08 12:23:44 +0300858 type->qualifier = EvqTemporary;
859
860 // Generate informative error messages for ESSL1.
861 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400862 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000863 {
Arun Patole7e7e68d2015-05-22 12:02:25 +0530864 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400865 "structures containing arrays may not be declared constant since they cannot be "
866 "initialized",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530867 identifier.c_str());
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000868 }
869 else
870 {
871 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
872 }
Olli Etuaho383b7912016-08-05 11:22:59 +0300873 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000874 }
Olli Etuaho376f1b52015-04-13 13:23:41 +0300875 if (type->isUnsizedArray())
876 {
877 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
Olli Etuaho376f1b52015-04-13 13:23:41 +0300878 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000879}
880
Olli Etuaho2935c582015-04-08 14:32:06 +0300881// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000882// and update the symbol table.
883//
Olli Etuaho2935c582015-04-08 14:32:06 +0300884// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000885//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400886bool TParseContext::declareVariable(const TSourceLoc &line,
887 const TString &identifier,
888 const TType &type,
Olli Etuaho2935c582015-04-08 14:32:06 +0300889 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000890{
Olli Etuaho2935c582015-04-08 14:32:06 +0300891 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000892
Olli Etuaho856c4972016-08-08 11:38:39 +0300893 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000894
Olli Etuaho2935c582015-04-08 14:32:06 +0300895 // gl_LastFragData may be redeclared with a new precision qualifier
896 if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
897 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400898 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
899 symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Olli Etuaho856c4972016-08-08 11:38:39 +0300900 if (static_cast<int>(type.getArraySize()) == maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +0300901 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400902 if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +0300903 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300904 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
Olli Etuaho2935c582015-04-08 14:32:06 +0300905 }
906 }
907 else
908 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400909 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
910 identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +0300911 return false;
912 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000913 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000914
Olli Etuaho8a176262016-08-16 14:23:01 +0300915 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +0300916 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000917
Olli Etuaho2935c582015-04-08 14:32:06 +0300918 (*variable) = new TVariable(&identifier, type);
919 if (!symbolTable.declare(*variable))
920 {
921 error(line, "redefinition", identifier.c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -0400922 *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +0300923 return false;
924 }
925
Olli Etuaho8a176262016-08-16 14:23:01 +0300926 if (!checkIsNonVoid(line, identifier, type.getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +0300927 return false;
928
929 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000930}
931
Martin Radev70866b82016-07-22 15:27:42 +0300932void TParseContext::checkIsParameterQualifierValid(
933 const TSourceLoc &line,
934 const TTypeQualifierBuilder &typeQualifierBuilder,
935 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530936{
Olli Etuaho613b9592016-09-05 12:05:53 +0300937 TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(&mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +0300938
939 if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530940 {
Martin Radev70866b82016-07-22 15:27:42 +0300941 checkOutParameterIsNotSampler(line, typeQualifier.qualifier, *type);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000942 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000943
Martin Radev70866b82016-07-22 15:27:42 +0300944 type->setQualifier(typeQualifier.qualifier);
945
946 if (typeQualifier.precision != EbpUndefined)
947 {
948 type->setPrecision(typeQualifier.precision);
949 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000950}
951
Olli Etuaho856c4972016-08-08 11:38:39 +0300952bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000953{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400954 const TExtensionBehavior &extBehavior = extensionBehavior();
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000955 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
Arun Patole7e7e68d2015-05-22 12:02:25 +0530956 if (iter == extBehavior.end())
957 {
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000958 error(line, "extension", extension.c_str(), "is not supported");
Olli Etuaho8a176262016-08-16 14:23:01 +0300959 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000960 }
zmo@google.comf5450912011-09-09 01:37:19 +0000961 // In GLSL ES, an extension's default behavior is "disable".
Arun Patole7e7e68d2015-05-22 12:02:25 +0530962 if (iter->second == EBhDisable || iter->second == EBhUndefined)
963 {
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000964 error(line, "extension", extension.c_str(), "is disabled");
Olli Etuaho8a176262016-08-16 14:23:01 +0300965 return false;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000966 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530967 if (iter->second == EBhWarn)
968 {
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000969 warning(line, "extension", extension.c_str(), "is being used");
Olli Etuaho8a176262016-08-16 14:23:01 +0300970 return true;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000971 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000972
Olli Etuaho8a176262016-08-16 14:23:01 +0300973 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000974}
975
Jamie Madillb98c3a82015-07-23 14:26:04 -0400976// These checks are common for all declarations starting a declarator list, and declarators that
977// follow an empty declaration.
Olli Etuaho383b7912016-08-05 11:22:59 +0300978void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400979 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -0400980{
Olli Etuahofa33d582015-04-09 14:33:12 +0300981 switch (publicType.qualifier)
982 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400983 case EvqVaryingIn:
984 case EvqVaryingOut:
985 case EvqAttribute:
986 case EvqVertexIn:
987 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +0300988 case EvqComputeIn:
Martin Radev4a9cd802016-09-01 16:51:51 +0300989 if (publicType.getBasicType() == EbtStruct)
Jamie Madillb98c3a82015-07-23 14:26:04 -0400990 {
991 error(identifierLocation, "cannot be used with a structure",
992 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +0300993 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400994 }
Olli Etuahofa33d582015-04-09 14:33:12 +0300995
Jamie Madillb98c3a82015-07-23 14:26:04 -0400996 default:
997 break;
Olli Etuahofa33d582015-04-09 14:33:12 +0300998 }
999
Jamie Madillb98c3a82015-07-23 14:26:04 -04001000 if (publicType.qualifier != EvqUniform &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001001 !checkIsNotSampler(identifierLocation, publicType.typeSpecifierNonArray,
1002 "samplers must be uniform"))
Olli Etuahofa33d582015-04-09 14:33:12 +03001003 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001004 return;
Olli Etuahofa33d582015-04-09 14:33:12 +03001005 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001006
1007 // check for layout qualifier issues
1008 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
1009
1010 if (layoutQualifier.matrixPacking != EmpUnspecified)
1011 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001012 error(identifierLocation, "layout qualifier",
1013 getMatrixPackingString(layoutQualifier.matrixPacking),
Olli Etuahofa33d582015-04-09 14:33:12 +03001014 "only valid for interface blocks");
Olli Etuaho383b7912016-08-05 11:22:59 +03001015 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001016 }
1017
1018 if (layoutQualifier.blockStorage != EbsUnspecified)
1019 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001020 error(identifierLocation, "layout qualifier",
1021 getBlockStorageString(layoutQualifier.blockStorage),
Olli Etuahofa33d582015-04-09 14:33:12 +03001022 "only valid for interface blocks");
Olli Etuaho383b7912016-08-05 11:22:59 +03001023 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001024 }
1025
Olli Etuaho383b7912016-08-05 11:22:59 +03001026 if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut)
Jamie Madilla5efff92013-06-06 11:56:47 -04001027 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001028 checkLocationIsNotSpecified(identifierLocation, publicType.layoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04001029 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001030}
1031
Olli Etuaho856c4972016-08-08 11:38:39 +03001032void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1033 const TString &layoutQualifierName,
1034 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001035{
1036
1037 if (mShaderVersion < versionRequired)
1038 {
1039 error(location, "invalid layout qualifier:", layoutQualifierName.c_str(), "not supported");
Martin Radev802abe02016-08-04 17:48:32 +03001040 }
1041}
1042
Olli Etuaho856c4972016-08-08 11:38:39 +03001043bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1044 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001045{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001046 const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
Martin Radev802abe02016-08-04 17:48:32 +03001047 for (size_t i = 0u; i < localSize.size(); ++i)
1048 {
1049 if (localSize[i] != -1)
1050 {
Martin Radev4c4c8e72016-08-04 12:25:34 +03001051 error(location, "invalid layout qualifier:", getWorkGroupSizeString(i),
Martin Radev802abe02016-08-04 17:48:32 +03001052 "only valid when used with 'in' in a compute shader global layout declaration");
Olli Etuaho8a176262016-08-16 14:23:01 +03001053 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001054 }
1055 }
1056
Olli Etuaho8a176262016-08-16 14:23:01 +03001057 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001058}
1059
Olli Etuaho383b7912016-08-05 11:22:59 +03001060void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
Olli Etuaho856c4972016-08-08 11:38:39 +03001061 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001062{
1063 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1064 {
1065 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1066 if (qual == EvqOut || qual == EvqInOut)
1067 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001068 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho8a176262016-08-16 14:23:01 +03001069 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001070 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001071 error(argument->getLine(),
Jamie Madillb98c3a82015-07-23 14:26:04 -04001072 "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
Olli Etuaho383b7912016-08-05 11:22:59 +03001073 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001074 }
1075 }
1076 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001077}
1078
Martin Radev70866b82016-07-22 15:27:42 +03001079void TParseContext::checkInvariantVariableQualifier(bool invariant,
1080 const TQualifier qualifier,
1081 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001082{
Martin Radev70866b82016-07-22 15:27:42 +03001083 if (!invariant)
1084 return;
1085
1086 if (mShaderVersion < 300)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001087 {
Martin Radev70866b82016-07-22 15:27:42 +03001088 // input variables in the fragment shader can be also qualified as invariant
1089 if (!sh::CanBeInvariantESSL1(qualifier))
1090 {
1091 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1092 }
1093 }
1094 else
1095 {
1096 if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
1097 {
1098 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1099 }
Olli Etuaho37ad4742015-04-27 13:18:50 +03001100 }
1101}
1102
Arun Patole7e7e68d2015-05-22 12:02:25 +05301103bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001104{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001105 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001106 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1107 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001108}
1109
Arun Patole7e7e68d2015-05-22 12:02:25 +05301110bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001111{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001112 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001113}
1114
Jamie Madillb98c3a82015-07-23 14:26:04 -04001115void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1116 const char *extName,
1117 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001118{
1119 pp::SourceLocation srcLoc;
1120 srcLoc.file = loc.first_file;
1121 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001122 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001123}
1124
Jamie Madillb98c3a82015-07-23 14:26:04 -04001125void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1126 const char *name,
1127 const char *value,
1128 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001129{
1130 pp::SourceLocation srcLoc;
1131 srcLoc.file = loc.first_file;
1132 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001133 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001134}
1135
Martin Radev4c4c8e72016-08-04 12:25:34 +03001136sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
Martin Radev802abe02016-08-04 17:48:32 +03001137{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001138 sh::WorkGroupSize result;
Martin Radev802abe02016-08-04 17:48:32 +03001139 for (size_t i = 0u; i < result.size(); ++i)
1140 {
1141 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1142 {
1143 result[i] = 1;
1144 }
1145 else
1146 {
1147 result[i] = mComputeShaderLocalSize[i];
1148 }
1149 }
1150 return result;
1151}
1152
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001153/////////////////////////////////////////////////////////////////////////////////
1154//
1155// Non-Errors.
1156//
1157/////////////////////////////////////////////////////////////////////////////////
1158
Jamie Madill5c097022014-08-20 16:38:32 -04001159const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1160 const TString *name,
1161 const TSymbol *symbol)
1162{
1163 const TVariable *variable = NULL;
1164
1165 if (!symbol)
1166 {
1167 error(location, "undeclared identifier", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001168 }
1169 else if (!symbol->isVariable())
1170 {
1171 error(location, "variable expected", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001172 }
1173 else
1174 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001175 variable = static_cast<const TVariable *>(symbol);
Jamie Madill5c097022014-08-20 16:38:32 -04001176
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001177 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
Olli Etuaho383b7912016-08-05 11:22:59 +03001178 !variable->getExtension().empty())
Jamie Madill5c097022014-08-20 16:38:32 -04001179 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001180 checkCanUseExtension(location, variable->getExtension());
Jamie Madill5c097022014-08-20 16:38:32 -04001181 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001182
1183 // Reject shaders using both gl_FragData and gl_FragColor
1184 TQualifier qualifier = variable->getType().getQualifier();
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001185 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001186 {
1187 mUsesFragData = true;
1188 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001189 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001190 {
1191 mUsesFragColor = true;
1192 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001193 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1194 {
1195 mUsesSecondaryOutputs = true;
1196 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001197
1198 // This validation is not quite correct - it's only an error to write to
1199 // both FragData and FragColor. For simplicity, and because users shouldn't
1200 // be rewarded for reading from undefined varaibles, return an error
1201 // if they are both referenced, rather than assigned.
1202 if (mUsesFragData && mUsesFragColor)
1203 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001204 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1205 if (mUsesSecondaryOutputs)
1206 {
1207 errorMessage =
1208 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1209 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1210 }
1211 error(location, errorMessage, name->c_str());
Jamie Madill14e95b32015-05-07 10:10:41 -04001212 }
Martin Radevb0883602016-08-04 17:48:58 +03001213
1214 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1215 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1216 qualifier == EvqWorkGroupSize)
1217 {
1218 error(location,
1219 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1220 "gl_WorkGroupSize");
1221 }
Jamie Madill5c097022014-08-20 16:38:32 -04001222 }
1223
1224 if (!variable)
1225 {
1226 TType type(EbtFloat, EbpUndefined);
1227 TVariable *fakeVariable = new TVariable(name, type);
1228 symbolTable.declare(fakeVariable);
1229 variable = fakeVariable;
1230 }
1231
1232 return variable;
1233}
1234
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001235TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1236 const TString *name,
1237 const TSymbol *symbol)
1238{
1239 const TVariable *variable = getNamedVariable(location, name, symbol);
1240
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001241 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001242 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001243 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001244 return intermediate.addConstantUnion(constArray, variable->getType(), location);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001245 }
1246 else
1247 {
1248 return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
1249 variable->getType(), location);
1250 }
1251}
1252
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001253//
1254// Look up a function name in the symbol table, and make sure it is a function.
1255//
1256// Return the function symbol if found, otherwise 0.
1257//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001258const TFunction *TParseContext::findFunction(const TSourceLoc &line,
1259 TFunction *call,
1260 int inputShaderVersion,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301261 bool *builtIn)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001262{
alokp@chromium.org0a576182010-08-09 17:16:27 +00001263 // First find by unmangled name to check whether the function name has been
1264 // hidden by a variable name or struct typename.
Nicolas Capensd4a9b8d2013-07-18 11:01:22 -04001265 // If a function is found, check for one with a matching argument list.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301266 const TSymbol *symbol = symbolTable.find(call->getName(), inputShaderVersion, builtIn);
1267 if (symbol == 0 || symbol->isFunction())
1268 {
Austin Kinross3ae64652015-01-26 15:51:39 -08001269 symbol = symbolTable.find(call->getMangledName(), inputShaderVersion, builtIn);
alokp@chromium.org0a576182010-08-09 17:16:27 +00001270 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001271
Arun Patole7e7e68d2015-05-22 12:02:25 +05301272 if (symbol == 0)
1273 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001274 error(line, "no matching overloaded function found", call->getName().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001275 return 0;
1276 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001277
Arun Patole7e7e68d2015-05-22 12:02:25 +05301278 if (!symbol->isFunction())
1279 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001280 error(line, "function name expected", call->getName().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001281 return 0;
1282 }
alokp@chromium.org0a576182010-08-09 17:16:27 +00001283
Jamie Madillb98c3a82015-07-23 14:26:04 -04001284 return static_cast<const TFunction *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001285}
1286
1287//
1288// Initializers show up in several places in the grammar. Have one set of
1289// code to handle them here.
1290//
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001291// Returns true on error, false if no error
1292//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001293bool TParseContext::executeInitializer(const TSourceLoc &line,
1294 const TString &identifier,
1295 const TPublicType &pType,
1296 TIntermTyped *initializer,
1297 TIntermNode **intermNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001298{
Olli Etuahoe7847b02015-03-16 11:56:12 +02001299 ASSERT(intermNode != nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001300 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001301
Olli Etuaho2935c582015-04-08 14:32:06 +03001302 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001303 if (type.isUnsizedArray())
1304 {
1305 type.setArraySize(initializer->getArraySize());
1306 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001307 if (!declareVariable(line, identifier, type, &variable))
1308 {
1309 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001310 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001311
Olli Etuahob0c645e2015-05-12 14:25:36 +03001312 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001313 if (symbolTable.atGlobalLevel() &&
1314 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001315 {
1316 // Error message does not completely match behavior with ESSL 1.00, but
1317 // we want to steer developers towards only using constant expressions.
1318 error(line, "global variable initializers must be constant expressions", "=");
1319 return true;
1320 }
1321 if (globalInitWarning)
1322 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001323 warning(
1324 line,
1325 "global variable initializers should be constant expressions "
1326 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1327 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001328 }
1329
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001330 //
1331 // identifier must be of type constant, a global, or a temporary
1332 //
1333 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301334 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1335 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001336 error(line, " cannot initialize this type of qualifier ",
1337 variable->getType().getQualifierString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001338 return true;
1339 }
1340 //
1341 // test for and propagate constant
1342 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001343
Arun Patole7e7e68d2015-05-22 12:02:25 +05301344 if (qualifier == EvqConst)
1345 {
1346 if (qualifier != initializer->getType().getQualifier())
1347 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001348 std::stringstream extraInfoStream;
1349 extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
1350 std::string extraInfo = extraInfoStream.str();
1351 error(line, " assigning non-constant to", "=", extraInfo.c_str());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001352 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001353 return true;
1354 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301355 if (type != initializer->getType())
1356 {
1357 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001358 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001359 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001360 return true;
1361 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001362
1363 // Save the constant folded value to the variable if possible. For example array
1364 // initializers are not folded, since that way copying the array literal to multiple places
1365 // in the shader is avoided.
1366 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1367 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301368 if (initializer->getAsConstantUnion())
1369 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001370 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001371 *intermNode = nullptr;
1372 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301373 }
1374 else if (initializer->getAsSymbolNode())
1375 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001376 const TSymbol *symbol =
1377 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1378 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001379
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001380 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001381 if (constArray)
1382 {
1383 variable->shareConstPointer(constArray);
1384 *intermNode = nullptr;
1385 return false;
1386 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001387 }
1388 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001389
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001390 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1391 variable->getUniqueId(), variable->getName(), variable->getType(), line);
1392 *intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1393 if (*intermNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001394 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001395 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1396 return true;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001397 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001398
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001399 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001400}
1401
Martin Radev70866b82016-07-22 15:27:42 +03001402TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301403 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001404{
Olli Etuaho613b9592016-09-05 12:05:53 +03001405 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001406
Martin Radev70866b82016-07-22 15:27:42 +03001407 TPublicType returnType = typeSpecifier;
1408 returnType.qualifier = typeQualifier.qualifier;
1409 returnType.invariant = typeQualifier.invariant;
1410 returnType.layoutQualifier = typeQualifier.layoutQualifier;
1411 returnType.precision = typeSpecifier.precision;
1412
1413 if (typeQualifier.precision != EbpUndefined)
1414 {
1415 returnType.precision = typeQualifier.precision;
1416 }
1417
Martin Radev4a9cd802016-09-01 16:51:51 +03001418 checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
1419 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03001420
Martin Radev4a9cd802016-09-01 16:51:51 +03001421 checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
1422 typeSpecifier.getLine());
Martin Radev70866b82016-07-22 15:27:42 +03001423
Martin Radev4a9cd802016-09-01 16:51:51 +03001424 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001425
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001426 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001427 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001428 if (typeSpecifier.array)
1429 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001430 error(typeSpecifier.getLine(), "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001431 returnType.clearArrayness();
1432 }
1433
Martin Radev70866b82016-07-22 15:27:42 +03001434 if (returnType.qualifier == EvqAttribute &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001435 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001436 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001437 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001438 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001439 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001440
Martin Radev70866b82016-07-22 15:27:42 +03001441 if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001442 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001443 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001444 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001445 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001446 }
1447 }
1448 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001449 {
Martin Radev70866b82016-07-22 15:27:42 +03001450 if (!returnType.layoutQualifier.isEmpty())
Olli Etuahoabb0c382015-07-13 12:01:12 +03001451 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001452 checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03001453 }
Martin Radev70866b82016-07-22 15:27:42 +03001454 if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
1455 returnType.qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001456 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001457 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
1458 typeSpecifier.getLine());
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001459 }
Martin Radev70866b82016-07-22 15:27:42 +03001460 if (returnType.qualifier == EvqComputeIn)
Martin Radev802abe02016-08-04 17:48:32 +03001461 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001462 error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
Martin Radev802abe02016-08-04 17:48:32 +03001463 "in");
Martin Radev802abe02016-08-04 17:48:32 +03001464 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001465 }
1466
1467 return returnType;
1468}
1469
Olli Etuaho856c4972016-08-08 11:38:39 +03001470void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1471 const TPublicType &type,
1472 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03001473{
1474 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
Martin Radev4a9cd802016-09-01 16:51:51 +03001475 if (type.getBasicType() == EbtBool)
Olli Etuahocc36b982015-07-10 14:14:18 +03001476 {
1477 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001478 }
1479
1480 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1481 switch (qualifier)
1482 {
1483 case EvqVertexIn:
1484 // ESSL 3.00 section 4.3.4
1485 if (type.array)
1486 {
1487 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001488 }
1489 // Vertex inputs with a struct type are disallowed in singleDeclarationErrorCheck
1490 return;
1491 case EvqFragmentOut:
1492 // ESSL 3.00 section 4.3.6
Martin Radev4a9cd802016-09-01 16:51:51 +03001493 if (type.typeSpecifierNonArray.isMatrix())
Olli Etuahocc36b982015-07-10 14:14:18 +03001494 {
1495 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001496 }
1497 // Fragment outputs with a struct type are disallowed in singleDeclarationErrorCheck
1498 return;
1499 default:
1500 break;
1501 }
1502
1503 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1504 // restrictions.
1505 bool typeContainsIntegers =
Martin Radev4a9cd802016-09-01 16:51:51 +03001506 (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
1507 type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
Olli Etuahocc36b982015-07-10 14:14:18 +03001508 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1509 {
1510 error(qualifierLocation, "must use 'flat' interpolation here",
1511 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001512 }
1513
Martin Radev4a9cd802016-09-01 16:51:51 +03001514 if (type.getBasicType() == EbtStruct)
Olli Etuahocc36b982015-07-10 14:14:18 +03001515 {
1516 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1517 // These restrictions are only implied by the ESSL 3.00 spec, but
1518 // the ESSL 3.10 spec lists these restrictions explicitly.
1519 if (type.array)
1520 {
1521 error(qualifierLocation, "cannot be an array of structures",
1522 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001523 }
1524 if (type.isStructureContainingArrays())
1525 {
1526 error(qualifierLocation, "cannot be a structure containing an array",
1527 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001528 }
1529 if (type.isStructureContainingType(EbtStruct))
1530 {
1531 error(qualifierLocation, "cannot be a structure containing a structure",
1532 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001533 }
1534 if (type.isStructureContainingType(EbtBool))
1535 {
1536 error(qualifierLocation, "cannot be a structure containing a bool",
1537 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001538 }
1539 }
1540}
1541
Olli Etuahofa33d582015-04-09 14:33:12 +03001542TIntermAggregate *TParseContext::parseSingleDeclaration(TPublicType &publicType,
1543 const TSourceLoc &identifierOrTypeLocation,
1544 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04001545{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001546 TType type(publicType);
1547 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
1548 mDirectiveHandler.pragma().stdgl.invariantAll)
1549 {
1550 TQualifier qualifier = type.getQualifier();
1551
1552 // The directive handler has already taken care of rejecting invalid uses of this pragma
1553 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
1554 // affected variable declarations:
1555 //
1556 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
1557 // elsewhere, in TranslatorGLSL.)
1558 //
1559 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
1560 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
1561 // the way this is currently implemented we have to enable this compiler option before
1562 // parsing the shader and determining the shading language version it uses. If this were
1563 // implemented as a post-pass, the workaround could be more targeted.
1564 //
1565 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
1566 // the specification, but there are desktop OpenGL drivers that expect that this is the
1567 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
1568 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
1569 {
1570 type.setInvariant(true);
1571 }
1572 }
1573
1574 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001575
Olli Etuahobab4c082015-04-24 16:38:49 +03001576 bool emptyDeclaration = (identifier == "");
Olli Etuahofa33d582015-04-09 14:33:12 +03001577
Olli Etuahobab4c082015-04-24 16:38:49 +03001578 mDeferredSingleDeclarationErrorCheck = emptyDeclaration;
1579
1580 if (emptyDeclaration)
1581 {
1582 if (publicType.isUnsizedArray())
1583 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001584 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1585 // error. It is assumed that this applies to empty declarations as well.
1586 error(identifierOrTypeLocation, "empty array declaration needs to specify a size",
1587 identifier.c_str());
Olli Etuahobab4c082015-04-24 16:38:49 +03001588 }
1589 }
1590 else
Jamie Madill60ed9812013-06-06 11:56:46 -04001591 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001592 singleDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001593
Olli Etuaho856c4972016-08-08 11:38:39 +03001594 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001595
Olli Etuaho2935c582015-04-08 14:32:06 +03001596 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001597 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001598
1599 if (variable && symbol)
Jamie Madill60ed9812013-06-06 11:56:46 -04001600 symbol->setId(variable->getUniqueId());
Jamie Madill60ed9812013-06-06 11:56:46 -04001601 }
1602
Olli Etuahoe7847b02015-03-16 11:56:12 +02001603 return intermediate.makeAggregate(symbol, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001604}
1605
Olli Etuahoe7847b02015-03-16 11:56:12 +02001606TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1607 const TSourceLoc &identifierLocation,
1608 const TString &identifier,
1609 const TSourceLoc &indexLocation,
1610 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04001611{
Olli Etuahofa33d582015-04-09 14:33:12 +03001612 mDeferredSingleDeclarationErrorCheck = false;
1613
Olli Etuaho383b7912016-08-05 11:22:59 +03001614 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001615
Olli Etuaho856c4972016-08-08 11:38:39 +03001616 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001617
Olli Etuaho8a176262016-08-16 14:23:01 +03001618 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001619
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001620 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001621
Olli Etuaho856c4972016-08-08 11:38:39 +03001622 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001623 // Make the type an array even if size check failed.
1624 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1625 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04001626
Olli Etuaho2935c582015-04-08 14:32:06 +03001627 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001628 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001629
Olli Etuahoe7847b02015-03-16 11:56:12 +02001630 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001631 if (variable && symbol)
Jamie Madill60ed9812013-06-06 11:56:46 -04001632 symbol->setId(variable->getUniqueId());
Jamie Madill60ed9812013-06-06 11:56:46 -04001633
Olli Etuahoe7847b02015-03-16 11:56:12 +02001634 return intermediate.makeAggregate(symbol, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001635}
1636
Jamie Madill06145232015-05-13 13:10:01 -04001637TIntermAggregate *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
Olli Etuahoe7847b02015-03-16 11:56:12 +02001638 const TSourceLoc &identifierLocation,
1639 const TString &identifier,
1640 const TSourceLoc &initLocation,
1641 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04001642{
Olli Etuahofa33d582015-04-09 14:33:12 +03001643 mDeferredSingleDeclarationErrorCheck = false;
1644
Olli Etuaho383b7912016-08-05 11:22:59 +03001645 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001646
Olli Etuahoe7847b02015-03-16 11:56:12 +02001647 TIntermNode *intermNode = nullptr;
1648 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04001649 {
1650 //
1651 // Build intermediate representation
1652 //
Olli Etuahoe7847b02015-03-16 11:56:12 +02001653 return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : nullptr;
Jamie Madill60ed9812013-06-06 11:56:46 -04001654 }
1655 else
1656 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001657 return nullptr;
Jamie Madill60ed9812013-06-06 11:56:46 -04001658 }
1659}
1660
Jamie Madillb98c3a82015-07-23 14:26:04 -04001661TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration(
1662 TPublicType &publicType,
1663 const TSourceLoc &identifierLocation,
1664 const TString &identifier,
1665 const TSourceLoc &indexLocation,
1666 TIntermTyped *indexExpression,
1667 const TSourceLoc &initLocation,
1668 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001669{
1670 mDeferredSingleDeclarationErrorCheck = false;
1671
Olli Etuaho383b7912016-08-05 11:22:59 +03001672 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001673
Olli Etuaho8a176262016-08-16 14:23:01 +03001674 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001675
1676 TPublicType arrayType(publicType);
1677
Olli Etuaho856c4972016-08-08 11:38:39 +03001678 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001679 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
1680 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03001681 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001682 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001683 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001684 }
1685 // Make the type an array even if size check failed.
1686 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1687 arrayType.setArraySize(size);
1688
1689 // initNode will correspond to the whole of "type b[n] = initializer".
1690 TIntermNode *initNode = nullptr;
1691 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
1692 {
1693 return initNode ? intermediate.makeAggregate(initNode, initLocation) : nullptr;
1694 }
1695 else
1696 {
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001697 return nullptr;
1698 }
1699}
1700
Martin Radev70866b82016-07-22 15:27:42 +03001701TIntermAggregate *TParseContext::parseInvariantDeclaration(
1702 const TTypeQualifierBuilder &typeQualifierBuilder,
1703 const TSourceLoc &identifierLoc,
1704 const TString *identifier,
1705 const TSymbol *symbol)
Jamie Madill47e3ec02014-08-20 16:38:33 -04001706{
Olli Etuaho613b9592016-09-05 12:05:53 +03001707 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
Jamie Madill47e3ec02014-08-20 16:38:33 -04001708
Martin Radev70866b82016-07-22 15:27:42 +03001709 if (!typeQualifier.invariant)
1710 {
1711 error(identifierLoc, "Expected invariant", identifier->c_str());
1712 return nullptr;
1713 }
1714 if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
1715 {
1716 return nullptr;
1717 }
Jamie Madill47e3ec02014-08-20 16:38:33 -04001718 if (!symbol)
1719 {
1720 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001721 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001722 }
Martin Radev70866b82016-07-22 15:27:42 +03001723 if (!IsQualifierUnspecified(typeQualifier.qualifier))
Jamie Madill47e3ec02014-08-20 16:38:33 -04001724 {
Martin Radev70866b82016-07-22 15:27:42 +03001725 error(identifierLoc, "invariant declaration specifies qualifier",
1726 getQualifierString(typeQualifier.qualifier));
Jamie Madill47e3ec02014-08-20 16:38:33 -04001727 }
Martin Radev70866b82016-07-22 15:27:42 +03001728 if (typeQualifier.precision != EbpUndefined)
1729 {
1730 error(identifierLoc, "invariant declaration specifies precision",
1731 getPrecisionString(typeQualifier.precision));
1732 }
1733 if (!typeQualifier.layoutQualifier.isEmpty())
1734 {
1735 error(identifierLoc, "invariant declaration specifies layout", "'layout'");
1736 }
1737
1738 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
1739 ASSERT(variable);
1740 const TType &type = variable->getType();
1741
1742 checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
1743 typeQualifier.line);
1744
1745 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
1746
1747 TIntermSymbol *intermSymbol =
1748 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
1749
1750 TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc);
1751 aggregate->setOp(EOpInvariantDeclaration);
1752 return aggregate;
Jamie Madill47e3ec02014-08-20 16:38:33 -04001753}
1754
Jamie Madillb98c3a82015-07-23 14:26:04 -04001755TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType,
1756 TIntermAggregate *aggregateDeclaration,
1757 const TSourceLoc &identifierLocation,
1758 const TString &identifier)
Jamie Madill502d66f2013-06-20 11:55:52 -04001759{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001760 // If the declaration starting this declarator list was empty (example: int,), some checks were
1761 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001762 if (mDeferredSingleDeclarationErrorCheck)
1763 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001764 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001765 mDeferredSingleDeclarationErrorCheck = false;
1766 }
1767
Olli Etuaho856c4972016-08-08 11:38:39 +03001768 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001769
Olli Etuaho856c4972016-08-08 11:38:39 +03001770 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04001771
Olli Etuaho2935c582015-04-08 14:32:06 +03001772 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001773 declareVariable(identifierLocation, identifier, TType(publicType), &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001774
Jamie Madillb98c3a82015-07-23 14:26:04 -04001775 TIntermSymbol *symbol =
1776 intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001777 if (variable && symbol)
Jamie Madill502d66f2013-06-20 11:55:52 -04001778 symbol->setId(variable->getUniqueId());
1779
Olli Etuahoe7847b02015-03-16 11:56:12 +02001780 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001781}
1782
Jamie Madillb98c3a82015-07-23 14:26:04 -04001783TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType,
1784 TIntermAggregate *aggregateDeclaration,
1785 const TSourceLoc &identifierLocation,
1786 const TString &identifier,
1787 const TSourceLoc &arrayLocation,
1788 TIntermTyped *indexExpression)
Jamie Madill502d66f2013-06-20 11:55:52 -04001789{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001790 // If the declaration starting this declarator list was empty (example: int,), some checks were
1791 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001792 if (mDeferredSingleDeclarationErrorCheck)
1793 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001794 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001795 mDeferredSingleDeclarationErrorCheck = false;
1796 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001797
Olli Etuaho856c4972016-08-08 11:38:39 +03001798 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001799
Olli Etuaho856c4972016-08-08 11:38:39 +03001800 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04001801
Olli Etuaho8a176262016-08-16 14:23:01 +03001802 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04001803 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001804 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03001805 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03001806 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001807
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001808 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001809 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04001810
Jamie Madillb98c3a82015-07-23 14:26:04 -04001811 TIntermSymbol *symbol =
1812 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001813 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001814 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02001815
1816 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001817 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001818
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001819 return nullptr;
Jamie Madill502d66f2013-06-20 11:55:52 -04001820}
1821
Jamie Madillb98c3a82015-07-23 14:26:04 -04001822TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicType,
1823 TIntermAggregate *aggregateDeclaration,
1824 const TSourceLoc &identifierLocation,
1825 const TString &identifier,
1826 const TSourceLoc &initLocation,
1827 TIntermTyped *initializer)
Jamie Madill502d66f2013-06-20 11:55:52 -04001828{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001829 // If the declaration starting this declarator list was empty (example: int,), some checks were
1830 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03001831 if (mDeferredSingleDeclarationErrorCheck)
1832 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001833 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03001834 mDeferredSingleDeclarationErrorCheck = false;
1835 }
Jamie Madill502d66f2013-06-20 11:55:52 -04001836
Olli Etuaho856c4972016-08-08 11:38:39 +03001837 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04001838
Olli Etuahoe7847b02015-03-16 11:56:12 +02001839 TIntermNode *intermNode = nullptr;
1840 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04001841 {
1842 //
1843 // build the intermediate representation
1844 //
1845 if (intermNode)
1846 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001847 return intermediate.growAggregate(aggregateDeclaration, intermNode, initLocation);
Jamie Madill502d66f2013-06-20 11:55:52 -04001848 }
1849 else
1850 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001851 return aggregateDeclaration;
Jamie Madill502d66f2013-06-20 11:55:52 -04001852 }
1853 }
1854 else
1855 {
Olli Etuahoe7847b02015-03-16 11:56:12 +02001856 return nullptr;
Jamie Madill502d66f2013-06-20 11:55:52 -04001857 }
1858}
1859
Jamie Madill06145232015-05-13 13:10:01 -04001860TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001861 TIntermAggregate *aggregateDeclaration,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301862 const TSourceLoc &identifierLocation,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001863 const TString &identifier,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301864 const TSourceLoc &indexLocation,
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001865 TIntermTyped *indexExpression,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001866 const TSourceLoc &initLocation,
1867 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001868{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001869 // If the declaration starting this declarator list was empty (example: int,), some checks were
1870 // not performed.
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001871 if (mDeferredSingleDeclarationErrorCheck)
1872 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001873 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001874 mDeferredSingleDeclarationErrorCheck = false;
1875 }
1876
Olli Etuaho856c4972016-08-08 11:38:39 +03001877 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001878
Olli Etuaho8a176262016-08-16 14:23:01 +03001879 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001880
1881 TPublicType arrayType(publicType);
1882
Olli Etuaho856c4972016-08-08 11:38:39 +03001883 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001884 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
1885 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03001886 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001887 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001888 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001889 }
1890 // Make the type an array even if size check failed.
1891 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1892 arrayType.setArraySize(size);
1893
1894 // initNode will correspond to the whole of "b[n] = initializer".
1895 TIntermNode *initNode = nullptr;
1896 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
1897 {
1898 if (initNode)
1899 {
1900 return intermediate.growAggregate(aggregateDeclaration, initNode, initLocation);
1901 }
1902 else
1903 {
1904 return aggregateDeclaration;
1905 }
1906 }
1907 else
1908 {
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001909 return nullptr;
1910 }
1911}
1912
Martin Radev70866b82016-07-22 15:27:42 +03001913void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
Jamie Madilla295edf2013-06-06 11:56:48 -04001914{
Olli Etuaho613b9592016-09-05 12:05:53 +03001915 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
Jamie Madilla295edf2013-06-06 11:56:48 -04001916 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04001917
Martin Radev70866b82016-07-22 15:27:42 +03001918 checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
1919 typeQualifier.line);
1920
Jamie Madillc2128ff2016-07-04 10:26:17 -04001921 // It should never be the case, but some strange parser errors can send us here.
1922 if (layoutQualifier.isEmpty())
1923 {
1924 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04001925 return;
1926 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001927
Martin Radev802abe02016-08-04 17:48:32 +03001928 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04001929 {
Martin Radev802abe02016-08-04 17:48:32 +03001930 error(typeQualifier.line, "invalid combination:", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04001931 return;
1932 }
1933
Martin Radev802abe02016-08-04 17:48:32 +03001934 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04001935 {
Martin Radev802abe02016-08-04 17:48:32 +03001936 if (mComputeShaderLocalSizeDeclared &&
1937 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
1938 {
1939 error(typeQualifier.line, "Work group size does not match the previous declaration",
1940 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001941 return;
1942 }
Jamie Madilla295edf2013-06-06 11:56:48 -04001943
Martin Radev802abe02016-08-04 17:48:32 +03001944 if (mShaderVersion < 310)
1945 {
1946 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001947 return;
1948 }
Jamie Madill099c0f32013-06-20 11:55:52 -04001949
Martin Radev4c4c8e72016-08-04 12:25:34 +03001950 if (!layoutQualifier.localSize.isAnyValueSet())
Martin Radev802abe02016-08-04 17:48:32 +03001951 {
1952 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03001953 return;
1954 }
1955
1956 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
1957 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
1958
1959 const TConstantUnion *maxComputeWorkGroupSizeData =
1960 maxComputeWorkGroupSize->getConstPointer();
1961
1962 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
1963 {
1964 if (layoutQualifier.localSize[i] != -1)
1965 {
1966 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
1967 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
1968 if (mComputeShaderLocalSize[i] < 1 ||
1969 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
1970 {
1971 std::stringstream errorMessageStream;
1972 errorMessageStream << "Value must be at least 1 and no greater than "
1973 << maxComputeWorkGroupSizeValue;
1974 const std::string &errorMessage = errorMessageStream.str();
1975
Martin Radev4c4c8e72016-08-04 12:25:34 +03001976 error(typeQualifier.line, "invalid value:", getWorkGroupSizeString(i),
Martin Radev802abe02016-08-04 17:48:32 +03001977 errorMessage.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03001978 return;
1979 }
1980 }
1981 }
1982
1983 mComputeShaderLocalSizeDeclared = true;
1984 }
1985 else
Jamie Madill1566ef72013-06-20 11:55:54 -04001986 {
Martin Radev802abe02016-08-04 17:48:32 +03001987
Olli Etuaho8a176262016-08-16 14:23:01 +03001988 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03001989 {
Martin Radev802abe02016-08-04 17:48:32 +03001990 return;
1991 }
1992
1993 if (typeQualifier.qualifier != EvqUniform)
1994 {
1995 error(typeQualifier.line, "invalid qualifier:",
1996 getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
Martin Radev802abe02016-08-04 17:48:32 +03001997 return;
1998 }
1999
2000 if (mShaderVersion < 300)
2001 {
2002 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
2003 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002004 return;
2005 }
2006
Olli Etuaho856c4972016-08-08 11:38:39 +03002007 checkLocationIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002008
2009 if (layoutQualifier.matrixPacking != EmpUnspecified)
2010 {
2011 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
2012 }
2013
2014 if (layoutQualifier.blockStorage != EbsUnspecified)
2015 {
2016 mDefaultBlockStorage = layoutQualifier.blockStorage;
2017 }
Jamie Madill1566ef72013-06-20 11:55:54 -04002018 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002019}
2020
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002021TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function,
2022 const TSourceLoc &location)
2023{
Olli Etuaho5d653182016-01-04 14:43:28 +02002024 // Note: symbolTableFunction could be the same as function if this is the first declaration.
2025 // Either way the instance in the symbol table is used to track whether the function is declared
2026 // multiple times.
2027 TFunction *symbolTableFunction =
2028 static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion()));
2029 if (symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100)
2030 {
2031 // ESSL 1.00.17 section 4.2.7.
2032 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
2033 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02002034 }
2035 symbolTableFunction->setHasPrototypeDeclaration();
2036
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002037 TIntermAggregate *prototype = new TIntermAggregate;
2038 prototype->setType(function.getReturnType());
2039 prototype->setName(function.getMangledName());
2040 prototype->setFunctionId(function.getUniqueId());
2041
2042 for (size_t i = 0; i < function.getParamCount(); i++)
2043 {
2044 const TConstParameter &param = function.getParam(i);
2045 if (param.name != 0)
2046 {
2047 TVariable variable(param.name, *param.type);
2048
2049 TIntermSymbol *paramSymbol = intermediate.addSymbol(
2050 variable.getUniqueId(), variable.getName(), variable.getType(), location);
2051 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
2052 }
2053 else
2054 {
2055 TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
2056 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
2057 }
2058 }
2059
2060 prototype->setOp(EOpPrototype);
2061
2062 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002063
2064 if (!symbolTable.atGlobalLevel())
2065 {
2066 // ESSL 3.00.4 section 4.2.4.
2067 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002068 }
2069
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002070 return prototype;
2071}
2072
2073TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function,
2074 TIntermAggregate *functionPrototype,
2075 TIntermAggregate *functionBody,
2076 const TSourceLoc &location)
2077{
2078 //?? Check that all paths return a value if return type != void ?
2079 // May be best done as post process phase on intermediate code
2080 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2081 {
2082 error(location, "function does not return a value:", "", function.getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002083 }
2084
2085 TIntermAggregate *aggregate =
2086 intermediate.growAggregate(functionPrototype, functionBody, location);
2087 intermediate.setAggregateOperator(aggregate, EOpFunction, location);
2088 aggregate->setName(function.getMangledName().c_str());
2089 aggregate->setType(function.getReturnType());
2090 aggregate->setFunctionId(function.getUniqueId());
2091
2092 symbolTable.pop();
2093 return aggregate;
2094}
2095
Jamie Madill185fb402015-06-12 15:48:48 -04002096void TParseContext::parseFunctionPrototype(const TSourceLoc &location,
2097 TFunction *function,
2098 TIntermAggregate **aggregateOut)
2099{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002100 const TSymbol *builtIn =
2101 symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002102
2103 if (builtIn)
2104 {
2105 error(location, "built-in functions cannot be redefined", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002106 }
2107
Jamie Madillb98c3a82015-07-23 14:26:04 -04002108 TFunction *prevDec =
2109 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Jamie Madill185fb402015-06-12 15:48:48 -04002110 //
2111 // Note: 'prevDec' could be 'function' if this is the first time we've seen function
2112 // as it would have just been put in the symbol table. Otherwise, we're looking up
2113 // an earlier occurance.
2114 //
2115 if (prevDec->isDefined())
2116 {
2117 // Then this function already has a body.
2118 error(location, "function already has a body", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002119 }
2120 prevDec->setDefined();
2121 //
2122 // Overload the unique ID of the definition to be the same unique ID as the declaration.
2123 // Eventually we will probably want to have only a single definition and just swap the
2124 // arguments to be the definition's arguments.
2125 //
2126 function->setUniqueId(prevDec->getUniqueId());
2127
2128 // Raise error message if main function takes any parameters or return anything other than void
2129 if (function->getName() == "main")
2130 {
2131 if (function->getParamCount() > 0)
2132 {
2133 error(location, "function cannot take any parameter(s)", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002134 }
2135 if (function->getReturnType().getBasicType() != EbtVoid)
2136 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002137 error(location, "", function->getReturnType().getBasicString(),
2138 "main function cannot return a value");
Jamie Madill185fb402015-06-12 15:48:48 -04002139 }
2140 }
2141
2142 //
2143 // Remember the return type for later checking for RETURN statements.
2144 //
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002145 mCurrentFunctionType = &(prevDec->getReturnType());
2146 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002147
2148 //
2149 // Insert parameters into the symbol table.
2150 // If the parameter has no name, it's not an error, just don't insert it
2151 // (could be used for unused args).
2152 //
2153 // Also, accumulate the list of parameters into the HIL, so lower level code
2154 // knows where to find parameters.
2155 //
2156 TIntermAggregate *paramNodes = new TIntermAggregate;
2157 for (size_t i = 0; i < function->getParamCount(); i++)
2158 {
2159 const TConstParameter &param = function->getParam(i);
2160 if (param.name != 0)
2161 {
2162 TVariable *variable = new TVariable(param.name, *param.type);
2163 //
2164 // Insert the parameters with name in the symbol table.
2165 //
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002166 if (!symbolTable.declare(variable))
2167 {
Jamie Madill185fb402015-06-12 15:48:48 -04002168 error(location, "redefinition", variable->getName().c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002169 paramNodes = intermediate.growAggregate(
2170 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
2171 continue;
Jamie Madill185fb402015-06-12 15:48:48 -04002172 }
2173
2174 //
2175 // Add the parameter to the HIL
2176 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002177 TIntermSymbol *symbol = intermediate.addSymbol(
2178 variable->getUniqueId(), variable->getName(), variable->getType(), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002179
2180 paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
2181 }
2182 else
2183 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002184 paramNodes = intermediate.growAggregate(
2185 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002186 }
2187 }
2188 intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
2189 *aggregateOut = paramNodes;
2190 setLoopNestingLevel(0);
2191}
2192
Jamie Madillb98c3a82015-07-23 14:26:04 -04002193TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002194{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002195 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002196 // We don't know at this point whether this is a function definition or a prototype.
2197 // The definition production code will check for redefinitions.
2198 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002199 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002200 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2201 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002202 //
2203 TFunction *prevDec =
2204 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302205
2206 if (getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltIn(function->getName().c_str()))
2207 {
2208 // With ESSL 3.00, names of built-in functions cannot be redeclared as functions.
2209 // Therefore overloading or redefining builtin functions is an error.
2210 error(location, "Name of a built-in function cannot be redeclared as function",
2211 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302212 }
2213 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002214 {
2215 if (prevDec->getReturnType() != function->getReturnType())
2216 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002217 error(location, "overloaded functions must have the same return type",
Jamie Madill185fb402015-06-12 15:48:48 -04002218 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002219 }
2220 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2221 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002222 if (prevDec->getParam(i).type->getQualifier() !=
2223 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002224 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002225 error(location, "overloaded functions must have the same parameter qualifiers",
Jamie Madill185fb402015-06-12 15:48:48 -04002226 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002227 }
2228 }
2229 }
2230
2231 //
2232 // Check for previously declared variables using the same name.
2233 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002234 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002235 if (prevSym)
2236 {
2237 if (!prevSym->isFunction())
2238 {
2239 error(location, "redefinition", function->getName().c_str(), "function");
Jamie Madill185fb402015-06-12 15:48:48 -04002240 }
2241 }
2242 else
2243 {
2244 // Insert the unmangled name to detect potential future redefinition as a variable.
Jamie Madillb98c3a82015-07-23 14:26:04 -04002245 TFunction *newFunction =
2246 new TFunction(NewPoolTString(function->getName().c_str()), &function->getReturnType());
Jamie Madill185fb402015-06-12 15:48:48 -04002247 symbolTable.getOuterLevel()->insertUnmangled(newFunction);
2248 }
2249
2250 // We're at the inner scope level of the function's arguments and body statement.
2251 // Add the function prototype to the surrounding scope instead.
2252 symbolTable.getOuterLevel()->insert(function);
2253
2254 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002255 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2256 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002257 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2258 //
2259 return function;
2260}
2261
Olli Etuaho9de84a52016-06-14 17:36:01 +03002262TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2263 const TString *name,
2264 const TSourceLoc &location)
2265{
2266 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2267 {
2268 error(location, "no qualifiers allowed for function return",
2269 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002270 }
2271 if (!type.layoutQualifier.isEmpty())
2272 {
2273 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002274 }
2275 // make sure a sampler is not involved as well...
Martin Radev4a9cd802016-09-01 16:51:51 +03002276 checkIsNotSampler(location, type.typeSpecifierNonArray,
2277 "samplers can't be function return values");
Olli Etuahoe29324f2016-06-15 10:58:03 +03002278 if (mShaderVersion < 300)
2279 {
2280 // Array return values are forbidden, but there's also no valid syntax for declaring array
2281 // return values in ESSL 1.00.
2282 ASSERT(type.arraySize == 0 || mDiagnostics.numErrors() > 0);
2283
2284 if (type.isStructureContainingArrays())
2285 {
2286 // ESSL 1.00.17 section 6.1 Function Definitions
2287 error(location, "structures containing arrays can't be function return values",
2288 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002289 }
2290 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002291
2292 // Add the function as a prototype after parsing it (we do not support recursion)
2293 return new TFunction(name, new TType(type));
2294}
2295
Jamie Madill06145232015-05-13 13:10:01 -04002296TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002297{
Jamie Madill06145232015-05-13 13:10:01 -04002298 TPublicType publicType = publicTypeIn;
Martin Radev4a9cd802016-09-01 16:51:51 +03002299 if (publicType.isStructSpecifier())
Olli Etuahobd163f62015-11-13 12:15:38 +02002300 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002301 error(publicType.getLine(), "constructor can't be a structure definition",
2302 getBasicString(publicType.getBasicType()));
Olli Etuahobd163f62015-11-13 12:15:38 +02002303 }
2304
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002305 TOperator op = EOpNull;
Martin Radev4a9cd802016-09-01 16:51:51 +03002306 if (publicType.getUserDef())
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002307 {
2308 op = EOpConstructStruct;
2309 }
2310 else
2311 {
Geoff Lang156d7192016-07-21 16:11:00 -04002312 op = sh::TypeToConstructorOperator(TType(publicType));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002313 if (op == EOpNull)
2314 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002315 error(publicType.getLine(), "cannot construct this type",
2316 getBasicString(publicType.getBasicType()));
2317 publicType.setBasicType(EbtFloat);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002318 op = EOpConstructFloat;
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002319 }
2320 }
2321
2322 TString tempString;
Dmitry Skiba7f17a502015-06-22 15:08:39 -07002323 const TType *type = new TType(publicType);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002324 return new TFunction(&tempString, type, op);
2325}
2326
Jamie Madillb98c3a82015-07-23 14:26:04 -04002327// This function is used to test for the correctness of the parameters passed to various constructor
2328// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002329//
Olli Etuaho856c4972016-08-08 11:38:39 +03002330// 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 +00002331//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002332TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002333 TOperator op,
2334 TFunction *fnCall,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302335 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002336{
Olli Etuaho856c4972016-08-08 11:38:39 +03002337 TType type = fnCall->getReturnType();
2338 if (type.isUnsizedArray())
2339 {
2340 type.setArraySize(static_cast<unsigned int>(fnCall->getParamCount()));
2341 }
2342 bool constType = true;
2343 for (size_t i = 0; i < fnCall->getParamCount(); ++i)
2344 {
2345 const TConstParameter &param = fnCall->getParam(i);
2346 if (param.type->getQualifier() != EvqConst)
2347 constType = false;
2348 }
2349 if (constType)
2350 type.setQualifier(EvqConst);
2351
Olli Etuaho8a176262016-08-16 14:23:01 +03002352 if (!checkConstructorArguments(line, arguments, *fnCall, op, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002353 {
2354 TIntermTyped *dummyNode = intermediate.setAggregateOperator(nullptr, op, line);
2355 dummyNode->setType(type);
2356 return dummyNode;
2357 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002358 TIntermAggregate *constructor = arguments->getAsAggregate();
2359 ASSERT(constructor != nullptr);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002360
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002361 // Turn the argument list itself into a constructor
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002362 constructor->setOp(op);
2363 constructor->setLine(line);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002364 ASSERT(constructor->isConstructor());
2365
2366 // Need to set type before setPrecisionFromChildren() because bool doesn't have precision.
Olli Etuaho856c4972016-08-08 11:38:39 +03002367 constructor->setType(type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002368
Olli Etuaho21203702014-11-13 16:16:21 +02002369 // Structs should not be precision qualified, the individual members may be.
2370 // Built-in types on the other hand should be precision qualified.
2371 if (op != EOpConstructStruct)
2372 {
2373 constructor->setPrecisionFromChildren();
Olli Etuaho856c4972016-08-08 11:38:39 +03002374 type.setPrecision(constructor->getPrecision());
Olli Etuaho21203702014-11-13 16:16:21 +02002375 }
2376
Olli Etuaho856c4972016-08-08 11:38:39 +03002377 constructor->setType(type);
2378
Olli Etuahof119a262016-08-19 15:54:22 +03002379 TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor, &mDiagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002380 if (constConstructor)
2381 {
2382 return constConstructor;
2383 }
2384
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002385 return constructor;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002386}
2387
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002388//
2389// Interface/uniform blocks
2390//
Martin Radev70866b82016-07-22 15:27:42 +03002391TIntermAggregate *TParseContext::addInterfaceBlock(
2392 const TTypeQualifierBuilder &typeQualifierBuilder,
2393 const TSourceLoc &nameLine,
2394 const TString &blockName,
2395 TFieldList *fieldList,
2396 const TString *instanceName,
2397 const TSourceLoc &instanceLine,
2398 TIntermTyped *arrayIndex,
2399 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002400{
Olli Etuaho856c4972016-08-08 11:38:39 +03002401 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002402
Olli Etuaho613b9592016-09-05 12:05:53 +03002403 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03002404
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002405 if (typeQualifier.qualifier != EvqUniform)
2406 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302407 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier),
2408 "interface blocks must be uniform");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002409 }
2410
Martin Radev70866b82016-07-22 15:27:42 +03002411 if (typeQualifier.invariant)
2412 {
2413 error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
2414 }
2415
Jamie Madill099c0f32013-06-20 11:55:52 -04002416 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03002417 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04002418
Jamie Madill099c0f32013-06-20 11:55:52 -04002419 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2420 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002421 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002422 }
2423
Jamie Madill1566ef72013-06-20 11:55:54 -04002424 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2425 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002426 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002427 }
2428
Olli Etuaho856c4972016-08-08 11:38:39 +03002429 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002430
Arun Patole7e7e68d2015-05-22 12:02:25 +05302431 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2432 if (!symbolTable.declare(blockNameSymbol))
2433 {
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002434 error(nameLine, "redefinition", blockName.c_str(), "interface block name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002435 }
2436
Jamie Madill98493dd2013-07-08 14:39:03 -04002437 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302438 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2439 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002440 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302441 TType *fieldType = field->type();
2442 if (IsSampler(fieldType->getBasicType()))
2443 {
2444 error(field->line(), "unsupported type", fieldType->getBasicString(),
2445 "sampler types are not allowed in interface blocks");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002446 }
2447
Jamie Madill98493dd2013-07-08 14:39:03 -04002448 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002449 switch (qualifier)
2450 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002451 case EvqGlobal:
2452 case EvqUniform:
2453 break;
2454 default:
2455 error(field->line(), "invalid qualifier on interface block member",
2456 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04002457 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002458 }
Jamie Madilla5efff92013-06-06 11:56:47 -04002459
Martin Radev70866b82016-07-22 15:27:42 +03002460 if (fieldType->isInvariant())
2461 {
2462 error(field->line(), "invalid qualifier on interface block member", "invariant");
2463 }
2464
Jamie Madilla5efff92013-06-06 11:56:47 -04002465 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04002466 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03002467 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Jamie Madill099c0f32013-06-20 11:55:52 -04002468
Jamie Madill98493dd2013-07-08 14:39:03 -04002469 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04002470 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002471 error(field->line(), "invalid layout qualifier:",
2472 getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
Jamie Madill1566ef72013-06-20 11:55:54 -04002473 }
2474
Jamie Madill98493dd2013-07-08 14:39:03 -04002475 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04002476 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002477 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002478 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002479 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04002480 {
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002481 warning(field->line(), "extraneous layout qualifier:",
Jamie Madillb98c3a82015-07-23 14:26:04 -04002482 getMatrixPackingString(fieldLayoutQualifier.matrixPacking),
2483 "only has an effect on matrix types");
Jamie Madill099c0f32013-06-20 11:55:52 -04002484 }
2485
Jamie Madill98493dd2013-07-08 14:39:03 -04002486 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002487 }
2488
Jamie Madill98493dd2013-07-08 14:39:03 -04002489 // add array index
Olli Etuaho856c4972016-08-08 11:38:39 +03002490 unsigned int arraySize = 0;
2491 if (arrayIndex != nullptr)
Jamie Madill98493dd2013-07-08 14:39:03 -04002492 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002493 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
Jamie Madill98493dd2013-07-08 14:39:03 -04002494 }
2495
Jamie Madillb98c3a82015-07-23 14:26:04 -04002496 TInterfaceBlock *interfaceBlock =
2497 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2498 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
2499 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002500
2501 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04002502 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002503
Jamie Madill98493dd2013-07-08 14:39:03 -04002504 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002505 {
2506 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04002507 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2508 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002509 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302510 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04002511
2512 // set parent pointer of the field variable
2513 fieldType->setInterfaceBlock(interfaceBlock);
2514
Arun Patole7e7e68d2015-05-22 12:02:25 +05302515 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04002516 fieldVariable->setQualifier(typeQualifier.qualifier);
2517
Arun Patole7e7e68d2015-05-22 12:02:25 +05302518 if (!symbolTable.declare(fieldVariable))
2519 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002520 error(field->line(), "redefinition", field->name().c_str(),
2521 "interface block member name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002522 }
2523 }
2524 }
2525 else
2526 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002527 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03002528
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002529 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05302530 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002531 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04002532
Arun Patole7e7e68d2015-05-22 12:02:25 +05302533 if (!symbolTable.declare(instanceTypeDef))
2534 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002535 error(instanceLine, "redefinition", instanceName->c_str(),
2536 "interface block instance name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002537 }
2538
Jamie Madillb98c3a82015-07-23 14:26:04 -04002539 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002540 symbolName = instanceTypeDef->getName();
2541 }
2542
Jamie Madillb98c3a82015-07-23 14:26:04 -04002543 TIntermAggregate *aggregate = intermediate.makeAggregate(
2544 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line),
2545 nameLine);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002546 aggregate->setOp(EOpDeclaration);
Jamie Madill98493dd2013-07-08 14:39:03 -04002547
2548 exitStructDeclaration();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002549 return aggregate;
2550}
2551
Olli Etuaho383b7912016-08-05 11:22:59 +03002552void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002553{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002554 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002555
2556 // Embedded structure definitions are not supported per GLSL ES spec.
2557 // They aren't allowed in GLSL either, but we need to detect this here
2558 // so we don't rely on the GLSL compiler to catch it.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302559 if (mStructNestingLevel > 1)
2560 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002561 error(line, "", "Embedded struct definitions are not allowed");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002562 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002563}
2564
2565void TParseContext::exitStructDeclaration()
2566{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002567 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002568}
2569
Jamie Madillb98c3a82015-07-23 14:26:04 -04002570namespace
2571{
kbr@chromium.org476541f2011-10-27 21:14:51 +00002572const int kWebGLMaxStructNesting = 4;
2573
2574} // namespace
2575
Olli Etuaho8a176262016-08-16 14:23:01 +03002576void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002577{
Arun Patole7e7e68d2015-05-22 12:02:25 +05302578 if (!IsWebGLBasedSpec(mShaderSpec))
2579 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002580 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002581 }
2582
Arun Patole7e7e68d2015-05-22 12:02:25 +05302583 if (field.type()->getBasicType() != EbtStruct)
2584 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002585 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002586 }
2587
2588 // We're already inside a structure definition at this point, so add
2589 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302590 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2591 {
Jamie Madill41a49272014-03-18 16:10:13 -04002592 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002593 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
2594 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04002595 std::string reason = reasonStream.str();
2596 error(line, reason.c_str(), field.name().c_str(), "");
Olli Etuaho8a176262016-08-16 14:23:01 +03002597 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002598 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002599}
2600
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00002601//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002602// Parse an array index expression
2603//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002604TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
2605 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302606 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002607{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002608 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2609 {
2610 if (baseExpression->getAsSymbolNode())
2611 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302612 error(location, " left of '[' is not of type array, matrix, or vector ",
2613 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002614 }
2615 else
2616 {
2617 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2618 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002619
2620 TConstantUnion *unionArray = new TConstantUnion[1];
2621 unionArray->setFConst(0.0f);
2622 return intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst),
2623 location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002624 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002625
Jamie Madill21c1e452014-12-29 11:33:41 -05002626 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2627
Olli Etuaho36b05142015-11-12 13:10:42 +02002628 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
2629 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
2630 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
2631 // index is a constant expression.
2632 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
2633 {
2634 if (baseExpression->isInterfaceBlock())
2635 {
2636 error(
2637 location, "", "[",
2638 "array indexes for interface blocks arrays must be constant integral expressions");
Olli Etuaho36b05142015-11-12 13:10:42 +02002639 }
2640 else if (baseExpression->getQualifier() == EvqFragmentOut)
2641 {
2642 error(location, "", "[",
2643 "array indexes for fragment outputs must be constant integral expressions");
Olli Etuaho36b05142015-11-12 13:10:42 +02002644 }
Olli Etuaho3e960462015-11-12 15:58:39 +02002645 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
2646 {
2647 error(location, "", "[", "array index for gl_FragData must be constant zero");
Olli Etuaho3e960462015-11-12 15:58:39 +02002648 }
Olli Etuaho36b05142015-11-12 13:10:42 +02002649 }
2650
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002651 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04002652 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002653 // If an out-of-range index is not qualified as constant, the behavior in the spec is
2654 // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
2655 // constant fold expressions that are not constant expressions). The most compatible way to
2656 // handle this case is to report a warning instead of an error and force the index to be in
2657 // the correct range.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002658 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madill21c1e452014-12-29 11:33:41 -05002659 int index = indexConstantUnion->getIConst(0);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002660
2661 int safeIndex = -1;
2662
2663 if (baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04002664 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002665 if (baseExpression->getQualifier() == EvqFragData && index > 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03002666 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002667 if (mShaderSpec == SH_WEBGL2_SPEC)
2668 {
2669 // Error has been already generated if index is not const.
2670 if (indexExpression->getQualifier() == EvqConst)
2671 {
2672 error(location, "", "[",
2673 "array index for gl_FragData must be constant zero");
2674 }
2675 safeIndex = 0;
2676 }
2677 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
2678 {
2679 outOfRangeError(outOfRangeIndexIsError, location, "", "[",
2680 "array index for gl_FragData must be zero when "
2681 "GL_EXT_draw_buffers is disabled");
2682 safeIndex = 0;
2683 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03002684 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002685 // Only do generic out-of-range check if similar error hasn't already been reported.
2686 if (safeIndex < 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03002687 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002688 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2689 baseExpression->getArraySize(),
2690 "array index out of range", "[]");
2691 }
2692 }
2693 else if (baseExpression->isMatrix())
2694 {
2695 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
Olli Etuaho90892fb2016-07-14 14:44:51 +03002696 baseExpression->getType().getCols(),
2697 "matrix field selection out of range", "[]");
Jamie Madill7164cf42013-07-08 13:30:59 -04002698 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002699 else if (baseExpression->isVector())
Jamie Madill7164cf42013-07-08 13:30:59 -04002700 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002701 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
2702 baseExpression->getType().getNominalSize(),
2703 "vector field selection out of range", "[]");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002704 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002705
2706 ASSERT(safeIndex >= 0);
2707 // Data of constant unions can't be changed, because it may be shared with other
2708 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
2709 // sanitized object.
2710 if (safeIndex != index)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002711 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002712 TConstantUnion *safeConstantUnion = new TConstantUnion();
2713 safeConstantUnion->setIConst(safeIndex);
2714 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002715 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002716
2717 return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location,
2718 &mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002719 }
Jamie Madill7164cf42013-07-08 13:30:59 -04002720 else
2721 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002722 return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location,
2723 &mDiagnostics);
Jamie Madill7164cf42013-07-08 13:30:59 -04002724 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002725}
2726
Olli Etuaho90892fb2016-07-14 14:44:51 +03002727int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
2728 const TSourceLoc &location,
2729 int index,
2730 int arraySize,
2731 const char *reason,
2732 const char *token)
2733{
2734 if (index >= arraySize || index < 0)
2735 {
2736 std::stringstream extraInfoStream;
2737 extraInfoStream << "'" << index << "'";
2738 std::string extraInfo = extraInfoStream.str();
2739 outOfRangeError(outOfRangeIndexIsError, location, reason, token, extraInfo.c_str());
2740 if (index < 0)
2741 {
2742 return 0;
2743 }
2744 else
2745 {
2746 return arraySize - 1;
2747 }
2748 }
2749 return index;
2750}
2751
Jamie Madillb98c3a82015-07-23 14:26:04 -04002752TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
2753 const TSourceLoc &dotLocation,
2754 const TString &fieldString,
2755 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002756{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002757 if (baseExpression->isArray())
2758 {
2759 error(fieldLocation, "cannot apply dot operator to an array", ".");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002760 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002761 }
2762
2763 if (baseExpression->isVector())
2764 {
2765 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002766 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
2767 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002768 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002769 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002770 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002771 }
2772
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002773 TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation);
2774 return intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation,
2775 &mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002776 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002777 else if (baseExpression->getBasicType() == EbtStruct)
2778 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302779 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04002780 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002781 {
2782 error(dotLocation, "structure has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002783 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002784 }
2785 else
2786 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002787 bool fieldFound = false;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002788 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04002789 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002790 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002791 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002792 {
2793 fieldFound = true;
2794 break;
2795 }
2796 }
2797 if (fieldFound)
2798 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002799 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
2800 index->setLine(fieldLocation);
2801 return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index,
2802 dotLocation, &mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002803 }
2804 else
2805 {
2806 error(dotLocation, " no such field in structure", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002807 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002808 }
2809 }
2810 }
Jamie Madill98493dd2013-07-08 14:39:03 -04002811 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002812 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302813 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04002814 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002815 {
2816 error(dotLocation, "interface block has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002817 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002818 }
2819 else
2820 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002821 bool fieldFound = false;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002822 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04002823 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002824 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002825 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002826 {
2827 fieldFound = true;
2828 break;
2829 }
2830 }
2831 if (fieldFound)
2832 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002833 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
2834 index->setLine(fieldLocation);
2835 return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
2836 dotLocation, &mDiagnostics);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002837 }
2838 else
2839 {
2840 error(dotLocation, " no such field in interface block", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002841 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002842 }
2843 }
2844 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002845 else
2846 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002847 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002848 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03002849 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05302850 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002851 }
2852 else
2853 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302854 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03002855 " field selection requires structure, vector, or interface block on left hand "
2856 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05302857 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002858 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002859 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002860 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002861}
2862
Jamie Madillb98c3a82015-07-23 14:26:04 -04002863TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
2864 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002865{
Martin Radev802abe02016-08-04 17:48:32 +03002866 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002867
2868 if (qualifierType == "shared")
2869 {
Jamie Madilla5efff92013-06-06 11:56:47 -04002870 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002871 }
2872 else if (qualifierType == "packed")
2873 {
Jamie Madilla5efff92013-06-06 11:56:47 -04002874 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002875 }
2876 else if (qualifierType == "std140")
2877 {
Jamie Madilla5efff92013-06-06 11:56:47 -04002878 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002879 }
2880 else if (qualifierType == "row_major")
2881 {
Jamie Madilla5efff92013-06-06 11:56:47 -04002882 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002883 }
2884 else if (qualifierType == "column_major")
2885 {
Jamie Madilla5efff92013-06-06 11:56:47 -04002886 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002887 }
2888 else if (qualifierType == "location")
2889 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002890 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(),
2891 "location requires an argument");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002892 }
2893 else
2894 {
2895 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002896 }
2897
Jamie Madilla5efff92013-06-06 11:56:47 -04002898 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002899}
2900
Martin Radev802abe02016-08-04 17:48:32 +03002901void TParseContext::parseLocalSize(const TString &qualifierType,
2902 const TSourceLoc &qualifierTypeLine,
2903 int intValue,
2904 const TSourceLoc &intValueLine,
2905 const std::string &intValueString,
2906 size_t index,
Martin Radev4c4c8e72016-08-04 12:25:34 +03002907 sh::WorkGroupSize *localSize)
Martin Radev802abe02016-08-04 17:48:32 +03002908{
Olli Etuaho856c4972016-08-08 11:38:39 +03002909 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03002910 if (intValue < 1)
2911 {
Martin Radev4c4c8e72016-08-04 12:25:34 +03002912 std::string errorMessage = std::string(getWorkGroupSizeString(index)) + " must be positive";
Martin Radev802abe02016-08-04 17:48:32 +03002913 error(intValueLine, "out of range:", intValueString.c_str(), errorMessage.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03002914 }
2915 (*localSize)[index] = intValue;
2916}
2917
Jamie Madillb98c3a82015-07-23 14:26:04 -04002918TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
2919 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002920 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302921 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002922{
Martin Radev802abe02016-08-04 17:48:32 +03002923 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002924
Martin Radev802abe02016-08-04 17:48:32 +03002925 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002926
Martin Radev802abe02016-08-04 17:48:32 +03002927 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002928 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04002929 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002930 if (intValue < 0)
2931 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002932 error(intValueLine, "out of range:", intValueString.c_str(),
2933 "location must be non-negative");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002934 }
2935 else
2936 {
Jamie Madilla5efff92013-06-06 11:56:47 -04002937 qualifier.location = intValue;
Olli Etuaho87d410c2016-09-05 13:33:26 +03002938 qualifier.locationsSpecified = 1;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002939 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002940 }
Martin Radev802abe02016-08-04 17:48:32 +03002941 else if (qualifierType == "local_size_x")
2942 {
2943 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
2944 &qualifier.localSize);
2945 }
2946 else if (qualifierType == "local_size_y")
2947 {
2948 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
2949 &qualifier.localSize);
2950 }
2951 else if (qualifierType == "local_size_z")
2952 {
2953 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
2954 &qualifier.localSize);
2955 }
2956 else
2957 {
2958 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03002959 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002960
Jamie Madilla5efff92013-06-06 11:56:47 -04002961 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002962}
2963
Olli Etuaho613b9592016-09-05 12:05:53 +03002964TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
2965{
2966 return new TTypeQualifierBuilder(
2967 new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
2968 mShaderVersion);
2969}
2970
Jamie Madillb98c3a82015-07-23 14:26:04 -04002971TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03002972 TLayoutQualifier rightQualifier,
2973 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002974{
Martin Radevc28888b2016-07-22 15:27:42 +03002975 return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
2976 &mDiagnostics);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00002977}
2978
Martin Radev70866b82016-07-22 15:27:42 +03002979TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
2980 const TTypeQualifierBuilder &typeQualifierBuilder,
2981 TPublicType *typeSpecifier,
2982 TFieldList *fieldList)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04002983{
Olli Etuaho613b9592016-09-05 12:05:53 +03002984 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04002985
Martin Radev70866b82016-07-22 15:27:42 +03002986 typeSpecifier->qualifier = typeQualifier.qualifier;
2987 typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
2988 typeSpecifier->invariant = typeQualifier.invariant;
2989 if (typeQualifier.precision != EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +05302990 {
Martin Radev70866b82016-07-22 15:27:42 +03002991 typeSpecifier->precision = typeQualifier.precision;
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04002992 }
Martin Radev70866b82016-07-22 15:27:42 +03002993 return addStructDeclaratorList(*typeSpecifier, fieldList);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04002994}
2995
Jamie Madillb98c3a82015-07-23 14:26:04 -04002996TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
2997 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002998{
Martin Radev4a9cd802016-09-01 16:51:51 +03002999 checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
3000 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03003001
Martin Radev4a9cd802016-09-01 16:51:51 +03003002 checkIsNonVoid(typeSpecifier.getLine(), (*fieldList)[0]->name(), typeSpecifier.getBasicType());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003003
Martin Radev4a9cd802016-09-01 16:51:51 +03003004 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003005
Arun Patole7e7e68d2015-05-22 12:02:25 +05303006 for (unsigned int i = 0; i < fieldList->size(); ++i)
3007 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003008 //
3009 // Careful not to replace already known aspects of type, like array-ness
3010 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303011 TType *type = (*fieldList)[i]->type();
Martin Radev4a9cd802016-09-01 16:51:51 +03003012 type->setBasicType(typeSpecifier.getBasicType());
3013 type->setPrimarySize(typeSpecifier.getPrimarySize());
3014 type->setSecondarySize(typeSpecifier.getSecondarySize());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003015 type->setPrecision(typeSpecifier.precision);
3016 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003017 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
Martin Radev70866b82016-07-22 15:27:42 +03003018 type->setInvariant(typeSpecifier.invariant);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003019
3020 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303021 if (type->isArray())
3022 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003023 checkIsValidTypeForArray(typeSpecifier.getLine(), typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003024 }
3025 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003026 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Martin Radev4a9cd802016-09-01 16:51:51 +03003027 if (typeSpecifier.getUserDef())
Arun Patole7e7e68d2015-05-22 12:02:25 +05303028 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003029 type->setStruct(typeSpecifier.getUserDef()->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003030 }
3031
Martin Radev4a9cd802016-09-01 16:51:51 +03003032 checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003033 }
3034
Jamie Madill98493dd2013-07-08 14:39:03 -04003035 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003036}
3037
Martin Radev4a9cd802016-09-01 16:51:51 +03003038TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
3039 const TSourceLoc &nameLine,
3040 const TString *structName,
3041 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003042{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303043 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003044 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003045
Jamie Madill9b820842015-02-12 10:40:10 -05003046 // Store a bool in the struct if we're at global scope, to allow us to
3047 // skip the local struct scoping workaround in HLSL.
Jamie Madill9b820842015-02-12 10:40:10 -05003048 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003049
Jamie Madill98493dd2013-07-08 14:39:03 -04003050 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003051 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003052 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303053 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3054 if (!symbolTable.declare(userTypeDef))
3055 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003056 error(nameLine, "redefinition", structName->c_str(), "struct");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003057 }
3058 }
3059
3060 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003061 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003062 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003063 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003064 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003065 switch (qualifier)
3066 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003067 case EvqGlobal:
3068 case EvqTemporary:
3069 break;
3070 default:
3071 error(field.line(), "invalid qualifier on struct member",
3072 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003073 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003074 }
Martin Radev70866b82016-07-22 15:27:42 +03003075 if (field.type()->isInvariant())
3076 {
3077 error(field.line(), "invalid qualifier on struct member", "invariant");
3078 }
3079
3080 checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003081 }
3082
Martin Radev4a9cd802016-09-01 16:51:51 +03003083 TTypeSpecifierNonArray typeSpecifierNonArray;
3084 typeSpecifierNonArray.initialize(EbtStruct, structLine);
3085 typeSpecifierNonArray.userDef = structureType;
3086 typeSpecifierNonArray.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003087 exitStructDeclaration();
3088
Martin Radev4a9cd802016-09-01 16:51:51 +03003089 return typeSpecifierNonArray;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003090}
3091
Jamie Madillb98c3a82015-07-23 14:26:04 -04003092TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
3093 TIntermAggregate *statementList,
3094 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003095{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003096 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003097 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003098 init->isVector())
3099 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003100 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3101 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003102 return nullptr;
3103 }
3104
Olli Etuahoac5274d2015-02-20 10:19:08 +02003105 if (statementList)
3106 {
3107 if (!ValidateSwitch::validate(switchType, this, statementList, loc))
3108 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003109 return nullptr;
3110 }
3111 }
3112
Olli Etuahoa3a36662015-02-17 13:46:51 +02003113 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3114 if (node == nullptr)
3115 {
3116 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003117 return nullptr;
3118 }
3119 return node;
3120}
3121
3122TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3123{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003124 if (mSwitchNestingLevel == 0)
3125 {
3126 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003127 return nullptr;
3128 }
3129 if (condition == nullptr)
3130 {
3131 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003132 return nullptr;
3133 }
3134 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003135 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003136 {
3137 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003138 }
3139 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003140 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3141 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3142 // fold in case labels.
3143 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003144 {
3145 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003146 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003147 TIntermCase *node = intermediate.addCase(condition, loc);
3148 if (node == nullptr)
3149 {
3150 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003151 return nullptr;
3152 }
3153 return node;
3154}
3155
3156TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3157{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003158 if (mSwitchNestingLevel == 0)
3159 {
3160 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003161 return nullptr;
3162 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003163 TIntermCase *node = intermediate.addCase(nullptr, loc);
3164 if (node == nullptr)
3165 {
3166 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003167 return nullptr;
3168 }
3169 return node;
3170}
3171
Jamie Madillb98c3a82015-07-23 14:26:04 -04003172TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3173 TIntermTyped *child,
3174 const TSourceLoc &loc,
3175 const TType *funcReturnType)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003176{
3177 if (child == nullptr)
3178 {
3179 return nullptr;
3180 }
3181
3182 switch (op)
3183 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003184 case EOpLogicalNot:
3185 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3186 child->isVector())
3187 {
3188 return nullptr;
3189 }
3190 break;
3191 case EOpBitwiseNot:
3192 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3193 child->isMatrix() || child->isArray())
3194 {
3195 return nullptr;
3196 }
3197 break;
3198 case EOpPostIncrement:
3199 case EOpPreIncrement:
3200 case EOpPostDecrement:
3201 case EOpPreDecrement:
3202 case EOpNegative:
3203 case EOpPositive:
3204 if (child->getBasicType() == EbtStruct || child->getBasicType() == EbtBool ||
Olli Etuaho558b0382016-08-26 17:54:34 +03003205 child->isArray() || IsSampler(child->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -04003206 {
3207 return nullptr;
3208 }
3209 // Operators for built-ins are already type checked against their prototype.
3210 default:
3211 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003212 }
3213
Olli Etuahof119a262016-08-19 15:54:22 +03003214 TIntermUnary *node = new TIntermUnary(op, child);
3215 node->setLine(loc);
Olli Etuahof119a262016-08-19 15:54:22 +03003216
3217 TIntermTyped *foldedNode = node->fold(&mDiagnostics);
3218 if (foldedNode)
3219 return foldedNode;
3220
3221 return node;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003222}
3223
Olli Etuaho09b22472015-02-11 11:47:26 +02003224TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3225{
Olli Etuahof6c694b2015-03-26 14:50:53 +02003226 TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003227 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003228 {
3229 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003230 return child;
3231 }
3232 return node;
3233}
3234
Jamie Madillb98c3a82015-07-23 14:26:04 -04003235TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3236 TIntermTyped *child,
3237 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003238{
Olli Etuaho856c4972016-08-08 11:38:39 +03003239 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003240 return addUnaryMath(op, child, loc);
3241}
3242
Jamie Madillb98c3a82015-07-23 14:26:04 -04003243bool TParseContext::binaryOpCommonCheck(TOperator op,
3244 TIntermTyped *left,
3245 TIntermTyped *right,
3246 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003247{
Olli Etuaho244be012016-08-18 15:26:02 +03003248 if (left->getType().getStruct() || right->getType().getStruct())
3249 {
3250 switch (op)
3251 {
3252 case EOpIndexDirectStruct:
3253 ASSERT(left->getType().getStruct());
3254 break;
3255 case EOpEqual:
3256 case EOpNotEqual:
3257 case EOpAssign:
3258 case EOpInitialize:
3259 if (left->getType() != right->getType())
3260 {
3261 return false;
3262 }
3263 break;
3264 default:
3265 error(loc, "Invalid operation for structs", GetOperatorString(op));
3266 return false;
3267 }
3268 }
3269
Olli Etuahod6b14282015-03-17 14:31:35 +02003270 if (left->isArray() || right->isArray())
3271 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003272 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003273 {
3274 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3275 return false;
3276 }
3277
3278 if (left->isArray() != right->isArray())
3279 {
3280 error(loc, "array / non-array mismatch", GetOperatorString(op));
3281 return false;
3282 }
3283
3284 switch (op)
3285 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003286 case EOpEqual:
3287 case EOpNotEqual:
3288 case EOpAssign:
3289 case EOpInitialize:
3290 break;
3291 default:
3292 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3293 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02003294 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03003295 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02003296 if (left->getArraySize() != right->getArraySize())
3297 {
3298 error(loc, "array size mismatch", GetOperatorString(op));
3299 return false;
3300 }
Olli Etuahod6b14282015-03-17 14:31:35 +02003301 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003302
3303 // Check ops which require integer / ivec parameters
3304 bool isBitShift = false;
3305 switch (op)
3306 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003307 case EOpBitShiftLeft:
3308 case EOpBitShiftRight:
3309 case EOpBitShiftLeftAssign:
3310 case EOpBitShiftRightAssign:
3311 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3312 // check that the basic type is an integer type.
3313 isBitShift = true;
3314 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3315 {
3316 return false;
3317 }
3318 break;
3319 case EOpBitwiseAnd:
3320 case EOpBitwiseXor:
3321 case EOpBitwiseOr:
3322 case EOpBitwiseAndAssign:
3323 case EOpBitwiseXorAssign:
3324 case EOpBitwiseOrAssign:
3325 // It is enough to check the type of only one operand, since later it
3326 // is checked that the operand types match.
3327 if (!IsInteger(left->getBasicType()))
3328 {
3329 return false;
3330 }
3331 break;
3332 default:
3333 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003334 }
3335
3336 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3337 // So the basic type should usually match.
3338 if (!isBitShift && left->getBasicType() != right->getBasicType())
3339 {
3340 return false;
3341 }
3342
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003343 // Check that:
3344 // 1. Type sizes match exactly on ops that require that.
3345 // 2. Restrictions for structs that contain arrays or samplers are respected.
3346 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
Jamie Madillb98c3a82015-07-23 14:26:04 -04003347 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003348 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003349 case EOpAssign:
3350 case EOpInitialize:
3351 case EOpEqual:
3352 case EOpNotEqual:
3353 // ESSL 1.00 sections 5.7, 5.8, 5.9
3354 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
3355 {
3356 error(loc, "undefined operation for structs containing arrays",
3357 GetOperatorString(op));
3358 return false;
3359 }
3360 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3361 // we interpret the spec so that this extends to structs containing samplers,
3362 // similarly to ESSL 1.00 spec.
3363 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
3364 left->getType().isStructureContainingSamplers())
3365 {
3366 error(loc, "undefined operation for structs containing samplers",
3367 GetOperatorString(op));
3368 return false;
3369 }
3370 case EOpLessThan:
3371 case EOpGreaterThan:
3372 case EOpLessThanEqual:
3373 case EOpGreaterThanEqual:
3374 if ((left->getNominalSize() != right->getNominalSize()) ||
3375 (left->getSecondarySize() != right->getSecondarySize()))
3376 {
3377 return false;
3378 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003379 break;
3380 case EOpAdd:
3381 case EOpSub:
3382 case EOpDiv:
3383 case EOpIMod:
3384 case EOpBitShiftLeft:
3385 case EOpBitShiftRight:
3386 case EOpBitwiseAnd:
3387 case EOpBitwiseXor:
3388 case EOpBitwiseOr:
3389 case EOpAddAssign:
3390 case EOpSubAssign:
3391 case EOpDivAssign:
3392 case EOpIModAssign:
3393 case EOpBitShiftLeftAssign:
3394 case EOpBitShiftRightAssign:
3395 case EOpBitwiseAndAssign:
3396 case EOpBitwiseXorAssign:
3397 case EOpBitwiseOrAssign:
3398 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
3399 {
3400 return false;
3401 }
3402
3403 // Are the sizes compatible?
3404 if (left->getNominalSize() != right->getNominalSize() ||
3405 left->getSecondarySize() != right->getSecondarySize())
3406 {
3407 // If the nominal sizes of operands do not match:
3408 // One of them must be a scalar.
3409 if (!left->isScalar() && !right->isScalar())
3410 return false;
3411
3412 // In the case of compound assignment other than multiply-assign,
3413 // the right side needs to be a scalar. Otherwise a vector/matrix
3414 // would be assigned to a scalar. A scalar can't be shifted by a
3415 // vector either.
3416 if (!right->isScalar() &&
3417 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
3418 return false;
3419 }
3420 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003421 default:
3422 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003423 }
3424
Olli Etuahod6b14282015-03-17 14:31:35 +02003425 return true;
3426}
3427
Olli Etuaho1dded802016-08-18 18:13:13 +03003428bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
3429 const TType &left,
3430 const TType &right)
3431{
3432 switch (op)
3433 {
3434 case EOpMul:
3435 case EOpMulAssign:
3436 return left.getNominalSize() == right.getNominalSize() &&
3437 left.getSecondarySize() == right.getSecondarySize();
3438 case EOpVectorTimesScalar:
3439 return true;
3440 case EOpVectorTimesScalarAssign:
3441 ASSERT(!left.isMatrix() && !right.isMatrix());
3442 return left.isVector() && !right.isVector();
3443 case EOpVectorTimesMatrix:
3444 return left.getNominalSize() == right.getRows();
3445 case EOpVectorTimesMatrixAssign:
3446 ASSERT(!left.isMatrix() && right.isMatrix());
3447 return left.isVector() && left.getNominalSize() == right.getRows() &&
3448 left.getNominalSize() == right.getCols();
3449 case EOpMatrixTimesVector:
3450 return left.getCols() == right.getNominalSize();
3451 case EOpMatrixTimesScalar:
3452 return true;
3453 case EOpMatrixTimesScalarAssign:
3454 ASSERT(left.isMatrix() && !right.isMatrix());
3455 return !right.isVector();
3456 case EOpMatrixTimesMatrix:
3457 return left.getCols() == right.getRows();
3458 case EOpMatrixTimesMatrixAssign:
3459 ASSERT(left.isMatrix() && right.isMatrix());
3460 // We need to check two things:
3461 // 1. The matrix multiplication step is valid.
3462 // 2. The result will have the same number of columns as the lvalue.
3463 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
3464
3465 default:
3466 UNREACHABLE();
3467 return false;
3468 }
3469}
3470
Jamie Madillb98c3a82015-07-23 14:26:04 -04003471TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
3472 TIntermTyped *left,
3473 TIntermTyped *right,
3474 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02003475{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003476 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003477 return nullptr;
3478
Olli Etuahofc1806e2015-03-17 13:03:11 +02003479 switch (op)
3480 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003481 case EOpEqual:
3482 case EOpNotEqual:
3483 break;
3484 case EOpLessThan:
3485 case EOpGreaterThan:
3486 case EOpLessThanEqual:
3487 case EOpGreaterThanEqual:
Olli Etuaho244be012016-08-18 15:26:02 +03003488 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3489 !right->getType().getStruct());
3490 if (left->isMatrix() || left->isVector())
Jamie Madillb98c3a82015-07-23 14:26:04 -04003491 {
3492 return nullptr;
3493 }
3494 break;
3495 case EOpLogicalOr:
3496 case EOpLogicalXor:
3497 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03003498 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3499 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003500 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isVector())
3501 {
3502 return nullptr;
3503 }
3504 break;
3505 case EOpAdd:
3506 case EOpSub:
3507 case EOpDiv:
3508 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03003509 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3510 !right->getType().getStruct());
3511 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04003512 {
3513 return nullptr;
3514 }
3515 break;
3516 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03003517 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3518 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003519 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03003520 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04003521 {
3522 return nullptr;
3523 }
3524 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003525 default:
3526 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02003527 }
3528
Olli Etuaho1dded802016-08-18 18:13:13 +03003529 if (op == EOpMul)
3530 {
3531 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
3532 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
3533 {
3534 return nullptr;
3535 }
3536 }
3537
Olli Etuaho3fdec912016-08-18 15:08:06 +03003538 TIntermBinary *node = new TIntermBinary(op, left, right);
3539 node->setLine(loc);
3540
Olli Etuaho3fdec912016-08-18 15:08:06 +03003541 // See if we can fold constants.
3542 TIntermTyped *foldedNode = node->fold(&mDiagnostics);
3543 if (foldedNode)
3544 return foldedNode;
3545
3546 return node;
Olli Etuahofc1806e2015-03-17 13:03:11 +02003547}
3548
Jamie Madillb98c3a82015-07-23 14:26:04 -04003549TIntermTyped *TParseContext::addBinaryMath(TOperator op,
3550 TIntermTyped *left,
3551 TIntermTyped *right,
3552 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003553{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003554 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003555 if (node == 0)
3556 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003557 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3558 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003559 return left;
3560 }
3561 return node;
3562}
3563
Jamie Madillb98c3a82015-07-23 14:26:04 -04003564TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
3565 TIntermTyped *left,
3566 TIntermTyped *right,
3567 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003568{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003569 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003570 if (node == 0)
3571 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003572 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3573 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003574 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02003575 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003576 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
3577 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003578 }
3579 return node;
3580}
3581
Jamie Madillb98c3a82015-07-23 14:26:04 -04003582TIntermTyped *TParseContext::createAssign(TOperator op,
3583 TIntermTyped *left,
3584 TIntermTyped *right,
3585 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003586{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003587 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003588 {
Olli Etuaho1dded802016-08-18 18:13:13 +03003589 if (op == EOpMulAssign)
3590 {
3591 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
3592 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
3593 {
3594 return nullptr;
3595 }
3596 }
Olli Etuaho3fdec912016-08-18 15:08:06 +03003597 TIntermBinary *node = new TIntermBinary(op, left, right);
3598 node->setLine(loc);
3599
Olli Etuaho3fdec912016-08-18 15:08:06 +03003600 return node;
Olli Etuahod6b14282015-03-17 14:31:35 +02003601 }
3602 return nullptr;
3603}
3604
Jamie Madillb98c3a82015-07-23 14:26:04 -04003605TIntermTyped *TParseContext::addAssign(TOperator op,
3606 TIntermTyped *left,
3607 TIntermTyped *right,
3608 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003609{
3610 TIntermTyped *node = createAssign(op, left, right, loc);
3611 if (node == nullptr)
3612 {
3613 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02003614 return left;
3615 }
3616 return node;
3617}
3618
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02003619TIntermTyped *TParseContext::addComma(TIntermTyped *left,
3620 TIntermTyped *right,
3621 const TSourceLoc &loc)
3622{
Corentin Wallez0d959252016-07-12 17:26:32 -04003623 // WebGL2 section 5.26, the following results in an error:
3624 // "Sequence operator applied to void, arrays, or structs containing arrays"
3625 if (mShaderSpec == SH_WEBGL2_SPEC && (left->isArray() || left->getBasicType() == EbtVoid ||
3626 left->getType().isStructureContainingArrays() ||
3627 right->isArray() || right->getBasicType() == EbtVoid ||
3628 right->getType().isStructureContainingArrays()))
3629 {
3630 error(loc,
3631 "sequence operator is not allowed for void, arrays, or structs containing arrays",
3632 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04003633 }
3634
Olli Etuaho15200042015-11-04 16:56:31 +02003635 return intermediate.addComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02003636}
3637
Olli Etuaho49300862015-02-20 14:54:49 +02003638TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
3639{
3640 switch (op)
3641 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003642 case EOpContinue:
3643 if (mLoopNestingLevel <= 0)
3644 {
3645 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003646 }
3647 break;
3648 case EOpBreak:
3649 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
3650 {
3651 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003652 }
3653 break;
3654 case EOpReturn:
3655 if (mCurrentFunctionType->getBasicType() != EbtVoid)
3656 {
3657 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04003658 }
3659 break;
3660 default:
3661 // No checks for discard
3662 break;
Olli Etuaho49300862015-02-20 14:54:49 +02003663 }
3664 return intermediate.addBranch(op, loc);
3665}
3666
Jamie Madillb98c3a82015-07-23 14:26:04 -04003667TIntermBranch *TParseContext::addBranch(TOperator op,
3668 TIntermTyped *returnValue,
3669 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02003670{
3671 ASSERT(op == EOpReturn);
3672 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003673 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02003674 {
3675 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02003676 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003677 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02003678 {
3679 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02003680 }
3681 return intermediate.addBranch(op, returnValue, loc);
3682}
3683
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003684void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
3685{
3686 ASSERT(!functionCall->isUserDefined());
3687 const TString &name = functionCall->getName();
3688 TIntermNode *offset = nullptr;
3689 TIntermSequence *arguments = functionCall->getSequence();
3690 if (name.compare(0, 16, "texelFetchOffset") == 0 ||
3691 name.compare(0, 16, "textureLodOffset") == 0 ||
3692 name.compare(0, 20, "textureProjLodOffset") == 0 ||
3693 name.compare(0, 17, "textureGradOffset") == 0 ||
3694 name.compare(0, 21, "textureProjGradOffset") == 0)
3695 {
3696 offset = arguments->back();
3697 }
3698 else if (name.compare(0, 13, "textureOffset") == 0 ||
3699 name.compare(0, 17, "textureProjOffset") == 0)
3700 {
3701 // A bias parameter might follow the offset parameter.
3702 ASSERT(arguments->size() >= 3);
3703 offset = (*arguments)[2];
3704 }
3705 if (offset != nullptr)
3706 {
3707 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
3708 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
3709 {
3710 TString unmangledName = TFunction::unmangleName(name);
3711 error(functionCall->getLine(), "Texture offset must be a constant expression",
3712 unmangledName.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003713 }
3714 else
3715 {
3716 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
3717 size_t size = offsetConstantUnion->getType().getObjectSize();
3718 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
3719 for (size_t i = 0u; i < size; ++i)
3720 {
3721 int offsetValue = values[i].getIConst();
3722 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
3723 {
3724 std::stringstream tokenStream;
3725 tokenStream << offsetValue;
3726 std::string token = tokenStream.str();
3727 error(offset->getLine(), "Texture offset value out of valid range",
3728 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003729 }
3730 }
3731 }
3732 }
3733}
3734
Jamie Madillb98c3a82015-07-23 14:26:04 -04003735TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
3736 TIntermNode *paramNode,
3737 TIntermNode *thisNode,
3738 const TSourceLoc &loc,
3739 bool *fatalError)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003740{
Jamie Madillb98c3a82015-07-23 14:26:04 -04003741 *fatalError = false;
3742 TOperator op = fnCall->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003743 TIntermTyped *callNode = nullptr;
3744
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003745 if (thisNode != nullptr)
3746 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003747 TConstantUnion *unionArray = new TConstantUnion[1];
Jamie Madillb98c3a82015-07-23 14:26:04 -04003748 int arraySize = 0;
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003749 TIntermTyped *typedThis = thisNode->getAsTyped();
3750 if (fnCall->getName() != "length")
3751 {
3752 error(loc, "invalid method", fnCall->getName().c_str());
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003753 }
3754 else if (paramNode != nullptr)
3755 {
3756 error(loc, "method takes no parameters", "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003757 }
3758 else if (typedThis == nullptr || !typedThis->isArray())
3759 {
3760 error(loc, "length can only be called on arrays", "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003761 }
3762 else
3763 {
Olli Etuaho96e67382015-04-23 14:27:02 +03003764 arraySize = typedThis->getArraySize();
Olli Etuaho39282e12015-04-23 15:41:48 +03003765 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003766 {
Olli Etuaho39282e12015-04-23 15:41:48 +03003767 // This code path can be hit with expressions like these:
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003768 // (a = b).length()
Olli Etuaho39282e12015-04-23 15:41:48 +03003769 // (func()).length()
3770 // (int[3](0, 1, 2)).length()
Jamie Madillb98c3a82015-07-23 14:26:04 -04003771 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
3772 // expression.
3773 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
3774 // spec section 5.9 which allows "An array, vector or matrix expression with the
3775 // length method applied".
3776 error(loc, "length can only be called on array names, not on array expressions",
3777 "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003778 }
3779 }
Olli Etuaho96e67382015-04-23 14:27:02 +03003780 unionArray->setIConst(arraySize);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003781 callNode =
3782 intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03003783 }
3784 else if (op != EOpNull)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003785 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003786 // Then this should be a constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +03003787 callNode = addConstructor(paramNode, op, fnCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003788 }
3789 else
3790 {
3791 //
3792 // Not a constructor. Find it in the symbol table.
3793 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303794 const TFunction *fnCandidate;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003795 bool builtIn;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003796 fnCandidate = findFunction(loc, fnCall, mShaderVersion, &builtIn);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003797 if (fnCandidate)
3798 {
3799 //
3800 // A declared function.
3801 //
Olli Etuaho383b7912016-08-05 11:22:59 +03003802 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003803 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003804 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003805 }
3806 op = fnCandidate->getBuiltInOp();
3807 if (builtIn && op != EOpNull)
3808 {
3809 //
3810 // A function call mapped to a built-in operation.
3811 //
3812 if (fnCandidate->getParamCount() == 1)
3813 {
3814 //
3815 // Treat it like a built-in unary operator.
3816 //
Olli Etuaho15c2ac32015-11-09 15:51:43 +02003817 TIntermAggregate *paramAgg = paramNode->getAsAggregate();
3818 paramNode = paramAgg->getSequence()->front();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003819 callNode = createUnaryMath(op, paramNode->getAsTyped(), loc,
3820 &fnCandidate->getReturnType());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003821 if (callNode == nullptr)
3822 {
3823 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003824 extraInfoStream
3825 << "built in unary operator function. Type: "
3826 << static_cast<TIntermTyped *>(paramNode)->getCompleteString();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003827 std::string extraInfo = extraInfoStream.str();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003828 error(paramNode->getLine(), " wrong operand type", "Internal Error",
3829 extraInfo.c_str());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003830 *fatalError = true;
3831 return nullptr;
3832 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003833 }
3834 else
3835 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003836 TIntermAggregate *aggregate =
3837 intermediate.setAggregateOperator(paramNode, op, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003838 aggregate->setType(fnCandidate->getReturnType());
3839 aggregate->setPrecisionFromChildren();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02003840 if (aggregate->areChildrenConstQualified())
3841 {
3842 aggregate->getTypePointer()->setQualifier(EvqConst);
3843 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003844
3845 // Some built-in functions have out parameters too.
3846 functionCallLValueErrorCheck(fnCandidate, aggregate);
Arun Patole274f0702015-05-05 13:33:30 +05303847
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003848 // See if we can constant fold a built-in. Note that this may be possible even
3849 // if it is not const-qualified.
Olli Etuahof119a262016-08-19 15:54:22 +03003850 TIntermTyped *foldedNode =
3851 intermediate.foldAggregateBuiltIn(aggregate, &mDiagnostics);
Arun Patole274f0702015-05-05 13:33:30 +05303852 if (foldedNode)
3853 {
Arun Patole274f0702015-05-05 13:33:30 +05303854 callNode = foldedNode;
3855 }
Olli Etuahob43846e2015-06-02 18:18:57 +03003856 else
3857 {
3858 callNode = aggregate;
3859 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003860 }
3861 }
3862 else
3863 {
3864 // This is a real function call
Jamie Madillb98c3a82015-07-23 14:26:04 -04003865 TIntermAggregate *aggregate =
3866 intermediate.setAggregateOperator(paramNode, EOpFunctionCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003867 aggregate->setType(fnCandidate->getReturnType());
3868
Jamie Madillb98c3a82015-07-23 14:26:04 -04003869 // this is how we know whether the given function is a builtIn function or a user
3870 // defined function
3871 // if builtIn == false, it's a userDefined -> could be an overloaded
3872 // builtIn function also
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003873 // if builtIn == true, it's definitely a builtIn function with EOpNull
3874 if (!builtIn)
3875 aggregate->setUserDefined();
3876 aggregate->setName(fnCandidate->getMangledName());
Corentin Wallez71d147f2015-02-11 11:15:24 -08003877 aggregate->setFunctionId(fnCandidate->getUniqueId());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003878
3879 // This needs to happen after the name is set
3880 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003881 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003882 aggregate->setBuiltInFunctionPrecision();
3883
Olli Etuahoe1a94c62015-11-16 17:35:25 +02003884 checkTextureOffsetConst(aggregate);
3885 }
3886
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003887 callNode = aggregate;
3888
3889 functionCallLValueErrorCheck(fnCandidate, aggregate);
3890 }
3891 }
3892 else
3893 {
3894 // error message was put out by findFunction()
3895 // Put on a dummy node for error recovery
Jamie Madill6ba6ead2015-05-04 14:21:21 -04003896 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003897 unionArray->setFConst(0.0f);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003898 callNode = intermediate.addConstantUnion(unionArray,
3899 TType(EbtFloat, EbpUndefined, EvqConst), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003900 }
3901 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02003902 return callNode;
3903}
3904
Jamie Madillb98c3a82015-07-23 14:26:04 -04003905TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
Olli Etuahod0bad2c2016-09-09 18:01:16 +03003906 TIntermTyped *trueExpression,
3907 TIntermTyped *falseExpression,
Olli Etuaho52901742015-04-15 13:42:45 +03003908 const TSourceLoc &loc)
3909{
Olli Etuaho856c4972016-08-08 11:38:39 +03003910 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03003911
Olli Etuahod0bad2c2016-09-09 18:01:16 +03003912 if (trueExpression->getType() != falseExpression->getType())
Olli Etuaho52901742015-04-15 13:42:45 +03003913 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +03003914 binaryOpError(loc, ":", trueExpression->getCompleteString(),
3915 falseExpression->getCompleteString());
3916 return falseExpression;
Olli Etuaho52901742015-04-15 13:42:45 +03003917 }
Olli Etuahoa2d53032015-04-15 14:14:44 +03003918 // ESSL1 sections 5.2 and 5.7:
3919 // ESSL3 section 5.7:
3920 // Ternary operator is not among the operators allowed for structures/arrays.
Olli Etuahod0bad2c2016-09-09 18:01:16 +03003921 if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
Olli Etuahoa2d53032015-04-15 14:14:44 +03003922 {
3923 error(loc, "ternary operator is not allowed for structures or arrays", ":");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03003924 return falseExpression;
Olli Etuahoa2d53032015-04-15 14:14:44 +03003925 }
Corentin Wallez0d959252016-07-12 17:26:32 -04003926 // WebGL2 section 5.26, the following results in an error:
3927 // "Ternary operator applied to void, arrays, or structs containing arrays"
Olli Etuahod0bad2c2016-09-09 18:01:16 +03003928 if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
Corentin Wallez0d959252016-07-12 17:26:32 -04003929 {
3930 error(loc, "ternary operator is not allowed for void", ":");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03003931 return falseExpression;
Corentin Wallez0d959252016-07-12 17:26:32 -04003932 }
3933
Olli Etuahod0bad2c2016-09-09 18:01:16 +03003934 return TIntermediate::AddTernarySelection(cond, trueExpression, falseExpression, loc);
Olli Etuaho52901742015-04-15 13:42:45 +03003935}
Olli Etuaho49300862015-02-20 14:54:49 +02003936
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003937//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003938// Parse an array of strings using yyparse.
3939//
3940// Returns 0 for success.
3941//
Jamie Madillb98c3a82015-07-23 14:26:04 -04003942int PaParseStrings(size_t count,
3943 const char *const string[],
3944 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05303945 TParseContext *context)
3946{
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003947 if ((count == 0) || (string == NULL))
3948 return 1;
3949
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003950 if (glslang_initialize(context))
3951 return 1;
3952
alokp@chromium.org408c45e2012-04-05 15:54:43 +00003953 int error = glslang_scan(count, string, length, context);
3954 if (!error)
3955 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003956
alokp@chromium.org73bc2982012-06-19 18:48:05 +00003957 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00003958
alokp@chromium.org6b495712012-06-29 00:06:58 +00003959 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003960}