blob: 7210de5f286def0818576960bf96c86151178aca [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
jchen10cc2a10e2017-05-03 14:05:12 +080038 if (type.getBasicType() == EbtStruct)
Martin Radev2cc85b32016-08-05 16:22:53 +030039 {
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
Olli Etuaho485eefd2017-02-14 17:40:06 +000051// Get a token from an image argument to use as an error message token.
52const char *GetImageArgumentToken(TIntermTyped *imageNode)
53{
54 ASSERT(IsImage(imageNode->getBasicType()));
55 while (imageNode->getAsBinaryNode() &&
56 (imageNode->getAsBinaryNode()->getOp() == EOpIndexIndirect ||
57 imageNode->getAsBinaryNode()->getOp() == EOpIndexDirect))
58 {
59 imageNode = imageNode->getAsBinaryNode()->getLeft();
60 }
61 TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode();
62 if (imageSymbol)
63 {
64 return imageSymbol->getSymbol().c_str();
65 }
66 return "image";
67}
68
Martin Radev2cc85b32016-08-05 16:22:53 +030069} // namespace
70
Jamie Madillacb4b812016-11-07 13:50:29 -050071TParseContext::TParseContext(TSymbolTable &symt,
72 TExtensionBehavior &ext,
73 sh::GLenum type,
74 ShShaderSpec spec,
75 ShCompileOptions options,
76 bool checksPrecErrors,
Olli Etuaho77ba4082016-12-16 12:01:18 +000077 TDiagnostics *diagnostics,
Jamie Madillacb4b812016-11-07 13:50:29 -050078 const ShBuiltInResources &resources)
79 : intermediate(),
80 symbolTable(symt),
Olli Etuahobb7e5a72017-04-24 10:16:44 +030081 mDeferredNonEmptyDeclarationErrorCheck(false),
Jamie Madillacb4b812016-11-07 13:50:29 -050082 mShaderType(type),
83 mShaderSpec(spec),
84 mCompileOptions(options),
85 mShaderVersion(100),
86 mTreeRoot(nullptr),
87 mLoopNestingLevel(0),
88 mStructNestingLevel(0),
89 mSwitchNestingLevel(0),
90 mCurrentFunctionType(nullptr),
91 mFunctionReturnsValue(false),
92 mChecksPrecisionErrors(checksPrecErrors),
93 mFragmentPrecisionHighOnESSL1(false),
94 mDefaultMatrixPacking(EmpColumnMajor),
95 mDefaultBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
Olli Etuaho77ba4082016-12-16 12:01:18 +000096 mDiagnostics(diagnostics),
Jamie Madillacb4b812016-11-07 13:50:29 -050097 mDirectiveHandler(ext,
Olli Etuaho77ba4082016-12-16 12:01:18 +000098 *mDiagnostics,
Jamie Madillacb4b812016-11-07 13:50:29 -050099 mShaderVersion,
100 mShaderType,
101 resources.WEBGL_debug_shader_precision == 1),
Olli Etuaho77ba4082016-12-16 12:01:18 +0000102 mPreprocessor(mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()),
Jamie Madillacb4b812016-11-07 13:50:29 -0500103 mScanner(nullptr),
104 mUsesFragData(false),
105 mUsesFragColor(false),
106 mUsesSecondaryOutputs(false),
107 mMinProgramTexelOffset(resources.MinProgramTexelOffset),
108 mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
Olli Etuaho09b04a22016-12-15 13:30:26 +0000109 mMultiviewAvailable(resources.OVR_multiview == 1),
Jamie Madillacb4b812016-11-07 13:50:29 -0500110 mComputeShaderLocalSizeDeclared(false),
Olli Etuaho09b04a22016-12-15 13:30:26 +0000111 mNumViews(-1),
112 mMaxNumViews(resources.MaxViewsOVR),
Olli Etuaho43364892017-02-13 16:00:12 +0000113 mMaxImageUnits(resources.MaxImageUnits),
114 mMaxCombinedTextureImageUnits(resources.MaxCombinedTextureImageUnits),
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000115 mMaxUniformLocations(resources.MaxUniformLocations),
Jamie Madillacb4b812016-11-07 13:50:29 -0500116 mDeclaringFunction(false)
117{
118 mComputeShaderLocalSize.fill(-1);
119}
120
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000121//
122// Look at a '.' field selector string and change it into offsets
123// for a vector.
124//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400125bool TParseContext::parseVectorFields(const TString &compString,
126 int vecSize,
127 TVectorFields &fields,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530128 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400130 fields.num = (int)compString.size();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530131 if (fields.num > 4)
132 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000133 error(line, "illegal vector field selection", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000134 return false;
135 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136
Jamie Madillb98c3a82015-07-23 14:26:04 -0400137 enum
138 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000139 exyzw,
140 ergba,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000141 estpq
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000142 } fieldSet[4];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000143
Arun Patole7e7e68d2015-05-22 12:02:25 +0530144 for (int i = 0; i < fields.num; ++i)
145 {
146 switch (compString[i])
147 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400148 case 'x':
149 fields.offsets[i] = 0;
150 fieldSet[i] = exyzw;
151 break;
152 case 'r':
153 fields.offsets[i] = 0;
154 fieldSet[i] = ergba;
155 break;
156 case 's':
157 fields.offsets[i] = 0;
158 fieldSet[i] = estpq;
159 break;
160 case 'y':
161 fields.offsets[i] = 1;
162 fieldSet[i] = exyzw;
163 break;
164 case 'g':
165 fields.offsets[i] = 1;
166 fieldSet[i] = ergba;
167 break;
168 case 't':
169 fields.offsets[i] = 1;
170 fieldSet[i] = estpq;
171 break;
172 case 'z':
173 fields.offsets[i] = 2;
174 fieldSet[i] = exyzw;
175 break;
176 case 'b':
177 fields.offsets[i] = 2;
178 fieldSet[i] = ergba;
179 break;
180 case 'p':
181 fields.offsets[i] = 2;
182 fieldSet[i] = estpq;
183 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530184
Jamie Madillb98c3a82015-07-23 14:26:04 -0400185 case 'w':
186 fields.offsets[i] = 3;
187 fieldSet[i] = exyzw;
188 break;
189 case 'a':
190 fields.offsets[i] = 3;
191 fieldSet[i] = ergba;
192 break;
193 case 'q':
194 fields.offsets[i] = 3;
195 fieldSet[i] = estpq;
196 break;
197 default:
198 error(line, "illegal vector field selection", compString.c_str());
199 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000200 }
201 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202
Arun Patole7e7e68d2015-05-22 12:02:25 +0530203 for (int i = 0; i < fields.num; ++i)
204 {
205 if (fields.offsets[i] >= vecSize)
206 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400207 error(line, "vector field selection out of range", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000208 return false;
209 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000210
Arun Patole7e7e68d2015-05-22 12:02:25 +0530211 if (i > 0)
212 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400213 if (fieldSet[i] != fieldSet[i - 1])
Arun Patole7e7e68d2015-05-22 12:02:25 +0530214 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400215 error(line, "illegal - vector component fields not from the same set",
216 compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000217 return false;
218 }
219 }
220 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000222 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000223}
224
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225///////////////////////////////////////////////////////////////////////
226//
227// Errors
228//
229////////////////////////////////////////////////////////////////////////
230
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000231//
232// Used by flex/bison to output all syntax and parsing errors.
233//
Olli Etuaho4de340a2016-12-16 09:32:03 +0000234void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000235{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000236 mDiagnostics->error(loc, reason, token);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000237}
238
Olli Etuaho4de340a2016-12-16 09:32:03 +0000239void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530240{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000241 mDiagnostics->warning(loc, reason, token);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +0000242}
243
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200244void TParseContext::outOfRangeError(bool isError,
245 const TSourceLoc &loc,
246 const char *reason,
Olli Etuaho4de340a2016-12-16 09:32:03 +0000247 const char *token)
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200248{
249 if (isError)
250 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000251 error(loc, reason, token);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200252 }
253 else
254 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000255 warning(loc, reason, token);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200256 }
257}
258
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259//
260// Same error message for all places assignments don't work.
261//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530262void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000263{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000264 std::stringstream reasonStream;
265 reasonStream << "cannot convert from '" << right << "' to '" << left << "'";
266 std::string reason = reasonStream.str();
267 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000268}
269
270//
271// Same error message for all places unary operations don't work.
272//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530273void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000275 std::stringstream reasonStream;
276 reasonStream << "wrong operand type - no operation '" << op
277 << "' exists that takes an operand of type " << operand
278 << " (or there is no acceptable conversion)";
279 std::string reason = reasonStream.str();
280 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000281}
282
283//
284// Same error message for all binary operations don't work.
285//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400286void TParseContext::binaryOpError(const TSourceLoc &line,
287 const char *op,
288 TString left,
289 TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000290{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000291 std::stringstream reasonStream;
292 reasonStream << "wrong operand types - no operation '" << op
293 << "' exists that takes a left-hand operand of type '" << left
294 << "' and a right operand of type '" << right
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
Olli Etuaho856c4972016-08-08 11:38:39 +0300300void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
301 TPrecision precision,
302 TBasicType type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530303{
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400304 if (!mChecksPrecisionErrors)
Olli Etuaho383b7912016-08-05 11:22:59 +0300305 return;
Martin Radev70866b82016-07-22 15:27:42 +0300306
307 if (precision != EbpUndefined && !SupportsPrecision(type))
308 {
309 error(line, "illegal type for precision qualifier", getBasicString(type));
310 }
311
Olli Etuaho183d7e22015-11-20 15:59:09 +0200312 if (precision == EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530313 {
Olli Etuaho183d7e22015-11-20 15:59:09 +0200314 switch (type)
315 {
316 case EbtFloat:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400317 error(line, "No precision specified for (float)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300318 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200319 case EbtInt:
320 case EbtUInt:
321 UNREACHABLE(); // there's always a predeclared qualifier
Jamie Madillb98c3a82015-07-23 14:26:04 -0400322 error(line, "No precision specified (int)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300323 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200324 default:
jchen10cc2a10e2017-05-03 14:05:12 +0800325 if (IsOpaqueType(type))
Olli Etuaho183d7e22015-11-20 15:59:09 +0200326 {
jchen10cc2a10e2017-05-03 14:05:12 +0800327 error(line, "No precision specified", getBasicString(type));
Martin Radev2cc85b32016-08-05 16:22:53 +0300328 return;
329 }
Olli Etuaho183d7e22015-11-20 15:59:09 +0200330 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000331 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000332}
333
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000334// Both test and if necessary, spit out an error, to see if the node is really
335// an l-value that can be operated on this way.
Olli Etuaho856c4972016-08-08 11:38:39 +0300336bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500338 TIntermSymbol *symNode = node->getAsSymbolNode();
339 TIntermBinary *binaryNode = node->getAsBinaryNode();
Olli Etuahob6fa0432016-09-28 16:28:05 +0100340 TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
341
342 if (swizzleNode)
343 {
344 bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
345 if (ok && swizzleNode->hasDuplicateOffsets())
346 {
347 error(line, " l-value of swizzle cannot have duplicate components", op);
348 return false;
349 }
350 return ok;
351 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000352
Arun Patole7e7e68d2015-05-22 12:02:25 +0530353 if (binaryNode)
354 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400355 switch (binaryNode->getOp())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530356 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400357 case EOpIndexDirect:
358 case EOpIndexIndirect:
359 case EOpIndexDirectStruct:
360 case EOpIndexDirectInterfaceBlock:
Olli Etuaho856c4972016-08-08 11:38:39 +0300361 return checkCanBeLValue(line, op, binaryNode->getLeft());
Jamie Madillb98c3a82015-07-23 14:26:04 -0400362 default:
363 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000364 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000365 error(line, " l-value required", op);
Olli Etuaho8a176262016-08-16 14:23:01 +0300366 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000367 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000368
jchen10cc2a10e2017-05-03 14:05:12 +0800369 std::string message;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530370 switch (node->getQualifier())
371 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400372 case EvqConst:
373 message = "can't modify a const";
374 break;
375 case EvqConstReadOnly:
376 message = "can't modify a const";
377 break;
378 case EvqAttribute:
379 message = "can't modify an attribute";
380 break;
381 case EvqFragmentIn:
382 message = "can't modify an input";
383 break;
384 case EvqVertexIn:
385 message = "can't modify an input";
386 break;
387 case EvqUniform:
388 message = "can't modify a uniform";
389 break;
390 case EvqVaryingIn:
391 message = "can't modify a varying";
392 break;
393 case EvqFragCoord:
394 message = "can't modify gl_FragCoord";
395 break;
396 case EvqFrontFacing:
397 message = "can't modify gl_FrontFacing";
398 break;
399 case EvqPointCoord:
400 message = "can't modify gl_PointCoord";
401 break;
Martin Radevb0883602016-08-04 17:48:58 +0300402 case EvqNumWorkGroups:
403 message = "can't modify gl_NumWorkGroups";
404 break;
405 case EvqWorkGroupSize:
406 message = "can't modify gl_WorkGroupSize";
407 break;
408 case EvqWorkGroupID:
409 message = "can't modify gl_WorkGroupID";
410 break;
411 case EvqLocalInvocationID:
412 message = "can't modify gl_LocalInvocationID";
413 break;
414 case EvqGlobalInvocationID:
415 message = "can't modify gl_GlobalInvocationID";
416 break;
417 case EvqLocalInvocationIndex:
418 message = "can't modify gl_LocalInvocationIndex";
419 break;
Olli Etuaho7142f6c2017-05-05 17:07:26 +0300420 case EvqViewIDOVR:
421 message = "can't modify gl_ViewID_OVR";
422 break;
Martin Radev802abe02016-08-04 17:48:32 +0300423 case EvqComputeIn:
424 message = "can't modify work group size variable";
425 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400426 default:
427 //
428 // Type that can't be written to?
429 //
430 if (node->getBasicType() == EbtVoid)
431 {
432 message = "can't modify void";
433 }
jchen10cc2a10e2017-05-03 14:05:12 +0800434 if (IsOpaqueType(node->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -0400435 {
jchen10cc2a10e2017-05-03 14:05:12 +0800436 message = "can't modify a variable with type ";
437 message += getBasicString(node->getBasicType());
Martin Radev2cc85b32016-08-05 16:22:53 +0300438 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000439 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000440
jchen10cc2a10e2017-05-03 14:05:12 +0800441 if (message.empty() && binaryNode == 0 && symNode == 0)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530442 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000443 error(line, "l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000444
Olli Etuaho8a176262016-08-16 14:23:01 +0300445 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000446 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000447
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000448 //
449 // Everything else is okay, no error.
450 //
jchen10cc2a10e2017-05-03 14:05:12 +0800451 if (message.empty())
Olli Etuaho8a176262016-08-16 14:23:01 +0300452 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000453
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000454 //
455 // If we get here, we have an error and a message.
456 //
Arun Patole7e7e68d2015-05-22 12:02:25 +0530457 if (symNode)
458 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000459 const char *symbol = symNode->getSymbol().c_str();
460 std::stringstream reasonStream;
461 reasonStream << "l-value required (" << message << " \"" << symbol << "\")";
462 std::string reason = reasonStream.str();
463 error(line, reason.c_str(), op);
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000464 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530465 else
466 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000467 std::stringstream reasonStream;
468 reasonStream << "l-value required (" << message << ")";
469 std::string reason = reasonStream.str();
470 error(line, reason.c_str(), op);
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000471 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000472
Olli Etuaho8a176262016-08-16 14:23:01 +0300473 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000474}
475
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000476// Both test, and if necessary spit out an error, to see if the node is really
477// a constant.
Olli Etuaho856c4972016-08-08 11:38:39 +0300478void TParseContext::checkIsConst(TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000479{
Olli Etuaho383b7912016-08-05 11:22:59 +0300480 if (node->getQualifier() != EvqConst)
481 {
482 error(node->getLine(), "constant expression required", "");
483 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000484}
485
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000486// Both test, and if necessary spit out an error, to see if the node is really
487// an integer.
Olli Etuaho856c4972016-08-08 11:38:39 +0300488void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000489{
Olli Etuaho383b7912016-08-05 11:22:59 +0300490 if (!node->isScalarInt())
491 {
492 error(node->getLine(), "integer expression required", token);
493 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000494}
495
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000496// Both test, and if necessary spit out an error, to see if we are currently
497// globally scoped.
Qiankun Miaof69682b2016-08-16 14:50:42 +0800498bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000499{
Olli Etuaho856c4972016-08-08 11:38:39 +0300500 if (!symbolTable.atGlobalLevel())
Olli Etuaho383b7912016-08-05 11:22:59 +0300501 {
502 error(line, "only allowed at global scope", token);
Qiankun Miaof69682b2016-08-16 14:50:42 +0800503 return false;
Olli Etuaho383b7912016-08-05 11:22:59 +0300504 }
Qiankun Miaof69682b2016-08-16 14:50:42 +0800505 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000506}
507
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508// For now, keep it simple: if it starts "gl_", it's reserved, independent
509// of scope. Except, if the symbol table is at the built-in push-level,
510// which is when we are parsing built-ins.
alokp@chromium.org613ef312010-07-21 18:54:22 +0000511// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
512// webgl shader.
Olli Etuaho856c4972016-08-08 11:38:39 +0300513bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000514{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530515 static const char *reservedErrMsg = "reserved built-in name";
516 if (!symbolTable.atBuiltInLevel())
517 {
518 if (identifier.compare(0, 3, "gl_") == 0)
519 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000520 error(line, reservedErrMsg, "gl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300521 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000522 }
Jamie Madillacb4b812016-11-07 13:50:29 -0500523 if (sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530524 {
525 if (identifier.compare(0, 6, "webgl_") == 0)
526 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000527 error(line, reservedErrMsg, "webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300528 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000529 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530530 if (identifier.compare(0, 7, "_webgl_") == 0)
531 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000532 error(line, reservedErrMsg, "_webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300533 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000534 }
535 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530536 if (identifier.find("__") != TString::npos)
537 {
538 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400539 "identifiers containing two consecutive underscores (__) are reserved as "
540 "possible future keywords",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530541 identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300542 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000543 }
544 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000545
Olli Etuaho8a176262016-08-16 14:23:01 +0300546 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000547}
548
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000549// Make sure there is enough data provided to the constructor to build
550// something of the type of the constructor. Also returns the type of
551// the constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +0300552bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800553 const TIntermSequence *arguments,
Olli Etuaho856c4972016-08-08 11:38:39 +0300554 TOperator op,
555 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000556{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000557 bool constructingMatrix = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400558 switch (op)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530559 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400560 case EOpConstructMat2:
561 case EOpConstructMat2x3:
562 case EOpConstructMat2x4:
563 case EOpConstructMat3x2:
564 case EOpConstructMat3:
565 case EOpConstructMat3x4:
566 case EOpConstructMat4x2:
567 case EOpConstructMat4x3:
568 case EOpConstructMat4:
569 constructingMatrix = true;
570 break;
571 default:
572 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000573 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000574
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000575 //
576 // Note: It's okay to have too many components available, but not okay to have unused
577 // arguments. 'full' will go to true when enough args have been seen. If we loop
578 // again, there is an extra argument, so 'overfull' will become true.
579 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000580
Jamie Madillb98c3a82015-07-23 14:26:04 -0400581 size_t size = 0;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400582 bool full = false;
583 bool overFull = false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000584 bool matrixInMatrix = false;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500585 bool arrayArg = false;
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800586 for (TIntermNode *arg : *arguments)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530587 {
Olli Etuaho72d10202017-01-19 15:58:30 +0000588 const TIntermTyped *argTyped = arg->getAsTyped();
589 size += argTyped->getType().getObjectSize();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530590
Olli Etuaho72d10202017-01-19 15:58:30 +0000591 if (constructingMatrix && argTyped->getType().isMatrix())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000592 matrixInMatrix = true;
593 if (full)
594 overFull = true;
Olli Etuaho856c4972016-08-08 11:38:39 +0300595 if (op != EOpConstructStruct && !type.isArray() && size >= type.getObjectSize())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000596 full = true;
Olli Etuaho72d10202017-01-19 15:58:30 +0000597 if (argTyped->getType().isArray())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000598 arrayArg = true;
599 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530600
Olli Etuaho856c4972016-08-08 11:38:39 +0300601 if (type.isArray())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300602 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300603 // The size of an unsized constructor should already have been determined.
604 ASSERT(!type.isUnsizedArray());
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800605 if (static_cast<size_t>(type.getArraySize()) != arguments->size())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300606 {
607 error(line, "array constructor needs one argument per array element", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300608 return false;
Olli Etuaho376f1b52015-04-13 13:23:41 +0300609 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000610 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000611
Arun Patole7e7e68d2015-05-22 12:02:25 +0530612 if (arrayArg && op != EOpConstructStruct)
613 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000614 error(line, "constructing from a non-dereferenced array", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300615 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000616 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000617
Olli Etuaho856c4972016-08-08 11:38:39 +0300618 if (matrixInMatrix && !type.isArray())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530619 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800620 if (arguments->size() != 1)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530621 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400622 error(line, "constructing matrix from matrix can only take one argument",
623 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300624 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000625 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000626 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000627
Arun Patole7e7e68d2015-05-22 12:02:25 +0530628 if (overFull)
629 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000630 error(line, "too many arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300631 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000632 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530633
Olli Etuaho856c4972016-08-08 11:38:39 +0300634 if (op == EOpConstructStruct && !type.isArray() &&
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800635 type.getStruct()->fields().size() != arguments->size())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530636 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400637 error(line,
638 "Number of constructor parameters does not match the number of structure fields",
639 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300640 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000641 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000642
Olli Etuaho856c4972016-08-08 11:38:39 +0300643 if (!type.isMatrix() || !matrixInMatrix)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530644 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300645 if ((op != EOpConstructStruct && size != 1 && size < type.getObjectSize()) ||
646 (op == EOpConstructStruct && size < type.getObjectSize()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530647 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000648 error(line, "not enough data provided for construction", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300649 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000650 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000651 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000652
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800653 if (arguments->empty())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530654 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200655 error(line, "constructor does not have any arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300656 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000657 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200658
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800659 for (TIntermNode *const &argNode : *arguments)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530660 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200661 TIntermTyped *argTyped = argNode->getAsTyped();
662 ASSERT(argTyped != nullptr);
jchen10cc2a10e2017-05-03 14:05:12 +0800663 if (op != EOpConstructStruct && IsOpaqueType(argTyped->getBasicType()))
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200664 {
jchen10cc2a10e2017-05-03 14:05:12 +0800665 std::string reason("cannot convert a variable with type ");
666 reason += getBasicString(argTyped->getBasicType());
667 error(line, reason.c_str(), "constructor");
Martin Radev2cc85b32016-08-05 16:22:53 +0300668 return false;
669 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200670 if (argTyped->getBasicType() == EbtVoid)
671 {
672 error(line, "cannot convert a void", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300673 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200674 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000675 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000676
Olli Etuaho856c4972016-08-08 11:38:39 +0300677 if (type.isArray())
678 {
679 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
680 // the array.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800681 for (TIntermNode *const &argNode : *arguments)
Olli Etuaho856c4972016-08-08 11:38:39 +0300682 {
683 const TType &argType = argNode->getAsTyped()->getType();
Jamie Madill34bf2d92017-02-06 13:40:59 -0500684 // It has already been checked that the argument is not an array, but we can arrive
685 // here due to prior error conditions.
686 if (argType.isArray())
687 {
688 return false;
689 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300690 if (!argType.sameElementType(type))
691 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000692 error(line, "Array constructor argument has an incorrect type", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300693 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300694 }
695 }
696 }
697 else if (op == EOpConstructStruct)
698 {
699 const TFieldList &fields = type.getStruct()->fields();
Olli Etuaho856c4972016-08-08 11:38:39 +0300700
701 for (size_t i = 0; i < fields.size(); i++)
702 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800703 if (i >= arguments->size() ||
704 (*arguments)[i]->getAsTyped()->getType() != *fields[i]->type())
Olli Etuaho856c4972016-08-08 11:38:39 +0300705 {
706 error(line, "Structure constructor arguments do not match structure fields",
Olli Etuaho4de340a2016-12-16 09:32:03 +0000707 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300708 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300709 }
710 }
711 }
712
Olli Etuaho8a176262016-08-16 14:23:01 +0300713 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000714}
715
Jamie Madillb98c3a82015-07-23 14:26:04 -0400716// This function checks to see if a void variable has been declared and raise an error message for
717// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000718//
719// returns true in case of an error
720//
Olli Etuaho856c4972016-08-08 11:38:39 +0300721bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400722 const TString &identifier,
723 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000724{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300725 if (type == EbtVoid)
726 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000727 error(line, "illegal use of type 'void'", identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300728 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300729 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000730
Olli Etuaho8a176262016-08-16 14:23:01 +0300731 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000732}
733
Jamie Madillb98c3a82015-07-23 14:26:04 -0400734// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300735// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300736void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000737{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530738 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
739 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000740 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530741 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000742}
743
Jamie Madillb98c3a82015-07-23 14:26:04 -0400744// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300745// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300746void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000747{
Martin Radev4a9cd802016-09-01 16:51:51 +0300748 if (pType.getBasicType() != EbtBool || pType.isAggregate())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530749 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000750 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530751 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000752}
753
jchen10cc2a10e2017-05-03 14:05:12 +0800754bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
755 const TTypeSpecifierNonArray &pType,
756 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000757{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530758 if (pType.type == EbtStruct)
759 {
Martin Radev2cc85b32016-08-05 16:22:53 +0300760 if (ContainsSampler(*pType.userDef))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530761 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000762 std::stringstream reasonStream;
763 reasonStream << reason << " (structure contains a sampler)";
764 std::string reasonStr = reasonStream.str();
765 error(line, reasonStr.c_str(), getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300766 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000767 }
jchen10cc2a10e2017-05-03 14:05:12 +0800768 // only samplers need to be checked from structs, since other opaque types can't be struct
769 // members.
Olli Etuaho8a176262016-08-16 14:23:01 +0300770 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530771 }
jchen10cc2a10e2017-05-03 14:05:12 +0800772 else if (IsOpaqueType(pType.type))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530773 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000774 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300775 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000776 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000777
Olli Etuaho8a176262016-08-16 14:23:01 +0300778 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000779}
780
Olli Etuaho856c4972016-08-08 11:38:39 +0300781void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
782 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400783{
784 if (pType.layoutQualifier.location != -1)
785 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400786 error(line, "location must only be specified for a single input or output variable",
787 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400788 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400789}
790
Olli Etuaho856c4972016-08-08 11:38:39 +0300791void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
792 const TLayoutQualifier &layoutQualifier)
793{
794 if (layoutQualifier.location != -1)
795 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000796 const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs";
797 if (mShaderVersion >= 310)
798 {
799 errorMsg =
800 "invalid layout qualifier: only valid on program inputs, outputs, and uniforms";
801 }
802 error(location, errorMsg, "location");
Olli Etuaho856c4972016-08-08 11:38:39 +0300803 }
804}
805
Martin Radev2cc85b32016-08-05 16:22:53 +0300806void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
807 TQualifier qualifier,
808 const TType &type)
809{
Martin Radev2cc85b32016-08-05 16:22:53 +0300810 ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
jchen10cc2a10e2017-05-03 14:05:12 +0800811 if (IsOpaqueType(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530812 {
jchen10cc2a10e2017-05-03 14:05:12 +0800813 error(line, "opaque types cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000814 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000815}
816
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000817// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300818unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000819{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530820 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000821
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200822 // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
823 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
824 // fold as array size.
825 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000826 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000827 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300828 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000829 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000830
Olli Etuaho856c4972016-08-08 11:38:39 +0300831 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400832
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000833 if (constant->getBasicType() == EbtUInt)
834 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300835 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000836 }
837 else
838 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300839 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000840
Olli Etuaho856c4972016-08-08 11:38:39 +0300841 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000842 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400843 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300844 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000845 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400846
Olli Etuaho856c4972016-08-08 11:38:39 +0300847 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -0400848 }
849
Olli Etuaho856c4972016-08-08 11:38:39 +0300850 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -0400851 {
852 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300853 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400854 }
855
856 // The size of arrays is restricted here to prevent issues further down the
857 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
858 // 4096 registers so this should be reasonable even for aggressively optimizable code.
859 const unsigned int sizeLimit = 65536;
860
Olli Etuaho856c4972016-08-08 11:38:39 +0300861 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -0400862 {
863 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300864 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000865 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300866
867 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000868}
869
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000870// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +0300871bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
872 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000873{
Olli Etuaho8a176262016-08-16 14:23:01 +0300874 if ((elementQualifier.qualifier == EvqAttribute) ||
875 (elementQualifier.qualifier == EvqVertexIn) ||
876 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +0300877 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400878 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300879 TType(elementQualifier).getQualifierString());
880 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000881 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000882
Olli Etuaho8a176262016-08-16 14:23:01 +0300883 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000884}
885
Olli Etuaho8a176262016-08-16 14:23:01 +0300886// See if this element type can be formed into an array.
887bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000888{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000889 //
890 // Can the type be an array?
891 //
Olli Etuaho8a176262016-08-16 14:23:01 +0300892 if (elementType.array)
Jamie Madill06145232015-05-13 13:10:01 -0400893 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300894 error(line, "cannot declare arrays of arrays",
895 TType(elementType).getCompleteString().c_str());
896 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000897 }
Olli Etuahocc36b982015-07-10 14:14:18 +0300898 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
899 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
900 // 4.3.4).
Martin Radev4a9cd802016-09-01 16:51:51 +0300901 if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
Olli Etuaho8a176262016-08-16 14:23:01 +0300902 sh::IsVarying(elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +0300903 {
904 error(line, "cannot declare arrays of structs of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300905 TType(elementType).getCompleteString().c_str());
906 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +0300907 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000908
Olli Etuaho8a176262016-08-16 14:23:01 +0300909 return true;
910}
911
912// Check if this qualified element type can be formed into an array.
913bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
914 const TPublicType &elementType)
915{
916 if (checkIsValidTypeForArray(indexLocation, elementType))
917 {
918 return checkIsValidQualifierForArray(indexLocation, elementType);
919 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000920 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000921}
922
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000923// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +0300924void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
925 const TString &identifier,
926 TPublicType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000927{
Olli Etuaho3739d232015-04-08 12:23:44 +0300928 ASSERT(type != nullptr);
929 if (type->qualifier == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000930 {
931 // Make the qualifier make sense.
Olli Etuaho3739d232015-04-08 12:23:44 +0300932 type->qualifier = EvqTemporary;
933
934 // Generate informative error messages for ESSL1.
935 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400936 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000937 {
Arun Patole7e7e68d2015-05-22 12:02:25 +0530938 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400939 "structures containing arrays may not be declared constant since they cannot be "
940 "initialized",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530941 identifier.c_str());
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000942 }
943 else
944 {
945 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
946 }
Olli Etuaho383b7912016-08-05 11:22:59 +0300947 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000948 }
Olli Etuaho376f1b52015-04-13 13:23:41 +0300949 if (type->isUnsizedArray())
950 {
951 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
Olli Etuaho376f1b52015-04-13 13:23:41 +0300952 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000953}
954
Olli Etuaho2935c582015-04-08 14:32:06 +0300955// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000956// and update the symbol table.
957//
Olli Etuaho2935c582015-04-08 14:32:06 +0300958// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000959//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400960bool TParseContext::declareVariable(const TSourceLoc &line,
961 const TString &identifier,
962 const TType &type,
Olli Etuaho2935c582015-04-08 14:32:06 +0300963 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000964{
Olli Etuaho2935c582015-04-08 14:32:06 +0300965 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000966
Olli Etuaho43364892017-02-13 16:00:12 +0000967 checkBindingIsValid(line, type);
968
Olli Etuaho856c4972016-08-08 11:38:39 +0300969 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000970
Olli Etuaho2935c582015-04-08 14:32:06 +0300971 // gl_LastFragData may be redeclared with a new precision qualifier
972 if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
973 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400974 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
975 symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Olli Etuaho856c4972016-08-08 11:38:39 +0300976 if (static_cast<int>(type.getArraySize()) == maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +0300977 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400978 if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +0300979 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300980 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
Olli Etuaho2935c582015-04-08 14:32:06 +0300981 }
982 }
983 else
984 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400985 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
986 identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +0300987 return false;
988 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000989 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000990
Olli Etuaho8a176262016-08-16 14:23:01 +0300991 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +0300992 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000993
Olli Etuaho2935c582015-04-08 14:32:06 +0300994 (*variable) = new TVariable(&identifier, type);
995 if (!symbolTable.declare(*variable))
996 {
997 error(line, "redefinition", identifier.c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -0400998 *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +0300999 return false;
1000 }
1001
Olli Etuaho8a176262016-08-16 14:23:01 +03001002 if (!checkIsNonVoid(line, identifier, type.getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +03001003 return false;
1004
1005 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001006}
1007
Martin Radev70866b82016-07-22 15:27:42 +03001008void TParseContext::checkIsParameterQualifierValid(
1009 const TSourceLoc &line,
1010 const TTypeQualifierBuilder &typeQualifierBuilder,
1011 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301012{
Olli Etuaho77ba4082016-12-16 12:01:18 +00001013 TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03001014
1015 if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301016 {
Martin Radev2cc85b32016-08-05 16:22:53 +03001017 checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type);
1018 }
1019
1020 if (!IsImage(type->getBasicType()))
1021 {
Olli Etuaho43364892017-02-13 16:00:12 +00001022 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line);
Martin Radev2cc85b32016-08-05 16:22:53 +03001023 }
1024 else
1025 {
1026 type->setMemoryQualifier(typeQualifier.memoryQualifier);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001027 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001028
Martin Radev70866b82016-07-22 15:27:42 +03001029 type->setQualifier(typeQualifier.qualifier);
1030
1031 if (typeQualifier.precision != EbpUndefined)
1032 {
1033 type->setPrecision(typeQualifier.precision);
1034 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001035}
1036
Olli Etuaho856c4972016-08-08 11:38:39 +03001037bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001038{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001039 const TExtensionBehavior &extBehavior = extensionBehavior();
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001040 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
Arun Patole7e7e68d2015-05-22 12:02:25 +05301041 if (iter == extBehavior.end())
1042 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001043 error(line, "extension is not supported", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001044 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001045 }
zmo@google.comf5450912011-09-09 01:37:19 +00001046 // In GLSL ES, an extension's default behavior is "disable".
Arun Patole7e7e68d2015-05-22 12:02:25 +05301047 if (iter->second == EBhDisable || iter->second == EBhUndefined)
1048 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00001049 // TODO(oetuaho@nvidia.com): This is slightly hacky. Might be better if symbols could be
1050 // associated with more than one extension.
1051 if (extension == "GL_OVR_multiview")
1052 {
1053 return checkCanUseExtension(line, "GL_OVR_multiview2");
1054 }
Olli Etuaho4de340a2016-12-16 09:32:03 +00001055 error(line, "extension is disabled", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001056 return false;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001057 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301058 if (iter->second == EBhWarn)
1059 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001060 warning(line, "extension is being used", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001061 return true;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001062 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001063
Olli Etuaho8a176262016-08-16 14:23:01 +03001064 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001065}
1066
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001067// ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause
1068// compile-time or link-time errors are the same whether or not the declaration is empty".
1069// This function implements all the checks that are done on qualifiers regardless of if the
1070// declaration is empty.
1071void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier,
1072 const sh::TLayoutQualifier &layoutQualifier,
1073 const TSourceLoc &location)
1074{
1075 if (qualifier == EvqShared && !layoutQualifier.isEmpty())
1076 {
1077 error(location, "Shared memory declarations cannot have layout specified", "layout");
1078 }
1079
1080 if (layoutQualifier.matrixPacking != EmpUnspecified)
1081 {
1082 error(location, "layout qualifier only valid for interface blocks",
1083 getMatrixPackingString(layoutQualifier.matrixPacking));
1084 return;
1085 }
1086
1087 if (layoutQualifier.blockStorage != EbsUnspecified)
1088 {
1089 error(location, "layout qualifier only valid for interface blocks",
1090 getBlockStorageString(layoutQualifier.blockStorage));
1091 return;
1092 }
1093
1094 if (qualifier == EvqFragmentOut)
1095 {
1096 if (layoutQualifier.location != -1 && layoutQualifier.yuv == true)
1097 {
1098 error(location, "invalid layout qualifier combination", "yuv");
1099 return;
1100 }
1101 }
1102 else
1103 {
1104 checkYuvIsNotSpecified(location, layoutQualifier.yuv);
1105 }
1106
1107 bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut;
1108 if (mShaderVersion >= 310 && qualifier == EvqUniform)
1109 {
1110 canHaveLocation = true;
1111 // We're not checking whether the uniform location is in range here since that depends on
1112 // the type of the variable.
1113 // The type can only be fully determined for non-empty declarations.
1114 }
1115 if (!canHaveLocation)
1116 {
1117 checkLocationIsNotSpecified(location, layoutQualifier);
1118 }
1119}
1120
Martin Radevb8b01222016-11-20 23:25:53 +02001121void TParseContext::emptyDeclarationErrorCheck(const TPublicType &publicType,
1122 const TSourceLoc &location)
1123{
1124 if (publicType.isUnsizedArray())
1125 {
1126 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1127 // error. It is assumed that this applies to empty declarations as well.
1128 error(location, "empty array declaration needs to specify a size", "");
1129 }
Martin Radevb8b01222016-11-20 23:25:53 +02001130}
1131
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001132// These checks are done for all declarations that are non-empty. They're done for non-empty
1133// declarations starting a declarator list, and declarators that follow an empty declaration.
1134void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
1135 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -04001136{
Olli Etuahofa33d582015-04-09 14:33:12 +03001137 switch (publicType.qualifier)
1138 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001139 case EvqVaryingIn:
1140 case EvqVaryingOut:
1141 case EvqAttribute:
1142 case EvqVertexIn:
1143 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +03001144 case EvqComputeIn:
Martin Radev4a9cd802016-09-01 16:51:51 +03001145 if (publicType.getBasicType() == EbtStruct)
Jamie Madillb98c3a82015-07-23 14:26:04 -04001146 {
1147 error(identifierLocation, "cannot be used with a structure",
1148 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +03001149 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001150 }
Olli Etuahofa33d582015-04-09 14:33:12 +03001151
Jamie Madillb98c3a82015-07-23 14:26:04 -04001152 default:
1153 break;
Olli Etuahofa33d582015-04-09 14:33:12 +03001154 }
jchen10cc2a10e2017-05-03 14:05:12 +08001155 std::string reason(getBasicString(publicType.getBasicType()));
1156 reason += "s must be uniform";
Jamie Madillb98c3a82015-07-23 14:26:04 -04001157 if (publicType.qualifier != EvqUniform &&
jchen10cc2a10e2017-05-03 14:05:12 +08001158 !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str()))
Martin Radev2cc85b32016-08-05 16:22:53 +03001159 {
1160 return;
1161 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001162
Andrei Volykhina5527072017-03-22 16:46:30 +03001163 if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal &&
1164 publicType.qualifier != EvqConst) &&
1165 publicType.getBasicType() == EbtYuvCscStandardEXT)
1166 {
1167 error(identifierLocation, "cannot be used with a yuvCscStandardEXT",
1168 getQualifierString(publicType.qualifier));
1169 return;
1170 }
1171
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001172 if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform)
1173 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001174 // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized.
1175 // But invalid shaders may still reach here with an unsized array declaration.
1176 if (!publicType.isUnsizedArray())
1177 {
1178 TType type(publicType);
1179 checkUniformLocationInRange(identifierLocation, type.getLocationCount(),
1180 publicType.layoutQualifier);
1181 }
1182 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001183
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001184 // check for layout qualifier issues
1185 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
Andrei Volykhina5527072017-03-22 16:46:30 +03001186
Martin Radev2cc85b32016-08-05 16:22:53 +03001187 if (IsImage(publicType.getBasicType()))
1188 {
1189
1190 switch (layoutQualifier.imageInternalFormat)
1191 {
1192 case EiifRGBA32F:
1193 case EiifRGBA16F:
1194 case EiifR32F:
1195 case EiifRGBA8:
1196 case EiifRGBA8_SNORM:
1197 if (!IsFloatImage(publicType.getBasicType()))
1198 {
1199 error(identifierLocation,
1200 "internal image format requires a floating image type",
1201 getBasicString(publicType.getBasicType()));
1202 return;
1203 }
1204 break;
1205 case EiifRGBA32I:
1206 case EiifRGBA16I:
1207 case EiifRGBA8I:
1208 case EiifR32I:
1209 if (!IsIntegerImage(publicType.getBasicType()))
1210 {
1211 error(identifierLocation,
1212 "internal image format requires an integer image type",
1213 getBasicString(publicType.getBasicType()));
1214 return;
1215 }
1216 break;
1217 case EiifRGBA32UI:
1218 case EiifRGBA16UI:
1219 case EiifRGBA8UI:
1220 case EiifR32UI:
1221 if (!IsUnsignedImage(publicType.getBasicType()))
1222 {
1223 error(identifierLocation,
1224 "internal image format requires an unsigned image type",
1225 getBasicString(publicType.getBasicType()));
1226 return;
1227 }
1228 break;
1229 case EiifUnspecified:
1230 error(identifierLocation, "layout qualifier", "No image internal format specified");
1231 return;
1232 default:
1233 error(identifierLocation, "layout qualifier", "unrecognized token");
1234 return;
1235 }
1236
1237 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
1238 switch (layoutQualifier.imageInternalFormat)
1239 {
1240 case EiifR32F:
1241 case EiifR32I:
1242 case EiifR32UI:
1243 break;
1244 default:
1245 if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
1246 {
1247 error(identifierLocation, "layout qualifier",
1248 "Except for images with the r32f, r32i and r32ui format qualifiers, "
1249 "image variables must be qualified readonly and/or writeonly");
1250 return;
1251 }
1252 break;
1253 }
1254 }
1255 else
1256 {
Olli Etuaho43364892017-02-13 16:00:12 +00001257 checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat);
Martin Radev2cc85b32016-08-05 16:22:53 +03001258
Olli Etuaho43364892017-02-13 16:00:12 +00001259 checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
1260 }
1261}
Martin Radev2cc85b32016-08-05 16:22:53 +03001262
Olli Etuaho43364892017-02-13 16:00:12 +00001263void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type)
1264{
1265 TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
1266 int arraySize = type.isArray() ? type.getArraySize() : 1;
1267 if (IsImage(type.getBasicType()))
1268 {
1269 checkImageBindingIsValid(identifierLocation, layoutQualifier.binding, arraySize);
1270 }
1271 else if (IsSampler(type.getBasicType()))
1272 {
1273 checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding, arraySize);
1274 }
1275 else
1276 {
1277 ASSERT(!IsOpaqueType(type.getBasicType()));
1278 checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
Martin Radev2cc85b32016-08-05 16:22:53 +03001279 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001280}
1281
Olli Etuaho856c4972016-08-08 11:38:39 +03001282void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1283 const TString &layoutQualifierName,
1284 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001285{
1286
1287 if (mShaderVersion < versionRequired)
1288 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001289 error(location, "invalid layout qualifier: not supported", layoutQualifierName.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03001290 }
1291}
1292
Olli Etuaho856c4972016-08-08 11:38:39 +03001293bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1294 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001295{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001296 const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
Martin Radev802abe02016-08-04 17:48:32 +03001297 for (size_t i = 0u; i < localSize.size(); ++i)
1298 {
1299 if (localSize[i] != -1)
1300 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001301 error(location,
1302 "invalid layout qualifier: only valid when used with 'in' in a compute shader "
1303 "global layout declaration",
1304 getWorkGroupSizeString(i));
Olli Etuaho8a176262016-08-16 14:23:01 +03001305 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001306 }
1307 }
1308
Olli Etuaho8a176262016-08-16 14:23:01 +03001309 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001310}
1311
Olli Etuaho43364892017-02-13 16:00:12 +00001312void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
Martin Radev2cc85b32016-08-05 16:22:53 +03001313 TLayoutImageInternalFormat internalFormat)
1314{
1315 if (internalFormat != EiifUnspecified)
1316 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001317 error(location, "invalid layout qualifier: only valid when used with images",
1318 getImageInternalFormatString(internalFormat));
Martin Radev2cc85b32016-08-05 16:22:53 +03001319 }
Olli Etuaho43364892017-02-13 16:00:12 +00001320}
1321
1322void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
1323{
1324 if (binding != -1)
1325 {
1326 error(location,
1327 "invalid layout qualifier: only valid when used with opaque types or blocks",
1328 "binding");
1329 }
1330}
1331
1332void TParseContext::checkImageBindingIsValid(const TSourceLoc &location, int binding, int arraySize)
1333{
1334 // Expects arraySize to be 1 when setting binding for only a single variable.
1335 if (binding >= 0 && binding + arraySize > mMaxImageUnits)
1336 {
1337 error(location, "image binding greater than gl_MaxImageUnits", "binding");
1338 }
1339}
1340
1341void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location,
1342 int binding,
1343 int arraySize)
1344{
1345 // Expects arraySize to be 1 when setting binding for only a single variable.
1346 if (binding >= 0 && binding + arraySize > mMaxCombinedTextureImageUnits)
1347 {
1348 error(location, "sampler binding greater than maximum texture units", "binding");
1349 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001350}
1351
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001352void TParseContext::checkUniformLocationInRange(const TSourceLoc &location,
1353 int objectLocationCount,
1354 const TLayoutQualifier &layoutQualifier)
1355{
1356 int loc = layoutQualifier.location;
1357 if (loc >= 0 && loc + objectLocationCount > mMaxUniformLocations)
1358 {
1359 error(location, "Uniform location out of range", "location");
1360 }
1361}
1362
Andrei Volykhina5527072017-03-22 16:46:30 +03001363void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv)
1364{
1365 if (yuv != false)
1366 {
1367 error(location, "invalid layout qualifier: only valid on program outputs", "yuv");
1368 }
1369}
1370
Olli Etuaho383b7912016-08-05 11:22:59 +03001371void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
Olli Etuaho856c4972016-08-08 11:38:39 +03001372 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001373{
1374 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1375 {
1376 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1377 if (qual == EvqOut || qual == EvqInOut)
1378 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001379 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho8a176262016-08-16 14:23:01 +03001380 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001381 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001382 error(argument->getLine(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00001383 "Constant value cannot be passed for 'out' or 'inout' parameters.",
Olli Etuahoec9232b2017-03-27 17:01:37 +03001384 fnCall->getFunctionSymbolInfo()->getName().c_str());
Olli Etuaho383b7912016-08-05 11:22:59 +03001385 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001386 }
1387 }
1388 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001389}
1390
Martin Radev70866b82016-07-22 15:27:42 +03001391void TParseContext::checkInvariantVariableQualifier(bool invariant,
1392 const TQualifier qualifier,
1393 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001394{
Martin Radev70866b82016-07-22 15:27:42 +03001395 if (!invariant)
1396 return;
1397
1398 if (mShaderVersion < 300)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001399 {
Martin Radev70866b82016-07-22 15:27:42 +03001400 // input variables in the fragment shader can be also qualified as invariant
1401 if (!sh::CanBeInvariantESSL1(qualifier))
1402 {
1403 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1404 }
1405 }
1406 else
1407 {
1408 if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
1409 {
1410 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1411 }
Olli Etuaho37ad4742015-04-27 13:18:50 +03001412 }
1413}
1414
Arun Patole7e7e68d2015-05-22 12:02:25 +05301415bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001416{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001417 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001418 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1419 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001420}
1421
Arun Patole7e7e68d2015-05-22 12:02:25 +05301422bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001423{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001424 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001425}
1426
Jamie Madillb98c3a82015-07-23 14:26:04 -04001427void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1428 const char *extName,
1429 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001430{
1431 pp::SourceLocation srcLoc;
1432 srcLoc.file = loc.first_file;
1433 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001434 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001435}
1436
Jamie Madillb98c3a82015-07-23 14:26:04 -04001437void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1438 const char *name,
1439 const char *value,
1440 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001441{
1442 pp::SourceLocation srcLoc;
1443 srcLoc.file = loc.first_file;
1444 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001445 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001446}
1447
Martin Radev4c4c8e72016-08-04 12:25:34 +03001448sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
Martin Radev802abe02016-08-04 17:48:32 +03001449{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001450 sh::WorkGroupSize result;
Martin Radev802abe02016-08-04 17:48:32 +03001451 for (size_t i = 0u; i < result.size(); ++i)
1452 {
1453 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1454 {
1455 result[i] = 1;
1456 }
1457 else
1458 {
1459 result[i] = mComputeShaderLocalSize[i];
1460 }
1461 }
1462 return result;
1463}
1464
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001465/////////////////////////////////////////////////////////////////////////////////
1466//
1467// Non-Errors.
1468//
1469/////////////////////////////////////////////////////////////////////////////////
1470
Jamie Madill5c097022014-08-20 16:38:32 -04001471const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1472 const TString *name,
1473 const TSymbol *symbol)
1474{
Yunchao Hed7297bf2017-04-19 15:27:10 +08001475 const TVariable *variable = nullptr;
Jamie Madill5c097022014-08-20 16:38:32 -04001476
1477 if (!symbol)
1478 {
1479 error(location, "undeclared identifier", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001480 }
1481 else if (!symbol->isVariable())
1482 {
1483 error(location, "variable expected", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001484 }
1485 else
1486 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001487 variable = static_cast<const TVariable *>(symbol);
Jamie Madill5c097022014-08-20 16:38:32 -04001488
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001489 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
Olli Etuaho383b7912016-08-05 11:22:59 +03001490 !variable->getExtension().empty())
Jamie Madill5c097022014-08-20 16:38:32 -04001491 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001492 checkCanUseExtension(location, variable->getExtension());
Jamie Madill5c097022014-08-20 16:38:32 -04001493 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001494
1495 // Reject shaders using both gl_FragData and gl_FragColor
1496 TQualifier qualifier = variable->getType().getQualifier();
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001497 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001498 {
1499 mUsesFragData = true;
1500 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001501 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001502 {
1503 mUsesFragColor = true;
1504 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001505 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1506 {
1507 mUsesSecondaryOutputs = true;
1508 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001509
1510 // This validation is not quite correct - it's only an error to write to
1511 // both FragData and FragColor. For simplicity, and because users shouldn't
1512 // be rewarded for reading from undefined varaibles, return an error
1513 // if they are both referenced, rather than assigned.
1514 if (mUsesFragData && mUsesFragColor)
1515 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001516 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1517 if (mUsesSecondaryOutputs)
1518 {
1519 errorMessage =
1520 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1521 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1522 }
1523 error(location, errorMessage, name->c_str());
Jamie Madill14e95b32015-05-07 10:10:41 -04001524 }
Martin Radevb0883602016-08-04 17:48:58 +03001525
1526 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1527 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1528 qualifier == EvqWorkGroupSize)
1529 {
1530 error(location,
1531 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1532 "gl_WorkGroupSize");
1533 }
Jamie Madill5c097022014-08-20 16:38:32 -04001534 }
1535
1536 if (!variable)
1537 {
1538 TType type(EbtFloat, EbpUndefined);
1539 TVariable *fakeVariable = new TVariable(name, type);
1540 symbolTable.declare(fakeVariable);
1541 variable = fakeVariable;
1542 }
1543
1544 return variable;
1545}
1546
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001547TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1548 const TString *name,
1549 const TSymbol *symbol)
1550{
1551 const TVariable *variable = getNamedVariable(location, name, symbol);
1552
Olli Etuaho09b04a22016-12-15 13:30:26 +00001553 if (variable->getType().getQualifier() == EvqViewIDOVR && IsWebGLBasedSpec(mShaderSpec) &&
1554 mShaderType == GL_FRAGMENT_SHADER && !isExtensionEnabled("GL_OVR_multiview2"))
1555 {
1556 // WEBGL_multiview spec
1557 error(location, "Need to enable OVR_multiview2 to use gl_ViewID_OVR in fragment shader",
1558 "gl_ViewID_OVR");
1559 }
1560
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001561 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001562 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001563 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001564 return intermediate.addConstantUnion(constArray, variable->getType(), location);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001565 }
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001566 else if (variable->getType().getQualifier() == EvqWorkGroupSize &&
1567 mComputeShaderLocalSizeDeclared)
1568 {
1569 // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
1570 // needs to be added to the AST as a constant and not as a symbol.
1571 sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
1572 TConstantUnion *constArray = new TConstantUnion[3];
1573 for (size_t i = 0; i < 3; ++i)
1574 {
1575 constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
1576 }
1577
1578 ASSERT(variable->getType().getBasicType() == EbtUInt);
1579 ASSERT(variable->getType().getObjectSize() == 3);
1580
1581 TType type(variable->getType());
1582 type.setQualifier(EvqConst);
1583 return intermediate.addConstantUnion(constArray, type, location);
1584 }
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001585 else
1586 {
1587 return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
1588 variable->getType(), location);
1589 }
1590}
1591
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001592//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001593// Initializers show up in several places in the grammar. Have one set of
1594// code to handle them here.
1595//
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001596// Returns true on error, false if no error
1597//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001598bool TParseContext::executeInitializer(const TSourceLoc &line,
1599 const TString &identifier,
1600 const TPublicType &pType,
1601 TIntermTyped *initializer,
Olli Etuaho13389b62016-10-16 11:48:18 +01001602 TIntermBinary **initNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001603{
Olli Etuaho13389b62016-10-16 11:48:18 +01001604 ASSERT(initNode != nullptr);
1605 ASSERT(*initNode == nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001606 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001607
Olli Etuaho2935c582015-04-08 14:32:06 +03001608 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001609 if (type.isUnsizedArray())
1610 {
Olli Etuaho02bd82c2016-11-03 10:29:43 +00001611 // We have not checked yet whether the initializer actually is an array or not.
1612 if (initializer->isArray())
1613 {
1614 type.setArraySize(initializer->getArraySize());
1615 }
1616 else
1617 {
1618 // Having a non-array initializer for an unsized array will result in an error later,
1619 // so we don't generate an error message here.
1620 type.setArraySize(1u);
1621 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03001622 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001623 if (!declareVariable(line, identifier, type, &variable))
1624 {
1625 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001626 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001627
Olli Etuahob0c645e2015-05-12 14:25:36 +03001628 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001629 if (symbolTable.atGlobalLevel() &&
1630 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001631 {
1632 // Error message does not completely match behavior with ESSL 1.00, but
1633 // we want to steer developers towards only using constant expressions.
1634 error(line, "global variable initializers must be constant expressions", "=");
1635 return true;
1636 }
1637 if (globalInitWarning)
1638 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001639 warning(
1640 line,
1641 "global variable initializers should be constant expressions "
1642 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1643 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001644 }
1645
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001646 //
1647 // identifier must be of type constant, a global, or a temporary
1648 //
1649 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301650 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1651 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001652 error(line, " cannot initialize this type of qualifier ",
1653 variable->getType().getQualifierString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001654 return true;
1655 }
1656 //
1657 // test for and propagate constant
1658 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001659
Arun Patole7e7e68d2015-05-22 12:02:25 +05301660 if (qualifier == EvqConst)
1661 {
1662 if (qualifier != initializer->getType().getQualifier())
1663 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001664 std::stringstream reasonStream;
1665 reasonStream << "assigning non-constant to '" << variable->getType().getCompleteString()
1666 << "'";
1667 std::string reason = reasonStream.str();
1668 error(line, reason.c_str(), "=");
alokp@chromium.org58e54292010-08-24 21:40:03 +00001669 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001670 return true;
1671 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301672 if (type != initializer->getType())
1673 {
1674 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001675 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001676 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001677 return true;
1678 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001679
1680 // Save the constant folded value to the variable if possible. For example array
1681 // initializers are not folded, since that way copying the array literal to multiple places
1682 // in the shader is avoided.
1683 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1684 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301685 if (initializer->getAsConstantUnion())
1686 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001687 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuaho13389b62016-10-16 11:48:18 +01001688 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001689 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301690 }
1691 else if (initializer->getAsSymbolNode())
1692 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001693 const TSymbol *symbol =
1694 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1695 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001696
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001697 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001698 if (constArray)
1699 {
1700 variable->shareConstPointer(constArray);
Olli Etuaho13389b62016-10-16 11:48:18 +01001701 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001702 return false;
1703 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001704 }
1705 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001706
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001707 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1708 variable->getUniqueId(), variable->getName(), variable->getType(), line);
Olli Etuaho13389b62016-10-16 11:48:18 +01001709 *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1710 if (*initNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001711 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001712 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1713 return true;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001714 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001715
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001716 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001717}
1718
Olli Etuaho0e3aee32016-10-27 12:56:38 +01001719void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
1720{
1721 checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
1722 typeSpecifier->getBasicType());
1723
1724 if (mShaderVersion < 300 && typeSpecifier->array)
1725 {
1726 error(typeSpecifier->getLine(), "not supported", "first-class array");
1727 typeSpecifier->clearArrayness();
1728 }
1729}
1730
Martin Radev70866b82016-07-22 15:27:42 +03001731TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301732 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001733{
Olli Etuaho77ba4082016-12-16 12:01:18 +00001734 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001735
Martin Radev70866b82016-07-22 15:27:42 +03001736 TPublicType returnType = typeSpecifier;
1737 returnType.qualifier = typeQualifier.qualifier;
1738 returnType.invariant = typeQualifier.invariant;
1739 returnType.layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03001740 returnType.memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03001741 returnType.precision = typeSpecifier.precision;
1742
1743 if (typeQualifier.precision != EbpUndefined)
1744 {
1745 returnType.precision = typeQualifier.precision;
1746 }
1747
Martin Radev4a9cd802016-09-01 16:51:51 +03001748 checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
1749 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03001750
Martin Radev4a9cd802016-09-01 16:51:51 +03001751 checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
1752 typeSpecifier.getLine());
Martin Radev70866b82016-07-22 15:27:42 +03001753
Martin Radev4a9cd802016-09-01 16:51:51 +03001754 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001755
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001756 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001757 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001758 if (typeSpecifier.array)
1759 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001760 error(typeSpecifier.getLine(), "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001761 returnType.clearArrayness();
1762 }
1763
Martin Radev70866b82016-07-22 15:27:42 +03001764 if (returnType.qualifier == EvqAttribute &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001765 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001766 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001767 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001768 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001769 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001770
Martin Radev70866b82016-07-22 15:27:42 +03001771 if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001772 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001773 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001774 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001775 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001776 }
1777 }
1778 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001779 {
Martin Radev70866b82016-07-22 15:27:42 +03001780 if (!returnType.layoutQualifier.isEmpty())
Olli Etuahoabb0c382015-07-13 12:01:12 +03001781 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001782 checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03001783 }
Martin Radev70866b82016-07-22 15:27:42 +03001784 if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
1785 returnType.qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001786 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001787 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
1788 typeSpecifier.getLine());
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001789 }
Martin Radev70866b82016-07-22 15:27:42 +03001790 if (returnType.qualifier == EvqComputeIn)
Martin Radev802abe02016-08-04 17:48:32 +03001791 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001792 error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
Martin Radev802abe02016-08-04 17:48:32 +03001793 "in");
Martin Radev802abe02016-08-04 17:48:32 +03001794 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001795 }
1796
1797 return returnType;
1798}
1799
Olli Etuaho856c4972016-08-08 11:38:39 +03001800void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1801 const TPublicType &type,
1802 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03001803{
1804 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
Martin Radev4a9cd802016-09-01 16:51:51 +03001805 if (type.getBasicType() == EbtBool)
Olli Etuahocc36b982015-07-10 14:14:18 +03001806 {
1807 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001808 }
1809
1810 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1811 switch (qualifier)
1812 {
1813 case EvqVertexIn:
1814 // ESSL 3.00 section 4.3.4
1815 if (type.array)
1816 {
1817 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001818 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001819 // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03001820 return;
1821 case EvqFragmentOut:
1822 // ESSL 3.00 section 4.3.6
Martin Radev4a9cd802016-09-01 16:51:51 +03001823 if (type.typeSpecifierNonArray.isMatrix())
Olli Etuahocc36b982015-07-10 14:14:18 +03001824 {
1825 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001826 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001827 // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03001828 return;
1829 default:
1830 break;
1831 }
1832
1833 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1834 // restrictions.
1835 bool typeContainsIntegers =
Martin Radev4a9cd802016-09-01 16:51:51 +03001836 (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
1837 type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
Olli Etuahocc36b982015-07-10 14:14:18 +03001838 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1839 {
1840 error(qualifierLocation, "must use 'flat' interpolation here",
1841 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001842 }
1843
Martin Radev4a9cd802016-09-01 16:51:51 +03001844 if (type.getBasicType() == EbtStruct)
Olli Etuahocc36b982015-07-10 14:14:18 +03001845 {
1846 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1847 // These restrictions are only implied by the ESSL 3.00 spec, but
1848 // the ESSL 3.10 spec lists these restrictions explicitly.
1849 if (type.array)
1850 {
1851 error(qualifierLocation, "cannot be an array of structures",
1852 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001853 }
1854 if (type.isStructureContainingArrays())
1855 {
1856 error(qualifierLocation, "cannot be a structure containing an array",
1857 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001858 }
1859 if (type.isStructureContainingType(EbtStruct))
1860 {
1861 error(qualifierLocation, "cannot be a structure containing a structure",
1862 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001863 }
1864 if (type.isStructureContainingType(EbtBool))
1865 {
1866 error(qualifierLocation, "cannot be a structure containing a bool",
1867 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001868 }
1869 }
1870}
1871
Martin Radev2cc85b32016-08-05 16:22:53 +03001872void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
1873{
1874 if (qualifier.getType() == QtStorage)
1875 {
1876 const TStorageQualifierWrapper &storageQualifier =
1877 static_cast<const TStorageQualifierWrapper &>(qualifier);
1878 if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
1879 !symbolTable.atGlobalLevel())
1880 {
1881 error(storageQualifier.getLine(),
1882 "Local variables can only use the const storage qualifier.",
1883 storageQualifier.getQualifierString().c_str());
1884 }
1885 }
1886}
1887
Olli Etuaho43364892017-02-13 16:00:12 +00001888void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
Martin Radev2cc85b32016-08-05 16:22:53 +03001889 const TSourceLoc &location)
1890{
1891 if (memoryQualifier.readonly)
1892 {
1893 error(location, "Only allowed with images.", "readonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03001894 }
1895 if (memoryQualifier.writeonly)
1896 {
1897 error(location, "Only allowed with images.", "writeonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03001898 }
Martin Radev049edfa2016-11-11 14:35:37 +02001899 if (memoryQualifier.coherent)
1900 {
1901 error(location, "Only allowed with images.", "coherent");
Martin Radev049edfa2016-11-11 14:35:37 +02001902 }
1903 if (memoryQualifier.restrictQualifier)
1904 {
1905 error(location, "Only allowed with images.", "restrict");
Martin Radev049edfa2016-11-11 14:35:37 +02001906 }
1907 if (memoryQualifier.volatileQualifier)
1908 {
1909 error(location, "Only allowed with images.", "volatile");
Martin Radev049edfa2016-11-11 14:35:37 +02001910 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001911}
1912
Olli Etuaho13389b62016-10-16 11:48:18 +01001913TIntermDeclaration *TParseContext::parseSingleDeclaration(
1914 TPublicType &publicType,
1915 const TSourceLoc &identifierOrTypeLocation,
1916 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04001917{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001918 TType type(publicType);
1919 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
1920 mDirectiveHandler.pragma().stdgl.invariantAll)
1921 {
1922 TQualifier qualifier = type.getQualifier();
1923
1924 // The directive handler has already taken care of rejecting invalid uses of this pragma
1925 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
1926 // affected variable declarations:
1927 //
1928 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
1929 // elsewhere, in TranslatorGLSL.)
1930 //
1931 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
1932 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
1933 // the way this is currently implemented we have to enable this compiler option before
1934 // parsing the shader and determining the shading language version it uses. If this were
1935 // implemented as a post-pass, the workaround could be more targeted.
1936 //
1937 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
1938 // the specification, but there are desktop OpenGL drivers that expect that this is the
1939 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
1940 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
1941 {
1942 type.setInvariant(true);
1943 }
1944 }
1945
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001946 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
1947 identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001948
Olli Etuahobab4c082015-04-24 16:38:49 +03001949 bool emptyDeclaration = (identifier == "");
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001950 mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration;
Olli Etuahofa33d582015-04-09 14:33:12 +03001951
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001952 TIntermSymbol *symbol = nullptr;
Olli Etuahobab4c082015-04-24 16:38:49 +03001953 if (emptyDeclaration)
1954 {
Martin Radevb8b01222016-11-20 23:25:53 +02001955 emptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001956 // In most cases we don't need to create a symbol node for an empty declaration.
1957 // But if the empty declaration is declaring a struct type, the symbol node will store that.
1958 if (type.getBasicType() == EbtStruct)
1959 {
1960 symbol = intermediate.addSymbol(0, "", type, identifierOrTypeLocation);
1961 }
Olli Etuahobab4c082015-04-24 16:38:49 +03001962 }
1963 else
Jamie Madill60ed9812013-06-06 11:56:46 -04001964 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001965 nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001966
Olli Etuaho856c4972016-08-08 11:38:39 +03001967 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001968
Olli Etuaho2935c582015-04-08 14:32:06 +03001969 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001970 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001971
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001972 if (variable)
Olli Etuaho13389b62016-10-16 11:48:18 +01001973 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001974 symbol = intermediate.addSymbol(variable->getUniqueId(), identifier, type,
1975 identifierOrTypeLocation);
Olli Etuaho13389b62016-10-16 11:48:18 +01001976 }
Jamie Madill60ed9812013-06-06 11:56:46 -04001977 }
1978
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001979 TIntermDeclaration *declaration = new TIntermDeclaration();
1980 declaration->setLine(identifierOrTypeLocation);
1981 if (symbol)
1982 {
1983 declaration->appendDeclarator(symbol);
1984 }
Olli Etuaho13389b62016-10-16 11:48:18 +01001985 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04001986}
1987
Olli Etuaho13389b62016-10-16 11:48:18 +01001988TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1989 const TSourceLoc &identifierLocation,
1990 const TString &identifier,
1991 const TSourceLoc &indexLocation,
1992 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04001993{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001994 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03001995
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001996 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
1997 identifierLocation);
1998
1999 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002000
Olli Etuaho856c4972016-08-08 11:38:39 +03002001 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002002
Olli Etuaho8a176262016-08-16 14:23:01 +03002003 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002004
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002005 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002006
Olli Etuaho856c4972016-08-08 11:38:39 +03002007 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002008 // Make the type an array even if size check failed.
2009 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2010 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04002011
Olli Etuaho2935c582015-04-08 14:32:06 +03002012 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002013 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04002014
Olli Etuaho13389b62016-10-16 11:48:18 +01002015 TIntermDeclaration *declaration = new TIntermDeclaration();
2016 declaration->setLine(identifierLocation);
2017
Olli Etuahoe7847b02015-03-16 11:56:12 +02002018 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002019 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002020 {
Jamie Madill60ed9812013-06-06 11:56:46 -04002021 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002022 declaration->appendDeclarator(symbol);
2023 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002024
Olli Etuaho13389b62016-10-16 11:48:18 +01002025 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002026}
2027
Olli Etuaho13389b62016-10-16 11:48:18 +01002028TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
2029 const TSourceLoc &identifierLocation,
2030 const TString &identifier,
2031 const TSourceLoc &initLocation,
2032 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04002033{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002034 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002035
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002036 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2037 identifierLocation);
2038
2039 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002040
Olli Etuaho13389b62016-10-16 11:48:18 +01002041 TIntermDeclaration *declaration = new TIntermDeclaration();
2042 declaration->setLine(identifierLocation);
2043
2044 TIntermBinary *initNode = nullptr;
2045 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04002046 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002047 if (initNode)
2048 {
2049 declaration->appendDeclarator(initNode);
2050 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002051 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002052 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002053}
2054
Olli Etuaho13389b62016-10-16 11:48:18 +01002055TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
Jamie Madillb98c3a82015-07-23 14:26:04 -04002056 TPublicType &publicType,
2057 const TSourceLoc &identifierLocation,
2058 const TString &identifier,
2059 const TSourceLoc &indexLocation,
2060 TIntermTyped *indexExpression,
2061 const TSourceLoc &initLocation,
2062 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002063{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002064 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002065
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002066 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2067 identifierLocation);
2068
2069 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002070
Olli Etuaho8a176262016-08-16 14:23:01 +03002071 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002072
2073 TPublicType arrayType(publicType);
2074
Olli Etuaho856c4972016-08-08 11:38:39 +03002075 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002076 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2077 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002078 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002079 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002080 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002081 }
2082 // Make the type an array even if size check failed.
2083 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2084 arrayType.setArraySize(size);
2085
Olli Etuaho13389b62016-10-16 11:48:18 +01002086 TIntermDeclaration *declaration = new TIntermDeclaration();
2087 declaration->setLine(identifierLocation);
2088
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002089 // initNode will correspond to the whole of "type b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002090 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002091 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2092 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002093 if (initNode)
2094 {
2095 declaration->appendDeclarator(initNode);
2096 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002097 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002098
2099 return declaration;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002100}
2101
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002102TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
Martin Radev70866b82016-07-22 15:27:42 +03002103 const TTypeQualifierBuilder &typeQualifierBuilder,
2104 const TSourceLoc &identifierLoc,
2105 const TString *identifier,
2106 const TSymbol *symbol)
Jamie Madill47e3ec02014-08-20 16:38:33 -04002107{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002108 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002109
Martin Radev70866b82016-07-22 15:27:42 +03002110 if (!typeQualifier.invariant)
2111 {
2112 error(identifierLoc, "Expected invariant", identifier->c_str());
2113 return nullptr;
2114 }
2115 if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
2116 {
2117 return nullptr;
2118 }
Jamie Madill47e3ec02014-08-20 16:38:33 -04002119 if (!symbol)
2120 {
2121 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002122 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04002123 }
Martin Radev70866b82016-07-22 15:27:42 +03002124 if (!IsQualifierUnspecified(typeQualifier.qualifier))
Jamie Madill47e3ec02014-08-20 16:38:33 -04002125 {
Martin Radev70866b82016-07-22 15:27:42 +03002126 error(identifierLoc, "invariant declaration specifies qualifier",
2127 getQualifierString(typeQualifier.qualifier));
Jamie Madill47e3ec02014-08-20 16:38:33 -04002128 }
Martin Radev70866b82016-07-22 15:27:42 +03002129 if (typeQualifier.precision != EbpUndefined)
2130 {
2131 error(identifierLoc, "invariant declaration specifies precision",
2132 getPrecisionString(typeQualifier.precision));
2133 }
2134 if (!typeQualifier.layoutQualifier.isEmpty())
2135 {
2136 error(identifierLoc, "invariant declaration specifies layout", "'layout'");
2137 }
2138
2139 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
2140 ASSERT(variable);
2141 const TType &type = variable->getType();
2142
2143 checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
2144 typeQualifier.line);
Olli Etuaho43364892017-02-13 16:00:12 +00002145 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev70866b82016-07-22 15:27:42 +03002146
2147 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
2148
2149 TIntermSymbol *intermSymbol =
2150 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
2151
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002152 return new TIntermInvariantDeclaration(intermSymbol, identifierLoc);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002153}
2154
Olli Etuaho13389b62016-10-16 11:48:18 +01002155void TParseContext::parseDeclarator(TPublicType &publicType,
2156 const TSourceLoc &identifierLocation,
2157 const TString &identifier,
2158 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002159{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002160 // If the declaration starting this declarator list was empty (example: int,), some checks were
2161 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002162 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002163 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002164 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2165 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002166 }
2167
Olli Etuaho856c4972016-08-08 11:38:39 +03002168 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002169
Olli Etuaho856c4972016-08-08 11:38:39 +03002170 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002171
Olli Etuaho2935c582015-04-08 14:32:06 +03002172 TVariable *variable = nullptr;
Olli Etuaho43364892017-02-13 16:00:12 +00002173 TType type(publicType);
2174 declareVariable(identifierLocation, identifier, type, &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002175
Olli Etuaho43364892017-02-13 16:00:12 +00002176 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002177 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002178 {
Jamie Madill502d66f2013-06-20 11:55:52 -04002179 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002180 declarationOut->appendDeclarator(symbol);
2181 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002182}
2183
Olli Etuaho13389b62016-10-16 11:48:18 +01002184void TParseContext::parseArrayDeclarator(TPublicType &publicType,
2185 const TSourceLoc &identifierLocation,
2186 const TString &identifier,
2187 const TSourceLoc &arrayLocation,
2188 TIntermTyped *indexExpression,
2189 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002190{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002191 // If the declaration starting this declarator list was empty (example: int,), some checks were
2192 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002193 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002194 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002195 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2196 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002197 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002198
Olli Etuaho856c4972016-08-08 11:38:39 +03002199 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002200
Olli Etuaho856c4972016-08-08 11:38:39 +03002201 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002202
Olli Etuaho8a176262016-08-16 14:23:01 +03002203 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04002204 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002205 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03002206 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03002207 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002208
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002209 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002210 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04002211
Jamie Madillb98c3a82015-07-23 14:26:04 -04002212 TIntermSymbol *symbol =
2213 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002214 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002215 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002216
Olli Etuaho13389b62016-10-16 11:48:18 +01002217 declarationOut->appendDeclarator(symbol);
Jamie Madill502d66f2013-06-20 11:55:52 -04002218 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002219}
2220
Olli Etuaho13389b62016-10-16 11:48:18 +01002221void TParseContext::parseInitDeclarator(const TPublicType &publicType,
2222 const TSourceLoc &identifierLocation,
2223 const TString &identifier,
2224 const TSourceLoc &initLocation,
2225 TIntermTyped *initializer,
2226 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002227{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002228 // If the declaration starting this declarator list was empty (example: int,), some checks were
2229 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002230 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002231 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002232 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2233 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002234 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002235
Olli Etuaho856c4972016-08-08 11:38:39 +03002236 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002237
Olli Etuaho13389b62016-10-16 11:48:18 +01002238 TIntermBinary *initNode = nullptr;
2239 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04002240 {
2241 //
2242 // build the intermediate representation
2243 //
Olli Etuaho13389b62016-10-16 11:48:18 +01002244 if (initNode)
Jamie Madill502d66f2013-06-20 11:55:52 -04002245 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002246 declarationOut->appendDeclarator(initNode);
Jamie Madill502d66f2013-06-20 11:55:52 -04002247 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002248 }
2249}
2250
Olli Etuaho13389b62016-10-16 11:48:18 +01002251void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
2252 const TSourceLoc &identifierLocation,
2253 const TString &identifier,
2254 const TSourceLoc &indexLocation,
2255 TIntermTyped *indexExpression,
2256 const TSourceLoc &initLocation,
2257 TIntermTyped *initializer,
2258 TIntermDeclaration *declarationOut)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002259{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002260 // If the declaration starting this declarator list was empty (example: int,), some checks were
2261 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002262 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002263 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002264 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2265 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002266 }
2267
Olli Etuaho856c4972016-08-08 11:38:39 +03002268 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002269
Olli Etuaho8a176262016-08-16 14:23:01 +03002270 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002271
2272 TPublicType arrayType(publicType);
2273
Olli Etuaho856c4972016-08-08 11:38:39 +03002274 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002275 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2276 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002277 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002278 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002279 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002280 }
2281 // Make the type an array even if size check failed.
2282 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2283 arrayType.setArraySize(size);
2284
2285 // initNode will correspond to the whole of "b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002286 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002287 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2288 {
2289 if (initNode)
2290 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002291 declarationOut->appendDeclarator(initNode);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002292 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002293 }
2294}
2295
Martin Radev70866b82016-07-22 15:27:42 +03002296void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
Jamie Madilla295edf2013-06-06 11:56:48 -04002297{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002298 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madilla295edf2013-06-06 11:56:48 -04002299 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04002300
Martin Radev70866b82016-07-22 15:27:42 +03002301 checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
2302 typeQualifier.line);
2303
Jamie Madillc2128ff2016-07-04 10:26:17 -04002304 // It should never be the case, but some strange parser errors can send us here.
2305 if (layoutQualifier.isEmpty())
2306 {
2307 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04002308 return;
2309 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002310
Martin Radev802abe02016-08-04 17:48:32 +03002311 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04002312 {
Olli Etuaho43364892017-02-13 16:00:12 +00002313 error(typeQualifier.line, "invalid layout qualifier combination", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04002314 return;
2315 }
2316
Olli Etuaho43364892017-02-13 16:00:12 +00002317 checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);
2318
2319 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev2cc85b32016-08-05 16:22:53 +03002320
2321 checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
2322
Andrei Volykhina5527072017-03-22 16:46:30 +03002323 checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv);
2324
Martin Radev802abe02016-08-04 17:48:32 +03002325 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04002326 {
Martin Radev802abe02016-08-04 17:48:32 +03002327 if (mComputeShaderLocalSizeDeclared &&
2328 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
2329 {
2330 error(typeQualifier.line, "Work group size does not match the previous declaration",
2331 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002332 return;
2333 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002334
Martin Radev802abe02016-08-04 17:48:32 +03002335 if (mShaderVersion < 310)
2336 {
2337 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002338 return;
2339 }
Jamie Madill099c0f32013-06-20 11:55:52 -04002340
Martin Radev4c4c8e72016-08-04 12:25:34 +03002341 if (!layoutQualifier.localSize.isAnyValueSet())
Martin Radev802abe02016-08-04 17:48:32 +03002342 {
2343 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002344 return;
2345 }
2346
2347 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
2348 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
2349
2350 const TConstantUnion *maxComputeWorkGroupSizeData =
2351 maxComputeWorkGroupSize->getConstPointer();
2352
2353 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
2354 {
2355 if (layoutQualifier.localSize[i] != -1)
2356 {
2357 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
2358 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
2359 if (mComputeShaderLocalSize[i] < 1 ||
2360 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
2361 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002362 std::stringstream reasonStream;
2363 reasonStream << "invalid value: Value must be at least 1 and no greater than "
2364 << maxComputeWorkGroupSizeValue;
2365 const std::string &reason = reasonStream.str();
Martin Radev802abe02016-08-04 17:48:32 +03002366
Olli Etuaho4de340a2016-12-16 09:32:03 +00002367 error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03002368 return;
2369 }
2370 }
2371 }
2372
2373 mComputeShaderLocalSizeDeclared = true;
2374 }
Olli Etuaho09b04a22016-12-15 13:30:26 +00002375 else if (mMultiviewAvailable &&
2376 (isExtensionEnabled("GL_OVR_multiview") || isExtensionEnabled("GL_OVR_multiview2")) &&
2377 typeQualifier.qualifier == EvqVertexIn)
2378 {
2379 // This error is only specified in WebGL, but tightens unspecified behavior in the native
2380 // specification.
2381 if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
2382 {
2383 error(typeQualifier.line, "Number of views does not match the previous declaration",
2384 "layout");
2385 return;
2386 }
2387
2388 if (layoutQualifier.numViews == -1)
2389 {
2390 error(typeQualifier.line, "No num_views specified", "layout");
2391 return;
2392 }
2393
2394 if (layoutQualifier.numViews > mMaxNumViews)
2395 {
2396 error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
2397 "layout");
2398 return;
2399 }
2400
2401 mNumViews = layoutQualifier.numViews;
2402 }
Martin Radev802abe02016-08-04 17:48:32 +03002403 else
Jamie Madill1566ef72013-06-20 11:55:54 -04002404 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00002405 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03002406 {
Martin Radev802abe02016-08-04 17:48:32 +03002407 return;
2408 }
2409
2410 if (typeQualifier.qualifier != EvqUniform)
2411 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002412 error(typeQualifier.line, "invalid qualifier: global layout must be uniform",
2413 getQualifierString(typeQualifier.qualifier));
Martin Radev802abe02016-08-04 17:48:32 +03002414 return;
2415 }
2416
2417 if (mShaderVersion < 300)
2418 {
2419 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
2420 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002421 return;
2422 }
2423
Olli Etuaho09b04a22016-12-15 13:30:26 +00002424 checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002425
2426 if (layoutQualifier.matrixPacking != EmpUnspecified)
2427 {
2428 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
2429 }
2430
2431 if (layoutQualifier.blockStorage != EbsUnspecified)
2432 {
2433 mDefaultBlockStorage = layoutQualifier.blockStorage;
2434 }
Jamie Madill1566ef72013-06-20 11:55:54 -04002435 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002436}
2437
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002438TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
2439 const TFunction &function,
2440 const TSourceLoc &location,
2441 bool insertParametersToSymbolTable)
2442{
Olli Etuahofe486322017-03-21 09:30:54 +00002443 TIntermFunctionPrototype *prototype =
2444 new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function));
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002445 // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
2446 // point to the data that already exists in the symbol table.
2447 prototype->getFunctionSymbolInfo()->setFromFunction(function);
2448 prototype->setLine(location);
2449
2450 for (size_t i = 0; i < function.getParamCount(); i++)
2451 {
2452 const TConstParameter &param = function.getParam(i);
2453
2454 // If the parameter has no name, it's not an error, just don't add it to symbol table (could
2455 // be used for unused args).
2456 if (param.name != nullptr)
2457 {
2458 TVariable *variable = new TVariable(param.name, *param.type);
2459
2460 // Insert the parameter in the symbol table.
2461 if (insertParametersToSymbolTable && !symbolTable.declare(variable))
2462 {
2463 error(location, "redefinition", variable->getName().c_str());
2464 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2465 continue;
2466 }
2467 TIntermSymbol *symbol = intermediate.addSymbol(
2468 variable->getUniqueId(), variable->getName(), variable->getType(), location);
2469 prototype->appendParameter(symbol);
2470 }
2471 else
2472 {
2473 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2474 }
2475 }
2476 return prototype;
2477}
2478
Olli Etuaho16c745a2017-01-16 17:02:27 +00002479TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
2480 const TFunction &parsedFunction,
2481 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002482{
Olli Etuaho476197f2016-10-11 13:59:08 +01002483 // Note: function found from the symbol table could be the same as parsedFunction if this is the
2484 // first declaration. Either way the instance in the symbol table is used to track whether the
2485 // function is declared multiple times.
2486 TFunction *function = static_cast<TFunction *>(
2487 symbolTable.find(parsedFunction.getMangledName(), getShaderVersion()));
2488 if (function->hasPrototypeDeclaration() && mShaderVersion == 100)
Olli Etuaho5d653182016-01-04 14:43:28 +02002489 {
2490 // ESSL 1.00.17 section 4.2.7.
2491 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
2492 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02002493 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002494 function->setHasPrototypeDeclaration();
Olli Etuaho5d653182016-01-04 14:43:28 +02002495
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002496 TIntermFunctionPrototype *prototype =
2497 createPrototypeNodeFromFunction(*function, location, false);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002498
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002499 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002500
2501 if (!symbolTable.atGlobalLevel())
2502 {
2503 // ESSL 3.00.4 section 4.2.4.
2504 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002505 }
2506
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002507 return prototype;
2508}
2509
Olli Etuaho336b1472016-10-05 16:37:55 +01002510TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002511 TIntermFunctionPrototype *functionPrototype,
Olli Etuaho336b1472016-10-05 16:37:55 +01002512 TIntermBlock *functionBody,
2513 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002514{
Olli Etuahof51fdd22016-10-03 10:03:40 +01002515 // Check that non-void functions have at least one return statement.
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002516 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2517 {
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002518 error(location, "function does not return a value:",
2519 functionPrototype->getFunctionSymbolInfo()->getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002520 }
2521
Olli Etuahof51fdd22016-10-03 10:03:40 +01002522 if (functionBody == nullptr)
2523 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01002524 functionBody = new TIntermBlock();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002525 functionBody->setLine(location);
2526 }
Olli Etuaho336b1472016-10-05 16:37:55 +01002527 TIntermFunctionDefinition *functionNode =
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002528 new TIntermFunctionDefinition(functionPrototype, functionBody);
Olli Etuaho336b1472016-10-05 16:37:55 +01002529 functionNode->setLine(location);
Olli Etuahof51fdd22016-10-03 10:03:40 +01002530
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002531 symbolTable.pop();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002532 return functionNode;
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002533}
2534
Olli Etuaho476197f2016-10-11 13:59:08 +01002535void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
2536 TFunction **function,
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002537 TIntermFunctionPrototype **prototypeOut)
Jamie Madill185fb402015-06-12 15:48:48 -04002538{
Olli Etuaho476197f2016-10-11 13:59:08 +01002539 ASSERT(function);
2540 ASSERT(*function);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002541 const TSymbol *builtIn =
Olli Etuaho476197f2016-10-11 13:59:08 +01002542 symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002543
2544 if (builtIn)
2545 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002546 error(location, "built-in functions cannot be redefined", (*function)->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002547 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002548 else
Jamie Madill185fb402015-06-12 15:48:48 -04002549 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002550 TFunction *prevDec = static_cast<TFunction *>(
2551 symbolTable.find((*function)->getMangledName(), getShaderVersion()));
2552
2553 // Note: 'prevDec' could be 'function' if this is the first time we've seen function as it
2554 // would have just been put in the symbol table. Otherwise, we're looking up an earlier
2555 // occurance.
2556 if (*function != prevDec)
2557 {
2558 // Swap the parameters of the previous declaration to the parameters of the function
2559 // definition (parameter names may differ).
2560 prevDec->swapParameters(**function);
2561
2562 // The function definition will share the same symbol as any previous declaration.
2563 *function = prevDec;
2564 }
2565
2566 if ((*function)->isDefined())
2567 {
2568 error(location, "function already has a body", (*function)->getName().c_str());
2569 }
2570
2571 (*function)->setDefined();
Jamie Madill185fb402015-06-12 15:48:48 -04002572 }
Jamie Madill185fb402015-06-12 15:48:48 -04002573
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002574 // Remember the return type for later checking for return statements.
Olli Etuaho476197f2016-10-11 13:59:08 +01002575 mCurrentFunctionType = &((*function)->getReturnType());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002576 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002577
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002578 *prototypeOut = createPrototypeNodeFromFunction(**function, location, true);
Jamie Madill185fb402015-06-12 15:48:48 -04002579 setLoopNestingLevel(0);
2580}
2581
Jamie Madillb98c3a82015-07-23 14:26:04 -04002582TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002583{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002584 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002585 // We don't know at this point whether this is a function definition or a prototype.
2586 // The definition production code will check for redefinitions.
2587 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002588 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002589 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2590 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002591 //
2592 TFunction *prevDec =
2593 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302594
Martin Radevda6254b2016-12-14 17:00:36 +02002595 if (getShaderVersion() >= 300 &&
2596 symbolTable.hasUnmangledBuiltInForShaderVersion(function->getName().c_str(),
2597 getShaderVersion()))
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302598 {
Martin Radevda6254b2016-12-14 17:00:36 +02002599 // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions.
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302600 // Therefore overloading or redefining builtin functions is an error.
2601 error(location, "Name of a built-in function cannot be redeclared as function",
2602 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302603 }
2604 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002605 {
2606 if (prevDec->getReturnType() != function->getReturnType())
2607 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002608 error(location, "function must have the same return type in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002609 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002610 }
2611 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2612 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002613 if (prevDec->getParam(i).type->getQualifier() !=
2614 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002615 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002616 error(location,
2617 "function must have the same parameter qualifiers in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002618 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002619 }
2620 }
2621 }
2622
2623 //
2624 // Check for previously declared variables using the same name.
2625 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002626 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002627 if (prevSym)
2628 {
2629 if (!prevSym->isFunction())
2630 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002631 error(location, "redefinition of a function", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002632 }
2633 }
2634 else
2635 {
2636 // Insert the unmangled name to detect potential future redefinition as a variable.
Olli Etuaho476197f2016-10-11 13:59:08 +01002637 symbolTable.getOuterLevel()->insertUnmangled(function);
Jamie Madill185fb402015-06-12 15:48:48 -04002638 }
2639
2640 // We're at the inner scope level of the function's arguments and body statement.
2641 // Add the function prototype to the surrounding scope instead.
2642 symbolTable.getOuterLevel()->insert(function);
2643
Olli Etuaho78d13742017-01-18 13:06:10 +00002644 // Raise error message if main function takes any parameters or return anything other than void
2645 if (function->getName() == "main")
2646 {
2647 if (function->getParamCount() > 0)
2648 {
2649 error(location, "function cannot take any parameter(s)", "main");
2650 }
2651 if (function->getReturnType().getBasicType() != EbtVoid)
2652 {
2653 error(location, "main function cannot return a value",
2654 function->getReturnType().getBasicString());
2655 }
2656 }
2657
Jamie Madill185fb402015-06-12 15:48:48 -04002658 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002659 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2660 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002661 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2662 //
2663 return function;
2664}
2665
Olli Etuaho9de84a52016-06-14 17:36:01 +03002666TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2667 const TString *name,
2668 const TSourceLoc &location)
2669{
2670 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2671 {
2672 error(location, "no qualifiers allowed for function return",
2673 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002674 }
2675 if (!type.layoutQualifier.isEmpty())
2676 {
2677 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002678 }
jchen10cc2a10e2017-05-03 14:05:12 +08002679 // make sure an opaque type is not involved as well...
2680 std::string reason(getBasicString(type.getBasicType()));
2681 reason += "s can't be function return values";
2682 checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002683 if (mShaderVersion < 300)
2684 {
2685 // Array return values are forbidden, but there's also no valid syntax for declaring array
2686 // return values in ESSL 1.00.
Olli Etuaho77ba4082016-12-16 12:01:18 +00002687 ASSERT(type.arraySize == 0 || mDiagnostics->numErrors() > 0);
Olli Etuahoe29324f2016-06-15 10:58:03 +03002688
2689 if (type.isStructureContainingArrays())
2690 {
2691 // ESSL 1.00.17 section 6.1 Function Definitions
2692 error(location, "structures containing arrays can't be function return values",
2693 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002694 }
2695 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002696
2697 // Add the function as a prototype after parsing it (we do not support recursion)
2698 return new TFunction(name, new TType(type));
2699}
2700
Jamie Madill06145232015-05-13 13:10:01 -04002701TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002702{
Jamie Madill06145232015-05-13 13:10:01 -04002703 TPublicType publicType = publicTypeIn;
Martin Radev4a9cd802016-09-01 16:51:51 +03002704 if (publicType.isStructSpecifier())
Olli Etuahobd163f62015-11-13 12:15:38 +02002705 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002706 error(publicType.getLine(), "constructor can't be a structure definition",
2707 getBasicString(publicType.getBasicType()));
Olli Etuahobd163f62015-11-13 12:15:38 +02002708 }
2709
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002710 TOperator op = EOpNull;
Martin Radev4a9cd802016-09-01 16:51:51 +03002711 if (publicType.getUserDef())
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002712 {
2713 op = EOpConstructStruct;
2714 }
2715 else
2716 {
Geoff Lang156d7192016-07-21 16:11:00 -04002717 op = sh::TypeToConstructorOperator(TType(publicType));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002718 if (op == EOpNull)
2719 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002720 error(publicType.getLine(), "cannot construct this type",
2721 getBasicString(publicType.getBasicType()));
2722 publicType.setBasicType(EbtFloat);
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002723 op = EOpConstructFloat;
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002724 }
2725 }
2726
Dmitry Skiba7f17a502015-06-22 15:08:39 -07002727 const TType *type = new TType(publicType);
Olli Etuaho72d10202017-01-19 15:58:30 +00002728 return new TFunction(nullptr, type, op);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002729}
2730
Jamie Madillb98c3a82015-07-23 14:26:04 -04002731// This function is used to test for the correctness of the parameters passed to various constructor
2732// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002733//
Olli Etuaho856c4972016-08-08 11:38:39 +03002734// 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 +00002735//
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002736TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002737 TOperator op,
Olli Etuaho72d10202017-01-19 15:58:30 +00002738 TType type,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302739 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002740{
Olli Etuaho856c4972016-08-08 11:38:39 +03002741 if (type.isUnsizedArray())
2742 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002743 if (arguments->empty())
Olli Etuahobbe9fb52016-11-03 17:16:05 +00002744 {
2745 error(line, "implicitly sized array constructor must have at least one argument", "[]");
2746 type.setArraySize(1u);
2747 return TIntermTyped::CreateZero(type);
2748 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002749 type.setArraySize(static_cast<unsigned int>(arguments->size()));
Olli Etuaho856c4972016-08-08 11:38:39 +03002750 }
Olli Etuaho856c4972016-08-08 11:38:39 +03002751
Olli Etuaho72d10202017-01-19 15:58:30 +00002752 if (!checkConstructorArguments(line, arguments, op, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002753 {
Olli Etuaho72d10202017-01-19 15:58:30 +00002754 return TIntermTyped::CreateZero(type);
Olli Etuaho856c4972016-08-08 11:38:39 +03002755 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002756
Olli Etuahofe486322017-03-21 09:30:54 +00002757 TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, op, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002758 constructorNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002759
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002760 TIntermTyped *constConstructor =
2761 intermediate.foldAggregateBuiltIn(constructorNode, mDiagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002762 if (constConstructor)
2763 {
2764 return constConstructor;
2765 }
2766
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002767 return constructorNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002768}
2769
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002770//
2771// Interface/uniform blocks
2772//
Olli Etuaho13389b62016-10-16 11:48:18 +01002773TIntermDeclaration *TParseContext::addInterfaceBlock(
Martin Radev70866b82016-07-22 15:27:42 +03002774 const TTypeQualifierBuilder &typeQualifierBuilder,
2775 const TSourceLoc &nameLine,
2776 const TString &blockName,
2777 TFieldList *fieldList,
2778 const TString *instanceName,
2779 const TSourceLoc &instanceLine,
2780 TIntermTyped *arrayIndex,
2781 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002782{
Olli Etuaho856c4972016-08-08 11:38:39 +03002783 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002784
Olli Etuaho77ba4082016-12-16 12:01:18 +00002785 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03002786
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002787 if (typeQualifier.qualifier != EvqUniform)
2788 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002789 error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform",
2790 getQualifierString(typeQualifier.qualifier));
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002791 }
2792
Martin Radev70866b82016-07-22 15:27:42 +03002793 if (typeQualifier.invariant)
2794 {
2795 error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
2796 }
2797
Olli Etuaho43364892017-02-13 16:00:12 +00002798 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
2799
2800 // TODO(oetuaho): Remove this and support binding for blocks.
2801 checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
Martin Radev2cc85b32016-08-05 16:22:53 +03002802
Andrei Volykhina5527072017-03-22 16:46:30 +03002803 checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
2804
Jamie Madill099c0f32013-06-20 11:55:52 -04002805 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03002806 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04002807
Jamie Madill099c0f32013-06-20 11:55:52 -04002808 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2809 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002810 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002811 }
2812
Jamie Madill1566ef72013-06-20 11:55:54 -04002813 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2814 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002815 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002816 }
2817
Olli Etuaho856c4972016-08-08 11:38:39 +03002818 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002819
Martin Radev2cc85b32016-08-05 16:22:53 +03002820 checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
2821
Arun Patole7e7e68d2015-05-22 12:02:25 +05302822 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2823 if (!symbolTable.declare(blockNameSymbol))
2824 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002825 error(nameLine, "redefinition of an interface block name", blockName.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002826 }
2827
Jamie Madill98493dd2013-07-08 14:39:03 -04002828 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302829 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2830 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002831 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302832 TType *fieldType = field->type();
jchen10cc2a10e2017-05-03 14:05:12 +08002833 if (IsOpaqueType(fieldType->getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +05302834 {
jchen10cc2a10e2017-05-03 14:05:12 +08002835 std::string reason("unsupported type - ");
2836 reason += fieldType->getBasicString();
2837 reason += " types are not allowed in interface blocks";
2838 error(field->line(), reason.c_str(), fieldType->getBasicString());
Martin Radev2cc85b32016-08-05 16:22:53 +03002839 }
2840
Jamie Madill98493dd2013-07-08 14:39:03 -04002841 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002842 switch (qualifier)
2843 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002844 case EvqGlobal:
2845 case EvqUniform:
2846 break;
2847 default:
2848 error(field->line(), "invalid qualifier on interface block member",
2849 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04002850 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002851 }
Jamie Madilla5efff92013-06-06 11:56:47 -04002852
Martin Radev70866b82016-07-22 15:27:42 +03002853 if (fieldType->isInvariant())
2854 {
2855 error(field->line(), "invalid qualifier on interface block member", "invariant");
2856 }
2857
Jamie Madilla5efff92013-06-06 11:56:47 -04002858 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04002859 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03002860 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Jamie Madill099c0f32013-06-20 11:55:52 -04002861
Jamie Madill98493dd2013-07-08 14:39:03 -04002862 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04002863 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002864 error(field->line(), "invalid layout qualifier: cannot be used here",
2865 getBlockStorageString(fieldLayoutQualifier.blockStorage));
Jamie Madill1566ef72013-06-20 11:55:54 -04002866 }
2867
Jamie Madill98493dd2013-07-08 14:39:03 -04002868 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04002869 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002870 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002871 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002872 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04002873 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002874 warning(field->line(),
2875 "extraneous layout qualifier: only has an effect on matrix types",
2876 getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
Jamie Madill099c0f32013-06-20 11:55:52 -04002877 }
2878
Jamie Madill98493dd2013-07-08 14:39:03 -04002879 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002880 }
2881
Jamie Madill98493dd2013-07-08 14:39:03 -04002882 // add array index
Olli Etuaho856c4972016-08-08 11:38:39 +03002883 unsigned int arraySize = 0;
2884 if (arrayIndex != nullptr)
Jamie Madill98493dd2013-07-08 14:39:03 -04002885 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002886 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
Jamie Madill98493dd2013-07-08 14:39:03 -04002887 }
2888
Jamie Madillb98c3a82015-07-23 14:26:04 -04002889 TInterfaceBlock *interfaceBlock =
2890 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2891 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
2892 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002893
2894 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04002895 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002896
Jamie Madill98493dd2013-07-08 14:39:03 -04002897 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002898 {
2899 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04002900 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2901 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002902 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302903 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04002904
2905 // set parent pointer of the field variable
2906 fieldType->setInterfaceBlock(interfaceBlock);
2907
Arun Patole7e7e68d2015-05-22 12:02:25 +05302908 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04002909 fieldVariable->setQualifier(typeQualifier.qualifier);
2910
Arun Patole7e7e68d2015-05-22 12:02:25 +05302911 if (!symbolTable.declare(fieldVariable))
2912 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002913 error(field->line(), "redefinition of an interface block member name",
2914 field->name().c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002915 }
2916 }
2917 }
2918 else
2919 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002920 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03002921
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002922 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05302923 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002924 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04002925
Arun Patole7e7e68d2015-05-22 12:02:25 +05302926 if (!symbolTable.declare(instanceTypeDef))
2927 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002928 error(instanceLine, "redefinition of an interface block instance name",
2929 instanceName->c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002930 }
2931
Jamie Madillb98c3a82015-07-23 14:26:04 -04002932 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002933 symbolName = instanceTypeDef->getName();
2934 }
2935
Olli Etuaho13389b62016-10-16 11:48:18 +01002936 TIntermSymbol *blockSymbol =
2937 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line);
2938 TIntermDeclaration *declaration = new TIntermDeclaration();
2939 declaration->appendDeclarator(blockSymbol);
2940 declaration->setLine(nameLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04002941
2942 exitStructDeclaration();
Olli Etuaho13389b62016-10-16 11:48:18 +01002943 return declaration;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002944}
2945
Olli Etuaho383b7912016-08-05 11:22:59 +03002946void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002947{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002948 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002949
2950 // Embedded structure definitions are not supported per GLSL ES spec.
Olli Etuaho4de340a2016-12-16 09:32:03 +00002951 // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302952 if (mStructNestingLevel > 1)
2953 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002954 error(line, "Embedded struct definitions are not allowed", "struct");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002955 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002956}
2957
2958void TParseContext::exitStructDeclaration()
2959{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002960 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002961}
2962
Olli Etuaho8a176262016-08-16 14:23:01 +03002963void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002964{
Jamie Madillacb4b812016-11-07 13:50:29 -05002965 if (!sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +05302966 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002967 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002968 }
2969
Arun Patole7e7e68d2015-05-22 12:02:25 +05302970 if (field.type()->getBasicType() != EbtStruct)
2971 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002972 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002973 }
2974
2975 // We're already inside a structure definition at this point, so add
2976 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302977 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2978 {
Jamie Madill41a49272014-03-18 16:10:13 -04002979 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002980 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
2981 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04002982 std::string reason = reasonStream.str();
Olli Etuaho4de340a2016-12-16 09:32:03 +00002983 error(line, reason.c_str(), field.name().c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03002984 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002985 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002986}
2987
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00002988//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002989// Parse an array index expression
2990//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002991TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
2992 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302993 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002994{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002995 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2996 {
2997 if (baseExpression->getAsSymbolNode())
2998 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302999 error(location, " left of '[' is not of type array, matrix, or vector ",
3000 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003001 }
3002 else
3003 {
3004 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
3005 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003006
3007 TConstantUnion *unionArray = new TConstantUnion[1];
3008 unionArray->setFConst(0.0f);
3009 return intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst),
3010 location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003011 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003012
Jamie Madill21c1e452014-12-29 11:33:41 -05003013 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
3014
Olli Etuaho36b05142015-11-12 13:10:42 +02003015 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
3016 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
3017 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
3018 // index is a constant expression.
3019 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
3020 {
3021 if (baseExpression->isInterfaceBlock())
3022 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003023 error(location,
3024 "array indexes for interface blocks arrays must be constant integral expressions",
3025 "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02003026 }
3027 else if (baseExpression->getQualifier() == EvqFragmentOut)
3028 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003029 error(location,
3030 "array indexes for fragment outputs must be constant integral expressions", "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02003031 }
Olli Etuaho3e960462015-11-12 15:58:39 +02003032 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
3033 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003034 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3e960462015-11-12 15:58:39 +02003035 }
Olli Etuaho36b05142015-11-12 13:10:42 +02003036 }
3037
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003038 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04003039 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003040 // If an out-of-range index is not qualified as constant, the behavior in the spec is
3041 // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
3042 // constant fold expressions that are not constant expressions). The most compatible way to
3043 // handle this case is to report a warning instead of an error and force the index to be in
3044 // the correct range.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003045 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003046 int index = indexConstantUnion->getIConst(0);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003047
3048 int safeIndex = -1;
3049
3050 if (baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04003051 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003052 if (baseExpression->getQualifier() == EvqFragData && index > 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003053 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003054 if (mShaderSpec == SH_WEBGL2_SPEC)
3055 {
3056 // Error has been already generated if index is not const.
3057 if (indexExpression->getQualifier() == EvqConst)
3058 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003059 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003060 }
3061 safeIndex = 0;
3062 }
3063 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
3064 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003065 outOfRangeError(outOfRangeIndexIsError, location,
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003066 "array index for gl_FragData must be zero when "
Olli Etuaho4de340a2016-12-16 09:32:03 +00003067 "GL_EXT_draw_buffers is disabled",
3068 "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003069 safeIndex = 0;
3070 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03003071 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003072 // Only do generic out-of-range check if similar error hasn't already been reported.
3073 if (safeIndex < 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003074 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003075 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3076 baseExpression->getArraySize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003077 "array index out of range");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003078 }
3079 }
3080 else if (baseExpression->isMatrix())
3081 {
3082 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
Olli Etuaho90892fb2016-07-14 14:44:51 +03003083 baseExpression->getType().getCols(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003084 "matrix field selection out of range");
Jamie Madill7164cf42013-07-08 13:30:59 -04003085 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003086 else if (baseExpression->isVector())
Jamie Madill7164cf42013-07-08 13:30:59 -04003087 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003088 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3089 baseExpression->getType().getNominalSize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003090 "vector field selection out of range");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003091 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003092
3093 ASSERT(safeIndex >= 0);
3094 // Data of constant unions can't be changed, because it may be shared with other
3095 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
3096 // sanitized object.
3097 if (safeIndex != index)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003098 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003099 TConstantUnion *safeConstantUnion = new TConstantUnion();
3100 safeConstantUnion->setIConst(safeIndex);
3101 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003102 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003103
3104 return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003105 mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003106 }
Jamie Madill7164cf42013-07-08 13:30:59 -04003107 else
3108 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003109 return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003110 mDiagnostics);
Jamie Madill7164cf42013-07-08 13:30:59 -04003111 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003112}
3113
Olli Etuaho90892fb2016-07-14 14:44:51 +03003114int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
3115 const TSourceLoc &location,
3116 int index,
3117 int arraySize,
Olli Etuaho4de340a2016-12-16 09:32:03 +00003118 const char *reason)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003119{
3120 if (index >= arraySize || index < 0)
3121 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003122 std::stringstream reasonStream;
3123 reasonStream << reason << " '" << index << "'";
3124 std::string token = reasonStream.str();
3125 outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
Olli Etuaho90892fb2016-07-14 14:44:51 +03003126 if (index < 0)
3127 {
3128 return 0;
3129 }
3130 else
3131 {
3132 return arraySize - 1;
3133 }
3134 }
3135 return index;
3136}
3137
Jamie Madillb98c3a82015-07-23 14:26:04 -04003138TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
3139 const TSourceLoc &dotLocation,
3140 const TString &fieldString,
3141 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003142{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003143 if (baseExpression->isArray())
3144 {
3145 error(fieldLocation, "cannot apply dot operator to an array", ".");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003146 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003147 }
3148
3149 if (baseExpression->isVector())
3150 {
3151 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003152 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
3153 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003154 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003155 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003156 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003157 }
3158
Olli Etuahob6fa0432016-09-28 16:28:05 +01003159 return TIntermediate::AddSwizzle(baseExpression, fields, dotLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003160 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003161 else if (baseExpression->getBasicType() == EbtStruct)
3162 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303163 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003164 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003165 {
3166 error(dotLocation, "structure has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003167 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003168 }
3169 else
3170 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003171 bool fieldFound = false;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003172 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003173 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003174 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003175 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003176 {
3177 fieldFound = true;
3178 break;
3179 }
3180 }
3181 if (fieldFound)
3182 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003183 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3184 index->setLine(fieldLocation);
3185 return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003186 dotLocation, mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003187 }
3188 else
3189 {
3190 error(dotLocation, " no such field in structure", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003191 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003192 }
3193 }
3194 }
Jamie Madill98493dd2013-07-08 14:39:03 -04003195 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003196 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303197 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003198 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003199 {
3200 error(dotLocation, "interface block has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003201 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003202 }
3203 else
3204 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003205 bool fieldFound = false;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003206 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003207 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003208 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003209 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003210 {
3211 fieldFound = true;
3212 break;
3213 }
3214 }
3215 if (fieldFound)
3216 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003217 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3218 index->setLine(fieldLocation);
3219 return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003220 dotLocation, mDiagnostics);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003221 }
3222 else
3223 {
3224 error(dotLocation, " no such field in interface block", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003225 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003226 }
3227 }
3228 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003229 else
3230 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003231 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003232 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03003233 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303234 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003235 }
3236 else
3237 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303238 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03003239 " field selection requires structure, vector, or interface block on left hand "
3240 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303241 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003242 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003243 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003244 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003245}
3246
Jamie Madillb98c3a82015-07-23 14:26:04 -04003247TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3248 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003249{
Martin Radev802abe02016-08-04 17:48:32 +03003250 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003251
3252 if (qualifierType == "shared")
3253 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003254 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003255 {
3256 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
3257 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003258 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003259 }
3260 else if (qualifierType == "packed")
3261 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003262 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003263 {
3264 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
3265 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003266 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003267 }
3268 else if (qualifierType == "std140")
3269 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003270 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003271 }
3272 else if (qualifierType == "row_major")
3273 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003274 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003275 }
3276 else if (qualifierType == "column_major")
3277 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003278 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003279 }
3280 else if (qualifierType == "location")
3281 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003282 error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
3283 qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003284 }
Andrei Volykhina5527072017-03-22 16:46:30 +03003285 else if (qualifierType == "yuv" && isExtensionEnabled("GL_EXT_YUV_target") &&
3286 mShaderType == GL_FRAGMENT_SHADER)
3287 {
3288 qualifier.yuv = true;
3289 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003290 else if (qualifierType == "rgba32f")
3291 {
3292 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3293 qualifier.imageInternalFormat = EiifRGBA32F;
3294 }
3295 else if (qualifierType == "rgba16f")
3296 {
3297 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3298 qualifier.imageInternalFormat = EiifRGBA16F;
3299 }
3300 else if (qualifierType == "r32f")
3301 {
3302 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3303 qualifier.imageInternalFormat = EiifR32F;
3304 }
3305 else if (qualifierType == "rgba8")
3306 {
3307 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3308 qualifier.imageInternalFormat = EiifRGBA8;
3309 }
3310 else if (qualifierType == "rgba8_snorm")
3311 {
3312 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3313 qualifier.imageInternalFormat = EiifRGBA8_SNORM;
3314 }
3315 else if (qualifierType == "rgba32i")
3316 {
3317 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3318 qualifier.imageInternalFormat = EiifRGBA32I;
3319 }
3320 else if (qualifierType == "rgba16i")
3321 {
3322 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3323 qualifier.imageInternalFormat = EiifRGBA16I;
3324 }
3325 else if (qualifierType == "rgba8i")
3326 {
3327 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3328 qualifier.imageInternalFormat = EiifRGBA8I;
3329 }
3330 else if (qualifierType == "r32i")
3331 {
3332 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3333 qualifier.imageInternalFormat = EiifR32I;
3334 }
3335 else if (qualifierType == "rgba32ui")
3336 {
3337 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3338 qualifier.imageInternalFormat = EiifRGBA32UI;
3339 }
3340 else if (qualifierType == "rgba16ui")
3341 {
3342 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3343 qualifier.imageInternalFormat = EiifRGBA16UI;
3344 }
3345 else if (qualifierType == "rgba8ui")
3346 {
3347 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3348 qualifier.imageInternalFormat = EiifRGBA8UI;
3349 }
3350 else if (qualifierType == "r32ui")
3351 {
3352 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3353 qualifier.imageInternalFormat = EiifR32UI;
3354 }
3355
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003356 else
3357 {
3358 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003359 }
3360
Jamie Madilla5efff92013-06-06 11:56:47 -04003361 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003362}
3363
Martin Radev802abe02016-08-04 17:48:32 +03003364void TParseContext::parseLocalSize(const TString &qualifierType,
3365 const TSourceLoc &qualifierTypeLine,
3366 int intValue,
3367 const TSourceLoc &intValueLine,
3368 const std::string &intValueString,
3369 size_t index,
Martin Radev4c4c8e72016-08-04 12:25:34 +03003370 sh::WorkGroupSize *localSize)
Martin Radev802abe02016-08-04 17:48:32 +03003371{
Olli Etuaho856c4972016-08-08 11:38:39 +03003372 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03003373 if (intValue < 1)
3374 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003375 std::stringstream reasonStream;
3376 reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
3377 std::string reason = reasonStream.str();
3378 error(intValueLine, reason.c_str(), intValueString.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003379 }
3380 (*localSize)[index] = intValue;
3381}
3382
Olli Etuaho09b04a22016-12-15 13:30:26 +00003383void TParseContext::parseNumViews(int intValue,
3384 const TSourceLoc &intValueLine,
3385 const std::string &intValueString,
3386 int *numViews)
3387{
3388 // This error is only specified in WebGL, but tightens unspecified behavior in the native
3389 // specification.
3390 if (intValue < 1)
3391 {
3392 error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
3393 }
3394 *numViews = intValue;
3395}
3396
Jamie Madillb98c3a82015-07-23 14:26:04 -04003397TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3398 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003399 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303400 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003401{
Martin Radev802abe02016-08-04 17:48:32 +03003402 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003403
Martin Radev802abe02016-08-04 17:48:32 +03003404 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003405
Martin Radev802abe02016-08-04 17:48:32 +03003406 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003407 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003408 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003409 if (intValue < 0)
3410 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003411 error(intValueLine, "out of range: location must be non-negative",
3412 intValueString.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003413 }
3414 else
3415 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003416 qualifier.location = intValue;
Olli Etuaho87d410c2016-09-05 13:33:26 +03003417 qualifier.locationsSpecified = 1;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003418 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003419 }
Olli Etuaho43364892017-02-13 16:00:12 +00003420 else if (qualifierType == "binding")
3421 {
3422 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3423 if (intValue < 0)
3424 {
3425 error(intValueLine, "out of range: binding must be non-negative",
3426 intValueString.c_str());
3427 }
3428 else
3429 {
3430 qualifier.binding = intValue;
3431 }
3432 }
Martin Radev802abe02016-08-04 17:48:32 +03003433 else if (qualifierType == "local_size_x")
3434 {
3435 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3436 &qualifier.localSize);
3437 }
3438 else if (qualifierType == "local_size_y")
3439 {
3440 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3441 &qualifier.localSize);
3442 }
3443 else if (qualifierType == "local_size_z")
3444 {
3445 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3446 &qualifier.localSize);
3447 }
Olli Etuaho09b04a22016-12-15 13:30:26 +00003448 else if (qualifierType == "num_views" && mMultiviewAvailable &&
3449 (isExtensionEnabled("GL_OVR_multiview") || isExtensionEnabled("GL_OVR_multiview2")) &&
3450 mShaderType == GL_VERTEX_SHADER)
3451 {
3452 parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
3453 }
Martin Radev802abe02016-08-04 17:48:32 +03003454 else
3455 {
3456 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003457 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003458
Jamie Madilla5efff92013-06-06 11:56:47 -04003459 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003460}
3461
Olli Etuaho613b9592016-09-05 12:05:53 +03003462TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
3463{
3464 return new TTypeQualifierBuilder(
3465 new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
3466 mShaderVersion);
3467}
3468
Jamie Madillb98c3a82015-07-23 14:26:04 -04003469TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003470 TLayoutQualifier rightQualifier,
3471 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003472{
Martin Radevc28888b2016-07-22 15:27:42 +03003473 return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003474 mDiagnostics);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003475}
3476
Olli Etuaho4de340a2016-12-16 09:32:03 +00003477TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
3478 const TFieldList *newlyAddedFields,
3479 const TSourceLoc &location)
3480{
3481 for (TField *field : *newlyAddedFields)
3482 {
3483 for (TField *oldField : *processedFields)
3484 {
3485 if (oldField->name() == field->name())
3486 {
3487 error(location, "duplicate field name in structure", field->name().c_str());
3488 }
3489 }
3490 processedFields->push_back(field);
3491 }
3492 return processedFields;
3493}
3494
Martin Radev70866b82016-07-22 15:27:42 +03003495TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
3496 const TTypeQualifierBuilder &typeQualifierBuilder,
3497 TPublicType *typeSpecifier,
3498 TFieldList *fieldList)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003499{
Olli Etuaho77ba4082016-12-16 12:01:18 +00003500 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003501
Martin Radev70866b82016-07-22 15:27:42 +03003502 typeSpecifier->qualifier = typeQualifier.qualifier;
3503 typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03003504 typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03003505 typeSpecifier->invariant = typeQualifier.invariant;
3506 if (typeQualifier.precision != EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +05303507 {
Martin Radev70866b82016-07-22 15:27:42 +03003508 typeSpecifier->precision = typeQualifier.precision;
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003509 }
Martin Radev70866b82016-07-22 15:27:42 +03003510 return addStructDeclaratorList(*typeSpecifier, fieldList);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003511}
3512
Jamie Madillb98c3a82015-07-23 14:26:04 -04003513TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3514 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003515{
Martin Radev4a9cd802016-09-01 16:51:51 +03003516 checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
3517 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03003518
Martin Radev4a9cd802016-09-01 16:51:51 +03003519 checkIsNonVoid(typeSpecifier.getLine(), (*fieldList)[0]->name(), typeSpecifier.getBasicType());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003520
Martin Radev4a9cd802016-09-01 16:51:51 +03003521 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003522
Arun Patole7e7e68d2015-05-22 12:02:25 +05303523 for (unsigned int i = 0; i < fieldList->size(); ++i)
3524 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003525 //
3526 // Careful not to replace already known aspects of type, like array-ness
3527 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303528 TType *type = (*fieldList)[i]->type();
Martin Radev4a9cd802016-09-01 16:51:51 +03003529 type->setBasicType(typeSpecifier.getBasicType());
3530 type->setPrimarySize(typeSpecifier.getPrimarySize());
3531 type->setSecondarySize(typeSpecifier.getSecondarySize());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003532 type->setPrecision(typeSpecifier.precision);
3533 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003534 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
Martin Radev2cc85b32016-08-05 16:22:53 +03003535 type->setMemoryQualifier(typeSpecifier.memoryQualifier);
Martin Radev70866b82016-07-22 15:27:42 +03003536 type->setInvariant(typeSpecifier.invariant);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003537
3538 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303539 if (type->isArray())
3540 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003541 checkIsValidTypeForArray(typeSpecifier.getLine(), typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003542 }
3543 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003544 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Martin Radev4a9cd802016-09-01 16:51:51 +03003545 if (typeSpecifier.getUserDef())
Arun Patole7e7e68d2015-05-22 12:02:25 +05303546 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003547 type->setStruct(typeSpecifier.getUserDef()->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003548 }
3549
Martin Radev4a9cd802016-09-01 16:51:51 +03003550 checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003551 }
3552
Jamie Madill98493dd2013-07-08 14:39:03 -04003553 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003554}
3555
Martin Radev4a9cd802016-09-01 16:51:51 +03003556TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
3557 const TSourceLoc &nameLine,
3558 const TString *structName,
3559 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003560{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303561 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003562 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003563
Jamie Madill9b820842015-02-12 10:40:10 -05003564 // Store a bool in the struct if we're at global scope, to allow us to
3565 // skip the local struct scoping workaround in HLSL.
Jamie Madill9b820842015-02-12 10:40:10 -05003566 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003567
Jamie Madill98493dd2013-07-08 14:39:03 -04003568 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003569 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003570 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303571 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3572 if (!symbolTable.declare(userTypeDef))
3573 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003574 error(nameLine, "redefinition of a struct", structName->c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003575 }
3576 }
3577
3578 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003579 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003580 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003581 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003582 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003583 switch (qualifier)
3584 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003585 case EvqGlobal:
3586 case EvqTemporary:
3587 break;
3588 default:
3589 error(field.line(), "invalid qualifier on struct member",
3590 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003591 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003592 }
Martin Radev70866b82016-07-22 15:27:42 +03003593 if (field.type()->isInvariant())
3594 {
3595 error(field.line(), "invalid qualifier on struct member", "invariant");
3596 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003597 if (IsImage(field.type()->getBasicType()))
3598 {
3599 error(field.line(), "disallowed type in struct", field.type()->getBasicString());
3600 }
3601
Olli Etuaho43364892017-02-13 16:00:12 +00003602 checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
3603
3604 checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);
Martin Radev70866b82016-07-22 15:27:42 +03003605
3606 checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003607 }
3608
Martin Radev4a9cd802016-09-01 16:51:51 +03003609 TTypeSpecifierNonArray typeSpecifierNonArray;
3610 typeSpecifierNonArray.initialize(EbtStruct, structLine);
3611 typeSpecifierNonArray.userDef = structureType;
3612 typeSpecifierNonArray.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003613 exitStructDeclaration();
3614
Martin Radev4a9cd802016-09-01 16:51:51 +03003615 return typeSpecifierNonArray;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003616}
3617
Jamie Madillb98c3a82015-07-23 14:26:04 -04003618TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01003619 TIntermBlock *statementList,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003620 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003621{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003622 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003623 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003624 init->isVector())
3625 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003626 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3627 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003628 return nullptr;
3629 }
3630
Olli Etuahoac5274d2015-02-20 10:19:08 +02003631 if (statementList)
3632 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00003633 if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
Olli Etuahoac5274d2015-02-20 10:19:08 +02003634 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003635 return nullptr;
3636 }
3637 }
3638
Olli Etuahoa3a36662015-02-17 13:46:51 +02003639 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3640 if (node == nullptr)
3641 {
3642 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003643 return nullptr;
3644 }
3645 return node;
3646}
3647
3648TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3649{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003650 if (mSwitchNestingLevel == 0)
3651 {
3652 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003653 return nullptr;
3654 }
3655 if (condition == nullptr)
3656 {
3657 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003658 return nullptr;
3659 }
3660 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003661 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003662 {
3663 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003664 }
3665 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003666 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3667 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3668 // fold in case labels.
3669 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003670 {
3671 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003672 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003673 TIntermCase *node = intermediate.addCase(condition, loc);
3674 if (node == nullptr)
3675 {
3676 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003677 return nullptr;
3678 }
3679 return node;
3680}
3681
3682TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3683{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003684 if (mSwitchNestingLevel == 0)
3685 {
3686 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003687 return nullptr;
3688 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003689 TIntermCase *node = intermediate.addCase(nullptr, loc);
3690 if (node == nullptr)
3691 {
3692 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003693 return nullptr;
3694 }
3695 return node;
3696}
3697
Jamie Madillb98c3a82015-07-23 14:26:04 -04003698TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3699 TIntermTyped *child,
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003700 const TSourceLoc &loc)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003701{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003702 ASSERT(child != nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003703
3704 switch (op)
3705 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003706 case EOpLogicalNot:
3707 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3708 child->isVector())
3709 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003710 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003711 return nullptr;
3712 }
3713 break;
3714 case EOpBitwiseNot:
3715 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3716 child->isMatrix() || child->isArray())
3717 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003718 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003719 return nullptr;
3720 }
3721 break;
3722 case EOpPostIncrement:
3723 case EOpPreIncrement:
3724 case EOpPostDecrement:
3725 case EOpPreDecrement:
3726 case EOpNegative:
3727 case EOpPositive:
3728 if (child->getBasicType() == EbtStruct || child->getBasicType() == EbtBool ||
Martin Radev2cc85b32016-08-05 16:22:53 +03003729 child->isArray() || IsOpaqueType(child->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -04003730 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003731 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003732 return nullptr;
3733 }
3734 // Operators for built-ins are already type checked against their prototype.
3735 default:
3736 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003737 }
3738
Olli Etuahof119a262016-08-19 15:54:22 +03003739 TIntermUnary *node = new TIntermUnary(op, child);
3740 node->setLine(loc);
Olli Etuahof119a262016-08-19 15:54:22 +03003741
Olli Etuaho77ba4082016-12-16 12:01:18 +00003742 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuahof119a262016-08-19 15:54:22 +03003743 if (foldedNode)
3744 return foldedNode;
3745
3746 return node;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003747}
3748
Olli Etuaho09b22472015-02-11 11:47:26 +02003749TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3750{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003751 TIntermTyped *node = createUnaryMath(op, child, loc);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003752 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003753 {
Olli Etuaho09b22472015-02-11 11:47:26 +02003754 return child;
3755 }
3756 return node;
3757}
3758
Jamie Madillb98c3a82015-07-23 14:26:04 -04003759TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3760 TIntermTyped *child,
3761 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003762{
Olli Etuaho856c4972016-08-08 11:38:39 +03003763 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003764 return addUnaryMath(op, child, loc);
3765}
3766
Jamie Madillb98c3a82015-07-23 14:26:04 -04003767bool TParseContext::binaryOpCommonCheck(TOperator op,
3768 TIntermTyped *left,
3769 TIntermTyped *right,
3770 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003771{
jchen10b4cf5652017-05-05 18:51:17 +08003772 // Check opaque types are not allowed to be operands in expressions other than array indexing
3773 // and structure member selection.
3774 if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType()))
3775 {
3776 switch (op)
3777 {
3778 case EOpIndexDirect:
3779 case EOpIndexIndirect:
3780 break;
3781 case EOpIndexDirectStruct:
3782 UNREACHABLE();
3783
3784 default:
3785 error(loc, "Invalid operation for variables with an opaque type",
3786 GetOperatorString(op));
3787 return false;
3788 }
3789 }
jchen10cc2a10e2017-05-03 14:05:12 +08003790
Olli Etuaho244be012016-08-18 15:26:02 +03003791 if (left->getType().getStruct() || right->getType().getStruct())
3792 {
3793 switch (op)
3794 {
3795 case EOpIndexDirectStruct:
3796 ASSERT(left->getType().getStruct());
3797 break;
3798 case EOpEqual:
3799 case EOpNotEqual:
3800 case EOpAssign:
3801 case EOpInitialize:
3802 if (left->getType() != right->getType())
3803 {
3804 return false;
3805 }
3806 break;
3807 default:
3808 error(loc, "Invalid operation for structs", GetOperatorString(op));
3809 return false;
3810 }
3811 }
3812
Olli Etuahod6b14282015-03-17 14:31:35 +02003813 if (left->isArray() || right->isArray())
3814 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003815 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003816 {
3817 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3818 return false;
3819 }
3820
3821 if (left->isArray() != right->isArray())
3822 {
3823 error(loc, "array / non-array mismatch", GetOperatorString(op));
3824 return false;
3825 }
3826
3827 switch (op)
3828 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003829 case EOpEqual:
3830 case EOpNotEqual:
3831 case EOpAssign:
3832 case EOpInitialize:
3833 break;
3834 default:
3835 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3836 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02003837 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03003838 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02003839 if (left->getArraySize() != right->getArraySize())
3840 {
3841 error(loc, "array size mismatch", GetOperatorString(op));
3842 return false;
3843 }
Olli Etuahod6b14282015-03-17 14:31:35 +02003844 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003845
3846 // Check ops which require integer / ivec parameters
3847 bool isBitShift = false;
3848 switch (op)
3849 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003850 case EOpBitShiftLeft:
3851 case EOpBitShiftRight:
3852 case EOpBitShiftLeftAssign:
3853 case EOpBitShiftRightAssign:
3854 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3855 // check that the basic type is an integer type.
3856 isBitShift = true;
3857 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3858 {
3859 return false;
3860 }
3861 break;
3862 case EOpBitwiseAnd:
3863 case EOpBitwiseXor:
3864 case EOpBitwiseOr:
3865 case EOpBitwiseAndAssign:
3866 case EOpBitwiseXorAssign:
3867 case EOpBitwiseOrAssign:
3868 // It is enough to check the type of only one operand, since later it
3869 // is checked that the operand types match.
3870 if (!IsInteger(left->getBasicType()))
3871 {
3872 return false;
3873 }
3874 break;
3875 default:
3876 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003877 }
3878
3879 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3880 // So the basic type should usually match.
3881 if (!isBitShift && left->getBasicType() != right->getBasicType())
3882 {
3883 return false;
3884 }
3885
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003886 // Check that:
3887 // 1. Type sizes match exactly on ops that require that.
3888 // 2. Restrictions for structs that contain arrays or samplers are respected.
3889 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
Jamie Madillb98c3a82015-07-23 14:26:04 -04003890 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003891 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003892 case EOpAssign:
3893 case EOpInitialize:
3894 case EOpEqual:
3895 case EOpNotEqual:
3896 // ESSL 1.00 sections 5.7, 5.8, 5.9
3897 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
3898 {
3899 error(loc, "undefined operation for structs containing arrays",
3900 GetOperatorString(op));
3901 return false;
3902 }
3903 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3904 // we interpret the spec so that this extends to structs containing samplers,
3905 // similarly to ESSL 1.00 spec.
3906 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
3907 left->getType().isStructureContainingSamplers())
3908 {
3909 error(loc, "undefined operation for structs containing samplers",
3910 GetOperatorString(op));
3911 return false;
3912 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003913
Olli Etuahoe1805592017-01-02 16:41:20 +00003914 if ((left->getNominalSize() != right->getNominalSize()) ||
3915 (left->getSecondarySize() != right->getSecondarySize()))
3916 {
3917 error(loc, "dimension mismatch", GetOperatorString(op));
3918 return false;
3919 }
3920 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003921 case EOpLessThan:
3922 case EOpGreaterThan:
3923 case EOpLessThanEqual:
3924 case EOpGreaterThanEqual:
Olli Etuahoe1805592017-01-02 16:41:20 +00003925 if (!left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04003926 {
Olli Etuahoe1805592017-01-02 16:41:20 +00003927 error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003928 return false;
3929 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003930 break;
3931 case EOpAdd:
3932 case EOpSub:
3933 case EOpDiv:
3934 case EOpIMod:
3935 case EOpBitShiftLeft:
3936 case EOpBitShiftRight:
3937 case EOpBitwiseAnd:
3938 case EOpBitwiseXor:
3939 case EOpBitwiseOr:
3940 case EOpAddAssign:
3941 case EOpSubAssign:
3942 case EOpDivAssign:
3943 case EOpIModAssign:
3944 case EOpBitShiftLeftAssign:
3945 case EOpBitShiftRightAssign:
3946 case EOpBitwiseAndAssign:
3947 case EOpBitwiseXorAssign:
3948 case EOpBitwiseOrAssign:
3949 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
3950 {
3951 return false;
3952 }
3953
3954 // Are the sizes compatible?
3955 if (left->getNominalSize() != right->getNominalSize() ||
3956 left->getSecondarySize() != right->getSecondarySize())
3957 {
3958 // If the nominal sizes of operands do not match:
3959 // One of them must be a scalar.
3960 if (!left->isScalar() && !right->isScalar())
3961 return false;
3962
3963 // In the case of compound assignment other than multiply-assign,
3964 // the right side needs to be a scalar. Otherwise a vector/matrix
3965 // would be assigned to a scalar. A scalar can't be shifted by a
3966 // vector either.
3967 if (!right->isScalar() &&
3968 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
3969 return false;
3970 }
3971 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003972 default:
3973 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003974 }
3975
Olli Etuahod6b14282015-03-17 14:31:35 +02003976 return true;
3977}
3978
Olli Etuaho1dded802016-08-18 18:13:13 +03003979bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
3980 const TType &left,
3981 const TType &right)
3982{
3983 switch (op)
3984 {
3985 case EOpMul:
3986 case EOpMulAssign:
3987 return left.getNominalSize() == right.getNominalSize() &&
3988 left.getSecondarySize() == right.getSecondarySize();
3989 case EOpVectorTimesScalar:
3990 return true;
3991 case EOpVectorTimesScalarAssign:
3992 ASSERT(!left.isMatrix() && !right.isMatrix());
3993 return left.isVector() && !right.isVector();
3994 case EOpVectorTimesMatrix:
3995 return left.getNominalSize() == right.getRows();
3996 case EOpVectorTimesMatrixAssign:
3997 ASSERT(!left.isMatrix() && right.isMatrix());
3998 return left.isVector() && left.getNominalSize() == right.getRows() &&
3999 left.getNominalSize() == right.getCols();
4000 case EOpMatrixTimesVector:
4001 return left.getCols() == right.getNominalSize();
4002 case EOpMatrixTimesScalar:
4003 return true;
4004 case EOpMatrixTimesScalarAssign:
4005 ASSERT(left.isMatrix() && !right.isMatrix());
4006 return !right.isVector();
4007 case EOpMatrixTimesMatrix:
4008 return left.getCols() == right.getRows();
4009 case EOpMatrixTimesMatrixAssign:
4010 ASSERT(left.isMatrix() && right.isMatrix());
4011 // We need to check two things:
4012 // 1. The matrix multiplication step is valid.
4013 // 2. The result will have the same number of columns as the lvalue.
4014 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
4015
4016 default:
4017 UNREACHABLE();
4018 return false;
4019 }
4020}
4021
Jamie Madillb98c3a82015-07-23 14:26:04 -04004022TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
4023 TIntermTyped *left,
4024 TIntermTyped *right,
4025 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02004026{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004027 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004028 return nullptr;
4029
Olli Etuahofc1806e2015-03-17 13:03:11 +02004030 switch (op)
4031 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004032 case EOpEqual:
4033 case EOpNotEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04004034 case EOpLessThan:
4035 case EOpGreaterThan:
4036 case EOpLessThanEqual:
4037 case EOpGreaterThanEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04004038 break;
4039 case EOpLogicalOr:
4040 case EOpLogicalXor:
4041 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03004042 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4043 !right->getType().getStruct());
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00004044 if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04004045 {
4046 return nullptr;
4047 }
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00004048 // Basic types matching should have been already checked.
4049 ASSERT(right->getBasicType() == EbtBool);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004050 break;
4051 case EOpAdd:
4052 case EOpSub:
4053 case EOpDiv:
4054 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03004055 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4056 !right->getType().getStruct());
4057 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04004058 {
4059 return nullptr;
4060 }
4061 break;
4062 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03004063 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4064 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004065 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03004066 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04004067 {
4068 return nullptr;
4069 }
4070 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004071 default:
4072 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02004073 }
4074
Olli Etuaho1dded802016-08-18 18:13:13 +03004075 if (op == EOpMul)
4076 {
4077 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
4078 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4079 {
4080 return nullptr;
4081 }
4082 }
4083
Olli Etuaho3fdec912016-08-18 15:08:06 +03004084 TIntermBinary *node = new TIntermBinary(op, left, right);
4085 node->setLine(loc);
4086
Olli Etuaho3fdec912016-08-18 15:08:06 +03004087 // See if we can fold constants.
Olli Etuaho77ba4082016-12-16 12:01:18 +00004088 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuaho3fdec912016-08-18 15:08:06 +03004089 if (foldedNode)
4090 return foldedNode;
4091
4092 return node;
Olli Etuahofc1806e2015-03-17 13:03:11 +02004093}
4094
Jamie Madillb98c3a82015-07-23 14:26:04 -04004095TIntermTyped *TParseContext::addBinaryMath(TOperator op,
4096 TIntermTyped *left,
4097 TIntermTyped *right,
4098 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004099{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004100 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004101 if (node == 0)
4102 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004103 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4104 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02004105 return left;
4106 }
4107 return node;
4108}
4109
Jamie Madillb98c3a82015-07-23 14:26:04 -04004110TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
4111 TIntermTyped *left,
4112 TIntermTyped *right,
4113 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004114{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004115 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004116 if (node == 0)
4117 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004118 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4119 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04004120 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02004121 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004122 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
4123 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004124 }
4125 return node;
4126}
4127
Olli Etuaho13389b62016-10-16 11:48:18 +01004128TIntermBinary *TParseContext::createAssign(TOperator op,
4129 TIntermTyped *left,
4130 TIntermTyped *right,
4131 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004132{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004133 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004134 {
Olli Etuaho1dded802016-08-18 18:13:13 +03004135 if (op == EOpMulAssign)
4136 {
4137 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
4138 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4139 {
4140 return nullptr;
4141 }
4142 }
Olli Etuaho3fdec912016-08-18 15:08:06 +03004143 TIntermBinary *node = new TIntermBinary(op, left, right);
4144 node->setLine(loc);
4145
Olli Etuaho3fdec912016-08-18 15:08:06 +03004146 return node;
Olli Etuahod6b14282015-03-17 14:31:35 +02004147 }
4148 return nullptr;
4149}
4150
Jamie Madillb98c3a82015-07-23 14:26:04 -04004151TIntermTyped *TParseContext::addAssign(TOperator op,
4152 TIntermTyped *left,
4153 TIntermTyped *right,
4154 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004155{
4156 TIntermTyped *node = createAssign(op, left, right, loc);
4157 if (node == nullptr)
4158 {
4159 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02004160 return left;
4161 }
4162 return node;
4163}
4164
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004165TIntermTyped *TParseContext::addComma(TIntermTyped *left,
4166 TIntermTyped *right,
4167 const TSourceLoc &loc)
4168{
Corentin Wallez0d959252016-07-12 17:26:32 -04004169 // WebGL2 section 5.26, the following results in an error:
4170 // "Sequence operator applied to void, arrays, or structs containing arrays"
Jamie Madilld7b1ab52016-12-12 14:42:19 -05004171 if (mShaderSpec == SH_WEBGL2_SPEC &&
4172 (left->isArray() || left->getBasicType() == EbtVoid ||
4173 left->getType().isStructureContainingArrays() || right->isArray() ||
4174 right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
Corentin Wallez0d959252016-07-12 17:26:32 -04004175 {
4176 error(loc,
4177 "sequence operator is not allowed for void, arrays, or structs containing arrays",
4178 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04004179 }
4180
Olli Etuaho4db7ded2016-10-13 12:23:11 +01004181 return TIntermediate::AddComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004182}
4183
Olli Etuaho49300862015-02-20 14:54:49 +02004184TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
4185{
4186 switch (op)
4187 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004188 case EOpContinue:
4189 if (mLoopNestingLevel <= 0)
4190 {
4191 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004192 }
4193 break;
4194 case EOpBreak:
4195 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
4196 {
4197 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004198 }
4199 break;
4200 case EOpReturn:
4201 if (mCurrentFunctionType->getBasicType() != EbtVoid)
4202 {
4203 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004204 }
4205 break;
4206 default:
4207 // No checks for discard
4208 break;
Olli Etuaho49300862015-02-20 14:54:49 +02004209 }
4210 return intermediate.addBranch(op, loc);
4211}
4212
Jamie Madillb98c3a82015-07-23 14:26:04 -04004213TIntermBranch *TParseContext::addBranch(TOperator op,
4214 TIntermTyped *returnValue,
4215 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02004216{
4217 ASSERT(op == EOpReturn);
4218 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004219 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02004220 {
4221 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004222 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004223 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02004224 {
4225 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004226 }
4227 return intermediate.addBranch(op, returnValue, loc);
4228}
4229
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004230void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
4231{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004232 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Olli Etuahobd674552016-10-06 13:28:42 +01004233 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004234 TIntermNode *offset = nullptr;
4235 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuahoec9232b2017-03-27 17:01:37 +03004236 if (name == "texelFetchOffset" || name == "textureLodOffset" ||
4237 name == "textureProjLodOffset" || name == "textureGradOffset" ||
4238 name == "textureProjGradOffset")
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004239 {
4240 offset = arguments->back();
4241 }
Olli Etuahoec9232b2017-03-27 17:01:37 +03004242 else if (name == "textureOffset" || name == "textureProjOffset")
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004243 {
4244 // A bias parameter might follow the offset parameter.
4245 ASSERT(arguments->size() >= 3);
4246 offset = (*arguments)[2];
4247 }
4248 if (offset != nullptr)
4249 {
4250 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
4251 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
4252 {
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004253 error(functionCall->getLine(), "Texture offset must be a constant expression",
Olli Etuahoec9232b2017-03-27 17:01:37 +03004254 name.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004255 }
4256 else
4257 {
4258 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
4259 size_t size = offsetConstantUnion->getType().getObjectSize();
4260 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
4261 for (size_t i = 0u; i < size; ++i)
4262 {
4263 int offsetValue = values[i].getIConst();
4264 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
4265 {
4266 std::stringstream tokenStream;
4267 tokenStream << offsetValue;
4268 std::string token = tokenStream.str();
4269 error(offset->getLine(), "Texture offset value out of valid range",
4270 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004271 }
4272 }
4273 }
4274 }
4275}
4276
Martin Radev2cc85b32016-08-05 16:22:53 +03004277// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
4278void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
4279{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004280 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Martin Radev2cc85b32016-08-05 16:22:53 +03004281 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
4282
4283 if (name.compare(0, 5, "image") == 0)
4284 {
4285 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuaho485eefd2017-02-14 17:40:06 +00004286 TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
Martin Radev2cc85b32016-08-05 16:22:53 +03004287
Olli Etuaho485eefd2017-02-14 17:40:06 +00004288 const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
Martin Radev2cc85b32016-08-05 16:22:53 +03004289
4290 if (name.compare(5, 5, "Store") == 0)
4291 {
4292 if (memoryQualifier.readonly)
4293 {
4294 error(imageNode->getLine(),
4295 "'imageStore' cannot be used with images qualified as 'readonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004296 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03004297 }
4298 }
4299 else if (name.compare(5, 4, "Load") == 0)
4300 {
4301 if (memoryQualifier.writeonly)
4302 {
4303 error(imageNode->getLine(),
4304 "'imageLoad' cannot be used with images qualified as 'writeonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004305 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03004306 }
4307 }
4308 }
4309}
4310
4311// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
4312void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
4313 const TFunction *functionDefinition,
4314 const TIntermAggregate *functionCall)
4315{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004316 ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
Martin Radev2cc85b32016-08-05 16:22:53 +03004317
4318 const TIntermSequence &arguments = *functionCall->getSequence();
4319
4320 ASSERT(functionDefinition->getParamCount() == arguments.size());
4321
4322 for (size_t i = 0; i < arguments.size(); ++i)
4323 {
Olli Etuaho485eefd2017-02-14 17:40:06 +00004324 TIntermTyped *typedArgument = arguments[i]->getAsTyped();
4325 const TType &functionArgumentType = typedArgument->getType();
Martin Radev2cc85b32016-08-05 16:22:53 +03004326 const TType &functionParameterType = *functionDefinition->getParam(i).type;
4327 ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
4328
4329 if (IsImage(functionArgumentType.getBasicType()))
4330 {
4331 const TMemoryQualifier &functionArgumentMemoryQualifier =
4332 functionArgumentType.getMemoryQualifier();
4333 const TMemoryQualifier &functionParameterMemoryQualifier =
4334 functionParameterType.getMemoryQualifier();
4335 if (functionArgumentMemoryQualifier.readonly &&
4336 !functionParameterMemoryQualifier.readonly)
4337 {
4338 error(functionCall->getLine(),
4339 "Function call discards the 'readonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004340 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03004341 }
4342
4343 if (functionArgumentMemoryQualifier.writeonly &&
4344 !functionParameterMemoryQualifier.writeonly)
4345 {
4346 error(functionCall->getLine(),
4347 "Function call discards the 'writeonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004348 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03004349 }
Martin Radev049edfa2016-11-11 14:35:37 +02004350
4351 if (functionArgumentMemoryQualifier.coherent &&
4352 !functionParameterMemoryQualifier.coherent)
4353 {
4354 error(functionCall->getLine(),
4355 "Function call discards the 'coherent' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004356 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02004357 }
4358
4359 if (functionArgumentMemoryQualifier.volatileQualifier &&
4360 !functionParameterMemoryQualifier.volatileQualifier)
4361 {
4362 error(functionCall->getLine(),
4363 "Function call discards the 'volatile' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004364 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02004365 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004366 }
4367 }
4368}
4369
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004370TIntermSequence *TParseContext::createEmptyArgumentsList()
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004371{
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004372 return new TIntermSequence();
Olli Etuaho72d10202017-01-19 15:58:30 +00004373}
4374
4375TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004376 TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00004377 TIntermNode *thisNode,
4378 const TSourceLoc &loc)
4379{
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004380 if (thisNode != nullptr)
4381 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004382 return addMethod(fnCall, arguments, thisNode, loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004383 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004384
4385 TOperator op = fnCall->getBuiltInOp();
4386 if (op != EOpNull)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004387 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004388 return addConstructor(arguments, op, fnCall->getReturnType(), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004389 }
4390 else
4391 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004392 return addNonConstructorFunctionCall(fnCall, arguments, loc);
4393 }
4394}
4395
4396TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
4397 TIntermSequence *arguments,
4398 TIntermNode *thisNode,
4399 const TSourceLoc &loc)
4400{
4401 TConstantUnion *unionArray = new TConstantUnion[1];
4402 int arraySize = 0;
4403 TIntermTyped *typedThis = thisNode->getAsTyped();
4404 // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
4405 // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
4406 // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
4407 // So accessing fnCall->getName() below is safe.
4408 if (fnCall->getName() != "length")
4409 {
4410 error(loc, "invalid method", fnCall->getName().c_str());
4411 }
4412 else if (!arguments->empty())
4413 {
4414 error(loc, "method takes no parameters", "length");
4415 }
4416 else if (typedThis == nullptr || !typedThis->isArray())
4417 {
4418 error(loc, "length can only be called on arrays", "length");
4419 }
4420 else
4421 {
4422 arraySize = typedThis->getArraySize();
4423 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuaho72d10202017-01-19 15:58:30 +00004424 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004425 // This code path can be hit with expressions like these:
4426 // (a = b).length()
4427 // (func()).length()
4428 // (int[3](0, 1, 2)).length()
4429 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
4430 // expression.
4431 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
4432 // spec section 5.9 which allows "An array, vector or matrix expression with the
4433 // length method applied".
4434 error(loc, "length can only be called on array names, not on array expressions",
4435 "length");
Olli Etuaho72d10202017-01-19 15:58:30 +00004436 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004437 }
4438 unionArray->setIConst(arraySize);
4439 return intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
4440}
4441
4442TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
4443 TIntermSequence *arguments,
4444 const TSourceLoc &loc)
4445{
4446 // First find by unmangled name to check whether the function name has been
4447 // hidden by a variable name or struct typename.
4448 // If a function is found, check for one with a matching argument list.
4449 bool builtIn;
4450 const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn);
4451 if (symbol != nullptr && !symbol->isFunction())
4452 {
4453 error(loc, "function name expected", fnCall->getName().c_str());
4454 }
4455 else
4456 {
4457 symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments),
4458 mShaderVersion, &builtIn);
4459 if (symbol == nullptr)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004460 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004461 error(loc, "no matching overloaded function found", fnCall->getName().c_str());
4462 }
4463 else
4464 {
4465 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004466 //
4467 // A declared function.
4468 //
Olli Etuaho383b7912016-08-05 11:22:59 +03004469 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004470 {
Olli Etuaho856c4972016-08-08 11:38:39 +03004471 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004472 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004473 TOperator op = fnCandidate->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004474 if (builtIn && op != EOpNull)
4475 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004476 // A function call mapped to a built-in operation.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004477 if (fnCandidate->getParamCount() == 1)
4478 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004479 // Treat it like a built-in unary operator.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004480 TIntermNode *unaryParamNode = arguments->front();
4481 TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004482 ASSERT(callNode != nullptr);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004483 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004484 }
4485 else
4486 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004487 TIntermAggregate *callNode =
Olli Etuahofe486322017-03-21 09:30:54 +00004488 TIntermAggregate::Create(fnCandidate->getReturnType(), op, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004489 callNode->setLine(loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004490
4491 // Some built-in functions have out parameters too.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004492 functionCallLValueErrorCheck(fnCandidate, callNode);
Arun Patole274f0702015-05-05 13:33:30 +05304493
Olli Etuaho7c3848e2015-11-04 13:19:17 +02004494 // See if we can constant fold a built-in. Note that this may be possible even
4495 // if it is not const-qualified.
Olli Etuahof119a262016-08-19 15:54:22 +03004496 TIntermTyped *foldedNode =
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004497 intermediate.foldAggregateBuiltIn(callNode, mDiagnostics);
Arun Patole274f0702015-05-05 13:33:30 +05304498 if (foldedNode)
4499 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004500 return foldedNode;
Arun Patole274f0702015-05-05 13:33:30 +05304501 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004502 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004503 }
4504 }
4505 else
4506 {
4507 // This is a real function call
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004508 TIntermAggregate *callNode = nullptr;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004509
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004510 // If builtIn == false, the function is user defined - could be an overloaded
4511 // built-in as well.
4512 // if builtIn == true, it's a builtIn function with no op associated with it.
4513 // This needs to happen after the function info including name is set.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004514 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004515 {
Olli Etuahofe486322017-03-21 09:30:54 +00004516 callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004517 checkTextureOffsetConst(callNode);
4518 checkImageMemoryAccessForBuiltinFunctions(callNode);
Martin Radev2cc85b32016-08-05 16:22:53 +03004519 }
4520 else
4521 {
Olli Etuahofe486322017-03-21 09:30:54 +00004522 callNode = TIntermAggregate::CreateFunctionCall(*fnCandidate, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004523 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004524 }
4525
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004526 functionCallLValueErrorCheck(fnCandidate, callNode);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004527
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004528 callNode->setLine(loc);
4529
4530 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004531 }
4532 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004533 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004534
4535 // Error message was already written. Put on a dummy node for error recovery.
4536 return TIntermTyped::CreateZero(TType(EbtFloat, EbpMedium, EvqConst));
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004537}
4538
Jamie Madillb98c3a82015-07-23 14:26:04 -04004539TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004540 TIntermTyped *trueExpression,
4541 TIntermTyped *falseExpression,
Olli Etuaho52901742015-04-15 13:42:45 +03004542 const TSourceLoc &loc)
4543{
Olli Etuaho856c4972016-08-08 11:38:39 +03004544 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03004545
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004546 if (trueExpression->getType() != falseExpression->getType())
Olli Etuaho52901742015-04-15 13:42:45 +03004547 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004548 binaryOpError(loc, ":", trueExpression->getCompleteString(),
4549 falseExpression->getCompleteString());
4550 return falseExpression;
Olli Etuaho52901742015-04-15 13:42:45 +03004551 }
Olli Etuahode318b22016-10-25 16:18:25 +01004552 if (IsOpaqueType(trueExpression->getBasicType()))
4553 {
4554 // ESSL 1.00 section 4.1.7
4555 // ESSL 3.00 section 4.1.7
4556 // Opaque/sampler types are not allowed in most types of expressions, including ternary.
4557 // Note that structs containing opaque types don't need to be checked as structs are
4558 // forbidden below.
4559 error(loc, "ternary operator is not allowed for opaque types", ":");
4560 return falseExpression;
4561 }
4562
Olli Etuahoa2d53032015-04-15 14:14:44 +03004563 // ESSL1 sections 5.2 and 5.7:
4564 // ESSL3 section 5.7:
4565 // Ternary operator is not among the operators allowed for structures/arrays.
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004566 if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
Olli Etuahoa2d53032015-04-15 14:14:44 +03004567 {
4568 error(loc, "ternary operator is not allowed for structures or arrays", ":");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004569 return falseExpression;
Olli Etuahoa2d53032015-04-15 14:14:44 +03004570 }
Corentin Wallez0d959252016-07-12 17:26:32 -04004571 // WebGL2 section 5.26, the following results in an error:
4572 // "Ternary operator applied to void, arrays, or structs containing arrays"
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004573 if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
Corentin Wallez0d959252016-07-12 17:26:32 -04004574 {
4575 error(loc, "ternary operator is not allowed for void", ":");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004576 return falseExpression;
Corentin Wallez0d959252016-07-12 17:26:32 -04004577 }
4578
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004579 return TIntermediate::AddTernarySelection(cond, trueExpression, falseExpression, loc);
Olli Etuaho52901742015-04-15 13:42:45 +03004580}
Olli Etuaho49300862015-02-20 14:54:49 +02004581
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004582//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004583// Parse an array of strings using yyparse.
4584//
4585// Returns 0 for success.
4586//
Jamie Madillb98c3a82015-07-23 14:26:04 -04004587int PaParseStrings(size_t count,
4588 const char *const string[],
4589 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05304590 TParseContext *context)
4591{
Yunchao He4f285442017-04-21 12:15:49 +08004592 if ((count == 0) || (string == nullptr))
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004593 return 1;
4594
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004595 if (glslang_initialize(context))
4596 return 1;
4597
alokp@chromium.org408c45e2012-04-05 15:54:43 +00004598 int error = glslang_scan(count, string, length, context);
4599 if (!error)
4600 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004601
alokp@chromium.org73bc2982012-06-19 18:48:05 +00004602 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00004603
alokp@chromium.org6b495712012-06-29 00:06:58 +00004604 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004605}
Jamie Madill45bcc782016-11-07 13:58:48 -05004606
4607} // namespace sh