blob: 4615bf31dbbe7f00be4e42af5e86ca8e831e7184 [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
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300549// Make sure the argument types are correct for constructing a specific type.
Olli Etuaho856c4972016-08-08 11:38:39 +0300550bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800551 const TIntermSequence *arguments,
Olli Etuaho856c4972016-08-08 11:38:39 +0300552 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000553{
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800554 if (arguments->empty())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530555 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200556 error(line, "constructor does not have any arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300557 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000558 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200559
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300560 for (TIntermNode *arg : *arguments)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530561 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300562 const TIntermTyped *argTyped = arg->getAsTyped();
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200563 ASSERT(argTyped != nullptr);
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300564 if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType()))
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200565 {
jchen10cc2a10e2017-05-03 14:05:12 +0800566 std::string reason("cannot convert a variable with type ");
567 reason += getBasicString(argTyped->getBasicType());
568 error(line, reason.c_str(), "constructor");
Martin Radev2cc85b32016-08-05 16:22:53 +0300569 return false;
570 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200571 if (argTyped->getBasicType() == EbtVoid)
572 {
573 error(line, "cannot convert a void", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300574 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200575 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000576 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000577
Olli Etuaho856c4972016-08-08 11:38:39 +0300578 if (type.isArray())
579 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300580 // The size of an unsized constructor should already have been determined.
581 ASSERT(!type.isUnsizedArray());
582 if (static_cast<size_t>(type.getArraySize()) != arguments->size())
583 {
584 error(line, "array constructor needs one argument per array element", "constructor");
585 return false;
586 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300587 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
588 // the array.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800589 for (TIntermNode *const &argNode : *arguments)
Olli Etuaho856c4972016-08-08 11:38:39 +0300590 {
591 const TType &argType = argNode->getAsTyped()->getType();
Jamie Madill34bf2d92017-02-06 13:40:59 -0500592 if (argType.isArray())
593 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300594 error(line, "constructing from a non-dereferenced array", "constructor");
Jamie Madill34bf2d92017-02-06 13:40:59 -0500595 return false;
596 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300597 if (!argType.sameElementType(type))
598 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000599 error(line, "Array constructor argument has an incorrect type", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300600 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300601 }
602 }
603 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300604 else if (type.getBasicType() == EbtStruct)
Olli Etuaho856c4972016-08-08 11:38:39 +0300605 {
606 const TFieldList &fields = type.getStruct()->fields();
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300607 if (fields.size() != arguments->size())
608 {
609 error(line,
610 "Number of constructor parameters does not match the number of structure fields",
611 "constructor");
612 return false;
613 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300614
615 for (size_t i = 0; i < fields.size(); i++)
616 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800617 if (i >= arguments->size() ||
618 (*arguments)[i]->getAsTyped()->getType() != *fields[i]->type())
Olli Etuaho856c4972016-08-08 11:38:39 +0300619 {
620 error(line, "Structure constructor arguments do not match structure fields",
Olli Etuaho4de340a2016-12-16 09:32:03 +0000621 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300622 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300623 }
624 }
625 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300626 else
627 {
628 // We're constructing a scalar, vector, or matrix.
629
630 // Note: It's okay to have too many components available, but not okay to have unused
631 // arguments. 'full' will go to true when enough args have been seen. If we loop again,
632 // there is an extra argument, so 'overFull' will become true.
633
634 size_t size = 0;
635 bool full = false;
636 bool overFull = false;
637 bool matrixArg = false;
638 for (TIntermNode *arg : *arguments)
639 {
640 const TIntermTyped *argTyped = arg->getAsTyped();
641 ASSERT(argTyped != nullptr);
642
643 if (argTyped->getType().isArray())
644 {
645 error(line, "constructing from a non-dereferenced array", "constructor");
646 return false;
647 }
648 if (argTyped->getType().isMatrix())
649 {
650 matrixArg = true;
651 }
652
653 size += argTyped->getType().getObjectSize();
654 if (full)
655 {
656 overFull = true;
657 }
658 if (type.getBasicType() != EbtStruct && !type.isArray() && size >= type.getObjectSize())
659 {
660 full = true;
661 }
662 }
663
664 if (type.isMatrix() && matrixArg)
665 {
666 if (arguments->size() != 1)
667 {
668 error(line, "constructing matrix from matrix can only take one argument",
669 "constructor");
670 return false;
671 }
672 }
673 else
674 {
675 if (size != 1 && size < type.getObjectSize())
676 {
677 error(line, "not enough data provided for construction", "constructor");
678 return false;
679 }
680 if (overFull)
681 {
682 error(line, "too many arguments", "constructor");
683 return false;
684 }
685 }
686 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300687
Olli Etuaho8a176262016-08-16 14:23:01 +0300688 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000689}
690
Jamie Madillb98c3a82015-07-23 14:26:04 -0400691// This function checks to see if a void variable has been declared and raise an error message for
692// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000693//
694// returns true in case of an error
695//
Olli Etuaho856c4972016-08-08 11:38:39 +0300696bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400697 const TString &identifier,
698 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000699{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300700 if (type == EbtVoid)
701 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000702 error(line, "illegal use of type 'void'", identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300703 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300704 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000705
Olli Etuaho8a176262016-08-16 14:23:01 +0300706 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000707}
708
Jamie Madillb98c3a82015-07-23 14:26:04 -0400709// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300710// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300711void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000712{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530713 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
714 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000715 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530716 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000717}
718
Jamie Madillb98c3a82015-07-23 14:26:04 -0400719// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300720// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300721void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000722{
Martin Radev4a9cd802016-09-01 16:51:51 +0300723 if (pType.getBasicType() != EbtBool || pType.isAggregate())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530724 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000725 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530726 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000727}
728
jchen10cc2a10e2017-05-03 14:05:12 +0800729bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
730 const TTypeSpecifierNonArray &pType,
731 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000732{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530733 if (pType.type == EbtStruct)
734 {
Martin Radev2cc85b32016-08-05 16:22:53 +0300735 if (ContainsSampler(*pType.userDef))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530736 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000737 std::stringstream reasonStream;
738 reasonStream << reason << " (structure contains a sampler)";
739 std::string reasonStr = reasonStream.str();
740 error(line, reasonStr.c_str(), getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300741 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000742 }
jchen10cc2a10e2017-05-03 14:05:12 +0800743 // only samplers need to be checked from structs, since other opaque types can't be struct
744 // members.
Olli Etuaho8a176262016-08-16 14:23:01 +0300745 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530746 }
jchen10cc2a10e2017-05-03 14:05:12 +0800747 else if (IsOpaqueType(pType.type))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530748 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000749 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300750 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000751 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000752
Olli Etuaho8a176262016-08-16 14:23:01 +0300753 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000754}
755
Olli Etuaho856c4972016-08-08 11:38:39 +0300756void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
757 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400758{
759 if (pType.layoutQualifier.location != -1)
760 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400761 error(line, "location must only be specified for a single input or output variable",
762 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400763 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400764}
765
Olli Etuaho856c4972016-08-08 11:38:39 +0300766void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
767 const TLayoutQualifier &layoutQualifier)
768{
769 if (layoutQualifier.location != -1)
770 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000771 const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs";
772 if (mShaderVersion >= 310)
773 {
774 errorMsg =
775 "invalid layout qualifier: only valid on program inputs, outputs, and uniforms";
776 }
777 error(location, errorMsg, "location");
Olli Etuaho856c4972016-08-08 11:38:39 +0300778 }
779}
780
Martin Radev2cc85b32016-08-05 16:22:53 +0300781void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
782 TQualifier qualifier,
783 const TType &type)
784{
Martin Radev2cc85b32016-08-05 16:22:53 +0300785 ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
jchen10cc2a10e2017-05-03 14:05:12 +0800786 if (IsOpaqueType(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530787 {
jchen10cc2a10e2017-05-03 14:05:12 +0800788 error(line, "opaque types cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000789 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000790}
791
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000792// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300793unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000794{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530795 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000796
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200797 // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
798 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
799 // fold as array size.
800 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000801 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000802 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300803 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000804 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000805
Olli Etuaho856c4972016-08-08 11:38:39 +0300806 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400807
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000808 if (constant->getBasicType() == EbtUInt)
809 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300810 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000811 }
812 else
813 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300814 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000815
Olli Etuaho856c4972016-08-08 11:38:39 +0300816 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000817 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400818 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300819 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000820 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400821
Olli Etuaho856c4972016-08-08 11:38:39 +0300822 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -0400823 }
824
Olli Etuaho856c4972016-08-08 11:38:39 +0300825 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -0400826 {
827 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300828 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400829 }
830
831 // The size of arrays is restricted here to prevent issues further down the
832 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
833 // 4096 registers so this should be reasonable even for aggressively optimizable code.
834 const unsigned int sizeLimit = 65536;
835
Olli Etuaho856c4972016-08-08 11:38:39 +0300836 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -0400837 {
838 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300839 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000840 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300841
842 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000843}
844
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000845// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +0300846bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
847 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000848{
Olli Etuaho8a176262016-08-16 14:23:01 +0300849 if ((elementQualifier.qualifier == EvqAttribute) ||
850 (elementQualifier.qualifier == EvqVertexIn) ||
851 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +0300852 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400853 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300854 TType(elementQualifier).getQualifierString());
855 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000856 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000857
Olli Etuaho8a176262016-08-16 14:23:01 +0300858 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000859}
860
Olli Etuaho8a176262016-08-16 14:23:01 +0300861// See if this element type can be formed into an array.
862bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000863{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000864 //
865 // Can the type be an array?
866 //
Olli Etuaho8a176262016-08-16 14:23:01 +0300867 if (elementType.array)
Jamie Madill06145232015-05-13 13:10:01 -0400868 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300869 error(line, "cannot declare arrays of arrays",
870 TType(elementType).getCompleteString().c_str());
871 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000872 }
Olli Etuahocc36b982015-07-10 14:14:18 +0300873 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
874 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
875 // 4.3.4).
Martin Radev4a9cd802016-09-01 16:51:51 +0300876 if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
Olli Etuaho8a176262016-08-16 14:23:01 +0300877 sh::IsVarying(elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +0300878 {
879 error(line, "cannot declare arrays of structs of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300880 TType(elementType).getCompleteString().c_str());
881 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +0300882 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000883
Olli Etuaho8a176262016-08-16 14:23:01 +0300884 return true;
885}
886
887// Check if this qualified element type can be formed into an array.
888bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
889 const TPublicType &elementType)
890{
891 if (checkIsValidTypeForArray(indexLocation, elementType))
892 {
893 return checkIsValidQualifierForArray(indexLocation, elementType);
894 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000895 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000896}
897
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000898// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +0300899void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
900 const TString &identifier,
901 TPublicType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000902{
Olli Etuaho3739d232015-04-08 12:23:44 +0300903 ASSERT(type != nullptr);
904 if (type->qualifier == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000905 {
906 // Make the qualifier make sense.
Olli Etuaho3739d232015-04-08 12:23:44 +0300907 type->qualifier = EvqTemporary;
908
909 // Generate informative error messages for ESSL1.
910 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400911 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000912 {
Arun Patole7e7e68d2015-05-22 12:02:25 +0530913 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400914 "structures containing arrays may not be declared constant since they cannot be "
915 "initialized",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530916 identifier.c_str());
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000917 }
918 else
919 {
920 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
921 }
Olli Etuaho383b7912016-08-05 11:22:59 +0300922 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000923 }
Olli Etuaho376f1b52015-04-13 13:23:41 +0300924 if (type->isUnsizedArray())
925 {
926 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
Olli Etuaho376f1b52015-04-13 13:23:41 +0300927 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000928}
929
Olli Etuaho2935c582015-04-08 14:32:06 +0300930// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000931// and update the symbol table.
932//
Olli Etuaho2935c582015-04-08 14:32:06 +0300933// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000934//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400935bool TParseContext::declareVariable(const TSourceLoc &line,
936 const TString &identifier,
937 const TType &type,
Olli Etuaho2935c582015-04-08 14:32:06 +0300938 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000939{
Olli Etuaho2935c582015-04-08 14:32:06 +0300940 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000941
Olli Etuaho43364892017-02-13 16:00:12 +0000942 checkBindingIsValid(line, type);
943
Olli Etuaho856c4972016-08-08 11:38:39 +0300944 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000945
Olli Etuaho2935c582015-04-08 14:32:06 +0300946 // gl_LastFragData may be redeclared with a new precision qualifier
947 if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
948 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400949 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
950 symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Olli Etuaho856c4972016-08-08 11:38:39 +0300951 if (static_cast<int>(type.getArraySize()) == maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +0300952 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400953 if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +0300954 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300955 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
Olli Etuaho2935c582015-04-08 14:32:06 +0300956 }
957 }
958 else
959 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400960 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
961 identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +0300962 return false;
963 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000964 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000965
Olli Etuaho8a176262016-08-16 14:23:01 +0300966 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +0300967 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000968
Olli Etuaho2935c582015-04-08 14:32:06 +0300969 (*variable) = new TVariable(&identifier, type);
970 if (!symbolTable.declare(*variable))
971 {
972 error(line, "redefinition", identifier.c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -0400973 *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +0300974 return false;
975 }
976
Olli Etuaho8a176262016-08-16 14:23:01 +0300977 if (!checkIsNonVoid(line, identifier, type.getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +0300978 return false;
979
980 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000981}
982
Martin Radev70866b82016-07-22 15:27:42 +0300983void TParseContext::checkIsParameterQualifierValid(
984 const TSourceLoc &line,
985 const TTypeQualifierBuilder &typeQualifierBuilder,
986 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530987{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000988 TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +0300989
990 if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530991 {
Martin Radev2cc85b32016-08-05 16:22:53 +0300992 checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type);
993 }
994
995 if (!IsImage(type->getBasicType()))
996 {
Olli Etuaho43364892017-02-13 16:00:12 +0000997 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line);
Martin Radev2cc85b32016-08-05 16:22:53 +0300998 }
999 else
1000 {
1001 type->setMemoryQualifier(typeQualifier.memoryQualifier);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001002 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001003
Martin Radev70866b82016-07-22 15:27:42 +03001004 type->setQualifier(typeQualifier.qualifier);
1005
1006 if (typeQualifier.precision != EbpUndefined)
1007 {
1008 type->setPrecision(typeQualifier.precision);
1009 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001010}
1011
Olli Etuaho856c4972016-08-08 11:38:39 +03001012bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001013{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001014 const TExtensionBehavior &extBehavior = extensionBehavior();
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001015 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
Arun Patole7e7e68d2015-05-22 12:02:25 +05301016 if (iter == extBehavior.end())
1017 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001018 error(line, "extension is not supported", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001019 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001020 }
zmo@google.comf5450912011-09-09 01:37:19 +00001021 // In GLSL ES, an extension's default behavior is "disable".
Arun Patole7e7e68d2015-05-22 12:02:25 +05301022 if (iter->second == EBhDisable || iter->second == EBhUndefined)
1023 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00001024 // TODO(oetuaho@nvidia.com): This is slightly hacky. Might be better if symbols could be
1025 // associated with more than one extension.
1026 if (extension == "GL_OVR_multiview")
1027 {
1028 return checkCanUseExtension(line, "GL_OVR_multiview2");
1029 }
Olli Etuaho4de340a2016-12-16 09:32:03 +00001030 error(line, "extension is disabled", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001031 return false;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001032 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301033 if (iter->second == EBhWarn)
1034 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001035 warning(line, "extension is being used", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001036 return true;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001037 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001038
Olli Etuaho8a176262016-08-16 14:23:01 +03001039 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001040}
1041
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001042// ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause
1043// compile-time or link-time errors are the same whether or not the declaration is empty".
1044// This function implements all the checks that are done on qualifiers regardless of if the
1045// declaration is empty.
1046void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier,
1047 const sh::TLayoutQualifier &layoutQualifier,
1048 const TSourceLoc &location)
1049{
1050 if (qualifier == EvqShared && !layoutQualifier.isEmpty())
1051 {
1052 error(location, "Shared memory declarations cannot have layout specified", "layout");
1053 }
1054
1055 if (layoutQualifier.matrixPacking != EmpUnspecified)
1056 {
1057 error(location, "layout qualifier only valid for interface blocks",
1058 getMatrixPackingString(layoutQualifier.matrixPacking));
1059 return;
1060 }
1061
1062 if (layoutQualifier.blockStorage != EbsUnspecified)
1063 {
1064 error(location, "layout qualifier only valid for interface blocks",
1065 getBlockStorageString(layoutQualifier.blockStorage));
1066 return;
1067 }
1068
1069 if (qualifier == EvqFragmentOut)
1070 {
1071 if (layoutQualifier.location != -1 && layoutQualifier.yuv == true)
1072 {
1073 error(location, "invalid layout qualifier combination", "yuv");
1074 return;
1075 }
1076 }
1077 else
1078 {
1079 checkYuvIsNotSpecified(location, layoutQualifier.yuv);
1080 }
1081
1082 bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut;
1083 if (mShaderVersion >= 310 && qualifier == EvqUniform)
1084 {
1085 canHaveLocation = true;
1086 // We're not checking whether the uniform location is in range here since that depends on
1087 // the type of the variable.
1088 // The type can only be fully determined for non-empty declarations.
1089 }
1090 if (!canHaveLocation)
1091 {
1092 checkLocationIsNotSpecified(location, layoutQualifier);
1093 }
1094}
1095
Martin Radevb8b01222016-11-20 23:25:53 +02001096void TParseContext::emptyDeclarationErrorCheck(const TPublicType &publicType,
1097 const TSourceLoc &location)
1098{
1099 if (publicType.isUnsizedArray())
1100 {
1101 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1102 // error. It is assumed that this applies to empty declarations as well.
1103 error(location, "empty array declaration needs to specify a size", "");
1104 }
Martin Radevb8b01222016-11-20 23:25:53 +02001105}
1106
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001107// These checks are done for all declarations that are non-empty. They're done for non-empty
1108// declarations starting a declarator list, and declarators that follow an empty declaration.
1109void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
1110 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -04001111{
Olli Etuahofa33d582015-04-09 14:33:12 +03001112 switch (publicType.qualifier)
1113 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001114 case EvqVaryingIn:
1115 case EvqVaryingOut:
1116 case EvqAttribute:
1117 case EvqVertexIn:
1118 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +03001119 case EvqComputeIn:
Martin Radev4a9cd802016-09-01 16:51:51 +03001120 if (publicType.getBasicType() == EbtStruct)
Jamie Madillb98c3a82015-07-23 14:26:04 -04001121 {
1122 error(identifierLocation, "cannot be used with a structure",
1123 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +03001124 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001125 }
Olli Etuahofa33d582015-04-09 14:33:12 +03001126
Jamie Madillb98c3a82015-07-23 14:26:04 -04001127 default:
1128 break;
Olli Etuahofa33d582015-04-09 14:33:12 +03001129 }
jchen10cc2a10e2017-05-03 14:05:12 +08001130 std::string reason(getBasicString(publicType.getBasicType()));
1131 reason += "s must be uniform";
Jamie Madillb98c3a82015-07-23 14:26:04 -04001132 if (publicType.qualifier != EvqUniform &&
jchen10cc2a10e2017-05-03 14:05:12 +08001133 !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str()))
Martin Radev2cc85b32016-08-05 16:22:53 +03001134 {
1135 return;
1136 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001137
Andrei Volykhina5527072017-03-22 16:46:30 +03001138 if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal &&
1139 publicType.qualifier != EvqConst) &&
1140 publicType.getBasicType() == EbtYuvCscStandardEXT)
1141 {
1142 error(identifierLocation, "cannot be used with a yuvCscStandardEXT",
1143 getQualifierString(publicType.qualifier));
1144 return;
1145 }
1146
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001147 if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform)
1148 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001149 // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized.
1150 // But invalid shaders may still reach here with an unsized array declaration.
1151 if (!publicType.isUnsizedArray())
1152 {
1153 TType type(publicType);
1154 checkUniformLocationInRange(identifierLocation, type.getLocationCount(),
1155 publicType.layoutQualifier);
1156 }
1157 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001158
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001159 // check for layout qualifier issues
1160 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
Andrei Volykhina5527072017-03-22 16:46:30 +03001161
Martin Radev2cc85b32016-08-05 16:22:53 +03001162 if (IsImage(publicType.getBasicType()))
1163 {
1164
1165 switch (layoutQualifier.imageInternalFormat)
1166 {
1167 case EiifRGBA32F:
1168 case EiifRGBA16F:
1169 case EiifR32F:
1170 case EiifRGBA8:
1171 case EiifRGBA8_SNORM:
1172 if (!IsFloatImage(publicType.getBasicType()))
1173 {
1174 error(identifierLocation,
1175 "internal image format requires a floating image type",
1176 getBasicString(publicType.getBasicType()));
1177 return;
1178 }
1179 break;
1180 case EiifRGBA32I:
1181 case EiifRGBA16I:
1182 case EiifRGBA8I:
1183 case EiifR32I:
1184 if (!IsIntegerImage(publicType.getBasicType()))
1185 {
1186 error(identifierLocation,
1187 "internal image format requires an integer image type",
1188 getBasicString(publicType.getBasicType()));
1189 return;
1190 }
1191 break;
1192 case EiifRGBA32UI:
1193 case EiifRGBA16UI:
1194 case EiifRGBA8UI:
1195 case EiifR32UI:
1196 if (!IsUnsignedImage(publicType.getBasicType()))
1197 {
1198 error(identifierLocation,
1199 "internal image format requires an unsigned image type",
1200 getBasicString(publicType.getBasicType()));
1201 return;
1202 }
1203 break;
1204 case EiifUnspecified:
1205 error(identifierLocation, "layout qualifier", "No image internal format specified");
1206 return;
1207 default:
1208 error(identifierLocation, "layout qualifier", "unrecognized token");
1209 return;
1210 }
1211
1212 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
1213 switch (layoutQualifier.imageInternalFormat)
1214 {
1215 case EiifR32F:
1216 case EiifR32I:
1217 case EiifR32UI:
1218 break;
1219 default:
1220 if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
1221 {
1222 error(identifierLocation, "layout qualifier",
1223 "Except for images with the r32f, r32i and r32ui format qualifiers, "
1224 "image variables must be qualified readonly and/or writeonly");
1225 return;
1226 }
1227 break;
1228 }
1229 }
1230 else
1231 {
Olli Etuaho43364892017-02-13 16:00:12 +00001232 checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat);
Martin Radev2cc85b32016-08-05 16:22:53 +03001233
Olli Etuaho43364892017-02-13 16:00:12 +00001234 checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
1235 }
1236}
Martin Radev2cc85b32016-08-05 16:22:53 +03001237
Olli Etuaho43364892017-02-13 16:00:12 +00001238void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type)
1239{
1240 TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
1241 int arraySize = type.isArray() ? type.getArraySize() : 1;
1242 if (IsImage(type.getBasicType()))
1243 {
1244 checkImageBindingIsValid(identifierLocation, layoutQualifier.binding, arraySize);
1245 }
1246 else if (IsSampler(type.getBasicType()))
1247 {
1248 checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding, arraySize);
1249 }
1250 else
1251 {
1252 ASSERT(!IsOpaqueType(type.getBasicType()));
1253 checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
Martin Radev2cc85b32016-08-05 16:22:53 +03001254 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001255}
1256
Olli Etuaho856c4972016-08-08 11:38:39 +03001257void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1258 const TString &layoutQualifierName,
1259 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001260{
1261
1262 if (mShaderVersion < versionRequired)
1263 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001264 error(location, "invalid layout qualifier: not supported", layoutQualifierName.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03001265 }
1266}
1267
Olli Etuaho856c4972016-08-08 11:38:39 +03001268bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1269 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001270{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001271 const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
Martin Radev802abe02016-08-04 17:48:32 +03001272 for (size_t i = 0u; i < localSize.size(); ++i)
1273 {
1274 if (localSize[i] != -1)
1275 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001276 error(location,
1277 "invalid layout qualifier: only valid when used with 'in' in a compute shader "
1278 "global layout declaration",
1279 getWorkGroupSizeString(i));
Olli Etuaho8a176262016-08-16 14:23:01 +03001280 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001281 }
1282 }
1283
Olli Etuaho8a176262016-08-16 14:23:01 +03001284 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001285}
1286
Olli Etuaho43364892017-02-13 16:00:12 +00001287void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
Martin Radev2cc85b32016-08-05 16:22:53 +03001288 TLayoutImageInternalFormat internalFormat)
1289{
1290 if (internalFormat != EiifUnspecified)
1291 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001292 error(location, "invalid layout qualifier: only valid when used with images",
1293 getImageInternalFormatString(internalFormat));
Martin Radev2cc85b32016-08-05 16:22:53 +03001294 }
Olli Etuaho43364892017-02-13 16:00:12 +00001295}
1296
1297void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
1298{
1299 if (binding != -1)
1300 {
1301 error(location,
1302 "invalid layout qualifier: only valid when used with opaque types or blocks",
1303 "binding");
1304 }
1305}
1306
1307void TParseContext::checkImageBindingIsValid(const TSourceLoc &location, int binding, int arraySize)
1308{
1309 // Expects arraySize to be 1 when setting binding for only a single variable.
1310 if (binding >= 0 && binding + arraySize > mMaxImageUnits)
1311 {
1312 error(location, "image binding greater than gl_MaxImageUnits", "binding");
1313 }
1314}
1315
1316void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location,
1317 int binding,
1318 int arraySize)
1319{
1320 // Expects arraySize to be 1 when setting binding for only a single variable.
1321 if (binding >= 0 && binding + arraySize > mMaxCombinedTextureImageUnits)
1322 {
1323 error(location, "sampler binding greater than maximum texture units", "binding");
1324 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001325}
1326
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001327void TParseContext::checkUniformLocationInRange(const TSourceLoc &location,
1328 int objectLocationCount,
1329 const TLayoutQualifier &layoutQualifier)
1330{
1331 int loc = layoutQualifier.location;
1332 if (loc >= 0 && loc + objectLocationCount > mMaxUniformLocations)
1333 {
1334 error(location, "Uniform location out of range", "location");
1335 }
1336}
1337
Andrei Volykhina5527072017-03-22 16:46:30 +03001338void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv)
1339{
1340 if (yuv != false)
1341 {
1342 error(location, "invalid layout qualifier: only valid on program outputs", "yuv");
1343 }
1344}
1345
Olli Etuaho383b7912016-08-05 11:22:59 +03001346void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
Olli Etuaho856c4972016-08-08 11:38:39 +03001347 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001348{
1349 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1350 {
1351 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1352 if (qual == EvqOut || qual == EvqInOut)
1353 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001354 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho8a176262016-08-16 14:23:01 +03001355 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001356 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001357 error(argument->getLine(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00001358 "Constant value cannot be passed for 'out' or 'inout' parameters.",
Olli Etuahoec9232b2017-03-27 17:01:37 +03001359 fnCall->getFunctionSymbolInfo()->getName().c_str());
Olli Etuaho383b7912016-08-05 11:22:59 +03001360 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001361 }
1362 }
1363 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001364}
1365
Martin Radev70866b82016-07-22 15:27:42 +03001366void TParseContext::checkInvariantVariableQualifier(bool invariant,
1367 const TQualifier qualifier,
1368 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001369{
Martin Radev70866b82016-07-22 15:27:42 +03001370 if (!invariant)
1371 return;
1372
1373 if (mShaderVersion < 300)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001374 {
Martin Radev70866b82016-07-22 15:27:42 +03001375 // input variables in the fragment shader can be also qualified as invariant
1376 if (!sh::CanBeInvariantESSL1(qualifier))
1377 {
1378 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1379 }
1380 }
1381 else
1382 {
1383 if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
1384 {
1385 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1386 }
Olli Etuaho37ad4742015-04-27 13:18:50 +03001387 }
1388}
1389
Arun Patole7e7e68d2015-05-22 12:02:25 +05301390bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001391{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001392 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001393 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1394 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001395}
1396
Arun Patole7e7e68d2015-05-22 12:02:25 +05301397bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001398{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001399 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001400}
1401
Jamie Madillb98c3a82015-07-23 14:26:04 -04001402void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1403 const char *extName,
1404 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001405{
1406 pp::SourceLocation srcLoc;
1407 srcLoc.file = loc.first_file;
1408 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001409 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001410}
1411
Jamie Madillb98c3a82015-07-23 14:26:04 -04001412void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1413 const char *name,
1414 const char *value,
1415 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001416{
1417 pp::SourceLocation srcLoc;
1418 srcLoc.file = loc.first_file;
1419 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001420 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001421}
1422
Martin Radev4c4c8e72016-08-04 12:25:34 +03001423sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
Martin Radev802abe02016-08-04 17:48:32 +03001424{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001425 sh::WorkGroupSize result;
Martin Radev802abe02016-08-04 17:48:32 +03001426 for (size_t i = 0u; i < result.size(); ++i)
1427 {
1428 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1429 {
1430 result[i] = 1;
1431 }
1432 else
1433 {
1434 result[i] = mComputeShaderLocalSize[i];
1435 }
1436 }
1437 return result;
1438}
1439
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001440/////////////////////////////////////////////////////////////////////////////////
1441//
1442// Non-Errors.
1443//
1444/////////////////////////////////////////////////////////////////////////////////
1445
Jamie Madill5c097022014-08-20 16:38:32 -04001446const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1447 const TString *name,
1448 const TSymbol *symbol)
1449{
Yunchao Hed7297bf2017-04-19 15:27:10 +08001450 const TVariable *variable = nullptr;
Jamie Madill5c097022014-08-20 16:38:32 -04001451
1452 if (!symbol)
1453 {
1454 error(location, "undeclared identifier", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001455 }
1456 else if (!symbol->isVariable())
1457 {
1458 error(location, "variable expected", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001459 }
1460 else
1461 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001462 variable = static_cast<const TVariable *>(symbol);
Jamie Madill5c097022014-08-20 16:38:32 -04001463
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001464 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
Olli Etuaho383b7912016-08-05 11:22:59 +03001465 !variable->getExtension().empty())
Jamie Madill5c097022014-08-20 16:38:32 -04001466 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001467 checkCanUseExtension(location, variable->getExtension());
Jamie Madill5c097022014-08-20 16:38:32 -04001468 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001469
1470 // Reject shaders using both gl_FragData and gl_FragColor
1471 TQualifier qualifier = variable->getType().getQualifier();
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001472 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001473 {
1474 mUsesFragData = true;
1475 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001476 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001477 {
1478 mUsesFragColor = true;
1479 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001480 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1481 {
1482 mUsesSecondaryOutputs = true;
1483 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001484
1485 // This validation is not quite correct - it's only an error to write to
1486 // both FragData and FragColor. For simplicity, and because users shouldn't
1487 // be rewarded for reading from undefined varaibles, return an error
1488 // if they are both referenced, rather than assigned.
1489 if (mUsesFragData && mUsesFragColor)
1490 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001491 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1492 if (mUsesSecondaryOutputs)
1493 {
1494 errorMessage =
1495 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1496 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1497 }
1498 error(location, errorMessage, name->c_str());
Jamie Madill14e95b32015-05-07 10:10:41 -04001499 }
Martin Radevb0883602016-08-04 17:48:58 +03001500
1501 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1502 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1503 qualifier == EvqWorkGroupSize)
1504 {
1505 error(location,
1506 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1507 "gl_WorkGroupSize");
1508 }
Jamie Madill5c097022014-08-20 16:38:32 -04001509 }
1510
1511 if (!variable)
1512 {
1513 TType type(EbtFloat, EbpUndefined);
1514 TVariable *fakeVariable = new TVariable(name, type);
1515 symbolTable.declare(fakeVariable);
1516 variable = fakeVariable;
1517 }
1518
1519 return variable;
1520}
1521
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001522TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1523 const TString *name,
1524 const TSymbol *symbol)
1525{
1526 const TVariable *variable = getNamedVariable(location, name, symbol);
1527
Olli Etuaho09b04a22016-12-15 13:30:26 +00001528 if (variable->getType().getQualifier() == EvqViewIDOVR && IsWebGLBasedSpec(mShaderSpec) &&
1529 mShaderType == GL_FRAGMENT_SHADER && !isExtensionEnabled("GL_OVR_multiview2"))
1530 {
1531 // WEBGL_multiview spec
1532 error(location, "Need to enable OVR_multiview2 to use gl_ViewID_OVR in fragment shader",
1533 "gl_ViewID_OVR");
1534 }
1535
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001536 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001537 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001538 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001539 return intermediate.addConstantUnion(constArray, variable->getType(), location);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001540 }
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001541 else if (variable->getType().getQualifier() == EvqWorkGroupSize &&
1542 mComputeShaderLocalSizeDeclared)
1543 {
1544 // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
1545 // needs to be added to the AST as a constant and not as a symbol.
1546 sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
1547 TConstantUnion *constArray = new TConstantUnion[3];
1548 for (size_t i = 0; i < 3; ++i)
1549 {
1550 constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
1551 }
1552
1553 ASSERT(variable->getType().getBasicType() == EbtUInt);
1554 ASSERT(variable->getType().getObjectSize() == 3);
1555
1556 TType type(variable->getType());
1557 type.setQualifier(EvqConst);
1558 return intermediate.addConstantUnion(constArray, type, location);
1559 }
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001560 else
1561 {
1562 return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
1563 variable->getType(), location);
1564 }
1565}
1566
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001567//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001568// Initializers show up in several places in the grammar. Have one set of
1569// code to handle them here.
1570//
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001571// Returns true on error, false if no error
1572//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001573bool TParseContext::executeInitializer(const TSourceLoc &line,
1574 const TString &identifier,
1575 const TPublicType &pType,
1576 TIntermTyped *initializer,
Olli Etuaho13389b62016-10-16 11:48:18 +01001577 TIntermBinary **initNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001578{
Olli Etuaho13389b62016-10-16 11:48:18 +01001579 ASSERT(initNode != nullptr);
1580 ASSERT(*initNode == nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001581 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001582
Olli Etuaho2935c582015-04-08 14:32:06 +03001583 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001584 if (type.isUnsizedArray())
1585 {
Olli Etuaho02bd82c2016-11-03 10:29:43 +00001586 // We have not checked yet whether the initializer actually is an array or not.
1587 if (initializer->isArray())
1588 {
1589 type.setArraySize(initializer->getArraySize());
1590 }
1591 else
1592 {
1593 // Having a non-array initializer for an unsized array will result in an error later,
1594 // so we don't generate an error message here.
1595 type.setArraySize(1u);
1596 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03001597 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001598 if (!declareVariable(line, identifier, type, &variable))
1599 {
1600 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001601 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001602
Olli Etuahob0c645e2015-05-12 14:25:36 +03001603 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001604 if (symbolTable.atGlobalLevel() &&
1605 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001606 {
1607 // Error message does not completely match behavior with ESSL 1.00, but
1608 // we want to steer developers towards only using constant expressions.
1609 error(line, "global variable initializers must be constant expressions", "=");
1610 return true;
1611 }
1612 if (globalInitWarning)
1613 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001614 warning(
1615 line,
1616 "global variable initializers should be constant expressions "
1617 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1618 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001619 }
1620
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001621 //
1622 // identifier must be of type constant, a global, or a temporary
1623 //
1624 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301625 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1626 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001627 error(line, " cannot initialize this type of qualifier ",
1628 variable->getType().getQualifierString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001629 return true;
1630 }
1631 //
1632 // test for and propagate constant
1633 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001634
Arun Patole7e7e68d2015-05-22 12:02:25 +05301635 if (qualifier == EvqConst)
1636 {
1637 if (qualifier != initializer->getType().getQualifier())
1638 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001639 std::stringstream reasonStream;
1640 reasonStream << "assigning non-constant to '" << variable->getType().getCompleteString()
1641 << "'";
1642 std::string reason = reasonStream.str();
1643 error(line, reason.c_str(), "=");
alokp@chromium.org58e54292010-08-24 21:40:03 +00001644 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001645 return true;
1646 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301647 if (type != initializer->getType())
1648 {
1649 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001650 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001651 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001652 return true;
1653 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001654
1655 // Save the constant folded value to the variable if possible. For example array
1656 // initializers are not folded, since that way copying the array literal to multiple places
1657 // in the shader is avoided.
1658 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1659 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301660 if (initializer->getAsConstantUnion())
1661 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001662 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuaho13389b62016-10-16 11:48:18 +01001663 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001664 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301665 }
1666 else if (initializer->getAsSymbolNode())
1667 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001668 const TSymbol *symbol =
1669 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1670 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001671
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001672 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001673 if (constArray)
1674 {
1675 variable->shareConstPointer(constArray);
Olli Etuaho13389b62016-10-16 11:48:18 +01001676 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001677 return false;
1678 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001679 }
1680 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001681
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001682 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1683 variable->getUniqueId(), variable->getName(), variable->getType(), line);
Olli Etuaho13389b62016-10-16 11:48:18 +01001684 *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1685 if (*initNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001686 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001687 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1688 return true;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001689 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001690
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001691 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001692}
1693
Olli Etuaho0e3aee32016-10-27 12:56:38 +01001694void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
1695{
1696 checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
1697 typeSpecifier->getBasicType());
1698
1699 if (mShaderVersion < 300 && typeSpecifier->array)
1700 {
1701 error(typeSpecifier->getLine(), "not supported", "first-class array");
1702 typeSpecifier->clearArrayness();
1703 }
1704}
1705
Martin Radev70866b82016-07-22 15:27:42 +03001706TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301707 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001708{
Olli Etuaho77ba4082016-12-16 12:01:18 +00001709 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001710
Martin Radev70866b82016-07-22 15:27:42 +03001711 TPublicType returnType = typeSpecifier;
1712 returnType.qualifier = typeQualifier.qualifier;
1713 returnType.invariant = typeQualifier.invariant;
1714 returnType.layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03001715 returnType.memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03001716 returnType.precision = typeSpecifier.precision;
1717
1718 if (typeQualifier.precision != EbpUndefined)
1719 {
1720 returnType.precision = typeQualifier.precision;
1721 }
1722
Martin Radev4a9cd802016-09-01 16:51:51 +03001723 checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
1724 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03001725
Martin Radev4a9cd802016-09-01 16:51:51 +03001726 checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
1727 typeSpecifier.getLine());
Martin Radev70866b82016-07-22 15:27:42 +03001728
Martin Radev4a9cd802016-09-01 16:51:51 +03001729 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001730
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001731 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001732 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001733 if (typeSpecifier.array)
1734 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001735 error(typeSpecifier.getLine(), "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001736 returnType.clearArrayness();
1737 }
1738
Martin Radev70866b82016-07-22 15:27:42 +03001739 if (returnType.qualifier == EvqAttribute &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001740 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001741 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001742 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001743 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001744 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001745
Martin Radev70866b82016-07-22 15:27:42 +03001746 if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001747 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001748 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001749 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001750 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001751 }
1752 }
1753 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001754 {
Martin Radev70866b82016-07-22 15:27:42 +03001755 if (!returnType.layoutQualifier.isEmpty())
Olli Etuahoabb0c382015-07-13 12:01:12 +03001756 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001757 checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03001758 }
Martin Radev70866b82016-07-22 15:27:42 +03001759 if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
1760 returnType.qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001761 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001762 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
1763 typeSpecifier.getLine());
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001764 }
Martin Radev70866b82016-07-22 15:27:42 +03001765 if (returnType.qualifier == EvqComputeIn)
Martin Radev802abe02016-08-04 17:48:32 +03001766 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001767 error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
Martin Radev802abe02016-08-04 17:48:32 +03001768 "in");
Martin Radev802abe02016-08-04 17:48:32 +03001769 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001770 }
1771
1772 return returnType;
1773}
1774
Olli Etuaho856c4972016-08-08 11:38:39 +03001775void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1776 const TPublicType &type,
1777 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03001778{
1779 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
Martin Radev4a9cd802016-09-01 16:51:51 +03001780 if (type.getBasicType() == EbtBool)
Olli Etuahocc36b982015-07-10 14:14:18 +03001781 {
1782 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001783 }
1784
1785 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1786 switch (qualifier)
1787 {
1788 case EvqVertexIn:
1789 // ESSL 3.00 section 4.3.4
1790 if (type.array)
1791 {
1792 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001793 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001794 // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03001795 return;
1796 case EvqFragmentOut:
1797 // ESSL 3.00 section 4.3.6
Martin Radev4a9cd802016-09-01 16:51:51 +03001798 if (type.typeSpecifierNonArray.isMatrix())
Olli Etuahocc36b982015-07-10 14:14:18 +03001799 {
1800 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001801 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001802 // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03001803 return;
1804 default:
1805 break;
1806 }
1807
1808 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1809 // restrictions.
1810 bool typeContainsIntegers =
Martin Radev4a9cd802016-09-01 16:51:51 +03001811 (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
1812 type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
Olli Etuahocc36b982015-07-10 14:14:18 +03001813 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1814 {
1815 error(qualifierLocation, "must use 'flat' interpolation here",
1816 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001817 }
1818
Martin Radev4a9cd802016-09-01 16:51:51 +03001819 if (type.getBasicType() == EbtStruct)
Olli Etuahocc36b982015-07-10 14:14:18 +03001820 {
1821 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1822 // These restrictions are only implied by the ESSL 3.00 spec, but
1823 // the ESSL 3.10 spec lists these restrictions explicitly.
1824 if (type.array)
1825 {
1826 error(qualifierLocation, "cannot be an array of structures",
1827 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001828 }
1829 if (type.isStructureContainingArrays())
1830 {
1831 error(qualifierLocation, "cannot be a structure containing an array",
1832 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001833 }
1834 if (type.isStructureContainingType(EbtStruct))
1835 {
1836 error(qualifierLocation, "cannot be a structure containing a structure",
1837 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001838 }
1839 if (type.isStructureContainingType(EbtBool))
1840 {
1841 error(qualifierLocation, "cannot be a structure containing a bool",
1842 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001843 }
1844 }
1845}
1846
Martin Radev2cc85b32016-08-05 16:22:53 +03001847void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
1848{
1849 if (qualifier.getType() == QtStorage)
1850 {
1851 const TStorageQualifierWrapper &storageQualifier =
1852 static_cast<const TStorageQualifierWrapper &>(qualifier);
1853 if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
1854 !symbolTable.atGlobalLevel())
1855 {
1856 error(storageQualifier.getLine(),
1857 "Local variables can only use the const storage qualifier.",
1858 storageQualifier.getQualifierString().c_str());
1859 }
1860 }
1861}
1862
Olli Etuaho43364892017-02-13 16:00:12 +00001863void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
Martin Radev2cc85b32016-08-05 16:22:53 +03001864 const TSourceLoc &location)
1865{
1866 if (memoryQualifier.readonly)
1867 {
1868 error(location, "Only allowed with images.", "readonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03001869 }
1870 if (memoryQualifier.writeonly)
1871 {
1872 error(location, "Only allowed with images.", "writeonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03001873 }
Martin Radev049edfa2016-11-11 14:35:37 +02001874 if (memoryQualifier.coherent)
1875 {
1876 error(location, "Only allowed with images.", "coherent");
Martin Radev049edfa2016-11-11 14:35:37 +02001877 }
1878 if (memoryQualifier.restrictQualifier)
1879 {
1880 error(location, "Only allowed with images.", "restrict");
Martin Radev049edfa2016-11-11 14:35:37 +02001881 }
1882 if (memoryQualifier.volatileQualifier)
1883 {
1884 error(location, "Only allowed with images.", "volatile");
Martin Radev049edfa2016-11-11 14:35:37 +02001885 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001886}
1887
Olli Etuaho13389b62016-10-16 11:48:18 +01001888TIntermDeclaration *TParseContext::parseSingleDeclaration(
1889 TPublicType &publicType,
1890 const TSourceLoc &identifierOrTypeLocation,
1891 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04001892{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001893 TType type(publicType);
1894 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
1895 mDirectiveHandler.pragma().stdgl.invariantAll)
1896 {
1897 TQualifier qualifier = type.getQualifier();
1898
1899 // The directive handler has already taken care of rejecting invalid uses of this pragma
1900 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
1901 // affected variable declarations:
1902 //
1903 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
1904 // elsewhere, in TranslatorGLSL.)
1905 //
1906 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
1907 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
1908 // the way this is currently implemented we have to enable this compiler option before
1909 // parsing the shader and determining the shading language version it uses. If this were
1910 // implemented as a post-pass, the workaround could be more targeted.
1911 //
1912 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
1913 // the specification, but there are desktop OpenGL drivers that expect that this is the
1914 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
1915 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
1916 {
1917 type.setInvariant(true);
1918 }
1919 }
1920
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001921 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
1922 identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001923
Olli Etuahobab4c082015-04-24 16:38:49 +03001924 bool emptyDeclaration = (identifier == "");
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001925 mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration;
Olli Etuahofa33d582015-04-09 14:33:12 +03001926
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001927 TIntermSymbol *symbol = nullptr;
Olli Etuahobab4c082015-04-24 16:38:49 +03001928 if (emptyDeclaration)
1929 {
Martin Radevb8b01222016-11-20 23:25:53 +02001930 emptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001931 // In most cases we don't need to create a symbol node for an empty declaration.
1932 // But if the empty declaration is declaring a struct type, the symbol node will store that.
1933 if (type.getBasicType() == EbtStruct)
1934 {
1935 symbol = intermediate.addSymbol(0, "", type, identifierOrTypeLocation);
1936 }
Olli Etuahobab4c082015-04-24 16:38:49 +03001937 }
1938 else
Jamie Madill60ed9812013-06-06 11:56:46 -04001939 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001940 nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001941
Olli Etuaho856c4972016-08-08 11:38:39 +03001942 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001943
Olli Etuaho2935c582015-04-08 14:32:06 +03001944 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001945 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001946
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001947 if (variable)
Olli Etuaho13389b62016-10-16 11:48:18 +01001948 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001949 symbol = intermediate.addSymbol(variable->getUniqueId(), identifier, type,
1950 identifierOrTypeLocation);
Olli Etuaho13389b62016-10-16 11:48:18 +01001951 }
Jamie Madill60ed9812013-06-06 11:56:46 -04001952 }
1953
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001954 TIntermDeclaration *declaration = new TIntermDeclaration();
1955 declaration->setLine(identifierOrTypeLocation);
1956 if (symbol)
1957 {
1958 declaration->appendDeclarator(symbol);
1959 }
Olli Etuaho13389b62016-10-16 11:48:18 +01001960 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04001961}
1962
Olli Etuaho13389b62016-10-16 11:48:18 +01001963TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1964 const TSourceLoc &identifierLocation,
1965 const TString &identifier,
1966 const TSourceLoc &indexLocation,
1967 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04001968{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001969 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03001970
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001971 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
1972 identifierLocation);
1973
1974 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001975
Olli Etuaho856c4972016-08-08 11:38:39 +03001976 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001977
Olli Etuaho8a176262016-08-16 14:23:01 +03001978 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001979
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001980 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001981
Olli Etuaho856c4972016-08-08 11:38:39 +03001982 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001983 // Make the type an array even if size check failed.
1984 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1985 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04001986
Olli Etuaho2935c582015-04-08 14:32:06 +03001987 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001988 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001989
Olli Etuaho13389b62016-10-16 11:48:18 +01001990 TIntermDeclaration *declaration = new TIntermDeclaration();
1991 declaration->setLine(identifierLocation);
1992
Olli Etuahoe7847b02015-03-16 11:56:12 +02001993 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001994 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01001995 {
Jamie Madill60ed9812013-06-06 11:56:46 -04001996 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01001997 declaration->appendDeclarator(symbol);
1998 }
Jamie Madill60ed9812013-06-06 11:56:46 -04001999
Olli Etuaho13389b62016-10-16 11:48:18 +01002000 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002001}
2002
Olli Etuaho13389b62016-10-16 11:48:18 +01002003TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
2004 const TSourceLoc &identifierLocation,
2005 const TString &identifier,
2006 const TSourceLoc &initLocation,
2007 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04002008{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002009 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002010
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002011 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2012 identifierLocation);
2013
2014 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002015
Olli Etuaho13389b62016-10-16 11:48:18 +01002016 TIntermDeclaration *declaration = new TIntermDeclaration();
2017 declaration->setLine(identifierLocation);
2018
2019 TIntermBinary *initNode = nullptr;
2020 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04002021 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002022 if (initNode)
2023 {
2024 declaration->appendDeclarator(initNode);
2025 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002026 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002027 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002028}
2029
Olli Etuaho13389b62016-10-16 11:48:18 +01002030TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
Jamie Madillb98c3a82015-07-23 14:26:04 -04002031 TPublicType &publicType,
2032 const TSourceLoc &identifierLocation,
2033 const TString &identifier,
2034 const TSourceLoc &indexLocation,
2035 TIntermTyped *indexExpression,
2036 const TSourceLoc &initLocation,
2037 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002038{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002039 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002040
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002041 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2042 identifierLocation);
2043
2044 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002045
Olli Etuaho8a176262016-08-16 14:23:01 +03002046 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002047
2048 TPublicType arrayType(publicType);
2049
Olli Etuaho856c4972016-08-08 11:38:39 +03002050 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002051 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2052 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002053 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002054 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002055 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002056 }
2057 // Make the type an array even if size check failed.
2058 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2059 arrayType.setArraySize(size);
2060
Olli Etuaho13389b62016-10-16 11:48:18 +01002061 TIntermDeclaration *declaration = new TIntermDeclaration();
2062 declaration->setLine(identifierLocation);
2063
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002064 // initNode will correspond to the whole of "type b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002065 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002066 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2067 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002068 if (initNode)
2069 {
2070 declaration->appendDeclarator(initNode);
2071 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002072 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002073
2074 return declaration;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002075}
2076
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002077TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
Martin Radev70866b82016-07-22 15:27:42 +03002078 const TTypeQualifierBuilder &typeQualifierBuilder,
2079 const TSourceLoc &identifierLoc,
2080 const TString *identifier,
2081 const TSymbol *symbol)
Jamie Madill47e3ec02014-08-20 16:38:33 -04002082{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002083 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002084
Martin Radev70866b82016-07-22 15:27:42 +03002085 if (!typeQualifier.invariant)
2086 {
2087 error(identifierLoc, "Expected invariant", identifier->c_str());
2088 return nullptr;
2089 }
2090 if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
2091 {
2092 return nullptr;
2093 }
Jamie Madill47e3ec02014-08-20 16:38:33 -04002094 if (!symbol)
2095 {
2096 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002097 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04002098 }
Martin Radev70866b82016-07-22 15:27:42 +03002099 if (!IsQualifierUnspecified(typeQualifier.qualifier))
Jamie Madill47e3ec02014-08-20 16:38:33 -04002100 {
Martin Radev70866b82016-07-22 15:27:42 +03002101 error(identifierLoc, "invariant declaration specifies qualifier",
2102 getQualifierString(typeQualifier.qualifier));
Jamie Madill47e3ec02014-08-20 16:38:33 -04002103 }
Martin Radev70866b82016-07-22 15:27:42 +03002104 if (typeQualifier.precision != EbpUndefined)
2105 {
2106 error(identifierLoc, "invariant declaration specifies precision",
2107 getPrecisionString(typeQualifier.precision));
2108 }
2109 if (!typeQualifier.layoutQualifier.isEmpty())
2110 {
2111 error(identifierLoc, "invariant declaration specifies layout", "'layout'");
2112 }
2113
2114 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
2115 ASSERT(variable);
2116 const TType &type = variable->getType();
2117
2118 checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
2119 typeQualifier.line);
Olli Etuaho43364892017-02-13 16:00:12 +00002120 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev70866b82016-07-22 15:27:42 +03002121
2122 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
2123
2124 TIntermSymbol *intermSymbol =
2125 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
2126
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002127 return new TIntermInvariantDeclaration(intermSymbol, identifierLoc);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002128}
2129
Olli Etuaho13389b62016-10-16 11:48:18 +01002130void TParseContext::parseDeclarator(TPublicType &publicType,
2131 const TSourceLoc &identifierLocation,
2132 const TString &identifier,
2133 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002134{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002135 // If the declaration starting this declarator list was empty (example: int,), some checks were
2136 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002137 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002138 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002139 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2140 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002141 }
2142
Olli Etuaho856c4972016-08-08 11:38:39 +03002143 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002144
Olli Etuaho856c4972016-08-08 11:38:39 +03002145 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002146
Olli Etuaho2935c582015-04-08 14:32:06 +03002147 TVariable *variable = nullptr;
Olli Etuaho43364892017-02-13 16:00:12 +00002148 TType type(publicType);
2149 declareVariable(identifierLocation, identifier, type, &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002150
Olli Etuaho43364892017-02-13 16:00:12 +00002151 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002152 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002153 {
Jamie Madill502d66f2013-06-20 11:55:52 -04002154 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002155 declarationOut->appendDeclarator(symbol);
2156 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002157}
2158
Olli Etuaho13389b62016-10-16 11:48:18 +01002159void TParseContext::parseArrayDeclarator(TPublicType &publicType,
2160 const TSourceLoc &identifierLocation,
2161 const TString &identifier,
2162 const TSourceLoc &arrayLocation,
2163 TIntermTyped *indexExpression,
2164 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002165{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002166 // If the declaration starting this declarator list was empty (example: int,), some checks were
2167 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002168 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002169 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002170 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2171 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002172 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002173
Olli Etuaho856c4972016-08-08 11:38:39 +03002174 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002175
Olli Etuaho856c4972016-08-08 11:38:39 +03002176 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002177
Olli Etuaho8a176262016-08-16 14:23:01 +03002178 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04002179 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002180 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03002181 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03002182 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002183
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002184 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002185 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04002186
Jamie Madillb98c3a82015-07-23 14:26:04 -04002187 TIntermSymbol *symbol =
2188 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002189 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002190 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002191
Olli Etuaho13389b62016-10-16 11:48:18 +01002192 declarationOut->appendDeclarator(symbol);
Jamie Madill502d66f2013-06-20 11:55:52 -04002193 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002194}
2195
Olli Etuaho13389b62016-10-16 11:48:18 +01002196void TParseContext::parseInitDeclarator(const TPublicType &publicType,
2197 const TSourceLoc &identifierLocation,
2198 const TString &identifier,
2199 const TSourceLoc &initLocation,
2200 TIntermTyped *initializer,
2201 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002202{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002203 // If the declaration starting this declarator list was empty (example: int,), some checks were
2204 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002205 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002206 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002207 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2208 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002209 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002210
Olli Etuaho856c4972016-08-08 11:38:39 +03002211 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002212
Olli Etuaho13389b62016-10-16 11:48:18 +01002213 TIntermBinary *initNode = nullptr;
2214 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04002215 {
2216 //
2217 // build the intermediate representation
2218 //
Olli Etuaho13389b62016-10-16 11:48:18 +01002219 if (initNode)
Jamie Madill502d66f2013-06-20 11:55:52 -04002220 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002221 declarationOut->appendDeclarator(initNode);
Jamie Madill502d66f2013-06-20 11:55:52 -04002222 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002223 }
2224}
2225
Olli Etuaho13389b62016-10-16 11:48:18 +01002226void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
2227 const TSourceLoc &identifierLocation,
2228 const TString &identifier,
2229 const TSourceLoc &indexLocation,
2230 TIntermTyped *indexExpression,
2231 const TSourceLoc &initLocation,
2232 TIntermTyped *initializer,
2233 TIntermDeclaration *declarationOut)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002234{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002235 // If the declaration starting this declarator list was empty (example: int,), some checks were
2236 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002237 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002238 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002239 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2240 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002241 }
2242
Olli Etuaho856c4972016-08-08 11:38:39 +03002243 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002244
Olli Etuaho8a176262016-08-16 14:23:01 +03002245 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002246
2247 TPublicType arrayType(publicType);
2248
Olli Etuaho856c4972016-08-08 11:38:39 +03002249 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002250 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2251 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002252 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002253 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002254 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002255 }
2256 // Make the type an array even if size check failed.
2257 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2258 arrayType.setArraySize(size);
2259
2260 // initNode will correspond to the whole of "b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002261 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002262 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2263 {
2264 if (initNode)
2265 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002266 declarationOut->appendDeclarator(initNode);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002267 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002268 }
2269}
2270
Martin Radev70866b82016-07-22 15:27:42 +03002271void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
Jamie Madilla295edf2013-06-06 11:56:48 -04002272{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002273 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madilla295edf2013-06-06 11:56:48 -04002274 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04002275
Martin Radev70866b82016-07-22 15:27:42 +03002276 checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
2277 typeQualifier.line);
2278
Jamie Madillc2128ff2016-07-04 10:26:17 -04002279 // It should never be the case, but some strange parser errors can send us here.
2280 if (layoutQualifier.isEmpty())
2281 {
2282 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04002283 return;
2284 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002285
Martin Radev802abe02016-08-04 17:48:32 +03002286 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04002287 {
Olli Etuaho43364892017-02-13 16:00:12 +00002288 error(typeQualifier.line, "invalid layout qualifier combination", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04002289 return;
2290 }
2291
Olli Etuaho43364892017-02-13 16:00:12 +00002292 checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);
2293
2294 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev2cc85b32016-08-05 16:22:53 +03002295
2296 checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
2297
Andrei Volykhina5527072017-03-22 16:46:30 +03002298 checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv);
2299
Martin Radev802abe02016-08-04 17:48:32 +03002300 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04002301 {
Martin Radev802abe02016-08-04 17:48:32 +03002302 if (mComputeShaderLocalSizeDeclared &&
2303 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
2304 {
2305 error(typeQualifier.line, "Work group size does not match the previous declaration",
2306 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002307 return;
2308 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002309
Martin Radev802abe02016-08-04 17:48:32 +03002310 if (mShaderVersion < 310)
2311 {
2312 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002313 return;
2314 }
Jamie Madill099c0f32013-06-20 11:55:52 -04002315
Martin Radev4c4c8e72016-08-04 12:25:34 +03002316 if (!layoutQualifier.localSize.isAnyValueSet())
Martin Radev802abe02016-08-04 17:48:32 +03002317 {
2318 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002319 return;
2320 }
2321
2322 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
2323 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
2324
2325 const TConstantUnion *maxComputeWorkGroupSizeData =
2326 maxComputeWorkGroupSize->getConstPointer();
2327
2328 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
2329 {
2330 if (layoutQualifier.localSize[i] != -1)
2331 {
2332 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
2333 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
2334 if (mComputeShaderLocalSize[i] < 1 ||
2335 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
2336 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002337 std::stringstream reasonStream;
2338 reasonStream << "invalid value: Value must be at least 1 and no greater than "
2339 << maxComputeWorkGroupSizeValue;
2340 const std::string &reason = reasonStream.str();
Martin Radev802abe02016-08-04 17:48:32 +03002341
Olli Etuaho4de340a2016-12-16 09:32:03 +00002342 error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03002343 return;
2344 }
2345 }
2346 }
2347
2348 mComputeShaderLocalSizeDeclared = true;
2349 }
Olli Etuaho09b04a22016-12-15 13:30:26 +00002350 else if (mMultiviewAvailable &&
2351 (isExtensionEnabled("GL_OVR_multiview") || isExtensionEnabled("GL_OVR_multiview2")) &&
2352 typeQualifier.qualifier == EvqVertexIn)
2353 {
2354 // This error is only specified in WebGL, but tightens unspecified behavior in the native
2355 // specification.
2356 if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
2357 {
2358 error(typeQualifier.line, "Number of views does not match the previous declaration",
2359 "layout");
2360 return;
2361 }
2362
2363 if (layoutQualifier.numViews == -1)
2364 {
2365 error(typeQualifier.line, "No num_views specified", "layout");
2366 return;
2367 }
2368
2369 if (layoutQualifier.numViews > mMaxNumViews)
2370 {
2371 error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
2372 "layout");
2373 return;
2374 }
2375
2376 mNumViews = layoutQualifier.numViews;
2377 }
Martin Radev802abe02016-08-04 17:48:32 +03002378 else
Jamie Madill1566ef72013-06-20 11:55:54 -04002379 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00002380 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03002381 {
Martin Radev802abe02016-08-04 17:48:32 +03002382 return;
2383 }
2384
2385 if (typeQualifier.qualifier != EvqUniform)
2386 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002387 error(typeQualifier.line, "invalid qualifier: global layout must be uniform",
2388 getQualifierString(typeQualifier.qualifier));
Martin Radev802abe02016-08-04 17:48:32 +03002389 return;
2390 }
2391
2392 if (mShaderVersion < 300)
2393 {
2394 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
2395 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002396 return;
2397 }
2398
Olli Etuaho09b04a22016-12-15 13:30:26 +00002399 checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002400
2401 if (layoutQualifier.matrixPacking != EmpUnspecified)
2402 {
2403 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
2404 }
2405
2406 if (layoutQualifier.blockStorage != EbsUnspecified)
2407 {
2408 mDefaultBlockStorage = layoutQualifier.blockStorage;
2409 }
Jamie Madill1566ef72013-06-20 11:55:54 -04002410 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002411}
2412
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002413TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
2414 const TFunction &function,
2415 const TSourceLoc &location,
2416 bool insertParametersToSymbolTable)
2417{
Olli Etuahofe486322017-03-21 09:30:54 +00002418 TIntermFunctionPrototype *prototype =
2419 new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function));
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002420 // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
2421 // point to the data that already exists in the symbol table.
2422 prototype->getFunctionSymbolInfo()->setFromFunction(function);
2423 prototype->setLine(location);
2424
2425 for (size_t i = 0; i < function.getParamCount(); i++)
2426 {
2427 const TConstParameter &param = function.getParam(i);
2428
2429 // If the parameter has no name, it's not an error, just don't add it to symbol table (could
2430 // be used for unused args).
2431 if (param.name != nullptr)
2432 {
2433 TVariable *variable = new TVariable(param.name, *param.type);
2434
2435 // Insert the parameter in the symbol table.
2436 if (insertParametersToSymbolTable && !symbolTable.declare(variable))
2437 {
2438 error(location, "redefinition", variable->getName().c_str());
2439 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2440 continue;
2441 }
2442 TIntermSymbol *symbol = intermediate.addSymbol(
2443 variable->getUniqueId(), variable->getName(), variable->getType(), location);
2444 prototype->appendParameter(symbol);
2445 }
2446 else
2447 {
2448 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2449 }
2450 }
2451 return prototype;
2452}
2453
Olli Etuaho16c745a2017-01-16 17:02:27 +00002454TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
2455 const TFunction &parsedFunction,
2456 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002457{
Olli Etuaho476197f2016-10-11 13:59:08 +01002458 // Note: function found from the symbol table could be the same as parsedFunction if this is the
2459 // first declaration. Either way the instance in the symbol table is used to track whether the
2460 // function is declared multiple times.
2461 TFunction *function = static_cast<TFunction *>(
2462 symbolTable.find(parsedFunction.getMangledName(), getShaderVersion()));
2463 if (function->hasPrototypeDeclaration() && mShaderVersion == 100)
Olli Etuaho5d653182016-01-04 14:43:28 +02002464 {
2465 // ESSL 1.00.17 section 4.2.7.
2466 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
2467 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02002468 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002469 function->setHasPrototypeDeclaration();
Olli Etuaho5d653182016-01-04 14:43:28 +02002470
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002471 TIntermFunctionPrototype *prototype =
2472 createPrototypeNodeFromFunction(*function, location, false);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002473
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002474 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002475
2476 if (!symbolTable.atGlobalLevel())
2477 {
2478 // ESSL 3.00.4 section 4.2.4.
2479 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002480 }
2481
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002482 return prototype;
2483}
2484
Olli Etuaho336b1472016-10-05 16:37:55 +01002485TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002486 TIntermFunctionPrototype *functionPrototype,
Olli Etuaho336b1472016-10-05 16:37:55 +01002487 TIntermBlock *functionBody,
2488 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002489{
Olli Etuahof51fdd22016-10-03 10:03:40 +01002490 // Check that non-void functions have at least one return statement.
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002491 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2492 {
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002493 error(location, "function does not return a value:",
2494 functionPrototype->getFunctionSymbolInfo()->getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002495 }
2496
Olli Etuahof51fdd22016-10-03 10:03:40 +01002497 if (functionBody == nullptr)
2498 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01002499 functionBody = new TIntermBlock();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002500 functionBody->setLine(location);
2501 }
Olli Etuaho336b1472016-10-05 16:37:55 +01002502 TIntermFunctionDefinition *functionNode =
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002503 new TIntermFunctionDefinition(functionPrototype, functionBody);
Olli Etuaho336b1472016-10-05 16:37:55 +01002504 functionNode->setLine(location);
Olli Etuahof51fdd22016-10-03 10:03:40 +01002505
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002506 symbolTable.pop();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002507 return functionNode;
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002508}
2509
Olli Etuaho476197f2016-10-11 13:59:08 +01002510void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
2511 TFunction **function,
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002512 TIntermFunctionPrototype **prototypeOut)
Jamie Madill185fb402015-06-12 15:48:48 -04002513{
Olli Etuaho476197f2016-10-11 13:59:08 +01002514 ASSERT(function);
2515 ASSERT(*function);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002516 const TSymbol *builtIn =
Olli Etuaho476197f2016-10-11 13:59:08 +01002517 symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002518
2519 if (builtIn)
2520 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002521 error(location, "built-in functions cannot be redefined", (*function)->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002522 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002523 else
Jamie Madill185fb402015-06-12 15:48:48 -04002524 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002525 TFunction *prevDec = static_cast<TFunction *>(
2526 symbolTable.find((*function)->getMangledName(), getShaderVersion()));
2527
2528 // Note: 'prevDec' could be 'function' if this is the first time we've seen function as it
2529 // would have just been put in the symbol table. Otherwise, we're looking up an earlier
2530 // occurance.
2531 if (*function != prevDec)
2532 {
2533 // Swap the parameters of the previous declaration to the parameters of the function
2534 // definition (parameter names may differ).
2535 prevDec->swapParameters(**function);
2536
2537 // The function definition will share the same symbol as any previous declaration.
2538 *function = prevDec;
2539 }
2540
2541 if ((*function)->isDefined())
2542 {
2543 error(location, "function already has a body", (*function)->getName().c_str());
2544 }
2545
2546 (*function)->setDefined();
Jamie Madill185fb402015-06-12 15:48:48 -04002547 }
Jamie Madill185fb402015-06-12 15:48:48 -04002548
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002549 // Remember the return type for later checking for return statements.
Olli Etuaho476197f2016-10-11 13:59:08 +01002550 mCurrentFunctionType = &((*function)->getReturnType());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002551 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002552
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002553 *prototypeOut = createPrototypeNodeFromFunction(**function, location, true);
Jamie Madill185fb402015-06-12 15:48:48 -04002554 setLoopNestingLevel(0);
2555}
2556
Jamie Madillb98c3a82015-07-23 14:26:04 -04002557TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002558{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002559 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002560 // We don't know at this point whether this is a function definition or a prototype.
2561 // The definition production code will check for redefinitions.
2562 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002563 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002564 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2565 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002566 //
2567 TFunction *prevDec =
2568 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302569
Martin Radevda6254b2016-12-14 17:00:36 +02002570 if (getShaderVersion() >= 300 &&
2571 symbolTable.hasUnmangledBuiltInForShaderVersion(function->getName().c_str(),
2572 getShaderVersion()))
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302573 {
Martin Radevda6254b2016-12-14 17:00:36 +02002574 // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions.
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302575 // Therefore overloading or redefining builtin functions is an error.
2576 error(location, "Name of a built-in function cannot be redeclared as function",
2577 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302578 }
2579 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002580 {
2581 if (prevDec->getReturnType() != function->getReturnType())
2582 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002583 error(location, "function must have the same return type in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002584 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002585 }
2586 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2587 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002588 if (prevDec->getParam(i).type->getQualifier() !=
2589 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002590 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002591 error(location,
2592 "function must have the same parameter qualifiers in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002593 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002594 }
2595 }
2596 }
2597
2598 //
2599 // Check for previously declared variables using the same name.
2600 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002601 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002602 if (prevSym)
2603 {
2604 if (!prevSym->isFunction())
2605 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002606 error(location, "redefinition of a function", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002607 }
2608 }
2609 else
2610 {
2611 // Insert the unmangled name to detect potential future redefinition as a variable.
Olli Etuaho476197f2016-10-11 13:59:08 +01002612 symbolTable.getOuterLevel()->insertUnmangled(function);
Jamie Madill185fb402015-06-12 15:48:48 -04002613 }
2614
2615 // We're at the inner scope level of the function's arguments and body statement.
2616 // Add the function prototype to the surrounding scope instead.
2617 symbolTable.getOuterLevel()->insert(function);
2618
Olli Etuaho78d13742017-01-18 13:06:10 +00002619 // Raise error message if main function takes any parameters or return anything other than void
2620 if (function->getName() == "main")
2621 {
2622 if (function->getParamCount() > 0)
2623 {
2624 error(location, "function cannot take any parameter(s)", "main");
2625 }
2626 if (function->getReturnType().getBasicType() != EbtVoid)
2627 {
2628 error(location, "main function cannot return a value",
2629 function->getReturnType().getBasicString());
2630 }
2631 }
2632
Jamie Madill185fb402015-06-12 15:48:48 -04002633 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002634 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2635 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002636 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2637 //
2638 return function;
2639}
2640
Olli Etuaho9de84a52016-06-14 17:36:01 +03002641TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2642 const TString *name,
2643 const TSourceLoc &location)
2644{
2645 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2646 {
2647 error(location, "no qualifiers allowed for function return",
2648 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002649 }
2650 if (!type.layoutQualifier.isEmpty())
2651 {
2652 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002653 }
jchen10cc2a10e2017-05-03 14:05:12 +08002654 // make sure an opaque type is not involved as well...
2655 std::string reason(getBasicString(type.getBasicType()));
2656 reason += "s can't be function return values";
2657 checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002658 if (mShaderVersion < 300)
2659 {
2660 // Array return values are forbidden, but there's also no valid syntax for declaring array
2661 // return values in ESSL 1.00.
Olli Etuaho77ba4082016-12-16 12:01:18 +00002662 ASSERT(type.arraySize == 0 || mDiagnostics->numErrors() > 0);
Olli Etuahoe29324f2016-06-15 10:58:03 +03002663
2664 if (type.isStructureContainingArrays())
2665 {
2666 // ESSL 1.00.17 section 6.1 Function Definitions
2667 error(location, "structures containing arrays can't be function return values",
2668 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002669 }
2670 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002671
2672 // Add the function as a prototype after parsing it (we do not support recursion)
2673 return new TFunction(name, new TType(type));
2674}
2675
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002676TFunction *TParseContext::addConstructorFunc(const TPublicType &publicType)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002677{
Martin Radev4a9cd802016-09-01 16:51:51 +03002678 if (publicType.isStructSpecifier())
Olli Etuahobd163f62015-11-13 12:15:38 +02002679 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002680 error(publicType.getLine(), "constructor can't be a structure definition",
2681 getBasicString(publicType.getBasicType()));
Olli Etuahobd163f62015-11-13 12:15:38 +02002682 }
2683
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002684 TType *type = new TType(publicType);
2685 if (!type->canBeConstructed())
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002686 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002687 error(publicType.getLine(), "cannot construct this type",
2688 getBasicString(publicType.getBasicType()));
2689 type->setBasicType(EbtFloat);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002690 }
2691
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002692 return new TFunction(nullptr, type, EOpConstruct);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002693}
2694
Jamie Madillb98c3a82015-07-23 14:26:04 -04002695// This function is used to test for the correctness of the parameters passed to various constructor
2696// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002697//
Olli Etuaho856c4972016-08-08 11:38:39 +03002698// 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 +00002699//
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002700TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00002701 TType type,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302702 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002703{
Olli Etuaho856c4972016-08-08 11:38:39 +03002704 if (type.isUnsizedArray())
2705 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002706 if (arguments->empty())
Olli Etuahobbe9fb52016-11-03 17:16:05 +00002707 {
2708 error(line, "implicitly sized array constructor must have at least one argument", "[]");
2709 type.setArraySize(1u);
2710 return TIntermTyped::CreateZero(type);
2711 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002712 type.setArraySize(static_cast<unsigned int>(arguments->size()));
Olli Etuaho856c4972016-08-08 11:38:39 +03002713 }
Olli Etuaho856c4972016-08-08 11:38:39 +03002714
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002715 if (!checkConstructorArguments(line, arguments, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002716 {
Olli Etuaho72d10202017-01-19 15:58:30 +00002717 return TIntermTyped::CreateZero(type);
Olli Etuaho856c4972016-08-08 11:38:39 +03002718 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002719
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002720 TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002721 constructorNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002722
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002723 TIntermTyped *constConstructor =
2724 intermediate.foldAggregateBuiltIn(constructorNode, mDiagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002725 if (constConstructor)
2726 {
2727 return constConstructor;
2728 }
2729
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002730 return constructorNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002731}
2732
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002733//
2734// Interface/uniform blocks
2735//
Olli Etuaho13389b62016-10-16 11:48:18 +01002736TIntermDeclaration *TParseContext::addInterfaceBlock(
Martin Radev70866b82016-07-22 15:27:42 +03002737 const TTypeQualifierBuilder &typeQualifierBuilder,
2738 const TSourceLoc &nameLine,
2739 const TString &blockName,
2740 TFieldList *fieldList,
2741 const TString *instanceName,
2742 const TSourceLoc &instanceLine,
2743 TIntermTyped *arrayIndex,
2744 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002745{
Olli Etuaho856c4972016-08-08 11:38:39 +03002746 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002747
Olli Etuaho77ba4082016-12-16 12:01:18 +00002748 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03002749
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002750 if (typeQualifier.qualifier != EvqUniform)
2751 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002752 error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform",
2753 getQualifierString(typeQualifier.qualifier));
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002754 }
2755
Martin Radev70866b82016-07-22 15:27:42 +03002756 if (typeQualifier.invariant)
2757 {
2758 error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
2759 }
2760
Olli Etuaho43364892017-02-13 16:00:12 +00002761 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
2762
2763 // TODO(oetuaho): Remove this and support binding for blocks.
2764 checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
Martin Radev2cc85b32016-08-05 16:22:53 +03002765
Andrei Volykhina5527072017-03-22 16:46:30 +03002766 checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
2767
Jamie Madill099c0f32013-06-20 11:55:52 -04002768 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03002769 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04002770
Jamie Madill099c0f32013-06-20 11:55:52 -04002771 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2772 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002773 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002774 }
2775
Jamie Madill1566ef72013-06-20 11:55:54 -04002776 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2777 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002778 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002779 }
2780
Olli Etuaho856c4972016-08-08 11:38:39 +03002781 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002782
Martin Radev2cc85b32016-08-05 16:22:53 +03002783 checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
2784
Arun Patole7e7e68d2015-05-22 12:02:25 +05302785 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2786 if (!symbolTable.declare(blockNameSymbol))
2787 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002788 error(nameLine, "redefinition of an interface block name", blockName.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002789 }
2790
Jamie Madill98493dd2013-07-08 14:39:03 -04002791 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302792 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2793 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002794 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302795 TType *fieldType = field->type();
jchen10cc2a10e2017-05-03 14:05:12 +08002796 if (IsOpaqueType(fieldType->getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +05302797 {
jchen10cc2a10e2017-05-03 14:05:12 +08002798 std::string reason("unsupported type - ");
2799 reason += fieldType->getBasicString();
2800 reason += " types are not allowed in interface blocks";
2801 error(field->line(), reason.c_str(), fieldType->getBasicString());
Martin Radev2cc85b32016-08-05 16:22:53 +03002802 }
2803
Jamie Madill98493dd2013-07-08 14:39:03 -04002804 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002805 switch (qualifier)
2806 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002807 case EvqGlobal:
2808 case EvqUniform:
2809 break;
2810 default:
2811 error(field->line(), "invalid qualifier on interface block member",
2812 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04002813 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002814 }
Jamie Madilla5efff92013-06-06 11:56:47 -04002815
Martin Radev70866b82016-07-22 15:27:42 +03002816 if (fieldType->isInvariant())
2817 {
2818 error(field->line(), "invalid qualifier on interface block member", "invariant");
2819 }
2820
Jamie Madilla5efff92013-06-06 11:56:47 -04002821 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04002822 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03002823 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Jamie Madill099c0f32013-06-20 11:55:52 -04002824
Jamie Madill98493dd2013-07-08 14:39:03 -04002825 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04002826 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002827 error(field->line(), "invalid layout qualifier: cannot be used here",
2828 getBlockStorageString(fieldLayoutQualifier.blockStorage));
Jamie Madill1566ef72013-06-20 11:55:54 -04002829 }
2830
Jamie Madill98493dd2013-07-08 14:39:03 -04002831 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04002832 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002833 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002834 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002835 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04002836 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002837 warning(field->line(),
2838 "extraneous layout qualifier: only has an effect on matrix types",
2839 getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
Jamie Madill099c0f32013-06-20 11:55:52 -04002840 }
2841
Jamie Madill98493dd2013-07-08 14:39:03 -04002842 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002843 }
2844
Jamie Madill98493dd2013-07-08 14:39:03 -04002845 // add array index
Olli Etuaho856c4972016-08-08 11:38:39 +03002846 unsigned int arraySize = 0;
2847 if (arrayIndex != nullptr)
Jamie Madill98493dd2013-07-08 14:39:03 -04002848 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002849 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
Jamie Madill98493dd2013-07-08 14:39:03 -04002850 }
2851
Jamie Madillb98c3a82015-07-23 14:26:04 -04002852 TInterfaceBlock *interfaceBlock =
2853 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2854 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
2855 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002856
2857 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04002858 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002859
Jamie Madill98493dd2013-07-08 14:39:03 -04002860 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002861 {
2862 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04002863 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2864 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002865 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302866 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04002867
2868 // set parent pointer of the field variable
2869 fieldType->setInterfaceBlock(interfaceBlock);
2870
Arun Patole7e7e68d2015-05-22 12:02:25 +05302871 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04002872 fieldVariable->setQualifier(typeQualifier.qualifier);
2873
Arun Patole7e7e68d2015-05-22 12:02:25 +05302874 if (!symbolTable.declare(fieldVariable))
2875 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002876 error(field->line(), "redefinition of an interface block member name",
2877 field->name().c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002878 }
2879 }
2880 }
2881 else
2882 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002883 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03002884
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002885 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05302886 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002887 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04002888
Arun Patole7e7e68d2015-05-22 12:02:25 +05302889 if (!symbolTable.declare(instanceTypeDef))
2890 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002891 error(instanceLine, "redefinition of an interface block instance name",
2892 instanceName->c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002893 }
2894
Jamie Madillb98c3a82015-07-23 14:26:04 -04002895 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002896 symbolName = instanceTypeDef->getName();
2897 }
2898
Olli Etuaho13389b62016-10-16 11:48:18 +01002899 TIntermSymbol *blockSymbol =
2900 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line);
2901 TIntermDeclaration *declaration = new TIntermDeclaration();
2902 declaration->appendDeclarator(blockSymbol);
2903 declaration->setLine(nameLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04002904
2905 exitStructDeclaration();
Olli Etuaho13389b62016-10-16 11:48:18 +01002906 return declaration;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002907}
2908
Olli Etuaho383b7912016-08-05 11:22:59 +03002909void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002910{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002911 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002912
2913 // Embedded structure definitions are not supported per GLSL ES spec.
Olli Etuaho4de340a2016-12-16 09:32:03 +00002914 // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302915 if (mStructNestingLevel > 1)
2916 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002917 error(line, "Embedded struct definitions are not allowed", "struct");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002918 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002919}
2920
2921void TParseContext::exitStructDeclaration()
2922{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002923 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002924}
2925
Olli Etuaho8a176262016-08-16 14:23:01 +03002926void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002927{
Jamie Madillacb4b812016-11-07 13:50:29 -05002928 if (!sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +05302929 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002930 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002931 }
2932
Arun Patole7e7e68d2015-05-22 12:02:25 +05302933 if (field.type()->getBasicType() != EbtStruct)
2934 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002935 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002936 }
2937
2938 // We're already inside a structure definition at this point, so add
2939 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302940 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2941 {
Jamie Madill41a49272014-03-18 16:10:13 -04002942 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002943 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
2944 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04002945 std::string reason = reasonStream.str();
Olli Etuaho4de340a2016-12-16 09:32:03 +00002946 error(line, reason.c_str(), field.name().c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03002947 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002948 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002949}
2950
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00002951//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002952// Parse an array index expression
2953//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002954TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
2955 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302956 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002957{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002958 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2959 {
2960 if (baseExpression->getAsSymbolNode())
2961 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302962 error(location, " left of '[' is not of type array, matrix, or vector ",
2963 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002964 }
2965 else
2966 {
2967 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2968 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002969
2970 TConstantUnion *unionArray = new TConstantUnion[1];
2971 unionArray->setFConst(0.0f);
2972 return intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst),
2973 location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002974 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002975
Jamie Madill21c1e452014-12-29 11:33:41 -05002976 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2977
Olli Etuaho36b05142015-11-12 13:10:42 +02002978 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
2979 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
2980 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
2981 // index is a constant expression.
2982 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
2983 {
2984 if (baseExpression->isInterfaceBlock())
2985 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002986 error(location,
2987 "array indexes for interface blocks arrays must be constant integral expressions",
2988 "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02002989 }
2990 else if (baseExpression->getQualifier() == EvqFragmentOut)
2991 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002992 error(location,
2993 "array indexes for fragment outputs must be constant integral expressions", "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02002994 }
Olli Etuaho3e960462015-11-12 15:58:39 +02002995 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
2996 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002997 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3e960462015-11-12 15:58:39 +02002998 }
Olli Etuaho36b05142015-11-12 13:10:42 +02002999 }
3000
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003001 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04003002 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003003 // If an out-of-range index is not qualified as constant, the behavior in the spec is
3004 // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
3005 // constant fold expressions that are not constant expressions). The most compatible way to
3006 // handle this case is to report a warning instead of an error and force the index to be in
3007 // the correct range.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003008 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003009 int index = indexConstantUnion->getIConst(0);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003010
3011 int safeIndex = -1;
3012
3013 if (baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04003014 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003015 if (baseExpression->getQualifier() == EvqFragData && index > 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003016 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003017 if (mShaderSpec == SH_WEBGL2_SPEC)
3018 {
3019 // Error has been already generated if index is not const.
3020 if (indexExpression->getQualifier() == EvqConst)
3021 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003022 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003023 }
3024 safeIndex = 0;
3025 }
3026 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
3027 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003028 outOfRangeError(outOfRangeIndexIsError, location,
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003029 "array index for gl_FragData must be zero when "
Olli Etuaho4de340a2016-12-16 09:32:03 +00003030 "GL_EXT_draw_buffers is disabled",
3031 "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003032 safeIndex = 0;
3033 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03003034 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003035 // Only do generic out-of-range check if similar error hasn't already been reported.
3036 if (safeIndex < 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003037 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003038 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3039 baseExpression->getArraySize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003040 "array index out of range");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003041 }
3042 }
3043 else if (baseExpression->isMatrix())
3044 {
3045 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
Olli Etuaho90892fb2016-07-14 14:44:51 +03003046 baseExpression->getType().getCols(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003047 "matrix field selection out of range");
Jamie Madill7164cf42013-07-08 13:30:59 -04003048 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003049 else if (baseExpression->isVector())
Jamie Madill7164cf42013-07-08 13:30:59 -04003050 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003051 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3052 baseExpression->getType().getNominalSize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003053 "vector field selection out of range");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003054 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003055
3056 ASSERT(safeIndex >= 0);
3057 // Data of constant unions can't be changed, because it may be shared with other
3058 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
3059 // sanitized object.
3060 if (safeIndex != index)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003061 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003062 TConstantUnion *safeConstantUnion = new TConstantUnion();
3063 safeConstantUnion->setIConst(safeIndex);
3064 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003065 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003066
3067 return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003068 mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003069 }
Jamie Madill7164cf42013-07-08 13:30:59 -04003070 else
3071 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003072 return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003073 mDiagnostics);
Jamie Madill7164cf42013-07-08 13:30:59 -04003074 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003075}
3076
Olli Etuaho90892fb2016-07-14 14:44:51 +03003077int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
3078 const TSourceLoc &location,
3079 int index,
3080 int arraySize,
Olli Etuaho4de340a2016-12-16 09:32:03 +00003081 const char *reason)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003082{
3083 if (index >= arraySize || index < 0)
3084 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003085 std::stringstream reasonStream;
3086 reasonStream << reason << " '" << index << "'";
3087 std::string token = reasonStream.str();
3088 outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
Olli Etuaho90892fb2016-07-14 14:44:51 +03003089 if (index < 0)
3090 {
3091 return 0;
3092 }
3093 else
3094 {
3095 return arraySize - 1;
3096 }
3097 }
3098 return index;
3099}
3100
Jamie Madillb98c3a82015-07-23 14:26:04 -04003101TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
3102 const TSourceLoc &dotLocation,
3103 const TString &fieldString,
3104 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003105{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003106 if (baseExpression->isArray())
3107 {
3108 error(fieldLocation, "cannot apply dot operator to an array", ".");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003109 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003110 }
3111
3112 if (baseExpression->isVector())
3113 {
3114 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003115 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
3116 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003117 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003118 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003119 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003120 }
3121
Olli Etuahob6fa0432016-09-28 16:28:05 +01003122 return TIntermediate::AddSwizzle(baseExpression, fields, dotLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003123 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003124 else if (baseExpression->getBasicType() == EbtStruct)
3125 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303126 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003127 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003128 {
3129 error(dotLocation, "structure has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003130 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003131 }
3132 else
3133 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003134 bool fieldFound = false;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003135 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003136 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003137 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003138 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003139 {
3140 fieldFound = true;
3141 break;
3142 }
3143 }
3144 if (fieldFound)
3145 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003146 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3147 index->setLine(fieldLocation);
3148 return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003149 dotLocation, mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003150 }
3151 else
3152 {
3153 error(dotLocation, " no such field in structure", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003154 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003155 }
3156 }
3157 }
Jamie Madill98493dd2013-07-08 14:39:03 -04003158 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003159 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303160 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003161 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003162 {
3163 error(dotLocation, "interface block has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003164 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003165 }
3166 else
3167 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003168 bool fieldFound = false;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003169 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003170 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003171 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003172 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003173 {
3174 fieldFound = true;
3175 break;
3176 }
3177 }
3178 if (fieldFound)
3179 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003180 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3181 index->setLine(fieldLocation);
3182 return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003183 dotLocation, mDiagnostics);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003184 }
3185 else
3186 {
3187 error(dotLocation, " no such field in interface block", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003188 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003189 }
3190 }
3191 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003192 else
3193 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003194 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003195 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03003196 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303197 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003198 }
3199 else
3200 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303201 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03003202 " field selection requires structure, vector, or interface block on left hand "
3203 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303204 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003205 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003206 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003207 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003208}
3209
Jamie Madillb98c3a82015-07-23 14:26:04 -04003210TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3211 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003212{
Martin Radev802abe02016-08-04 17:48:32 +03003213 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003214
3215 if (qualifierType == "shared")
3216 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003217 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003218 {
3219 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
3220 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003221 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003222 }
3223 else if (qualifierType == "packed")
3224 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003225 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003226 {
3227 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
3228 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003229 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003230 }
3231 else if (qualifierType == "std140")
3232 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003233 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003234 }
3235 else if (qualifierType == "row_major")
3236 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003237 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003238 }
3239 else if (qualifierType == "column_major")
3240 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003241 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003242 }
3243 else if (qualifierType == "location")
3244 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003245 error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
3246 qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003247 }
Andrei Volykhina5527072017-03-22 16:46:30 +03003248 else if (qualifierType == "yuv" && isExtensionEnabled("GL_EXT_YUV_target") &&
3249 mShaderType == GL_FRAGMENT_SHADER)
3250 {
3251 qualifier.yuv = true;
3252 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003253 else if (qualifierType == "rgba32f")
3254 {
3255 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3256 qualifier.imageInternalFormat = EiifRGBA32F;
3257 }
3258 else if (qualifierType == "rgba16f")
3259 {
3260 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3261 qualifier.imageInternalFormat = EiifRGBA16F;
3262 }
3263 else if (qualifierType == "r32f")
3264 {
3265 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3266 qualifier.imageInternalFormat = EiifR32F;
3267 }
3268 else if (qualifierType == "rgba8")
3269 {
3270 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3271 qualifier.imageInternalFormat = EiifRGBA8;
3272 }
3273 else if (qualifierType == "rgba8_snorm")
3274 {
3275 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3276 qualifier.imageInternalFormat = EiifRGBA8_SNORM;
3277 }
3278 else if (qualifierType == "rgba32i")
3279 {
3280 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3281 qualifier.imageInternalFormat = EiifRGBA32I;
3282 }
3283 else if (qualifierType == "rgba16i")
3284 {
3285 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3286 qualifier.imageInternalFormat = EiifRGBA16I;
3287 }
3288 else if (qualifierType == "rgba8i")
3289 {
3290 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3291 qualifier.imageInternalFormat = EiifRGBA8I;
3292 }
3293 else if (qualifierType == "r32i")
3294 {
3295 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3296 qualifier.imageInternalFormat = EiifR32I;
3297 }
3298 else if (qualifierType == "rgba32ui")
3299 {
3300 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3301 qualifier.imageInternalFormat = EiifRGBA32UI;
3302 }
3303 else if (qualifierType == "rgba16ui")
3304 {
3305 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3306 qualifier.imageInternalFormat = EiifRGBA16UI;
3307 }
3308 else if (qualifierType == "rgba8ui")
3309 {
3310 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3311 qualifier.imageInternalFormat = EiifRGBA8UI;
3312 }
3313 else if (qualifierType == "r32ui")
3314 {
3315 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3316 qualifier.imageInternalFormat = EiifR32UI;
3317 }
3318
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003319 else
3320 {
3321 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003322 }
3323
Jamie Madilla5efff92013-06-06 11:56:47 -04003324 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003325}
3326
Martin Radev802abe02016-08-04 17:48:32 +03003327void TParseContext::parseLocalSize(const TString &qualifierType,
3328 const TSourceLoc &qualifierTypeLine,
3329 int intValue,
3330 const TSourceLoc &intValueLine,
3331 const std::string &intValueString,
3332 size_t index,
Martin Radev4c4c8e72016-08-04 12:25:34 +03003333 sh::WorkGroupSize *localSize)
Martin Radev802abe02016-08-04 17:48:32 +03003334{
Olli Etuaho856c4972016-08-08 11:38:39 +03003335 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03003336 if (intValue < 1)
3337 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003338 std::stringstream reasonStream;
3339 reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
3340 std::string reason = reasonStream.str();
3341 error(intValueLine, reason.c_str(), intValueString.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003342 }
3343 (*localSize)[index] = intValue;
3344}
3345
Olli Etuaho09b04a22016-12-15 13:30:26 +00003346void TParseContext::parseNumViews(int intValue,
3347 const TSourceLoc &intValueLine,
3348 const std::string &intValueString,
3349 int *numViews)
3350{
3351 // This error is only specified in WebGL, but tightens unspecified behavior in the native
3352 // specification.
3353 if (intValue < 1)
3354 {
3355 error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
3356 }
3357 *numViews = intValue;
3358}
3359
Jamie Madillb98c3a82015-07-23 14:26:04 -04003360TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3361 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003362 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303363 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003364{
Martin Radev802abe02016-08-04 17:48:32 +03003365 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003366
Martin Radev802abe02016-08-04 17:48:32 +03003367 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003368
Martin Radev802abe02016-08-04 17:48:32 +03003369 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003370 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003371 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003372 if (intValue < 0)
3373 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003374 error(intValueLine, "out of range: location must be non-negative",
3375 intValueString.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003376 }
3377 else
3378 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003379 qualifier.location = intValue;
Olli Etuaho87d410c2016-09-05 13:33:26 +03003380 qualifier.locationsSpecified = 1;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003381 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003382 }
Olli Etuaho43364892017-02-13 16:00:12 +00003383 else if (qualifierType == "binding")
3384 {
3385 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3386 if (intValue < 0)
3387 {
3388 error(intValueLine, "out of range: binding must be non-negative",
3389 intValueString.c_str());
3390 }
3391 else
3392 {
3393 qualifier.binding = intValue;
3394 }
3395 }
Martin Radev802abe02016-08-04 17:48:32 +03003396 else if (qualifierType == "local_size_x")
3397 {
3398 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3399 &qualifier.localSize);
3400 }
3401 else if (qualifierType == "local_size_y")
3402 {
3403 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3404 &qualifier.localSize);
3405 }
3406 else if (qualifierType == "local_size_z")
3407 {
3408 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3409 &qualifier.localSize);
3410 }
Olli Etuaho09b04a22016-12-15 13:30:26 +00003411 else if (qualifierType == "num_views" && mMultiviewAvailable &&
3412 (isExtensionEnabled("GL_OVR_multiview") || isExtensionEnabled("GL_OVR_multiview2")) &&
3413 mShaderType == GL_VERTEX_SHADER)
3414 {
3415 parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
3416 }
Martin Radev802abe02016-08-04 17:48:32 +03003417 else
3418 {
3419 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003420 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003421
Jamie Madilla5efff92013-06-06 11:56:47 -04003422 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003423}
3424
Olli Etuaho613b9592016-09-05 12:05:53 +03003425TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
3426{
3427 return new TTypeQualifierBuilder(
3428 new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
3429 mShaderVersion);
3430}
3431
Jamie Madillb98c3a82015-07-23 14:26:04 -04003432TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003433 TLayoutQualifier rightQualifier,
3434 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003435{
Martin Radevc28888b2016-07-22 15:27:42 +03003436 return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003437 mDiagnostics);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003438}
3439
Olli Etuaho4de340a2016-12-16 09:32:03 +00003440TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
3441 const TFieldList *newlyAddedFields,
3442 const TSourceLoc &location)
3443{
3444 for (TField *field : *newlyAddedFields)
3445 {
3446 for (TField *oldField : *processedFields)
3447 {
3448 if (oldField->name() == field->name())
3449 {
3450 error(location, "duplicate field name in structure", field->name().c_str());
3451 }
3452 }
3453 processedFields->push_back(field);
3454 }
3455 return processedFields;
3456}
3457
Martin Radev70866b82016-07-22 15:27:42 +03003458TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
3459 const TTypeQualifierBuilder &typeQualifierBuilder,
3460 TPublicType *typeSpecifier,
3461 TFieldList *fieldList)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003462{
Olli Etuaho77ba4082016-12-16 12:01:18 +00003463 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003464
Martin Radev70866b82016-07-22 15:27:42 +03003465 typeSpecifier->qualifier = typeQualifier.qualifier;
3466 typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03003467 typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03003468 typeSpecifier->invariant = typeQualifier.invariant;
3469 if (typeQualifier.precision != EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +05303470 {
Martin Radev70866b82016-07-22 15:27:42 +03003471 typeSpecifier->precision = typeQualifier.precision;
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003472 }
Martin Radev70866b82016-07-22 15:27:42 +03003473 return addStructDeclaratorList(*typeSpecifier, fieldList);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003474}
3475
Jamie Madillb98c3a82015-07-23 14:26:04 -04003476TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3477 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003478{
Martin Radev4a9cd802016-09-01 16:51:51 +03003479 checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
3480 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03003481
Martin Radev4a9cd802016-09-01 16:51:51 +03003482 checkIsNonVoid(typeSpecifier.getLine(), (*fieldList)[0]->name(), typeSpecifier.getBasicType());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003483
Martin Radev4a9cd802016-09-01 16:51:51 +03003484 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003485
Arun Patole7e7e68d2015-05-22 12:02:25 +05303486 for (unsigned int i = 0; i < fieldList->size(); ++i)
3487 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003488 //
3489 // Careful not to replace already known aspects of type, like array-ness
3490 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303491 TType *type = (*fieldList)[i]->type();
Martin Radev4a9cd802016-09-01 16:51:51 +03003492 type->setBasicType(typeSpecifier.getBasicType());
3493 type->setPrimarySize(typeSpecifier.getPrimarySize());
3494 type->setSecondarySize(typeSpecifier.getSecondarySize());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003495 type->setPrecision(typeSpecifier.precision);
3496 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003497 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
Martin Radev2cc85b32016-08-05 16:22:53 +03003498 type->setMemoryQualifier(typeSpecifier.memoryQualifier);
Martin Radev70866b82016-07-22 15:27:42 +03003499 type->setInvariant(typeSpecifier.invariant);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003500
3501 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303502 if (type->isArray())
3503 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003504 checkIsValidTypeForArray(typeSpecifier.getLine(), typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003505 }
3506 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003507 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Martin Radev4a9cd802016-09-01 16:51:51 +03003508 if (typeSpecifier.getUserDef())
Arun Patole7e7e68d2015-05-22 12:02:25 +05303509 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003510 type->setStruct(typeSpecifier.getUserDef()->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003511 }
3512
Martin Radev4a9cd802016-09-01 16:51:51 +03003513 checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003514 }
3515
Jamie Madill98493dd2013-07-08 14:39:03 -04003516 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003517}
3518
Martin Radev4a9cd802016-09-01 16:51:51 +03003519TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
3520 const TSourceLoc &nameLine,
3521 const TString *structName,
3522 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003523{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303524 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003525 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003526
Jamie Madill9b820842015-02-12 10:40:10 -05003527 // Store a bool in the struct if we're at global scope, to allow us to
3528 // skip the local struct scoping workaround in HLSL.
Jamie Madill9b820842015-02-12 10:40:10 -05003529 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003530
Jamie Madill98493dd2013-07-08 14:39:03 -04003531 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003532 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003533 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303534 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3535 if (!symbolTable.declare(userTypeDef))
3536 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003537 error(nameLine, "redefinition of a struct", structName->c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003538 }
3539 }
3540
3541 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003542 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003543 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003544 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003545 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003546 switch (qualifier)
3547 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003548 case EvqGlobal:
3549 case EvqTemporary:
3550 break;
3551 default:
3552 error(field.line(), "invalid qualifier on struct member",
3553 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003554 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003555 }
Martin Radev70866b82016-07-22 15:27:42 +03003556 if (field.type()->isInvariant())
3557 {
3558 error(field.line(), "invalid qualifier on struct member", "invariant");
3559 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003560 if (IsImage(field.type()->getBasicType()))
3561 {
3562 error(field.line(), "disallowed type in struct", field.type()->getBasicString());
3563 }
3564
Olli Etuaho43364892017-02-13 16:00:12 +00003565 checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
3566
3567 checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);
Martin Radev70866b82016-07-22 15:27:42 +03003568
3569 checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003570 }
3571
Martin Radev4a9cd802016-09-01 16:51:51 +03003572 TTypeSpecifierNonArray typeSpecifierNonArray;
3573 typeSpecifierNonArray.initialize(EbtStruct, structLine);
3574 typeSpecifierNonArray.userDef = structureType;
3575 typeSpecifierNonArray.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003576 exitStructDeclaration();
3577
Martin Radev4a9cd802016-09-01 16:51:51 +03003578 return typeSpecifierNonArray;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003579}
3580
Jamie Madillb98c3a82015-07-23 14:26:04 -04003581TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01003582 TIntermBlock *statementList,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003583 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003584{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003585 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003586 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003587 init->isVector())
3588 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003589 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3590 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003591 return nullptr;
3592 }
3593
Olli Etuahoac5274d2015-02-20 10:19:08 +02003594 if (statementList)
3595 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00003596 if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
Olli Etuahoac5274d2015-02-20 10:19:08 +02003597 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003598 return nullptr;
3599 }
3600 }
3601
Olli Etuahoa3a36662015-02-17 13:46:51 +02003602 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3603 if (node == nullptr)
3604 {
3605 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003606 return nullptr;
3607 }
3608 return node;
3609}
3610
3611TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3612{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003613 if (mSwitchNestingLevel == 0)
3614 {
3615 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003616 return nullptr;
3617 }
3618 if (condition == nullptr)
3619 {
3620 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003621 return nullptr;
3622 }
3623 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003624 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003625 {
3626 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003627 }
3628 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003629 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3630 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3631 // fold in case labels.
3632 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003633 {
3634 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003635 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003636 TIntermCase *node = intermediate.addCase(condition, loc);
3637 if (node == nullptr)
3638 {
3639 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003640 return nullptr;
3641 }
3642 return node;
3643}
3644
3645TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3646{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003647 if (mSwitchNestingLevel == 0)
3648 {
3649 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003650 return nullptr;
3651 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003652 TIntermCase *node = intermediate.addCase(nullptr, loc);
3653 if (node == nullptr)
3654 {
3655 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003656 return nullptr;
3657 }
3658 return node;
3659}
3660
Jamie Madillb98c3a82015-07-23 14:26:04 -04003661TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3662 TIntermTyped *child,
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003663 const TSourceLoc &loc)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003664{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003665 ASSERT(child != nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003666
3667 switch (op)
3668 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003669 case EOpLogicalNot:
3670 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3671 child->isVector())
3672 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003673 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003674 return nullptr;
3675 }
3676 break;
3677 case EOpBitwiseNot:
3678 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3679 child->isMatrix() || child->isArray())
3680 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003681 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003682 return nullptr;
3683 }
3684 break;
3685 case EOpPostIncrement:
3686 case EOpPreIncrement:
3687 case EOpPostDecrement:
3688 case EOpPreDecrement:
3689 case EOpNegative:
3690 case EOpPositive:
Olli Etuaho94050052017-05-08 14:17:44 +03003691 if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() ||
3692 child->getBasicType() == EbtBool || child->isArray() ||
3693 IsOpaqueType(child->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -04003694 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003695 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003696 return nullptr;
3697 }
3698 // Operators for built-ins are already type checked against their prototype.
3699 default:
3700 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003701 }
3702
Olli Etuahof119a262016-08-19 15:54:22 +03003703 TIntermUnary *node = new TIntermUnary(op, child);
3704 node->setLine(loc);
Olli Etuahof119a262016-08-19 15:54:22 +03003705
Olli Etuaho77ba4082016-12-16 12:01:18 +00003706 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuahof119a262016-08-19 15:54:22 +03003707 if (foldedNode)
3708 return foldedNode;
3709
3710 return node;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003711}
3712
Olli Etuaho09b22472015-02-11 11:47:26 +02003713TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3714{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003715 TIntermTyped *node = createUnaryMath(op, child, loc);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003716 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003717 {
Olli Etuaho09b22472015-02-11 11:47:26 +02003718 return child;
3719 }
3720 return node;
3721}
3722
Jamie Madillb98c3a82015-07-23 14:26:04 -04003723TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3724 TIntermTyped *child,
3725 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003726{
Olli Etuaho856c4972016-08-08 11:38:39 +03003727 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003728 return addUnaryMath(op, child, loc);
3729}
3730
Jamie Madillb98c3a82015-07-23 14:26:04 -04003731bool TParseContext::binaryOpCommonCheck(TOperator op,
3732 TIntermTyped *left,
3733 TIntermTyped *right,
3734 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003735{
jchen10b4cf5652017-05-05 18:51:17 +08003736 // Check opaque types are not allowed to be operands in expressions other than array indexing
3737 // and structure member selection.
3738 if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType()))
3739 {
3740 switch (op)
3741 {
3742 case EOpIndexDirect:
3743 case EOpIndexIndirect:
3744 break;
3745 case EOpIndexDirectStruct:
3746 UNREACHABLE();
3747
3748 default:
3749 error(loc, "Invalid operation for variables with an opaque type",
3750 GetOperatorString(op));
3751 return false;
3752 }
3753 }
jchen10cc2a10e2017-05-03 14:05:12 +08003754
Olli Etuaho244be012016-08-18 15:26:02 +03003755 if (left->getType().getStruct() || right->getType().getStruct())
3756 {
3757 switch (op)
3758 {
3759 case EOpIndexDirectStruct:
3760 ASSERT(left->getType().getStruct());
3761 break;
3762 case EOpEqual:
3763 case EOpNotEqual:
3764 case EOpAssign:
3765 case EOpInitialize:
3766 if (left->getType() != right->getType())
3767 {
3768 return false;
3769 }
3770 break;
3771 default:
3772 error(loc, "Invalid operation for structs", GetOperatorString(op));
3773 return false;
3774 }
3775 }
3776
Olli Etuaho94050052017-05-08 14:17:44 +03003777 if (left->isInterfaceBlock() || right->isInterfaceBlock())
3778 {
3779 switch (op)
3780 {
3781 case EOpIndexDirectInterfaceBlock:
3782 ASSERT(left->getType().getInterfaceBlock());
3783 break;
3784 default:
3785 error(loc, "Invalid operation for interface blocks", GetOperatorString(op));
3786 return false;
3787 }
3788 }
3789
Olli Etuahod6b14282015-03-17 14:31:35 +02003790 if (left->isArray() || right->isArray())
3791 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003792 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003793 {
3794 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3795 return false;
3796 }
3797
3798 if (left->isArray() != right->isArray())
3799 {
3800 error(loc, "array / non-array mismatch", GetOperatorString(op));
3801 return false;
3802 }
3803
3804 switch (op)
3805 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003806 case EOpEqual:
3807 case EOpNotEqual:
3808 case EOpAssign:
3809 case EOpInitialize:
3810 break;
3811 default:
3812 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3813 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02003814 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03003815 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02003816 if (left->getArraySize() != right->getArraySize())
3817 {
3818 error(loc, "array size mismatch", GetOperatorString(op));
3819 return false;
3820 }
Olli Etuahod6b14282015-03-17 14:31:35 +02003821 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003822
3823 // Check ops which require integer / ivec parameters
3824 bool isBitShift = false;
3825 switch (op)
3826 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003827 case EOpBitShiftLeft:
3828 case EOpBitShiftRight:
3829 case EOpBitShiftLeftAssign:
3830 case EOpBitShiftRightAssign:
3831 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3832 // check that the basic type is an integer type.
3833 isBitShift = true;
3834 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3835 {
3836 return false;
3837 }
3838 break;
3839 case EOpBitwiseAnd:
3840 case EOpBitwiseXor:
3841 case EOpBitwiseOr:
3842 case EOpBitwiseAndAssign:
3843 case EOpBitwiseXorAssign:
3844 case EOpBitwiseOrAssign:
3845 // It is enough to check the type of only one operand, since later it
3846 // is checked that the operand types match.
3847 if (!IsInteger(left->getBasicType()))
3848 {
3849 return false;
3850 }
3851 break;
3852 default:
3853 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003854 }
3855
3856 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3857 // So the basic type should usually match.
3858 if (!isBitShift && left->getBasicType() != right->getBasicType())
3859 {
3860 return false;
3861 }
3862
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003863 // Check that:
3864 // 1. Type sizes match exactly on ops that require that.
3865 // 2. Restrictions for structs that contain arrays or samplers are respected.
3866 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
Jamie Madillb98c3a82015-07-23 14:26:04 -04003867 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003868 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003869 case EOpAssign:
3870 case EOpInitialize:
3871 case EOpEqual:
3872 case EOpNotEqual:
3873 // ESSL 1.00 sections 5.7, 5.8, 5.9
3874 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
3875 {
3876 error(loc, "undefined operation for structs containing arrays",
3877 GetOperatorString(op));
3878 return false;
3879 }
3880 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3881 // we interpret the spec so that this extends to structs containing samplers,
3882 // similarly to ESSL 1.00 spec.
3883 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
3884 left->getType().isStructureContainingSamplers())
3885 {
3886 error(loc, "undefined operation for structs containing samplers",
3887 GetOperatorString(op));
3888 return false;
3889 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003890
Olli Etuahoe1805592017-01-02 16:41:20 +00003891 if ((left->getNominalSize() != right->getNominalSize()) ||
3892 (left->getSecondarySize() != right->getSecondarySize()))
3893 {
3894 error(loc, "dimension mismatch", GetOperatorString(op));
3895 return false;
3896 }
3897 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003898 case EOpLessThan:
3899 case EOpGreaterThan:
3900 case EOpLessThanEqual:
3901 case EOpGreaterThanEqual:
Olli Etuahoe1805592017-01-02 16:41:20 +00003902 if (!left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04003903 {
Olli Etuahoe1805592017-01-02 16:41:20 +00003904 error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003905 return false;
3906 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003907 break;
3908 case EOpAdd:
3909 case EOpSub:
3910 case EOpDiv:
3911 case EOpIMod:
3912 case EOpBitShiftLeft:
3913 case EOpBitShiftRight:
3914 case EOpBitwiseAnd:
3915 case EOpBitwiseXor:
3916 case EOpBitwiseOr:
3917 case EOpAddAssign:
3918 case EOpSubAssign:
3919 case EOpDivAssign:
3920 case EOpIModAssign:
3921 case EOpBitShiftLeftAssign:
3922 case EOpBitShiftRightAssign:
3923 case EOpBitwiseAndAssign:
3924 case EOpBitwiseXorAssign:
3925 case EOpBitwiseOrAssign:
3926 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
3927 {
3928 return false;
3929 }
3930
3931 // Are the sizes compatible?
3932 if (left->getNominalSize() != right->getNominalSize() ||
3933 left->getSecondarySize() != right->getSecondarySize())
3934 {
3935 // If the nominal sizes of operands do not match:
3936 // One of them must be a scalar.
3937 if (!left->isScalar() && !right->isScalar())
3938 return false;
3939
3940 // In the case of compound assignment other than multiply-assign,
3941 // the right side needs to be a scalar. Otherwise a vector/matrix
3942 // would be assigned to a scalar. A scalar can't be shifted by a
3943 // vector either.
3944 if (!right->isScalar() &&
3945 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
3946 return false;
3947 }
3948 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003949 default:
3950 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003951 }
3952
Olli Etuahod6b14282015-03-17 14:31:35 +02003953 return true;
3954}
3955
Olli Etuaho1dded802016-08-18 18:13:13 +03003956bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
3957 const TType &left,
3958 const TType &right)
3959{
3960 switch (op)
3961 {
3962 case EOpMul:
3963 case EOpMulAssign:
3964 return left.getNominalSize() == right.getNominalSize() &&
3965 left.getSecondarySize() == right.getSecondarySize();
3966 case EOpVectorTimesScalar:
3967 return true;
3968 case EOpVectorTimesScalarAssign:
3969 ASSERT(!left.isMatrix() && !right.isMatrix());
3970 return left.isVector() && !right.isVector();
3971 case EOpVectorTimesMatrix:
3972 return left.getNominalSize() == right.getRows();
3973 case EOpVectorTimesMatrixAssign:
3974 ASSERT(!left.isMatrix() && right.isMatrix());
3975 return left.isVector() && left.getNominalSize() == right.getRows() &&
3976 left.getNominalSize() == right.getCols();
3977 case EOpMatrixTimesVector:
3978 return left.getCols() == right.getNominalSize();
3979 case EOpMatrixTimesScalar:
3980 return true;
3981 case EOpMatrixTimesScalarAssign:
3982 ASSERT(left.isMatrix() && !right.isMatrix());
3983 return !right.isVector();
3984 case EOpMatrixTimesMatrix:
3985 return left.getCols() == right.getRows();
3986 case EOpMatrixTimesMatrixAssign:
3987 ASSERT(left.isMatrix() && right.isMatrix());
3988 // We need to check two things:
3989 // 1. The matrix multiplication step is valid.
3990 // 2. The result will have the same number of columns as the lvalue.
3991 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
3992
3993 default:
3994 UNREACHABLE();
3995 return false;
3996 }
3997}
3998
Jamie Madillb98c3a82015-07-23 14:26:04 -04003999TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
4000 TIntermTyped *left,
4001 TIntermTyped *right,
4002 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02004003{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004004 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004005 return nullptr;
4006
Olli Etuahofc1806e2015-03-17 13:03:11 +02004007 switch (op)
4008 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004009 case EOpEqual:
4010 case EOpNotEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04004011 case EOpLessThan:
4012 case EOpGreaterThan:
4013 case EOpLessThanEqual:
4014 case EOpGreaterThanEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04004015 break;
4016 case EOpLogicalOr:
4017 case EOpLogicalXor:
4018 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03004019 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4020 !right->getType().getStruct());
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00004021 if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04004022 {
4023 return nullptr;
4024 }
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00004025 // Basic types matching should have been already checked.
4026 ASSERT(right->getBasicType() == EbtBool);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004027 break;
4028 case EOpAdd:
4029 case EOpSub:
4030 case EOpDiv:
4031 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03004032 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4033 !right->getType().getStruct());
4034 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04004035 {
4036 return nullptr;
4037 }
4038 break;
4039 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03004040 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4041 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004042 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03004043 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04004044 {
4045 return nullptr;
4046 }
4047 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004048 default:
4049 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02004050 }
4051
Olli Etuaho1dded802016-08-18 18:13:13 +03004052 if (op == EOpMul)
4053 {
4054 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
4055 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4056 {
4057 return nullptr;
4058 }
4059 }
4060
Olli Etuaho3fdec912016-08-18 15:08:06 +03004061 TIntermBinary *node = new TIntermBinary(op, left, right);
4062 node->setLine(loc);
4063
Olli Etuaho3fdec912016-08-18 15:08:06 +03004064 // See if we can fold constants.
Olli Etuaho77ba4082016-12-16 12:01:18 +00004065 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuaho3fdec912016-08-18 15:08:06 +03004066 if (foldedNode)
4067 return foldedNode;
4068
4069 return node;
Olli Etuahofc1806e2015-03-17 13:03:11 +02004070}
4071
Jamie Madillb98c3a82015-07-23 14:26:04 -04004072TIntermTyped *TParseContext::addBinaryMath(TOperator op,
4073 TIntermTyped *left,
4074 TIntermTyped *right,
4075 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004076{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004077 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004078 if (node == 0)
4079 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004080 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4081 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02004082 return left;
4083 }
4084 return node;
4085}
4086
Jamie Madillb98c3a82015-07-23 14:26:04 -04004087TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
4088 TIntermTyped *left,
4089 TIntermTyped *right,
4090 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004091{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004092 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004093 if (node == 0)
4094 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004095 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4096 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04004097 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02004098 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004099 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
4100 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004101 }
4102 return node;
4103}
4104
Olli Etuaho13389b62016-10-16 11:48:18 +01004105TIntermBinary *TParseContext::createAssign(TOperator op,
4106 TIntermTyped *left,
4107 TIntermTyped *right,
4108 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004109{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004110 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004111 {
Olli Etuaho1dded802016-08-18 18:13:13 +03004112 if (op == EOpMulAssign)
4113 {
4114 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
4115 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4116 {
4117 return nullptr;
4118 }
4119 }
Olli Etuaho3fdec912016-08-18 15:08:06 +03004120 TIntermBinary *node = new TIntermBinary(op, left, right);
4121 node->setLine(loc);
4122
Olli Etuaho3fdec912016-08-18 15:08:06 +03004123 return node;
Olli Etuahod6b14282015-03-17 14:31:35 +02004124 }
4125 return nullptr;
4126}
4127
Jamie Madillb98c3a82015-07-23 14:26:04 -04004128TIntermTyped *TParseContext::addAssign(TOperator op,
4129 TIntermTyped *left,
4130 TIntermTyped *right,
4131 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004132{
4133 TIntermTyped *node = createAssign(op, left, right, loc);
4134 if (node == nullptr)
4135 {
4136 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02004137 return left;
4138 }
4139 return node;
4140}
4141
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004142TIntermTyped *TParseContext::addComma(TIntermTyped *left,
4143 TIntermTyped *right,
4144 const TSourceLoc &loc)
4145{
Corentin Wallez0d959252016-07-12 17:26:32 -04004146 // WebGL2 section 5.26, the following results in an error:
4147 // "Sequence operator applied to void, arrays, or structs containing arrays"
Jamie Madilld7b1ab52016-12-12 14:42:19 -05004148 if (mShaderSpec == SH_WEBGL2_SPEC &&
4149 (left->isArray() || left->getBasicType() == EbtVoid ||
4150 left->getType().isStructureContainingArrays() || right->isArray() ||
4151 right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
Corentin Wallez0d959252016-07-12 17:26:32 -04004152 {
4153 error(loc,
4154 "sequence operator is not allowed for void, arrays, or structs containing arrays",
4155 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04004156 }
4157
Olli Etuaho4db7ded2016-10-13 12:23:11 +01004158 return TIntermediate::AddComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004159}
4160
Olli Etuaho49300862015-02-20 14:54:49 +02004161TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
4162{
4163 switch (op)
4164 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004165 case EOpContinue:
4166 if (mLoopNestingLevel <= 0)
4167 {
4168 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004169 }
4170 break;
4171 case EOpBreak:
4172 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
4173 {
4174 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004175 }
4176 break;
4177 case EOpReturn:
4178 if (mCurrentFunctionType->getBasicType() != EbtVoid)
4179 {
4180 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004181 }
4182 break;
4183 default:
4184 // No checks for discard
4185 break;
Olli Etuaho49300862015-02-20 14:54:49 +02004186 }
4187 return intermediate.addBranch(op, loc);
4188}
4189
Jamie Madillb98c3a82015-07-23 14:26:04 -04004190TIntermBranch *TParseContext::addBranch(TOperator op,
4191 TIntermTyped *returnValue,
4192 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02004193{
4194 ASSERT(op == EOpReturn);
4195 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004196 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02004197 {
4198 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004199 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004200 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02004201 {
4202 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004203 }
4204 return intermediate.addBranch(op, returnValue, loc);
4205}
4206
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004207void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
4208{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004209 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Olli Etuahobd674552016-10-06 13:28:42 +01004210 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004211 TIntermNode *offset = nullptr;
4212 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuahoec9232b2017-03-27 17:01:37 +03004213 if (name == "texelFetchOffset" || name == "textureLodOffset" ||
4214 name == "textureProjLodOffset" || name == "textureGradOffset" ||
4215 name == "textureProjGradOffset")
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004216 {
4217 offset = arguments->back();
4218 }
Olli Etuahoec9232b2017-03-27 17:01:37 +03004219 else if (name == "textureOffset" || name == "textureProjOffset")
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004220 {
4221 // A bias parameter might follow the offset parameter.
4222 ASSERT(arguments->size() >= 3);
4223 offset = (*arguments)[2];
4224 }
4225 if (offset != nullptr)
4226 {
4227 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
4228 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
4229 {
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004230 error(functionCall->getLine(), "Texture offset must be a constant expression",
Olli Etuahoec9232b2017-03-27 17:01:37 +03004231 name.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004232 }
4233 else
4234 {
4235 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
4236 size_t size = offsetConstantUnion->getType().getObjectSize();
4237 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
4238 for (size_t i = 0u; i < size; ++i)
4239 {
4240 int offsetValue = values[i].getIConst();
4241 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
4242 {
4243 std::stringstream tokenStream;
4244 tokenStream << offsetValue;
4245 std::string token = tokenStream.str();
4246 error(offset->getLine(), "Texture offset value out of valid range",
4247 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004248 }
4249 }
4250 }
4251 }
4252}
4253
Martin Radev2cc85b32016-08-05 16:22:53 +03004254// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
4255void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
4256{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004257 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Martin Radev2cc85b32016-08-05 16:22:53 +03004258 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
4259
4260 if (name.compare(0, 5, "image") == 0)
4261 {
4262 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuaho485eefd2017-02-14 17:40:06 +00004263 TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
Martin Radev2cc85b32016-08-05 16:22:53 +03004264
Olli Etuaho485eefd2017-02-14 17:40:06 +00004265 const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
Martin Radev2cc85b32016-08-05 16:22:53 +03004266
4267 if (name.compare(5, 5, "Store") == 0)
4268 {
4269 if (memoryQualifier.readonly)
4270 {
4271 error(imageNode->getLine(),
4272 "'imageStore' cannot be used with images qualified as 'readonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004273 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03004274 }
4275 }
4276 else if (name.compare(5, 4, "Load") == 0)
4277 {
4278 if (memoryQualifier.writeonly)
4279 {
4280 error(imageNode->getLine(),
4281 "'imageLoad' cannot be used with images qualified as 'writeonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004282 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03004283 }
4284 }
4285 }
4286}
4287
4288// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
4289void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
4290 const TFunction *functionDefinition,
4291 const TIntermAggregate *functionCall)
4292{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004293 ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
Martin Radev2cc85b32016-08-05 16:22:53 +03004294
4295 const TIntermSequence &arguments = *functionCall->getSequence();
4296
4297 ASSERT(functionDefinition->getParamCount() == arguments.size());
4298
4299 for (size_t i = 0; i < arguments.size(); ++i)
4300 {
Olli Etuaho485eefd2017-02-14 17:40:06 +00004301 TIntermTyped *typedArgument = arguments[i]->getAsTyped();
4302 const TType &functionArgumentType = typedArgument->getType();
Martin Radev2cc85b32016-08-05 16:22:53 +03004303 const TType &functionParameterType = *functionDefinition->getParam(i).type;
4304 ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
4305
4306 if (IsImage(functionArgumentType.getBasicType()))
4307 {
4308 const TMemoryQualifier &functionArgumentMemoryQualifier =
4309 functionArgumentType.getMemoryQualifier();
4310 const TMemoryQualifier &functionParameterMemoryQualifier =
4311 functionParameterType.getMemoryQualifier();
4312 if (functionArgumentMemoryQualifier.readonly &&
4313 !functionParameterMemoryQualifier.readonly)
4314 {
4315 error(functionCall->getLine(),
4316 "Function call discards the 'readonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004317 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03004318 }
4319
4320 if (functionArgumentMemoryQualifier.writeonly &&
4321 !functionParameterMemoryQualifier.writeonly)
4322 {
4323 error(functionCall->getLine(),
4324 "Function call discards the 'writeonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004325 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03004326 }
Martin Radev049edfa2016-11-11 14:35:37 +02004327
4328 if (functionArgumentMemoryQualifier.coherent &&
4329 !functionParameterMemoryQualifier.coherent)
4330 {
4331 error(functionCall->getLine(),
4332 "Function call discards the 'coherent' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004333 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02004334 }
4335
4336 if (functionArgumentMemoryQualifier.volatileQualifier &&
4337 !functionParameterMemoryQualifier.volatileQualifier)
4338 {
4339 error(functionCall->getLine(),
4340 "Function call discards the 'volatile' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004341 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02004342 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004343 }
4344 }
4345}
4346
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004347TIntermSequence *TParseContext::createEmptyArgumentsList()
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004348{
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004349 return new TIntermSequence();
Olli Etuaho72d10202017-01-19 15:58:30 +00004350}
4351
4352TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004353 TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00004354 TIntermNode *thisNode,
4355 const TSourceLoc &loc)
4356{
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004357 if (thisNode != nullptr)
4358 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004359 return addMethod(fnCall, arguments, thisNode, loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004360 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004361
4362 TOperator op = fnCall->getBuiltInOp();
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004363 if (op == EOpConstruct)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004364 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004365 return addConstructor(arguments, fnCall->getReturnType(), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004366 }
4367 else
4368 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004369 ASSERT(op == EOpNull);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004370 return addNonConstructorFunctionCall(fnCall, arguments, loc);
4371 }
4372}
4373
4374TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
4375 TIntermSequence *arguments,
4376 TIntermNode *thisNode,
4377 const TSourceLoc &loc)
4378{
4379 TConstantUnion *unionArray = new TConstantUnion[1];
4380 int arraySize = 0;
4381 TIntermTyped *typedThis = thisNode->getAsTyped();
4382 // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
4383 // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
4384 // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
4385 // So accessing fnCall->getName() below is safe.
4386 if (fnCall->getName() != "length")
4387 {
4388 error(loc, "invalid method", fnCall->getName().c_str());
4389 }
4390 else if (!arguments->empty())
4391 {
4392 error(loc, "method takes no parameters", "length");
4393 }
4394 else if (typedThis == nullptr || !typedThis->isArray())
4395 {
4396 error(loc, "length can only be called on arrays", "length");
4397 }
4398 else
4399 {
4400 arraySize = typedThis->getArraySize();
4401 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuaho72d10202017-01-19 15:58:30 +00004402 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004403 // This code path can be hit with expressions like these:
4404 // (a = b).length()
4405 // (func()).length()
4406 // (int[3](0, 1, 2)).length()
4407 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
4408 // expression.
4409 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
4410 // spec section 5.9 which allows "An array, vector or matrix expression with the
4411 // length method applied".
4412 error(loc, "length can only be called on array names, not on array expressions",
4413 "length");
Olli Etuaho72d10202017-01-19 15:58:30 +00004414 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004415 }
4416 unionArray->setIConst(arraySize);
4417 return intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
4418}
4419
4420TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
4421 TIntermSequence *arguments,
4422 const TSourceLoc &loc)
4423{
4424 // First find by unmangled name to check whether the function name has been
4425 // hidden by a variable name or struct typename.
4426 // If a function is found, check for one with a matching argument list.
4427 bool builtIn;
4428 const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn);
4429 if (symbol != nullptr && !symbol->isFunction())
4430 {
4431 error(loc, "function name expected", fnCall->getName().c_str());
4432 }
4433 else
4434 {
4435 symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments),
4436 mShaderVersion, &builtIn);
4437 if (symbol == nullptr)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004438 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004439 error(loc, "no matching overloaded function found", fnCall->getName().c_str());
4440 }
4441 else
4442 {
4443 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004444 //
4445 // A declared function.
4446 //
Olli Etuaho383b7912016-08-05 11:22:59 +03004447 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004448 {
Olli Etuaho856c4972016-08-08 11:38:39 +03004449 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004450 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004451 TOperator op = fnCandidate->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004452 if (builtIn && op != EOpNull)
4453 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004454 // A function call mapped to a built-in operation.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004455 if (fnCandidate->getParamCount() == 1)
4456 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004457 // Treat it like a built-in unary operator.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004458 TIntermNode *unaryParamNode = arguments->front();
4459 TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004460 ASSERT(callNode != nullptr);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004461 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004462 }
4463 else
4464 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004465 TIntermAggregate *callNode =
Olli Etuahofe486322017-03-21 09:30:54 +00004466 TIntermAggregate::Create(fnCandidate->getReturnType(), op, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004467 callNode->setLine(loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004468
4469 // Some built-in functions have out parameters too.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004470 functionCallLValueErrorCheck(fnCandidate, callNode);
Arun Patole274f0702015-05-05 13:33:30 +05304471
Olli Etuaho7c3848e2015-11-04 13:19:17 +02004472 // See if we can constant fold a built-in. Note that this may be possible even
4473 // if it is not const-qualified.
Olli Etuahof119a262016-08-19 15:54:22 +03004474 TIntermTyped *foldedNode =
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004475 intermediate.foldAggregateBuiltIn(callNode, mDiagnostics);
Arun Patole274f0702015-05-05 13:33:30 +05304476 if (foldedNode)
4477 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004478 return foldedNode;
Arun Patole274f0702015-05-05 13:33:30 +05304479 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004480 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004481 }
4482 }
4483 else
4484 {
4485 // This is a real function call
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004486 TIntermAggregate *callNode = nullptr;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004487
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004488 // If builtIn == false, the function is user defined - could be an overloaded
4489 // built-in as well.
4490 // if builtIn == true, it's a builtIn function with no op associated with it.
4491 // This needs to happen after the function info including name is set.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004492 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004493 {
Olli Etuahofe486322017-03-21 09:30:54 +00004494 callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004495 checkTextureOffsetConst(callNode);
4496 checkImageMemoryAccessForBuiltinFunctions(callNode);
Martin Radev2cc85b32016-08-05 16:22:53 +03004497 }
4498 else
4499 {
Olli Etuahofe486322017-03-21 09:30:54 +00004500 callNode = TIntermAggregate::CreateFunctionCall(*fnCandidate, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004501 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004502 }
4503
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004504 functionCallLValueErrorCheck(fnCandidate, callNode);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004505
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004506 callNode->setLine(loc);
4507
4508 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004509 }
4510 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004511 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004512
4513 // Error message was already written. Put on a dummy node for error recovery.
4514 return TIntermTyped::CreateZero(TType(EbtFloat, EbpMedium, EvqConst));
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004515}
4516
Jamie Madillb98c3a82015-07-23 14:26:04 -04004517TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004518 TIntermTyped *trueExpression,
4519 TIntermTyped *falseExpression,
Olli Etuaho52901742015-04-15 13:42:45 +03004520 const TSourceLoc &loc)
4521{
Olli Etuaho856c4972016-08-08 11:38:39 +03004522 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03004523
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004524 if (trueExpression->getType() != falseExpression->getType())
Olli Etuaho52901742015-04-15 13:42:45 +03004525 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004526 binaryOpError(loc, "?:", trueExpression->getCompleteString(),
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004527 falseExpression->getCompleteString());
4528 return falseExpression;
Olli Etuaho52901742015-04-15 13:42:45 +03004529 }
Olli Etuahode318b22016-10-25 16:18:25 +01004530 if (IsOpaqueType(trueExpression->getBasicType()))
4531 {
4532 // ESSL 1.00 section 4.1.7
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004533 // ESSL 3.00.6 section 4.1.7
Olli Etuahode318b22016-10-25 16:18:25 +01004534 // Opaque/sampler types are not allowed in most types of expressions, including ternary.
4535 // Note that structs containing opaque types don't need to be checked as structs are
4536 // forbidden below.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004537 error(loc, "ternary operator is not allowed for opaque types", "?:");
Olli Etuahode318b22016-10-25 16:18:25 +01004538 return falseExpression;
4539 }
4540
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004541 // ESSL 1.00.17 sections 5.2 and 5.7:
Olli Etuahoa2d53032015-04-15 14:14:44 +03004542 // Ternary operator is not among the operators allowed for structures/arrays.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004543 // ESSL 3.00.6 section 5.7:
4544 // Ternary operator support is optional for arrays. No certainty that it works across all
4545 // devices with struct either, so we err on the side of caution here. TODO (oetuaho@nvidia.com):
4546 // Would be nice to make the spec and implementation agree completely here.
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004547 if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
Olli Etuahoa2d53032015-04-15 14:14:44 +03004548 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004549 error(loc, "ternary operator is not allowed for structures or arrays", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004550 return falseExpression;
Olli Etuahoa2d53032015-04-15 14:14:44 +03004551 }
Olli Etuaho94050052017-05-08 14:17:44 +03004552 if (trueExpression->getBasicType() == EbtInterfaceBlock)
4553 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004554 error(loc, "ternary operator is not allowed for interface blocks", "?:");
Olli Etuaho94050052017-05-08 14:17:44 +03004555 return falseExpression;
4556 }
4557
Corentin Wallez0d959252016-07-12 17:26:32 -04004558 // WebGL2 section 5.26, the following results in an error:
4559 // "Ternary operator applied to void, arrays, or structs containing arrays"
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004560 if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
Corentin Wallez0d959252016-07-12 17:26:32 -04004561 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004562 error(loc, "ternary operator is not allowed for void", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004563 return falseExpression;
Corentin Wallez0d959252016-07-12 17:26:32 -04004564 }
4565
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004566 return TIntermediate::AddTernarySelection(cond, trueExpression, falseExpression, loc);
Olli Etuaho52901742015-04-15 13:42:45 +03004567}
Olli Etuaho49300862015-02-20 14:54:49 +02004568
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004569//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004570// Parse an array of strings using yyparse.
4571//
4572// Returns 0 for success.
4573//
Jamie Madillb98c3a82015-07-23 14:26:04 -04004574int PaParseStrings(size_t count,
4575 const char *const string[],
4576 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05304577 TParseContext *context)
4578{
Yunchao He4f285442017-04-21 12:15:49 +08004579 if ((count == 0) || (string == nullptr))
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004580 return 1;
4581
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004582 if (glslang_initialize(context))
4583 return 1;
4584
alokp@chromium.org408c45e2012-04-05 15:54:43 +00004585 int error = glslang_scan(count, string, length, context);
4586 if (!error)
4587 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004588
alokp@chromium.org73bc2982012-06-19 18:48:05 +00004589 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00004590
alokp@chromium.org6b495712012-06-29 00:06:58 +00004591 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004592}
Jamie Madill45bcc782016-11-07 13:58:48 -05004593
4594} // namespace sh