blob: 8ca734f63d1eae65d6312ba0267c8a839e260e96 [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
Olli Etuaho487b63a2017-05-23 15:55:09 +0300643 if (argTyped->getBasicType() == EbtStruct)
644 {
645 error(line, "a struct cannot be used as a constructor argument for this type",
646 "constructor");
647 return false;
648 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300649 if (argTyped->getType().isArray())
650 {
651 error(line, "constructing from a non-dereferenced array", "constructor");
652 return false;
653 }
654 if (argTyped->getType().isMatrix())
655 {
656 matrixArg = true;
657 }
658
659 size += argTyped->getType().getObjectSize();
660 if (full)
661 {
662 overFull = true;
663 }
Olli Etuaho487b63a2017-05-23 15:55:09 +0300664 if (size >= type.getObjectSize())
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300665 {
666 full = true;
667 }
668 }
669
670 if (type.isMatrix() && matrixArg)
671 {
672 if (arguments->size() != 1)
673 {
674 error(line, "constructing matrix from matrix can only take one argument",
675 "constructor");
676 return false;
677 }
678 }
679 else
680 {
681 if (size != 1 && size < type.getObjectSize())
682 {
683 error(line, "not enough data provided for construction", "constructor");
684 return false;
685 }
686 if (overFull)
687 {
688 error(line, "too many arguments", "constructor");
689 return false;
690 }
691 }
692 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300693
Olli Etuaho8a176262016-08-16 14:23:01 +0300694 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000695}
696
Jamie Madillb98c3a82015-07-23 14:26:04 -0400697// This function checks to see if a void variable has been declared and raise an error message for
698// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000699//
700// returns true in case of an error
701//
Olli Etuaho856c4972016-08-08 11:38:39 +0300702bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400703 const TString &identifier,
704 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000705{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300706 if (type == EbtVoid)
707 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000708 error(line, "illegal use of type 'void'", identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300709 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300710 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000711
Olli Etuaho8a176262016-08-16 14:23:01 +0300712 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000713}
714
Jamie Madillb98c3a82015-07-23 14:26:04 -0400715// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300716// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300717void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000718{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530719 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
720 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000721 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530722 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000723}
724
Jamie Madillb98c3a82015-07-23 14:26:04 -0400725// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300726// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300727void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000728{
Martin Radev4a9cd802016-09-01 16:51:51 +0300729 if (pType.getBasicType() != EbtBool || pType.isAggregate())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530730 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000731 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530732 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000733}
734
jchen10cc2a10e2017-05-03 14:05:12 +0800735bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
736 const TTypeSpecifierNonArray &pType,
737 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000738{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530739 if (pType.type == EbtStruct)
740 {
Martin Radev2cc85b32016-08-05 16:22:53 +0300741 if (ContainsSampler(*pType.userDef))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530742 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000743 std::stringstream reasonStream;
744 reasonStream << reason << " (structure contains a sampler)";
745 std::string reasonStr = reasonStream.str();
746 error(line, reasonStr.c_str(), getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300747 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000748 }
jchen10cc2a10e2017-05-03 14:05:12 +0800749 // only samplers need to be checked from structs, since other opaque types can't be struct
750 // members.
Olli Etuaho8a176262016-08-16 14:23:01 +0300751 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530752 }
jchen10cc2a10e2017-05-03 14:05:12 +0800753 else if (IsOpaqueType(pType.type))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530754 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000755 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300756 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000757 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000758
Olli Etuaho8a176262016-08-16 14:23:01 +0300759 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000760}
761
Olli Etuaho856c4972016-08-08 11:38:39 +0300762void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
763 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400764{
765 if (pType.layoutQualifier.location != -1)
766 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400767 error(line, "location must only be specified for a single input or output variable",
768 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400769 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400770}
771
Olli Etuaho856c4972016-08-08 11:38:39 +0300772void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
773 const TLayoutQualifier &layoutQualifier)
774{
775 if (layoutQualifier.location != -1)
776 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000777 const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs";
778 if (mShaderVersion >= 310)
779 {
780 errorMsg =
781 "invalid layout qualifier: only valid on program inputs, outputs, and uniforms";
782 }
783 error(location, errorMsg, "location");
Olli Etuaho856c4972016-08-08 11:38:39 +0300784 }
785}
786
Martin Radev2cc85b32016-08-05 16:22:53 +0300787void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
788 TQualifier qualifier,
789 const TType &type)
790{
Martin Radev2cc85b32016-08-05 16:22:53 +0300791 ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
jchen10cc2a10e2017-05-03 14:05:12 +0800792 if (IsOpaqueType(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530793 {
jchen10cc2a10e2017-05-03 14:05:12 +0800794 error(line, "opaque types cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000795 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000796}
797
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000798// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300799unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000800{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530801 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000802
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200803 // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
804 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
805 // fold as array size.
806 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000807 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000808 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300809 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000810 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000811
Olli Etuaho856c4972016-08-08 11:38:39 +0300812 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400813
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000814 if (constant->getBasicType() == EbtUInt)
815 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300816 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000817 }
818 else
819 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300820 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000821
Olli Etuaho856c4972016-08-08 11:38:39 +0300822 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000823 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400824 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300825 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000826 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400827
Olli Etuaho856c4972016-08-08 11:38:39 +0300828 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -0400829 }
830
Olli Etuaho856c4972016-08-08 11:38:39 +0300831 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -0400832 {
833 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300834 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400835 }
836
837 // The size of arrays is restricted here to prevent issues further down the
838 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
839 // 4096 registers so this should be reasonable even for aggressively optimizable code.
840 const unsigned int sizeLimit = 65536;
841
Olli Etuaho856c4972016-08-08 11:38:39 +0300842 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -0400843 {
844 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300845 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000846 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300847
848 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000849}
850
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000851// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +0300852bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
853 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000854{
Olli Etuaho8a176262016-08-16 14:23:01 +0300855 if ((elementQualifier.qualifier == EvqAttribute) ||
856 (elementQualifier.qualifier == EvqVertexIn) ||
857 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +0300858 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400859 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300860 TType(elementQualifier).getQualifierString());
861 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000862 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000863
Olli Etuaho8a176262016-08-16 14:23:01 +0300864 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000865}
866
Olli Etuaho8a176262016-08-16 14:23:01 +0300867// See if this element type can be formed into an array.
868bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000869{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000870 //
871 // Can the type be an array?
872 //
Olli Etuaho8a176262016-08-16 14:23:01 +0300873 if (elementType.array)
Jamie Madill06145232015-05-13 13:10:01 -0400874 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300875 error(line, "cannot declare arrays of arrays",
876 TType(elementType).getCompleteString().c_str());
877 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000878 }
Olli Etuahocc36b982015-07-10 14:14:18 +0300879 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
880 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
881 // 4.3.4).
Martin Radev4a9cd802016-09-01 16:51:51 +0300882 if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
Olli Etuaho8a176262016-08-16 14:23:01 +0300883 sh::IsVarying(elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +0300884 {
885 error(line, "cannot declare arrays of structs of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300886 TType(elementType).getCompleteString().c_str());
887 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +0300888 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000889
Olli Etuaho8a176262016-08-16 14:23:01 +0300890 return true;
891}
892
893// Check if this qualified element type can be formed into an array.
894bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
895 const TPublicType &elementType)
896{
897 if (checkIsValidTypeForArray(indexLocation, elementType))
898 {
899 return checkIsValidQualifierForArray(indexLocation, elementType);
900 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000901 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000902}
903
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000904// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +0300905void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
906 const TString &identifier,
907 TPublicType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000908{
Olli Etuaho3739d232015-04-08 12:23:44 +0300909 ASSERT(type != nullptr);
910 if (type->qualifier == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000911 {
912 // Make the qualifier make sense.
Olli Etuaho3739d232015-04-08 12:23:44 +0300913 type->qualifier = EvqTemporary;
914
915 // Generate informative error messages for ESSL1.
916 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400917 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000918 {
Arun Patole7e7e68d2015-05-22 12:02:25 +0530919 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400920 "structures containing arrays may not be declared constant since they cannot be "
921 "initialized",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530922 identifier.c_str());
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000923 }
924 else
925 {
926 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
927 }
Olli Etuaho383b7912016-08-05 11:22:59 +0300928 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000929 }
Olli Etuaho376f1b52015-04-13 13:23:41 +0300930 if (type->isUnsizedArray())
931 {
932 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
Olli Etuaho376f1b52015-04-13 13:23:41 +0300933 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000934}
935
Olli Etuaho2935c582015-04-08 14:32:06 +0300936// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000937// and update the symbol table.
938//
Olli Etuaho2935c582015-04-08 14:32:06 +0300939// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000940//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400941bool TParseContext::declareVariable(const TSourceLoc &line,
942 const TString &identifier,
943 const TType &type,
Olli Etuaho2935c582015-04-08 14:32:06 +0300944 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000945{
Olli Etuaho2935c582015-04-08 14:32:06 +0300946 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000947
Olli Etuaho43364892017-02-13 16:00:12 +0000948 checkBindingIsValid(line, type);
949
Olli Etuaho856c4972016-08-08 11:38:39 +0300950 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000951
Olli Etuaho2935c582015-04-08 14:32:06 +0300952 // gl_LastFragData may be redeclared with a new precision qualifier
953 if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
954 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400955 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
956 symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Olli Etuaho856c4972016-08-08 11:38:39 +0300957 if (static_cast<int>(type.getArraySize()) == maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +0300958 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400959 if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +0300960 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300961 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
Olli Etuaho2935c582015-04-08 14:32:06 +0300962 }
963 }
964 else
965 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400966 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
967 identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +0300968 return false;
969 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000970 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000971
Olli Etuaho8a176262016-08-16 14:23:01 +0300972 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +0300973 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000974
Olli Etuaho2935c582015-04-08 14:32:06 +0300975 (*variable) = new TVariable(&identifier, type);
976 if (!symbolTable.declare(*variable))
977 {
978 error(line, "redefinition", identifier.c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -0400979 *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +0300980 return false;
981 }
982
Olli Etuaho8a176262016-08-16 14:23:01 +0300983 if (!checkIsNonVoid(line, identifier, type.getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +0300984 return false;
985
986 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000987}
988
Martin Radev70866b82016-07-22 15:27:42 +0300989void TParseContext::checkIsParameterQualifierValid(
990 const TSourceLoc &line,
991 const TTypeQualifierBuilder &typeQualifierBuilder,
992 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530993{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000994 TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +0300995
996 if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530997 {
Martin Radev2cc85b32016-08-05 16:22:53 +0300998 checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type);
999 }
1000
1001 if (!IsImage(type->getBasicType()))
1002 {
Olli Etuaho43364892017-02-13 16:00:12 +00001003 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line);
Martin Radev2cc85b32016-08-05 16:22:53 +03001004 }
1005 else
1006 {
1007 type->setMemoryQualifier(typeQualifier.memoryQualifier);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001008 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001009
Martin Radev70866b82016-07-22 15:27:42 +03001010 type->setQualifier(typeQualifier.qualifier);
1011
1012 if (typeQualifier.precision != EbpUndefined)
1013 {
1014 type->setPrecision(typeQualifier.precision);
1015 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001016}
1017
Olli Etuaho856c4972016-08-08 11:38:39 +03001018bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001019{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001020 const TExtensionBehavior &extBehavior = extensionBehavior();
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001021 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
Arun Patole7e7e68d2015-05-22 12:02:25 +05301022 if (iter == extBehavior.end())
1023 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001024 error(line, "extension is not supported", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001025 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001026 }
zmo@google.comf5450912011-09-09 01:37:19 +00001027 // In GLSL ES, an extension's default behavior is "disable".
Arun Patole7e7e68d2015-05-22 12:02:25 +05301028 if (iter->second == EBhDisable || iter->second == EBhUndefined)
1029 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00001030 // TODO(oetuaho@nvidia.com): This is slightly hacky. Might be better if symbols could be
1031 // associated with more than one extension.
1032 if (extension == "GL_OVR_multiview")
1033 {
1034 return checkCanUseExtension(line, "GL_OVR_multiview2");
1035 }
Olli Etuaho4de340a2016-12-16 09:32:03 +00001036 error(line, "extension is disabled", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001037 return false;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001038 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301039 if (iter->second == EBhWarn)
1040 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001041 warning(line, "extension is being used", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001042 return true;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001043 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001044
Olli Etuaho8a176262016-08-16 14:23:01 +03001045 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001046}
1047
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001048// ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause
1049// compile-time or link-time errors are the same whether or not the declaration is empty".
1050// This function implements all the checks that are done on qualifiers regardless of if the
1051// declaration is empty.
1052void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier,
1053 const sh::TLayoutQualifier &layoutQualifier,
1054 const TSourceLoc &location)
1055{
1056 if (qualifier == EvqShared && !layoutQualifier.isEmpty())
1057 {
1058 error(location, "Shared memory declarations cannot have layout specified", "layout");
1059 }
1060
1061 if (layoutQualifier.matrixPacking != EmpUnspecified)
1062 {
1063 error(location, "layout qualifier only valid for interface blocks",
1064 getMatrixPackingString(layoutQualifier.matrixPacking));
1065 return;
1066 }
1067
1068 if (layoutQualifier.blockStorage != EbsUnspecified)
1069 {
1070 error(location, "layout qualifier only valid for interface blocks",
1071 getBlockStorageString(layoutQualifier.blockStorage));
1072 return;
1073 }
1074
1075 if (qualifier == EvqFragmentOut)
1076 {
1077 if (layoutQualifier.location != -1 && layoutQualifier.yuv == true)
1078 {
1079 error(location, "invalid layout qualifier combination", "yuv");
1080 return;
1081 }
1082 }
1083 else
1084 {
1085 checkYuvIsNotSpecified(location, layoutQualifier.yuv);
1086 }
1087
1088 bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut;
1089 if (mShaderVersion >= 310 && qualifier == EvqUniform)
1090 {
1091 canHaveLocation = true;
1092 // We're not checking whether the uniform location is in range here since that depends on
1093 // the type of the variable.
1094 // The type can only be fully determined for non-empty declarations.
1095 }
1096 if (!canHaveLocation)
1097 {
1098 checkLocationIsNotSpecified(location, layoutQualifier);
1099 }
1100}
1101
Martin Radevb8b01222016-11-20 23:25:53 +02001102void TParseContext::emptyDeclarationErrorCheck(const TPublicType &publicType,
1103 const TSourceLoc &location)
1104{
1105 if (publicType.isUnsizedArray())
1106 {
1107 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1108 // error. It is assumed that this applies to empty declarations as well.
1109 error(location, "empty array declaration needs to specify a size", "");
1110 }
Martin Radevb8b01222016-11-20 23:25:53 +02001111}
1112
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001113// These checks are done for all declarations that are non-empty. They're done for non-empty
1114// declarations starting a declarator list, and declarators that follow an empty declaration.
1115void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
1116 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -04001117{
Olli Etuahofa33d582015-04-09 14:33:12 +03001118 switch (publicType.qualifier)
1119 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001120 case EvqVaryingIn:
1121 case EvqVaryingOut:
1122 case EvqAttribute:
1123 case EvqVertexIn:
1124 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +03001125 case EvqComputeIn:
Martin Radev4a9cd802016-09-01 16:51:51 +03001126 if (publicType.getBasicType() == EbtStruct)
Jamie Madillb98c3a82015-07-23 14:26:04 -04001127 {
1128 error(identifierLocation, "cannot be used with a structure",
1129 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +03001130 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001131 }
Olli Etuahofa33d582015-04-09 14:33:12 +03001132
Jamie Madillb98c3a82015-07-23 14:26:04 -04001133 default:
1134 break;
Olli Etuahofa33d582015-04-09 14:33:12 +03001135 }
jchen10cc2a10e2017-05-03 14:05:12 +08001136 std::string reason(getBasicString(publicType.getBasicType()));
1137 reason += "s must be uniform";
Jamie Madillb98c3a82015-07-23 14:26:04 -04001138 if (publicType.qualifier != EvqUniform &&
jchen10cc2a10e2017-05-03 14:05:12 +08001139 !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str()))
Martin Radev2cc85b32016-08-05 16:22:53 +03001140 {
1141 return;
1142 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001143
Andrei Volykhina5527072017-03-22 16:46:30 +03001144 if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal &&
1145 publicType.qualifier != EvqConst) &&
1146 publicType.getBasicType() == EbtYuvCscStandardEXT)
1147 {
1148 error(identifierLocation, "cannot be used with a yuvCscStandardEXT",
1149 getQualifierString(publicType.qualifier));
1150 return;
1151 }
1152
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001153 if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform)
1154 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001155 // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized.
1156 // But invalid shaders may still reach here with an unsized array declaration.
1157 if (!publicType.isUnsizedArray())
1158 {
1159 TType type(publicType);
1160 checkUniformLocationInRange(identifierLocation, type.getLocationCount(),
1161 publicType.layoutQualifier);
1162 }
1163 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001164
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001165 // check for layout qualifier issues
1166 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
Andrei Volykhina5527072017-03-22 16:46:30 +03001167
Martin Radev2cc85b32016-08-05 16:22:53 +03001168 if (IsImage(publicType.getBasicType()))
1169 {
1170
1171 switch (layoutQualifier.imageInternalFormat)
1172 {
1173 case EiifRGBA32F:
1174 case EiifRGBA16F:
1175 case EiifR32F:
1176 case EiifRGBA8:
1177 case EiifRGBA8_SNORM:
1178 if (!IsFloatImage(publicType.getBasicType()))
1179 {
1180 error(identifierLocation,
1181 "internal image format requires a floating image type",
1182 getBasicString(publicType.getBasicType()));
1183 return;
1184 }
1185 break;
1186 case EiifRGBA32I:
1187 case EiifRGBA16I:
1188 case EiifRGBA8I:
1189 case EiifR32I:
1190 if (!IsIntegerImage(publicType.getBasicType()))
1191 {
1192 error(identifierLocation,
1193 "internal image format requires an integer image type",
1194 getBasicString(publicType.getBasicType()));
1195 return;
1196 }
1197 break;
1198 case EiifRGBA32UI:
1199 case EiifRGBA16UI:
1200 case EiifRGBA8UI:
1201 case EiifR32UI:
1202 if (!IsUnsignedImage(publicType.getBasicType()))
1203 {
1204 error(identifierLocation,
1205 "internal image format requires an unsigned image type",
1206 getBasicString(publicType.getBasicType()));
1207 return;
1208 }
1209 break;
1210 case EiifUnspecified:
1211 error(identifierLocation, "layout qualifier", "No image internal format specified");
1212 return;
1213 default:
1214 error(identifierLocation, "layout qualifier", "unrecognized token");
1215 return;
1216 }
1217
1218 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
1219 switch (layoutQualifier.imageInternalFormat)
1220 {
1221 case EiifR32F:
1222 case EiifR32I:
1223 case EiifR32UI:
1224 break;
1225 default:
1226 if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
1227 {
1228 error(identifierLocation, "layout qualifier",
1229 "Except for images with the r32f, r32i and r32ui format qualifiers, "
1230 "image variables must be qualified readonly and/or writeonly");
1231 return;
1232 }
1233 break;
1234 }
1235 }
1236 else
1237 {
Olli Etuaho43364892017-02-13 16:00:12 +00001238 checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat);
Martin Radev2cc85b32016-08-05 16:22:53 +03001239
Olli Etuaho43364892017-02-13 16:00:12 +00001240 checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
1241 }
1242}
Martin Radev2cc85b32016-08-05 16:22:53 +03001243
Olli Etuaho43364892017-02-13 16:00:12 +00001244void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type)
1245{
1246 TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
1247 int arraySize = type.isArray() ? type.getArraySize() : 1;
1248 if (IsImage(type.getBasicType()))
1249 {
1250 checkImageBindingIsValid(identifierLocation, layoutQualifier.binding, arraySize);
1251 }
1252 else if (IsSampler(type.getBasicType()))
1253 {
1254 checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding, arraySize);
1255 }
1256 else
1257 {
1258 ASSERT(!IsOpaqueType(type.getBasicType()));
1259 checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
Martin Radev2cc85b32016-08-05 16:22:53 +03001260 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001261}
1262
Olli Etuaho856c4972016-08-08 11:38:39 +03001263void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1264 const TString &layoutQualifierName,
1265 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001266{
1267
1268 if (mShaderVersion < versionRequired)
1269 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001270 error(location, "invalid layout qualifier: not supported", layoutQualifierName.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03001271 }
1272}
1273
Olli Etuaho856c4972016-08-08 11:38:39 +03001274bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1275 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001276{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001277 const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
Martin Radev802abe02016-08-04 17:48:32 +03001278 for (size_t i = 0u; i < localSize.size(); ++i)
1279 {
1280 if (localSize[i] != -1)
1281 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001282 error(location,
1283 "invalid layout qualifier: only valid when used with 'in' in a compute shader "
1284 "global layout declaration",
1285 getWorkGroupSizeString(i));
Olli Etuaho8a176262016-08-16 14:23:01 +03001286 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001287 }
1288 }
1289
Olli Etuaho8a176262016-08-16 14:23:01 +03001290 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001291}
1292
Olli Etuaho43364892017-02-13 16:00:12 +00001293void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
Martin Radev2cc85b32016-08-05 16:22:53 +03001294 TLayoutImageInternalFormat internalFormat)
1295{
1296 if (internalFormat != EiifUnspecified)
1297 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001298 error(location, "invalid layout qualifier: only valid when used with images",
1299 getImageInternalFormatString(internalFormat));
Martin Radev2cc85b32016-08-05 16:22:53 +03001300 }
Olli Etuaho43364892017-02-13 16:00:12 +00001301}
1302
1303void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
1304{
1305 if (binding != -1)
1306 {
1307 error(location,
1308 "invalid layout qualifier: only valid when used with opaque types or blocks",
1309 "binding");
1310 }
1311}
1312
1313void TParseContext::checkImageBindingIsValid(const TSourceLoc &location, int binding, int arraySize)
1314{
1315 // Expects arraySize to be 1 when setting binding for only a single variable.
1316 if (binding >= 0 && binding + arraySize > mMaxImageUnits)
1317 {
1318 error(location, "image binding greater than gl_MaxImageUnits", "binding");
1319 }
1320}
1321
1322void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location,
1323 int binding,
1324 int arraySize)
1325{
1326 // Expects arraySize to be 1 when setting binding for only a single variable.
1327 if (binding >= 0 && binding + arraySize > mMaxCombinedTextureImageUnits)
1328 {
1329 error(location, "sampler binding greater than maximum texture units", "binding");
1330 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001331}
1332
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001333void TParseContext::checkUniformLocationInRange(const TSourceLoc &location,
1334 int objectLocationCount,
1335 const TLayoutQualifier &layoutQualifier)
1336{
1337 int loc = layoutQualifier.location;
1338 if (loc >= 0 && loc + objectLocationCount > mMaxUniformLocations)
1339 {
1340 error(location, "Uniform location out of range", "location");
1341 }
1342}
1343
Andrei Volykhina5527072017-03-22 16:46:30 +03001344void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv)
1345{
1346 if (yuv != false)
1347 {
1348 error(location, "invalid layout qualifier: only valid on program outputs", "yuv");
1349 }
1350}
1351
Olli Etuaho383b7912016-08-05 11:22:59 +03001352void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
Olli Etuaho856c4972016-08-08 11:38:39 +03001353 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001354{
1355 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1356 {
1357 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1358 if (qual == EvqOut || qual == EvqInOut)
1359 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001360 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho8a176262016-08-16 14:23:01 +03001361 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001362 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001363 error(argument->getLine(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00001364 "Constant value cannot be passed for 'out' or 'inout' parameters.",
Olli Etuahoec9232b2017-03-27 17:01:37 +03001365 fnCall->getFunctionSymbolInfo()->getName().c_str());
Olli Etuaho383b7912016-08-05 11:22:59 +03001366 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001367 }
1368 }
1369 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001370}
1371
Martin Radev70866b82016-07-22 15:27:42 +03001372void TParseContext::checkInvariantVariableQualifier(bool invariant,
1373 const TQualifier qualifier,
1374 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001375{
Martin Radev70866b82016-07-22 15:27:42 +03001376 if (!invariant)
1377 return;
1378
1379 if (mShaderVersion < 300)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001380 {
Martin Radev70866b82016-07-22 15:27:42 +03001381 // input variables in the fragment shader can be also qualified as invariant
1382 if (!sh::CanBeInvariantESSL1(qualifier))
1383 {
1384 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1385 }
1386 }
1387 else
1388 {
1389 if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
1390 {
1391 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1392 }
Olli Etuaho37ad4742015-04-27 13:18:50 +03001393 }
1394}
1395
Arun Patole7e7e68d2015-05-22 12:02:25 +05301396bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001397{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001398 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001399 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1400 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001401}
1402
Arun Patole7e7e68d2015-05-22 12:02:25 +05301403bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001404{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001405 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001406}
1407
Jamie Madillb98c3a82015-07-23 14:26:04 -04001408void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1409 const char *extName,
1410 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001411{
1412 pp::SourceLocation srcLoc;
1413 srcLoc.file = loc.first_file;
1414 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001415 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001416}
1417
Jamie Madillb98c3a82015-07-23 14:26:04 -04001418void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1419 const char *name,
1420 const char *value,
1421 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001422{
1423 pp::SourceLocation srcLoc;
1424 srcLoc.file = loc.first_file;
1425 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001426 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001427}
1428
Martin Radev4c4c8e72016-08-04 12:25:34 +03001429sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
Martin Radev802abe02016-08-04 17:48:32 +03001430{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001431 sh::WorkGroupSize result;
Martin Radev802abe02016-08-04 17:48:32 +03001432 for (size_t i = 0u; i < result.size(); ++i)
1433 {
1434 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1435 {
1436 result[i] = 1;
1437 }
1438 else
1439 {
1440 result[i] = mComputeShaderLocalSize[i];
1441 }
1442 }
1443 return result;
1444}
1445
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001446/////////////////////////////////////////////////////////////////////////////////
1447//
1448// Non-Errors.
1449//
1450/////////////////////////////////////////////////////////////////////////////////
1451
Jamie Madill5c097022014-08-20 16:38:32 -04001452const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1453 const TString *name,
1454 const TSymbol *symbol)
1455{
Yunchao Hed7297bf2017-04-19 15:27:10 +08001456 const TVariable *variable = nullptr;
Jamie Madill5c097022014-08-20 16:38:32 -04001457
1458 if (!symbol)
1459 {
1460 error(location, "undeclared identifier", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001461 }
1462 else if (!symbol->isVariable())
1463 {
1464 error(location, "variable expected", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001465 }
1466 else
1467 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001468 variable = static_cast<const TVariable *>(symbol);
Jamie Madill5c097022014-08-20 16:38:32 -04001469
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001470 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
Olli Etuaho383b7912016-08-05 11:22:59 +03001471 !variable->getExtension().empty())
Jamie Madill5c097022014-08-20 16:38:32 -04001472 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001473 checkCanUseExtension(location, variable->getExtension());
Jamie Madill5c097022014-08-20 16:38:32 -04001474 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001475
1476 // Reject shaders using both gl_FragData and gl_FragColor
1477 TQualifier qualifier = variable->getType().getQualifier();
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001478 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001479 {
1480 mUsesFragData = true;
1481 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001482 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001483 {
1484 mUsesFragColor = true;
1485 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001486 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1487 {
1488 mUsesSecondaryOutputs = true;
1489 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001490
1491 // This validation is not quite correct - it's only an error to write to
1492 // both FragData and FragColor. For simplicity, and because users shouldn't
1493 // be rewarded for reading from undefined varaibles, return an error
1494 // if they are both referenced, rather than assigned.
1495 if (mUsesFragData && mUsesFragColor)
1496 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001497 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1498 if (mUsesSecondaryOutputs)
1499 {
1500 errorMessage =
1501 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1502 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1503 }
1504 error(location, errorMessage, name->c_str());
Jamie Madill14e95b32015-05-07 10:10:41 -04001505 }
Martin Radevb0883602016-08-04 17:48:58 +03001506
1507 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1508 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1509 qualifier == EvqWorkGroupSize)
1510 {
1511 error(location,
1512 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1513 "gl_WorkGroupSize");
1514 }
Jamie Madill5c097022014-08-20 16:38:32 -04001515 }
1516
1517 if (!variable)
1518 {
1519 TType type(EbtFloat, EbpUndefined);
1520 TVariable *fakeVariable = new TVariable(name, type);
1521 symbolTable.declare(fakeVariable);
1522 variable = fakeVariable;
1523 }
1524
1525 return variable;
1526}
1527
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001528TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1529 const TString *name,
1530 const TSymbol *symbol)
1531{
1532 const TVariable *variable = getNamedVariable(location, name, symbol);
1533
Olli Etuaho09b04a22016-12-15 13:30:26 +00001534 if (variable->getType().getQualifier() == EvqViewIDOVR && IsWebGLBasedSpec(mShaderSpec) &&
1535 mShaderType == GL_FRAGMENT_SHADER && !isExtensionEnabled("GL_OVR_multiview2"))
1536 {
1537 // WEBGL_multiview spec
1538 error(location, "Need to enable OVR_multiview2 to use gl_ViewID_OVR in fragment shader",
1539 "gl_ViewID_OVR");
1540 }
1541
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001542 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001543 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001544 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001545 return intermediate.addConstantUnion(constArray, variable->getType(), location);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001546 }
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001547 else if (variable->getType().getQualifier() == EvqWorkGroupSize &&
1548 mComputeShaderLocalSizeDeclared)
1549 {
1550 // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
1551 // needs to be added to the AST as a constant and not as a symbol.
1552 sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
1553 TConstantUnion *constArray = new TConstantUnion[3];
1554 for (size_t i = 0; i < 3; ++i)
1555 {
1556 constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
1557 }
1558
1559 ASSERT(variable->getType().getBasicType() == EbtUInt);
1560 ASSERT(variable->getType().getObjectSize() == 3);
1561
1562 TType type(variable->getType());
1563 type.setQualifier(EvqConst);
1564 return intermediate.addConstantUnion(constArray, type, location);
1565 }
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001566 else
1567 {
1568 return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
1569 variable->getType(), location);
1570 }
1571}
1572
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001573//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001574// Initializers show up in several places in the grammar. Have one set of
1575// code to handle them here.
1576//
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001577// Returns true on error, false if no error
1578//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001579bool TParseContext::executeInitializer(const TSourceLoc &line,
1580 const TString &identifier,
1581 const TPublicType &pType,
1582 TIntermTyped *initializer,
Olli Etuaho13389b62016-10-16 11:48:18 +01001583 TIntermBinary **initNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001584{
Olli Etuaho13389b62016-10-16 11:48:18 +01001585 ASSERT(initNode != nullptr);
1586 ASSERT(*initNode == nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001587 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001588
Olli Etuaho2935c582015-04-08 14:32:06 +03001589 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001590 if (type.isUnsizedArray())
1591 {
Olli Etuaho02bd82c2016-11-03 10:29:43 +00001592 // We have not checked yet whether the initializer actually is an array or not.
1593 if (initializer->isArray())
1594 {
1595 type.setArraySize(initializer->getArraySize());
1596 }
1597 else
1598 {
1599 // Having a non-array initializer for an unsized array will result in an error later,
1600 // so we don't generate an error message here.
1601 type.setArraySize(1u);
1602 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03001603 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001604 if (!declareVariable(line, identifier, type, &variable))
1605 {
1606 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001607 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001608
Olli Etuahob0c645e2015-05-12 14:25:36 +03001609 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001610 if (symbolTable.atGlobalLevel() &&
1611 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001612 {
1613 // Error message does not completely match behavior with ESSL 1.00, but
1614 // we want to steer developers towards only using constant expressions.
1615 error(line, "global variable initializers must be constant expressions", "=");
1616 return true;
1617 }
1618 if (globalInitWarning)
1619 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001620 warning(
1621 line,
1622 "global variable initializers should be constant expressions "
1623 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1624 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001625 }
1626
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001627 //
1628 // identifier must be of type constant, a global, or a temporary
1629 //
1630 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301631 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1632 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001633 error(line, " cannot initialize this type of qualifier ",
1634 variable->getType().getQualifierString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001635 return true;
1636 }
1637 //
1638 // test for and propagate constant
1639 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001640
Arun Patole7e7e68d2015-05-22 12:02:25 +05301641 if (qualifier == EvqConst)
1642 {
1643 if (qualifier != initializer->getType().getQualifier())
1644 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001645 std::stringstream reasonStream;
1646 reasonStream << "assigning non-constant to '" << variable->getType().getCompleteString()
1647 << "'";
1648 std::string reason = reasonStream.str();
1649 error(line, reason.c_str(), "=");
alokp@chromium.org58e54292010-08-24 21:40:03 +00001650 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001651 return true;
1652 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301653 if (type != initializer->getType())
1654 {
1655 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001656 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001657 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001658 return true;
1659 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001660
1661 // Save the constant folded value to the variable if possible. For example array
1662 // initializers are not folded, since that way copying the array literal to multiple places
1663 // in the shader is avoided.
1664 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1665 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301666 if (initializer->getAsConstantUnion())
1667 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001668 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuaho13389b62016-10-16 11:48:18 +01001669 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001670 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301671 }
1672 else if (initializer->getAsSymbolNode())
1673 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001674 const TSymbol *symbol =
1675 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1676 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001677
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001678 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001679 if (constArray)
1680 {
1681 variable->shareConstPointer(constArray);
Olli Etuaho13389b62016-10-16 11:48:18 +01001682 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001683 return false;
1684 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001685 }
1686 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001687
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001688 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1689 variable->getUniqueId(), variable->getName(), variable->getType(), line);
Olli Etuaho13389b62016-10-16 11:48:18 +01001690 *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1691 if (*initNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001692 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001693 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1694 return true;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001695 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001696
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001697 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001698}
1699
Olli Etuaho0e3aee32016-10-27 12:56:38 +01001700void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
1701{
1702 checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
1703 typeSpecifier->getBasicType());
1704
1705 if (mShaderVersion < 300 && typeSpecifier->array)
1706 {
1707 error(typeSpecifier->getLine(), "not supported", "first-class array");
1708 typeSpecifier->clearArrayness();
1709 }
1710}
1711
Martin Radev70866b82016-07-22 15:27:42 +03001712TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301713 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001714{
Olli Etuaho77ba4082016-12-16 12:01:18 +00001715 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001716
Martin Radev70866b82016-07-22 15:27:42 +03001717 TPublicType returnType = typeSpecifier;
1718 returnType.qualifier = typeQualifier.qualifier;
1719 returnType.invariant = typeQualifier.invariant;
1720 returnType.layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03001721 returnType.memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03001722 returnType.precision = typeSpecifier.precision;
1723
1724 if (typeQualifier.precision != EbpUndefined)
1725 {
1726 returnType.precision = typeQualifier.precision;
1727 }
1728
Martin Radev4a9cd802016-09-01 16:51:51 +03001729 checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
1730 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03001731
Martin Radev4a9cd802016-09-01 16:51:51 +03001732 checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
1733 typeSpecifier.getLine());
Martin Radev70866b82016-07-22 15:27:42 +03001734
Martin Radev4a9cd802016-09-01 16:51:51 +03001735 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001736
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001737 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001738 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001739 if (typeSpecifier.array)
1740 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001741 error(typeSpecifier.getLine(), "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001742 returnType.clearArrayness();
1743 }
1744
Martin Radev70866b82016-07-22 15:27:42 +03001745 if (returnType.qualifier == EvqAttribute &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001746 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001747 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001748 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001749 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001750 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001751
Martin Radev70866b82016-07-22 15:27:42 +03001752 if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001753 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001754 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001755 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001756 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001757 }
1758 }
1759 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001760 {
Martin Radev70866b82016-07-22 15:27:42 +03001761 if (!returnType.layoutQualifier.isEmpty())
Olli Etuahoabb0c382015-07-13 12:01:12 +03001762 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001763 checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03001764 }
Martin Radev70866b82016-07-22 15:27:42 +03001765 if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
1766 returnType.qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001767 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001768 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
1769 typeSpecifier.getLine());
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001770 }
Martin Radev70866b82016-07-22 15:27:42 +03001771 if (returnType.qualifier == EvqComputeIn)
Martin Radev802abe02016-08-04 17:48:32 +03001772 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001773 error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
Martin Radev802abe02016-08-04 17:48:32 +03001774 "in");
Martin Radev802abe02016-08-04 17:48:32 +03001775 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001776 }
1777
1778 return returnType;
1779}
1780
Olli Etuaho856c4972016-08-08 11:38:39 +03001781void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1782 const TPublicType &type,
1783 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03001784{
1785 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
Martin Radev4a9cd802016-09-01 16:51:51 +03001786 if (type.getBasicType() == EbtBool)
Olli Etuahocc36b982015-07-10 14:14:18 +03001787 {
1788 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001789 }
1790
1791 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1792 switch (qualifier)
1793 {
1794 case EvqVertexIn:
1795 // ESSL 3.00 section 4.3.4
1796 if (type.array)
1797 {
1798 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001799 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001800 // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03001801 return;
1802 case EvqFragmentOut:
1803 // ESSL 3.00 section 4.3.6
Martin Radev4a9cd802016-09-01 16:51:51 +03001804 if (type.typeSpecifierNonArray.isMatrix())
Olli Etuahocc36b982015-07-10 14:14:18 +03001805 {
1806 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001807 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001808 // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03001809 return;
1810 default:
1811 break;
1812 }
1813
1814 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1815 // restrictions.
1816 bool typeContainsIntegers =
Martin Radev4a9cd802016-09-01 16:51:51 +03001817 (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
1818 type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
Olli Etuahocc36b982015-07-10 14:14:18 +03001819 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1820 {
1821 error(qualifierLocation, "must use 'flat' interpolation here",
1822 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001823 }
1824
Martin Radev4a9cd802016-09-01 16:51:51 +03001825 if (type.getBasicType() == EbtStruct)
Olli Etuahocc36b982015-07-10 14:14:18 +03001826 {
1827 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1828 // These restrictions are only implied by the ESSL 3.00 spec, but
1829 // the ESSL 3.10 spec lists these restrictions explicitly.
1830 if (type.array)
1831 {
1832 error(qualifierLocation, "cannot be an array of structures",
1833 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001834 }
1835 if (type.isStructureContainingArrays())
1836 {
1837 error(qualifierLocation, "cannot be a structure containing an array",
1838 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001839 }
1840 if (type.isStructureContainingType(EbtStruct))
1841 {
1842 error(qualifierLocation, "cannot be a structure containing a structure",
1843 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001844 }
1845 if (type.isStructureContainingType(EbtBool))
1846 {
1847 error(qualifierLocation, "cannot be a structure containing a bool",
1848 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001849 }
1850 }
1851}
1852
Martin Radev2cc85b32016-08-05 16:22:53 +03001853void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
1854{
1855 if (qualifier.getType() == QtStorage)
1856 {
1857 const TStorageQualifierWrapper &storageQualifier =
1858 static_cast<const TStorageQualifierWrapper &>(qualifier);
1859 if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
1860 !symbolTable.atGlobalLevel())
1861 {
1862 error(storageQualifier.getLine(),
1863 "Local variables can only use the const storage qualifier.",
1864 storageQualifier.getQualifierString().c_str());
1865 }
1866 }
1867}
1868
Olli Etuaho43364892017-02-13 16:00:12 +00001869void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
Martin Radev2cc85b32016-08-05 16:22:53 +03001870 const TSourceLoc &location)
1871{
1872 if (memoryQualifier.readonly)
1873 {
1874 error(location, "Only allowed with images.", "readonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03001875 }
1876 if (memoryQualifier.writeonly)
1877 {
1878 error(location, "Only allowed with images.", "writeonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03001879 }
Martin Radev049edfa2016-11-11 14:35:37 +02001880 if (memoryQualifier.coherent)
1881 {
1882 error(location, "Only allowed with images.", "coherent");
Martin Radev049edfa2016-11-11 14:35:37 +02001883 }
1884 if (memoryQualifier.restrictQualifier)
1885 {
1886 error(location, "Only allowed with images.", "restrict");
Martin Radev049edfa2016-11-11 14:35:37 +02001887 }
1888 if (memoryQualifier.volatileQualifier)
1889 {
1890 error(location, "Only allowed with images.", "volatile");
Martin Radev049edfa2016-11-11 14:35:37 +02001891 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001892}
1893
Olli Etuaho13389b62016-10-16 11:48:18 +01001894TIntermDeclaration *TParseContext::parseSingleDeclaration(
1895 TPublicType &publicType,
1896 const TSourceLoc &identifierOrTypeLocation,
1897 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04001898{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001899 TType type(publicType);
1900 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
1901 mDirectiveHandler.pragma().stdgl.invariantAll)
1902 {
1903 TQualifier qualifier = type.getQualifier();
1904
1905 // The directive handler has already taken care of rejecting invalid uses of this pragma
1906 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
1907 // affected variable declarations:
1908 //
1909 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
1910 // elsewhere, in TranslatorGLSL.)
1911 //
1912 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
1913 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
1914 // the way this is currently implemented we have to enable this compiler option before
1915 // parsing the shader and determining the shading language version it uses. If this were
1916 // implemented as a post-pass, the workaround could be more targeted.
1917 //
1918 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
1919 // the specification, but there are desktop OpenGL drivers that expect that this is the
1920 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
1921 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
1922 {
1923 type.setInvariant(true);
1924 }
1925 }
1926
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001927 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
1928 identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001929
Olli Etuahobab4c082015-04-24 16:38:49 +03001930 bool emptyDeclaration = (identifier == "");
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001931 mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration;
Olli Etuahofa33d582015-04-09 14:33:12 +03001932
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001933 TIntermSymbol *symbol = nullptr;
Olli Etuahobab4c082015-04-24 16:38:49 +03001934 if (emptyDeclaration)
1935 {
Martin Radevb8b01222016-11-20 23:25:53 +02001936 emptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001937 // In most cases we don't need to create a symbol node for an empty declaration.
1938 // But if the empty declaration is declaring a struct type, the symbol node will store that.
1939 if (type.getBasicType() == EbtStruct)
1940 {
1941 symbol = intermediate.addSymbol(0, "", type, identifierOrTypeLocation);
1942 }
Olli Etuahobab4c082015-04-24 16:38:49 +03001943 }
1944 else
Jamie Madill60ed9812013-06-06 11:56:46 -04001945 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001946 nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001947
Olli Etuaho856c4972016-08-08 11:38:39 +03001948 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001949
Olli Etuaho2935c582015-04-08 14:32:06 +03001950 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001951 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001952
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001953 if (variable)
Olli Etuaho13389b62016-10-16 11:48:18 +01001954 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001955 symbol = intermediate.addSymbol(variable->getUniqueId(), identifier, type,
1956 identifierOrTypeLocation);
Olli Etuaho13389b62016-10-16 11:48:18 +01001957 }
Jamie Madill60ed9812013-06-06 11:56:46 -04001958 }
1959
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001960 TIntermDeclaration *declaration = new TIntermDeclaration();
1961 declaration->setLine(identifierOrTypeLocation);
1962 if (symbol)
1963 {
1964 declaration->appendDeclarator(symbol);
1965 }
Olli Etuaho13389b62016-10-16 11:48:18 +01001966 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04001967}
1968
Olli Etuaho13389b62016-10-16 11:48:18 +01001969TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1970 const TSourceLoc &identifierLocation,
1971 const TString &identifier,
1972 const TSourceLoc &indexLocation,
1973 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04001974{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001975 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03001976
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001977 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
1978 identifierLocation);
1979
1980 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001981
Olli Etuaho856c4972016-08-08 11:38:39 +03001982 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001983
Olli Etuaho8a176262016-08-16 14:23:01 +03001984 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001985
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001986 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001987
Olli Etuaho856c4972016-08-08 11:38:39 +03001988 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001989 // Make the type an array even if size check failed.
1990 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1991 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04001992
Olli Etuaho2935c582015-04-08 14:32:06 +03001993 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001994 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001995
Olli Etuaho13389b62016-10-16 11:48:18 +01001996 TIntermDeclaration *declaration = new TIntermDeclaration();
1997 declaration->setLine(identifierLocation);
1998
Olli Etuahoe7847b02015-03-16 11:56:12 +02001999 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002000 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002001 {
Jamie Madill60ed9812013-06-06 11:56:46 -04002002 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002003 declaration->appendDeclarator(symbol);
2004 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002005
Olli Etuaho13389b62016-10-16 11:48:18 +01002006 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002007}
2008
Olli Etuaho13389b62016-10-16 11:48:18 +01002009TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
2010 const TSourceLoc &identifierLocation,
2011 const TString &identifier,
2012 const TSourceLoc &initLocation,
2013 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04002014{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002015 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002016
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002017 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2018 identifierLocation);
2019
2020 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002021
Olli Etuaho13389b62016-10-16 11:48:18 +01002022 TIntermDeclaration *declaration = new TIntermDeclaration();
2023 declaration->setLine(identifierLocation);
2024
2025 TIntermBinary *initNode = nullptr;
2026 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04002027 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002028 if (initNode)
2029 {
2030 declaration->appendDeclarator(initNode);
2031 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002032 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002033 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002034}
2035
Olli Etuaho13389b62016-10-16 11:48:18 +01002036TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
Jamie Madillb98c3a82015-07-23 14:26:04 -04002037 TPublicType &publicType,
2038 const TSourceLoc &identifierLocation,
2039 const TString &identifier,
2040 const TSourceLoc &indexLocation,
2041 TIntermTyped *indexExpression,
2042 const TSourceLoc &initLocation,
2043 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002044{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002045 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002046
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002047 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2048 identifierLocation);
2049
2050 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002051
Olli Etuaho8a176262016-08-16 14:23:01 +03002052 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002053
2054 TPublicType arrayType(publicType);
2055
Olli Etuaho856c4972016-08-08 11:38:39 +03002056 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002057 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2058 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002059 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002060 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002061 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002062 }
2063 // Make the type an array even if size check failed.
2064 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2065 arrayType.setArraySize(size);
2066
Olli Etuaho13389b62016-10-16 11:48:18 +01002067 TIntermDeclaration *declaration = new TIntermDeclaration();
2068 declaration->setLine(identifierLocation);
2069
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002070 // initNode will correspond to the whole of "type b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002071 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002072 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2073 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002074 if (initNode)
2075 {
2076 declaration->appendDeclarator(initNode);
2077 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002078 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002079
2080 return declaration;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002081}
2082
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002083TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
Martin Radev70866b82016-07-22 15:27:42 +03002084 const TTypeQualifierBuilder &typeQualifierBuilder,
2085 const TSourceLoc &identifierLoc,
2086 const TString *identifier,
2087 const TSymbol *symbol)
Jamie Madill47e3ec02014-08-20 16:38:33 -04002088{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002089 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002090
Martin Radev70866b82016-07-22 15:27:42 +03002091 if (!typeQualifier.invariant)
2092 {
2093 error(identifierLoc, "Expected invariant", identifier->c_str());
2094 return nullptr;
2095 }
2096 if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
2097 {
2098 return nullptr;
2099 }
Jamie Madill47e3ec02014-08-20 16:38:33 -04002100 if (!symbol)
2101 {
2102 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002103 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04002104 }
Martin Radev70866b82016-07-22 15:27:42 +03002105 if (!IsQualifierUnspecified(typeQualifier.qualifier))
Jamie Madill47e3ec02014-08-20 16:38:33 -04002106 {
Martin Radev70866b82016-07-22 15:27:42 +03002107 error(identifierLoc, "invariant declaration specifies qualifier",
2108 getQualifierString(typeQualifier.qualifier));
Jamie Madill47e3ec02014-08-20 16:38:33 -04002109 }
Martin Radev70866b82016-07-22 15:27:42 +03002110 if (typeQualifier.precision != EbpUndefined)
2111 {
2112 error(identifierLoc, "invariant declaration specifies precision",
2113 getPrecisionString(typeQualifier.precision));
2114 }
2115 if (!typeQualifier.layoutQualifier.isEmpty())
2116 {
2117 error(identifierLoc, "invariant declaration specifies layout", "'layout'");
2118 }
2119
2120 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
2121 ASSERT(variable);
2122 const TType &type = variable->getType();
2123
2124 checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
2125 typeQualifier.line);
Olli Etuaho43364892017-02-13 16:00:12 +00002126 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev70866b82016-07-22 15:27:42 +03002127
2128 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
2129
2130 TIntermSymbol *intermSymbol =
2131 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
2132
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002133 return new TIntermInvariantDeclaration(intermSymbol, identifierLoc);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002134}
2135
Olli Etuaho13389b62016-10-16 11:48:18 +01002136void TParseContext::parseDeclarator(TPublicType &publicType,
2137 const TSourceLoc &identifierLocation,
2138 const TString &identifier,
2139 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002140{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002141 // If the declaration starting this declarator list was empty (example: int,), some checks were
2142 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002143 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002144 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002145 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2146 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002147 }
2148
Olli Etuaho856c4972016-08-08 11:38:39 +03002149 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002150
Olli Etuaho856c4972016-08-08 11:38:39 +03002151 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002152
Olli Etuaho2935c582015-04-08 14:32:06 +03002153 TVariable *variable = nullptr;
Olli Etuaho43364892017-02-13 16:00:12 +00002154 TType type(publicType);
2155 declareVariable(identifierLocation, identifier, type, &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002156
Olli Etuaho43364892017-02-13 16:00:12 +00002157 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002158 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002159 {
Jamie Madill502d66f2013-06-20 11:55:52 -04002160 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002161 declarationOut->appendDeclarator(symbol);
2162 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002163}
2164
Olli Etuaho13389b62016-10-16 11:48:18 +01002165void TParseContext::parseArrayDeclarator(TPublicType &publicType,
2166 const TSourceLoc &identifierLocation,
2167 const TString &identifier,
2168 const TSourceLoc &arrayLocation,
2169 TIntermTyped *indexExpression,
2170 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002171{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002172 // If the declaration starting this declarator list was empty (example: int,), some checks were
2173 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002174 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002175 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002176 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2177 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002178 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002179
Olli Etuaho856c4972016-08-08 11:38:39 +03002180 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002181
Olli Etuaho856c4972016-08-08 11:38:39 +03002182 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002183
Olli Etuaho8a176262016-08-16 14:23:01 +03002184 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04002185 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002186 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03002187 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03002188 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002189
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002190 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002191 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04002192
Jamie Madillb98c3a82015-07-23 14:26:04 -04002193 TIntermSymbol *symbol =
2194 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002195 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002196 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002197
Olli Etuaho13389b62016-10-16 11:48:18 +01002198 declarationOut->appendDeclarator(symbol);
Jamie Madill502d66f2013-06-20 11:55:52 -04002199 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002200}
2201
Olli Etuaho13389b62016-10-16 11:48:18 +01002202void TParseContext::parseInitDeclarator(const TPublicType &publicType,
2203 const TSourceLoc &identifierLocation,
2204 const TString &identifier,
2205 const TSourceLoc &initLocation,
2206 TIntermTyped *initializer,
2207 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002208{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002209 // If the declaration starting this declarator list was empty (example: int,), some checks were
2210 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002211 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002212 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002213 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2214 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002215 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002216
Olli Etuaho856c4972016-08-08 11:38:39 +03002217 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002218
Olli Etuaho13389b62016-10-16 11:48:18 +01002219 TIntermBinary *initNode = nullptr;
2220 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04002221 {
2222 //
2223 // build the intermediate representation
2224 //
Olli Etuaho13389b62016-10-16 11:48:18 +01002225 if (initNode)
Jamie Madill502d66f2013-06-20 11:55:52 -04002226 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002227 declarationOut->appendDeclarator(initNode);
Jamie Madill502d66f2013-06-20 11:55:52 -04002228 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002229 }
2230}
2231
Olli Etuaho13389b62016-10-16 11:48:18 +01002232void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
2233 const TSourceLoc &identifierLocation,
2234 const TString &identifier,
2235 const TSourceLoc &indexLocation,
2236 TIntermTyped *indexExpression,
2237 const TSourceLoc &initLocation,
2238 TIntermTyped *initializer,
2239 TIntermDeclaration *declarationOut)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002240{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002241 // If the declaration starting this declarator list was empty (example: int,), some checks were
2242 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002243 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002244 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002245 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2246 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002247 }
2248
Olli Etuaho856c4972016-08-08 11:38:39 +03002249 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002250
Olli Etuaho8a176262016-08-16 14:23:01 +03002251 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002252
2253 TPublicType arrayType(publicType);
2254
Olli Etuaho856c4972016-08-08 11:38:39 +03002255 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002256 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2257 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002258 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002259 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002260 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002261 }
2262 // Make the type an array even if size check failed.
2263 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2264 arrayType.setArraySize(size);
2265
2266 // initNode will correspond to the whole of "b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002267 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002268 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2269 {
2270 if (initNode)
2271 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002272 declarationOut->appendDeclarator(initNode);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002273 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002274 }
2275}
2276
Martin Radev70866b82016-07-22 15:27:42 +03002277void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
Jamie Madilla295edf2013-06-06 11:56:48 -04002278{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002279 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madilla295edf2013-06-06 11:56:48 -04002280 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04002281
Martin Radev70866b82016-07-22 15:27:42 +03002282 checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
2283 typeQualifier.line);
2284
Jamie Madillc2128ff2016-07-04 10:26:17 -04002285 // It should never be the case, but some strange parser errors can send us here.
2286 if (layoutQualifier.isEmpty())
2287 {
2288 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04002289 return;
2290 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002291
Martin Radev802abe02016-08-04 17:48:32 +03002292 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04002293 {
Olli Etuaho43364892017-02-13 16:00:12 +00002294 error(typeQualifier.line, "invalid layout qualifier combination", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04002295 return;
2296 }
2297
Olli Etuaho43364892017-02-13 16:00:12 +00002298 checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);
2299
2300 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev2cc85b32016-08-05 16:22:53 +03002301
2302 checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
2303
Andrei Volykhina5527072017-03-22 16:46:30 +03002304 checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv);
2305
Martin Radev802abe02016-08-04 17:48:32 +03002306 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04002307 {
Martin Radev802abe02016-08-04 17:48:32 +03002308 if (mComputeShaderLocalSizeDeclared &&
2309 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
2310 {
2311 error(typeQualifier.line, "Work group size does not match the previous declaration",
2312 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002313 return;
2314 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002315
Martin Radev802abe02016-08-04 17:48:32 +03002316 if (mShaderVersion < 310)
2317 {
2318 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002319 return;
2320 }
Jamie Madill099c0f32013-06-20 11:55:52 -04002321
Martin Radev4c4c8e72016-08-04 12:25:34 +03002322 if (!layoutQualifier.localSize.isAnyValueSet())
Martin Radev802abe02016-08-04 17:48:32 +03002323 {
2324 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002325 return;
2326 }
2327
2328 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
2329 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
2330
2331 const TConstantUnion *maxComputeWorkGroupSizeData =
2332 maxComputeWorkGroupSize->getConstPointer();
2333
2334 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
2335 {
2336 if (layoutQualifier.localSize[i] != -1)
2337 {
2338 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
2339 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
2340 if (mComputeShaderLocalSize[i] < 1 ||
2341 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
2342 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002343 std::stringstream reasonStream;
2344 reasonStream << "invalid value: Value must be at least 1 and no greater than "
2345 << maxComputeWorkGroupSizeValue;
2346 const std::string &reason = reasonStream.str();
Martin Radev802abe02016-08-04 17:48:32 +03002347
Olli Etuaho4de340a2016-12-16 09:32:03 +00002348 error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03002349 return;
2350 }
2351 }
2352 }
2353
2354 mComputeShaderLocalSizeDeclared = true;
2355 }
Olli Etuaho09b04a22016-12-15 13:30:26 +00002356 else if (mMultiviewAvailable &&
2357 (isExtensionEnabled("GL_OVR_multiview") || isExtensionEnabled("GL_OVR_multiview2")) &&
2358 typeQualifier.qualifier == EvqVertexIn)
2359 {
2360 // This error is only specified in WebGL, but tightens unspecified behavior in the native
2361 // specification.
2362 if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
2363 {
2364 error(typeQualifier.line, "Number of views does not match the previous declaration",
2365 "layout");
2366 return;
2367 }
2368
2369 if (layoutQualifier.numViews == -1)
2370 {
2371 error(typeQualifier.line, "No num_views specified", "layout");
2372 return;
2373 }
2374
2375 if (layoutQualifier.numViews > mMaxNumViews)
2376 {
2377 error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
2378 "layout");
2379 return;
2380 }
2381
2382 mNumViews = layoutQualifier.numViews;
2383 }
Martin Radev802abe02016-08-04 17:48:32 +03002384 else
Jamie Madill1566ef72013-06-20 11:55:54 -04002385 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00002386 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03002387 {
Martin Radev802abe02016-08-04 17:48:32 +03002388 return;
2389 }
2390
2391 if (typeQualifier.qualifier != EvqUniform)
2392 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002393 error(typeQualifier.line, "invalid qualifier: global layout must be uniform",
2394 getQualifierString(typeQualifier.qualifier));
Martin Radev802abe02016-08-04 17:48:32 +03002395 return;
2396 }
2397
2398 if (mShaderVersion < 300)
2399 {
2400 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
2401 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002402 return;
2403 }
2404
Olli Etuaho09b04a22016-12-15 13:30:26 +00002405 checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002406
2407 if (layoutQualifier.matrixPacking != EmpUnspecified)
2408 {
2409 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
2410 }
2411
2412 if (layoutQualifier.blockStorage != EbsUnspecified)
2413 {
2414 mDefaultBlockStorage = layoutQualifier.blockStorage;
2415 }
Jamie Madill1566ef72013-06-20 11:55:54 -04002416 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002417}
2418
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002419TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
2420 const TFunction &function,
2421 const TSourceLoc &location,
2422 bool insertParametersToSymbolTable)
2423{
Olli Etuahofe486322017-03-21 09:30:54 +00002424 TIntermFunctionPrototype *prototype =
2425 new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function));
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002426 // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
2427 // point to the data that already exists in the symbol table.
2428 prototype->getFunctionSymbolInfo()->setFromFunction(function);
2429 prototype->setLine(location);
2430
2431 for (size_t i = 0; i < function.getParamCount(); i++)
2432 {
2433 const TConstParameter &param = function.getParam(i);
2434
2435 // If the parameter has no name, it's not an error, just don't add it to symbol table (could
2436 // be used for unused args).
2437 if (param.name != nullptr)
2438 {
2439 TVariable *variable = new TVariable(param.name, *param.type);
2440
2441 // Insert the parameter in the symbol table.
2442 if (insertParametersToSymbolTable && !symbolTable.declare(variable))
2443 {
2444 error(location, "redefinition", variable->getName().c_str());
2445 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2446 continue;
2447 }
2448 TIntermSymbol *symbol = intermediate.addSymbol(
2449 variable->getUniqueId(), variable->getName(), variable->getType(), location);
2450 prototype->appendParameter(symbol);
2451 }
2452 else
2453 {
2454 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2455 }
2456 }
2457 return prototype;
2458}
2459
Olli Etuaho16c745a2017-01-16 17:02:27 +00002460TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
2461 const TFunction &parsedFunction,
2462 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002463{
Olli Etuaho476197f2016-10-11 13:59:08 +01002464 // Note: function found from the symbol table could be the same as parsedFunction if this is the
2465 // first declaration. Either way the instance in the symbol table is used to track whether the
2466 // function is declared multiple times.
2467 TFunction *function = static_cast<TFunction *>(
2468 symbolTable.find(parsedFunction.getMangledName(), getShaderVersion()));
2469 if (function->hasPrototypeDeclaration() && mShaderVersion == 100)
Olli Etuaho5d653182016-01-04 14:43:28 +02002470 {
2471 // ESSL 1.00.17 section 4.2.7.
2472 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
2473 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02002474 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002475 function->setHasPrototypeDeclaration();
Olli Etuaho5d653182016-01-04 14:43:28 +02002476
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002477 TIntermFunctionPrototype *prototype =
2478 createPrototypeNodeFromFunction(*function, location, false);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002479
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002480 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002481
2482 if (!symbolTable.atGlobalLevel())
2483 {
2484 // ESSL 3.00.4 section 4.2.4.
2485 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002486 }
2487
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002488 return prototype;
2489}
2490
Olli Etuaho336b1472016-10-05 16:37:55 +01002491TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002492 TIntermFunctionPrototype *functionPrototype,
Olli Etuaho336b1472016-10-05 16:37:55 +01002493 TIntermBlock *functionBody,
2494 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002495{
Olli Etuahof51fdd22016-10-03 10:03:40 +01002496 // Check that non-void functions have at least one return statement.
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002497 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2498 {
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002499 error(location, "function does not return a value:",
2500 functionPrototype->getFunctionSymbolInfo()->getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002501 }
2502
Olli Etuahof51fdd22016-10-03 10:03:40 +01002503 if (functionBody == nullptr)
2504 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01002505 functionBody = new TIntermBlock();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002506 functionBody->setLine(location);
2507 }
Olli Etuaho336b1472016-10-05 16:37:55 +01002508 TIntermFunctionDefinition *functionNode =
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002509 new TIntermFunctionDefinition(functionPrototype, functionBody);
Olli Etuaho336b1472016-10-05 16:37:55 +01002510 functionNode->setLine(location);
Olli Etuahof51fdd22016-10-03 10:03:40 +01002511
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002512 symbolTable.pop();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002513 return functionNode;
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002514}
2515
Olli Etuaho476197f2016-10-11 13:59:08 +01002516void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
2517 TFunction **function,
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002518 TIntermFunctionPrototype **prototypeOut)
Jamie Madill185fb402015-06-12 15:48:48 -04002519{
Olli Etuaho476197f2016-10-11 13:59:08 +01002520 ASSERT(function);
2521 ASSERT(*function);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002522 const TSymbol *builtIn =
Olli Etuaho476197f2016-10-11 13:59:08 +01002523 symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002524
2525 if (builtIn)
2526 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002527 error(location, "built-in functions cannot be redefined", (*function)->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002528 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002529 else
Jamie Madill185fb402015-06-12 15:48:48 -04002530 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002531 TFunction *prevDec = static_cast<TFunction *>(
2532 symbolTable.find((*function)->getMangledName(), getShaderVersion()));
2533
2534 // Note: 'prevDec' could be 'function' if this is the first time we've seen function as it
2535 // would have just been put in the symbol table. Otherwise, we're looking up an earlier
2536 // occurance.
2537 if (*function != prevDec)
2538 {
2539 // Swap the parameters of the previous declaration to the parameters of the function
2540 // definition (parameter names may differ).
2541 prevDec->swapParameters(**function);
2542
2543 // The function definition will share the same symbol as any previous declaration.
2544 *function = prevDec;
2545 }
2546
2547 if ((*function)->isDefined())
2548 {
2549 error(location, "function already has a body", (*function)->getName().c_str());
2550 }
2551
2552 (*function)->setDefined();
Jamie Madill185fb402015-06-12 15:48:48 -04002553 }
Jamie Madill185fb402015-06-12 15:48:48 -04002554
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002555 // Remember the return type for later checking for return statements.
Olli Etuaho476197f2016-10-11 13:59:08 +01002556 mCurrentFunctionType = &((*function)->getReturnType());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002557 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002558
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002559 *prototypeOut = createPrototypeNodeFromFunction(**function, location, true);
Jamie Madill185fb402015-06-12 15:48:48 -04002560 setLoopNestingLevel(0);
2561}
2562
Jamie Madillb98c3a82015-07-23 14:26:04 -04002563TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002564{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002565 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002566 // We don't know at this point whether this is a function definition or a prototype.
2567 // The definition production code will check for redefinitions.
2568 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002569 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002570 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2571 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002572 //
2573 TFunction *prevDec =
2574 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302575
Martin Radevda6254b2016-12-14 17:00:36 +02002576 if (getShaderVersion() >= 300 &&
2577 symbolTable.hasUnmangledBuiltInForShaderVersion(function->getName().c_str(),
2578 getShaderVersion()))
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302579 {
Martin Radevda6254b2016-12-14 17:00:36 +02002580 // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions.
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302581 // Therefore overloading or redefining builtin functions is an error.
2582 error(location, "Name of a built-in function cannot be redeclared as function",
2583 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302584 }
2585 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002586 {
2587 if (prevDec->getReturnType() != function->getReturnType())
2588 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002589 error(location, "function must have the same return type in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002590 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002591 }
2592 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2593 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002594 if (prevDec->getParam(i).type->getQualifier() !=
2595 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002596 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002597 error(location,
2598 "function must have the same parameter qualifiers in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002599 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002600 }
2601 }
2602 }
2603
2604 //
2605 // Check for previously declared variables using the same name.
2606 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002607 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002608 if (prevSym)
2609 {
2610 if (!prevSym->isFunction())
2611 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002612 error(location, "redefinition of a function", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002613 }
2614 }
2615 else
2616 {
2617 // Insert the unmangled name to detect potential future redefinition as a variable.
Olli Etuaho476197f2016-10-11 13:59:08 +01002618 symbolTable.getOuterLevel()->insertUnmangled(function);
Jamie Madill185fb402015-06-12 15:48:48 -04002619 }
2620
2621 // We're at the inner scope level of the function's arguments and body statement.
2622 // Add the function prototype to the surrounding scope instead.
2623 symbolTable.getOuterLevel()->insert(function);
2624
Olli Etuaho78d13742017-01-18 13:06:10 +00002625 // Raise error message if main function takes any parameters or return anything other than void
2626 if (function->getName() == "main")
2627 {
2628 if (function->getParamCount() > 0)
2629 {
2630 error(location, "function cannot take any parameter(s)", "main");
2631 }
2632 if (function->getReturnType().getBasicType() != EbtVoid)
2633 {
2634 error(location, "main function cannot return a value",
2635 function->getReturnType().getBasicString());
2636 }
2637 }
2638
Jamie Madill185fb402015-06-12 15:48:48 -04002639 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002640 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2641 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002642 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2643 //
2644 return function;
2645}
2646
Olli Etuaho9de84a52016-06-14 17:36:01 +03002647TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2648 const TString *name,
2649 const TSourceLoc &location)
2650{
2651 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2652 {
2653 error(location, "no qualifiers allowed for function return",
2654 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002655 }
2656 if (!type.layoutQualifier.isEmpty())
2657 {
2658 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002659 }
jchen10cc2a10e2017-05-03 14:05:12 +08002660 // make sure an opaque type is not involved as well...
2661 std::string reason(getBasicString(type.getBasicType()));
2662 reason += "s can't be function return values";
2663 checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002664 if (mShaderVersion < 300)
2665 {
2666 // Array return values are forbidden, but there's also no valid syntax for declaring array
2667 // return values in ESSL 1.00.
Olli Etuaho77ba4082016-12-16 12:01:18 +00002668 ASSERT(type.arraySize == 0 || mDiagnostics->numErrors() > 0);
Olli Etuahoe29324f2016-06-15 10:58:03 +03002669
2670 if (type.isStructureContainingArrays())
2671 {
2672 // ESSL 1.00.17 section 6.1 Function Definitions
2673 error(location, "structures containing arrays can't be function return values",
2674 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002675 }
2676 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002677
2678 // Add the function as a prototype after parsing it (we do not support recursion)
2679 return new TFunction(name, new TType(type));
2680}
2681
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002682TFunction *TParseContext::addConstructorFunc(const TPublicType &publicType)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002683{
Martin Radev4a9cd802016-09-01 16:51:51 +03002684 if (publicType.isStructSpecifier())
Olli Etuahobd163f62015-11-13 12:15:38 +02002685 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002686 error(publicType.getLine(), "constructor can't be a structure definition",
2687 getBasicString(publicType.getBasicType()));
Olli Etuahobd163f62015-11-13 12:15:38 +02002688 }
2689
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002690 TType *type = new TType(publicType);
2691 if (!type->canBeConstructed())
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002692 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002693 error(publicType.getLine(), "cannot construct this type",
2694 getBasicString(publicType.getBasicType()));
2695 type->setBasicType(EbtFloat);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002696 }
2697
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002698 return new TFunction(nullptr, type, EOpConstruct);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002699}
2700
Jamie Madillb98c3a82015-07-23 14:26:04 -04002701// This function is used to test for the correctness of the parameters passed to various constructor
2702// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002703//
Olli Etuaho856c4972016-08-08 11:38:39 +03002704// 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 +00002705//
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002706TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00002707 TType type,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302708 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002709{
Olli Etuaho856c4972016-08-08 11:38:39 +03002710 if (type.isUnsizedArray())
2711 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002712 if (arguments->empty())
Olli Etuahobbe9fb52016-11-03 17:16:05 +00002713 {
2714 error(line, "implicitly sized array constructor must have at least one argument", "[]");
2715 type.setArraySize(1u);
2716 return TIntermTyped::CreateZero(type);
2717 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002718 type.setArraySize(static_cast<unsigned int>(arguments->size()));
Olli Etuaho856c4972016-08-08 11:38:39 +03002719 }
Olli Etuaho856c4972016-08-08 11:38:39 +03002720
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002721 if (!checkConstructorArguments(line, arguments, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002722 {
Olli Etuaho72d10202017-01-19 15:58:30 +00002723 return TIntermTyped::CreateZero(type);
Olli Etuaho856c4972016-08-08 11:38:39 +03002724 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002725
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002726 TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002727 constructorNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002728
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002729 TIntermTyped *constConstructor =
2730 intermediate.foldAggregateBuiltIn(constructorNode, mDiagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002731 if (constConstructor)
2732 {
2733 return constConstructor;
2734 }
2735
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002736 return constructorNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002737}
2738
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002739//
2740// Interface/uniform blocks
2741//
Olli Etuaho13389b62016-10-16 11:48:18 +01002742TIntermDeclaration *TParseContext::addInterfaceBlock(
Martin Radev70866b82016-07-22 15:27:42 +03002743 const TTypeQualifierBuilder &typeQualifierBuilder,
2744 const TSourceLoc &nameLine,
2745 const TString &blockName,
2746 TFieldList *fieldList,
2747 const TString *instanceName,
2748 const TSourceLoc &instanceLine,
2749 TIntermTyped *arrayIndex,
2750 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002751{
Olli Etuaho856c4972016-08-08 11:38:39 +03002752 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002753
Olli Etuaho77ba4082016-12-16 12:01:18 +00002754 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03002755
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002756 if (typeQualifier.qualifier != EvqUniform)
2757 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002758 error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform",
2759 getQualifierString(typeQualifier.qualifier));
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002760 }
2761
Martin Radev70866b82016-07-22 15:27:42 +03002762 if (typeQualifier.invariant)
2763 {
2764 error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
2765 }
2766
Olli Etuaho43364892017-02-13 16:00:12 +00002767 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
2768
2769 // TODO(oetuaho): Remove this and support binding for blocks.
2770 checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
Martin Radev2cc85b32016-08-05 16:22:53 +03002771
Andrei Volykhina5527072017-03-22 16:46:30 +03002772 checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
2773
Jamie Madill099c0f32013-06-20 11:55:52 -04002774 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03002775 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04002776
Jamie Madill099c0f32013-06-20 11:55:52 -04002777 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2778 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002779 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002780 }
2781
Jamie Madill1566ef72013-06-20 11:55:54 -04002782 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2783 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002784 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002785 }
2786
Olli Etuaho856c4972016-08-08 11:38:39 +03002787 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002788
Martin Radev2cc85b32016-08-05 16:22:53 +03002789 checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
2790
Arun Patole7e7e68d2015-05-22 12:02:25 +05302791 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2792 if (!symbolTable.declare(blockNameSymbol))
2793 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002794 error(nameLine, "redefinition of an interface block name", blockName.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002795 }
2796
Jamie Madill98493dd2013-07-08 14:39:03 -04002797 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302798 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2799 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002800 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302801 TType *fieldType = field->type();
jchen10cc2a10e2017-05-03 14:05:12 +08002802 if (IsOpaqueType(fieldType->getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +05302803 {
jchen10cc2a10e2017-05-03 14:05:12 +08002804 std::string reason("unsupported type - ");
2805 reason += fieldType->getBasicString();
2806 reason += " types are not allowed in interface blocks";
2807 error(field->line(), reason.c_str(), fieldType->getBasicString());
Martin Radev2cc85b32016-08-05 16:22:53 +03002808 }
2809
Jamie Madill98493dd2013-07-08 14:39:03 -04002810 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002811 switch (qualifier)
2812 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002813 case EvqGlobal:
2814 case EvqUniform:
2815 break;
2816 default:
2817 error(field->line(), "invalid qualifier on interface block member",
2818 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04002819 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002820 }
Jamie Madilla5efff92013-06-06 11:56:47 -04002821
Martin Radev70866b82016-07-22 15:27:42 +03002822 if (fieldType->isInvariant())
2823 {
2824 error(field->line(), "invalid qualifier on interface block member", "invariant");
2825 }
2826
Jamie Madilla5efff92013-06-06 11:56:47 -04002827 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04002828 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03002829 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Jamie Madill099c0f32013-06-20 11:55:52 -04002830
Jamie Madill98493dd2013-07-08 14:39:03 -04002831 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04002832 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002833 error(field->line(), "invalid layout qualifier: cannot be used here",
2834 getBlockStorageString(fieldLayoutQualifier.blockStorage));
Jamie Madill1566ef72013-06-20 11:55:54 -04002835 }
2836
Jamie Madill98493dd2013-07-08 14:39:03 -04002837 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04002838 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002839 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002840 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002841 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04002842 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002843 warning(field->line(),
2844 "extraneous layout qualifier: only has an effect on matrix types",
2845 getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
Jamie Madill099c0f32013-06-20 11:55:52 -04002846 }
2847
Jamie Madill98493dd2013-07-08 14:39:03 -04002848 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002849 }
2850
Jamie Madill98493dd2013-07-08 14:39:03 -04002851 // add array index
Olli Etuaho856c4972016-08-08 11:38:39 +03002852 unsigned int arraySize = 0;
2853 if (arrayIndex != nullptr)
Jamie Madill98493dd2013-07-08 14:39:03 -04002854 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002855 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
Jamie Madill98493dd2013-07-08 14:39:03 -04002856 }
2857
Jamie Madillb98c3a82015-07-23 14:26:04 -04002858 TInterfaceBlock *interfaceBlock =
2859 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2860 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
2861 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002862
2863 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04002864 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002865
Jamie Madill98493dd2013-07-08 14:39:03 -04002866 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002867 {
2868 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04002869 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2870 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002871 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302872 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04002873
2874 // set parent pointer of the field variable
2875 fieldType->setInterfaceBlock(interfaceBlock);
2876
Arun Patole7e7e68d2015-05-22 12:02:25 +05302877 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04002878 fieldVariable->setQualifier(typeQualifier.qualifier);
2879
Arun Patole7e7e68d2015-05-22 12:02:25 +05302880 if (!symbolTable.declare(fieldVariable))
2881 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002882 error(field->line(), "redefinition of an interface block member name",
2883 field->name().c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002884 }
2885 }
2886 }
2887 else
2888 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002889 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03002890
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002891 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05302892 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002893 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04002894
Arun Patole7e7e68d2015-05-22 12:02:25 +05302895 if (!symbolTable.declare(instanceTypeDef))
2896 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002897 error(instanceLine, "redefinition of an interface block instance name",
2898 instanceName->c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002899 }
2900
Jamie Madillb98c3a82015-07-23 14:26:04 -04002901 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002902 symbolName = instanceTypeDef->getName();
2903 }
2904
Olli Etuaho13389b62016-10-16 11:48:18 +01002905 TIntermSymbol *blockSymbol =
2906 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line);
2907 TIntermDeclaration *declaration = new TIntermDeclaration();
2908 declaration->appendDeclarator(blockSymbol);
2909 declaration->setLine(nameLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04002910
2911 exitStructDeclaration();
Olli Etuaho13389b62016-10-16 11:48:18 +01002912 return declaration;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002913}
2914
Olli Etuaho383b7912016-08-05 11:22:59 +03002915void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002916{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002917 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002918
2919 // Embedded structure definitions are not supported per GLSL ES spec.
Olli Etuaho4de340a2016-12-16 09:32:03 +00002920 // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302921 if (mStructNestingLevel > 1)
2922 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002923 error(line, "Embedded struct definitions are not allowed", "struct");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002924 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002925}
2926
2927void TParseContext::exitStructDeclaration()
2928{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002929 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002930}
2931
Olli Etuaho8a176262016-08-16 14:23:01 +03002932void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002933{
Jamie Madillacb4b812016-11-07 13:50:29 -05002934 if (!sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +05302935 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002936 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002937 }
2938
Arun Patole7e7e68d2015-05-22 12:02:25 +05302939 if (field.type()->getBasicType() != EbtStruct)
2940 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002941 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002942 }
2943
2944 // We're already inside a structure definition at this point, so add
2945 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302946 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2947 {
Jamie Madill41a49272014-03-18 16:10:13 -04002948 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002949 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
2950 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04002951 std::string reason = reasonStream.str();
Olli Etuaho4de340a2016-12-16 09:32:03 +00002952 error(line, reason.c_str(), field.name().c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03002953 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002954 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002955}
2956
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00002957//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002958// Parse an array index expression
2959//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002960TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
2961 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302962 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002963{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002964 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2965 {
2966 if (baseExpression->getAsSymbolNode())
2967 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302968 error(location, " left of '[' is not of type array, matrix, or vector ",
2969 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002970 }
2971 else
2972 {
2973 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2974 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002975
2976 TConstantUnion *unionArray = new TConstantUnion[1];
2977 unionArray->setFConst(0.0f);
2978 return intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst),
2979 location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002980 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002981
Jamie Madill21c1e452014-12-29 11:33:41 -05002982 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2983
Olli Etuaho36b05142015-11-12 13:10:42 +02002984 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
2985 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
2986 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
2987 // index is a constant expression.
2988 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
2989 {
2990 if (baseExpression->isInterfaceBlock())
2991 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002992 error(location,
2993 "array indexes for interface blocks arrays must be constant integral expressions",
2994 "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02002995 }
2996 else if (baseExpression->getQualifier() == EvqFragmentOut)
2997 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002998 error(location,
2999 "array indexes for fragment outputs must be constant integral expressions", "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02003000 }
Olli Etuaho3e960462015-11-12 15:58:39 +02003001 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
3002 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003003 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3e960462015-11-12 15:58:39 +02003004 }
Olli Etuaho36b05142015-11-12 13:10:42 +02003005 }
3006
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003007 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04003008 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003009 // If an out-of-range index is not qualified as constant, the behavior in the spec is
3010 // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
3011 // constant fold expressions that are not constant expressions). The most compatible way to
3012 // handle this case is to report a warning instead of an error and force the index to be in
3013 // the correct range.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003014 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003015 int index = indexConstantUnion->getIConst(0);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003016
3017 int safeIndex = -1;
3018
3019 if (baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04003020 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003021 if (baseExpression->getQualifier() == EvqFragData && index > 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003022 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003023 if (mShaderSpec == SH_WEBGL2_SPEC)
3024 {
3025 // Error has been already generated if index is not const.
3026 if (indexExpression->getQualifier() == EvqConst)
3027 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003028 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003029 }
3030 safeIndex = 0;
3031 }
3032 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
3033 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003034 outOfRangeError(outOfRangeIndexIsError, location,
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003035 "array index for gl_FragData must be zero when "
Olli Etuaho4de340a2016-12-16 09:32:03 +00003036 "GL_EXT_draw_buffers is disabled",
3037 "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003038 safeIndex = 0;
3039 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03003040 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003041 // Only do generic out-of-range check if similar error hasn't already been reported.
3042 if (safeIndex < 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003043 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003044 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3045 baseExpression->getArraySize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003046 "array index out of range");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003047 }
3048 }
3049 else if (baseExpression->isMatrix())
3050 {
3051 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
Olli Etuaho90892fb2016-07-14 14:44:51 +03003052 baseExpression->getType().getCols(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003053 "matrix field selection out of range");
Jamie Madill7164cf42013-07-08 13:30:59 -04003054 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003055 else if (baseExpression->isVector())
Jamie Madill7164cf42013-07-08 13:30:59 -04003056 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003057 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3058 baseExpression->getType().getNominalSize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003059 "vector field selection out of range");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003060 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003061
3062 ASSERT(safeIndex >= 0);
3063 // Data of constant unions can't be changed, because it may be shared with other
3064 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
3065 // sanitized object.
3066 if (safeIndex != index)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003067 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003068 TConstantUnion *safeConstantUnion = new TConstantUnion();
3069 safeConstantUnion->setIConst(safeIndex);
3070 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003071 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003072
3073 return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003074 mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003075 }
Jamie Madill7164cf42013-07-08 13:30:59 -04003076 else
3077 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003078 return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003079 mDiagnostics);
Jamie Madill7164cf42013-07-08 13:30:59 -04003080 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003081}
3082
Olli Etuaho90892fb2016-07-14 14:44:51 +03003083int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
3084 const TSourceLoc &location,
3085 int index,
3086 int arraySize,
Olli Etuaho4de340a2016-12-16 09:32:03 +00003087 const char *reason)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003088{
3089 if (index >= arraySize || index < 0)
3090 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003091 std::stringstream reasonStream;
3092 reasonStream << reason << " '" << index << "'";
3093 std::string token = reasonStream.str();
3094 outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
Olli Etuaho90892fb2016-07-14 14:44:51 +03003095 if (index < 0)
3096 {
3097 return 0;
3098 }
3099 else
3100 {
3101 return arraySize - 1;
3102 }
3103 }
3104 return index;
3105}
3106
Jamie Madillb98c3a82015-07-23 14:26:04 -04003107TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
3108 const TSourceLoc &dotLocation,
3109 const TString &fieldString,
3110 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003111{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003112 if (baseExpression->isArray())
3113 {
3114 error(fieldLocation, "cannot apply dot operator to an array", ".");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003115 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003116 }
3117
3118 if (baseExpression->isVector())
3119 {
3120 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003121 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
3122 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003123 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003124 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003125 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003126 }
3127
Olli Etuahob6fa0432016-09-28 16:28:05 +01003128 return TIntermediate::AddSwizzle(baseExpression, fields, dotLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003129 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003130 else if (baseExpression->getBasicType() == EbtStruct)
3131 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303132 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003133 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003134 {
3135 error(dotLocation, "structure has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003136 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003137 }
3138 else
3139 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003140 bool fieldFound = false;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003141 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003142 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003143 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003144 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003145 {
3146 fieldFound = true;
3147 break;
3148 }
3149 }
3150 if (fieldFound)
3151 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003152 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3153 index->setLine(fieldLocation);
3154 return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003155 dotLocation, mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003156 }
3157 else
3158 {
3159 error(dotLocation, " no such field in structure", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003160 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003161 }
3162 }
3163 }
Jamie Madill98493dd2013-07-08 14:39:03 -04003164 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003165 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303166 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003167 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003168 {
3169 error(dotLocation, "interface block has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003170 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003171 }
3172 else
3173 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003174 bool fieldFound = false;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003175 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003176 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003177 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003178 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003179 {
3180 fieldFound = true;
3181 break;
3182 }
3183 }
3184 if (fieldFound)
3185 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003186 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3187 index->setLine(fieldLocation);
3188 return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003189 dotLocation, mDiagnostics);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003190 }
3191 else
3192 {
3193 error(dotLocation, " no such field in interface block", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003194 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003195 }
3196 }
3197 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003198 else
3199 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003200 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003201 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03003202 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303203 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003204 }
3205 else
3206 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303207 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03003208 " field selection requires structure, vector, or interface block on left hand "
3209 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303210 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003211 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003212 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003213 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003214}
3215
Jamie Madillb98c3a82015-07-23 14:26:04 -04003216TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3217 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003218{
Martin Radev802abe02016-08-04 17:48:32 +03003219 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003220
3221 if (qualifierType == "shared")
3222 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003223 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003224 {
3225 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
3226 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003227 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003228 }
3229 else if (qualifierType == "packed")
3230 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003231 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003232 {
3233 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
3234 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003235 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003236 }
3237 else if (qualifierType == "std140")
3238 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003239 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003240 }
3241 else if (qualifierType == "row_major")
3242 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003243 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003244 }
3245 else if (qualifierType == "column_major")
3246 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003247 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003248 }
3249 else if (qualifierType == "location")
3250 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003251 error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
3252 qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003253 }
Andrei Volykhina5527072017-03-22 16:46:30 +03003254 else if (qualifierType == "yuv" && isExtensionEnabled("GL_EXT_YUV_target") &&
3255 mShaderType == GL_FRAGMENT_SHADER)
3256 {
3257 qualifier.yuv = true;
3258 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003259 else if (qualifierType == "rgba32f")
3260 {
3261 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3262 qualifier.imageInternalFormat = EiifRGBA32F;
3263 }
3264 else if (qualifierType == "rgba16f")
3265 {
3266 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3267 qualifier.imageInternalFormat = EiifRGBA16F;
3268 }
3269 else if (qualifierType == "r32f")
3270 {
3271 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3272 qualifier.imageInternalFormat = EiifR32F;
3273 }
3274 else if (qualifierType == "rgba8")
3275 {
3276 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3277 qualifier.imageInternalFormat = EiifRGBA8;
3278 }
3279 else if (qualifierType == "rgba8_snorm")
3280 {
3281 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3282 qualifier.imageInternalFormat = EiifRGBA8_SNORM;
3283 }
3284 else if (qualifierType == "rgba32i")
3285 {
3286 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3287 qualifier.imageInternalFormat = EiifRGBA32I;
3288 }
3289 else if (qualifierType == "rgba16i")
3290 {
3291 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3292 qualifier.imageInternalFormat = EiifRGBA16I;
3293 }
3294 else if (qualifierType == "rgba8i")
3295 {
3296 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3297 qualifier.imageInternalFormat = EiifRGBA8I;
3298 }
3299 else if (qualifierType == "r32i")
3300 {
3301 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3302 qualifier.imageInternalFormat = EiifR32I;
3303 }
3304 else if (qualifierType == "rgba32ui")
3305 {
3306 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3307 qualifier.imageInternalFormat = EiifRGBA32UI;
3308 }
3309 else if (qualifierType == "rgba16ui")
3310 {
3311 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3312 qualifier.imageInternalFormat = EiifRGBA16UI;
3313 }
3314 else if (qualifierType == "rgba8ui")
3315 {
3316 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3317 qualifier.imageInternalFormat = EiifRGBA8UI;
3318 }
3319 else if (qualifierType == "r32ui")
3320 {
3321 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3322 qualifier.imageInternalFormat = EiifR32UI;
3323 }
3324
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003325 else
3326 {
3327 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003328 }
3329
Jamie Madilla5efff92013-06-06 11:56:47 -04003330 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003331}
3332
Martin Radev802abe02016-08-04 17:48:32 +03003333void TParseContext::parseLocalSize(const TString &qualifierType,
3334 const TSourceLoc &qualifierTypeLine,
3335 int intValue,
3336 const TSourceLoc &intValueLine,
3337 const std::string &intValueString,
3338 size_t index,
Martin Radev4c4c8e72016-08-04 12:25:34 +03003339 sh::WorkGroupSize *localSize)
Martin Radev802abe02016-08-04 17:48:32 +03003340{
Olli Etuaho856c4972016-08-08 11:38:39 +03003341 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03003342 if (intValue < 1)
3343 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003344 std::stringstream reasonStream;
3345 reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
3346 std::string reason = reasonStream.str();
3347 error(intValueLine, reason.c_str(), intValueString.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003348 }
3349 (*localSize)[index] = intValue;
3350}
3351
Olli Etuaho09b04a22016-12-15 13:30:26 +00003352void TParseContext::parseNumViews(int intValue,
3353 const TSourceLoc &intValueLine,
3354 const std::string &intValueString,
3355 int *numViews)
3356{
3357 // This error is only specified in WebGL, but tightens unspecified behavior in the native
3358 // specification.
3359 if (intValue < 1)
3360 {
3361 error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
3362 }
3363 *numViews = intValue;
3364}
3365
Jamie Madillb98c3a82015-07-23 14:26:04 -04003366TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3367 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003368 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303369 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003370{
Martin Radev802abe02016-08-04 17:48:32 +03003371 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003372
Martin Radev802abe02016-08-04 17:48:32 +03003373 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003374
Martin Radev802abe02016-08-04 17:48:32 +03003375 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003376 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003377 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003378 if (intValue < 0)
3379 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003380 error(intValueLine, "out of range: location must be non-negative",
3381 intValueString.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003382 }
3383 else
3384 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003385 qualifier.location = intValue;
Olli Etuaho87d410c2016-09-05 13:33:26 +03003386 qualifier.locationsSpecified = 1;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003387 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003388 }
Olli Etuaho43364892017-02-13 16:00:12 +00003389 else if (qualifierType == "binding")
3390 {
3391 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3392 if (intValue < 0)
3393 {
3394 error(intValueLine, "out of range: binding must be non-negative",
3395 intValueString.c_str());
3396 }
3397 else
3398 {
3399 qualifier.binding = intValue;
3400 }
3401 }
Martin Radev802abe02016-08-04 17:48:32 +03003402 else if (qualifierType == "local_size_x")
3403 {
3404 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3405 &qualifier.localSize);
3406 }
3407 else if (qualifierType == "local_size_y")
3408 {
3409 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3410 &qualifier.localSize);
3411 }
3412 else if (qualifierType == "local_size_z")
3413 {
3414 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3415 &qualifier.localSize);
3416 }
Olli Etuaho09b04a22016-12-15 13:30:26 +00003417 else if (qualifierType == "num_views" && mMultiviewAvailable &&
3418 (isExtensionEnabled("GL_OVR_multiview") || isExtensionEnabled("GL_OVR_multiview2")) &&
3419 mShaderType == GL_VERTEX_SHADER)
3420 {
3421 parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
3422 }
Martin Radev802abe02016-08-04 17:48:32 +03003423 else
3424 {
3425 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003426 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003427
Jamie Madilla5efff92013-06-06 11:56:47 -04003428 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003429}
3430
Olli Etuaho613b9592016-09-05 12:05:53 +03003431TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
3432{
3433 return new TTypeQualifierBuilder(
3434 new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
3435 mShaderVersion);
3436}
3437
Jamie Madillb98c3a82015-07-23 14:26:04 -04003438TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003439 TLayoutQualifier rightQualifier,
3440 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003441{
Martin Radevc28888b2016-07-22 15:27:42 +03003442 return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003443 mDiagnostics);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003444}
3445
Olli Etuaho4de340a2016-12-16 09:32:03 +00003446TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
3447 const TFieldList *newlyAddedFields,
3448 const TSourceLoc &location)
3449{
3450 for (TField *field : *newlyAddedFields)
3451 {
3452 for (TField *oldField : *processedFields)
3453 {
3454 if (oldField->name() == field->name())
3455 {
3456 error(location, "duplicate field name in structure", field->name().c_str());
3457 }
3458 }
3459 processedFields->push_back(field);
3460 }
3461 return processedFields;
3462}
3463
Martin Radev70866b82016-07-22 15:27:42 +03003464TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
3465 const TTypeQualifierBuilder &typeQualifierBuilder,
3466 TPublicType *typeSpecifier,
3467 TFieldList *fieldList)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003468{
Olli Etuaho77ba4082016-12-16 12:01:18 +00003469 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003470
Martin Radev70866b82016-07-22 15:27:42 +03003471 typeSpecifier->qualifier = typeQualifier.qualifier;
3472 typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03003473 typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03003474 typeSpecifier->invariant = typeQualifier.invariant;
3475 if (typeQualifier.precision != EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +05303476 {
Martin Radev70866b82016-07-22 15:27:42 +03003477 typeSpecifier->precision = typeQualifier.precision;
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003478 }
Martin Radev70866b82016-07-22 15:27:42 +03003479 return addStructDeclaratorList(*typeSpecifier, fieldList);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003480}
3481
Jamie Madillb98c3a82015-07-23 14:26:04 -04003482TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3483 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003484{
Martin Radev4a9cd802016-09-01 16:51:51 +03003485 checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
3486 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03003487
Martin Radev4a9cd802016-09-01 16:51:51 +03003488 checkIsNonVoid(typeSpecifier.getLine(), (*fieldList)[0]->name(), typeSpecifier.getBasicType());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003489
Martin Radev4a9cd802016-09-01 16:51:51 +03003490 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003491
Arun Patole7e7e68d2015-05-22 12:02:25 +05303492 for (unsigned int i = 0; i < fieldList->size(); ++i)
3493 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003494 //
3495 // Careful not to replace already known aspects of type, like array-ness
3496 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303497 TType *type = (*fieldList)[i]->type();
Martin Radev4a9cd802016-09-01 16:51:51 +03003498 type->setBasicType(typeSpecifier.getBasicType());
3499 type->setPrimarySize(typeSpecifier.getPrimarySize());
3500 type->setSecondarySize(typeSpecifier.getSecondarySize());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003501 type->setPrecision(typeSpecifier.precision);
3502 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003503 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
Martin Radev2cc85b32016-08-05 16:22:53 +03003504 type->setMemoryQualifier(typeSpecifier.memoryQualifier);
Martin Radev70866b82016-07-22 15:27:42 +03003505 type->setInvariant(typeSpecifier.invariant);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003506
3507 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303508 if (type->isArray())
3509 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003510 checkIsValidTypeForArray(typeSpecifier.getLine(), typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003511 }
3512 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003513 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Martin Radev4a9cd802016-09-01 16:51:51 +03003514 if (typeSpecifier.getUserDef())
Arun Patole7e7e68d2015-05-22 12:02:25 +05303515 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003516 type->setStruct(typeSpecifier.getUserDef()->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003517 }
3518
Martin Radev4a9cd802016-09-01 16:51:51 +03003519 checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003520 }
3521
Jamie Madill98493dd2013-07-08 14:39:03 -04003522 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003523}
3524
Martin Radev4a9cd802016-09-01 16:51:51 +03003525TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
3526 const TSourceLoc &nameLine,
3527 const TString *structName,
3528 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003529{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303530 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003531 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003532
Jamie Madill9b820842015-02-12 10:40:10 -05003533 // Store a bool in the struct if we're at global scope, to allow us to
3534 // skip the local struct scoping workaround in HLSL.
Jamie Madill9b820842015-02-12 10:40:10 -05003535 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003536
Jamie Madill98493dd2013-07-08 14:39:03 -04003537 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003538 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003539 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303540 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3541 if (!symbolTable.declare(userTypeDef))
3542 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003543 error(nameLine, "redefinition of a struct", structName->c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003544 }
3545 }
3546
3547 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003548 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003549 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003550 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003551 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003552 switch (qualifier)
3553 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003554 case EvqGlobal:
3555 case EvqTemporary:
3556 break;
3557 default:
3558 error(field.line(), "invalid qualifier on struct member",
3559 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003560 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003561 }
Martin Radev70866b82016-07-22 15:27:42 +03003562 if (field.type()->isInvariant())
3563 {
3564 error(field.line(), "invalid qualifier on struct member", "invariant");
3565 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003566 if (IsImage(field.type()->getBasicType()))
3567 {
3568 error(field.line(), "disallowed type in struct", field.type()->getBasicString());
3569 }
3570
Olli Etuaho43364892017-02-13 16:00:12 +00003571 checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
3572
3573 checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);
Martin Radev70866b82016-07-22 15:27:42 +03003574
3575 checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003576 }
3577
Martin Radev4a9cd802016-09-01 16:51:51 +03003578 TTypeSpecifierNonArray typeSpecifierNonArray;
3579 typeSpecifierNonArray.initialize(EbtStruct, structLine);
3580 typeSpecifierNonArray.userDef = structureType;
3581 typeSpecifierNonArray.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003582 exitStructDeclaration();
3583
Martin Radev4a9cd802016-09-01 16:51:51 +03003584 return typeSpecifierNonArray;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003585}
3586
Jamie Madillb98c3a82015-07-23 14:26:04 -04003587TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01003588 TIntermBlock *statementList,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003589 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003590{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003591 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003592 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003593 init->isVector())
3594 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003595 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3596 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003597 return nullptr;
3598 }
3599
Olli Etuahoac5274d2015-02-20 10:19:08 +02003600 if (statementList)
3601 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00003602 if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
Olli Etuahoac5274d2015-02-20 10:19:08 +02003603 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003604 return nullptr;
3605 }
3606 }
3607
Olli Etuahoa3a36662015-02-17 13:46:51 +02003608 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3609 if (node == nullptr)
3610 {
3611 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003612 return nullptr;
3613 }
3614 return node;
3615}
3616
3617TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3618{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003619 if (mSwitchNestingLevel == 0)
3620 {
3621 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003622 return nullptr;
3623 }
3624 if (condition == nullptr)
3625 {
3626 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003627 return nullptr;
3628 }
3629 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003630 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003631 {
3632 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003633 }
3634 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003635 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3636 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3637 // fold in case labels.
3638 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003639 {
3640 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003641 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003642 TIntermCase *node = intermediate.addCase(condition, loc);
3643 if (node == nullptr)
3644 {
3645 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003646 return nullptr;
3647 }
3648 return node;
3649}
3650
3651TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3652{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003653 if (mSwitchNestingLevel == 0)
3654 {
3655 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003656 return nullptr;
3657 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003658 TIntermCase *node = intermediate.addCase(nullptr, loc);
3659 if (node == nullptr)
3660 {
3661 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003662 return nullptr;
3663 }
3664 return node;
3665}
3666
Jamie Madillb98c3a82015-07-23 14:26:04 -04003667TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3668 TIntermTyped *child,
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003669 const TSourceLoc &loc)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003670{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003671 ASSERT(child != nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003672
3673 switch (op)
3674 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003675 case EOpLogicalNot:
3676 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3677 child->isVector())
3678 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003679 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003680 return nullptr;
3681 }
3682 break;
3683 case EOpBitwiseNot:
3684 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3685 child->isMatrix() || child->isArray())
3686 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003687 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003688 return nullptr;
3689 }
3690 break;
3691 case EOpPostIncrement:
3692 case EOpPreIncrement:
3693 case EOpPostDecrement:
3694 case EOpPreDecrement:
3695 case EOpNegative:
3696 case EOpPositive:
Olli Etuaho94050052017-05-08 14:17:44 +03003697 if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() ||
3698 child->getBasicType() == EbtBool || child->isArray() ||
3699 IsOpaqueType(child->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -04003700 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003701 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003702 return nullptr;
3703 }
3704 // Operators for built-ins are already type checked against their prototype.
3705 default:
3706 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003707 }
3708
Olli Etuahof119a262016-08-19 15:54:22 +03003709 TIntermUnary *node = new TIntermUnary(op, child);
3710 node->setLine(loc);
Olli Etuahof119a262016-08-19 15:54:22 +03003711
Olli Etuaho77ba4082016-12-16 12:01:18 +00003712 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuahof119a262016-08-19 15:54:22 +03003713 if (foldedNode)
3714 return foldedNode;
3715
3716 return node;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003717}
3718
Olli Etuaho09b22472015-02-11 11:47:26 +02003719TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3720{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003721 TIntermTyped *node = createUnaryMath(op, child, loc);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003722 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003723 {
Olli Etuaho09b22472015-02-11 11:47:26 +02003724 return child;
3725 }
3726 return node;
3727}
3728
Jamie Madillb98c3a82015-07-23 14:26:04 -04003729TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3730 TIntermTyped *child,
3731 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003732{
Olli Etuaho856c4972016-08-08 11:38:39 +03003733 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003734 return addUnaryMath(op, child, loc);
3735}
3736
Jamie Madillb98c3a82015-07-23 14:26:04 -04003737bool TParseContext::binaryOpCommonCheck(TOperator op,
3738 TIntermTyped *left,
3739 TIntermTyped *right,
3740 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003741{
jchen10b4cf5652017-05-05 18:51:17 +08003742 // Check opaque types are not allowed to be operands in expressions other than array indexing
3743 // and structure member selection.
3744 if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType()))
3745 {
3746 switch (op)
3747 {
3748 case EOpIndexDirect:
3749 case EOpIndexIndirect:
3750 break;
3751 case EOpIndexDirectStruct:
3752 UNREACHABLE();
3753
3754 default:
3755 error(loc, "Invalid operation for variables with an opaque type",
3756 GetOperatorString(op));
3757 return false;
3758 }
3759 }
jchen10cc2a10e2017-05-03 14:05:12 +08003760
Olli Etuaho244be012016-08-18 15:26:02 +03003761 if (left->getType().getStruct() || right->getType().getStruct())
3762 {
3763 switch (op)
3764 {
3765 case EOpIndexDirectStruct:
3766 ASSERT(left->getType().getStruct());
3767 break;
3768 case EOpEqual:
3769 case EOpNotEqual:
3770 case EOpAssign:
3771 case EOpInitialize:
3772 if (left->getType() != right->getType())
3773 {
3774 return false;
3775 }
3776 break;
3777 default:
3778 error(loc, "Invalid operation for structs", GetOperatorString(op));
3779 return false;
3780 }
3781 }
3782
Olli Etuaho94050052017-05-08 14:17:44 +03003783 if (left->isInterfaceBlock() || right->isInterfaceBlock())
3784 {
3785 switch (op)
3786 {
3787 case EOpIndexDirectInterfaceBlock:
3788 ASSERT(left->getType().getInterfaceBlock());
3789 break;
3790 default:
3791 error(loc, "Invalid operation for interface blocks", GetOperatorString(op));
3792 return false;
3793 }
3794 }
3795
Olli Etuahod6b14282015-03-17 14:31:35 +02003796 if (left->isArray() || right->isArray())
3797 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003798 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003799 {
3800 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3801 return false;
3802 }
3803
3804 if (left->isArray() != right->isArray())
3805 {
3806 error(loc, "array / non-array mismatch", GetOperatorString(op));
3807 return false;
3808 }
3809
3810 switch (op)
3811 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003812 case EOpEqual:
3813 case EOpNotEqual:
3814 case EOpAssign:
3815 case EOpInitialize:
3816 break;
3817 default:
3818 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3819 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02003820 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03003821 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02003822 if (left->getArraySize() != right->getArraySize())
3823 {
3824 error(loc, "array size mismatch", GetOperatorString(op));
3825 return false;
3826 }
Olli Etuahod6b14282015-03-17 14:31:35 +02003827 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003828
3829 // Check ops which require integer / ivec parameters
3830 bool isBitShift = false;
3831 switch (op)
3832 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003833 case EOpBitShiftLeft:
3834 case EOpBitShiftRight:
3835 case EOpBitShiftLeftAssign:
3836 case EOpBitShiftRightAssign:
3837 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3838 // check that the basic type is an integer type.
3839 isBitShift = true;
3840 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3841 {
3842 return false;
3843 }
3844 break;
3845 case EOpBitwiseAnd:
3846 case EOpBitwiseXor:
3847 case EOpBitwiseOr:
3848 case EOpBitwiseAndAssign:
3849 case EOpBitwiseXorAssign:
3850 case EOpBitwiseOrAssign:
3851 // It is enough to check the type of only one operand, since later it
3852 // is checked that the operand types match.
3853 if (!IsInteger(left->getBasicType()))
3854 {
3855 return false;
3856 }
3857 break;
3858 default:
3859 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003860 }
3861
3862 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3863 // So the basic type should usually match.
3864 if (!isBitShift && left->getBasicType() != right->getBasicType())
3865 {
3866 return false;
3867 }
3868
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003869 // Check that:
3870 // 1. Type sizes match exactly on ops that require that.
3871 // 2. Restrictions for structs that contain arrays or samplers are respected.
3872 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
Jamie Madillb98c3a82015-07-23 14:26:04 -04003873 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003874 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003875 case EOpAssign:
3876 case EOpInitialize:
3877 case EOpEqual:
3878 case EOpNotEqual:
3879 // ESSL 1.00 sections 5.7, 5.8, 5.9
3880 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
3881 {
3882 error(loc, "undefined operation for structs containing arrays",
3883 GetOperatorString(op));
3884 return false;
3885 }
3886 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3887 // we interpret the spec so that this extends to structs containing samplers,
3888 // similarly to ESSL 1.00 spec.
3889 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
3890 left->getType().isStructureContainingSamplers())
3891 {
3892 error(loc, "undefined operation for structs containing samplers",
3893 GetOperatorString(op));
3894 return false;
3895 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003896
Olli Etuahoe1805592017-01-02 16:41:20 +00003897 if ((left->getNominalSize() != right->getNominalSize()) ||
3898 (left->getSecondarySize() != right->getSecondarySize()))
3899 {
3900 error(loc, "dimension mismatch", GetOperatorString(op));
3901 return false;
3902 }
3903 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003904 case EOpLessThan:
3905 case EOpGreaterThan:
3906 case EOpLessThanEqual:
3907 case EOpGreaterThanEqual:
Olli Etuahoe1805592017-01-02 16:41:20 +00003908 if (!left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04003909 {
Olli Etuahoe1805592017-01-02 16:41:20 +00003910 error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003911 return false;
3912 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003913 break;
3914 case EOpAdd:
3915 case EOpSub:
3916 case EOpDiv:
3917 case EOpIMod:
3918 case EOpBitShiftLeft:
3919 case EOpBitShiftRight:
3920 case EOpBitwiseAnd:
3921 case EOpBitwiseXor:
3922 case EOpBitwiseOr:
3923 case EOpAddAssign:
3924 case EOpSubAssign:
3925 case EOpDivAssign:
3926 case EOpIModAssign:
3927 case EOpBitShiftLeftAssign:
3928 case EOpBitShiftRightAssign:
3929 case EOpBitwiseAndAssign:
3930 case EOpBitwiseXorAssign:
3931 case EOpBitwiseOrAssign:
3932 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
3933 {
3934 return false;
3935 }
3936
3937 // Are the sizes compatible?
3938 if (left->getNominalSize() != right->getNominalSize() ||
3939 left->getSecondarySize() != right->getSecondarySize())
3940 {
3941 // If the nominal sizes of operands do not match:
3942 // One of them must be a scalar.
3943 if (!left->isScalar() && !right->isScalar())
3944 return false;
3945
3946 // In the case of compound assignment other than multiply-assign,
3947 // the right side needs to be a scalar. Otherwise a vector/matrix
3948 // would be assigned to a scalar. A scalar can't be shifted by a
3949 // vector either.
3950 if (!right->isScalar() &&
3951 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
3952 return false;
3953 }
3954 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003955 default:
3956 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003957 }
3958
Olli Etuahod6b14282015-03-17 14:31:35 +02003959 return true;
3960}
3961
Olli Etuaho1dded802016-08-18 18:13:13 +03003962bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
3963 const TType &left,
3964 const TType &right)
3965{
3966 switch (op)
3967 {
3968 case EOpMul:
3969 case EOpMulAssign:
3970 return left.getNominalSize() == right.getNominalSize() &&
3971 left.getSecondarySize() == right.getSecondarySize();
3972 case EOpVectorTimesScalar:
3973 return true;
3974 case EOpVectorTimesScalarAssign:
3975 ASSERT(!left.isMatrix() && !right.isMatrix());
3976 return left.isVector() && !right.isVector();
3977 case EOpVectorTimesMatrix:
3978 return left.getNominalSize() == right.getRows();
3979 case EOpVectorTimesMatrixAssign:
3980 ASSERT(!left.isMatrix() && right.isMatrix());
3981 return left.isVector() && left.getNominalSize() == right.getRows() &&
3982 left.getNominalSize() == right.getCols();
3983 case EOpMatrixTimesVector:
3984 return left.getCols() == right.getNominalSize();
3985 case EOpMatrixTimesScalar:
3986 return true;
3987 case EOpMatrixTimesScalarAssign:
3988 ASSERT(left.isMatrix() && !right.isMatrix());
3989 return !right.isVector();
3990 case EOpMatrixTimesMatrix:
3991 return left.getCols() == right.getRows();
3992 case EOpMatrixTimesMatrixAssign:
3993 ASSERT(left.isMatrix() && right.isMatrix());
3994 // We need to check two things:
3995 // 1. The matrix multiplication step is valid.
3996 // 2. The result will have the same number of columns as the lvalue.
3997 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
3998
3999 default:
4000 UNREACHABLE();
4001 return false;
4002 }
4003}
4004
Jamie Madillb98c3a82015-07-23 14:26:04 -04004005TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
4006 TIntermTyped *left,
4007 TIntermTyped *right,
4008 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02004009{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004010 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004011 return nullptr;
4012
Olli Etuahofc1806e2015-03-17 13:03:11 +02004013 switch (op)
4014 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004015 case EOpEqual:
4016 case EOpNotEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04004017 case EOpLessThan:
4018 case EOpGreaterThan:
4019 case EOpLessThanEqual:
4020 case EOpGreaterThanEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04004021 break;
4022 case EOpLogicalOr:
4023 case EOpLogicalXor:
4024 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03004025 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4026 !right->getType().getStruct());
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00004027 if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04004028 {
4029 return nullptr;
4030 }
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00004031 // Basic types matching should have been already checked.
4032 ASSERT(right->getBasicType() == EbtBool);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004033 break;
4034 case EOpAdd:
4035 case EOpSub:
4036 case EOpDiv:
4037 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03004038 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4039 !right->getType().getStruct());
4040 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04004041 {
4042 return nullptr;
4043 }
4044 break;
4045 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03004046 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4047 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004048 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03004049 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04004050 {
4051 return nullptr;
4052 }
4053 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004054 default:
4055 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02004056 }
4057
Olli Etuaho1dded802016-08-18 18:13:13 +03004058 if (op == EOpMul)
4059 {
4060 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
4061 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4062 {
4063 return nullptr;
4064 }
4065 }
4066
Olli Etuaho3fdec912016-08-18 15:08:06 +03004067 TIntermBinary *node = new TIntermBinary(op, left, right);
4068 node->setLine(loc);
4069
Olli Etuaho3fdec912016-08-18 15:08:06 +03004070 // See if we can fold constants.
Olli Etuaho77ba4082016-12-16 12:01:18 +00004071 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuaho3fdec912016-08-18 15:08:06 +03004072 if (foldedNode)
4073 return foldedNode;
4074
4075 return node;
Olli Etuahofc1806e2015-03-17 13:03:11 +02004076}
4077
Jamie Madillb98c3a82015-07-23 14:26:04 -04004078TIntermTyped *TParseContext::addBinaryMath(TOperator op,
4079 TIntermTyped *left,
4080 TIntermTyped *right,
4081 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004082{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004083 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004084 if (node == 0)
4085 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004086 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4087 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02004088 return left;
4089 }
4090 return node;
4091}
4092
Jamie Madillb98c3a82015-07-23 14:26:04 -04004093TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
4094 TIntermTyped *left,
4095 TIntermTyped *right,
4096 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004097{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004098 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004099 if (node == 0)
4100 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004101 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4102 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04004103 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02004104 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004105 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
4106 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004107 }
4108 return node;
4109}
4110
Olli Etuaho13389b62016-10-16 11:48:18 +01004111TIntermBinary *TParseContext::createAssign(TOperator op,
4112 TIntermTyped *left,
4113 TIntermTyped *right,
4114 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004115{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004116 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004117 {
Olli Etuaho1dded802016-08-18 18:13:13 +03004118 if (op == EOpMulAssign)
4119 {
4120 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
4121 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4122 {
4123 return nullptr;
4124 }
4125 }
Olli Etuaho3fdec912016-08-18 15:08:06 +03004126 TIntermBinary *node = new TIntermBinary(op, left, right);
4127 node->setLine(loc);
4128
Olli Etuaho3fdec912016-08-18 15:08:06 +03004129 return node;
Olli Etuahod6b14282015-03-17 14:31:35 +02004130 }
4131 return nullptr;
4132}
4133
Jamie Madillb98c3a82015-07-23 14:26:04 -04004134TIntermTyped *TParseContext::addAssign(TOperator op,
4135 TIntermTyped *left,
4136 TIntermTyped *right,
4137 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004138{
4139 TIntermTyped *node = createAssign(op, left, right, loc);
4140 if (node == nullptr)
4141 {
4142 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02004143 return left;
4144 }
4145 return node;
4146}
4147
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004148TIntermTyped *TParseContext::addComma(TIntermTyped *left,
4149 TIntermTyped *right,
4150 const TSourceLoc &loc)
4151{
Corentin Wallez0d959252016-07-12 17:26:32 -04004152 // WebGL2 section 5.26, the following results in an error:
4153 // "Sequence operator applied to void, arrays, or structs containing arrays"
Jamie Madilld7b1ab52016-12-12 14:42:19 -05004154 if (mShaderSpec == SH_WEBGL2_SPEC &&
4155 (left->isArray() || left->getBasicType() == EbtVoid ||
4156 left->getType().isStructureContainingArrays() || right->isArray() ||
4157 right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
Corentin Wallez0d959252016-07-12 17:26:32 -04004158 {
4159 error(loc,
4160 "sequence operator is not allowed for void, arrays, or structs containing arrays",
4161 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04004162 }
4163
Olli Etuaho4db7ded2016-10-13 12:23:11 +01004164 return TIntermediate::AddComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004165}
4166
Olli Etuaho49300862015-02-20 14:54:49 +02004167TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
4168{
4169 switch (op)
4170 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004171 case EOpContinue:
4172 if (mLoopNestingLevel <= 0)
4173 {
4174 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004175 }
4176 break;
4177 case EOpBreak:
4178 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
4179 {
4180 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004181 }
4182 break;
4183 case EOpReturn:
4184 if (mCurrentFunctionType->getBasicType() != EbtVoid)
4185 {
4186 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004187 }
4188 break;
4189 default:
4190 // No checks for discard
4191 break;
Olli Etuaho49300862015-02-20 14:54:49 +02004192 }
4193 return intermediate.addBranch(op, loc);
4194}
4195
Jamie Madillb98c3a82015-07-23 14:26:04 -04004196TIntermBranch *TParseContext::addBranch(TOperator op,
4197 TIntermTyped *returnValue,
4198 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02004199{
4200 ASSERT(op == EOpReturn);
4201 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004202 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02004203 {
4204 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004205 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004206 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02004207 {
4208 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004209 }
4210 return intermediate.addBranch(op, returnValue, loc);
4211}
4212
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004213void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
4214{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004215 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Olli Etuahobd674552016-10-06 13:28:42 +01004216 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004217 TIntermNode *offset = nullptr;
4218 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuahoec9232b2017-03-27 17:01:37 +03004219 if (name == "texelFetchOffset" || name == "textureLodOffset" ||
4220 name == "textureProjLodOffset" || name == "textureGradOffset" ||
4221 name == "textureProjGradOffset")
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004222 {
4223 offset = arguments->back();
4224 }
Olli Etuahoec9232b2017-03-27 17:01:37 +03004225 else if (name == "textureOffset" || name == "textureProjOffset")
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004226 {
4227 // A bias parameter might follow the offset parameter.
4228 ASSERT(arguments->size() >= 3);
4229 offset = (*arguments)[2];
4230 }
4231 if (offset != nullptr)
4232 {
4233 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
4234 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
4235 {
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004236 error(functionCall->getLine(), "Texture offset must be a constant expression",
Olli Etuahoec9232b2017-03-27 17:01:37 +03004237 name.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004238 }
4239 else
4240 {
4241 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
4242 size_t size = offsetConstantUnion->getType().getObjectSize();
4243 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
4244 for (size_t i = 0u; i < size; ++i)
4245 {
4246 int offsetValue = values[i].getIConst();
4247 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
4248 {
4249 std::stringstream tokenStream;
4250 tokenStream << offsetValue;
4251 std::string token = tokenStream.str();
4252 error(offset->getLine(), "Texture offset value out of valid range",
4253 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004254 }
4255 }
4256 }
4257 }
4258}
4259
Martin Radev2cc85b32016-08-05 16:22:53 +03004260// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
4261void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
4262{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004263 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Martin Radev2cc85b32016-08-05 16:22:53 +03004264 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
4265
4266 if (name.compare(0, 5, "image") == 0)
4267 {
4268 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuaho485eefd2017-02-14 17:40:06 +00004269 TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
Martin Radev2cc85b32016-08-05 16:22:53 +03004270
Olli Etuaho485eefd2017-02-14 17:40:06 +00004271 const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
Martin Radev2cc85b32016-08-05 16:22:53 +03004272
4273 if (name.compare(5, 5, "Store") == 0)
4274 {
4275 if (memoryQualifier.readonly)
4276 {
4277 error(imageNode->getLine(),
4278 "'imageStore' cannot be used with images qualified as 'readonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004279 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03004280 }
4281 }
4282 else if (name.compare(5, 4, "Load") == 0)
4283 {
4284 if (memoryQualifier.writeonly)
4285 {
4286 error(imageNode->getLine(),
4287 "'imageLoad' cannot be used with images qualified as 'writeonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004288 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03004289 }
4290 }
4291 }
4292}
4293
4294// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
4295void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
4296 const TFunction *functionDefinition,
4297 const TIntermAggregate *functionCall)
4298{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004299 ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
Martin Radev2cc85b32016-08-05 16:22:53 +03004300
4301 const TIntermSequence &arguments = *functionCall->getSequence();
4302
4303 ASSERT(functionDefinition->getParamCount() == arguments.size());
4304
4305 for (size_t i = 0; i < arguments.size(); ++i)
4306 {
Olli Etuaho485eefd2017-02-14 17:40:06 +00004307 TIntermTyped *typedArgument = arguments[i]->getAsTyped();
4308 const TType &functionArgumentType = typedArgument->getType();
Martin Radev2cc85b32016-08-05 16:22:53 +03004309 const TType &functionParameterType = *functionDefinition->getParam(i).type;
4310 ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
4311
4312 if (IsImage(functionArgumentType.getBasicType()))
4313 {
4314 const TMemoryQualifier &functionArgumentMemoryQualifier =
4315 functionArgumentType.getMemoryQualifier();
4316 const TMemoryQualifier &functionParameterMemoryQualifier =
4317 functionParameterType.getMemoryQualifier();
4318 if (functionArgumentMemoryQualifier.readonly &&
4319 !functionParameterMemoryQualifier.readonly)
4320 {
4321 error(functionCall->getLine(),
4322 "Function call discards the 'readonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004323 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03004324 }
4325
4326 if (functionArgumentMemoryQualifier.writeonly &&
4327 !functionParameterMemoryQualifier.writeonly)
4328 {
4329 error(functionCall->getLine(),
4330 "Function call discards the 'writeonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004331 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03004332 }
Martin Radev049edfa2016-11-11 14:35:37 +02004333
4334 if (functionArgumentMemoryQualifier.coherent &&
4335 !functionParameterMemoryQualifier.coherent)
4336 {
4337 error(functionCall->getLine(),
4338 "Function call discards the 'coherent' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004339 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02004340 }
4341
4342 if (functionArgumentMemoryQualifier.volatileQualifier &&
4343 !functionParameterMemoryQualifier.volatileQualifier)
4344 {
4345 error(functionCall->getLine(),
4346 "Function call discards the 'volatile' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004347 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02004348 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004349 }
4350 }
4351}
4352
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004353TIntermSequence *TParseContext::createEmptyArgumentsList()
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004354{
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004355 return new TIntermSequence();
Olli Etuaho72d10202017-01-19 15:58:30 +00004356}
4357
4358TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004359 TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00004360 TIntermNode *thisNode,
4361 const TSourceLoc &loc)
4362{
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004363 if (thisNode != nullptr)
4364 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004365 return addMethod(fnCall, arguments, thisNode, loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004366 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004367
4368 TOperator op = fnCall->getBuiltInOp();
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004369 if (op == EOpConstruct)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004370 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004371 return addConstructor(arguments, fnCall->getReturnType(), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004372 }
4373 else
4374 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004375 ASSERT(op == EOpNull);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004376 return addNonConstructorFunctionCall(fnCall, arguments, loc);
4377 }
4378}
4379
4380TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
4381 TIntermSequence *arguments,
4382 TIntermNode *thisNode,
4383 const TSourceLoc &loc)
4384{
4385 TConstantUnion *unionArray = new TConstantUnion[1];
4386 int arraySize = 0;
4387 TIntermTyped *typedThis = thisNode->getAsTyped();
4388 // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
4389 // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
4390 // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
4391 // So accessing fnCall->getName() below is safe.
4392 if (fnCall->getName() != "length")
4393 {
4394 error(loc, "invalid method", fnCall->getName().c_str());
4395 }
4396 else if (!arguments->empty())
4397 {
4398 error(loc, "method takes no parameters", "length");
4399 }
4400 else if (typedThis == nullptr || !typedThis->isArray())
4401 {
4402 error(loc, "length can only be called on arrays", "length");
4403 }
4404 else
4405 {
4406 arraySize = typedThis->getArraySize();
4407 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuaho72d10202017-01-19 15:58:30 +00004408 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004409 // This code path can be hit with expressions like these:
4410 // (a = b).length()
4411 // (func()).length()
4412 // (int[3](0, 1, 2)).length()
4413 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
4414 // expression.
4415 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
4416 // spec section 5.9 which allows "An array, vector or matrix expression with the
4417 // length method applied".
4418 error(loc, "length can only be called on array names, not on array expressions",
4419 "length");
Olli Etuaho72d10202017-01-19 15:58:30 +00004420 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004421 }
4422 unionArray->setIConst(arraySize);
4423 return intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
4424}
4425
4426TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
4427 TIntermSequence *arguments,
4428 const TSourceLoc &loc)
4429{
4430 // First find by unmangled name to check whether the function name has been
4431 // hidden by a variable name or struct typename.
4432 // If a function is found, check for one with a matching argument list.
4433 bool builtIn;
4434 const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn);
4435 if (symbol != nullptr && !symbol->isFunction())
4436 {
4437 error(loc, "function name expected", fnCall->getName().c_str());
4438 }
4439 else
4440 {
4441 symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments),
4442 mShaderVersion, &builtIn);
4443 if (symbol == nullptr)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004444 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004445 error(loc, "no matching overloaded function found", fnCall->getName().c_str());
4446 }
4447 else
4448 {
4449 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004450 //
4451 // A declared function.
4452 //
Olli Etuaho383b7912016-08-05 11:22:59 +03004453 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004454 {
Olli Etuaho856c4972016-08-08 11:38:39 +03004455 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004456 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004457 TOperator op = fnCandidate->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004458 if (builtIn && op != EOpNull)
4459 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004460 // A function call mapped to a built-in operation.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004461 if (fnCandidate->getParamCount() == 1)
4462 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004463 // Treat it like a built-in unary operator.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004464 TIntermNode *unaryParamNode = arguments->front();
4465 TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004466 ASSERT(callNode != nullptr);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004467 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004468 }
4469 else
4470 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004471 TIntermAggregate *callNode =
Olli Etuahofe486322017-03-21 09:30:54 +00004472 TIntermAggregate::Create(fnCandidate->getReturnType(), op, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004473 callNode->setLine(loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004474
4475 // Some built-in functions have out parameters too.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004476 functionCallLValueErrorCheck(fnCandidate, callNode);
Arun Patole274f0702015-05-05 13:33:30 +05304477
Olli Etuaho7c3848e2015-11-04 13:19:17 +02004478 // See if we can constant fold a built-in. Note that this may be possible even
4479 // if it is not const-qualified.
Olli Etuahof119a262016-08-19 15:54:22 +03004480 TIntermTyped *foldedNode =
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004481 intermediate.foldAggregateBuiltIn(callNode, mDiagnostics);
Arun Patole274f0702015-05-05 13:33:30 +05304482 if (foldedNode)
4483 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004484 return foldedNode;
Arun Patole274f0702015-05-05 13:33:30 +05304485 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004486 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004487 }
4488 }
4489 else
4490 {
4491 // This is a real function call
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004492 TIntermAggregate *callNode = nullptr;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004493
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004494 // If builtIn == false, the function is user defined - could be an overloaded
4495 // built-in as well.
4496 // if builtIn == true, it's a builtIn function with no op associated with it.
4497 // This needs to happen after the function info including name is set.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004498 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004499 {
Olli Etuahofe486322017-03-21 09:30:54 +00004500 callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004501 checkTextureOffsetConst(callNode);
4502 checkImageMemoryAccessForBuiltinFunctions(callNode);
Martin Radev2cc85b32016-08-05 16:22:53 +03004503 }
4504 else
4505 {
Olli Etuahofe486322017-03-21 09:30:54 +00004506 callNode = TIntermAggregate::CreateFunctionCall(*fnCandidate, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004507 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004508 }
4509
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004510 functionCallLValueErrorCheck(fnCandidate, callNode);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004511
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004512 callNode->setLine(loc);
4513
4514 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004515 }
4516 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004517 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004518
4519 // Error message was already written. Put on a dummy node for error recovery.
4520 return TIntermTyped::CreateZero(TType(EbtFloat, EbpMedium, EvqConst));
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004521}
4522
Jamie Madillb98c3a82015-07-23 14:26:04 -04004523TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004524 TIntermTyped *trueExpression,
4525 TIntermTyped *falseExpression,
Olli Etuaho52901742015-04-15 13:42:45 +03004526 const TSourceLoc &loc)
4527{
Olli Etuaho856c4972016-08-08 11:38:39 +03004528 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03004529
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004530 if (trueExpression->getType() != falseExpression->getType())
Olli Etuaho52901742015-04-15 13:42:45 +03004531 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004532 binaryOpError(loc, "?:", trueExpression->getCompleteString(),
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004533 falseExpression->getCompleteString());
4534 return falseExpression;
Olli Etuaho52901742015-04-15 13:42:45 +03004535 }
Olli Etuahode318b22016-10-25 16:18:25 +01004536 if (IsOpaqueType(trueExpression->getBasicType()))
4537 {
4538 // ESSL 1.00 section 4.1.7
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004539 // ESSL 3.00.6 section 4.1.7
Olli Etuahode318b22016-10-25 16:18:25 +01004540 // Opaque/sampler types are not allowed in most types of expressions, including ternary.
4541 // Note that structs containing opaque types don't need to be checked as structs are
4542 // forbidden below.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004543 error(loc, "ternary operator is not allowed for opaque types", "?:");
Olli Etuahode318b22016-10-25 16:18:25 +01004544 return falseExpression;
4545 }
4546
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004547 // ESSL 1.00.17 sections 5.2 and 5.7:
Olli Etuahoa2d53032015-04-15 14:14:44 +03004548 // Ternary operator is not among the operators allowed for structures/arrays.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004549 // ESSL 3.00.6 section 5.7:
4550 // Ternary operator support is optional for arrays. No certainty that it works across all
4551 // devices with struct either, so we err on the side of caution here. TODO (oetuaho@nvidia.com):
4552 // Would be nice to make the spec and implementation agree completely here.
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004553 if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
Olli Etuahoa2d53032015-04-15 14:14:44 +03004554 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004555 error(loc, "ternary operator is not allowed for structures or arrays", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004556 return falseExpression;
Olli Etuahoa2d53032015-04-15 14:14:44 +03004557 }
Olli Etuaho94050052017-05-08 14:17:44 +03004558 if (trueExpression->getBasicType() == EbtInterfaceBlock)
4559 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004560 error(loc, "ternary operator is not allowed for interface blocks", "?:");
Olli Etuaho94050052017-05-08 14:17:44 +03004561 return falseExpression;
4562 }
4563
Corentin Wallez0d959252016-07-12 17:26:32 -04004564 // WebGL2 section 5.26, the following results in an error:
4565 // "Ternary operator applied to void, arrays, or structs containing arrays"
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004566 if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
Corentin Wallez0d959252016-07-12 17:26:32 -04004567 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004568 error(loc, "ternary operator is not allowed for void", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004569 return falseExpression;
Corentin Wallez0d959252016-07-12 17:26:32 -04004570 }
4571
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004572 return TIntermediate::AddTernarySelection(cond, trueExpression, falseExpression, loc);
Olli Etuaho52901742015-04-15 13:42:45 +03004573}
Olli Etuaho49300862015-02-20 14:54:49 +02004574
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004575//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004576// Parse an array of strings using yyparse.
4577//
4578// Returns 0 for success.
4579//
Jamie Madillb98c3a82015-07-23 14:26:04 -04004580int PaParseStrings(size_t count,
4581 const char *const string[],
4582 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05304583 TParseContext *context)
4584{
Yunchao He4f285442017-04-21 12:15:49 +08004585 if ((count == 0) || (string == nullptr))
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004586 return 1;
4587
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004588 if (glslang_initialize(context))
4589 return 1;
4590
alokp@chromium.org408c45e2012-04-05 15:54:43 +00004591 int error = glslang_scan(count, string, length, context);
4592 if (!error)
4593 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004594
alokp@chromium.org73bc2982012-06-19 18:48:05 +00004595 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00004596
alokp@chromium.org6b495712012-06-29 00:06:58 +00004597 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004598}
Jamie Madill45bcc782016-11-07 13:58:48 -05004599
4600} // namespace sh