blob: 258af09cd466996b55093a57102cd90e4331367c [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
Jamie Madill45bcc782016-11-07 13:58:48 -050019namespace sh
20{
21
alokp@chromium.org8b851c62012-06-15 16:25:11 +000022///////////////////////////////////////////////////////////////////////
23//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000024// Sub- vector and matrix fields
25//
26////////////////////////////////////////////////////////////////////////
27
Martin Radev2cc85b32016-08-05 16:22:53 +030028namespace
29{
30
31const int kWebGLMaxStructNesting = 4;
32
33bool ContainsSampler(const TType &type)
34{
35 if (IsSampler(type.getBasicType()))
36 return true;
37
38 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock())
39 {
40 const TFieldList &fields = type.getStruct()->fields();
41 for (unsigned int i = 0; i < fields.size(); ++i)
42 {
43 if (ContainsSampler(*fields[i]->type()))
44 return true;
45 }
46 }
47
48 return false;
49}
50
51bool ContainsImage(const TType &type)
52{
53 if (IsImage(type.getBasicType()))
54 return true;
55
56 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock())
57 {
58 const TFieldList &fields = type.getStruct()->fields();
59 for (unsigned int i = 0; i < fields.size(); ++i)
60 {
61 if (ContainsImage(*fields[i]->type()))
62 return true;
63 }
64 }
65
66 return false;
67}
68
Olli Etuaho485eefd2017-02-14 17:40:06 +000069// Get a token from an image argument to use as an error message token.
70const char *GetImageArgumentToken(TIntermTyped *imageNode)
71{
72 ASSERT(IsImage(imageNode->getBasicType()));
73 while (imageNode->getAsBinaryNode() &&
74 (imageNode->getAsBinaryNode()->getOp() == EOpIndexIndirect ||
75 imageNode->getAsBinaryNode()->getOp() == EOpIndexDirect))
76 {
77 imageNode = imageNode->getAsBinaryNode()->getLeft();
78 }
79 TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode();
80 if (imageSymbol)
81 {
82 return imageSymbol->getSymbol().c_str();
83 }
84 return "image";
85}
86
Martin Radev2cc85b32016-08-05 16:22:53 +030087} // namespace
88
Jamie Madillacb4b812016-11-07 13:50:29 -050089TParseContext::TParseContext(TSymbolTable &symt,
90 TExtensionBehavior &ext,
91 sh::GLenum type,
92 ShShaderSpec spec,
93 ShCompileOptions options,
94 bool checksPrecErrors,
Olli Etuaho77ba4082016-12-16 12:01:18 +000095 TDiagnostics *diagnostics,
Jamie Madillacb4b812016-11-07 13:50:29 -050096 const ShBuiltInResources &resources)
97 : intermediate(),
98 symbolTable(symt),
99 mDeferredSingleDeclarationErrorCheck(false),
100 mShaderType(type),
101 mShaderSpec(spec),
102 mCompileOptions(options),
103 mShaderVersion(100),
104 mTreeRoot(nullptr),
105 mLoopNestingLevel(0),
106 mStructNestingLevel(0),
107 mSwitchNestingLevel(0),
108 mCurrentFunctionType(nullptr),
109 mFunctionReturnsValue(false),
110 mChecksPrecisionErrors(checksPrecErrors),
111 mFragmentPrecisionHighOnESSL1(false),
112 mDefaultMatrixPacking(EmpColumnMajor),
113 mDefaultBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
Olli Etuaho77ba4082016-12-16 12:01:18 +0000114 mDiagnostics(diagnostics),
Jamie Madillacb4b812016-11-07 13:50:29 -0500115 mDirectiveHandler(ext,
Olli Etuaho77ba4082016-12-16 12:01:18 +0000116 *mDiagnostics,
Jamie Madillacb4b812016-11-07 13:50:29 -0500117 mShaderVersion,
118 mShaderType,
119 resources.WEBGL_debug_shader_precision == 1),
Olli Etuaho77ba4082016-12-16 12:01:18 +0000120 mPreprocessor(mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()),
Jamie Madillacb4b812016-11-07 13:50:29 -0500121 mScanner(nullptr),
122 mUsesFragData(false),
123 mUsesFragColor(false),
124 mUsesSecondaryOutputs(false),
125 mMinProgramTexelOffset(resources.MinProgramTexelOffset),
126 mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
Olli Etuaho09b04a22016-12-15 13:30:26 +0000127 mMultiviewAvailable(resources.OVR_multiview == 1),
Jamie Madillacb4b812016-11-07 13:50:29 -0500128 mComputeShaderLocalSizeDeclared(false),
Olli Etuaho09b04a22016-12-15 13:30:26 +0000129 mNumViews(-1),
130 mMaxNumViews(resources.MaxViewsOVR),
Olli Etuaho43364892017-02-13 16:00:12 +0000131 mMaxImageUnits(resources.MaxImageUnits),
132 mMaxCombinedTextureImageUnits(resources.MaxCombinedTextureImageUnits),
Jamie Madillacb4b812016-11-07 13:50:29 -0500133 mDeclaringFunction(false)
134{
135 mComputeShaderLocalSize.fill(-1);
136}
137
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138//
139// Look at a '.' field selector string and change it into offsets
140// for a vector.
141//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400142bool TParseContext::parseVectorFields(const TString &compString,
143 int vecSize,
144 TVectorFields &fields,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530145 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000146{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400147 fields.num = (int)compString.size();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530148 if (fields.num > 4)
149 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000150 error(line, "illegal vector field selection", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000151 return false;
152 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000153
Jamie Madillb98c3a82015-07-23 14:26:04 -0400154 enum
155 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000156 exyzw,
157 ergba,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000158 estpq
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000159 } fieldSet[4];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000160
Arun Patole7e7e68d2015-05-22 12:02:25 +0530161 for (int i = 0; i < fields.num; ++i)
162 {
163 switch (compString[i])
164 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400165 case 'x':
166 fields.offsets[i] = 0;
167 fieldSet[i] = exyzw;
168 break;
169 case 'r':
170 fields.offsets[i] = 0;
171 fieldSet[i] = ergba;
172 break;
173 case 's':
174 fields.offsets[i] = 0;
175 fieldSet[i] = estpq;
176 break;
177 case 'y':
178 fields.offsets[i] = 1;
179 fieldSet[i] = exyzw;
180 break;
181 case 'g':
182 fields.offsets[i] = 1;
183 fieldSet[i] = ergba;
184 break;
185 case 't':
186 fields.offsets[i] = 1;
187 fieldSet[i] = estpq;
188 break;
189 case 'z':
190 fields.offsets[i] = 2;
191 fieldSet[i] = exyzw;
192 break;
193 case 'b':
194 fields.offsets[i] = 2;
195 fieldSet[i] = ergba;
196 break;
197 case 'p':
198 fields.offsets[i] = 2;
199 fieldSet[i] = estpq;
200 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530201
Jamie Madillb98c3a82015-07-23 14:26:04 -0400202 case 'w':
203 fields.offsets[i] = 3;
204 fieldSet[i] = exyzw;
205 break;
206 case 'a':
207 fields.offsets[i] = 3;
208 fieldSet[i] = ergba;
209 break;
210 case 'q':
211 fields.offsets[i] = 3;
212 fieldSet[i] = estpq;
213 break;
214 default:
215 error(line, "illegal vector field selection", compString.c_str());
216 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000217 }
218 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219
Arun Patole7e7e68d2015-05-22 12:02:25 +0530220 for (int i = 0; i < fields.num; ++i)
221 {
222 if (fields.offsets[i] >= vecSize)
223 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400224 error(line, "vector field selection out of range", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000225 return false;
226 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000227
Arun Patole7e7e68d2015-05-22 12:02:25 +0530228 if (i > 0)
229 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400230 if (fieldSet[i] != fieldSet[i - 1])
Arun Patole7e7e68d2015-05-22 12:02:25 +0530231 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400232 error(line, "illegal - vector component fields not from the same set",
233 compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000234 return false;
235 }
236 }
237 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000238
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000239 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240}
241
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242///////////////////////////////////////////////////////////////////////
243//
244// Errors
245//
246////////////////////////////////////////////////////////////////////////
247
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000248//
249// Used by flex/bison to output all syntax and parsing errors.
250//
Olli Etuaho4de340a2016-12-16 09:32:03 +0000251void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000253 mDiagnostics->error(loc, reason, token);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000254}
255
Olli Etuaho4de340a2016-12-16 09:32:03 +0000256void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530257{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000258 mDiagnostics->warning(loc, reason, token);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +0000259}
260
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200261void TParseContext::outOfRangeError(bool isError,
262 const TSourceLoc &loc,
263 const char *reason,
Olli Etuaho4de340a2016-12-16 09:32:03 +0000264 const char *token)
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200265{
266 if (isError)
267 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000268 error(loc, reason, token);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200269 }
270 else
271 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000272 warning(loc, reason, token);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200273 }
274}
275
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000276//
277// Same error message for all places assignments don't work.
278//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530279void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000280{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000281 std::stringstream reasonStream;
282 reasonStream << "cannot convert from '" << right << "' to '" << left << "'";
283 std::string reason = reasonStream.str();
284 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000285}
286
287//
288// Same error message for all places unary operations don't work.
289//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530290void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000291{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000292 std::stringstream reasonStream;
293 reasonStream << "wrong operand type - no operation '" << op
294 << "' exists that takes an operand of type " << operand
295 << " (or there is no acceptable conversion)";
296 std::string reason = reasonStream.str();
297 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000298}
299
300//
301// Same error message for all binary operations don't work.
302//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400303void TParseContext::binaryOpError(const TSourceLoc &line,
304 const char *op,
305 TString left,
306 TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000307{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000308 std::stringstream reasonStream;
309 reasonStream << "wrong operand types - no operation '" << op
310 << "' exists that takes a left-hand operand of type '" << left
311 << "' and a right operand of type '" << right
312 << "' (or there is no acceptable conversion)";
313 std::string reason = reasonStream.str();
314 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000315}
316
Olli Etuaho856c4972016-08-08 11:38:39 +0300317void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
318 TPrecision precision,
319 TBasicType type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530320{
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400321 if (!mChecksPrecisionErrors)
Olli Etuaho383b7912016-08-05 11:22:59 +0300322 return;
Martin Radev70866b82016-07-22 15:27:42 +0300323
324 if (precision != EbpUndefined && !SupportsPrecision(type))
325 {
326 error(line, "illegal type for precision qualifier", getBasicString(type));
327 }
328
Olli Etuaho183d7e22015-11-20 15:59:09 +0200329 if (precision == EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530330 {
Olli Etuaho183d7e22015-11-20 15:59:09 +0200331 switch (type)
332 {
333 case EbtFloat:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400334 error(line, "No precision specified for (float)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300335 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200336 case EbtInt:
337 case EbtUInt:
338 UNREACHABLE(); // there's always a predeclared qualifier
Jamie Madillb98c3a82015-07-23 14:26:04 -0400339 error(line, "No precision specified (int)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300340 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200341 default:
342 if (IsSampler(type))
343 {
344 error(line, "No precision specified (sampler)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300345 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200346 }
Martin Radev2cc85b32016-08-05 16:22:53 +0300347 if (IsImage(type))
348 {
349 error(line, "No precision specified (image)", "");
350 return;
351 }
Olli Etuaho183d7e22015-11-20 15:59:09 +0200352 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000353 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000354}
355
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000356// Both test and if necessary, spit out an error, to see if the node is really
357// an l-value that can be operated on this way.
Olli Etuaho856c4972016-08-08 11:38:39 +0300358bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000359{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500360 TIntermSymbol *symNode = node->getAsSymbolNode();
361 TIntermBinary *binaryNode = node->getAsBinaryNode();
Olli Etuahob6fa0432016-09-28 16:28:05 +0100362 TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
363
364 if (swizzleNode)
365 {
366 bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
367 if (ok && swizzleNode->hasDuplicateOffsets())
368 {
369 error(line, " l-value of swizzle cannot have duplicate components", op);
370 return false;
371 }
372 return ok;
373 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000374
Arun Patole7e7e68d2015-05-22 12:02:25 +0530375 if (binaryNode)
376 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400377 switch (binaryNode->getOp())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530378 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400379 case EOpIndexDirect:
380 case EOpIndexIndirect:
381 case EOpIndexDirectStruct:
382 case EOpIndexDirectInterfaceBlock:
Olli Etuaho856c4972016-08-08 11:38:39 +0300383 return checkCanBeLValue(line, op, binaryNode->getLeft());
Jamie Madillb98c3a82015-07-23 14:26:04 -0400384 default:
385 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000386 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000387 error(line, " l-value required", op);
Olli Etuaho8a176262016-08-16 14:23:01 +0300388 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000389 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000390
Arun Patole7e7e68d2015-05-22 12:02:25 +0530391 const char *message = 0;
392 switch (node->getQualifier())
393 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400394 case EvqConst:
395 message = "can't modify a const";
396 break;
397 case EvqConstReadOnly:
398 message = "can't modify a const";
399 break;
400 case EvqAttribute:
401 message = "can't modify an attribute";
402 break;
403 case EvqFragmentIn:
404 message = "can't modify an input";
405 break;
406 case EvqVertexIn:
407 message = "can't modify an input";
408 break;
409 case EvqUniform:
410 message = "can't modify a uniform";
411 break;
412 case EvqVaryingIn:
413 message = "can't modify a varying";
414 break;
415 case EvqFragCoord:
416 message = "can't modify gl_FragCoord";
417 break;
418 case EvqFrontFacing:
419 message = "can't modify gl_FrontFacing";
420 break;
421 case EvqPointCoord:
422 message = "can't modify gl_PointCoord";
423 break;
Martin Radevb0883602016-08-04 17:48:58 +0300424 case EvqNumWorkGroups:
425 message = "can't modify gl_NumWorkGroups";
426 break;
427 case EvqWorkGroupSize:
428 message = "can't modify gl_WorkGroupSize";
429 break;
430 case EvqWorkGroupID:
431 message = "can't modify gl_WorkGroupID";
432 break;
433 case EvqLocalInvocationID:
434 message = "can't modify gl_LocalInvocationID";
435 break;
436 case EvqGlobalInvocationID:
437 message = "can't modify gl_GlobalInvocationID";
438 break;
439 case EvqLocalInvocationIndex:
440 message = "can't modify gl_LocalInvocationIndex";
441 break;
Martin Radev802abe02016-08-04 17:48:32 +0300442 case EvqComputeIn:
443 message = "can't modify work group size variable";
444 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400445 default:
446 //
447 // Type that can't be written to?
448 //
449 if (node->getBasicType() == EbtVoid)
450 {
451 message = "can't modify void";
452 }
453 if (IsSampler(node->getBasicType()))
454 {
455 message = "can't modify a sampler";
456 }
Martin Radev2cc85b32016-08-05 16:22:53 +0300457 if (IsImage(node->getBasicType()))
458 {
459 message = "can't modify an image";
460 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000461 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000462
Arun Patole7e7e68d2015-05-22 12:02:25 +0530463 if (message == 0 && binaryNode == 0 && symNode == 0)
464 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000465 error(line, "l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000466
Olli Etuaho8a176262016-08-16 14:23:01 +0300467 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000468 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000469
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000470 //
471 // Everything else is okay, no error.
472 //
473 if (message == 0)
Olli Etuaho8a176262016-08-16 14:23:01 +0300474 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000475
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000476 //
477 // If we get here, we have an error and a message.
478 //
Arun Patole7e7e68d2015-05-22 12:02:25 +0530479 if (symNode)
480 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000481 const char *symbol = symNode->getSymbol().c_str();
482 std::stringstream reasonStream;
483 reasonStream << "l-value required (" << message << " \"" << symbol << "\")";
484 std::string reason = reasonStream.str();
485 error(line, reason.c_str(), op);
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000486 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530487 else
488 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000489 std::stringstream reasonStream;
490 reasonStream << "l-value required (" << message << ")";
491 std::string reason = reasonStream.str();
492 error(line, reason.c_str(), op);
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000493 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000494
Olli Etuaho8a176262016-08-16 14:23:01 +0300495 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000496}
497
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000498// Both test, and if necessary spit out an error, to see if the node is really
499// a constant.
Olli Etuaho856c4972016-08-08 11:38:39 +0300500void TParseContext::checkIsConst(TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000501{
Olli Etuaho383b7912016-08-05 11:22:59 +0300502 if (node->getQualifier() != EvqConst)
503 {
504 error(node->getLine(), "constant expression required", "");
505 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000506}
507
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508// Both test, and if necessary spit out an error, to see if the node is really
509// an integer.
Olli Etuaho856c4972016-08-08 11:38:39 +0300510void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000511{
Olli Etuaho383b7912016-08-05 11:22:59 +0300512 if (!node->isScalarInt())
513 {
514 error(node->getLine(), "integer expression required", token);
515 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000516}
517
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000518// Both test, and if necessary spit out an error, to see if we are currently
519// globally scoped.
Qiankun Miaof69682b2016-08-16 14:50:42 +0800520bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000521{
Olli Etuaho856c4972016-08-08 11:38:39 +0300522 if (!symbolTable.atGlobalLevel())
Olli Etuaho383b7912016-08-05 11:22:59 +0300523 {
524 error(line, "only allowed at global scope", token);
Qiankun Miaof69682b2016-08-16 14:50:42 +0800525 return false;
Olli Etuaho383b7912016-08-05 11:22:59 +0300526 }
Qiankun Miaof69682b2016-08-16 14:50:42 +0800527 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000528}
529
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000530// For now, keep it simple: if it starts "gl_", it's reserved, independent
531// of scope. Except, if the symbol table is at the built-in push-level,
532// which is when we are parsing built-ins.
alokp@chromium.org613ef312010-07-21 18:54:22 +0000533// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
534// webgl shader.
Olli Etuaho856c4972016-08-08 11:38:39 +0300535bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000536{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530537 static const char *reservedErrMsg = "reserved built-in name";
538 if (!symbolTable.atBuiltInLevel())
539 {
540 if (identifier.compare(0, 3, "gl_") == 0)
541 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000542 error(line, reservedErrMsg, "gl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300543 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000544 }
Jamie Madillacb4b812016-11-07 13:50:29 -0500545 if (sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530546 {
547 if (identifier.compare(0, 6, "webgl_") == 0)
548 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000549 error(line, reservedErrMsg, "webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300550 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000551 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530552 if (identifier.compare(0, 7, "_webgl_") == 0)
553 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000554 error(line, reservedErrMsg, "_webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300555 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000556 }
557 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530558 if (identifier.find("__") != TString::npos)
559 {
560 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400561 "identifiers containing two consecutive underscores (__) are reserved as "
562 "possible future keywords",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530563 identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300564 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000565 }
566 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000567
Olli Etuaho8a176262016-08-16 14:23:01 +0300568 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000569}
570
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000571// Make sure there is enough data provided to the constructor to build
572// something of the type of the constructor. Also returns the type of
573// the constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +0300574bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800575 const TIntermSequence *arguments,
Olli Etuaho856c4972016-08-08 11:38:39 +0300576 TOperator op,
577 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000578{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000579 bool constructingMatrix = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400580 switch (op)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530581 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400582 case EOpConstructMat2:
583 case EOpConstructMat2x3:
584 case EOpConstructMat2x4:
585 case EOpConstructMat3x2:
586 case EOpConstructMat3:
587 case EOpConstructMat3x4:
588 case EOpConstructMat4x2:
589 case EOpConstructMat4x3:
590 case EOpConstructMat4:
591 constructingMatrix = true;
592 break;
593 default:
594 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000595 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000596
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000597 //
598 // Note: It's okay to have too many components available, but not okay to have unused
599 // arguments. 'full' will go to true when enough args have been seen. If we loop
600 // again, there is an extra argument, so 'overfull' will become true.
601 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000602
Jamie Madillb98c3a82015-07-23 14:26:04 -0400603 size_t size = 0;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400604 bool full = false;
605 bool overFull = false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000606 bool matrixInMatrix = false;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500607 bool arrayArg = false;
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800608 for (TIntermNode *arg : *arguments)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530609 {
Olli Etuaho72d10202017-01-19 15:58:30 +0000610 const TIntermTyped *argTyped = arg->getAsTyped();
611 size += argTyped->getType().getObjectSize();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530612
Olli Etuaho72d10202017-01-19 15:58:30 +0000613 if (constructingMatrix && argTyped->getType().isMatrix())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000614 matrixInMatrix = true;
615 if (full)
616 overFull = true;
Olli Etuaho856c4972016-08-08 11:38:39 +0300617 if (op != EOpConstructStruct && !type.isArray() && size >= type.getObjectSize())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000618 full = true;
Olli Etuaho72d10202017-01-19 15:58:30 +0000619 if (argTyped->getType().isArray())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000620 arrayArg = true;
621 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530622
Olli Etuaho856c4972016-08-08 11:38:39 +0300623 if (type.isArray())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300624 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300625 // The size of an unsized constructor should already have been determined.
626 ASSERT(!type.isUnsizedArray());
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800627 if (static_cast<size_t>(type.getArraySize()) != arguments->size())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300628 {
629 error(line, "array constructor needs one argument per array element", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300630 return false;
Olli Etuaho376f1b52015-04-13 13:23:41 +0300631 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000632 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000633
Arun Patole7e7e68d2015-05-22 12:02:25 +0530634 if (arrayArg && op != EOpConstructStruct)
635 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000636 error(line, "constructing from a non-dereferenced array", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300637 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000638 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000639
Olli Etuaho856c4972016-08-08 11:38:39 +0300640 if (matrixInMatrix && !type.isArray())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530641 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800642 if (arguments->size() != 1)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530643 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400644 error(line, "constructing matrix from matrix can only take one argument",
645 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300646 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000647 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000648 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000649
Arun Patole7e7e68d2015-05-22 12:02:25 +0530650 if (overFull)
651 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000652 error(line, "too many arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300653 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000654 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530655
Olli Etuaho856c4972016-08-08 11:38:39 +0300656 if (op == EOpConstructStruct && !type.isArray() &&
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800657 type.getStruct()->fields().size() != arguments->size())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530658 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400659 error(line,
660 "Number of constructor parameters does not match the number of structure fields",
661 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300662 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000663 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000664
Olli Etuaho856c4972016-08-08 11:38:39 +0300665 if (!type.isMatrix() || !matrixInMatrix)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530666 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300667 if ((op != EOpConstructStruct && size != 1 && size < type.getObjectSize()) ||
668 (op == EOpConstructStruct && size < type.getObjectSize()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530669 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000670 error(line, "not enough data provided for construction", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300671 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000672 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000673 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000674
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800675 if (arguments->empty())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530676 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200677 error(line, "constructor does not have any arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300678 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000679 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200680
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800681 for (TIntermNode *const &argNode : *arguments)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530682 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200683 TIntermTyped *argTyped = argNode->getAsTyped();
684 ASSERT(argTyped != nullptr);
685 if (op != EOpConstructStruct && IsSampler(argTyped->getBasicType()))
686 {
687 error(line, "cannot convert a sampler", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300688 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200689 }
Martin Radev2cc85b32016-08-05 16:22:53 +0300690 if (op != EOpConstructStruct && IsImage(argTyped->getBasicType()))
691 {
692 error(line, "cannot convert an image", "constructor");
693 return false;
694 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200695 if (argTyped->getBasicType() == EbtVoid)
696 {
697 error(line, "cannot convert a void", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300698 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200699 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000700 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000701
Olli Etuaho856c4972016-08-08 11:38:39 +0300702 if (type.isArray())
703 {
704 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
705 // the array.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800706 for (TIntermNode *const &argNode : *arguments)
Olli Etuaho856c4972016-08-08 11:38:39 +0300707 {
708 const TType &argType = argNode->getAsTyped()->getType();
Jamie Madill34bf2d92017-02-06 13:40:59 -0500709 // It has already been checked that the argument is not an array, but we can arrive
710 // here due to prior error conditions.
711 if (argType.isArray())
712 {
713 return false;
714 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300715 if (!argType.sameElementType(type))
716 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000717 error(line, "Array constructor argument has an incorrect type", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300718 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300719 }
720 }
721 }
722 else if (op == EOpConstructStruct)
723 {
724 const TFieldList &fields = type.getStruct()->fields();
Olli Etuaho856c4972016-08-08 11:38:39 +0300725
726 for (size_t i = 0; i < fields.size(); i++)
727 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800728 if (i >= arguments->size() ||
729 (*arguments)[i]->getAsTyped()->getType() != *fields[i]->type())
Olli Etuaho856c4972016-08-08 11:38:39 +0300730 {
731 error(line, "Structure constructor arguments do not match structure fields",
Olli Etuaho4de340a2016-12-16 09:32:03 +0000732 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300733 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300734 }
735 }
736 }
737
Olli Etuaho8a176262016-08-16 14:23:01 +0300738 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000739}
740
Jamie Madillb98c3a82015-07-23 14:26:04 -0400741// This function checks to see if a void variable has been declared and raise an error message for
742// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000743//
744// returns true in case of an error
745//
Olli Etuaho856c4972016-08-08 11:38:39 +0300746bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400747 const TString &identifier,
748 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000749{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300750 if (type == EbtVoid)
751 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000752 error(line, "illegal use of type 'void'", identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300753 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300754 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000755
Olli Etuaho8a176262016-08-16 14:23:01 +0300756 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000757}
758
Jamie Madillb98c3a82015-07-23 14:26:04 -0400759// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300760// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300761void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000762{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530763 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
764 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000765 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530766 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000767}
768
Jamie Madillb98c3a82015-07-23 14:26:04 -0400769// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300770// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300771void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000772{
Martin Radev4a9cd802016-09-01 16:51:51 +0300773 if (pType.getBasicType() != EbtBool || pType.isAggregate())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530774 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000775 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530776 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000777}
778
Olli Etuaho856c4972016-08-08 11:38:39 +0300779bool TParseContext::checkIsNotSampler(const TSourceLoc &line,
Martin Radev4a9cd802016-09-01 16:51:51 +0300780 const TTypeSpecifierNonArray &pType,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400781 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000782{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530783 if (pType.type == EbtStruct)
784 {
Martin Radev2cc85b32016-08-05 16:22:53 +0300785 if (ContainsSampler(*pType.userDef))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530786 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000787 std::stringstream reasonStream;
788 reasonStream << reason << " (structure contains a sampler)";
789 std::string reasonStr = reasonStream.str();
790 error(line, reasonStr.c_str(), getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300791 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000792 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530793
Olli Etuaho8a176262016-08-16 14:23:01 +0300794 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530795 }
796 else if (IsSampler(pType.type))
797 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000798 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300799 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000800 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000801
Olli Etuaho8a176262016-08-16 14:23:01 +0300802 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000803}
804
Martin Radev2cc85b32016-08-05 16:22:53 +0300805bool TParseContext::checkIsNotImage(const TSourceLoc &line,
806 const TTypeSpecifierNonArray &pType,
807 const char *reason)
808{
809 if (pType.type == EbtStruct)
810 {
811 if (ContainsImage(*pType.userDef))
812 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000813 std::stringstream reasonStream;
814 reasonStream << reason << " (structure contains an image)";
815 std::string reasonStr = reasonStream.str();
816 error(line, reasonStr.c_str(), getBasicString(pType.type));
Martin Radev2cc85b32016-08-05 16:22:53 +0300817
818 return false;
819 }
820
821 return true;
822 }
823 else if (IsImage(pType.type))
824 {
825 error(line, reason, getBasicString(pType.type));
826
827 return false;
828 }
829
830 return true;
831}
832
Olli Etuaho856c4972016-08-08 11:38:39 +0300833void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
834 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400835{
836 if (pType.layoutQualifier.location != -1)
837 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400838 error(line, "location must only be specified for a single input or output variable",
839 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400840 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400841}
842
Olli Etuaho856c4972016-08-08 11:38:39 +0300843void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
844 const TLayoutQualifier &layoutQualifier)
845{
846 if (layoutQualifier.location != -1)
847 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000848 error(location, "invalid layout qualifier: only valid on program inputs and outputs",
849 "location");
Olli Etuaho856c4972016-08-08 11:38:39 +0300850 }
851}
852
Martin Radev2cc85b32016-08-05 16:22:53 +0300853void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
854 TQualifier qualifier,
855 const TType &type)
856{
857 checkOutParameterIsNotSampler(line, qualifier, type);
858 checkOutParameterIsNotImage(line, qualifier, type);
859}
860
Olli Etuaho856c4972016-08-08 11:38:39 +0300861void TParseContext::checkOutParameterIsNotSampler(const TSourceLoc &line,
862 TQualifier qualifier,
863 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000864{
Martin Radev2cc85b32016-08-05 16:22:53 +0300865 ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
866 if (IsSampler(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530867 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000868 error(line, "samplers cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000869 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000870}
871
Martin Radev2cc85b32016-08-05 16:22:53 +0300872void TParseContext::checkOutParameterIsNotImage(const TSourceLoc &line,
873 TQualifier qualifier,
874 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000875{
Martin Radev2cc85b32016-08-05 16:22:53 +0300876 ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
877 if (IsImage(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530878 {
Martin Radev2cc85b32016-08-05 16:22:53 +0300879 error(line, "images cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000880 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000881}
882
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000883// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300884unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000885{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530886 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000887
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200888 // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
889 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
890 // fold as array size.
891 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000892 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000893 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300894 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000895 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000896
Olli Etuaho856c4972016-08-08 11:38:39 +0300897 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400898
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000899 if (constant->getBasicType() == EbtUInt)
900 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300901 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000902 }
903 else
904 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300905 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000906
Olli Etuaho856c4972016-08-08 11:38:39 +0300907 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000908 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400909 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300910 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000911 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400912
Olli Etuaho856c4972016-08-08 11:38:39 +0300913 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -0400914 }
915
Olli Etuaho856c4972016-08-08 11:38:39 +0300916 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -0400917 {
918 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300919 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400920 }
921
922 // The size of arrays is restricted here to prevent issues further down the
923 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
924 // 4096 registers so this should be reasonable even for aggressively optimizable code.
925 const unsigned int sizeLimit = 65536;
926
Olli Etuaho856c4972016-08-08 11:38:39 +0300927 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -0400928 {
929 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300930 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000931 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300932
933 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000934}
935
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000936// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +0300937bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
938 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000939{
Olli Etuaho8a176262016-08-16 14:23:01 +0300940 if ((elementQualifier.qualifier == EvqAttribute) ||
941 (elementQualifier.qualifier == EvqVertexIn) ||
942 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +0300943 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400944 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300945 TType(elementQualifier).getQualifierString());
946 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000947 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000948
Olli Etuaho8a176262016-08-16 14:23:01 +0300949 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000950}
951
Olli Etuaho8a176262016-08-16 14:23:01 +0300952// See if this element type can be formed into an array.
953bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000954{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000955 //
956 // Can the type be an array?
957 //
Olli Etuaho8a176262016-08-16 14:23:01 +0300958 if (elementType.array)
Jamie Madill06145232015-05-13 13:10:01 -0400959 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300960 error(line, "cannot declare arrays of arrays",
961 TType(elementType).getCompleteString().c_str());
962 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000963 }
Olli Etuahocc36b982015-07-10 14:14:18 +0300964 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
965 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
966 // 4.3.4).
Martin Radev4a9cd802016-09-01 16:51:51 +0300967 if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
Olli Etuaho8a176262016-08-16 14:23:01 +0300968 sh::IsVarying(elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +0300969 {
970 error(line, "cannot declare arrays of structs of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300971 TType(elementType).getCompleteString().c_str());
972 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +0300973 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000974
Olli Etuaho8a176262016-08-16 14:23:01 +0300975 return true;
976}
977
978// Check if this qualified element type can be formed into an array.
979bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
980 const TPublicType &elementType)
981{
982 if (checkIsValidTypeForArray(indexLocation, elementType))
983 {
984 return checkIsValidQualifierForArray(indexLocation, elementType);
985 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000986 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000987}
988
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000989// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +0300990void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
991 const TString &identifier,
992 TPublicType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000993{
Olli Etuaho3739d232015-04-08 12:23:44 +0300994 ASSERT(type != nullptr);
995 if (type->qualifier == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000996 {
997 // Make the qualifier make sense.
Olli Etuaho3739d232015-04-08 12:23:44 +0300998 type->qualifier = EvqTemporary;
999
1000 // Generate informative error messages for ESSL1.
1001 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001002 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +00001003 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05301004 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001005 "structures containing arrays may not be declared constant since they cannot be "
1006 "initialized",
Arun Patole7e7e68d2015-05-22 12:02:25 +05301007 identifier.c_str());
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +00001008 }
1009 else
1010 {
1011 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
1012 }
Olli Etuaho383b7912016-08-05 11:22:59 +03001013 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001014 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03001015 if (type->isUnsizedArray())
1016 {
1017 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
Olli Etuaho376f1b52015-04-13 13:23:41 +03001018 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001019}
1020
Olli Etuaho2935c582015-04-08 14:32:06 +03001021// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001022// and update the symbol table.
1023//
Olli Etuaho2935c582015-04-08 14:32:06 +03001024// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001025//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001026bool TParseContext::declareVariable(const TSourceLoc &line,
1027 const TString &identifier,
1028 const TType &type,
Olli Etuaho2935c582015-04-08 14:32:06 +03001029 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001030{
Olli Etuaho2935c582015-04-08 14:32:06 +03001031 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001032
Olli Etuaho43364892017-02-13 16:00:12 +00001033 checkBindingIsValid(line, type);
1034
Olli Etuaho856c4972016-08-08 11:38:39 +03001035 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001036
Olli Etuaho2935c582015-04-08 14:32:06 +03001037 // gl_LastFragData may be redeclared with a new precision qualifier
1038 if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
1039 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001040 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
1041 symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Olli Etuaho856c4972016-08-08 11:38:39 +03001042 if (static_cast<int>(type.getArraySize()) == maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +03001043 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001044 if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +03001045 {
Olli Etuaho8a176262016-08-16 14:23:01 +03001046 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
Olli Etuaho2935c582015-04-08 14:32:06 +03001047 }
1048 }
1049 else
1050 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001051 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
1052 identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +03001053 return false;
1054 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001055 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001056
Olli Etuaho8a176262016-08-16 14:23:01 +03001057 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +03001058 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001059
Olli Etuaho2935c582015-04-08 14:32:06 +03001060 (*variable) = new TVariable(&identifier, type);
1061 if (!symbolTable.declare(*variable))
1062 {
1063 error(line, "redefinition", identifier.c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -04001064 *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +03001065 return false;
1066 }
1067
Olli Etuaho8a176262016-08-16 14:23:01 +03001068 if (!checkIsNonVoid(line, identifier, type.getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +03001069 return false;
1070
1071 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001072}
1073
Martin Radev70866b82016-07-22 15:27:42 +03001074void TParseContext::checkIsParameterQualifierValid(
1075 const TSourceLoc &line,
1076 const TTypeQualifierBuilder &typeQualifierBuilder,
1077 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301078{
Olli Etuaho77ba4082016-12-16 12:01:18 +00001079 TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03001080
1081 if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301082 {
Martin Radev2cc85b32016-08-05 16:22:53 +03001083 checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type);
1084 }
1085
1086 if (!IsImage(type->getBasicType()))
1087 {
Olli Etuaho43364892017-02-13 16:00:12 +00001088 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line);
Martin Radev2cc85b32016-08-05 16:22:53 +03001089 }
1090 else
1091 {
1092 type->setMemoryQualifier(typeQualifier.memoryQualifier);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001093 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001094
Martin Radev70866b82016-07-22 15:27:42 +03001095 type->setQualifier(typeQualifier.qualifier);
1096
1097 if (typeQualifier.precision != EbpUndefined)
1098 {
1099 type->setPrecision(typeQualifier.precision);
1100 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001101}
1102
Olli Etuaho856c4972016-08-08 11:38:39 +03001103bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001104{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001105 const TExtensionBehavior &extBehavior = extensionBehavior();
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001106 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
Arun Patole7e7e68d2015-05-22 12:02:25 +05301107 if (iter == extBehavior.end())
1108 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001109 error(line, "extension is not supported", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001110 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001111 }
zmo@google.comf5450912011-09-09 01:37:19 +00001112 // In GLSL ES, an extension's default behavior is "disable".
Arun Patole7e7e68d2015-05-22 12:02:25 +05301113 if (iter->second == EBhDisable || iter->second == EBhUndefined)
1114 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00001115 // TODO(oetuaho@nvidia.com): This is slightly hacky. Might be better if symbols could be
1116 // associated with more than one extension.
1117 if (extension == "GL_OVR_multiview")
1118 {
1119 return checkCanUseExtension(line, "GL_OVR_multiview2");
1120 }
Olli Etuaho4de340a2016-12-16 09:32:03 +00001121 error(line, "extension is disabled", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001122 return false;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001123 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301124 if (iter->second == EBhWarn)
1125 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001126 warning(line, "extension is being used", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001127 return true;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001128 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001129
Olli Etuaho8a176262016-08-16 14:23:01 +03001130 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001131}
1132
Martin Radevb8b01222016-11-20 23:25:53 +02001133void TParseContext::emptyDeclarationErrorCheck(const TPublicType &publicType,
1134 const TSourceLoc &location)
1135{
1136 if (publicType.isUnsizedArray())
1137 {
1138 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1139 // error. It is assumed that this applies to empty declarations as well.
1140 error(location, "empty array declaration needs to specify a size", "");
1141 }
1142 if (publicType.qualifier == EvqShared && !publicType.layoutQualifier.isEmpty())
1143 {
1144 error(location, "Shared memory declarations cannot have layout specified", "layout");
1145 }
1146}
1147
Jamie Madillb98c3a82015-07-23 14:26:04 -04001148// These checks are common for all declarations starting a declarator list, and declarators that
1149// follow an empty declaration.
Olli Etuaho383b7912016-08-05 11:22:59 +03001150void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001151 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -04001152{
Olli Etuahofa33d582015-04-09 14:33:12 +03001153 switch (publicType.qualifier)
1154 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001155 case EvqVaryingIn:
1156 case EvqVaryingOut:
1157 case EvqAttribute:
1158 case EvqVertexIn:
1159 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +03001160 case EvqComputeIn:
Martin Radev4a9cd802016-09-01 16:51:51 +03001161 if (publicType.getBasicType() == EbtStruct)
Jamie Madillb98c3a82015-07-23 14:26:04 -04001162 {
1163 error(identifierLocation, "cannot be used with a structure",
1164 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +03001165 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001166 }
Olli Etuahofa33d582015-04-09 14:33:12 +03001167
Jamie Madillb98c3a82015-07-23 14:26:04 -04001168 default:
1169 break;
Olli Etuahofa33d582015-04-09 14:33:12 +03001170 }
1171
Jamie Madillb98c3a82015-07-23 14:26:04 -04001172 if (publicType.qualifier != EvqUniform &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001173 !checkIsNotSampler(identifierLocation, publicType.typeSpecifierNonArray,
1174 "samplers must be uniform"))
Olli Etuahofa33d582015-04-09 14:33:12 +03001175 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001176 return;
Olli Etuahofa33d582015-04-09 14:33:12 +03001177 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001178 if (publicType.qualifier != EvqUniform &&
1179 !checkIsNotImage(identifierLocation, publicType.typeSpecifierNonArray,
1180 "images must be uniform"))
1181 {
1182 return;
1183 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001184
1185 // check for layout qualifier issues
1186 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
1187
1188 if (layoutQualifier.matrixPacking != EmpUnspecified)
1189 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001190 error(identifierLocation, "layout qualifier only valid for interface blocks",
1191 getMatrixPackingString(layoutQualifier.matrixPacking));
Olli Etuaho383b7912016-08-05 11:22:59 +03001192 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001193 }
1194
1195 if (layoutQualifier.blockStorage != EbsUnspecified)
1196 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001197 error(identifierLocation, "layout qualifier only valid for interface blocks",
1198 getBlockStorageString(layoutQualifier.blockStorage));
Olli Etuaho383b7912016-08-05 11:22:59 +03001199 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001200 }
1201
Olli Etuaho383b7912016-08-05 11:22:59 +03001202 if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut)
Jamie Madilla5efff92013-06-06 11:56:47 -04001203 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001204 checkLocationIsNotSpecified(identifierLocation, publicType.layoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04001205 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001206
1207 if (IsImage(publicType.getBasicType()))
1208 {
1209
1210 switch (layoutQualifier.imageInternalFormat)
1211 {
1212 case EiifRGBA32F:
1213 case EiifRGBA16F:
1214 case EiifR32F:
1215 case EiifRGBA8:
1216 case EiifRGBA8_SNORM:
1217 if (!IsFloatImage(publicType.getBasicType()))
1218 {
1219 error(identifierLocation,
1220 "internal image format requires a floating image type",
1221 getBasicString(publicType.getBasicType()));
1222 return;
1223 }
1224 break;
1225 case EiifRGBA32I:
1226 case EiifRGBA16I:
1227 case EiifRGBA8I:
1228 case EiifR32I:
1229 if (!IsIntegerImage(publicType.getBasicType()))
1230 {
1231 error(identifierLocation,
1232 "internal image format requires an integer image type",
1233 getBasicString(publicType.getBasicType()));
1234 return;
1235 }
1236 break;
1237 case EiifRGBA32UI:
1238 case EiifRGBA16UI:
1239 case EiifRGBA8UI:
1240 case EiifR32UI:
1241 if (!IsUnsignedImage(publicType.getBasicType()))
1242 {
1243 error(identifierLocation,
1244 "internal image format requires an unsigned image type",
1245 getBasicString(publicType.getBasicType()));
1246 return;
1247 }
1248 break;
1249 case EiifUnspecified:
1250 error(identifierLocation, "layout qualifier", "No image internal format specified");
1251 return;
1252 default:
1253 error(identifierLocation, "layout qualifier", "unrecognized token");
1254 return;
1255 }
1256
1257 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
1258 switch (layoutQualifier.imageInternalFormat)
1259 {
1260 case EiifR32F:
1261 case EiifR32I:
1262 case EiifR32UI:
1263 break;
1264 default:
1265 if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
1266 {
1267 error(identifierLocation, "layout qualifier",
1268 "Except for images with the r32f, r32i and r32ui format qualifiers, "
1269 "image variables must be qualified readonly and/or writeonly");
1270 return;
1271 }
1272 break;
1273 }
1274 }
1275 else
1276 {
Olli Etuaho43364892017-02-13 16:00:12 +00001277 checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat);
Martin Radev2cc85b32016-08-05 16:22:53 +03001278
Olli Etuaho43364892017-02-13 16:00:12 +00001279 checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
1280 }
1281}
Martin Radev2cc85b32016-08-05 16:22:53 +03001282
Olli Etuaho43364892017-02-13 16:00:12 +00001283void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type)
1284{
1285 TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
1286 int arraySize = type.isArray() ? type.getArraySize() : 1;
1287 if (IsImage(type.getBasicType()))
1288 {
1289 checkImageBindingIsValid(identifierLocation, layoutQualifier.binding, arraySize);
1290 }
1291 else if (IsSampler(type.getBasicType()))
1292 {
1293 checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding, arraySize);
1294 }
1295 else
1296 {
1297 ASSERT(!IsOpaqueType(type.getBasicType()));
1298 checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
Martin Radev2cc85b32016-08-05 16:22:53 +03001299 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001300}
1301
Olli Etuaho856c4972016-08-08 11:38:39 +03001302void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1303 const TString &layoutQualifierName,
1304 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001305{
1306
1307 if (mShaderVersion < versionRequired)
1308 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001309 error(location, "invalid layout qualifier: not supported", layoutQualifierName.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03001310 }
1311}
1312
Olli Etuaho856c4972016-08-08 11:38:39 +03001313bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1314 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001315{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001316 const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
Martin Radev802abe02016-08-04 17:48:32 +03001317 for (size_t i = 0u; i < localSize.size(); ++i)
1318 {
1319 if (localSize[i] != -1)
1320 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001321 error(location,
1322 "invalid layout qualifier: only valid when used with 'in' in a compute shader "
1323 "global layout declaration",
1324 getWorkGroupSizeString(i));
Olli Etuaho8a176262016-08-16 14:23:01 +03001325 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001326 }
1327 }
1328
Olli Etuaho8a176262016-08-16 14:23:01 +03001329 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001330}
1331
Olli Etuaho43364892017-02-13 16:00:12 +00001332void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
Martin Radev2cc85b32016-08-05 16:22:53 +03001333 TLayoutImageInternalFormat internalFormat)
1334{
1335 if (internalFormat != EiifUnspecified)
1336 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001337 error(location, "invalid layout qualifier: only valid when used with images",
1338 getImageInternalFormatString(internalFormat));
Martin Radev2cc85b32016-08-05 16:22:53 +03001339 }
Olli Etuaho43364892017-02-13 16:00:12 +00001340}
1341
1342void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
1343{
1344 if (binding != -1)
1345 {
1346 error(location,
1347 "invalid layout qualifier: only valid when used with opaque types or blocks",
1348 "binding");
1349 }
1350}
1351
1352void TParseContext::checkImageBindingIsValid(const TSourceLoc &location, int binding, int arraySize)
1353{
1354 // Expects arraySize to be 1 when setting binding for only a single variable.
1355 if (binding >= 0 && binding + arraySize > mMaxImageUnits)
1356 {
1357 error(location, "image binding greater than gl_MaxImageUnits", "binding");
1358 }
1359}
1360
1361void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location,
1362 int binding,
1363 int arraySize)
1364{
1365 // Expects arraySize to be 1 when setting binding for only a single variable.
1366 if (binding >= 0 && binding + arraySize > mMaxCombinedTextureImageUnits)
1367 {
1368 error(location, "sampler binding greater than maximum texture units", "binding");
1369 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001370}
1371
Olli Etuaho383b7912016-08-05 11:22:59 +03001372void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
Olli Etuaho856c4972016-08-08 11:38:39 +03001373 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001374{
1375 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1376 {
1377 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1378 if (qual == EvqOut || qual == EvqInOut)
1379 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001380 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho8a176262016-08-16 14:23:01 +03001381 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001382 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001383 TString unmangledName =
1384 TFunction::unmangleName(fnCall->getFunctionSymbolInfo()->getName());
Olli Etuaho856c4972016-08-08 11:38:39 +03001385 error(argument->getLine(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00001386 "Constant value cannot be passed for 'out' or 'inout' parameters.",
1387 unmangledName.c_str());
Olli Etuaho383b7912016-08-05 11:22:59 +03001388 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001389 }
1390 }
1391 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001392}
1393
Martin Radev70866b82016-07-22 15:27:42 +03001394void TParseContext::checkInvariantVariableQualifier(bool invariant,
1395 const TQualifier qualifier,
1396 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001397{
Martin Radev70866b82016-07-22 15:27:42 +03001398 if (!invariant)
1399 return;
1400
1401 if (mShaderVersion < 300)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001402 {
Martin Radev70866b82016-07-22 15:27:42 +03001403 // input variables in the fragment shader can be also qualified as invariant
1404 if (!sh::CanBeInvariantESSL1(qualifier))
1405 {
1406 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1407 }
1408 }
1409 else
1410 {
1411 if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
1412 {
1413 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1414 }
Olli Etuaho37ad4742015-04-27 13:18:50 +03001415 }
1416}
1417
Arun Patole7e7e68d2015-05-22 12:02:25 +05301418bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001419{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001420 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001421 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1422 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001423}
1424
Arun Patole7e7e68d2015-05-22 12:02:25 +05301425bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001426{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001427 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001428}
1429
Jamie Madillb98c3a82015-07-23 14:26:04 -04001430void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1431 const char *extName,
1432 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001433{
1434 pp::SourceLocation srcLoc;
1435 srcLoc.file = loc.first_file;
1436 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001437 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001438}
1439
Jamie Madillb98c3a82015-07-23 14:26:04 -04001440void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1441 const char *name,
1442 const char *value,
1443 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001444{
1445 pp::SourceLocation srcLoc;
1446 srcLoc.file = loc.first_file;
1447 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001448 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001449}
1450
Martin Radev4c4c8e72016-08-04 12:25:34 +03001451sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
Martin Radev802abe02016-08-04 17:48:32 +03001452{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001453 sh::WorkGroupSize result;
Martin Radev802abe02016-08-04 17:48:32 +03001454 for (size_t i = 0u; i < result.size(); ++i)
1455 {
1456 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1457 {
1458 result[i] = 1;
1459 }
1460 else
1461 {
1462 result[i] = mComputeShaderLocalSize[i];
1463 }
1464 }
1465 return result;
1466}
1467
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001468/////////////////////////////////////////////////////////////////////////////////
1469//
1470// Non-Errors.
1471//
1472/////////////////////////////////////////////////////////////////////////////////
1473
Jamie Madill5c097022014-08-20 16:38:32 -04001474const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1475 const TString *name,
1476 const TSymbol *symbol)
1477{
1478 const TVariable *variable = NULL;
1479
1480 if (!symbol)
1481 {
1482 error(location, "undeclared identifier", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001483 }
1484 else if (!symbol->isVariable())
1485 {
1486 error(location, "variable expected", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001487 }
1488 else
1489 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001490 variable = static_cast<const TVariable *>(symbol);
Jamie Madill5c097022014-08-20 16:38:32 -04001491
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001492 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
Olli Etuaho383b7912016-08-05 11:22:59 +03001493 !variable->getExtension().empty())
Jamie Madill5c097022014-08-20 16:38:32 -04001494 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001495 checkCanUseExtension(location, variable->getExtension());
Jamie Madill5c097022014-08-20 16:38:32 -04001496 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001497
1498 // Reject shaders using both gl_FragData and gl_FragColor
1499 TQualifier qualifier = variable->getType().getQualifier();
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001500 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001501 {
1502 mUsesFragData = true;
1503 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001504 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001505 {
1506 mUsesFragColor = true;
1507 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001508 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1509 {
1510 mUsesSecondaryOutputs = true;
1511 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001512
1513 // This validation is not quite correct - it's only an error to write to
1514 // both FragData and FragColor. For simplicity, and because users shouldn't
1515 // be rewarded for reading from undefined varaibles, return an error
1516 // if they are both referenced, rather than assigned.
1517 if (mUsesFragData && mUsesFragColor)
1518 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001519 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1520 if (mUsesSecondaryOutputs)
1521 {
1522 errorMessage =
1523 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1524 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1525 }
1526 error(location, errorMessage, name->c_str());
Jamie Madill14e95b32015-05-07 10:10:41 -04001527 }
Martin Radevb0883602016-08-04 17:48:58 +03001528
1529 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1530 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1531 qualifier == EvqWorkGroupSize)
1532 {
1533 error(location,
1534 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1535 "gl_WorkGroupSize");
1536 }
Jamie Madill5c097022014-08-20 16:38:32 -04001537 }
1538
1539 if (!variable)
1540 {
1541 TType type(EbtFloat, EbpUndefined);
1542 TVariable *fakeVariable = new TVariable(name, type);
1543 symbolTable.declare(fakeVariable);
1544 variable = fakeVariable;
1545 }
1546
1547 return variable;
1548}
1549
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001550TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1551 const TString *name,
1552 const TSymbol *symbol)
1553{
1554 const TVariable *variable = getNamedVariable(location, name, symbol);
1555
Olli Etuaho09b04a22016-12-15 13:30:26 +00001556 if (variable->getType().getQualifier() == EvqViewIDOVR && IsWebGLBasedSpec(mShaderSpec) &&
1557 mShaderType == GL_FRAGMENT_SHADER && !isExtensionEnabled("GL_OVR_multiview2"))
1558 {
1559 // WEBGL_multiview spec
1560 error(location, "Need to enable OVR_multiview2 to use gl_ViewID_OVR in fragment shader",
1561 "gl_ViewID_OVR");
1562 }
1563
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001564 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001565 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001566 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001567 return intermediate.addConstantUnion(constArray, variable->getType(), location);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001568 }
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001569 else if (variable->getType().getQualifier() == EvqWorkGroupSize &&
1570 mComputeShaderLocalSizeDeclared)
1571 {
1572 // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
1573 // needs to be added to the AST as a constant and not as a symbol.
1574 sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
1575 TConstantUnion *constArray = new TConstantUnion[3];
1576 for (size_t i = 0; i < 3; ++i)
1577 {
1578 constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
1579 }
1580
1581 ASSERT(variable->getType().getBasicType() == EbtUInt);
1582 ASSERT(variable->getType().getObjectSize() == 3);
1583
1584 TType type(variable->getType());
1585 type.setQualifier(EvqConst);
1586 return intermediate.addConstantUnion(constArray, type, location);
1587 }
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001588 else
1589 {
1590 return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
1591 variable->getType(), location);
1592 }
1593}
1594
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001595//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001596// Initializers show up in several places in the grammar. Have one set of
1597// code to handle them here.
1598//
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001599// Returns true on error, false if no error
1600//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001601bool TParseContext::executeInitializer(const TSourceLoc &line,
1602 const TString &identifier,
1603 const TPublicType &pType,
1604 TIntermTyped *initializer,
Olli Etuaho13389b62016-10-16 11:48:18 +01001605 TIntermBinary **initNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001606{
Olli Etuaho13389b62016-10-16 11:48:18 +01001607 ASSERT(initNode != nullptr);
1608 ASSERT(*initNode == nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001609 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001610
Olli Etuaho2935c582015-04-08 14:32:06 +03001611 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001612 if (type.isUnsizedArray())
1613 {
Olli Etuaho02bd82c2016-11-03 10:29:43 +00001614 // We have not checked yet whether the initializer actually is an array or not.
1615 if (initializer->isArray())
1616 {
1617 type.setArraySize(initializer->getArraySize());
1618 }
1619 else
1620 {
1621 // Having a non-array initializer for an unsized array will result in an error later,
1622 // so we don't generate an error message here.
1623 type.setArraySize(1u);
1624 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03001625 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001626 if (!declareVariable(line, identifier, type, &variable))
1627 {
1628 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001629 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001630
Olli Etuahob0c645e2015-05-12 14:25:36 +03001631 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001632 if (symbolTable.atGlobalLevel() &&
1633 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001634 {
1635 // Error message does not completely match behavior with ESSL 1.00, but
1636 // we want to steer developers towards only using constant expressions.
1637 error(line, "global variable initializers must be constant expressions", "=");
1638 return true;
1639 }
1640 if (globalInitWarning)
1641 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001642 warning(
1643 line,
1644 "global variable initializers should be constant expressions "
1645 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1646 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001647 }
1648
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001649 //
1650 // identifier must be of type constant, a global, or a temporary
1651 //
1652 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301653 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1654 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001655 error(line, " cannot initialize this type of qualifier ",
1656 variable->getType().getQualifierString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001657 return true;
1658 }
1659 //
1660 // test for and propagate constant
1661 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001662
Arun Patole7e7e68d2015-05-22 12:02:25 +05301663 if (qualifier == EvqConst)
1664 {
1665 if (qualifier != initializer->getType().getQualifier())
1666 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001667 std::stringstream reasonStream;
1668 reasonStream << "assigning non-constant to '" << variable->getType().getCompleteString()
1669 << "'";
1670 std::string reason = reasonStream.str();
1671 error(line, reason.c_str(), "=");
alokp@chromium.org58e54292010-08-24 21:40:03 +00001672 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001673 return true;
1674 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301675 if (type != initializer->getType())
1676 {
1677 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001678 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001679 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001680 return true;
1681 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001682
1683 // Save the constant folded value to the variable if possible. For example array
1684 // initializers are not folded, since that way copying the array literal to multiple places
1685 // in the shader is avoided.
1686 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1687 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301688 if (initializer->getAsConstantUnion())
1689 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001690 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuaho13389b62016-10-16 11:48:18 +01001691 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001692 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301693 }
1694 else if (initializer->getAsSymbolNode())
1695 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001696 const TSymbol *symbol =
1697 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1698 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001699
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001700 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001701 if (constArray)
1702 {
1703 variable->shareConstPointer(constArray);
Olli Etuaho13389b62016-10-16 11:48:18 +01001704 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001705 return false;
1706 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001707 }
1708 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001709
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001710 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1711 variable->getUniqueId(), variable->getName(), variable->getType(), line);
Olli Etuaho13389b62016-10-16 11:48:18 +01001712 *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1713 if (*initNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001714 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001715 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1716 return true;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001717 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001718
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001719 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001720}
1721
Olli Etuaho0e3aee32016-10-27 12:56:38 +01001722void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
1723{
1724 checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
1725 typeSpecifier->getBasicType());
1726
1727 if (mShaderVersion < 300 && typeSpecifier->array)
1728 {
1729 error(typeSpecifier->getLine(), "not supported", "first-class array");
1730 typeSpecifier->clearArrayness();
1731 }
1732}
1733
Martin Radev70866b82016-07-22 15:27:42 +03001734TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301735 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001736{
Olli Etuaho77ba4082016-12-16 12:01:18 +00001737 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001738
Martin Radev70866b82016-07-22 15:27:42 +03001739 TPublicType returnType = typeSpecifier;
1740 returnType.qualifier = typeQualifier.qualifier;
1741 returnType.invariant = typeQualifier.invariant;
1742 returnType.layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03001743 returnType.memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03001744 returnType.precision = typeSpecifier.precision;
1745
1746 if (typeQualifier.precision != EbpUndefined)
1747 {
1748 returnType.precision = typeQualifier.precision;
1749 }
1750
Martin Radev4a9cd802016-09-01 16:51:51 +03001751 checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
1752 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03001753
Martin Radev4a9cd802016-09-01 16:51:51 +03001754 checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
1755 typeSpecifier.getLine());
Martin Radev70866b82016-07-22 15:27:42 +03001756
Martin Radev4a9cd802016-09-01 16:51:51 +03001757 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001758
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001759 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001760 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001761 if (typeSpecifier.array)
1762 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001763 error(typeSpecifier.getLine(), "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001764 returnType.clearArrayness();
1765 }
1766
Martin Radev70866b82016-07-22 15:27:42 +03001767 if (returnType.qualifier == EvqAttribute &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001768 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001769 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001770 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001771 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001772 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001773
Martin Radev70866b82016-07-22 15:27:42 +03001774 if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001775 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001776 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001777 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001778 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001779 }
1780 }
1781 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001782 {
Martin Radev70866b82016-07-22 15:27:42 +03001783 if (!returnType.layoutQualifier.isEmpty())
Olli Etuahoabb0c382015-07-13 12:01:12 +03001784 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001785 checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03001786 }
Martin Radev70866b82016-07-22 15:27:42 +03001787 if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
1788 returnType.qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001789 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001790 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
1791 typeSpecifier.getLine());
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001792 }
Martin Radev70866b82016-07-22 15:27:42 +03001793 if (returnType.qualifier == EvqComputeIn)
Martin Radev802abe02016-08-04 17:48:32 +03001794 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001795 error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
Martin Radev802abe02016-08-04 17:48:32 +03001796 "in");
Martin Radev802abe02016-08-04 17:48:32 +03001797 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001798 }
1799
1800 return returnType;
1801}
1802
Olli Etuaho856c4972016-08-08 11:38:39 +03001803void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1804 const TPublicType &type,
1805 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03001806{
1807 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
Martin Radev4a9cd802016-09-01 16:51:51 +03001808 if (type.getBasicType() == EbtBool)
Olli Etuahocc36b982015-07-10 14:14:18 +03001809 {
1810 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001811 }
1812
1813 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1814 switch (qualifier)
1815 {
1816 case EvqVertexIn:
1817 // ESSL 3.00 section 4.3.4
1818 if (type.array)
1819 {
1820 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001821 }
1822 // Vertex inputs with a struct type are disallowed in singleDeclarationErrorCheck
1823 return;
1824 case EvqFragmentOut:
1825 // ESSL 3.00 section 4.3.6
Martin Radev4a9cd802016-09-01 16:51:51 +03001826 if (type.typeSpecifierNonArray.isMatrix())
Olli Etuahocc36b982015-07-10 14:14:18 +03001827 {
1828 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001829 }
1830 // Fragment outputs with a struct type are disallowed in singleDeclarationErrorCheck
1831 return;
1832 default:
1833 break;
1834 }
1835
1836 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1837 // restrictions.
1838 bool typeContainsIntegers =
Martin Radev4a9cd802016-09-01 16:51:51 +03001839 (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
1840 type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
Olli Etuahocc36b982015-07-10 14:14:18 +03001841 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1842 {
1843 error(qualifierLocation, "must use 'flat' interpolation here",
1844 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001845 }
1846
Martin Radev4a9cd802016-09-01 16:51:51 +03001847 if (type.getBasicType() == EbtStruct)
Olli Etuahocc36b982015-07-10 14:14:18 +03001848 {
1849 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1850 // These restrictions are only implied by the ESSL 3.00 spec, but
1851 // the ESSL 3.10 spec lists these restrictions explicitly.
1852 if (type.array)
1853 {
1854 error(qualifierLocation, "cannot be an array of structures",
1855 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001856 }
1857 if (type.isStructureContainingArrays())
1858 {
1859 error(qualifierLocation, "cannot be a structure containing an array",
1860 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001861 }
1862 if (type.isStructureContainingType(EbtStruct))
1863 {
1864 error(qualifierLocation, "cannot be a structure containing a structure",
1865 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001866 }
1867 if (type.isStructureContainingType(EbtBool))
1868 {
1869 error(qualifierLocation, "cannot be a structure containing a bool",
1870 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001871 }
1872 }
1873}
1874
Martin Radev2cc85b32016-08-05 16:22:53 +03001875void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
1876{
1877 if (qualifier.getType() == QtStorage)
1878 {
1879 const TStorageQualifierWrapper &storageQualifier =
1880 static_cast<const TStorageQualifierWrapper &>(qualifier);
1881 if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
1882 !symbolTable.atGlobalLevel())
1883 {
1884 error(storageQualifier.getLine(),
1885 "Local variables can only use the const storage qualifier.",
1886 storageQualifier.getQualifierString().c_str());
1887 }
1888 }
1889}
1890
Olli Etuaho43364892017-02-13 16:00:12 +00001891void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
Martin Radev2cc85b32016-08-05 16:22:53 +03001892 const TSourceLoc &location)
1893{
1894 if (memoryQualifier.readonly)
1895 {
1896 error(location, "Only allowed with images.", "readonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03001897 }
1898 if (memoryQualifier.writeonly)
1899 {
1900 error(location, "Only allowed with images.", "writeonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03001901 }
Martin Radev049edfa2016-11-11 14:35:37 +02001902 if (memoryQualifier.coherent)
1903 {
1904 error(location, "Only allowed with images.", "coherent");
Martin Radev049edfa2016-11-11 14:35:37 +02001905 }
1906 if (memoryQualifier.restrictQualifier)
1907 {
1908 error(location, "Only allowed with images.", "restrict");
Martin Radev049edfa2016-11-11 14:35:37 +02001909 }
1910 if (memoryQualifier.volatileQualifier)
1911 {
1912 error(location, "Only allowed with images.", "volatile");
Martin Radev049edfa2016-11-11 14:35:37 +02001913 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001914}
1915
Olli Etuaho13389b62016-10-16 11:48:18 +01001916TIntermDeclaration *TParseContext::parseSingleDeclaration(
1917 TPublicType &publicType,
1918 const TSourceLoc &identifierOrTypeLocation,
1919 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04001920{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001921 TType type(publicType);
1922 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
1923 mDirectiveHandler.pragma().stdgl.invariantAll)
1924 {
1925 TQualifier qualifier = type.getQualifier();
1926
1927 // The directive handler has already taken care of rejecting invalid uses of this pragma
1928 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
1929 // affected variable declarations:
1930 //
1931 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
1932 // elsewhere, in TranslatorGLSL.)
1933 //
1934 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
1935 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
1936 // the way this is currently implemented we have to enable this compiler option before
1937 // parsing the shader and determining the shading language version it uses. If this were
1938 // implemented as a post-pass, the workaround could be more targeted.
1939 //
1940 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
1941 // the specification, but there are desktop OpenGL drivers that expect that this is the
1942 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
1943 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
1944 {
1945 type.setInvariant(true);
1946 }
1947 }
1948
1949 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001950
Olli Etuahobab4c082015-04-24 16:38:49 +03001951 bool emptyDeclaration = (identifier == "");
Olli Etuahofa33d582015-04-09 14:33:12 +03001952
Olli Etuahobab4c082015-04-24 16:38:49 +03001953 mDeferredSingleDeclarationErrorCheck = emptyDeclaration;
1954
Olli Etuaho13389b62016-10-16 11:48:18 +01001955 TIntermDeclaration *declaration = new TIntermDeclaration();
1956 declaration->setLine(identifierOrTypeLocation);
1957
Olli Etuahobab4c082015-04-24 16:38:49 +03001958 if (emptyDeclaration)
1959 {
Martin Radevb8b01222016-11-20 23:25:53 +02001960 emptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Olli Etuahobab4c082015-04-24 16:38:49 +03001961 }
1962 else
Jamie Madill60ed9812013-06-06 11:56:46 -04001963 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001964 singleDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001965
Olli Etuaho856c4972016-08-08 11:38:39 +03001966 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001967
Olli Etuaho2935c582015-04-08 14:32:06 +03001968 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001969 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001970
1971 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01001972 {
Jamie Madill60ed9812013-06-06 11:56:46 -04001973 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01001974 }
Jamie Madill60ed9812013-06-06 11:56:46 -04001975 }
1976
Olli Etuaho13389b62016-10-16 11:48:18 +01001977 // We append the symbol even if the declaration is empty, mainly because of struct declarations
1978 // that may just declare a type.
1979 declaration->appendDeclarator(symbol);
1980
1981 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04001982}
1983
Olli Etuaho13389b62016-10-16 11:48:18 +01001984TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1985 const TSourceLoc &identifierLocation,
1986 const TString &identifier,
1987 const TSourceLoc &indexLocation,
1988 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04001989{
Olli Etuahofa33d582015-04-09 14:33:12 +03001990 mDeferredSingleDeclarationErrorCheck = false;
1991
Olli Etuaho383b7912016-08-05 11:22:59 +03001992 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001993
Olli Etuaho856c4972016-08-08 11:38:39 +03001994 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001995
Olli Etuaho8a176262016-08-16 14:23:01 +03001996 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001997
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001998 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001999
Olli Etuaho856c4972016-08-08 11:38:39 +03002000 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002001 // Make the type an array even if size check failed.
2002 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2003 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04002004
Olli Etuaho2935c582015-04-08 14:32:06 +03002005 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002006 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04002007
Olli Etuaho13389b62016-10-16 11:48:18 +01002008 TIntermDeclaration *declaration = new TIntermDeclaration();
2009 declaration->setLine(identifierLocation);
2010
Olli Etuahoe7847b02015-03-16 11:56:12 +02002011 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002012 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002013 {
Jamie Madill60ed9812013-06-06 11:56:46 -04002014 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002015 declaration->appendDeclarator(symbol);
2016 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002017
Olli Etuaho13389b62016-10-16 11:48:18 +01002018 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002019}
2020
Olli Etuaho13389b62016-10-16 11:48:18 +01002021TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
2022 const TSourceLoc &identifierLocation,
2023 const TString &identifier,
2024 const TSourceLoc &initLocation,
2025 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04002026{
Olli Etuahofa33d582015-04-09 14:33:12 +03002027 mDeferredSingleDeclarationErrorCheck = false;
2028
Olli Etuaho383b7912016-08-05 11:22:59 +03002029 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002030
Olli Etuaho13389b62016-10-16 11:48:18 +01002031 TIntermDeclaration *declaration = new TIntermDeclaration();
2032 declaration->setLine(identifierLocation);
2033
2034 TIntermBinary *initNode = nullptr;
2035 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04002036 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002037 if (initNode)
2038 {
2039 declaration->appendDeclarator(initNode);
2040 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002041 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002042 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002043}
2044
Olli Etuaho13389b62016-10-16 11:48:18 +01002045TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
Jamie Madillb98c3a82015-07-23 14:26:04 -04002046 TPublicType &publicType,
2047 const TSourceLoc &identifierLocation,
2048 const TString &identifier,
2049 const TSourceLoc &indexLocation,
2050 TIntermTyped *indexExpression,
2051 const TSourceLoc &initLocation,
2052 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002053{
2054 mDeferredSingleDeclarationErrorCheck = false;
2055
Olli Etuaho383b7912016-08-05 11:22:59 +03002056 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002057
Olli Etuaho8a176262016-08-16 14:23:01 +03002058 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002059
2060 TPublicType arrayType(publicType);
2061
Olli Etuaho856c4972016-08-08 11:38:39 +03002062 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002063 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2064 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002065 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002066 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002067 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002068 }
2069 // Make the type an array even if size check failed.
2070 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2071 arrayType.setArraySize(size);
2072
Olli Etuaho13389b62016-10-16 11:48:18 +01002073 TIntermDeclaration *declaration = new TIntermDeclaration();
2074 declaration->setLine(identifierLocation);
2075
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002076 // initNode will correspond to the whole of "type b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002077 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002078 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2079 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002080 if (initNode)
2081 {
2082 declaration->appendDeclarator(initNode);
2083 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002084 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002085
2086 return declaration;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002087}
2088
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002089TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
Martin Radev70866b82016-07-22 15:27:42 +03002090 const TTypeQualifierBuilder &typeQualifierBuilder,
2091 const TSourceLoc &identifierLoc,
2092 const TString *identifier,
2093 const TSymbol *symbol)
Jamie Madill47e3ec02014-08-20 16:38:33 -04002094{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002095 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002096
Martin Radev70866b82016-07-22 15:27:42 +03002097 if (!typeQualifier.invariant)
2098 {
2099 error(identifierLoc, "Expected invariant", identifier->c_str());
2100 return nullptr;
2101 }
2102 if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
2103 {
2104 return nullptr;
2105 }
Jamie Madill47e3ec02014-08-20 16:38:33 -04002106 if (!symbol)
2107 {
2108 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002109 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04002110 }
Martin Radev70866b82016-07-22 15:27:42 +03002111 if (!IsQualifierUnspecified(typeQualifier.qualifier))
Jamie Madill47e3ec02014-08-20 16:38:33 -04002112 {
Martin Radev70866b82016-07-22 15:27:42 +03002113 error(identifierLoc, "invariant declaration specifies qualifier",
2114 getQualifierString(typeQualifier.qualifier));
Jamie Madill47e3ec02014-08-20 16:38:33 -04002115 }
Martin Radev70866b82016-07-22 15:27:42 +03002116 if (typeQualifier.precision != EbpUndefined)
2117 {
2118 error(identifierLoc, "invariant declaration specifies precision",
2119 getPrecisionString(typeQualifier.precision));
2120 }
2121 if (!typeQualifier.layoutQualifier.isEmpty())
2122 {
2123 error(identifierLoc, "invariant declaration specifies layout", "'layout'");
2124 }
2125
2126 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
2127 ASSERT(variable);
2128 const TType &type = variable->getType();
2129
2130 checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
2131 typeQualifier.line);
Olli Etuaho43364892017-02-13 16:00:12 +00002132 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev70866b82016-07-22 15:27:42 +03002133
2134 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
2135
2136 TIntermSymbol *intermSymbol =
2137 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
2138
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002139 return new TIntermInvariantDeclaration(intermSymbol, identifierLoc);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002140}
2141
Olli Etuaho13389b62016-10-16 11:48:18 +01002142void TParseContext::parseDeclarator(TPublicType &publicType,
2143 const TSourceLoc &identifierLocation,
2144 const TString &identifier,
2145 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002146{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002147 // If the declaration starting this declarator list was empty (example: int,), some checks were
2148 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03002149 if (mDeferredSingleDeclarationErrorCheck)
2150 {
Olli Etuaho383b7912016-08-05 11:22:59 +03002151 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03002152 mDeferredSingleDeclarationErrorCheck = false;
2153 }
2154
Olli Etuaho856c4972016-08-08 11:38:39 +03002155 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002156
Olli Etuaho856c4972016-08-08 11:38:39 +03002157 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002158
Olli Etuaho2935c582015-04-08 14:32:06 +03002159 TVariable *variable = nullptr;
Olli Etuaho43364892017-02-13 16:00:12 +00002160 TType type(publicType);
2161 declareVariable(identifierLocation, identifier, type, &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002162
Olli Etuaho43364892017-02-13 16:00:12 +00002163 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002164 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002165 {
Jamie Madill502d66f2013-06-20 11:55:52 -04002166 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002167 declarationOut->appendDeclarator(symbol);
2168 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002169}
2170
Olli Etuaho13389b62016-10-16 11:48:18 +01002171void TParseContext::parseArrayDeclarator(TPublicType &publicType,
2172 const TSourceLoc &identifierLocation,
2173 const TString &identifier,
2174 const TSourceLoc &arrayLocation,
2175 TIntermTyped *indexExpression,
2176 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002177{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002178 // If the declaration starting this declarator list was empty (example: int,), some checks were
2179 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03002180 if (mDeferredSingleDeclarationErrorCheck)
2181 {
Olli Etuaho383b7912016-08-05 11:22:59 +03002182 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03002183 mDeferredSingleDeclarationErrorCheck = false;
2184 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002185
Olli Etuaho856c4972016-08-08 11:38:39 +03002186 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002187
Olli Etuaho856c4972016-08-08 11:38:39 +03002188 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002189
Olli Etuaho8a176262016-08-16 14:23:01 +03002190 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04002191 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002192 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03002193 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03002194 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002195
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002196 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002197 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04002198
Jamie Madillb98c3a82015-07-23 14:26:04 -04002199 TIntermSymbol *symbol =
2200 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002201 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002202 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002203
Olli Etuaho13389b62016-10-16 11:48:18 +01002204 declarationOut->appendDeclarator(symbol);
Jamie Madill502d66f2013-06-20 11:55:52 -04002205 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002206}
2207
Olli Etuaho13389b62016-10-16 11:48:18 +01002208void TParseContext::parseInitDeclarator(const TPublicType &publicType,
2209 const TSourceLoc &identifierLocation,
2210 const TString &identifier,
2211 const TSourceLoc &initLocation,
2212 TIntermTyped *initializer,
2213 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002214{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002215 // If the declaration starting this declarator list was empty (example: int,), some checks were
2216 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03002217 if (mDeferredSingleDeclarationErrorCheck)
2218 {
Olli Etuaho383b7912016-08-05 11:22:59 +03002219 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03002220 mDeferredSingleDeclarationErrorCheck = false;
2221 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002222
Olli Etuaho856c4972016-08-08 11:38:39 +03002223 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002224
Olli Etuaho13389b62016-10-16 11:48:18 +01002225 TIntermBinary *initNode = nullptr;
2226 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04002227 {
2228 //
2229 // build the intermediate representation
2230 //
Olli Etuaho13389b62016-10-16 11:48:18 +01002231 if (initNode)
Jamie Madill502d66f2013-06-20 11:55:52 -04002232 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002233 declarationOut->appendDeclarator(initNode);
Jamie Madill502d66f2013-06-20 11:55:52 -04002234 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002235 }
2236}
2237
Olli Etuaho13389b62016-10-16 11:48:18 +01002238void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
2239 const TSourceLoc &identifierLocation,
2240 const TString &identifier,
2241 const TSourceLoc &indexLocation,
2242 TIntermTyped *indexExpression,
2243 const TSourceLoc &initLocation,
2244 TIntermTyped *initializer,
2245 TIntermDeclaration *declarationOut)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002246{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002247 // If the declaration starting this declarator list was empty (example: int,), some checks were
2248 // not performed.
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002249 if (mDeferredSingleDeclarationErrorCheck)
2250 {
Olli Etuaho383b7912016-08-05 11:22:59 +03002251 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002252 mDeferredSingleDeclarationErrorCheck = false;
2253 }
2254
Olli Etuaho856c4972016-08-08 11:38:39 +03002255 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002256
Olli Etuaho8a176262016-08-16 14:23:01 +03002257 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002258
2259 TPublicType arrayType(publicType);
2260
Olli Etuaho856c4972016-08-08 11:38:39 +03002261 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002262 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2263 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002264 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002265 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002266 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002267 }
2268 // Make the type an array even if size check failed.
2269 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2270 arrayType.setArraySize(size);
2271
2272 // initNode will correspond to the whole of "b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002273 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002274 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2275 {
2276 if (initNode)
2277 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002278 declarationOut->appendDeclarator(initNode);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002279 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002280 }
2281}
2282
Martin Radev70866b82016-07-22 15:27:42 +03002283void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
Jamie Madilla295edf2013-06-06 11:56:48 -04002284{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002285 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madilla295edf2013-06-06 11:56:48 -04002286 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04002287
Martin Radev70866b82016-07-22 15:27:42 +03002288 checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
2289 typeQualifier.line);
2290
Jamie Madillc2128ff2016-07-04 10:26:17 -04002291 // It should never be the case, but some strange parser errors can send us here.
2292 if (layoutQualifier.isEmpty())
2293 {
2294 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04002295 return;
2296 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002297
Martin Radev802abe02016-08-04 17:48:32 +03002298 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04002299 {
Olli Etuaho43364892017-02-13 16:00:12 +00002300 error(typeQualifier.line, "invalid layout qualifier combination", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04002301 return;
2302 }
2303
Olli Etuaho43364892017-02-13 16:00:12 +00002304 checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);
2305
2306 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev2cc85b32016-08-05 16:22:53 +03002307
2308 checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
2309
Martin Radev802abe02016-08-04 17:48:32 +03002310 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04002311 {
Martin Radev802abe02016-08-04 17:48:32 +03002312 if (mComputeShaderLocalSizeDeclared &&
2313 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
2314 {
2315 error(typeQualifier.line, "Work group size does not match the previous declaration",
2316 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002317 return;
2318 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002319
Martin Radev802abe02016-08-04 17:48:32 +03002320 if (mShaderVersion < 310)
2321 {
2322 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002323 return;
2324 }
Jamie Madill099c0f32013-06-20 11:55:52 -04002325
Martin Radev4c4c8e72016-08-04 12:25:34 +03002326 if (!layoutQualifier.localSize.isAnyValueSet())
Martin Radev802abe02016-08-04 17:48:32 +03002327 {
2328 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002329 return;
2330 }
2331
2332 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
2333 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
2334
2335 const TConstantUnion *maxComputeWorkGroupSizeData =
2336 maxComputeWorkGroupSize->getConstPointer();
2337
2338 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
2339 {
2340 if (layoutQualifier.localSize[i] != -1)
2341 {
2342 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
2343 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
2344 if (mComputeShaderLocalSize[i] < 1 ||
2345 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
2346 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002347 std::stringstream reasonStream;
2348 reasonStream << "invalid value: Value must be at least 1 and no greater than "
2349 << maxComputeWorkGroupSizeValue;
2350 const std::string &reason = reasonStream.str();
Martin Radev802abe02016-08-04 17:48:32 +03002351
Olli Etuaho4de340a2016-12-16 09:32:03 +00002352 error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03002353 return;
2354 }
2355 }
2356 }
2357
2358 mComputeShaderLocalSizeDeclared = true;
2359 }
Olli Etuaho09b04a22016-12-15 13:30:26 +00002360 else if (mMultiviewAvailable &&
2361 (isExtensionEnabled("GL_OVR_multiview") || isExtensionEnabled("GL_OVR_multiview2")) &&
2362 typeQualifier.qualifier == EvqVertexIn)
2363 {
2364 // This error is only specified in WebGL, but tightens unspecified behavior in the native
2365 // specification.
2366 if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
2367 {
2368 error(typeQualifier.line, "Number of views does not match the previous declaration",
2369 "layout");
2370 return;
2371 }
2372
2373 if (layoutQualifier.numViews == -1)
2374 {
2375 error(typeQualifier.line, "No num_views specified", "layout");
2376 return;
2377 }
2378
2379 if (layoutQualifier.numViews > mMaxNumViews)
2380 {
2381 error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
2382 "layout");
2383 return;
2384 }
2385
2386 mNumViews = layoutQualifier.numViews;
2387 }
Martin Radev802abe02016-08-04 17:48:32 +03002388 else
Jamie Madill1566ef72013-06-20 11:55:54 -04002389 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00002390 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03002391 {
Martin Radev802abe02016-08-04 17:48:32 +03002392 return;
2393 }
2394
2395 if (typeQualifier.qualifier != EvqUniform)
2396 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002397 error(typeQualifier.line, "invalid qualifier: global layout must be uniform",
2398 getQualifierString(typeQualifier.qualifier));
Martin Radev802abe02016-08-04 17:48:32 +03002399 return;
2400 }
2401
2402 if (mShaderVersion < 300)
2403 {
2404 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
2405 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002406 return;
2407 }
2408
Olli Etuaho09b04a22016-12-15 13:30:26 +00002409 checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002410
2411 if (layoutQualifier.matrixPacking != EmpUnspecified)
2412 {
2413 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
2414 }
2415
2416 if (layoutQualifier.blockStorage != EbsUnspecified)
2417 {
2418 mDefaultBlockStorage = layoutQualifier.blockStorage;
2419 }
Jamie Madill1566ef72013-06-20 11:55:54 -04002420 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002421}
2422
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002423TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
2424 const TFunction &function,
2425 const TSourceLoc &location,
2426 bool insertParametersToSymbolTable)
2427{
2428 TIntermFunctionPrototype *prototype = new TIntermFunctionPrototype(function.getReturnType());
2429 // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
2430 // point to the data that already exists in the symbol table.
2431 prototype->getFunctionSymbolInfo()->setFromFunction(function);
2432 prototype->setLine(location);
2433
2434 for (size_t i = 0; i < function.getParamCount(); i++)
2435 {
2436 const TConstParameter &param = function.getParam(i);
2437
2438 // If the parameter has no name, it's not an error, just don't add it to symbol table (could
2439 // be used for unused args).
2440 if (param.name != nullptr)
2441 {
2442 TVariable *variable = new TVariable(param.name, *param.type);
2443
2444 // Insert the parameter in the symbol table.
2445 if (insertParametersToSymbolTable && !symbolTable.declare(variable))
2446 {
2447 error(location, "redefinition", variable->getName().c_str());
2448 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2449 continue;
2450 }
2451 TIntermSymbol *symbol = intermediate.addSymbol(
2452 variable->getUniqueId(), variable->getName(), variable->getType(), location);
2453 prototype->appendParameter(symbol);
2454 }
2455 else
2456 {
2457 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2458 }
2459 }
2460 return prototype;
2461}
2462
Olli Etuaho16c745a2017-01-16 17:02:27 +00002463TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
2464 const TFunction &parsedFunction,
2465 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002466{
Olli Etuaho476197f2016-10-11 13:59:08 +01002467 // Note: function found from the symbol table could be the same as parsedFunction if this is the
2468 // first declaration. Either way the instance in the symbol table is used to track whether the
2469 // function is declared multiple times.
2470 TFunction *function = static_cast<TFunction *>(
2471 symbolTable.find(parsedFunction.getMangledName(), getShaderVersion()));
2472 if (function->hasPrototypeDeclaration() && mShaderVersion == 100)
Olli Etuaho5d653182016-01-04 14:43:28 +02002473 {
2474 // ESSL 1.00.17 section 4.2.7.
2475 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
2476 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02002477 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002478 function->setHasPrototypeDeclaration();
Olli Etuaho5d653182016-01-04 14:43:28 +02002479
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002480 TIntermFunctionPrototype *prototype =
2481 createPrototypeNodeFromFunction(*function, location, false);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002482
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002483 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002484
2485 if (!symbolTable.atGlobalLevel())
2486 {
2487 // ESSL 3.00.4 section 4.2.4.
2488 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002489 }
2490
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002491 return prototype;
2492}
2493
Olli Etuaho336b1472016-10-05 16:37:55 +01002494TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002495 TIntermFunctionPrototype *functionPrototype,
Olli Etuaho336b1472016-10-05 16:37:55 +01002496 TIntermBlock *functionBody,
2497 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002498{
Olli Etuahof51fdd22016-10-03 10:03:40 +01002499 // Check that non-void functions have at least one return statement.
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002500 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2501 {
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002502 error(location, "function does not return a value:",
2503 functionPrototype->getFunctionSymbolInfo()->getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002504 }
2505
Olli Etuahof51fdd22016-10-03 10:03:40 +01002506 if (functionBody == nullptr)
2507 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01002508 functionBody = new TIntermBlock();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002509 functionBody->setLine(location);
2510 }
Olli Etuaho336b1472016-10-05 16:37:55 +01002511 TIntermFunctionDefinition *functionNode =
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002512 new TIntermFunctionDefinition(functionPrototype, functionBody);
Olli Etuaho336b1472016-10-05 16:37:55 +01002513 functionNode->setLine(location);
Olli Etuahof51fdd22016-10-03 10:03:40 +01002514
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002515 symbolTable.pop();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002516 return functionNode;
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002517}
2518
Olli Etuaho476197f2016-10-11 13:59:08 +01002519void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
2520 TFunction **function,
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002521 TIntermFunctionPrototype **prototypeOut)
Jamie Madill185fb402015-06-12 15:48:48 -04002522{
Olli Etuaho476197f2016-10-11 13:59:08 +01002523 ASSERT(function);
2524 ASSERT(*function);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002525 const TSymbol *builtIn =
Olli Etuaho476197f2016-10-11 13:59:08 +01002526 symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002527
2528 if (builtIn)
2529 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002530 error(location, "built-in functions cannot be redefined", (*function)->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002531 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002532 else
Jamie Madill185fb402015-06-12 15:48:48 -04002533 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002534 TFunction *prevDec = static_cast<TFunction *>(
2535 symbolTable.find((*function)->getMangledName(), getShaderVersion()));
2536
2537 // Note: 'prevDec' could be 'function' if this is the first time we've seen function as it
2538 // would have just been put in the symbol table. Otherwise, we're looking up an earlier
2539 // occurance.
2540 if (*function != prevDec)
2541 {
2542 // Swap the parameters of the previous declaration to the parameters of the function
2543 // definition (parameter names may differ).
2544 prevDec->swapParameters(**function);
2545
2546 // The function definition will share the same symbol as any previous declaration.
2547 *function = prevDec;
2548 }
2549
2550 if ((*function)->isDefined())
2551 {
2552 error(location, "function already has a body", (*function)->getName().c_str());
2553 }
2554
2555 (*function)->setDefined();
Jamie Madill185fb402015-06-12 15:48:48 -04002556 }
Jamie Madill185fb402015-06-12 15:48:48 -04002557
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002558 // Remember the return type for later checking for return statements.
Olli Etuaho476197f2016-10-11 13:59:08 +01002559 mCurrentFunctionType = &((*function)->getReturnType());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002560 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002561
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002562 *prototypeOut = createPrototypeNodeFromFunction(**function, location, true);
Jamie Madill185fb402015-06-12 15:48:48 -04002563 setLoopNestingLevel(0);
2564}
2565
Jamie Madillb98c3a82015-07-23 14:26:04 -04002566TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002567{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002568 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002569 // We don't know at this point whether this is a function definition or a prototype.
2570 // The definition production code will check for redefinitions.
2571 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002572 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002573 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2574 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002575 //
2576 TFunction *prevDec =
2577 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302578
Martin Radevda6254b2016-12-14 17:00:36 +02002579 if (getShaderVersion() >= 300 &&
2580 symbolTable.hasUnmangledBuiltInForShaderVersion(function->getName().c_str(),
2581 getShaderVersion()))
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302582 {
Martin Radevda6254b2016-12-14 17:00:36 +02002583 // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions.
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302584 // Therefore overloading or redefining builtin functions is an error.
2585 error(location, "Name of a built-in function cannot be redeclared as function",
2586 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302587 }
2588 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002589 {
2590 if (prevDec->getReturnType() != function->getReturnType())
2591 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002592 error(location, "function must have the same return type in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002593 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002594 }
2595 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2596 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002597 if (prevDec->getParam(i).type->getQualifier() !=
2598 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002599 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002600 error(location,
2601 "function must have the same parameter qualifiers in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002602 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002603 }
2604 }
2605 }
2606
2607 //
2608 // Check for previously declared variables using the same name.
2609 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002610 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002611 if (prevSym)
2612 {
2613 if (!prevSym->isFunction())
2614 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002615 error(location, "redefinition of a function", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002616 }
2617 }
2618 else
2619 {
2620 // Insert the unmangled name to detect potential future redefinition as a variable.
Olli Etuaho476197f2016-10-11 13:59:08 +01002621 symbolTable.getOuterLevel()->insertUnmangled(function);
Jamie Madill185fb402015-06-12 15:48:48 -04002622 }
2623
2624 // We're at the inner scope level of the function's arguments and body statement.
2625 // Add the function prototype to the surrounding scope instead.
2626 symbolTable.getOuterLevel()->insert(function);
2627
Olli Etuaho78d13742017-01-18 13:06:10 +00002628 // Raise error message if main function takes any parameters or return anything other than void
2629 if (function->getName() == "main")
2630 {
2631 if (function->getParamCount() > 0)
2632 {
2633 error(location, "function cannot take any parameter(s)", "main");
2634 }
2635 if (function->getReturnType().getBasicType() != EbtVoid)
2636 {
2637 error(location, "main function cannot return a value",
2638 function->getReturnType().getBasicString());
2639 }
2640 }
2641
Jamie Madill185fb402015-06-12 15:48:48 -04002642 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002643 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2644 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002645 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2646 //
2647 return function;
2648}
2649
Olli Etuaho9de84a52016-06-14 17:36:01 +03002650TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2651 const TString *name,
2652 const TSourceLoc &location)
2653{
2654 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2655 {
2656 error(location, "no qualifiers allowed for function return",
2657 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002658 }
2659 if (!type.layoutQualifier.isEmpty())
2660 {
2661 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002662 }
Martin Radev2cc85b32016-08-05 16:22:53 +03002663 // make sure a sampler or an image is not involved as well...
Martin Radev4a9cd802016-09-01 16:51:51 +03002664 checkIsNotSampler(location, type.typeSpecifierNonArray,
2665 "samplers can't be function return values");
Martin Radev2cc85b32016-08-05 16:22:53 +03002666 checkIsNotImage(location, type.typeSpecifierNonArray, "images can't be function return values");
Olli Etuahoe29324f2016-06-15 10:58:03 +03002667 if (mShaderVersion < 300)
2668 {
2669 // Array return values are forbidden, but there's also no valid syntax for declaring array
2670 // return values in ESSL 1.00.
Olli Etuaho77ba4082016-12-16 12:01:18 +00002671 ASSERT(type.arraySize == 0 || mDiagnostics->numErrors() > 0);
Olli Etuahoe29324f2016-06-15 10:58:03 +03002672
2673 if (type.isStructureContainingArrays())
2674 {
2675 // ESSL 1.00.17 section 6.1 Function Definitions
2676 error(location, "structures containing arrays can't be function return values",
2677 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002678 }
2679 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002680
2681 // Add the function as a prototype after parsing it (we do not support recursion)
2682 return new TFunction(name, new TType(type));
2683}
2684
Jamie Madill06145232015-05-13 13:10:01 -04002685TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002686{
Jamie Madill06145232015-05-13 13:10:01 -04002687 TPublicType publicType = publicTypeIn;
Martin Radev4a9cd802016-09-01 16:51:51 +03002688 if (publicType.isStructSpecifier())
Olli Etuahobd163f62015-11-13 12:15:38 +02002689 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002690 error(publicType.getLine(), "constructor can't be a structure definition",
2691 getBasicString(publicType.getBasicType()));
Olli Etuahobd163f62015-11-13 12:15:38 +02002692 }
2693
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002694 TOperator op = EOpNull;
Martin Radev4a9cd802016-09-01 16:51:51 +03002695 if (publicType.getUserDef())
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002696 {
2697 op = EOpConstructStruct;
2698 }
2699 else
2700 {
Geoff Lang156d7192016-07-21 16:11:00 -04002701 op = sh::TypeToConstructorOperator(TType(publicType));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002702 if (op == EOpNull)
2703 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002704 error(publicType.getLine(), "cannot construct this type",
2705 getBasicString(publicType.getBasicType()));
2706 publicType.setBasicType(EbtFloat);
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002707 op = EOpConstructFloat;
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002708 }
2709 }
2710
Dmitry Skiba7f17a502015-06-22 15:08:39 -07002711 const TType *type = new TType(publicType);
Olli Etuaho72d10202017-01-19 15:58:30 +00002712 return new TFunction(nullptr, type, op);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002713}
2714
Jamie Madillb98c3a82015-07-23 14:26:04 -04002715// This function is used to test for the correctness of the parameters passed to various constructor
2716// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002717//
Olli Etuaho856c4972016-08-08 11:38:39 +03002718// 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 +00002719//
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002720TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002721 TOperator op,
Olli Etuaho72d10202017-01-19 15:58:30 +00002722 TType type,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302723 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002724{
Olli Etuaho856c4972016-08-08 11:38:39 +03002725 if (type.isUnsizedArray())
2726 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002727 if (arguments->empty())
Olli Etuahobbe9fb52016-11-03 17:16:05 +00002728 {
2729 error(line, "implicitly sized array constructor must have at least one argument", "[]");
2730 type.setArraySize(1u);
2731 return TIntermTyped::CreateZero(type);
2732 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002733 type.setArraySize(static_cast<unsigned int>(arguments->size()));
Olli Etuaho856c4972016-08-08 11:38:39 +03002734 }
Olli Etuaho856c4972016-08-08 11:38:39 +03002735
Olli Etuaho72d10202017-01-19 15:58:30 +00002736 if (!checkConstructorArguments(line, arguments, op, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002737 {
Olli Etuaho72d10202017-01-19 15:58:30 +00002738 return TIntermTyped::CreateZero(type);
Olli Etuaho856c4972016-08-08 11:38:39 +03002739 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002740
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002741 TIntermAggregate *constructorNode = new TIntermAggregate(type, op, arguments);
2742 constructorNode->setLine(line);
2743 ASSERT(constructorNode->isConstructor());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002744
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002745 TIntermTyped *constConstructor =
2746 intermediate.foldAggregateBuiltIn(constructorNode, mDiagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002747 if (constConstructor)
2748 {
2749 return constConstructor;
2750 }
2751
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002752 return constructorNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002753}
2754
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002755//
2756// Interface/uniform blocks
2757//
Olli Etuaho13389b62016-10-16 11:48:18 +01002758TIntermDeclaration *TParseContext::addInterfaceBlock(
Martin Radev70866b82016-07-22 15:27:42 +03002759 const TTypeQualifierBuilder &typeQualifierBuilder,
2760 const TSourceLoc &nameLine,
2761 const TString &blockName,
2762 TFieldList *fieldList,
2763 const TString *instanceName,
2764 const TSourceLoc &instanceLine,
2765 TIntermTyped *arrayIndex,
2766 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002767{
Olli Etuaho856c4972016-08-08 11:38:39 +03002768 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002769
Olli Etuaho77ba4082016-12-16 12:01:18 +00002770 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03002771
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002772 if (typeQualifier.qualifier != EvqUniform)
2773 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002774 error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform",
2775 getQualifierString(typeQualifier.qualifier));
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002776 }
2777
Martin Radev70866b82016-07-22 15:27:42 +03002778 if (typeQualifier.invariant)
2779 {
2780 error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
2781 }
2782
Olli Etuaho43364892017-02-13 16:00:12 +00002783 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
2784
2785 // TODO(oetuaho): Remove this and support binding for blocks.
2786 checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
Martin Radev2cc85b32016-08-05 16:22:53 +03002787
Jamie Madill099c0f32013-06-20 11:55:52 -04002788 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03002789 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04002790
Jamie Madill099c0f32013-06-20 11:55:52 -04002791 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2792 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002793 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002794 }
2795
Jamie Madill1566ef72013-06-20 11:55:54 -04002796 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2797 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002798 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002799 }
2800
Olli Etuaho856c4972016-08-08 11:38:39 +03002801 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002802
Martin Radev2cc85b32016-08-05 16:22:53 +03002803 checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
2804
Arun Patole7e7e68d2015-05-22 12:02:25 +05302805 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2806 if (!symbolTable.declare(blockNameSymbol))
2807 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002808 error(nameLine, "redefinition of an interface block name", blockName.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002809 }
2810
Jamie Madill98493dd2013-07-08 14:39:03 -04002811 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302812 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2813 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002814 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302815 TType *fieldType = field->type();
2816 if (IsSampler(fieldType->getBasicType()))
2817 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002818 error(field->line(),
2819 "unsupported type - sampler types are not allowed in interface blocks",
2820 fieldType->getBasicString());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002821 }
2822
Martin Radev2cc85b32016-08-05 16:22:53 +03002823 if (IsImage(fieldType->getBasicType()))
2824 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002825 error(field->line(),
2826 "unsupported type - image types are not allowed in interface blocks",
2827 fieldType->getBasicString());
Martin Radev2cc85b32016-08-05 16:22:53 +03002828 }
2829
Jamie Madill98493dd2013-07-08 14:39:03 -04002830 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002831 switch (qualifier)
2832 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002833 case EvqGlobal:
2834 case EvqUniform:
2835 break;
2836 default:
2837 error(field->line(), "invalid qualifier on interface block member",
2838 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04002839 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002840 }
Jamie Madilla5efff92013-06-06 11:56:47 -04002841
Martin Radev70866b82016-07-22 15:27:42 +03002842 if (fieldType->isInvariant())
2843 {
2844 error(field->line(), "invalid qualifier on interface block member", "invariant");
2845 }
2846
Jamie Madilla5efff92013-06-06 11:56:47 -04002847 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04002848 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03002849 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Jamie Madill099c0f32013-06-20 11:55:52 -04002850
Jamie Madill98493dd2013-07-08 14:39:03 -04002851 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04002852 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002853 error(field->line(), "invalid layout qualifier: cannot be used here",
2854 getBlockStorageString(fieldLayoutQualifier.blockStorage));
Jamie Madill1566ef72013-06-20 11:55:54 -04002855 }
2856
Jamie Madill98493dd2013-07-08 14:39:03 -04002857 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04002858 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002859 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002860 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002861 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04002862 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002863 warning(field->line(),
2864 "extraneous layout qualifier: only has an effect on matrix types",
2865 getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
Jamie Madill099c0f32013-06-20 11:55:52 -04002866 }
2867
Jamie Madill98493dd2013-07-08 14:39:03 -04002868 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002869 }
2870
Jamie Madill98493dd2013-07-08 14:39:03 -04002871 // add array index
Olli Etuaho856c4972016-08-08 11:38:39 +03002872 unsigned int arraySize = 0;
2873 if (arrayIndex != nullptr)
Jamie Madill98493dd2013-07-08 14:39:03 -04002874 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002875 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
Jamie Madill98493dd2013-07-08 14:39:03 -04002876 }
2877
Jamie Madillb98c3a82015-07-23 14:26:04 -04002878 TInterfaceBlock *interfaceBlock =
2879 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2880 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
2881 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002882
2883 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04002884 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002885
Jamie Madill98493dd2013-07-08 14:39:03 -04002886 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002887 {
2888 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04002889 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2890 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002891 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302892 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04002893
2894 // set parent pointer of the field variable
2895 fieldType->setInterfaceBlock(interfaceBlock);
2896
Arun Patole7e7e68d2015-05-22 12:02:25 +05302897 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04002898 fieldVariable->setQualifier(typeQualifier.qualifier);
2899
Arun Patole7e7e68d2015-05-22 12:02:25 +05302900 if (!symbolTable.declare(fieldVariable))
2901 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002902 error(field->line(), "redefinition of an interface block member name",
2903 field->name().c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002904 }
2905 }
2906 }
2907 else
2908 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002909 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03002910
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002911 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05302912 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002913 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04002914
Arun Patole7e7e68d2015-05-22 12:02:25 +05302915 if (!symbolTable.declare(instanceTypeDef))
2916 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002917 error(instanceLine, "redefinition of an interface block instance name",
2918 instanceName->c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002919 }
2920
Jamie Madillb98c3a82015-07-23 14:26:04 -04002921 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002922 symbolName = instanceTypeDef->getName();
2923 }
2924
Olli Etuaho13389b62016-10-16 11:48:18 +01002925 TIntermSymbol *blockSymbol =
2926 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line);
2927 TIntermDeclaration *declaration = new TIntermDeclaration();
2928 declaration->appendDeclarator(blockSymbol);
2929 declaration->setLine(nameLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04002930
2931 exitStructDeclaration();
Olli Etuaho13389b62016-10-16 11:48:18 +01002932 return declaration;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002933}
2934
Olli Etuaho383b7912016-08-05 11:22:59 +03002935void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002936{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002937 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002938
2939 // Embedded structure definitions are not supported per GLSL ES spec.
Olli Etuaho4de340a2016-12-16 09:32:03 +00002940 // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302941 if (mStructNestingLevel > 1)
2942 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002943 error(line, "Embedded struct definitions are not allowed", "struct");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002944 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002945}
2946
2947void TParseContext::exitStructDeclaration()
2948{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002949 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002950}
2951
Olli Etuaho8a176262016-08-16 14:23:01 +03002952void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002953{
Jamie Madillacb4b812016-11-07 13:50:29 -05002954 if (!sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +05302955 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002956 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002957 }
2958
Arun Patole7e7e68d2015-05-22 12:02:25 +05302959 if (field.type()->getBasicType() != EbtStruct)
2960 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002961 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002962 }
2963
2964 // We're already inside a structure definition at this point, so add
2965 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302966 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2967 {
Jamie Madill41a49272014-03-18 16:10:13 -04002968 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002969 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
2970 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04002971 std::string reason = reasonStream.str();
Olli Etuaho4de340a2016-12-16 09:32:03 +00002972 error(line, reason.c_str(), field.name().c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03002973 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002974 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002975}
2976
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00002977//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002978// Parse an array index expression
2979//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002980TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
2981 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302982 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002983{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002984 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2985 {
2986 if (baseExpression->getAsSymbolNode())
2987 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302988 error(location, " left of '[' is not of type array, matrix, or vector ",
2989 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002990 }
2991 else
2992 {
2993 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2994 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002995
2996 TConstantUnion *unionArray = new TConstantUnion[1];
2997 unionArray->setFConst(0.0f);
2998 return intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst),
2999 location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003000 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003001
Jamie Madill21c1e452014-12-29 11:33:41 -05003002 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
3003
Olli Etuaho36b05142015-11-12 13:10:42 +02003004 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
3005 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
3006 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
3007 // index is a constant expression.
3008 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
3009 {
3010 if (baseExpression->isInterfaceBlock())
3011 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003012 error(location,
3013 "array indexes for interface blocks arrays must be constant integral expressions",
3014 "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02003015 }
3016 else if (baseExpression->getQualifier() == EvqFragmentOut)
3017 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003018 error(location,
3019 "array indexes for fragment outputs must be constant integral expressions", "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02003020 }
Olli Etuaho3e960462015-11-12 15:58:39 +02003021 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
3022 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003023 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3e960462015-11-12 15:58:39 +02003024 }
Olli Etuaho36b05142015-11-12 13:10:42 +02003025 }
3026
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003027 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04003028 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003029 // If an out-of-range index is not qualified as constant, the behavior in the spec is
3030 // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
3031 // constant fold expressions that are not constant expressions). The most compatible way to
3032 // handle this case is to report a warning instead of an error and force the index to be in
3033 // the correct range.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003034 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003035 int index = indexConstantUnion->getIConst(0);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003036
3037 int safeIndex = -1;
3038
3039 if (baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04003040 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003041 if (baseExpression->getQualifier() == EvqFragData && index > 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003042 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003043 if (mShaderSpec == SH_WEBGL2_SPEC)
3044 {
3045 // Error has been already generated if index is not const.
3046 if (indexExpression->getQualifier() == EvqConst)
3047 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003048 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003049 }
3050 safeIndex = 0;
3051 }
3052 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
3053 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003054 outOfRangeError(outOfRangeIndexIsError, location,
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003055 "array index for gl_FragData must be zero when "
Olli Etuaho4de340a2016-12-16 09:32:03 +00003056 "GL_EXT_draw_buffers is disabled",
3057 "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003058 safeIndex = 0;
3059 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03003060 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003061 // Only do generic out-of-range check if similar error hasn't already been reported.
3062 if (safeIndex < 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003063 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003064 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3065 baseExpression->getArraySize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003066 "array index out of range");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003067 }
3068 }
3069 else if (baseExpression->isMatrix())
3070 {
3071 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
Olli Etuaho90892fb2016-07-14 14:44:51 +03003072 baseExpression->getType().getCols(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003073 "matrix field selection out of range");
Jamie Madill7164cf42013-07-08 13:30:59 -04003074 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003075 else if (baseExpression->isVector())
Jamie Madill7164cf42013-07-08 13:30:59 -04003076 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003077 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3078 baseExpression->getType().getNominalSize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003079 "vector field selection out of range");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003080 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003081
3082 ASSERT(safeIndex >= 0);
3083 // Data of constant unions can't be changed, because it may be shared with other
3084 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
3085 // sanitized object.
3086 if (safeIndex != index)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003087 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003088 TConstantUnion *safeConstantUnion = new TConstantUnion();
3089 safeConstantUnion->setIConst(safeIndex);
3090 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003091 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003092
3093 return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003094 mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003095 }
Jamie Madill7164cf42013-07-08 13:30:59 -04003096 else
3097 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003098 return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003099 mDiagnostics);
Jamie Madill7164cf42013-07-08 13:30:59 -04003100 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003101}
3102
Olli Etuaho90892fb2016-07-14 14:44:51 +03003103int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
3104 const TSourceLoc &location,
3105 int index,
3106 int arraySize,
Olli Etuaho4de340a2016-12-16 09:32:03 +00003107 const char *reason)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003108{
3109 if (index >= arraySize || index < 0)
3110 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003111 std::stringstream reasonStream;
3112 reasonStream << reason << " '" << index << "'";
3113 std::string token = reasonStream.str();
3114 outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
Olli Etuaho90892fb2016-07-14 14:44:51 +03003115 if (index < 0)
3116 {
3117 return 0;
3118 }
3119 else
3120 {
3121 return arraySize - 1;
3122 }
3123 }
3124 return index;
3125}
3126
Jamie Madillb98c3a82015-07-23 14:26:04 -04003127TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
3128 const TSourceLoc &dotLocation,
3129 const TString &fieldString,
3130 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003131{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003132 if (baseExpression->isArray())
3133 {
3134 error(fieldLocation, "cannot apply dot operator to an array", ".");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003135 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003136 }
3137
3138 if (baseExpression->isVector())
3139 {
3140 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003141 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
3142 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003143 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003144 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003145 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003146 }
3147
Olli Etuahob6fa0432016-09-28 16:28:05 +01003148 return TIntermediate::AddSwizzle(baseExpression, fields, dotLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003149 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003150 else if (baseExpression->getBasicType() == EbtStruct)
3151 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303152 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003153 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003154 {
3155 error(dotLocation, "structure has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003156 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003157 }
3158 else
3159 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003160 bool fieldFound = false;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003161 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003162 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003163 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003164 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003165 {
3166 fieldFound = true;
3167 break;
3168 }
3169 }
3170 if (fieldFound)
3171 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003172 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3173 index->setLine(fieldLocation);
3174 return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003175 dotLocation, mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003176 }
3177 else
3178 {
3179 error(dotLocation, " no such field in structure", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003180 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003181 }
3182 }
3183 }
Jamie Madill98493dd2013-07-08 14:39:03 -04003184 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003185 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303186 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003187 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003188 {
3189 error(dotLocation, "interface block has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003190 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003191 }
3192 else
3193 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003194 bool fieldFound = false;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003195 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003196 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003197 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003198 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003199 {
3200 fieldFound = true;
3201 break;
3202 }
3203 }
3204 if (fieldFound)
3205 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003206 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3207 index->setLine(fieldLocation);
3208 return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003209 dotLocation, mDiagnostics);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003210 }
3211 else
3212 {
3213 error(dotLocation, " no such field in interface block", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003214 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003215 }
3216 }
3217 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003218 else
3219 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003220 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003221 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03003222 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303223 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003224 }
3225 else
3226 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303227 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03003228 " field selection requires structure, vector, or interface block on left hand "
3229 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303230 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003231 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003232 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003233 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003234}
3235
Jamie Madillb98c3a82015-07-23 14:26:04 -04003236TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3237 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003238{
Martin Radev802abe02016-08-04 17:48:32 +03003239 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003240
3241 if (qualifierType == "shared")
3242 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003243 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003244 {
3245 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
3246 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003247 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003248 }
3249 else if (qualifierType == "packed")
3250 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003251 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003252 {
3253 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
3254 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003255 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003256 }
3257 else if (qualifierType == "std140")
3258 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003259 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003260 }
3261 else if (qualifierType == "row_major")
3262 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003263 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003264 }
3265 else if (qualifierType == "column_major")
3266 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003267 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003268 }
3269 else if (qualifierType == "location")
3270 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003271 error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
3272 qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003273 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003274 else if (qualifierType == "rgba32f")
3275 {
3276 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3277 qualifier.imageInternalFormat = EiifRGBA32F;
3278 }
3279 else if (qualifierType == "rgba16f")
3280 {
3281 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3282 qualifier.imageInternalFormat = EiifRGBA16F;
3283 }
3284 else if (qualifierType == "r32f")
3285 {
3286 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3287 qualifier.imageInternalFormat = EiifR32F;
3288 }
3289 else if (qualifierType == "rgba8")
3290 {
3291 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3292 qualifier.imageInternalFormat = EiifRGBA8;
3293 }
3294 else if (qualifierType == "rgba8_snorm")
3295 {
3296 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3297 qualifier.imageInternalFormat = EiifRGBA8_SNORM;
3298 }
3299 else if (qualifierType == "rgba32i")
3300 {
3301 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3302 qualifier.imageInternalFormat = EiifRGBA32I;
3303 }
3304 else if (qualifierType == "rgba16i")
3305 {
3306 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3307 qualifier.imageInternalFormat = EiifRGBA16I;
3308 }
3309 else if (qualifierType == "rgba8i")
3310 {
3311 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3312 qualifier.imageInternalFormat = EiifRGBA8I;
3313 }
3314 else if (qualifierType == "r32i")
3315 {
3316 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3317 qualifier.imageInternalFormat = EiifR32I;
3318 }
3319 else if (qualifierType == "rgba32ui")
3320 {
3321 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3322 qualifier.imageInternalFormat = EiifRGBA32UI;
3323 }
3324 else if (qualifierType == "rgba16ui")
3325 {
3326 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3327 qualifier.imageInternalFormat = EiifRGBA16UI;
3328 }
3329 else if (qualifierType == "rgba8ui")
3330 {
3331 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3332 qualifier.imageInternalFormat = EiifRGBA8UI;
3333 }
3334 else if (qualifierType == "r32ui")
3335 {
3336 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3337 qualifier.imageInternalFormat = EiifR32UI;
3338 }
3339
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003340 else
3341 {
3342 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003343 }
3344
Jamie Madilla5efff92013-06-06 11:56:47 -04003345 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003346}
3347
Martin Radev802abe02016-08-04 17:48:32 +03003348void TParseContext::parseLocalSize(const TString &qualifierType,
3349 const TSourceLoc &qualifierTypeLine,
3350 int intValue,
3351 const TSourceLoc &intValueLine,
3352 const std::string &intValueString,
3353 size_t index,
Martin Radev4c4c8e72016-08-04 12:25:34 +03003354 sh::WorkGroupSize *localSize)
Martin Radev802abe02016-08-04 17:48:32 +03003355{
Olli Etuaho856c4972016-08-08 11:38:39 +03003356 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03003357 if (intValue < 1)
3358 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003359 std::stringstream reasonStream;
3360 reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
3361 std::string reason = reasonStream.str();
3362 error(intValueLine, reason.c_str(), intValueString.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003363 }
3364 (*localSize)[index] = intValue;
3365}
3366
Olli Etuaho09b04a22016-12-15 13:30:26 +00003367void TParseContext::parseNumViews(int intValue,
3368 const TSourceLoc &intValueLine,
3369 const std::string &intValueString,
3370 int *numViews)
3371{
3372 // This error is only specified in WebGL, but tightens unspecified behavior in the native
3373 // specification.
3374 if (intValue < 1)
3375 {
3376 error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
3377 }
3378 *numViews = intValue;
3379}
3380
Jamie Madillb98c3a82015-07-23 14:26:04 -04003381TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3382 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003383 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303384 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003385{
Martin Radev802abe02016-08-04 17:48:32 +03003386 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003387
Martin Radev802abe02016-08-04 17:48:32 +03003388 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003389
Martin Radev802abe02016-08-04 17:48:32 +03003390 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003391 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003392 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003393 if (intValue < 0)
3394 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003395 error(intValueLine, "out of range: location must be non-negative",
3396 intValueString.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003397 }
3398 else
3399 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003400 qualifier.location = intValue;
Olli Etuaho87d410c2016-09-05 13:33:26 +03003401 qualifier.locationsSpecified = 1;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003402 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003403 }
Olli Etuaho43364892017-02-13 16:00:12 +00003404 else if (qualifierType == "binding")
3405 {
3406 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3407 if (intValue < 0)
3408 {
3409 error(intValueLine, "out of range: binding must be non-negative",
3410 intValueString.c_str());
3411 }
3412 else
3413 {
3414 qualifier.binding = intValue;
3415 }
3416 }
Martin Radev802abe02016-08-04 17:48:32 +03003417 else if (qualifierType == "local_size_x")
3418 {
3419 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3420 &qualifier.localSize);
3421 }
3422 else if (qualifierType == "local_size_y")
3423 {
3424 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3425 &qualifier.localSize);
3426 }
3427 else if (qualifierType == "local_size_z")
3428 {
3429 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3430 &qualifier.localSize);
3431 }
Olli Etuaho09b04a22016-12-15 13:30:26 +00003432 else if (qualifierType == "num_views" && mMultiviewAvailable &&
3433 (isExtensionEnabled("GL_OVR_multiview") || isExtensionEnabled("GL_OVR_multiview2")) &&
3434 mShaderType == GL_VERTEX_SHADER)
3435 {
3436 parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
3437 }
Martin Radev802abe02016-08-04 17:48:32 +03003438 else
3439 {
3440 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003441 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003442
Jamie Madilla5efff92013-06-06 11:56:47 -04003443 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003444}
3445
Olli Etuaho613b9592016-09-05 12:05:53 +03003446TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
3447{
3448 return new TTypeQualifierBuilder(
3449 new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
3450 mShaderVersion);
3451}
3452
Jamie Madillb98c3a82015-07-23 14:26:04 -04003453TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003454 TLayoutQualifier rightQualifier,
3455 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003456{
Martin Radevc28888b2016-07-22 15:27:42 +03003457 return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003458 mDiagnostics);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003459}
3460
Olli Etuaho4de340a2016-12-16 09:32:03 +00003461TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
3462 const TFieldList *newlyAddedFields,
3463 const TSourceLoc &location)
3464{
3465 for (TField *field : *newlyAddedFields)
3466 {
3467 for (TField *oldField : *processedFields)
3468 {
3469 if (oldField->name() == field->name())
3470 {
3471 error(location, "duplicate field name in structure", field->name().c_str());
3472 }
3473 }
3474 processedFields->push_back(field);
3475 }
3476 return processedFields;
3477}
3478
Martin Radev70866b82016-07-22 15:27:42 +03003479TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
3480 const TTypeQualifierBuilder &typeQualifierBuilder,
3481 TPublicType *typeSpecifier,
3482 TFieldList *fieldList)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003483{
Olli Etuaho77ba4082016-12-16 12:01:18 +00003484 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003485
Martin Radev70866b82016-07-22 15:27:42 +03003486 typeSpecifier->qualifier = typeQualifier.qualifier;
3487 typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03003488 typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03003489 typeSpecifier->invariant = typeQualifier.invariant;
3490 if (typeQualifier.precision != EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +05303491 {
Martin Radev70866b82016-07-22 15:27:42 +03003492 typeSpecifier->precision = typeQualifier.precision;
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003493 }
Martin Radev70866b82016-07-22 15:27:42 +03003494 return addStructDeclaratorList(*typeSpecifier, fieldList);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003495}
3496
Jamie Madillb98c3a82015-07-23 14:26:04 -04003497TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3498 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003499{
Martin Radev4a9cd802016-09-01 16:51:51 +03003500 checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
3501 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03003502
Martin Radev4a9cd802016-09-01 16:51:51 +03003503 checkIsNonVoid(typeSpecifier.getLine(), (*fieldList)[0]->name(), typeSpecifier.getBasicType());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003504
Martin Radev4a9cd802016-09-01 16:51:51 +03003505 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003506
Arun Patole7e7e68d2015-05-22 12:02:25 +05303507 for (unsigned int i = 0; i < fieldList->size(); ++i)
3508 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003509 //
3510 // Careful not to replace already known aspects of type, like array-ness
3511 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303512 TType *type = (*fieldList)[i]->type();
Martin Radev4a9cd802016-09-01 16:51:51 +03003513 type->setBasicType(typeSpecifier.getBasicType());
3514 type->setPrimarySize(typeSpecifier.getPrimarySize());
3515 type->setSecondarySize(typeSpecifier.getSecondarySize());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003516 type->setPrecision(typeSpecifier.precision);
3517 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003518 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
Martin Radev2cc85b32016-08-05 16:22:53 +03003519 type->setMemoryQualifier(typeSpecifier.memoryQualifier);
Martin Radev70866b82016-07-22 15:27:42 +03003520 type->setInvariant(typeSpecifier.invariant);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003521
3522 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303523 if (type->isArray())
3524 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003525 checkIsValidTypeForArray(typeSpecifier.getLine(), typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003526 }
3527 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003528 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Martin Radev4a9cd802016-09-01 16:51:51 +03003529 if (typeSpecifier.getUserDef())
Arun Patole7e7e68d2015-05-22 12:02:25 +05303530 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003531 type->setStruct(typeSpecifier.getUserDef()->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003532 }
3533
Martin Radev4a9cd802016-09-01 16:51:51 +03003534 checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003535 }
3536
Jamie Madill98493dd2013-07-08 14:39:03 -04003537 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003538}
3539
Martin Radev4a9cd802016-09-01 16:51:51 +03003540TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
3541 const TSourceLoc &nameLine,
3542 const TString *structName,
3543 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003544{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303545 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003546 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003547
Jamie Madill9b820842015-02-12 10:40:10 -05003548 // Store a bool in the struct if we're at global scope, to allow us to
3549 // skip the local struct scoping workaround in HLSL.
Jamie Madill9b820842015-02-12 10:40:10 -05003550 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003551
Jamie Madill98493dd2013-07-08 14:39:03 -04003552 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003553 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003554 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303555 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3556 if (!symbolTable.declare(userTypeDef))
3557 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003558 error(nameLine, "redefinition of a struct", structName->c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003559 }
3560 }
3561
3562 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003563 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003564 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003565 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003566 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003567 switch (qualifier)
3568 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003569 case EvqGlobal:
3570 case EvqTemporary:
3571 break;
3572 default:
3573 error(field.line(), "invalid qualifier on struct member",
3574 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003575 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003576 }
Martin Radev70866b82016-07-22 15:27:42 +03003577 if (field.type()->isInvariant())
3578 {
3579 error(field.line(), "invalid qualifier on struct member", "invariant");
3580 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003581 if (IsImage(field.type()->getBasicType()))
3582 {
3583 error(field.line(), "disallowed type in struct", field.type()->getBasicString());
3584 }
3585
Olli Etuaho43364892017-02-13 16:00:12 +00003586 checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
3587
3588 checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);
Martin Radev70866b82016-07-22 15:27:42 +03003589
3590 checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003591 }
3592
Martin Radev4a9cd802016-09-01 16:51:51 +03003593 TTypeSpecifierNonArray typeSpecifierNonArray;
3594 typeSpecifierNonArray.initialize(EbtStruct, structLine);
3595 typeSpecifierNonArray.userDef = structureType;
3596 typeSpecifierNonArray.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003597 exitStructDeclaration();
3598
Martin Radev4a9cd802016-09-01 16:51:51 +03003599 return typeSpecifierNonArray;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003600}
3601
Jamie Madillb98c3a82015-07-23 14:26:04 -04003602TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01003603 TIntermBlock *statementList,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003604 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003605{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003606 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003607 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003608 init->isVector())
3609 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003610 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3611 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003612 return nullptr;
3613 }
3614
Olli Etuahoac5274d2015-02-20 10:19:08 +02003615 if (statementList)
3616 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00003617 if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
Olli Etuahoac5274d2015-02-20 10:19:08 +02003618 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003619 return nullptr;
3620 }
3621 }
3622
Olli Etuahoa3a36662015-02-17 13:46:51 +02003623 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3624 if (node == nullptr)
3625 {
3626 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003627 return nullptr;
3628 }
3629 return node;
3630}
3631
3632TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3633{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003634 if (mSwitchNestingLevel == 0)
3635 {
3636 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003637 return nullptr;
3638 }
3639 if (condition == nullptr)
3640 {
3641 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003642 return nullptr;
3643 }
3644 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003645 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003646 {
3647 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003648 }
3649 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003650 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3651 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3652 // fold in case labels.
3653 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003654 {
3655 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003656 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003657 TIntermCase *node = intermediate.addCase(condition, loc);
3658 if (node == nullptr)
3659 {
3660 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003661 return nullptr;
3662 }
3663 return node;
3664}
3665
3666TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3667{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003668 if (mSwitchNestingLevel == 0)
3669 {
3670 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003671 return nullptr;
3672 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003673 TIntermCase *node = intermediate.addCase(nullptr, loc);
3674 if (node == nullptr)
3675 {
3676 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003677 return nullptr;
3678 }
3679 return node;
3680}
3681
Jamie Madillb98c3a82015-07-23 14:26:04 -04003682TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3683 TIntermTyped *child,
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003684 const TSourceLoc &loc)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003685{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003686 ASSERT(child != nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003687
3688 switch (op)
3689 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003690 case EOpLogicalNot:
3691 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3692 child->isVector())
3693 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003694 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003695 return nullptr;
3696 }
3697 break;
3698 case EOpBitwiseNot:
3699 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3700 child->isMatrix() || child->isArray())
3701 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003702 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003703 return nullptr;
3704 }
3705 break;
3706 case EOpPostIncrement:
3707 case EOpPreIncrement:
3708 case EOpPostDecrement:
3709 case EOpPreDecrement:
3710 case EOpNegative:
3711 case EOpPositive:
3712 if (child->getBasicType() == EbtStruct || child->getBasicType() == EbtBool ||
Martin Radev2cc85b32016-08-05 16:22:53 +03003713 child->isArray() || IsOpaqueType(child->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -04003714 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003715 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003716 return nullptr;
3717 }
3718 // Operators for built-ins are already type checked against their prototype.
3719 default:
3720 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003721 }
3722
Olli Etuahof119a262016-08-19 15:54:22 +03003723 TIntermUnary *node = new TIntermUnary(op, child);
3724 node->setLine(loc);
Olli Etuahof119a262016-08-19 15:54:22 +03003725
Olli Etuaho77ba4082016-12-16 12:01:18 +00003726 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuahof119a262016-08-19 15:54:22 +03003727 if (foldedNode)
3728 return foldedNode;
3729
3730 return node;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003731}
3732
Olli Etuaho09b22472015-02-11 11:47:26 +02003733TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3734{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003735 TIntermTyped *node = createUnaryMath(op, child, loc);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003736 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003737 {
Olli Etuaho09b22472015-02-11 11:47:26 +02003738 return child;
3739 }
3740 return node;
3741}
3742
Jamie Madillb98c3a82015-07-23 14:26:04 -04003743TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3744 TIntermTyped *child,
3745 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003746{
Olli Etuaho856c4972016-08-08 11:38:39 +03003747 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003748 return addUnaryMath(op, child, loc);
3749}
3750
Jamie Madillb98c3a82015-07-23 14:26:04 -04003751bool TParseContext::binaryOpCommonCheck(TOperator op,
3752 TIntermTyped *left,
3753 TIntermTyped *right,
3754 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003755{
Olli Etuaho244be012016-08-18 15:26:02 +03003756 if (left->getType().getStruct() || right->getType().getStruct())
3757 {
3758 switch (op)
3759 {
3760 case EOpIndexDirectStruct:
3761 ASSERT(left->getType().getStruct());
3762 break;
3763 case EOpEqual:
3764 case EOpNotEqual:
3765 case EOpAssign:
3766 case EOpInitialize:
3767 if (left->getType() != right->getType())
3768 {
3769 return false;
3770 }
3771 break;
3772 default:
3773 error(loc, "Invalid operation for structs", GetOperatorString(op));
3774 return false;
3775 }
3776 }
3777
Olli Etuahod6b14282015-03-17 14:31:35 +02003778 if (left->isArray() || right->isArray())
3779 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003780 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003781 {
3782 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3783 return false;
3784 }
3785
3786 if (left->isArray() != right->isArray())
3787 {
3788 error(loc, "array / non-array mismatch", GetOperatorString(op));
3789 return false;
3790 }
3791
3792 switch (op)
3793 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003794 case EOpEqual:
3795 case EOpNotEqual:
3796 case EOpAssign:
3797 case EOpInitialize:
3798 break;
3799 default:
3800 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3801 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02003802 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03003803 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02003804 if (left->getArraySize() != right->getArraySize())
3805 {
3806 error(loc, "array size mismatch", GetOperatorString(op));
3807 return false;
3808 }
Olli Etuahod6b14282015-03-17 14:31:35 +02003809 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003810
3811 // Check ops which require integer / ivec parameters
3812 bool isBitShift = false;
3813 switch (op)
3814 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003815 case EOpBitShiftLeft:
3816 case EOpBitShiftRight:
3817 case EOpBitShiftLeftAssign:
3818 case EOpBitShiftRightAssign:
3819 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3820 // check that the basic type is an integer type.
3821 isBitShift = true;
3822 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3823 {
3824 return false;
3825 }
3826 break;
3827 case EOpBitwiseAnd:
3828 case EOpBitwiseXor:
3829 case EOpBitwiseOr:
3830 case EOpBitwiseAndAssign:
3831 case EOpBitwiseXorAssign:
3832 case EOpBitwiseOrAssign:
3833 // It is enough to check the type of only one operand, since later it
3834 // is checked that the operand types match.
3835 if (!IsInteger(left->getBasicType()))
3836 {
3837 return false;
3838 }
3839 break;
3840 default:
3841 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003842 }
3843
3844 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3845 // So the basic type should usually match.
3846 if (!isBitShift && left->getBasicType() != right->getBasicType())
3847 {
3848 return false;
3849 }
3850
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003851 // Check that:
3852 // 1. Type sizes match exactly on ops that require that.
3853 // 2. Restrictions for structs that contain arrays or samplers are respected.
3854 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
Jamie Madillb98c3a82015-07-23 14:26:04 -04003855 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003856 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003857 case EOpAssign:
3858 case EOpInitialize:
3859 case EOpEqual:
3860 case EOpNotEqual:
3861 // ESSL 1.00 sections 5.7, 5.8, 5.9
3862 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
3863 {
3864 error(loc, "undefined operation for structs containing arrays",
3865 GetOperatorString(op));
3866 return false;
3867 }
3868 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3869 // we interpret the spec so that this extends to structs containing samplers,
3870 // similarly to ESSL 1.00 spec.
3871 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
3872 left->getType().isStructureContainingSamplers())
3873 {
3874 error(loc, "undefined operation for structs containing samplers",
3875 GetOperatorString(op));
3876 return false;
3877 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003878
3879 if ((op == EOpAssign || op == EOpInitialize) &&
3880 left->getType().isStructureContainingImages())
3881 {
3882 error(loc, "undefined operation for structs containing images",
3883 GetOperatorString(op));
3884 return false;
3885 }
Olli Etuahoe1805592017-01-02 16:41:20 +00003886 if ((left->getNominalSize() != right->getNominalSize()) ||
3887 (left->getSecondarySize() != right->getSecondarySize()))
3888 {
3889 error(loc, "dimension mismatch", GetOperatorString(op));
3890 return false;
3891 }
3892 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003893 case EOpLessThan:
3894 case EOpGreaterThan:
3895 case EOpLessThanEqual:
3896 case EOpGreaterThanEqual:
Olli Etuahoe1805592017-01-02 16:41:20 +00003897 if (!left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04003898 {
Olli Etuahoe1805592017-01-02 16:41:20 +00003899 error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003900 return false;
3901 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003902 break;
3903 case EOpAdd:
3904 case EOpSub:
3905 case EOpDiv:
3906 case EOpIMod:
3907 case EOpBitShiftLeft:
3908 case EOpBitShiftRight:
3909 case EOpBitwiseAnd:
3910 case EOpBitwiseXor:
3911 case EOpBitwiseOr:
3912 case EOpAddAssign:
3913 case EOpSubAssign:
3914 case EOpDivAssign:
3915 case EOpIModAssign:
3916 case EOpBitShiftLeftAssign:
3917 case EOpBitShiftRightAssign:
3918 case EOpBitwiseAndAssign:
3919 case EOpBitwiseXorAssign:
3920 case EOpBitwiseOrAssign:
3921 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
3922 {
3923 return false;
3924 }
3925
3926 // Are the sizes compatible?
3927 if (left->getNominalSize() != right->getNominalSize() ||
3928 left->getSecondarySize() != right->getSecondarySize())
3929 {
3930 // If the nominal sizes of operands do not match:
3931 // One of them must be a scalar.
3932 if (!left->isScalar() && !right->isScalar())
3933 return false;
3934
3935 // In the case of compound assignment other than multiply-assign,
3936 // the right side needs to be a scalar. Otherwise a vector/matrix
3937 // would be assigned to a scalar. A scalar can't be shifted by a
3938 // vector either.
3939 if (!right->isScalar() &&
3940 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
3941 return false;
3942 }
3943 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003944 default:
3945 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003946 }
3947
Olli Etuahod6b14282015-03-17 14:31:35 +02003948 return true;
3949}
3950
Olli Etuaho1dded802016-08-18 18:13:13 +03003951bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
3952 const TType &left,
3953 const TType &right)
3954{
3955 switch (op)
3956 {
3957 case EOpMul:
3958 case EOpMulAssign:
3959 return left.getNominalSize() == right.getNominalSize() &&
3960 left.getSecondarySize() == right.getSecondarySize();
3961 case EOpVectorTimesScalar:
3962 return true;
3963 case EOpVectorTimesScalarAssign:
3964 ASSERT(!left.isMatrix() && !right.isMatrix());
3965 return left.isVector() && !right.isVector();
3966 case EOpVectorTimesMatrix:
3967 return left.getNominalSize() == right.getRows();
3968 case EOpVectorTimesMatrixAssign:
3969 ASSERT(!left.isMatrix() && right.isMatrix());
3970 return left.isVector() && left.getNominalSize() == right.getRows() &&
3971 left.getNominalSize() == right.getCols();
3972 case EOpMatrixTimesVector:
3973 return left.getCols() == right.getNominalSize();
3974 case EOpMatrixTimesScalar:
3975 return true;
3976 case EOpMatrixTimesScalarAssign:
3977 ASSERT(left.isMatrix() && !right.isMatrix());
3978 return !right.isVector();
3979 case EOpMatrixTimesMatrix:
3980 return left.getCols() == right.getRows();
3981 case EOpMatrixTimesMatrixAssign:
3982 ASSERT(left.isMatrix() && right.isMatrix());
3983 // We need to check two things:
3984 // 1. The matrix multiplication step is valid.
3985 // 2. The result will have the same number of columns as the lvalue.
3986 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
3987
3988 default:
3989 UNREACHABLE();
3990 return false;
3991 }
3992}
3993
Jamie Madillb98c3a82015-07-23 14:26:04 -04003994TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
3995 TIntermTyped *left,
3996 TIntermTyped *right,
3997 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02003998{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003999 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004000 return nullptr;
4001
Olli Etuahofc1806e2015-03-17 13:03:11 +02004002 switch (op)
4003 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004004 case EOpEqual:
4005 case EOpNotEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04004006 case EOpLessThan:
4007 case EOpGreaterThan:
4008 case EOpLessThanEqual:
4009 case EOpGreaterThanEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04004010 break;
4011 case EOpLogicalOr:
4012 case EOpLogicalXor:
4013 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03004014 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4015 !right->getType().getStruct());
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00004016 if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04004017 {
4018 return nullptr;
4019 }
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00004020 // Basic types matching should have been already checked.
4021 ASSERT(right->getBasicType() == EbtBool);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004022 break;
4023 case EOpAdd:
4024 case EOpSub:
4025 case EOpDiv:
4026 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03004027 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4028 !right->getType().getStruct());
4029 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04004030 {
4031 return nullptr;
4032 }
4033 break;
4034 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03004035 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4036 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004037 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03004038 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04004039 {
4040 return nullptr;
4041 }
4042 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004043 default:
4044 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02004045 }
4046
Olli Etuaho1dded802016-08-18 18:13:13 +03004047 if (op == EOpMul)
4048 {
4049 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
4050 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4051 {
4052 return nullptr;
4053 }
4054 }
4055
Olli Etuaho3fdec912016-08-18 15:08:06 +03004056 TIntermBinary *node = new TIntermBinary(op, left, right);
4057 node->setLine(loc);
4058
Olli Etuaho3fdec912016-08-18 15:08:06 +03004059 // See if we can fold constants.
Olli Etuaho77ba4082016-12-16 12:01:18 +00004060 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuaho3fdec912016-08-18 15:08:06 +03004061 if (foldedNode)
4062 return foldedNode;
4063
4064 return node;
Olli Etuahofc1806e2015-03-17 13:03:11 +02004065}
4066
Jamie Madillb98c3a82015-07-23 14:26:04 -04004067TIntermTyped *TParseContext::addBinaryMath(TOperator op,
4068 TIntermTyped *left,
4069 TIntermTyped *right,
4070 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004071{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004072 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004073 if (node == 0)
4074 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004075 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4076 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02004077 return left;
4078 }
4079 return node;
4080}
4081
Jamie Madillb98c3a82015-07-23 14:26:04 -04004082TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
4083 TIntermTyped *left,
4084 TIntermTyped *right,
4085 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004086{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004087 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004088 if (node == 0)
4089 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004090 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4091 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04004092 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02004093 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004094 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
4095 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004096 }
4097 return node;
4098}
4099
Olli Etuaho13389b62016-10-16 11:48:18 +01004100TIntermBinary *TParseContext::createAssign(TOperator op,
4101 TIntermTyped *left,
4102 TIntermTyped *right,
4103 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004104{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004105 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004106 {
Olli Etuaho1dded802016-08-18 18:13:13 +03004107 if (op == EOpMulAssign)
4108 {
4109 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
4110 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4111 {
4112 return nullptr;
4113 }
4114 }
Olli Etuaho3fdec912016-08-18 15:08:06 +03004115 TIntermBinary *node = new TIntermBinary(op, left, right);
4116 node->setLine(loc);
4117
Olli Etuaho3fdec912016-08-18 15:08:06 +03004118 return node;
Olli Etuahod6b14282015-03-17 14:31:35 +02004119 }
4120 return nullptr;
4121}
4122
Jamie Madillb98c3a82015-07-23 14:26:04 -04004123TIntermTyped *TParseContext::addAssign(TOperator op,
4124 TIntermTyped *left,
4125 TIntermTyped *right,
4126 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004127{
4128 TIntermTyped *node = createAssign(op, left, right, loc);
4129 if (node == nullptr)
4130 {
4131 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02004132 return left;
4133 }
4134 return node;
4135}
4136
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004137TIntermTyped *TParseContext::addComma(TIntermTyped *left,
4138 TIntermTyped *right,
4139 const TSourceLoc &loc)
4140{
Corentin Wallez0d959252016-07-12 17:26:32 -04004141 // WebGL2 section 5.26, the following results in an error:
4142 // "Sequence operator applied to void, arrays, or structs containing arrays"
Jamie Madilld7b1ab52016-12-12 14:42:19 -05004143 if (mShaderSpec == SH_WEBGL2_SPEC &&
4144 (left->isArray() || left->getBasicType() == EbtVoid ||
4145 left->getType().isStructureContainingArrays() || right->isArray() ||
4146 right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
Corentin Wallez0d959252016-07-12 17:26:32 -04004147 {
4148 error(loc,
4149 "sequence operator is not allowed for void, arrays, or structs containing arrays",
4150 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04004151 }
4152
Olli Etuaho4db7ded2016-10-13 12:23:11 +01004153 return TIntermediate::AddComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004154}
4155
Olli Etuaho49300862015-02-20 14:54:49 +02004156TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
4157{
4158 switch (op)
4159 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004160 case EOpContinue:
4161 if (mLoopNestingLevel <= 0)
4162 {
4163 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004164 }
4165 break;
4166 case EOpBreak:
4167 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
4168 {
4169 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004170 }
4171 break;
4172 case EOpReturn:
4173 if (mCurrentFunctionType->getBasicType() != EbtVoid)
4174 {
4175 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004176 }
4177 break;
4178 default:
4179 // No checks for discard
4180 break;
Olli Etuaho49300862015-02-20 14:54:49 +02004181 }
4182 return intermediate.addBranch(op, loc);
4183}
4184
Jamie Madillb98c3a82015-07-23 14:26:04 -04004185TIntermBranch *TParseContext::addBranch(TOperator op,
4186 TIntermTyped *returnValue,
4187 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02004188{
4189 ASSERT(op == EOpReturn);
4190 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004191 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02004192 {
4193 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004194 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004195 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02004196 {
4197 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004198 }
4199 return intermediate.addBranch(op, returnValue, loc);
4200}
4201
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004202void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
4203{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004204 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Olli Etuahobd674552016-10-06 13:28:42 +01004205 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004206 TIntermNode *offset = nullptr;
4207 TIntermSequence *arguments = functionCall->getSequence();
4208 if (name.compare(0, 16, "texelFetchOffset") == 0 ||
4209 name.compare(0, 16, "textureLodOffset") == 0 ||
4210 name.compare(0, 20, "textureProjLodOffset") == 0 ||
4211 name.compare(0, 17, "textureGradOffset") == 0 ||
4212 name.compare(0, 21, "textureProjGradOffset") == 0)
4213 {
4214 offset = arguments->back();
4215 }
4216 else if (name.compare(0, 13, "textureOffset") == 0 ||
4217 name.compare(0, 17, "textureProjOffset") == 0)
4218 {
4219 // A bias parameter might follow the offset parameter.
4220 ASSERT(arguments->size() >= 3);
4221 offset = (*arguments)[2];
4222 }
4223 if (offset != nullptr)
4224 {
4225 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
4226 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
4227 {
4228 TString unmangledName = TFunction::unmangleName(name);
4229 error(functionCall->getLine(), "Texture offset must be a constant expression",
4230 unmangledName.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004231 }
4232 else
4233 {
4234 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
4235 size_t size = offsetConstantUnion->getType().getObjectSize();
4236 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
4237 for (size_t i = 0u; i < size; ++i)
4238 {
4239 int offsetValue = values[i].getIConst();
4240 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
4241 {
4242 std::stringstream tokenStream;
4243 tokenStream << offsetValue;
4244 std::string token = tokenStream.str();
4245 error(offset->getLine(), "Texture offset value out of valid range",
4246 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004247 }
4248 }
4249 }
4250 }
4251}
4252
Martin Radev2cc85b32016-08-05 16:22:53 +03004253// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
4254void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
4255{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004256 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Martin Radev2cc85b32016-08-05 16:22:53 +03004257 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
4258
4259 if (name.compare(0, 5, "image") == 0)
4260 {
4261 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuaho485eefd2017-02-14 17:40:06 +00004262 TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
Martin Radev2cc85b32016-08-05 16:22:53 +03004263
Olli Etuaho485eefd2017-02-14 17:40:06 +00004264 const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
Martin Radev2cc85b32016-08-05 16:22:53 +03004265
4266 if (name.compare(5, 5, "Store") == 0)
4267 {
4268 if (memoryQualifier.readonly)
4269 {
4270 error(imageNode->getLine(),
4271 "'imageStore' cannot be used with images qualified as 'readonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004272 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03004273 }
4274 }
4275 else if (name.compare(5, 4, "Load") == 0)
4276 {
4277 if (memoryQualifier.writeonly)
4278 {
4279 error(imageNode->getLine(),
4280 "'imageLoad' cannot be used with images qualified as 'writeonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004281 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03004282 }
4283 }
4284 }
4285}
4286
4287// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
4288void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
4289 const TFunction *functionDefinition,
4290 const TIntermAggregate *functionCall)
4291{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004292 ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
Martin Radev2cc85b32016-08-05 16:22:53 +03004293
4294 const TIntermSequence &arguments = *functionCall->getSequence();
4295
4296 ASSERT(functionDefinition->getParamCount() == arguments.size());
4297
4298 for (size_t i = 0; i < arguments.size(); ++i)
4299 {
Olli Etuaho485eefd2017-02-14 17:40:06 +00004300 TIntermTyped *typedArgument = arguments[i]->getAsTyped();
4301 const TType &functionArgumentType = typedArgument->getType();
Martin Radev2cc85b32016-08-05 16:22:53 +03004302 const TType &functionParameterType = *functionDefinition->getParam(i).type;
4303 ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
4304
4305 if (IsImage(functionArgumentType.getBasicType()))
4306 {
4307 const TMemoryQualifier &functionArgumentMemoryQualifier =
4308 functionArgumentType.getMemoryQualifier();
4309 const TMemoryQualifier &functionParameterMemoryQualifier =
4310 functionParameterType.getMemoryQualifier();
4311 if (functionArgumentMemoryQualifier.readonly &&
4312 !functionParameterMemoryQualifier.readonly)
4313 {
4314 error(functionCall->getLine(),
4315 "Function call discards the 'readonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004316 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03004317 }
4318
4319 if (functionArgumentMemoryQualifier.writeonly &&
4320 !functionParameterMemoryQualifier.writeonly)
4321 {
4322 error(functionCall->getLine(),
4323 "Function call discards the 'writeonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004324 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03004325 }
Martin Radev049edfa2016-11-11 14:35:37 +02004326
4327 if (functionArgumentMemoryQualifier.coherent &&
4328 !functionParameterMemoryQualifier.coherent)
4329 {
4330 error(functionCall->getLine(),
4331 "Function call discards the 'coherent' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004332 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02004333 }
4334
4335 if (functionArgumentMemoryQualifier.volatileQualifier &&
4336 !functionParameterMemoryQualifier.volatileQualifier)
4337 {
4338 error(functionCall->getLine(),
4339 "Function call discards the 'volatile' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004340 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02004341 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004342 }
4343 }
4344}
4345
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004346TIntermSequence *TParseContext::createEmptyArgumentsList()
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004347{
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004348 return new TIntermSequence();
Olli Etuaho72d10202017-01-19 15:58:30 +00004349}
4350
4351TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004352 TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00004353 TIntermNode *thisNode,
4354 const TSourceLoc &loc)
4355{
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004356 if (thisNode != nullptr)
4357 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004358 return addMethod(fnCall, arguments, thisNode, loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004359 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004360
4361 TOperator op = fnCall->getBuiltInOp();
4362 if (op != EOpNull)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004363 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004364 return addConstructor(arguments, op, fnCall->getReturnType(), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004365 }
4366 else
4367 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004368 return addNonConstructorFunctionCall(fnCall, arguments, loc);
4369 }
4370}
4371
4372TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
4373 TIntermSequence *arguments,
4374 TIntermNode *thisNode,
4375 const TSourceLoc &loc)
4376{
4377 TConstantUnion *unionArray = new TConstantUnion[1];
4378 int arraySize = 0;
4379 TIntermTyped *typedThis = thisNode->getAsTyped();
4380 // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
4381 // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
4382 // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
4383 // So accessing fnCall->getName() below is safe.
4384 if (fnCall->getName() != "length")
4385 {
4386 error(loc, "invalid method", fnCall->getName().c_str());
4387 }
4388 else if (!arguments->empty())
4389 {
4390 error(loc, "method takes no parameters", "length");
4391 }
4392 else if (typedThis == nullptr || !typedThis->isArray())
4393 {
4394 error(loc, "length can only be called on arrays", "length");
4395 }
4396 else
4397 {
4398 arraySize = typedThis->getArraySize();
4399 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuaho72d10202017-01-19 15:58:30 +00004400 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004401 // This code path can be hit with expressions like these:
4402 // (a = b).length()
4403 // (func()).length()
4404 // (int[3](0, 1, 2)).length()
4405 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
4406 // expression.
4407 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
4408 // spec section 5.9 which allows "An array, vector or matrix expression with the
4409 // length method applied".
4410 error(loc, "length can only be called on array names, not on array expressions",
4411 "length");
Olli Etuaho72d10202017-01-19 15:58:30 +00004412 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004413 }
4414 unionArray->setIConst(arraySize);
4415 return intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
4416}
4417
4418TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
4419 TIntermSequence *arguments,
4420 const TSourceLoc &loc)
4421{
4422 // First find by unmangled name to check whether the function name has been
4423 // hidden by a variable name or struct typename.
4424 // If a function is found, check for one with a matching argument list.
4425 bool builtIn;
4426 const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn);
4427 if (symbol != nullptr && !symbol->isFunction())
4428 {
4429 error(loc, "function name expected", fnCall->getName().c_str());
4430 }
4431 else
4432 {
4433 symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments),
4434 mShaderVersion, &builtIn);
4435 if (symbol == nullptr)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004436 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004437 error(loc, "no matching overloaded function found", fnCall->getName().c_str());
4438 }
4439 else
4440 {
4441 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004442 //
4443 // A declared function.
4444 //
Olli Etuaho383b7912016-08-05 11:22:59 +03004445 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004446 {
Olli Etuaho856c4972016-08-08 11:38:39 +03004447 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004448 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004449 TOperator op = fnCandidate->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004450 if (builtIn && op != EOpNull)
4451 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004452 // A function call mapped to a built-in operation.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004453 if (fnCandidate->getParamCount() == 1)
4454 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004455 // Treat it like a built-in unary operator.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004456 TIntermNode *unaryParamNode = arguments->front();
4457 TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004458 ASSERT(callNode != nullptr);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004459 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004460 }
4461 else
4462 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004463 TIntermAggregate *callNode =
4464 new TIntermAggregate(fnCandidate->getReturnType(), op, arguments);
4465 callNode->setLine(loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004466
4467 // Some built-in functions have out parameters too.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004468 functionCallLValueErrorCheck(fnCandidate, callNode);
Arun Patole274f0702015-05-05 13:33:30 +05304469
Olli Etuaho7c3848e2015-11-04 13:19:17 +02004470 // See if we can constant fold a built-in. Note that this may be possible even
4471 // if it is not const-qualified.
Olli Etuahof119a262016-08-19 15:54:22 +03004472 TIntermTyped *foldedNode =
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004473 intermediate.foldAggregateBuiltIn(callNode, mDiagnostics);
Arun Patole274f0702015-05-05 13:33:30 +05304474 if (foldedNode)
4475 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004476 return foldedNode;
Arun Patole274f0702015-05-05 13:33:30 +05304477 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004478 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004479 }
4480 }
4481 else
4482 {
4483 // This is a real function call
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004484 TIntermAggregate *callNode = nullptr;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004485
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004486 // If builtIn == false, the function is user defined - could be an overloaded
4487 // built-in as well.
4488 // if builtIn == true, it's a builtIn function with no op associated with it.
4489 // This needs to happen after the function info including name is set.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004490 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004491 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004492 callNode = new TIntermAggregate(fnCandidate->getReturnType(),
4493 EOpCallBuiltInFunction, arguments);
4494 // Note that name needs to be set before texture function type is determined.
4495 callNode->getFunctionSymbolInfo()->setFromFunction(*fnCandidate);
4496 callNode->setBuiltInFunctionPrecision();
4497 checkTextureOffsetConst(callNode);
4498 checkImageMemoryAccessForBuiltinFunctions(callNode);
Martin Radev2cc85b32016-08-05 16:22:53 +03004499 }
4500 else
4501 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004502 callNode = new TIntermAggregate(fnCandidate->getReturnType(),
4503 EOpCallFunctionInAST, arguments);
4504 callNode->getFunctionSymbolInfo()->setFromFunction(*fnCandidate);
4505 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004506 }
4507
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004508 functionCallLValueErrorCheck(fnCandidate, callNode);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004509
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004510 callNode->setLine(loc);
4511
4512 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004513 }
4514 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004515 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004516
4517 // Error message was already written. Put on a dummy node for error recovery.
4518 return TIntermTyped::CreateZero(TType(EbtFloat, EbpMedium, EvqConst));
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004519}
4520
Jamie Madillb98c3a82015-07-23 14:26:04 -04004521TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004522 TIntermTyped *trueExpression,
4523 TIntermTyped *falseExpression,
Olli Etuaho52901742015-04-15 13:42:45 +03004524 const TSourceLoc &loc)
4525{
Olli Etuaho856c4972016-08-08 11:38:39 +03004526 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03004527
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004528 if (trueExpression->getType() != falseExpression->getType())
Olli Etuaho52901742015-04-15 13:42:45 +03004529 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004530 binaryOpError(loc, ":", trueExpression->getCompleteString(),
4531 falseExpression->getCompleteString());
4532 return falseExpression;
Olli Etuaho52901742015-04-15 13:42:45 +03004533 }
Olli Etuahode318b22016-10-25 16:18:25 +01004534 if (IsOpaqueType(trueExpression->getBasicType()))
4535 {
4536 // ESSL 1.00 section 4.1.7
4537 // ESSL 3.00 section 4.1.7
4538 // Opaque/sampler types are not allowed in most types of expressions, including ternary.
4539 // Note that structs containing opaque types don't need to be checked as structs are
4540 // forbidden below.
4541 error(loc, "ternary operator is not allowed for opaque types", ":");
4542 return falseExpression;
4543 }
4544
Olli Etuahoa2d53032015-04-15 14:14:44 +03004545 // ESSL1 sections 5.2 and 5.7:
4546 // ESSL3 section 5.7:
4547 // Ternary operator is not among the operators allowed for structures/arrays.
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004548 if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
Olli Etuahoa2d53032015-04-15 14:14:44 +03004549 {
4550 error(loc, "ternary operator is not allowed for structures or arrays", ":");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004551 return falseExpression;
Olli Etuahoa2d53032015-04-15 14:14:44 +03004552 }
Corentin Wallez0d959252016-07-12 17:26:32 -04004553 // WebGL2 section 5.26, the following results in an error:
4554 // "Ternary operator applied to void, arrays, or structs containing arrays"
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004555 if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
Corentin Wallez0d959252016-07-12 17:26:32 -04004556 {
4557 error(loc, "ternary operator is not allowed for void", ":");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004558 return falseExpression;
Corentin Wallez0d959252016-07-12 17:26:32 -04004559 }
4560
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004561 return TIntermediate::AddTernarySelection(cond, trueExpression, falseExpression, loc);
Olli Etuaho52901742015-04-15 13:42:45 +03004562}
Olli Etuaho49300862015-02-20 14:54:49 +02004563
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004564//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004565// Parse an array of strings using yyparse.
4566//
4567// Returns 0 for success.
4568//
Jamie Madillb98c3a82015-07-23 14:26:04 -04004569int PaParseStrings(size_t count,
4570 const char *const string[],
4571 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05304572 TParseContext *context)
4573{
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004574 if ((count == 0) || (string == NULL))
4575 return 1;
4576
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004577 if (glslang_initialize(context))
4578 return 1;
4579
alokp@chromium.org408c45e2012-04-05 15:54:43 +00004580 int error = glslang_scan(count, string, length, context);
4581 if (!error)
4582 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004583
alokp@chromium.org73bc2982012-06-19 18:48:05 +00004584 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00004585
alokp@chromium.org6b495712012-06-29 00:06:58 +00004586 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004587}
Jamie Madill45bcc782016-11-07 13:58:48 -05004588
4589} // namespace sh